Skip to content

Commit

Permalink
Initial working version with multiple datasets
Browse files Browse the repository at this point in the history
  • Loading branch information
mdml committed Jun 21, 2020
1 parent f88ea43 commit 8264521
Show file tree
Hide file tree
Showing 12 changed files with 252 additions and 224 deletions.
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
"d3-zoom": "^1.8.3",
"eslint-config-airbnb": "^18.1.0",
"lodash": "^4.17.15",
"materialize-css": "^1.0.0-rc.2",
"query-string": "^6.9.0",
"react": "^16.12.0",
"react-dom": "^16.12.0",
Expand Down
30 changes: 16 additions & 14 deletions src/components/SortIcon.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import React, {useCallback, useState, useEffect} from 'react'
import Grid from '@material-ui/core/Grid'
import { ExpandLess, ExpandMore, Remove } from '@material-ui/icons'
import {ASCENDING, DESCENDING, NO_SORT} from '../constants.js'
import React, { useCallback, useState, useEffect } from 'react';
import Grid from '@material-ui/core/Grid';
import { ExpandLess, ExpandMore, Remove } from '@material-ui/icons';
import { ASCENDING, DESCENDING, NO_SORT } from '../constants.js';

const SortIcon = ({
onChange,
}) => {
// State
const [sortOrder, setSortOrder] = useState(NO_SORT)
const [sortOrder, setSortOrder] = useState(NO_SORT);

// Callbacks
const handleClick = useCallback( () => {
if (sortOrder === DESCENDING) setSortOrder(NO_SORT)
else if (sortOrder === NO_SORT) setSortOrder(ASCENDING)
else setSortOrder(DESCENDING)
}, [sortOrder, setSortOrder])
if (sortOrder === DESCENDING) setSortOrder(NO_SORT);
else if (sortOrder === NO_SORT) setSortOrder(ASCENDING);
else setSortOrder(DESCENDING);
}, [sortOrder, setSortOrder]);

// Effects
useEffect( () => onChange(sortOrder), [sortOrder])
useEffect(() => onChange(sortOrder), [sortOrder, onChange]);

// Render
let icon
Expand All @@ -30,8 +30,10 @@ const SortIcon = ({
}

return (
<Grid onClick={handleClick} style={{position: 'relative', top: '5px'}}>{icon}</Grid>
)
}
<Grid onClick={handleClick} style={{position: 'relative', top: '5px'}}>
{icon}
</Grid>
);
};

export default SortIcon
export default SortIcon;
43 changes: 19 additions & 24 deletions src/layout/Navbar.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
import React, {useState} from 'react'
import PropTypes from 'prop-types';
import Drawer from '@material-ui/core/Drawer'
import CssBaseline from '@material-ui/core/CssBaseline'
import AppBar from '@material-ui/core/AppBar'
import Toolbar from '@material-ui/core/Toolbar'
import Grid from '@material-ui/core/Grid'
import Typography from '@material-ui/core/Typography'
import { makeStyles } from '@material-ui/core/styles'
import List from '@material-ui/core/List'
import ListItem from '@material-ui/core/ListItem'
import ListItemText from '@material-ui/core/ListItemText'
import React from 'react';
import CssBaseline from '@material-ui/core/CssBaseline';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Grid from '@material-ui/core/Grid';
import Typography from '@material-ui/core/Typography';
import { makeStyles } from '@material-ui/core/styles';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import ListItemText from '@material-ui/core/ListItemText';
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom"
Link,
} from "react-router-dom";


import {About, Credits, DataExplorer, SuperDendrixResults} from '../pages'
import { About, Credits, DataExplorer, SuperDendrixResults } from '../pages';

const useStyles = makeStyles(theme => ({
appbar: {
Expand All @@ -38,13 +36,10 @@ const useStyles = makeStyles(theme => ({
textDecoration: 'underline',
},
},
}))
}));

