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 ability to spawn code notebooks from cBioPortal queries #4856

Merged
merged 33 commits into from
Aug 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
75e3472
Add ability to spawn code notebooks first-commit
gautamsarawagi Feb 26, 2024
01e07f6
Merge branch 'cBioPortal:master' into spawn_code_notebook
gautamsarawagi Feb 28, 2024
a016406
Toolbar added to run the code
gautamsarawagi Feb 28, 2024
e58141b
Merge branch 'cBioPortal:master' into spawn_code_notebook
gautamsarawagi Mar 7, 2024
c375294
File Added to Read the Content
gautamsarawagi Mar 8, 2024
24c15a8
Merge branch 'cBioPortal:master' into spawn_code_notebook
gautamsarawagi Mar 8, 2024
f054014
Merge branch 'cBioPortal:master' into spawn_code_notebook
gautamsarawagi Mar 15, 2024
93e90f1
AddedNotebook Code and Modified Iframe
gautamsarawagi Mar 17, 2024
6684d51
Create READEME.md for the notebook
gautamsarawagi Mar 17, 2024
c8719b5
Merge branch 'cBioPortal:master' into spawn_code_notebook
gautamsarawagi Mar 21, 2024
0f00437
File Communication with Button Added and Notebook Code Removed
gautamsarawagi Mar 21, 2024
b8a40fb
Files Saving Successful on page load
gautamsarawagi Mar 22, 2024
852cb3d
file-name Changed and attempt to auto-execute the file
gautamsarawagi Mar 27, 2024
f9b568f
Task 1 Updates
gautamsarawagi Jun 17, 2024
8976b10
Merge branch 'cBioPortal:master' into spawn_code_notebook
gautamsarawagi Jun 17, 2024
5608105
Merge branch 'cBioPortal:master' into spawn_code_notebook
gautamsarawagi Jul 15, 2024
980056a
Session Modal Added
gautamsarawagi Jul 15, 2024
1dae9c3
Added Loader and Changes in the Headers of the Host Page
gautamsarawagi Jul 25, 2024
21b3627
Merge branch 'cBioPortal:master' into spawn_code_notebook
gautamsarawagi Jul 25, 2024
9f3a248
Added more policies with the url
gautamsarawagi Jul 25, 2024
0ac925f
Code Refactor and Monitoring the Extension
gautamsarawagi Jul 29, 2024
76c6bcb
Updating headers
gautamsarawagi Jul 29, 2024
f4b52ba
Merge branch 'cBioPortal:master' into spawn_code_notebook
gautamsarawagi Jul 30, 2024
d1e0477
Using LocalStorage Instead of Directly Sending
gautamsarawagi Jul 30, 2024
eb9a094
Updated Notebook Content
gautamsarawagi Aug 1, 2024
740f598
Removed Iframe Changes
gautamsarawagi Aug 7, 2024
cdeda8f
Updated Url and Oncoprinter fixes for Jupyter
gautamsarawagi Aug 9, 2024
8d55ec8
Update READEME.md
alisman Aug 12, 2024
52db8a0
Deleting notebookContent on modal close and updated notebook readme
gautamsarawagi Aug 12, 2024
695edbf
Merge branch 'cBioPortal:master' into spawn_code_notebook
gautamsarawagi Aug 12, 2024
9502794
Update OncoprintControls.tsx
gautamsarawagi Aug 12, 2024
a7c1abd
Merge branch 'cBioPortal:master' into spawn_code_notebook
gautamsarawagi Aug 19, 2024
52c65d1
Correct the Filename and Added Beta! text in button
gautamsarawagi Aug 19, 2024
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
5 changes: 5 additions & 0 deletions notebook/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

## For using the notebook and its contents:

