-
-
Notifications
You must be signed in to change notification settings - Fork 349
add oncokb patient report tab to patient view page #5284
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
base: master
Are you sure you want to change the base?
Changes from all commits
c9d006e
5ac8370
3102d0c
b3d2e0b
0177443
16d0b29
ccfa0d5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| import { observer } from 'mobx-react'; | ||
| import React, { useEffect } from 'react'; | ||
| import IFrameLoader from 'shared/components/iframeLoader/IFrameLoader'; | ||
| import WindowStore from 'shared/components/window/WindowStore'; | ||
| import { CLINICAL_ATTRIBUTE_ID_ENUM } from 'shared/constants'; | ||
| import { PatientViewPageStore } from '../clinicalInformation/PatientViewPageStore'; | ||
| import { getAnnotatedSamples } from './PatientReportUtils'; | ||
|
|
||
| interface IPatientReportTabProps { | ||
| patientViewPageStore: PatientViewPageStore; | ||
| } | ||
|
|
||
| class PatientMetadata { | ||
| id = ''; | ||
| name = ''; | ||
| age = ''; | ||
| sex = ''; | ||
| } | ||
|
|
||
| const IFRAME_NAME = 'patient-report-iframe'; | ||
|
|
||
| const PatientReportTab = observer( | ||
| ({ patientViewPageStore }: IPatientReportTabProps) => { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you should type this using React.FunctionComponent generic
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wondering if we want to do this since React does not recommend. It's a rather trivial change so I'm find with it if it helps maintain the style of the codebase, but wondering your thoughts on this: facebook/create-react-app#8177 |
||
| const isDataComplete = | ||
| patientViewPageStore.clinicalDataGroupedBySample.isComplete && | ||
| patientViewPageStore.patientViewData.isComplete && | ||
| patientViewPageStore.mutationData.isComplete && | ||
| patientViewPageStore.oncoKbData.isComplete && | ||
| patientViewPageStore.discreteCNAData.isComplete && | ||
| patientViewPageStore.cnaOncoKbData.isComplete && | ||
| patientViewPageStore.structuralVariantData.isComplete && | ||
| patientViewPageStore.structuralVariantOncoKbData.isComplete; | ||
|
|
||
| useEffect(() => { | ||
| if (isDataComplete) { | ||
| const patientMetadata = new PatientMetadata(); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. lets put this code in a utitility file somewhere and add some comments about what it does.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i mean the whole contents of the this useEffect hook. be careful though to dereference data from the mobx promises before you pass them into this function |
||
| patientMetadata.id = patientViewPageStore.patientId; | ||
| patientMetadata.sex = | ||
| patientViewPageStore.patientViewData.result.patient?.clinicalData.find( | ||
| data => | ||
| data.clinicalAttributeId === | ||
| CLINICAL_ATTRIBUTE_ID_ENUM.SEX | ||
| )?.value ?? ''; | ||
|
|
||
| const samples = getAnnotatedSamples( | ||
| patientViewPageStore.clinicalDataGroupedBySample.result, | ||
| patientViewPageStore.uniqueSampleKeyToTumorType, | ||
| patientViewPageStore.mutationData.result, | ||
| patientViewPageStore.oncoKbData.result, | ||
| patientViewPageStore.discreteCNAData.result, | ||
| patientViewPageStore.cnaOncoKbData.result, | ||
| patientViewPageStore.structuralVariantData.result, | ||
| patientViewPageStore.structuralVariantOncoKbData.result | ||
| ); | ||
|
|
||
| const form = document.createElement('form'); | ||
alisman marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| form.method = 'POST'; | ||
| form.action = | ||
| 'https://beta.report.oncokb.org/report/cbioportal'; | ||
| form.target = IFRAME_NAME; | ||
|
|
||
| let input = document.createElement('input'); | ||
| input.type = 'hidden'; | ||
| input.name = 'annotatedSamples'; | ||
| input.value = JSON.stringify(samples); | ||
| form.appendChild(input); | ||
|
|
||
| input = document.createElement('input'); | ||
| input.type = 'hidden'; | ||
| input.name = 'patientMetadata'; | ||
| input.value = JSON.stringify(patientMetadata); | ||
| form.appendChild(input); | ||
|
|
||
| document.body.appendChild(form); | ||
| form.submit(); | ||
| document.body.removeChild(form); | ||
| } | ||
| }, [isDataComplete]); | ||
|
|
||
| return ( | ||
| <div> | ||
| <IFrameLoader | ||
| height={WindowStore.size.height - 220} | ||
| name={IFRAME_NAME} | ||
| /> | ||
| </div> | ||
| ); | ||
| } | ||
| ); | ||
| export default PatientReportTab; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| import { IOncoKbData } from 'cbioportal-utils'; | ||
| import { getAnnotatedSamples } from './PatientReportUtils'; | ||
| import { | ||
| ClinicalData, | ||
| DiscreteCopyNumberData, | ||
| Mutation, | ||
| StructuralVariant, | ||
| } from 'cbioportal-ts-api-client'; | ||
| import { assert } from 'chai'; | ||
|
|
||
| describe('Patient Report Utils', () => { | ||
| const clinicalDataGroupedBySample: { | ||
| id: string; | ||
| clinicalData: ClinicalData[]; | ||
| }[] = [ | ||
| { id: '1', clinicalData: [] }, | ||
| { id: '2', clinicalData: [] }, | ||
| ]; | ||
| const uniqueSampleKeyToTumorType: { [sampleId: string]: string } = { | ||
| '1': 'Melanoma', | ||
| '2': 'Breast Cancer', | ||
| }; | ||
| const mutations: Partial<Mutation>[] = [ | ||
| { | ||
| entrezGeneId: 673, | ||
| gene: { | ||
| entrezGeneId: 673, | ||
| geneticEntityId: 0, | ||
| hugoGeneSymbol: 'BRAF', | ||
| type: '', | ||
| }, | ||
| mutationType: 'Missense_Mutation', | ||
| proteinChange: 'V600E', | ||
| sampleId: '1', | ||
| uniqueSampleKey: '1', | ||
| }, | ||
| ]; | ||
| const mutationsOncoKBData: IOncoKbData = { | ||
| indicatorMap: { '673_Melanoma_V600E_Missense_Mutation': {} as any }, | ||
| }; | ||
| const copyNumberAlterations: Partial<DiscreteCopyNumberData>[] = [ | ||
| { | ||
| alteration: 2, // Amplification | ||
| entrezGeneId: 2064, | ||
| gene: { | ||
| entrezGeneId: 2064, | ||
| geneticEntityId: 0, | ||
| hugoGeneSymbol: 'ERBB2', | ||
| type: '', | ||
| }, | ||
| molecularProfileId: '', | ||
| sampleId: '1', | ||
| uniqueSampleKey: '1', | ||
| }, | ||
| ]; | ||
| const copyNumberAlterationsOncoKBData: IOncoKbData = { | ||
| indicatorMap: { '2064_Melanoma_Amplification': {} as any }, | ||
| }; | ||
| const structuralVariants: Partial<StructuralVariant>[] = [ | ||
| { | ||
| sampleId: '2', | ||
| site1EntrezGeneId: 613, | ||
| site1HugoSymbol: 'BCR', | ||
| site2EntrezGeneId: 25, | ||
| site2HugoSymbol: 'ABL1', | ||
| uniqueSampleKey: '2', | ||
| }, | ||
| ]; | ||
| const structuralVariantsOncoKBData: IOncoKbData = { indicatorMap: {} }; | ||
|
|
||
| it('should construct samples from alteration data', () => { | ||
| const annotatedSamples = getAnnotatedSamples( | ||
| clinicalDataGroupedBySample, | ||
| uniqueSampleKeyToTumorType, | ||
| mutations as Mutation[], | ||
| mutationsOncoKBData, | ||
| copyNumberAlterations as DiscreteCopyNumberData[], | ||
| copyNumberAlterationsOncoKBData, | ||
| structuralVariants as StructuralVariant[], | ||
| structuralVariantsOncoKBData | ||
| ); | ||
|
|
||
| const sample1 = annotatedSamples.find(sample => sample.id === '1'); | ||
| assert(sample1 !== undefined); | ||
| const sample2 = annotatedSamples.find(sample => sample.id === '2'); | ||
| assert(sample2 !== undefined); | ||
|
|
||
| assert(sample1!.mutations.length === 1); | ||
| assert(sample1!.copyNumberAlterations.length === 1); | ||
| assert(sample1!.structuralVariants.length === 0); | ||
|
|
||
| assert(sample2!.mutations.length === 0); | ||
| assert(sample2!.copyNumberAlterations.length === 0); | ||
| assert(sample2!.structuralVariants.length === 1); | ||
|
|
||
| const structuralVariant = sample2!.structuralVariants[0]; | ||
| assert(structuralVariant.query.hugoSymbol === 'BCR'); | ||
| assert(structuralVariant.query.alteration === 'BCR-ABL1 Fusion'); | ||
| assert(structuralVariant.query.consequence === 'fusion'); | ||
| }); | ||
| }); |
Uh oh!
There was an error while loading. Please reload this page.