From 9f259efab8d7097c87263c42f5f02ff63cf8932e Mon Sep 17 00:00:00 2001 From: Jonathan Fisher <49597360+jpfisher72@users.noreply.github.com> Date: Wed, 1 May 2024 22:20:45 -0400 Subject: [PATCH] Further fixes (#16) * Small fixes * Add proper theme support * Final changes to UpSet Generator * Update search components * misc * About Page * UMAP * fix build * fix build --- immuscreen/package.json | 2 + immuscreen/src/app/about/page.tsx | 15 +- immuscreen/src/app/celllineage/UpSetPlot.tsx | 4 +- immuscreen/src/app/celllineage/page.tsx | 72 ++- immuscreen/src/app/gene/page.tsx | 10 +- immuscreen/src/app/icres/atacbarplot.tsx | 21 +- immuscreen/src/app/icres/page.tsx | 13 +- immuscreen/src/app/layout.tsx | 24 +- immuscreen/src/app/page.tsx | 8 +- immuscreen/src/app/phenotype/page.tsx | 4 + immuscreen/src/app/snp/page.tsx | 2 +- .../src/common/components/cellTypeTree.tsx | 20 +- .../mainsearch/CcreAutocomplete.tsx | 84 +-- .../mainsearch/CelltypeAutocomplete.tsx | 136 ----- .../mainsearch/GeneAutocomplete.tsx | 218 ++++---- .../components/mainsearch/SnpAutocomplete.tsx | 200 +++---- immuscreen/src/common/components/umapplot.tsx | 527 +++++++++--------- .../src/common/gbview/defaulttracks.tsx | 15 +- .../src/common/gbview/genomebrowserview.tsx | 4 +- immuscreen/src/common/lib/themes.ts | 3 +- 20 files changed, 652 insertions(+), 730 deletions(-) delete mode 100644 immuscreen/src/common/components/mainsearch/CelltypeAutocomplete.tsx diff --git a/immuscreen/package.json b/immuscreen/package.json index 08a8d77..e4a4488 100644 --- a/immuscreen/package.json +++ b/immuscreen/package.json @@ -37,11 +37,13 @@ "dependencies": { "@apollo/client": "alpha", "@apollo/experimental-nextjs-app-support": "^0.4.1", + "@emotion/cache": "^11.11.0", "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", "@mui/icons-material": "^5.14.3", "@mui/lab": "^5.0.0-alpha.169", "@mui/material": "^5.14.2", + "@mui/material-nextjs": "^5.15.11", "@mui/styles": "^5.14.5", "@types/node": "^20.4.9", "@types/react": "^18.2.19", diff --git a/immuscreen/src/app/about/page.tsx b/immuscreen/src/app/about/page.tsx index 31e6f1c..7f1c1e8 100644 --- a/immuscreen/src/app/about/page.tsx +++ b/immuscreen/src/app/about/page.tsx @@ -4,18 +4,17 @@ import { Typography } from "@mui/material" import Grid2 from "@mui/material/Unstable_Grid2/Grid2" - - -//Need better text styling - export default function About() { return (
- - About igSCREEN - Search immune Candidate cis-Regulatory Elements by ENCODE - + + About igSCREEN + Search immune Candidate cis-Regulatory Elements by ENCODE + igSCREEN is a comprehensive catalog of multi-omic knowledge about human immune cells. It was designed and built by Dr. Zhiping Weng’s and Dr. Jill Moore’s labs at UMass Chan Medical School. + For questions or comments please contact us at Zhiping.Weng@umassmed.edu and Jill.Moore@umassmed.edu + This work is supported by U01AI173584. +
) diff --git a/immuscreen/src/app/celllineage/UpSetPlot.tsx b/immuscreen/src/app/celllineage/UpSetPlot.tsx index 4ae600f..88a27eb 100644 --- a/immuscreen/src/app/celllineage/UpSetPlot.tsx +++ b/immuscreen/src/app/celllineage/UpSetPlot.tsx @@ -205,7 +205,7 @@ export default function UpSetPlot({ width, height, data, handleDownload, referen {d.name.length > 12 ? d.name.substring(0, 9).replaceAll('_', ' ') + '...' : d.name.replaceAll('_', ' ')} {/* this expands clickable area for download */} - + ); @@ -262,7 +262,7 @@ export default function UpSetPlot({ width, height, data, handleDownload, referen /> {/* this expands clickable area for download */} - + {Array.from(d.name).map((char, index) => ( vals[0]).flat().join(',')})${cellGroupings.exclude.length > 0 ? `Except(${cellGroupings.exclude.map(vals => vals[0]).flat().join(',')})` : ''}` : downloadKey}.bed` + a.download = `${(downloadKey[0] === '0' || downloadKey[0] === '1') ? `Intersect_${cellGroupings.intersect.map(vals => vals[0]).flat().join('_')}_${cellGroupings.exclude.length > 0 ? `Except_${cellGroupings.exclude.map(vals => vals[0]).flat().join('_')}` : ''}` : downloadKey}.bed` a.click(); URL.revokeObjectURL(blobUrl); }) @@ -450,6 +450,7 @@ export default function UpSet() { const Checkboxes = () => <> + Immune cCRE classes to Include: const HeaderAbout = () => - <> - UpSet Generator - - Select Up to 6 cells to generate an UpSet plot. For stimulable cells, hold Option/Command (MacOS) or Alt/Windows (Windows) and click to stimulate cell. By default, all cells are unstimulated. Stimulable cells can be unstimulated, stimulated, or both (counts as two selections). Stimulating a cell does not automatically select it. The more cells types that are selected, the longer it will take to generate. Click any bar/count in UpSet plot to download set (.BED) - - + + UpSet Generator + Generate UpSet plots of immune cCREs active in selected cell types. + How to Use: + + + + + + + Click to select up to 6 cells. + + + + + + + + For stimulable cells, hold Option/Command (MacOS) or Alt/Windows (Windows) and click to stimulate cell. + + + + + + + + Stimulating a cell does not automatically select it. + + + + + + + + By default, all cells are unstimulated. Stimulable cells can be unstimulated, stimulated, or both (counts as two selections). + + + + + + + + The more cells types that are selected, the longer it will take to generate. + + + + + + + + Click any bar/count in UpSet plot to download set (.BED) + + + + const GenerateUpsetButton = () => - : } sx={{ textTransform: "none", m: 1 }} variant="contained" onClick={handleGenerateUpSet}> + : } sx={{ textTransform: "none", mt: 2, mb: 2, mr: 2 }} variant="contained" onClick={handleGenerateUpSet}> {loading_count ? "Generating" : noneSelected ? "Select Cells to Generate UpSet" : "Generate UpSet"} @@ -495,7 +545,7 @@ export default function UpSet() { return ( <> - + {/* Display header, checkboxes and UpSet on left on big screen */} diff --git a/immuscreen/src/app/gene/page.tsx b/immuscreen/src/app/gene/page.tsx index ec7f579..10534b2 100644 --- a/immuscreen/src/app/gene/page.tsx +++ b/immuscreen/src/app/gene/page.tsx @@ -77,7 +77,7 @@ const Gene = () => { return ( searchParams.get('gene') ? // Gene Selected View - + {searchParams.get("gene") && Gene Details: {searchParams.get("gene")}} @@ -86,7 +86,7 @@ const Gene = () => { - + @@ -190,8 +190,8 @@ const Gene = () => { onChange={handleColorSchemeChange} aria-label="Platform" > - Gene Expression - CellType Cluster + Gene Expression + Cell Type Cluster

@@ -207,7 +207,7 @@ const Gene = () => {


- {} + {}
) diff --git a/immuscreen/src/app/icres/atacbarplot.tsx b/immuscreen/src/app/icres/atacbarplot.tsx index 01131fb..1988361 100644 --- a/immuscreen/src/app/icres/atacbarplot.tsx +++ b/immuscreen/src/app/icres/atacbarplot.tsx @@ -35,6 +35,7 @@ const tooltipStyles = { const legendGlyphSize = 15; +//This should eventually be redone. It feels wrong to style the tooltip this way const CellTypesLegends = ({ title, plottitle, children }: { title: string; plottitle?: string; children: React.ReactNode }) => { return (
@@ -73,8 +74,6 @@ const CellTypesLegends = ({ title, plottitle, children }: { title: string; plott ); } - - export const AtacBarPlot: React.FC<{ plottitle?: string, byct?: boolean, study: string, barplotdata: { color: string, ct_description?: string, celltype: string, class: string, subclass: string, description: string, order: number, value: number, name: string, study: string, group: string, grouping: string, stimulation: string }[] }> = (props) => { const width = 1000 const height = 700 @@ -139,7 +138,7 @@ export const AtacBarPlot: React.FC<{ plottitle?: string, byct?: boolean, study: }); return ( -
+
- - label}> + + {(labels) => ( -
+
{labels.map((label, i) => { return ( - +

{label.text}

@@ -296,15 +295,13 @@ export const AtacBarPlot: React.FC<{ plottitle?: string, byct?: boolean, study: )} + {/* Why is the styling being done like this, not readable. Why is there also styling above in CellTypeLegends? */} -
- ); +
+ ); +} + +//This should eventually be redone. It feels wrong to style the tooltip this way +const CellTypesLegends = ({ title, plottitle, children }: { title: string; plottitle?: string; children: React.ReactNode }) => { + return ( +
+
{title}
+ {children} + +
+ ); } + +/** + * @todo this file needs to be typed. Also the manual css injection with -
- - - ) -} + const linearScale = scaleLinear({ + domain: [minValue, maxValue], + range: ["#ffcd00", "#ff0000"], + }); + let uniqcelltypes = [...new Set([...props.data].sort((a, b) => { + if (!experimentInfo[a.name]?.order) console.log(a.name) //some experiments returned in gene expression umap are not in experiment list? + return experimentInfo[a.name]?.order - experimentInfo[b.name]?.order + }).map(c => getCellDisplayName(c.celltype as any)))] + let ordinalColorScale = uniqcelltypes && scaleOrdinal({ + domain: uniqcelltypes, + //Duplicates? + range: uniqcelltypes.map((c) => getCellColor(c as CellName)), + }) + const legendGlyphSize = 15; + return ( +
+ + + + {"\u25EF unstimulated, \u25B3 stimulated "} + + + {props.data.map(point => { + return ( + + {point.stimulation === 'S' ? + handleHover(event, point)} + onMouseLeave={(event) => handleLeaveHover(event, point)} + fill={(props.colorScheme === 'geneexp' || props.colorScheme === 'ZScore') ? linearScale(point.value) : getCellColor(point.celltype)} + stroke={tooltipData && tooltipData.celltype === point.celltype ? 'black' : ''} + /> : + handleHover(event, point)} + onMouseLeave={(event) => handleLeaveHover(event, point)} + //fill= {`${linearScale(point.value)}`} + fill={(props.colorScheme === 'geneexp' || props.colorScheme === 'ZScore') ? linearScale(point.value) : getCellColor(point.celltype)} + stroke={tooltipData && tooltipData.celltype === point.celltype ? 'black' : ''} + /> + } + ) + })} + + + {tooltipOpen && tooltipData && ( + +
+

Celltype: {getCellDisplayName(tooltipData.celltype as CellQueryValue, true)}

+
+
+

Name: {tooltipData.name}

+
+
+

Class {tooltipData.class}

+
+
+

Value {tooltipData.value.toFixed(2)}

+
+
+ )} +
+ {(props.colorScheme === 'geneexp' || props.colorScheme === 'ZScore') ? + + (+d).toFixed(2)} + > + {(labels) => + labels.sort((a, b) => b.index - a.index).map((label, i) => ( + { + //if (events) alert(`clicked: ${JSON.stringify(label)}`); + }} + > + + + + + {label.text} + + + )) + } + + + : + + + {(labels) => ( +
+ {labels.map((label, i) => { + return ( + + + + + +

+ {label.text} +

+
+
+ ) + })} +
+ )} +
+
+ } + +
+
+ ) +} \ No newline at end of file diff --git a/immuscreen/src/common/gbview/defaulttracks.tsx b/immuscreen/src/common/gbview/defaulttracks.tsx index f88d3e4..c38e8a9 100644 --- a/immuscreen/src/common/gbview/defaulttracks.tsx +++ b/immuscreen/src/common/gbview/defaulttracks.tsx @@ -6,6 +6,7 @@ import { DenseBigBed, EmptyTrack, FullBigWig } from "umms-gb" import { client } from "../utils" import { BIG_QUERY } from "./queries" import { GenomicRange, BigQueryResponse, BigResponseData } from "./types" +import { Tooltip } from "@mui/material" type DefaultTracksProps = { @@ -75,7 +76,17 @@ export const TitledTrack: React.FC<{ svgRef={svgRef} onMouseOver={(x) => oncCREMousedOver && x.name && oncCREMousedOver(cCRECoordinateMap.get(x.name))} onMouseOut={oncCREMousedOut} - + tooltipContent={(rect) => { + return ( +
+ + + {rect.name} + + +
+ ) + }} /> ) : ( = (props) => { const [cTracks, setTracks] = useState<[string, string][]>( [ - ["All iCREs", "https://downloads.wenglab.org/Calderon-Corces_activeCREs_iSCREEN_withcolors.bigBed"], + ["All immune cCREs", "https://downloads.wenglab.org/Calderon-Corces_activeCREs_iSCREEN_withcolors.bigBed"], ] ) const height = useMemo(() => cTracks.length * 80, [cTracks]) diff --git a/immuscreen/src/common/gbview/genomebrowserview.tsx b/immuscreen/src/common/gbview/genomebrowserview.tsx index 19c8fb7..c10d4c8 100644 --- a/immuscreen/src/common/gbview/genomebrowserview.tsx +++ b/immuscreen/src/common/gbview/genomebrowserview.tsx @@ -147,11 +147,11 @@ export const GenomeBrowserView: React.FC = (props: Genom {props.accession && } - {props.gene && = 500000 ? true : false} - />} + />