1. The code for the Jupyterlite extension and the environment can be accessed from [here](https://github.com/cBioPortal/cbio-jupyter).
2. The instructions to use it present in this [file](https://github.com/cBioPortal/cbio-jupyter/blob/main/README.md)
148 changes: 148 additions & 0 deletions src/pages/staticPages/tools/oncoprinter/JupyterNotebookModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import { action, observable } from 'mobx';
import React from 'react';
import {
Modal,
Form,
FormControl,
FormGroup,
ControlLabel,
Button,
} from 'react-bootstrap';
import { buildCBioPortalPageUrl } from 'shared/api/urls';

interface FilenameModalProps {
show: boolean;
fileContent: string;
fileName: string;
handleClose: () => void;
}

interface FilenameModalState {
folderName: string;
validated: boolean;
errorMessage: string;
}

class JupyterNoteBookModal extends React.Component<
FilenameModalProps,
FilenameModalState
> {
public channel: BroadcastChannel;

constructor(props: FilenameModalProps) {
super(props);
this.state = {
folderName: '',
validated: false,
errorMessage: '',
};
this.channel = new BroadcastChannel('jupyter_channel');
}

componentDidMount() {
this.setState({ folderName: '' });
}

handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
this.setState({ folderName: event.target.value, errorMessage: '' });
};

@action
handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();

const { folderName } = this.state;

if (folderName.trim() === '' || /\s/.test(folderName)) {
this.setState({
validated: false,
errorMessage: 'Session name cannot be empty or contain spaces',
});
return;
}

const { fileContent, fileName } = this.props;

const data = {
type: 'from-cbioportal-to-jupyterlite',
fileContent: fileContent,
filename: `${fileName}.csv`,
folderName: folderName,
};

const jupyterNotebookTool = window.open(
'https://cbio-jupyter.netlify.app/lite/lab/index.html',
'_blank'
);

if (jupyterNotebookTool) {
const receiveMessage = (event: MessageEvent) => {
if (event.data.type === 'jupyterlite-ready') {
console.log('Now sending the data...');
jupyterNotebookTool.postMessage(data, '*');
window.removeEventListener('message', receiveMessage);
this.props.handleClose();
}
};

window.addEventListener('message', receiveMessage);
}

this.setState({ folderName: '', validated: false, errorMessage: '' });
// this.props.handleClose();
};

render() {
const { show, handleClose } = this.props;
const { folderName, errorMessage } = this.state;

return (
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>Enter Session Name</Modal.Title>
</Modal.Header>
<Modal.Body>
<Form
onSubmit={e =>
this.handleSubmit(
(e as unknown) as React.FormEvent<
HTMLFormElement
>
)
}
>
<FormGroup controlId="formFolderName">
<ControlLabel className="py-2">
Session Name
</ControlLabel>
<FormControl
type="text"
placeholder="Enter Session Name"
value={folderName}
onChange={e =>
this.handleChange(
(e as unknown) as React.ChangeEvent<
HTMLInputElement
>
)
}
required
/>
{errorMessage && (
<div style={{ color: 'red' }}>
{errorMessage}
</div>
)}
</FormGroup>
<Modal.Footer>
<Button onClick={handleClose}>Close</Button>
<Button type="submit">Open Jupyter Notebook</Button>
</Modal.Footer>
</Form>
</Modal.Body>
</Modal>
);
}
}

export default JupyterNoteBookModal;
60 changes: 60 additions & 0 deletions src/pages/staticPages/tools/oncoprinter/Oncoprinter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ import ClinicalTrackColorPicker from 'shared/components/oncoprint/ClinicalTrackC
import classnames from 'classnames';
import { getDefaultClinicalAttributeColoringForStringDatatype } from './OncoprinterToolUtils';
import { OncoprintColorModal } from 'shared/components/oncoprint/OncoprintColorModal';
import JupyterNoteBookModal from './JupyterNotebookModal';
import { convertToCSV } from 'shared/lib/calculation/JSONtoCSV';