const Navbar = ({
styles,
css,
}) => {
const classes = useStyles()
const Navbar = () => {
const classes = useStyles();
return (
<Router>
<CssBaseline />
Expand Down Expand Up @@ -83,7 +78,7 @@ const Navbar = ({
</Route>
</Switch>
</Router>
)
}
);
};

export default Navbar
export default Navbar;
3 changes: 2 additions & 1 deletion src/pages/SuperDendrixResults.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const SuperDendrixResults = withRouter(({
<InputLabel id="dataset-select">Dataset</InputLabel>
<Select
labelId="dataset-select"
value={selectedDataset}
value={datasets.includes(selectedDataset) ? selectedDataset : ''}
onChange={(e) => setSelectedDataset(e.target.value)}
>
{
Expand Down Expand Up @@ -102,6 +102,7 @@ const SuperDendrixResults = withRouter(({
search: queryString.stringify({
alterations: alterations.sort(ascending),
profileName: profile,
dataset: selectedDataset,
})
})
}}
Expand Down
24 changes: 12 additions & 12 deletions src/pages/explorer/charts/AlterationTooltip.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import React, {useState, useEffect, useRef} from 'react'
import { makeStyles } from '@material-ui/core/styles'
import Table from '@material-ui/core/Table'
import TableBody from '@material-ui/core/TableBody'
import TableCell from '@material-ui/core/TableCell'
import TableHead from '@material-ui/core/TableHead'
import TableRow from '@material-ui/core/TableRow'
import Box from '@material-ui/core/Box'
import Popover from '@material-ui/core/Popover'
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Table from '@material-ui/core/Table';
import TableBody from '@material-ui/core/TableBody';
import TableCell from '@material-ui/core/TableCell';
import TableHead from '@material-ui/core/TableHead';
import TableRow from '@material-ui/core/TableRow';
import Box from '@material-ui/core/Box';
import Popover from '@material-ui/core/Popover';

const useStyles = makeStyles(theme => ({
popover: {
Expand Down Expand Up @@ -83,7 +83,7 @@ const AlterationTooltip = ({
</Table>
</Box>
</Popover>
)
}
);
};

export default AlterationTooltip
export default AlterationTooltip;
96 changes: 52 additions & 44 deletions src/pages/explorer/charts/Chart.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
import React, {useEffect, useMemo, useState, useRef, useCallback} from 'react'
import { makeStyles } from '@material-ui/core/styles'
import Grid from '@material-ui/core/Grid'
import Typography from '@material-ui/core/Typography'
import {fromPairs, range} from 'lodash'
import {select, event as d3Event} from 'd3-selection'
import {brushX} from 'd3-brush'
import {scaleLinear, scaleBand, scaleLog} from 'd3-scale'
import {extent, min, max, ascending} from 'd3-array'
import {axisLeft, axisBottom} from 'd3-axis'

import AlterationTooltip from './AlterationTooltip.js'
import './style.css'
import {fieldSorter} from '../../../helpers.js'
import {ASCENDING, DESCENDING, NO_SORT} from '../../../constants.js'
import React, { useEffect, useMemo, useState, useRef, useCallback } from 'react';
import Grid from '@material-ui/core/Grid';
import { fromPairs } from 'lodash';
import {select, event as d3Event} from 'd3-selection';
import { brushX } from 'd3-brush';
import { scaleLinear, scaleBand } from 'd3-scale';
import { extent, max, ascending } from 'd3-array';
import { axisLeft } from 'd3-axis';

import AlterationTooltip from './AlterationTooltip.js';
import './style.css';
import { fieldSorter } from '../../../helpers.js';
import { ASCENDING, NO_SORT } from '../../../constants.js';

// Constants
const margin = { left: 100, top: 10, right: 30, bottom: 30}
const paddingInner = 0
const margin = {
left: 100,
top: 10,
right: 30,
bottom: 30
};
const paddingInner = 0;

const Chart = ({
alterations,
Expand Down Expand Up @@ -44,11 +47,12 @@ const Chart = ({
// CHART COMPUTATION
//////////////////////////////////////////////////////////////////////////////
// Data preprocessing
const width = useMemo( () => containerWidth - margin.left - margin.right, [containerWidth])
const samples = useMemo( () => Object.keys(scores), [scores])
const values = useMemo( () => samples.map( s => scores[s] ), [scores, samples])
const events = useMemo( () => Object.keys(alterations), [alterations])
const alterationCounts = useMemo( () => samples.map(s => sampleToAlterationCount[s] ), [samples, sampleToAlterationCount])
const width = useMemo(() => containerWidth - margin.left - margin.right, [containerWidth]);
const samples = useMemo(() => Object.keys(scores), [scores]);
const values = useMemo(() => samples.map( s => scores[s]), [scores, samples]);
const events = useMemo(() => Object.keys(alterations), [alterations]);
const alterationCounts = useMemo(() => samples.map(s => sampleToAlterationCount[s]).map((c) => c ? c : 1), [samples, sampleToAlterationCount]);
const maxAlterationCount = useMemo(() => max(alterationCounts), [alterationCounts]);

const alterationMap = useMemo( () => (
fromPairs(
Expand Down Expand Up @@ -84,8 +88,8 @@ const Chart = ({
score: scores[s],
tissue: sampleToTissue[s],
alterations: alterationIndex,
}
})
};
});

// Do some custom sorting, always sorting by sample at the end
const fields = [ ]
Expand All @@ -111,17 +115,18 @@ const Chart = ({

const brushXScale = useMemo( () => (
scaleBand().domain(sortedSamples).range([0, width]).paddingInner(paddingInner)
), [sortedSamples, width])
), [sortedSamples, width]);
const brushYScale = useMemo( () => (
scaleLinear().domain([1, max(alterationCounts)+1]).range([brushHeight, 0])
), [alterationCounts])
scaleLinear().domain([1, maxAlterationCount+1]).range([brushHeight, 0])
), [maxAlterationCount]);

const barXScale = useMemo( () => {
return scaleBand().domain(visibleSamples).range([0, width]).paddingInner(paddingInner)
}, [visibleSamples, width]);
const barYScale = useMemo( () => (
scaleLinear().domain(extent(values)).range([barHeight, 0])
), [values, barHeight]);
const barYScale = useMemo( () => {
const domain = samples.length === 0 ? [-100, 100] : extent(values);
return scaleLinear().domain(domain).range([barHeight, 0])
}, [samples, values, barHeight]);

//////////////////////////////////////////////////////////////////////////////
// THRESHOLD SCORE LOGIC
Expand Down Expand Up @@ -157,7 +162,7 @@ const Chart = ({
return 0.2
}
return 1;
}, [thresholdScore, legend.sort]);
}, [legend.sort, thresholdXIndex]);

//////////////////////////////////////////////////////////////////////////////
// EFFECTS
Expand All @@ -177,7 +182,7 @@ const Chart = ({
} else { // reset
setVisibleSamples(sortedSamples)
}
})
});

select(el).on('click', () => {
select(el).call(brush.move, null) // reset on click
Expand All @@ -188,7 +193,7 @@ const Chart = ({
select(el).call(brush.move, null) // reset on click

return () => select(el).on(".brush", null) // destruct
}, [samples, sortedSamples, width])
}, [brushXScale, samples, sortedSamples, width]);


// Add axes
Expand All @@ -211,7 +216,10 @@ const Chart = ({
return () => {
window.removeEventListener('resize', handleResize)
}
})
});

