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

Add "View NG-CHM" button on OncoPrint Heatmap tab #2872

Merged
merged 1 commit into from
Dec 19, 2019
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
1 change: 1 addition & 0 deletions src/config/IAppConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ export interface IServerConfig {
skin_title: string;
skin_authorization_message: string | null;
skin_patientview_filter_genes_profiled_all_samples: boolean;
show_mdacc_heatmap: boolean;
quick_search_enabled: boolean;
default_cross_cancer_study_list: string; // this has a default
default_cross_cancer_study_list_name: string; // this has a default
Expand Down
1 change: 1 addition & 0 deletions src/config/serverConfigDefaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const ServerConfigDefaults: Partial<IServerConfig> = {
'https://bioinformatics.mdanderson.org/study2url?studyid=',
mdacc_heatmap_study_url:
'https:// bioinformatics.mdanderson.org/TCGA/NGCHMPortal/?',
show_mdacc_heatmap: false,

mygene_info_url:
'https://mygene.info/v3/gene/<%= entrezGeneId %>?fields=uniprot',
Expand Down
40 changes: 40 additions & 0 deletions src/pages/resultsView/ResultsViewPageStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1390,6 +1390,46 @@ export class ResultsViewPageStore {
},
});


// remoteNgchmUrl queries mdanderson.org to test if there are NGCHMs for one selected
// study. The result is either the full URL to a portal page, or an empty string.
readonly remoteNgchmUrl = remoteData<string>({
await:()=>[this.studyIds],
invoke:async()=>{
var result = '';

if (this.studyIds.result!.length === 1) {

const queryData = {
studyid:this.studyIds.result![0],
format:"json"
};

var urlResponse;

try {
urlResponse = await request.get("https://bioinformatics.mdanderson.org/study2url")
.timeout(30000)
.query(queryData) as any;
} catch (err) {
// Just eat the exception. Result will be empty string.
}

if (urlResponse && urlResponse.body.fileContent) {
const parsedUrlResponse = JSON.parse(urlResponse.body.fileContent.trimEnd()) as any;

if (parsedUrlResponse.length >= 1) {
// This is faked out for now. study2url needs mods to include site url
result = "https://bioinformatics.mdanderson.org/TCGA/NGCHMPortal?" + parsedUrlResponse[0];
}
}
}

return Promise.resolve (result);
}
});


readonly molecularProfilesWithData = remoteData<MolecularProfile[]>({
await: () => [
this.molecularProfilesInStudies,
Expand Down
3 changes: 2 additions & 1 deletion src/pages/staticPages/tools/oncoprinter/Oncoprinter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,8 @@ export default class Oncoprinter extends React.Component<IOncoprinterProps, {}>
},
onClickZoomOut:()=>{
this.oncoprint.setHorzZoom(this.oncoprint.getHorzZoom()*0.7);
}
},
onClickNGCHM:()=>{} // do nothing in oncoprinter mode
};
}

Expand Down
10 changes: 6 additions & 4 deletions src/pages/studyView/StudyViewPageStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2256,11 +2256,13 @@ export class StudyViewPageStore {
await: () => [this.queriedPhysicalStudyIds],
onError: (error => {}),
invoke: async () => {
let isSinglePhysicalStudy = this.queriedPhysicalStudyIds.result.length === 1;
if (isSinglePhysicalStudy) {
return await getHeatmapMeta(getMDAndersonHeatmapStudyMetaUrl(this.queriedPhysicalStudyIds.result[0]));
if (AppConfig.serverConfig.show_mdacc_heatmap) {
let isSinglePhysicalStudy = this.queriedPhysicalStudyIds.result.length === 1;
if (isSinglePhysicalStudy) {
return await getHeatmapMeta(getMDAndersonHeatmapStudyMetaUrl(this.queriedPhysicalStudyIds.result[0]));
}
}
return [];
return []; // if not enabled or conditions not met, just return default answer
}
}, []);

