Skip to content

Commit

Permalink
add signature activities table (#127)
Browse files Browse the repository at this point in the history
- add basic version of signature activities table
- improve some controllers to prevent unnecessary re-renders and re-dispatch of actions
- add actions, queries, and reducer functions to get signature activities
- get min/max/range of activities in given signature
  • Loading branch information
vincerubinetti authored Mar 30, 2020
1 parent d077afd commit 8f68997
Show file tree
Hide file tree
Showing 24 changed files with 12,478 additions and 12,218 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "adage-frontend",
"version": "0.2.2",
"version": "0.2.3",
"dependencies": {
"@greenelab/hclust": "^0.0.0",
"@stdlib/stdlib": "^0.0.91",
Expand Down
9 changes: 6 additions & 3 deletions src/actions/samples.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { createFetchAction } from './fetch';

import { urlSampleDetails } from '../backend/samples';
import { urlSampleList } from '../backend/samples';
import { urlActivities } from '../backend/samples';
import { urlSampleActivities } from '../backend/samples';

// actions related to the "sample" sub-object of the state

Expand Down Expand Up @@ -36,8 +36,11 @@ export const getSampleSelectedDetails = createAction(
'GET_SAMPLE_SELECTED_DETAILS'
);

// get signatures for specified samples
export const getActivities = createFetchAction('GET_ACTIVITIES', urlActivities);
// get activities for specified samples
export const getSampleActivities = createFetchAction(
'GET_SAMPLE_ACTIVITIES',
urlSampleActivities
);

// calculate volcano plot data based on sample groups and set it in state
export const setVolcano = createAction('SET_VOLCANO');
7 changes: 7 additions & 0 deletions src/actions/signatures.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { createFetchAction } from './fetch';
import { urlSignatureDetails } from '../backend/signatures';
import { urlSignatureList } from '../backend/signatures';
import { urlSignatureParticipations } from '../backend/signatures';
import { urlSignatureActivities } from '../backend/signatures';

// actions related to the "signature" sub-object of the state

Expand Down Expand Up @@ -35,3 +36,9 @@ export const getSignatureParticipations = createFetchAction(
'GET_SIGNATURE_PARTICIPATIONS',
urlSignatureParticipations
);

// get activities for specified signatures
export const getSignatureActivities = createFetchAction(
'GET_SIGNATURE_ACTIVITIES',
urlSignatureActivities
);
6 changes: 5 additions & 1 deletion src/backend/samples.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ export const urlSampleList = ({ limit = defaultLimit }) => {
return url;
};

export const urlActivities = ({ modelId, sampleIds, limit = defaultLimit }) => {
export const urlSampleActivities = ({
modelId,
sampleIds,
limit = defaultLimit
}) => {
const params = new URLSearchParams();
params.set('limit', limit);
if (modelId)
Expand Down
17 changes: 17 additions & 0 deletions src/backend/signatures.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { defaultLimit } from '.';

const prefixA = 'signature/';
const prefixB = 'participation/';
const prefixC = 'activity/';

export const urlSignatureDetails = ({ id }) => {
const url = server + prefixA + id;
Expand All @@ -30,3 +31,19 @@ export const urlSignatureParticipations = ({ id, limit = defaultLimit }) => {
const url = server + prefixB + '?' + params.toString();
return url;
};

export const urlSignatureActivities = ({
modelId,
signatureIds,
limit = defaultLimit
}) => {
const params = new URLSearchParams();
params.set('limit', limit);
if (modelId)
params.set('mlmodel', modelId);
if (signatureIds)
params.set('signatures', signatureIds.join(','));

const url = server + prefixC + '?' + params.toString();
return url;
};
1 change: 1 addition & 0 deletions src/components/table/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
}
.th {
height: 28px;
font-weight: 500;
transition: color var(--fast);
user-select: none;
}
Expand Down
8 changes: 7 additions & 1 deletion src/controllers/genes.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,18 +59,23 @@ let GeneController = ({
// when selected genes change
// re-get participations
useEffect(() => {
// if we dont have all we need, dont even dispatch action
if (!selectedGenesLoaded)
return;

getGeneParticipations({
cancelType: 'GET_GENE_PARTICIPATIONS',
ids: selectedGenes.map((gene) => gene.id),
limit: selectedGenes.length ? MAX_INT : 1
});
}, [selectedGenes, getGeneParticipations]);
}, [selectedGenes, selectedGenesLoaded, getGeneParticipations]);

// when full gene or signature lists load, or selected genes change
// recompute enriched signatures
useEffect(() => {
// if we dont have all we need, dont even dispatch action
if (
!selectedGenesLoaded ||
!isArray(geneParticipations) ||
!geneParticipations.length ||
!isArray(geneList) ||
Expand All @@ -94,6 +99,7 @@ let GeneController = ({
}, [
geneParticipations,
selectedGenes,
selectedGenesLoaded,
geneList,
signatureList,
setEnrichedSignatures
Expand Down
32 changes: 5 additions & 27 deletions src/controllers/samples.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ import { connect } from 'react-redux';

import { getSampleList } from '../actions/samples';
import { getSampleSelectedDetails } from '../actions/samples';
import { getSignatureSelectedDetails } from '../actions/signatures';
import { getActivities } from '../actions/samples';
import { getSampleActivities } from '../actions/samples';
import { setVolcano } from '../actions/samples';
import { selectSamples } from '../actions/samples';
import { isArray } from '../util/types';
Expand All @@ -22,16 +21,13 @@ let SampleController = ({
signatureList,
selectedModel,
selectedExperiment,
selectedSignature,
selectedSamplesLoaded,
selectedSignatureLoaded,
activities,
diamondGroup,
spadeGroup,
getSampleList,
getSampleSelectedDetails,
getSignatureSelectedDetails,
getActivities,
getSampleActivities,
setVolcano,
selectSamples
}) => {
Expand Down Expand Up @@ -62,21 +58,6 @@ let SampleController = ({
getSampleSelectedDetails();
}, [sampleList.length, selectedSamplesLoaded, getSampleSelectedDetails]);

// when full signature list loads or when new signature selected
// fill in full details of selected signature
useEffect(() => {
// if details already filled in, exit
if (selectedSignatureLoaded)
return;

getSignatureSelectedDetails();
}, [
signatureList.length,
selectedSignature.id,
selectedSignatureLoaded,
getSignatureSelectedDetails
]);

// when selected model or experiment changes
// get sample activities
useEffect(() => {
Expand All @@ -88,12 +69,12 @@ let SampleController = ({
)
return;

getActivities({
getSampleActivities({
modelId: selectedModel,
sampleIds: selectedExperiment.samples.map((sample) => sample.id),
limit: MAX_INT
});
}, [selectedModel, selectedExperiment, getActivities]);
}, [selectedModel, selectedExperiment, getSampleActivities]);

// when sample groups or activities change
// recalculate volcano plot data
Expand Down Expand Up @@ -129,11 +110,9 @@ const mapStateToProps = (state) => ({
signatureList: state.signatures.list,
selectedModel: state.models.selected,
selectedExperiment: state.experiments.selected,
selectedSignature: state.signatures.selected,
selectedSamplesLoaded: state.samples.selected.every(
(selected) => selected.name
),
selectedSignatureLoaded: state.signatures.selected.name ? true : false,
activities: state.samples.activities,
diamondGroup: state.samples.groups.diamond,
spadeGroup: state.samples.groups.spade
Expand All @@ -142,8 +121,7 @@ const mapStateToProps = (state) => ({
const mapDispatchToProps = makeMapDispatchToProps({
getSampleList,
getSampleSelectedDetails,
getSignatureSelectedDetails,
getActivities,
getSampleActivities,
setVolcano,
selectSamples
});
Expand Down
25 changes: 21 additions & 4 deletions src/controllers/signatures.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { connect } from 'react-redux';
import { getSignatureList } from '../actions/signatures';
import { getSignatureSelectedDetails } from '../actions/signatures';
import { getSignatureParticipations } from '../actions/signatures';
import { getSignatureActivities } from '../actions/signatures';
import { MAX_INT } from './';
import { makeMapDispatchToProps } from './util';

Expand All @@ -16,7 +17,8 @@ let SignatureController = ({
selectedSignatureLoaded,
getSignatureList,
getSignatureSelectedDetails,
getSignatureParticipations
getSignatureParticipations,
getSignatureActivities
}) => {
// when selected model changes
// get full signature list
Expand Down Expand Up @@ -45,7 +47,7 @@ let SignatureController = ({
getSignatureSelectedDetails
]);

// when selected signature change
// when selected signature changes
// re-get participations
useEffect(() => {
// if we don't have all we need, exit
Expand All @@ -57,7 +59,21 @@ let SignatureController = ({
id: selectedSignature.id,
limit: MAX_INT
});
}, [selectedSignature, getSignatureParticipations]);
}, [selectedSignature.id, getSignatureParticipations]);

// when selected model or signature changes
// get signature activities
useEffect(() => {
// if we dont have all we need, dont even dispatch action
if (!selectedModel || !selectedSignature.id)
return;

getSignatureActivities({
modelId: selectedModel,
signatureIds: [selectedSignature.id],
limit: MAX_INT
});
}, [selectedModel, selectedSignature.id, getSignatureActivities]);

return <></>;
};
Expand All @@ -72,7 +88,8 @@ const mapStateToProps = (state) => ({
const mapDispatchToProps = makeMapDispatchToProps({
getSignatureList,
getSignatureSelectedDetails,
getSignatureParticipations
getSignatureParticipations,
getSignatureActivities
});

SignatureController = connect(
Expand Down
12 changes: 6 additions & 6 deletions src/pages/experiments/group/table/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@ let Table = ({ samples }) => (
{
name: 'Group',
key: 'groupIndex',
width: '60px',
align: 'center',
padded: false,
render: ({ row }) => (
<>
<GroupButton
Expand All @@ -40,13 +37,16 @@ let Table = ({ samples }) => (
Icon={SpadeIcon}
/>
</>
)
),
width: '60px',
align: 'center',
padded: false
},
{
name: 'Name',
key: 'name',
width: 'calc((100% - 60px) * 0.2)',
render: ({ row }) => <SampleLink sample={row} />
render: ({ row }) => <SampleLink sample={row} />,
width: 'calc((100% - 60px) * 0.2)'
},
{
name: 'Description',
Expand Down
82 changes: 40 additions & 42 deletions src/pages/experiments/search/single-table/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,48 +13,46 @@ import './index.css';

// single search result table

let Table = ({ results, highlightedIndex, select }) => {
return (
<TableComponent
data={results}
columns={[
{
render: ({ row }) => (
<Clickable
icon={row.selected ? <RadioedIcon /> : <UnradioedIcon />}
button
onClick={() => select({ accession: row.accession })}
aria-label="Select this experiment"
/>
),
width: '30px',
padded: false
},
{
name: 'Accession',
key: 'accession',
render: ({ row }) => <ExperimentLink experiment={row} />,
width: 'calc((100% - 30px) * 0.25)'
},
{
name: 'Samples',
key: 'samples',
value: ({ cell }) => cell?.length,
render: ({ cell }) => cell?.length,
width: 'calc((100% - 30px) * 0.15)',
align: 'center'
},
{
name: 'Name',
key: 'name',
width: 'calc((100% - 30px) * 0.6)'
}
]}
highlightedIndex={highlightedIndex}
sortable={false}
/>
);
};
let Table = ({ results, highlightedIndex, select }) => (
<TableComponent
data={results}
columns={[
{
render: ({ row }) => (
<Clickable
icon={row.selected ? <RadioedIcon /> : <UnradioedIcon />}
button
onClick={() => select({ accession: row.accession })}
aria-label="Select this experiment"
/>
),
width: '30px',
padded: false
},
{
name: 'Accession',
key: 'accession',
render: ({ row }) => <ExperimentLink experiment={row} />,
width: 'calc((100% - 30px) * 0.25)'
},
{
name: 'Samples',
key: 'samples',
value: ({ cell }) => cell?.length,
render: ({ cell }) => cell?.length,
width: 'calc((100% - 30px) * 0.15)',
align: 'center'
},
{
name: 'Name',
key: 'name',
width: 'calc((100% - 30px) * 0.6)'
}
]}
highlightedIndex={highlightedIndex}
sortable={false}
/>
);

const mapDispatchToProps = (dispatch) => ({
select: (...args) => dispatch(selectExperiment(...args))
Expand Down
Loading

0 comments on commit 8f68997

Please sign in to comment.