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]: Added pharmacogenomics sections #283

Merged
merged 11 commits into from
Nov 14, 2023
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
49 changes: 23 additions & 26 deletions apps/platform/src/pages/DrugPage/Profile.jsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,36 @@
import { gql } from '@apollo/client';
import {
PlatformApiProvider,
SectionContainer,
SummaryContainer,
summaryUtils,
} from 'ui';
import MechanismsOfActionSummary from 'sections/src/drug/MechanismsOfAction/Summary';
import IndicationsSummary from 'sections/src/drug/Indications/Summary';
import KnownDrugsSummary from 'sections/src/drug/KnownDrugs/Summary';
import DrugWarningsSummary from 'sections/src/drug/DrugWarnings/Summary';
import AdverseEventsSummary from 'sections/src/drug/AdverseEvents/Summary';
import BibliographySummary from 'sections/src/drug/Bibliography/Summary';
import { gql } from "@apollo/client";
import { PlatformApiProvider, SectionContainer, SummaryContainer, summaryUtils } from "ui";
import MechanismsOfActionSummary from "sections/src/drug/MechanismsOfAction/Summary";
import IndicationsSummary from "sections/src/drug/Indications/Summary";
import KnownDrugsSummary from "sections/src/drug/KnownDrugs/Summary";
import DrugWarningsSummary from "sections/src/drug/DrugWarnings/Summary";
import PharmacogenomicsSummary from "sections/src/drug/Pharmacogenomics/Summary";
import AdverseEventsSummary from "sections/src/drug/AdverseEvents/Summary";
import BibliographySummary from "sections/src/drug/Bibliography/Summary";

import MechanismsOfActionSection from 'sections/src/drug/MechanismsOfAction/Body';
import IndicationsSection from 'sections/src/drug/Indications/Body';
import KnownDrugsSection from 'sections/src/drug/KnownDrugs/Body';
import DrugWarningsSection from 'sections/src/drug/DrugWarnings/Body';
import AdverseEventsSection from 'sections/src/drug/AdverseEvents/Body';
import BibliographySection from 'sections/src/drug/Bibliography/Body';
import MechanismsOfActionSection from "sections/src/drug/MechanismsOfAction/Body";
import IndicationsSection from "sections/src/drug/Indications/Body";
import KnownDrugsSection from "sections/src/drug/KnownDrugs/Body";
import DrugWarningsSection from "sections/src/drug/DrugWarnings/Body";
import PharmacogenomicsSection from "sections/src/drug/Pharmacogenomics/Body";
import AdverseEventsSection from "sections/src/drug/AdverseEvents/Body";
import BibliographySection from "sections/src/drug/Bibliography/Body";

import client from '../../client';
import ProfileHeader from './ProfileHeader';
import client from "../../client";
import ProfileHeader from "./ProfileHeader";

const summaries = [
MechanismsOfActionSummary,
IndicationsSummary,
KnownDrugsSummary,
DrugWarningsSummary,
PharmacogenomicsSummary,
AdverseEventsSummary,
BibliographySummary,
];

