Skip to content

Commit

Permalink
cross-study dot plot shows one plot per gene; add the dot plot to sin…
Browse files Browse the repository at this point in the history
…gle study expression analysis
  • Loading branch information
carsten-jahn committed Jan 26, 2023
1 parent 8817507 commit 1b97a12
Show file tree
Hide file tree
Showing 8 changed files with 317 additions and 276 deletions.
21 changes: 19 additions & 2 deletions client/src/atoms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import {
AllGenesDocument,
AllGenesQuery,
AllGenesQueryVariables,
CellOAnnotationGroupIdDocument,
CellOAnnotationGroupIdQuery,
CellOAnnotationGroupIdQueryVariables,
OmicsGeneFragment,
StudyBasicsDocument,
StudyBasicsFragment,
Expand Down Expand Up @@ -35,12 +38,12 @@ export const userGenesState = atom<Omics[]>({
default: []
})

export const celltypeDiscoveryGenesState = atom<(Omics|null)[]>({
export const celltypeDiscoveryGenesState = atom<(Omics | null)[]>({
key: "celltypeDiscoveryGenesState",
default: [null, null]
})

export const celltypeDiscoveryCoexpressionSamplesState = atom<(number[]|null)[]>({
export const celltypeDiscoveryCoexpressionSamplesState = atom<(number[] | null)[]>({
key: "celltypeDiscoveryCoexpressionSamplesState",
default: [null]
})
Expand Down Expand Up @@ -191,3 +194,17 @@ export const allGenesState = selector<Map<number, OmicsGeneFragment> | undefined
}
}
});


export const cellOAnnotationGroupIdState = selector<number | undefined>({
key: "cellOAnnotationGroupIdState",
get: async ({get}) => {
const annotationGroupIdData = await apolloClient.query<CellOAnnotationGroupIdQuery, CellOAnnotationGroupIdQueryVariables>({
query: CellOAnnotationGroupIdDocument,
fetchPolicy: 'no-cache'
});
if (annotationGroupIdData?.data) {
return annotationGroupIdData.data.annotationGroupsList[0].annotationGroupId;
}
}
});
68 changes: 68 additions & 0 deletions client/src/components/ExpressionDotPlot/ExpressionDotPlot.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import React, {useEffect, useMemo, useState} from 'react';
import {VegaLite, View, VisualizationSpec} from "react-vega";
import {DotPlotElementFragment} from "../../generated/types";
import {ScenegraphEvent} from "vega";


function createSpec(annotationTitle: string, xAxis: "studyName" | "displaySymbol") {
return {
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {"name": "table"},
"mark": {"type": "point", "filled": true},
"encoding": {
"y": {
"field": "annotationDisplayValue",
"type": "ordinal",
"title": annotationTitle
},
"x": xAxis === "studyName" ? {
"field": "studyName", "type": "nominal", "title": "Study",
} : {
"field": "displaySymbol", "type": "nominal", "title": "Gene",
},
"size": {
"field": "exprCellsFraction",
"type": "quantitative",
"title": "Expr. fraction"
},
"color": {
"field": "q3",
"type": "quantitative",
"scale": {"scheme": "viridis", reverse: true}
}

}
} as VisualizationSpec;
}

export function ExpressionDotPlot({
data,
annotationTitle,
xAxis,
onClick
}:
{
data: DotPlotElementFragment[],
annotationTitle: string,
xAxis: "studyName" | "displaySymbol",
onClick?: (dotPlotElement: DotPlotElementFragment, event: ScenegraphEvent) => void
}) {
const spec = useMemo(() => createSpec(annotationTitle, xAxis), [annotationTitle, xAxis]);

const setUpSelectionListener = (view: View) => {
view.addEventListener("click", (event, item) => {
if (item && onClick) {
const dotPlotElement = item.datum as DotPlotElementFragment;
onClick(dotPlotElement, event);
}
});
};

return <VegaLite
spec={spec}
onNewView={(view) => setUpSelectionListener(view)}
data={{
"table": data
}}/>
}

Loading

0 comments on commit 1b97a12

Please sign in to comment.