// Change the data
useEffect(() => setHighlightedSample(null), [samples, alterations]);

//////////////////////////////////////////////////////////////////////////////
// EVENT HANDLERS
Expand All @@ -227,10 +235,10 @@ const Chart = ({
// HELPERS
//////////////////////////////////////////////////////////////////////////////
const sampleFill = useCallback( (s) => {
const sampleAlterations = sampleToAlterations[s]
if (sampleAlterations.length === 0) return 'lightgray'
else if (sampleAlterations.length > 1) return 'black'
else return legend.eventColors[sampleAlterations[0]]
const sampleAlterations = sampleToAlterations[s] || [];
if (sampleAlterations.length === 0) return 'lightgray';
else if (sampleAlterations.length > 1) return 'black';
else return legend.eventColors[sampleAlterations[0]];
}, [legend, sampleToAlterations]);

const sampleOpacity = useCallback((s) => {
Expand Down Expand Up @@ -314,13 +322,13 @@ const Chart = ({
/>
<g id="Bars">
{
visibleSamples.map( s => (
visibleSamples.map(s => (
<rect
key={s}
x={barXScale(s)}
y={barYScale(Math.max(0, scores[s]))}
y={barYScale(Math.max(0, scores[s] ? scores[s] : 0))}
width={barXScale.bandwidth()}
height={Math.abs(barYScale(scores[s]) - barYScale(0))}
height={Math.abs(barYScale(scores[s] ? scores[s] : 0) - barYScale(0))}
fillOpacity={sampleOpacity(s)}
fill={sampleFill(s)}
onMouseEnter={(e) => handleMouseEnter(e, s)}
Expand Down Expand Up @@ -357,7 +365,7 @@ const Chart = ({
/>
}
</Grid>
)
}
);
};

export default Chart
export default Chart;
Loading

0 comments on commit 8264521

Please sign in to comment.