const DRUG = 'drug';
const DRUG_PROFILE_SUMMARY_FRAGMENT = summaryUtils.createSummaryFragment(
summaries,
'Drug'
);
const DRUG = "drug";
const DRUG_PROFILE_SUMMARY_FRAGMENT = summaryUtils.createSummaryFragment(summaries, "Drug");
const DRUG_PROFILE_QUERY = gql`
query DrugProfileQuery($chemblId: String!) {
drug(chemblId: $chemblId) {
Expand Down Expand Up @@ -63,6 +58,7 @@ function Profile({ chemblId, name }) {
<IndicationsSummary />
<KnownDrugsSummary />
<DrugWarningsSummary />
<PharmacogenomicsSummary />
<AdverseEventsSummary />
<BibliographySummary />
</SummaryContainer>
Expand All @@ -72,6 +68,7 @@ function Profile({ chemblId, name }) {
<IndicationsSection id={chemblId} label={name} entity={DRUG} />
<KnownDrugsSection id={chemblId} label={name} entity={DRUG} />
<DrugWarningsSection id={chemblId} label={name} entity={DRUG} />
<PharmacogenomicsSection id={chemblId} label={name} entity={DRUG} />
<AdverseEventsSection id={chemblId} label={name} entity={DRUG} />
<BibliographySection id={chemblId} label={name} entity={DRUG} />
</SectionContainer>
Expand Down
7 changes: 7 additions & 0 deletions apps/platform/src/pages/TargetPage/Profile.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
import KnownDrugsSummary from 'sections/src/target/KnownDrugs/Summary';
import TractabilitySummary from 'sections/src/target/Tractability/Summary';
import SafetySummary from 'sections/src/target/Safety/Summary';
import PharmacogenomicsSummary from 'sections/src/target/Pharmacogenomics/Summary';
import ChemicalProbesSummary from 'sections/src/target/ChemicalProbes/Summary';
import BaselineExpressionSummary from 'sections/src/target/Expression/Summary';
import DepMapSummary from 'sections/src/target/DepMap/Summary';
Expand All @@ -35,6 +36,7 @@ const TractabilitySection = lazy(() =>
import('sections/src/target/Tractability/Body')
);
const SafetySection = lazy(() => import('sections/src/target/Safety/Body'));
const PharmacogenomicsSection = lazy(() => import('sections/src/target/Pharmacogenomics/Body'));
const ChemicalProbesSection = lazy(() =>
import('sections/src/target/ChemicalProbes/Body')
);
Expand Down Expand Up @@ -75,6 +77,7 @@ const summaries = [
KnownDrugsSummary,
TractabilitySummary,
SafetySummary,
PharmacogenomicsSummary,
ChemicalProbesSummary,
BaselineExpressionSummary,
DepMapSummary,
Expand Down Expand Up @@ -120,6 +123,7 @@ function Profile({ ensgId, symbol }) {
<KnownDrugsSummary />
<TractabilitySummary />
<SafetySummary />
<PharmacogenomicsSummary/>
<ChemicalProbesSummary />
<BaselineExpressionSummary />
<DepMapSummary />
Expand All @@ -145,6 +149,9 @@ function Profile({ ensgId, symbol }) {
<Suspense fallback={<SectionLoader />}>
<SafetySection id={ensgId} label={symbol} entity={TARGET} />
</Suspense>
<Suspense fallback={<SectionLoader />}>
<PharmacogenomicsSection id={ensgId} label={symbol} entity={TARGET}/>
</Suspense>
<Suspense fallback={<SectionLoader />}>
<ChemicalProbesSection id={ensgId} label={symbol} entity={TARGET} />
</Suspense>
Expand Down
8 changes: 7 additions & 1 deletion packages/sections/src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ export const colorRange = [
"#005299",
];

export const PHARM_GKB_COLOR = {
green: "#52a237",
yellow: "#f0c584",
red: "#ec2746",
};

export const defaultRowsPerPageOptions = [10, 25, 100];

export const decimalPlaces = 3;
Expand All @@ -38,7 +44,7 @@ const clinicalPhases = {
4: "Phase IV",
};

export const phaseMap = (clinicalPhase) => {
export const phaseMap = clinicalPhase => {
const clinicalPhaseId = String(clinicalPhase);
return clinicalPhases[clinicalPhaseId];
};
Expand Down
249 changes: 249 additions & 0 deletions packages/sections/src/drug/Pharmacogenomics/Body.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
import classNames from "classnames";
import { useQuery } from "@apollo/client";
import { makeStyles } from "@mui/styles";
import { Link, SectionItem, Tooltip, DataTable, LabelChip, PublicationsDrawer } from "ui";

import { epmcUrl } from "../../utils/urls";
import { definition } from ".";
import Description from "./Description";
import PHARMACOGENOMICS_QUERY from "./Pharmacogenomics.gql";
import {
naLabel,
defaultRowsPerPageOptions,
PHARM_GKB_COLOR,
variantConsequenceSource,
} from "../../constants";
import { identifiersOrgLink, sentenceCase } from "../../utils/global";

const useStyles = makeStyles(theme => ({
level: {
color: "white",
padding: theme.spacing(0.5),
borderRadius: theme.spacing(0.5),
},
green: {
background: PHARM_GKB_COLOR.green,
},
red: {
background: PHARM_GKB_COLOR.red,
},
yellow: {
background: PHARM_GKB_COLOR.yellow,
},
blue: {
background: theme.palette.primary.main,
},
}));

const getLevelElementClassName = level => {
switch (level) {
case "1":
return "green";
case "1A":
return "green";
case "2":
return "level-blue";
case "2A":
return "level-blue";
case "3":
return "level-yellow";
case "4":
return "level-red";
default:
return "level-red";
}
};

function Body({ id: chemblId, label: name, entity }) {
const variables = { chemblId };
const classes = useStyles();

const columns = [
{
id: "gene",
label: "Gene",
renderCell: ({ target, isDirectTarget }) => {
if (target) {
const tooltipText = isDirectTarget
? "The variant is in the drug's primary target gene."
: "The variant is outside the drug's primary target gene.";
return (
<Tooltip title={tooltipText} showHelpIcon>
<Link to={`/target/${target.id}`}>
<span>{target.approvedSymbol}</span>
</Link>
</Tooltip>
);
}
return naLabel;
},
},
{
id: "variantRsId",
label: "rsID",
renderCell: ({ variantRsId }) =>
variantRsId ? (
<Link
external
to={`http://www.ensembl.org/Homo_sapiens/Variation/Explore?v=${variantRsId}`}
>
{variantRsId}
</Link>
) : (
naLabel
),
},
{
id: "genotypeId",
label: "Genotype ID",
tooltip: (
<>
VCF-style(chr_pos_ref_allele1,allele2). See{" "}
<Link
external
to="https://github.com/apriltuesday/opentargets-pharmgkb/tree/issue-18#variant-coordinate-computation"
>
here
</Link>{" "}
for more details.
</>
),
renderCell: ({ genotypeId }) => genotypeId || naLabel,
},
{
id: "variantConsequence",
label: "Variant Consequence",
renderCell: ({ variantFunctionalConsequence, genotypeId }) => {
const pvparams = genotypeId?.split(",")[0].split("_") || [];
return (
<div style={{ display: "flex", gap: "5px" }}>
{variantFunctionalConsequence ? (
<LabelChip
label={variantConsequenceSource.VEP.label}
value={sentenceCase(variantFunctionalConsequence.label)}
tooltip={variantConsequenceSource.VEP.tooltip}
to={identifiersOrgLink("SO", variantFunctionalConsequence.id.slice(3))}
/>
) : (
naLabel
)}
{(variantFunctionalConsequence?.id === "SO:0001583" ||
variantFunctionalConsequence?.id === "SO:0001587") && (
<LabelChip
label={variantConsequenceSource.ProtVar.label}
to={`https://www.ebi.ac.uk/ProtVar/query?chromosome=${pvparams[0]}&genomic_position=${pvparams[1]}&reference_allele=${pvparams[2]}&alternative_allele=${pvparams[3]}`}
tooltip={variantConsequenceSource.ProtVar.tooltip}
/>
)}
</div>
);
},
filterValue: ({ variantFunctionalConsequence }) =>
`${sentenceCase(variantFunctionalConsequence.label)}`,
},
{
id: "drugResponse",
label: "Drug Response Phenotype",
renderCell: ({ phenotypeText = naLabel, phenotypeFromSourceId, genotypeAnnotationText }) => {
const phenotypeTextElement = phenotypeFromSourceId ? (
<Tooltip title={genotypeAnnotationText} showHelpIcon>
<Link to={`/disease/${phenotypeFromSourceId}`}>{phenotypeText}</Link>
</Tooltip>
) : (
<Tooltip showHelpIcon title={genotypeAnnotationText}>
{phenotypeText}
</Tooltip>
);
return phenotypeTextElement;
},
},
{
id: "drugResponseCategory",
label: "Drug Response Category",
renderCell: ({ pgxCategory }) => pgxCategory || naLabel,
},
{
id: "confidenceLevel",
label: "Confidence Level",
tooltip: (
<>
As defined by
<Link external to={`https://www.pharmgkb.org/page/clinAnnLevels`}>
{" "}
PharmGKB ClinAnn Levels
</Link>
</>
),
renderCell: ({ evidenceLevel }) => {
if (evidenceLevel) {
const levelClass = getLevelElementClassName(evidenceLevel);
return (
<span className={classNames(classes.level, classes[levelClass])}>
Level {evidenceLevel}
</span>
);
}
return naLabel;
},
},
{
id: "source",
label: "Source",
renderCell: ({ studyId }) =>
studyId ? (
<Link external to={`https://www.pharmgkb.org/clinicalAnnotation/${studyId}`}>
PharmGKB
</Link>
) : (
naLabel
),
},
{
id: "literature",
label: "Literature",
renderCell: ({ literature }) => {
const literatureList =
literature?.reduce((acc, id) => {
if (id === "NA") return acc;

return [
...acc,
{
name: id,
url: epmcUrl(id),
group: "literature",
},
];
}, []) || [];

return <PublicationsDrawer entries={literatureList} />;
},
},
];

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

return (
<SectionItem
definition={definition}
request={request}
entity={entity}
renderDescription={() => <Description name={name} />}
renderBody={({ drug }) => (
<DataTable
showGlobalFilter
dataDownloader
columns={columns}
rows={drug.pharmacogenomics}
rowsPerPageOptions={defaultRowsPerPageOptions}
query={PHARMACOGENOMICS_QUERY.loc.source.body}
variables={variables}
/>
)}
/>
);
}

export default Body;
Loading
Loading