From f88ea43997078ba52f9eeedd6c401a1ccdbbaaa0 Mon Sep 17 00:00:00 2001 From: Max Leiserson Date: Wed, 10 Jun 2020 16:30:55 -0400 Subject: [PATCH] Add SuperDendrix Results --- src/layout/Navbar.js | 8 +- src/pages/About.js | 21 ++++- src/pages/Credits.js | 19 ++++- src/pages/SuperDendrixResults.js | 125 +++++++++++++++++++++++++++++ src/pages/explorer/charts/Chart.js | 21 +++-- src/pages/index.js | 8 +- 6 files changed, 190 insertions(+), 12 deletions(-) create mode 100644 src/pages/SuperDendrixResults.js diff --git a/src/layout/Navbar.js b/src/layout/Navbar.js index 2aee59c..76bce17 100644 --- a/src/layout/Navbar.js +++ b/src/layout/Navbar.js @@ -18,7 +18,7 @@ import { } from "react-router-dom" -import {About, Credits, DataExplorer} from '../pages' +import {About, Credits, DataExplorer, SuperDendrixResults} from '../pages' const useStyles = makeStyles(theme => ({ appbar: { @@ -59,6 +59,7 @@ const Navbar = ({ Explorer + SuperDendrix About Credits @@ -74,7 +75,10 @@ const Navbar = ({ - + + + + diff --git a/src/pages/About.js b/src/pages/About.js index 165e2bd..baf5a70 100644 --- a/src/pages/About.js +++ b/src/pages/About.js @@ -1,11 +1,30 @@ import React from 'react'; +import { Link } from 'react-router-dom'; import Container from '@material-ui/core/Container' import Typography from '@material-ui/core/Typography' const About = () => { return ( - + About + This web application is for exploring genetic dependencies profiles + and alterations in cancer cell line data (Park et al. in submission). + (See Credits for details on the data.) + Users select a profile and set of alterations to view, and the web application + creates a waterfall plot of the dependency scores and alterations. +

+ SuperDendrix refers to a computational pipeline for identifying sets of alterations + and cancer types that are significantly associated with genetic dependencies. + These results are available in SuperDendrix Results. +

+ Contributors* + + *Strict random order
) } diff --git a/src/pages/Credits.js b/src/pages/Credits.js index b5a8d46..9f98bff 100644 --- a/src/pages/Credits.js +++ b/src/pages/Credits.js @@ -1,11 +1,28 @@ import React from 'react'; +import { Link } from 'react-router-dom'; import Container from '@material-ui/core/Container' import Typography from '@material-ui/core/Typography' const Credits = () => { return ( - + Credits + Technology
+ This web application was built with open-source tools, including: + + It is hosted on Heroku and GitHub Pages, and is open-source. +

+ Data
+ This web application uses public data from two projects from the Broad Institute: + + For more details on this project, see the About page.
) } diff --git a/src/pages/SuperDendrixResults.js b/src/pages/SuperDendrixResults.js new file mode 100644 index 0000000..d640474 --- /dev/null +++ b/src/pages/SuperDendrixResults.js @@ -0,0 +1,125 @@ +import React, { useState, useEffect } from 'react'; +import Container from '@material-ui/core/Container'; +import Grid from '@material-ui/core/Grid'; +import Typography from '@material-ui/core/Typography'; +import FormControl from '@material-ui/core/FormControl'; +import Select from '@material-ui/core/Select'; +import MenuItem from '@material-ui/core/MenuItem'; +import InputLabel from '@material-ui/core/InputLabel'; +import Table from '@material-ui/core/Table'; +import TableBody from '@material-ui/core/TableBody'; +import TableCell from '@material-ui/core/TableCell'; +import TableContainer from '@material-ui/core/TableContainer'; +import TableHead from '@material-ui/core/TableHead'; +import TableRow from '@material-ui/core/TableRow'; +import {json as d3Json} from 'd3-fetch'; +import {ascending} from 'd3-array'; +import queryString from 'query-string'; +import {withRouter} from 'react-router'; + +const SuperDendrixResults = withRouter(({ + history, + location, +}) => { + // Load the manifest with the list of datasets + const dataURL = `${process.env.REACT_APP_SUPERDENDRIX_DATA_URL}/manifest.json`; + const [datasets, setDatasets] = useState([]); + const [selectedDataset, setSelectedDataset] = useState('19Q1'); + useEffect( () => { + d3Json(dataURL) + .then((jsonData) => setDatasets(jsonData.datasets)) + .catch((error) => { + console.error(error) + }) + }, [dataURL]); + + // Load the SuperDendrix results + const superDendrixResultsURL = `${process.env.REACT_APP_SUPERDENDRIX_DATA_URL}/${selectedDataset}/superdendrix-results.json`; + const [superDendrixResults, setSuperDendrixResults] = useState([]); + useEffect(() => { + d3Json(superDendrixResultsURL) + .then((jsonData) => setSuperDendrixResults(jsonData.sets)) + .catch( (error) => { + console.error(error) + }) + }, [selectedDataset, superDendrixResultsURL, setSuperDendrixResults]); + + return ( + + + + SuperDendrix Results + + + + Dataset + + + + + Click on the row to view the set in the Explorer! + + + + + + + Profile Name + Alterations + Weight W(M) + FDR + + +
+
+
+ + + + + { + superDendrixResults.map(({ + profile, + alterations, + weight, + fdr, + }, i) => ( + { + history.push({ + pathname: '/', + search: queryString.stringify({ + alterations: alterations.sort(ascending), + profileName: profile, + }) + }) + }} + style={{ cursor: 'pointer' }} + > + {profile} + {alterations.join(', ')} + { weight } + { fdr } + + ))} + +
+
+
+
+
+ ); +}); + +export default SuperDendrixResults; diff --git a/src/pages/explorer/charts/Chart.js b/src/pages/explorer/charts/Chart.js index 776476f..1212de0 100644 --- a/src/pages/explorer/charts/Chart.js +++ b/src/pages/explorer/charts/Chart.js @@ -127,10 +127,21 @@ const Chart = ({ // THRESHOLD SCORE LOGIC ////////////////////////////////////////////////////////////////////////////// const thresholdXIndex = useMemo( () => { + // Handle the increased dependency + if (direction === 'increased_dependency'){ + let index = -1; + sortedSamples.forEach((sample, i) => { + if (scores[sample] > thresholdScore && index === -1){ + index = i - 1; + } + }); + return index === -1 ? null : sortedSamples[index]; + } + // Handle the decreased dependency let index = -1; - sortedSamples.forEach((sample, i) => { - if (direction === 'increased_dependency' && scores[sample] > thresholdScore && index === -1){ - index = i - 1; + [...sortedSamples].reverse().forEach((sample, i) => { + if (scores[sample] < thresholdScore && index === -1){ + index = sortedSamples.length - (i - 1); } }); return index === -1 ? null : sortedSamples[index]; @@ -224,9 +235,9 @@ const Chart = ({ const sampleOpacity = useCallback((s) => { if (direction === 'increased_dependency'){ - return scores[s] < thresholdScore ? 1 : 0.5 + return scores[s] < thresholdScore ? 1 : 1; } - return scores[s] > thresholdScore ? 1 : 0.5 + return scores[s] > thresholdScore ? 1 : 1; }, [scores, thresholdScore, direction]); ////////////////////////////////////////////////////////////////////////////// diff --git a/src/pages/index.js b/src/pages/index.js index 90d07fa..74942fb 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -1,8 +1,10 @@ -import About from './About.js' -import Credits from './Credits.js' -import DataExplorer from './explorer' +import About from './About.js'; +import Credits from './Credits.js'; +import DataExplorer from './explorer'; +import SuperDendrixResults from './SuperDendrixResults'; export { About, Credits, DataExplorer, + SuperDendrixResults, }