Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Platform]: Add variants widget to credible set page #497

Merged
merged 18 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions apps/platform/src/pages/CredibleSetPage/CredibleSetPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ function CredibleSetPage() {

const credibleSet = data?.credibleSets[0];
const variantId = credibleSet?.variant?.id;
const referenceAllele = credibleSet?.variant?.referenceAllele
const alternateAllele = credibleSet?.variant?.alternateAllele
const studyId = credibleSet?.study?.studyId;

return (
Expand All @@ -45,8 +47,8 @@ function CredibleSetPage() {
loading={loading}
studyId={studyId}
variantId={variantId}
referenceAllele={credibleSet?.variant?.referenceAllele}
alternateAllele={credibleSet?.variant?.alternateAllele}
referenceAllele={referenceAllele}
alternateAllele={alternateAllele}
/>
<ScrollToTop />
<Route
Expand All @@ -67,7 +69,12 @@ function CredibleSetPage() {
<Suspense fallback={<LoadingBackdrop height={11500} />}>
<Switch>
<Route exact path={path}>
<Profile studyLocusId={studyLocusId} variantId={variantId} />
<Profile
studyLocusId={studyLocusId}
variantId={variantId}
referenceAllele={referenceAllele}
alternateAllele={alternateAllele}
/>
</Route>
</Switch>
</Suspense>
Expand Down
35 changes: 25 additions & 10 deletions apps/platform/src/pages/CredibleSetPage/Profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ import {
summaryUtils,
} from "ui";

// import PharmacogenomicsSummary from "sections/src/variant/Pharmacogenomics/Summary";
import VariantsSummary from "sections/src/credibleSet/Variants/Summary";

import client from "../../client";
import ProfileHeader from "./ProfileHeader";
// const PharmacogenomicsSection = lazy(
// () => import("sections/src/variant/Pharmacogenomics/Body")
// );
const VariantsSection = lazy(
() => import("sections/src/credibleSet/Variants/Body")
);

const summaries = [
// PharmacogenomicsSummary,
VariantsSummary,
];

const CREDIBLE_SET = "credibleSets";
Expand All @@ -41,9 +41,17 @@ const CREDIBLE_SET_PROFILE_QUERY = gql`
type ProfileProps = {
studyLocusId: string;
variantId: string;
referenceAllele: string;
alternateAllele: string;
};

function Profile({ studyLocusId, variantId }: ProfileProps) {
function Profile({
studyLocusId,
variantId,
referenceAllele,
alternateAllele,
}: ProfileProps) {

return (
<PlatformApiProvider
entity={CREDIBLE_SET}
Expand All @@ -54,16 +62,23 @@ function Profile({ studyLocusId, variantId }: ProfileProps) {
<ProfileHeader variantId={variantId} />

<SummaryContainer>
{/* <PharmacogenomicsSummary /> */}
<VariantsSummary />
</SummaryContainer>

<SectionContainer>
{/* <Suspense fallback={<SectionLoader />}>
<PharmacogenomicsSection id={varId} entity={VARIANT} />
</Suspense> */}
<Suspense fallback={<SectionLoader />}>
<VariantsSection
studyLocusId={studyLocusId}
leadVariantId={variantId}
leadReferenceAllele={referenceAllele}
leadAlternateAllele={alternateAllele}
entity={CREDIBLE_SET}
/>
</Suspense>
</SectionContainer>
</PlatformApiProvider>
);

}

export default Profile;
198 changes: 198 additions & 0 deletions packages/sections/src/credibleSet/Variants/Body.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
import { useQuery } from "@apollo/client";
import { Box, Chip } from "@mui/material";
import {
Link,
SectionItem,
DataTable,
ScientificNotation,
DisplayVariantId,
} from "ui";
import { naLabel, defaultRowsPerPageOptions } from "../../constants";
import { definition } from ".";
import Description from "./Description";
import VARIANTS_QUERY from "./VariantsQuery.gql";
import { variantComparator } from "../../utils/comparators";

type getColumnsType = {
leadVariantId: string;
leadReferenceAllele: string;
leadAlternateAllele: string;
};

function getColumns({
leadVariantId,
leadReferenceAllele,
leadAlternateAllele,
}: getColumnsType) {

return [
{
id: "variant.id",
label: "Variant ID",
comparator: variantComparator,
sortable: true,
filterValue: ({ variant: v }) => (
`${v?.chromosome}_${v?.position}_${v?.referenceAllele}_${v?.alternateAllele}`
),
renderCell: ({ variant }) => {
if (!variant) return naLabel;
const { id: variantId, referenceAllele, alternateAllele } = variant;
const displayElement = <Link to={`/variant/${variantId}`}>
<DisplayVariantId
variantId={variantId}
referenceAllele={referenceAllele}
alternateAllele={alternateAllele}
expand={false}
/>
</Link>;
if (variantId === leadVariantId) {
return <Box display="flex" alignItems="center" gap={0.5}>
{displayElement}
<Chip label="lead" variant="outlined" size="small"/>
</Box>;
}
return displayElement;
},
exportValue: ({ variant }) => variant?.id,
},
{
id: "pValue",
label: "P-value",
comparator: (a, b) =>
a?.pValueMantissa * 10 ** a?.pValueExponent -
b?.pValueMantissa * 10 ** b?.pValueExponent,
sortable: true,
filterValue: false,
renderCell: ({ pValueMantissa, pValueExponent }) => {
if (typeof pValueMantissa !== "number" ||
typeof pValueExponent !== "number") return naLabel;
return <ScientificNotation number={[pValueMantissa, pValueExponent]} />;
},
exportValue: ({ pValueMantissa, pValueExponent }) => {
if (typeof pValueMantissa !== "number" ||
typeof pValueExponent !== "number") return null;
return `${pValueMantissa}x10${pValueExponent}`;
},
},
{
id: "beta",
label: "Beta",
filterValue: false,
tooltip: "Beta with respect to the ALT allele",
renderCell: ({ beta }) => {
if (typeof beta !== "number") return naLabel;
return beta.toPrecision(3);
},
},
{
id: "standardError",
label: "Standard error",
filterValue: false,
tooltip: "Standard Error: Estimate of the standard deviation of the sampling distribution of the beta",
renderCell: ({ standardError }) => {
if (typeof standardError !== "number") return naLabel;
return standardError.toPrecision(3);
},
},
{
id: "r2Overall",
label: "LD (r²)",
filterValue: false,
tooltip: <>
Linkage disequilibrium with the lead variant (
<DisplayVariantId
variantId={leadVariantId}
referenceAllele={leadReferenceAllele}
alternateAllele={leadAlternateAllele}
expand={false}
/>
)
</>,
renderCell: ({ r2Overall }) => {
if (typeof r2Overall !== "number") return naLabel;
return r2Overall.toPrecision(3);
},
},
{
id: "posteriorProbability",
label: "Posterior Probability",
filterValue: false,
tooltip: "Posterior inclusion probability from fine-mapping that this variant is causal",
comparator: (rowA, rowB) => rowA?.posteriorProbability - rowB?.posteriorProbability,
sortable: true,
renderCell: ({ posteriorProbability }) => {
if (typeof posteriorProbability !== "number") return naLabel;
return posteriorProbability.toPrecision(3);
},
},
{
id: 'logBF',
label: 'LOG(BF)',
filterValue: false,
renderCell: ({ logBF }) => {
if (typeof logBF !== "number") return naLabel;
return logBF.toPrecision(3);
},
}
];

}

type BodyProps = {
studyLocusId: string,
leadVariantId: string,
leadReferenceAllele: string,
leadAlternateAllele: string,
entity: string,
};

function Body({
studyLocusId,
leadVariantId,
leadReferenceAllele,
leadAlternateAllele,
entity
}: BodyProps) {

const variables = {
studyLocusIds: [studyLocusId],
};

const request = useQuery(VARIANTS_QUERY, {
variables,
});

const columns = getColumns({
leadVariantId,
leadReferenceAllele,
leadAlternateAllele,
});

return (
<SectionItem
definition={definition}
entity={entity}
request={request}
renderDescription={() => <Description />}
renderBody={({ credibleSets }) => {
// debugger
return (
<DataTable
dataDownloader
showGlobalFilter
sortBy="posteriorProbability"
order="desc"
columns={columns}
rows={credibleSets[0].locus}
rowsPerPageOptions={defaultRowsPerPageOptions}
query={VARIANTS_QUERY.loc.source.body}
variables={variables}
/>
);
}}
/>
);

}

export default Body;
14 changes: 14 additions & 0 deletions packages/sections/src/credibleSet/Variants/Description.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Link } from "ui";

function Description() {
return (
<>
Source:{" "}
<Link to="../" >
Open Targets
</Link>
</>
);
}

export default Description;
16 changes: 16 additions & 0 deletions packages/sections/src/credibleSet/Variants/Summary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { SummaryItem, usePlatformApi } from "ui";

import { definition } from ".";
import VARIANTS_SUMMARY from "./VariantsSummaryFragment.gql";

function Summary() {
const request = usePlatformApi(VARIANTS_SUMMARY);

return <SummaryItem definition={definition} request={request} />;
}

Summary.fragments = {
VariantsSummaryFragment: VARIANTS_SUMMARY,
};

export default Summary;
21 changes: 21 additions & 0 deletions packages/sections/src/credibleSet/Variants/VariantsQuery.gql
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
query VariantsQuery($studyLocusIds: [String!]!) {
credibleSets(studyLocusIds: $studyLocusIds) {
studyLocusId
locus {
logBF
posteriorProbability
variant {
id
chromosome
position
referenceAllele
alternateAllele
}
pValueMantissa
pValueExponent
beta
standardError
r2Overall
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
fragment VariantsSummaryFragment on credibleSet {
locus {
beta
}
}
7 changes: 7 additions & 0 deletions packages/sections/src/credibleSet/Variants/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const id = "variants";
export const definition = {
id,
name: "Variants in Credible Set",
shortName: "VA",
hasData: data => data?.[0]?.locus?.length > 0,
};
Loading