interface IOncoprinterProps {
divId: string;
Expand Down Expand Up @@ -73,6 +75,20 @@ export default class Oncoprinter extends React.Component<

@observable.ref public oncoprint: OncoprintJS | undefined = undefined;

@observable public showJupyterNotebookModal = false;
@observable private jupyterFileContent = '';
@observable private jupyterFileName = '';

@action
private openJupyterNotebookModal = () => {
this.showJupyterNotebookModal = true;
};

@action
private closeJupyterNotebookModal = () => {
this.showJupyterNotebookModal = false;
};

constructor(props: IOncoprinterProps) {
super(props);

Expand Down Expand Up @@ -280,6 +296,44 @@ export default class Oncoprinter extends React.Component<
file += `${caseId}\n`;
}
fileDownload(file, `OncoPrintSamples.txt`);
break;
case 'jupyterNoteBook':
const fieldsToKeep = [
'hugoGeneSymbol',
'alterationType',
'chr',
'startPosition',
'endPosition',
'referenceAllele',
'variantAllele',
'proteinChange',
'proteinPosStart',
'proteinPosEnd',
'mutationType',
'oncoKbOncogenic',
'patientId',
'sampleId',
'isHotspot',
];

if (
this.props.store._mutations &&
this.props.store._studyIds
) {
const allGenesMutationsCsv = convertToCSV(
this.props.store.mutationsDataProps,
fieldsToKeep
);

this.jupyterFileContent = allGenesMutationsCsv;

this.jupyterFileName = this.props.store.studyIdProps.join(
'&'
);

this.openJupyterNotebookModal();
}

break;
}
},
Expand Down Expand Up @@ -569,6 +623,12 @@ export default class Oncoprinter extends React.Component<
</div>
</div>
</div>
<JupyterNoteBookModal
show={this.showJupyterNotebookModal}
handleClose={this.closeJupyterNotebookModal}
fileContent={this.jupyterFileContent}
fileName={this.jupyterFileName}
/>
</div>
);
}
Expand Down
16 changes: 16 additions & 0 deletions src/pages/staticPages/tools/oncoprinter/OncoprinterStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ export default class OncoprinterStore {
@observable hideGermlineMutations = false;
@observable customDriverWarningHidden: boolean;

@observable _mutations: string | undefined = undefined;
@observable _studyIds: string | undefined = undefined;

@observable _userSelectedClinicalTracksColors: {
[trackLabel: string]: {
[attributeValue: string]: RGBAColor;
Expand Down Expand Up @@ -205,6 +208,19 @@ export default class OncoprinterStore {
this.initialize();
}

@action public setJupyterInput(mutations: string, studyIds: string) {
this._mutations = mutations;
this._studyIds = studyIds;
}

@computed get mutationsDataProps() {
if (this._mutations) return JSON.parse(this._mutations);
}

@computed get studyIdProps() {
if (this._studyIds) return JSON.parse(this._studyIds);
}

@computed get parsedGeneticInputLines() {
if (!this._geneticDataInput) {
return {
Expand Down
14 changes: 14 additions & 0 deletions src/pages/staticPages/tools/oncoprinter/OncoprinterTool.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ export default class OncoprinterTool extends React.Component<
@observable geneOrderInput = '';
@observable sampleOrderInput = '';

// jupyter incoming data
@observable mutations = '';
@observable studyIds = '';

constructor(props: IOncoprinterToolProps) {
super(props);
makeObservable(this);
Expand All @@ -76,11 +80,17 @@ export default class OncoprinterTool extends React.Component<
this.geneticDataInput = postData.genetic;
this.clinicalDataInput = postData.clinical;
this.heatmapDataInput = postData.heatmap;
this.studyIds = postData.studyIds;
this.mutations = postData.mutations;

this.doSubmit(
this.geneticDataInput,
this.clinicalDataInput,
this.heatmapDataInput
);

this.handleJupyterData(this.mutations, this.studyIds);

getBrowserWindow().clientPostedData = null;
}
}
Expand Down Expand Up @@ -163,6 +173,10 @@ export default class OncoprinterTool extends React.Component<
}
}

@action private handleJupyterData(mutations: string, studyIds: string) {
this.store.setJupyterInput(mutations, studyIds);
}

@autobind private geneticFileInputRef(input: HTMLInputElement | null) {
this.geneticFileInput = input;
}
Expand Down
Loading