Expand Down
8 changes: 8 additions & 0 deletions src/shared/components/oncoprint/ResultsViewOncoprint.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,11 @@ export default class ResultsViewOncoprint extends React.Component<IResultsViewOn
get heatmapIsDynamicallyQueried () {
return self.heatmapIsDynamicallyQueried;
},
get ngchmButtonActive() {
return (AppConfig.serverConfig.show_mdacc_heatmap &&
(self.props.store.remoteNgchmUrl.result &&
self.props.store.remoteNgchmUrl.result != '') ? true : false);
},
get heatmapGeneInputValue() {
return self.heatmapGeneInputValue;
},
Expand Down Expand Up @@ -583,6 +588,9 @@ export default class ResultsViewOncoprint extends React.Component<IResultsViewOn
onClickAddTreatmentsToHeatmap:(treatmentIds:string[])=>{
this.addHeatmapTracks(this.selectedHeatmapProfile, treatmentIds);
},
onClickNGCHM:()=>{
window.open(this.props.store.remoteNgchmUrl.result, '_blank');
},
onClickDownload:(type:string)=>{
switch(type) {
case "pdf":
Expand Down
53 changes: 53 additions & 0 deletions src/shared/components/oncoprint/controls/ConfirmNgchmModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import * as React from 'react';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would be nice to have a comment here about what NGCHM is.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Have a look.

import { Button, Modal } from 'react-bootstrap';
import {observer} from "mobx-react";
import {observable} from "mobx";

//
// NG-CHM are "Next-Generation Clustered Heat Maps", a highly interactive viewer of
// even very large heat maps, as described here:
// https://bioinformatics.mdanderson.org/public-software/ngchm/
// Source code for the viewer and other tools can be found at
// https://github.com/MD-Anderson-Bioinformatics
//

@observer
export default class ConfirmNgchmModal extends React.Component<{ show:boolean, onHide:()=>void, openNgchmWindow:()=>void }, {}> {

// CSS properties in img tag below should go in .css file?
// margin-right:20px; margin-bottom:20px;

render() {
return (
<Modal show={this.props.show} onHide={this.props.onHide} animation={false}>
<Modal.Header closeButton>
<Modal.Title>Open new tab to MD Anderson NG-CHM?</Modal.Title>
</Modal.Header>
<Modal.Body>
<div className="oncoprint__controls__heatmap_menu mdacc-modal">
<p>Continue will open a tab or window to a different site (not cBioPortal).</p>
<img src={require("./mdandersonlogo260x85.png")} alt="MD Anderson Cancer Center logo" style={{width:153, height:50, margin:2, 'margin-right':20, 'margin-bottom':20, float:'left'}}/>
<p>
The University of Texas MD Anderson Cancer Center has created a
Next-Generation Clustered Heatmap compendium
based on the same dataset or a very similar dataset containing many of the
same TCGA samples. Continue will display a page of NG-CHM based on
this dataset.
</p>
<div style={{clear:'left'}}/>
Read details on the data processing used for this TCGA compendium <a
href="https://bioinformatics.mdanderson.org/public-datasets/about-the-tcga-compendium/"
target='_blank'
>
here
</a> (opens in a new tab).
</div>
</Modal.Body>
<Modal.Footer>
<Button onClick={()=>{this.props.openNgchmWindow(); this.props.onHide();}}>Continue</Button>
<Button onClick={this.props.onHide}>Cancel</Button>
</Modal.Footer>
</Modal>
);
}
}
29 changes: 26 additions & 3 deletions src/shared/components/oncoprint/controls/OncoprintControls.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import * as React from 'react';
import {observer, Observer} from 'mobx-react';
import {Button, ButtonGroup} from 'react-bootstrap';
import {Button, ButtonGroup, Modal} from 'react-bootstrap';
import CustomDropdown from './CustomDropdown';
import ConfirmNgchmModal from './ConfirmNgchmModal';
import ReactSelect from 'react-select1';
import {MobxPromise} from 'mobxpromise';
import {action, computed, IObservableObject, observable, ObservableMap, reaction, toJS,} from 'mobx';
Expand Down Expand Up @@ -65,13 +66,12 @@ export interface IOncoprintControlsHandlers {
onChangeSelectedClinicalTracks?: (
attributeIds: (string | SpecialAttribute)[]
) => void;

onClickAddGenesToHeatmap?: () => void;
onClickAddTreatmentsToHeatmap?: (treatments: string[]) => void;
onSelectHeatmapProfile?: (molecularProfileId: string) => void;
onChangeHeatmapGeneInputValue?: (value: string) => void;
onChangeHeatmapTreatmentInputValue?: (value: string) => void;

onClickNGCHM: () => void;
onSetHorzZoom: (z: number) => void;
onClickZoomIn: () => void;
onClickZoomOut: () => void;
Expand Down Expand Up @@ -116,6 +116,7 @@ export interface IOncoprintControlsState {
heatmapGeneInputValue?: string;
heatmapTreatmentInputValue?: string;
hideHeatmapMenu?: boolean;
ngchmButtonActive?: boolean;

customDriverAnnotationBinaryMenuLabel?: string;
customDriverAnnotationTiersMenuLabel?: string;
Expand Down Expand Up @@ -176,6 +177,7 @@ const EVENT_KEY = {
downloadOrder: '28',
downloadTabular: '29',
horzZoomSlider: '30',
viewNGCHM: '31',
addTreatmentsToHeatmap: '32',
};

Expand All @@ -189,6 +191,7 @@ export default class OncoprintControls extends React.Component<
@observable private _selectedTreatmentIds: string[] = [];
private textareaTreatmentText = '';
@observable treatmentFilter = '';
@observable showConfirmNgchmModal:boolean = false;

constructor(props: IOncoprintControlsProps) {
super(props);
Expand Down Expand Up @@ -444,6 +447,11 @@ export default class OncoprintControls extends React.Component<
this.props.handlers.onClickDownload &&
this.props.handlers.onClickDownload('tabular');
break;
case EVENT_KEY.viewNGCHM:
if (this.props.state.ngchmButtonActive && this.props.handlers.onClickNGCHM) {
this.showConfirmNgchmModal = true;
}
break;
}
}

Expand Down Expand Up @@ -695,6 +703,16 @@ export default class OncoprintControls extends React.Component<
Add Treatment Response to Heatmap
</button>,
]}

{this.props.state.ngchmButtonActive &&
(<DefaultTooltip overlay={<span>Open a new tab for NG-CHM with this study from MD Anderson Cancer Center compendium.</span>}>
<button
className={classNames("btn", "btn-sm", "btn-default")}
name={EVENT_KEY.viewNGCHM}
onClick={this.onButtonClick}
>View Next-Generation Clustered Heat Map (NG-CHM)</button>
</DefaultTooltip>)
}
</div>
);
}
Expand Down Expand Up @@ -1309,6 +1327,11 @@ export default class OncoprintControls extends React.Component<
<Observer>{this.getDownloadMenu}</Observer>
<Observer>{this.getHorzZoomControls}</Observer>
{this.minimapButton}
<ConfirmNgchmModal
show={this.showConfirmNgchmModal}
onHide={()=>this.showConfirmNgchmModal=false}
openNgchmWindow={this.props.handlers.onClickNGCHM}
/>
</ButtonGroup>
</div>
);
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.