diff --git a/immuscreen/package.json b/immuscreen/package.json index 08a8d77..5cd5128 100644 --- a/immuscreen/package.json +++ b/immuscreen/package.json @@ -35,57 +35,59 @@ } }, "dependencies": { - "@apollo/client": "alpha", - "@apollo/experimental-nextjs-app-support": "^0.4.1", - "@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/styles": "^5.14.5", - "@types/node": "^20.4.9", - "@types/react": "^18.2.19", - "@types/react-dom": "18.2.7", - "@visx/axis": "^3.8.0", - "@visx/event": "latest", - "@visx/glyph": "latest", + "@apollo/client": "^3.10.5", + "@apollo/experimental-nextjs-app-support": "^0.11.2", + "@emotion/cache": "^11.11.0", + "@emotion/react": "^11.11.4", + "@emotion/styled": "^11.11.5", + "@mui/icons-material": "^5.15.20", + "@mui/lab": "^5.0.0-alpha.170", + "@mui/material": "^5.15.20", + "@mui/material-nextjs": "^5.15.11", + "@mui/styles": "^5.15.20", + "@types/node": "^20.14.5", + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "@visx/axis": "^3.10.1", + "@visx/event": "^3.3.0", + "@visx/glyph": "^3.3.0", "@visx/gradient": "^3.3.0", "@visx/grid": "^3.5.0", "@visx/group": "^3.3.0", "@visx/hierarchy": "^3.3.0", - "@visx/legend": "latest", - "@visx/mock-data": "latest", - "@visx/responsive": "^3.3.0", - "@visx/scale": "latest", + "@visx/legend": "^3.10.3", + "@visx/mock-data": "^3.3.0", + "@visx/responsive": "^3.10.2", + "@visx/scale": "^3.5.0", "@visx/shape": "^3.5.0", "@visx/text": "^3.3.0", "@visx/tooltip": "^3.3.0", - "@visx/vendor": "latest", - "@weng-lab/psychscreen-ui-components": "^0.8.6", + "@visx/vendor": "^3.5.0", + "@weng-lab/psychscreen-ui-components": "^0.8.8", "@weng-lab/ts-ztable": "^4.0.1", - "autoprefixer": "10.4.15", - "bpnet-ui": "^0.2.9", - "eslint": "8.47.0", - "eslint-config-next": "13.4.19", - "graphql": "^16.7.1", + "autoprefixer": "^10.4.19", + "bpnet-ui": "^0.3.8", + "eslint": "^9.5.0", + "eslint-config-next": "^14.2.4", + "graphql": "^16.8.2", "jubilant-carnival": "^0.6.0", "logojs-react": "^2.1.1", - "next": "14.1.0", + "next": "^14.2.4", "normalize.css": "^8.0.1", "only": "^0.0.2", - "postcss": "8.4.27", + "postcss": "^8.4.38", "queryz": "^0.0.3", - "react": "18.2.0", - "react-dom": "18.2.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", "react-dropzone": "^14.2.3", - "semantic-ui-react": "latest", - "server": "^1.0.38", - "sharp": "^0.32.4", - "tailwindcss": "3.3.3", - "typescript": "5.1.6", - "umap-js": "^1.3.3", - "umms-gb": "^3.10.0", - "uuid": "^9.0.1" + "semantic-ui-react": "^2.1.5", + "server": "^1.0.39", + "sharp": "^0.33.4", + "tailwindcss": "^3.4.4", + "typescript": "^5.4.5", + "umap-js": "^1.4.0", + "umms-gb": "^3.9.14", + "uuid": "^10.0.0" }, "devDependencies": { "file-loader": "^6.2.0", @@ -109,5 +111,6 @@ "not dead", "not ie <= 11", "not op_mini all" - ] + ], + "packageManager": "yarn@3.5.0+sha512.2dc70be5fce9f66756d25b00a888f3ca66f86b502b76750e72ba54cec89da767b938c54124595e26f868825688e0fe3552c26c76a330673343057acadd5cfcf2" } diff --git a/immuscreen/public/assets/disease-trait.png b/immuscreen/public/assets/disease-trait.png new file mode 100644 index 0000000..1c23a13 Binary files /dev/null and b/immuscreen/public/assets/disease-trait.png differ diff --git a/immuscreen/public/assets/gene-bcre.png b/immuscreen/public/assets/gene-bcre.png new file mode 100644 index 0000000..1fca4f7 Binary files /dev/null and b/immuscreen/public/assets/gene-bcre.png differ diff --git a/immuscreen/public/assets/phenotype.png b/immuscreen/public/assets/phenotype.png new file mode 100644 index 0000000..80482c3 Binary files /dev/null and b/immuscreen/public/assets/phenotype.png differ diff --git a/immuscreen/public/assets/single-cell.png b/immuscreen/public/assets/single-cell.png new file mode 100644 index 0000000..47db688 Binary files /dev/null and b/immuscreen/public/assets/single-cell.png differ diff --git a/immuscreen/public/assets/snp-qtl.png b/immuscreen/public/assets/snp-qtl.png new file mode 100644 index 0000000..a60902b Binary files /dev/null and b/immuscreen/public/assets/snp-qtl.png differ diff --git a/immuscreen/public/assets/upset.png b/immuscreen/public/assets/upset.png new file mode 100644 index 0000000..63f9f13 Binary files /dev/null and b/immuscreen/public/assets/upset.png differ diff --git a/immuscreen/public/cellTypes/Erythrocyte.png b/immuscreen/public/cellTypes/Erythroblast.png similarity index 100% rename from immuscreen/public/cellTypes/Erythrocyte.png rename to immuscreen/public/cellTypes/Erythroblast.png diff --git a/immuscreen/public/igSCREEN_red.png b/immuscreen/public/igSCREEN_red.png new file mode 100644 index 0000000..a16b6b5 Binary files /dev/null and b/immuscreen/public/igSCREEN_red.png differ diff --git a/immuscreen/public/igSCREEN_red_light.png b/immuscreen/public/igSCREEN_red_light.png new file mode 100644 index 0000000..7c8cbab Binary files /dev/null and b/immuscreen/public/igSCREEN_red_light.png differ diff --git a/immuscreen/src/app/about/page.tsx b/immuscreen/src/app/about/page.tsx index 31e6f1c..5de43f9 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 + 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..0a71ac2 100644 --- a/immuscreen/src/app/celllineage/UpSetPlot.tsx +++ b/immuscreen/src/app/celllineage/UpSetPlot.tsx @@ -153,7 +153,7 @@ export default function UpSetPlot({ width, height, data, handleDownload, referen } {/* The set size plot */} - + {setSizeData.map((d, i) => { const barWidth = setSizePlotBarsWidth - (setSizePlotWidthScale(d.count) ?? 0); @@ -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 */} - + ); @@ -213,7 +213,7 @@ export default function UpSetPlot({ width, height, data, handleDownload, referen {/* The intersection plot and circles */} - + {intersectionData.map((d) => { const barWidth = intersectionPlotWidthScale.bandwidth(); @@ -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) - - + + Immune cCRE Activity by Cell Type + Compare immune cCRE activity between selected immune 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/celllineage/types.ts b/immuscreen/src/app/celllineage/types.ts index 17ebfc4..adeee24 100644 --- a/immuscreen/src/app/celllineage/types.ts +++ b/immuscreen/src/app/celllineage/types.ts @@ -68,7 +68,7 @@ export type CellDisplayName = | "Multipotent progenitor" | "Common myeloid progenitor" | "Megakaryocyte-erythroid progenitor" - | "Erythrocyte" + | "Erythroblast" | "Granulocyte-monocyte progenitors" | "Lymphocyte-primed multipotent progenitor" | "Common lymphoid progenitor" diff --git a/immuscreen/src/app/gene/page.tsx b/immuscreen/src/app/gene/page.tsx index 2e0d17e..7eb0b03 100644 --- a/immuscreen/src/app/gene/page.tsx +++ b/immuscreen/src/app/gene/page.tsx @@ -1,7 +1,7 @@ "use client" -import React, { useState} from "react" +import React, { useState } from "react" import { Tabs, Tab, Typography, colors } from "@mui/material" -import { client } from "../../common/utils" +import { client, toScientificNotation } from "../../common/utils" import { StyledTab } from "../../common/utils" import Grid2 from "@mui/material/Unstable_Grid2/Grid2" import { useQuery } from "@apollo/client" @@ -15,10 +15,19 @@ import ToggleButton from '@mui/material/ToggleButton'; import ToggleButtonGroup from '@mui/material/ToggleButtonGroup'; -const Gene = () =>{ +const Gene = () => { const searchParams: ReadonlyURLSearchParams = useSearchParams()! + const [value, setValue] = useState(0) - + const [colorScheme, setcolorScheme] = useState('geneexp'); + + const handleColorSchemeChange = ( + event: React.MouseEvent, + newScheme: string, + ) => { + setcolorScheme(newScheme); + }; + const handleChange = (_, newValue: number) => { setValue(newValue) } @@ -65,172 +74,148 @@ const Gene = () =>{ client, }) - - const [colorScheme, setcolorScheme] = useState('genexp'); - const handleColorSchemeChange = ( - event: React.MouseEvent, - newScheme: string, - ) => { - setcolorScheme(newScheme); - }; - - return !searchParams.get('gene') ?
- - - - Gene Portal - -
- -
-
- { } + return ( + searchParams.get('gene') ? + // Gene Selected View + + + + {searchParams.get("gene") && Gene Details: {searchParams.get("gene")}} + + + + + + + + - - - -
: ( -
- - - - {searchParams.get("gene") && Gene Details: {searchParams.get("gene")}} - - - - - - - - + {value === 0 && + + + + } + {value === 1 && !loading && !soskicLoading && !yazarLoading && + + + row.variant_id || "", + }, + { + header: "Nominal P", + HeaderRender: () => Nominal P, + value: (row) => row.pval_nominal && toScientificNotation(row.pval_nominal, 2) || 0, + }, + { + header: "Beta P", + HeaderRender: () => Beta P, + value: (row) => row.pval_beta && toScientificNotation(row.pval_beta, 2) || 0, + } + ]} + tableTitle={`GTEX whole-blood eQTLs for ${searchParams.get('gene')}:`} + rows={data?.icreeQTLQuery || []} + itemsPerPage={10} + /> - - {value===1 && !loading && !soskicLoading && !yazarLoading && - - - row.variant_id || "", - - }, - { - header: "Nominal P-Value", - value: (row) => row.pval_nominal && row.pval_nominal.toExponential(2) || 0, - }, - { - header: "Beta P-Value", - value: (row) => row.pval_beta && row.pval_beta.toExponential(2) || 0, - } - - ]} - tableTitle={`GTEX whole-blood eQTLs for ${searchParams.get('gene')}:`} - rows={data?.icreeQTLQuery || []} - - - itemsPerPage={10} - /> - - - - row.rsid || "", - - }, - - { - header: "P-Value", - value: (row) => row.pvalue && row.pvalue.toExponential(2) || 0 , - }, - { - header: "Q-Value", - value: (row) => row.qvalue && row.qvalue.toExponential(2) || 0, - }, - { - header: "Celltype", - value: (row) => row.celltype || "", - - } - ]} - tableTitle={`Yazar.Powell eQTLs for ${searchParams.get('gene')}:`} - rows={(yazarData.icreeQTLQuery) || []} - - sortColumn={3} - itemsPerPage={10} - /> - - - - row.variant_id || "", - - }, - { - header: "Nominal P-Value", - value: (row) => row.pval_nominal && row.pval_nominal.toExponential(2) || 0, - }, - { - header: "Beta P-Value", - value: (row) => row.pval_beta && row.pval_beta.toExponential(2) || 0, - }, - { - header: "Celltype", - value: (row) => row.celltype || "", - - } - ]} - tableTitle={`Soskic.Trynka eQTLs have been identified for ${searchParams.get('gene')}:`} - rows={(soskicData.icreeQTLQuery) || []} - - sortColumn={3} - itemsPerPage={10} - /> - - - - - - } - {value===0 && } - {value===2 && rnumapdata && !rnaumaploading && rnumapdata.calderonRnaUmapQuery.length>0 && - - Color Scheme: -

- + row.rsid || "", + }, + { + header: "P", + HeaderRender: () => P, + value: (row) => row.pvalue && toScientificNotation(row.pvalue, 2) || 0, + }, + { + header: "Q", + HeaderRender: () => Q, + value: (row) => row.qvalue && toScientificNotation(row.qvalue, 2) || 0, + }, + { + header: "Celltype", + value: (row) => row.celltype || "", + } + ]} + tableTitle={`Yazar.Powell eQTLs for ${searchParams.get('gene')}:`} + rows={(yazarData.icreeQTLQuery) || []} + sortColumn={3} + itemsPerPage={10} + /> +
+ + row.variant_id || "", + }, + { + header: "Nominal P", + HeaderRender: () => Nominal P, + value: (row) => row.pval_nominal && toScientificNotation(row.pval_nominal, 2) || 0, + }, + { + header: "Beta P", + HeaderRender: () => Beta P, + value: (row) => row.pval_beta && toScientificNotation(row.pval_beta, 2) || 0, + }, + { + header: "Celltype", + value: (row) => row.celltype || "", + } + ]} + tableTitle={`Soskic.Trynka eQTLs for ${searchParams.get('gene')}:`} + rows={(soskicData.icreeQTLQuery) || []} + sortColumn={3} + itemsPerPage={10} + /> + +
+ } + {value === 2 && rnumapdata && !rnaumaploading && rnumapdata.calderonRnaUmapQuery.length > 0 && + + Color Scheme: +

+ - Gene Expression - CellType Cluster + > + Gene Expression + Cell Type Cluster -
-
- {return {...d, value: Math.log(d.value+0.01)} })} plottitle={"log10 TPM"}/> -
- } +
+
+ { return { ...d, value: Math.log(d.value + 0.01) } })} plottitle={"log10 TPM"} /> +
+ } +
+ : + //Gene Not Selected View + + + Gene Portal +
+
+
+ {}
- - -
+
) } diff --git a/immuscreen/src/app/globals.css b/immuscreen/src/app/globals.css index 53fea21..d6cdcab 100644 --- a/immuscreen/src/app/globals.css +++ b/immuscreen/src/app/globals.css @@ -397,7 +397,6 @@ template { /* Limit the amount of space the content can take up so it doesn't run into edge */ #body-wrapper { - max-width: 95%; margin-left: auto; margin-right: auto; } diff --git a/immuscreen/src/app/icres/atacbarplot.tsx b/immuscreen/src/app/icres/atacbarplot.tsx index 4bdefe3..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,10 +74,8 @@ 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 = 800 + const width = 1000 const height = 700 const margin = { top: 40, right: 8, bottom: 40, left: 60 }; const xMax = width - margin.left - margin.right; @@ -139,7 +138,7 @@ export const AtacBarPlot: React.FC<{ plottitle?: string, byct?: boolean, study: }); return ( -
+
- + {yScale.domain()[1] > 1.64 && + + } {/* Axis Break */} @@ -261,10 +270,10 @@ export const AtacBarPlot: React.FC<{ plottitle?: string, byct?: boolean, study:
- - label}> + + {(labels) => ( -
+
{labels.map((label, i) => { return ( - +

{label.text}

@@ -286,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].sort((a,b) => a.value - b.value).map(point => { + return ( + + {point.stimulation === 'S' ? + handleHover(event, point)} + onMouseLeave={(event) => handleLeaveHover(event, point)} + fill={(props.colorScheme === 'geneexp' || props.colorScheme === 'ZScore') ? point.value > 1.64 ? 'red' : 'yellow' : 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') ? point.value > 1.64 ? 'red' : 'yellow' : 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/consts.ts b/immuscreen/src/common/consts.ts index 09d9c80..6896044 100644 --- a/immuscreen/src/common/consts.ts +++ b/immuscreen/src/common/consts.ts @@ -1,8 +1,4 @@ -/** - * @todo the cell info in this file and in celllineage/utils.ts need to be combined - */ - -import { CellDisplayName, CellName, CellTypeStaticInfo } from "../app/celllineage/types" +import { CellName, CellTypeStaticInfo } from "../app/celllineage/types" export const cellTypeStaticInfo: { [key in CellName]: CellTypeStaticInfo } = { Monocytes: { @@ -417,15 +413,15 @@ export const cellTypeStaticInfo: { [key in CellName]: CellTypeStaticInfo } = { }, Ery: { id: "Ery", - displayName: "Erythrocyte", - unstimImagePath: '/cellTypes/Erythrocyte.png', + displayName: "Erythroblast", + unstimImagePath: '/cellTypes/Erythroblast.png', stimulable: false, queryValues: { unstimulated: { Corces: "Ery" } }, unstimCount: 56267, color: "#684fda", - treeDisplayName: "Erythrocyte" + treeDisplayName: "Erythroblast" }, GMP: { id: "GMP", @@ -557,14 +553,14 @@ export const experimentInfo: { [key: string]: {order: number, description: strin '6792-MEP-SRX1427809': { order: 29, description: 'Megakaryocyte Erythroid Progenitor in donor 6792', displayName: 'Megakaryocyte Erythroid Progenitor', group: 'Progenitors', study: 'Corces et al', pmid: '27526324' }, '7256-MEP-SRX1427863': { order: 30, description: 'Megakaryocyte Erythroid Progenitor in donor 7256', displayName: 'Megakaryocyte Erythroid Progenitor', group: 'Progenitors', study: 'Corces et al', pmid: '27526324' }, '7256-MEP-SRX1427864': { order: 31, description: 'Megakaryocyte Erythroid Progenitor in donor 7256', displayName: 'Megakaryocyte Erythroid Progenitor', group: 'Progenitors', study: 'Corces et al', pmid: '27526324' }, - '2596-Ery-SRX1427825': { order: 32, description: 'Erythrocyte in donor 2596', displayName: 'Erythrocyte', group: 'Myeloid', study: 'Corces et al', pmid: '27526324' }, - '2596-Ery-SRX1427826': { order: 33, description: 'Erythrocyte in donor 2596', displayName: 'Erythrocyte', group: 'Myeloid', study: 'Corces et al', pmid: '27526324' }, - '2596-Ery-SRX1427827': { order: 34, description: 'Erythrocyte in donor 2596', displayName: 'Erythrocyte', group: 'Myeloid', study: 'Corces et al', pmid: '27526324' }, - '5483-Ery-SRX1427846': { order: 35, description: 'Erythrocyte in donor 5483', displayName: 'Erythrocyte', group: 'Myeloid', study: 'Corces et al', pmid: '27526324' }, - '5483-Ery-SRX1427847': { order: 36, description: 'Erythrocyte in donor 5483', displayName: 'Erythrocyte', group: 'Myeloid', study: 'Corces et al', pmid: '27526324' }, - '5483-Ery-SRX1427848': { order: 37, description: 'Erythrocyte in donor 5483', displayName: 'Erythrocyte', group: 'Myeloid', study: 'Corces et al', pmid: '27526324' }, - '6926-Ery-SRX1427852': { order: 38, description: 'Erythrocyte in donor 6926', displayName: 'Erythrocyte', group: 'Myeloid', study: 'Corces et al', pmid: '27526324' }, - '6926-Ery-SRX1427853': { order: 39, description: 'Erythrocyte in donor 6926', displayName: 'Erythrocyte', group: 'Myeloid', study: 'Corces et al', pmid: '27526324' }, + '2596-Ery-SRX1427825': { order: 32, description: 'Erythroblast in donor 2596', displayName: 'Erythroblast', group: 'Myeloid', study: 'Corces et al', pmid: '27526324' }, + '2596-Ery-SRX1427826': { order: 33, description: 'Erythroblast in donor 2596', displayName: 'Erythroblast', group: 'Myeloid', study: 'Corces et al', pmid: '27526324' }, + '2596-Ery-SRX1427827': { order: 34, description: 'Erythroblast in donor 2596', displayName: 'Erythroblast', group: 'Myeloid', study: 'Corces et al', pmid: '27526324' }, + '5483-Ery-SRX1427846': { order: 35, description: 'Erythroblast in donor 5483', displayName: 'Erythroblast', group: 'Myeloid', study: 'Corces et al', pmid: '27526324' }, + '5483-Ery-SRX1427847': { order: 36, description: 'Erythroblast in donor 5483', displayName: 'Erythroblast', group: 'Myeloid', study: 'Corces et al', pmid: '27526324' }, + '5483-Ery-SRX1427848': { order: 37, description: 'Erythroblast in donor 5483', displayName: 'Erythroblast', group: 'Myeloid', study: 'Corces et al', pmid: '27526324' }, + '6926-Ery-SRX1427852': { order: 38, description: 'Erythroblast in donor 6926', displayName: 'Erythroblast', group: 'Myeloid', study: 'Corces et al', pmid: '27526324' }, + '6926-Ery-SRX1427853': { order: 39, description: 'Erythroblast in donor 6926', displayName: 'Erythroblast', group: 'Myeloid', study: 'Corces et al', pmid: '27526324' }, '2596-GMP-SRX1427828': { order: 40, description: 'Granulocyte-Monocyte Progenitors in donor 2596', displayName: 'Granulocyte-Monocyte Progenitors', group: 'Progenitors', study: 'Corces et al', pmid: '27526324' }, '4983-GMP-SRX1427794': { order: 41, description: 'Granulocyte-Monocyte Progenitors in donor 4983', displayName: 'Granulocyte-Monocyte Progenitors', group: 'Progenitors', study: 'Corces et al', pmid: '27526324' }, '4983-GMP-SRX1427795': { order: 42, description: 'Granulocyte-Monocyte Progenitors in donor 4983', displayName: 'Granulocyte-Monocyte Progenitors', group: 'Progenitors', study: 'Corces et al', pmid: '27526324' }, diff --git a/immuscreen/src/common/gbview/bulkAtacSelector.tsx b/immuscreen/src/common/gbview/bulkAtacSelector.tsx new file mode 100644 index 0000000..6075db0 --- /dev/null +++ b/immuscreen/src/common/gbview/bulkAtacSelector.tsx @@ -0,0 +1,87 @@ +import { ChangeEvent, useEffect, useMemo, useState } from "react"; +import { CellQueryValue, CellTypeStaticInfo } from "../../app/celllineage/types"; +import { extractQueryValues, getCellDisplayName } from "../../app/celllineage/utils"; +import { cellTypeStaticInfo } from "../consts"; +import { Dialog, DialogTitle, DialogContent, DialogContentText, TextField, DialogActions, Button, FormGroup, FormControlLabel, Checkbox } from "@mui/material"; + +type ModalProps = { + open: boolean + onAccept: (cells: CellQueryValue[]) => void; + onCancel: () => void; + selected: CellQueryValue[]; +} + +const BulkAtacModal: React.FC = (props: ModalProps) => { + const currentlySelected = useMemo(() => { + const x = {} + Object.values(cellTypeStaticInfo).forEach((cellInfo: CellTypeStaticInfo) => { + const queryVals = extractQueryValues(cellInfo, "B") + queryVals.forEach(queryVal => { + x[queryVal] = !!props.selected.find(x => x === queryVal) + }) + }) + return x as { [key in CellQueryValue]: boolean } + }, [cellTypeStaticInfo, props.selected]) + + const [selectedCells, setSelectedCells] = useState<{ [key in CellQueryValue]: boolean }>(currentlySelected) + + //Set back state of selectedCells before closing + const handleCancel = () => { + setSelectedCells(currentlySelected) + props.onCancel() + }; + + const handleChange = (event: React.ChangeEvent) => { + setSelectedCells({ + ...selectedCells, + [event.target.name]: event.target.checked, + }); + }; + + const handleAccept = () => { + props.onAccept([...Object.entries(selectedCells).filter(x => x[1]).map(x => x[0] as CellQueryValue)]) + props.onCancel() + } + + const handleDeselectAll = () => { + setSelectedCells( + Object.fromEntries( + Object.entries(selectedCells).map(x => [x[0], false]) + ) as { [key in CellQueryValue]: boolean } + ) + } + + return ( + + Select Bulk ATAC tracks + + + Select tracks you wish to display: + + + { + Object.entries(selectedCells).map(([queryVal, selected]: [CellQueryValue, boolean], i) => + + } + label={getCellDisplayName(queryVal, true, true) + (["HSC", "CD34_Cord_Blood", "CD34_Bone_Marrow"].find(x => x === queryVal) ? ` (${queryVal})` : '')} + /> + ) + } + + + + + + + + + ) +}; + +export default BulkAtacModal \ No newline at end of file diff --git a/immuscreen/src/common/gbview/bulkatacmodal.tsx b/immuscreen/src/common/gbview/bulkatacmodal.tsx deleted file mode 100644 index 1fb191a..0000000 --- a/immuscreen/src/common/gbview/bulkatacmodal.tsx +++ /dev/null @@ -1,327 +0,0 @@ -import React, { useCallback, useState } from "react"; -import { Modal, Accordion, Box } from "@mui/material"; -import { Typography, Button } from "@weng-lab/psychscreen-ui-components"; -import { - AccordionDetails, - AccordionSummary, - Checkbox, - FormControlLabel, - FormGroup, - Grid, - Paper -} from "@mui/material"; -import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; -import ExpandLessIcon from "@mui/icons-material/ExpandLess"; - -type BulkAtacTrackModalTrackModalProps = { - open?: boolean; - onAccept?: (tracks: [string, string][]) => void; - onCancel?: () => void; - initialSelection: [string, string][]; -}; - -const style = { - position: "absolute" as "absolute", - top: "25%", - left: "50%", - transform: "translate(-50%, -15%)", - width: "50%", - bgcolor: "background.paper", - backgroundColor: "#ffffff", - border: "2px solid #000", - p: 4, - padding: "2em", - borderRadius: "20px", -}; - -const TRACKS = { - - "Bulk Atac Tracks": [ - [ - "Bulk B Stimulated", - "https://downloads.wenglab.org/Bulk_B-S.bigWig", - ], - [ - "Bulk B Untimulated", - "https://downloads.wenglab.org/Bulk_B-U.bigWig", - ], - [ - "CD8pos T Stimulated", - "https://downloads.wenglab.org/CD8pos_T-S.bigWig", - ], - [ - "CD8pos T Unstimulated", - "https://downloads.wenglab.org/CD8pos_T-U.bigWig", - ], - [ - "Central memory CD8pos T Stimulated", - "https://downloads.wenglab.org/Central_memory_CD8pos_T-S.bigWig" - ], - [ - "Central memory CD8pos T Unstimulated", - "https://downloads.wenglab.org/Central_memory_CD8pos_T-U.bigWig" - ],[ - "Effector CD4pos T Stimulated", - "https://downloads.wenglab.org/Effector_CD4pos_T-S.bigWig" - ], - [ - "Effector CD4pos T Unstimulated", - "https://downloads.wenglab.org/Effector_CD4pos_T-U.bigWig" - ], - [ - "Effector memory CD8pos T Stimulated", - "https://downloads.wenglab.org/Effector_memory_CD8pos_T-S.bigWig" - ], - [ - "Effector memory CD8pos T Unstimulated", - "https://downloads.wenglab.org/Effector_memory_CD8pos_T-U.bigWig" - ], - [ - "Follicular T Helper Stimulated", - "https://downloads.wenglab.org/Follicular_T_Helper-S.bigWig" - ], - [ - "Follicular T Helper Unstimulated", - "https://downloads.wenglab.org/Follicular_T_Helper-U.bigWig" - ], - [ - "Gamma delta T Stimulated", - "https://downloads.wenglab.org/Gamma_delta_T-S.bigWig" - ], - [ - "Gamma delta T Unstimulated", - "https://downloads.wenglab.org/Gamma_delta_T-U.bigWig" - ], - [ - "Immature NK Unstimulated", - "https://downloads.wenglab.org/Immature_NK-U.bigWig" - ], - [ - "Mature NK Unstimulated", - "https://downloads.wenglab.org/Mature_NK-U.bigWig" - ], - [ - "Mem B Stimulated", - "https://downloads.wenglab.org/Mem_B-S.bigWig" - ], - [ - "Mem B Unstimulated", - "https://downloads.wenglab.org/Mem_B-U.bigWig" - ], - [ - "Memory Teffs Stimulated", - "https://downloads.wenglab.org/Memory_Teffs-S.bigWig" - ], - [ - "Memory Teffs Unstimulated", - "https://downloads.wenglab.org/Memory_Teffs-U.bigWig" - ], - [ - "Memory Tregs Stimulated", - "https://downloads.wenglab.org/Memory_Tregs-S.bigWig" - ], - [ - "Memory Tregs Unstimulated", - "https://downloads.wenglab.org/Memory_Tregs-U.bigWig" - - ], - [ - "Monocytes Unstimulated", - "https://downloads.wenglab.org/Monocytes-U.bigWig" - ], - [ - "Myeloid DCs Unstimulated", - "https://downloads.wenglab.org/Myeloid_DCs-U.bigWig" - ], - [ - "Naive B Stimulated", - "https://downloads.wenglab.org/Naive_B-S.bigWig" - ], - [ - "Naive B Unstimulated", - "https://downloads.wenglab.org/Naive_B-U.bigWig" - ], - [ - "Naive CD8 T Stimulated", - "https://downloads.wenglab.org/Naive_CD8_T-S.bigWig" - ], - [ - "Naive CD8 T Unstimulated", - - "https://downloads.wenglab.org/Naive_CD8_T-U.bigWig" - ], - [ - "Naive Teffs Stimulated", - "https://downloads.wenglab.org/Naive_Teffs-S.bigWig" - ], - [ - "Naive Teffs Unstimulated", - "https://downloads.wenglab.org/Naive_Teffs-U.bigWig" - ], - [ - "Naive Tregs Stimulated", - "https://downloads.wenglab.org/Naive_Tregs-S.bigWig" - ], - [ - "Naive Tregs Unstimulated", - "https://downloads.wenglab.org/Naive_Tregs-U.bigWig" - ], - [ - "pDCs Unstimulated", - "https://downloads.wenglab.org/pDCs-U.bigWig" - - ], - [ - "Plasmablasts Unstimulated", - "https://downloads.wenglab.org/Plasmablasts-U.bigWig" - ], - [ - "Regulatory T Stimulated", - "https://downloads.wenglab.org/Regulatory_T-S.bigWig" - ], - [ - "Regulatory T Unstimulated", - "https://downloads.wenglab.org/Regulatory_T-U.bigWig" - ], - [ - "Th17 precursors Stimulated", - "https://downloads.wenglab.org/Th17_precursors-S.bigWig" - ], - [ - "Th17 precursors Unstimulated", - "https://downloads.wenglab.org/Th17_precursors-U.bigWig" - ], - [ - "Th1 precursors Stimulated", - "https://downloads.wenglab.org/Th1_precursors-S.bigWig" - ], - [ - "Th1 precursors Unstimulated", - "https://downloads.wenglab.org/Th1_precursors-U.bigWig" - ], - [ - "Th2 precursors Stimulated", - "https://downloads.wenglab.org/Th2_precursors-S.bigWig" - ], - [ - "Th2 precursors Unstimulated", - "https://downloads.wenglab.org/Th2_precursors-U.bigWig" - ] - ] -}; - -const BulkAtacTrackModal: React.FC = (props) => { - const [expanded, setExpanded] = useState( - new Map(Object.keys(TRACKS).map((k) => [k, false])) - ); - const [selectedTracks, setSelectedTracks] = useState( - props.initialSelection.map((x) => x[0]) - ); - const toggleTrack = useCallback( - (track: string[]) => { - const selected = !!selectedTracks.find((x) => x === track[0])?.length; - if (!selected) setSelectedTracks([...selectedTracks, track[0]]); - else setSelectedTracks(selectedTracks.filter((x) => x !== track[0])); - }, - [selectedTracks] - ); - const expand = useCallback( - (key: string) => - setExpanded( - new Map( - Object.keys(TRACKS).map((k) => [ - k, - k === key ? !expanded.get(k) : !!expanded.get(k), - ]) - ) - ), - [expanded] - ); - - const onAccept = useCallback( - () => - props.onAccept && - props.onAccept([ - ...TRACKS["Bulk Atac Tracks"].filter( - (track) => - (selectedTracks.find((x) => x === track[0])?.length || 0) > 0 - ) - - ] as [string, string][]), - [selectedTracks, props] - ); - - return ( - - - - Select Bulk Atac Tracks for Display - - - expand("Bulk Atac Tracks")} - expandIcon={!expanded ? : } - aria-controls="panel1a-content" - id="panel1a-header" - > - - Bulk Atac Tracks - - - - - - - {TRACKS["Bulk Atac Tracks"].map((track) => ( - x === track[0])?.length || - 0) > 0 - } - /> - } - label={track[0]} - onChange={() => toggleTrack(track)} - /> - ))} - - - - - -
- -   - -
-
-
- ); -}; -export default BulkAtacTrackModal; diff --git a/immuscreen/src/common/gbview/bulkatactracks.tsx b/immuscreen/src/common/gbview/bulkatactracks.tsx index 8e53c29..2a05165 100644 --- a/immuscreen/src/common/gbview/bulkatactracks.tsx +++ b/immuscreen/src/common/gbview/bulkatactracks.tsx @@ -2,71 +2,12 @@ import { gql, useQuery } from "@apollo/client"; import { BigWigData, BigBedData, BigZoomData } from "bigwig-reader"; import React, { RefObject, useEffect, useMemo, useState } from "react"; import { DenseBigBed, EmptyTrack, FullBigWig } from "umms-gb"; -import { BigRequest, RequestError, } from "umms-gb/dist/components/tracks/trackset/types"; +import { RequestError, } from "umms-gb/dist/components/tracks/trackset/types"; import { ValuedPoint } from "umms-gb/dist/utils/types"; import { client } from "../utils" -import BulkAtacTrackModal from "./bulkatacmodal"; -import { BulkAtacCelltypeTrack, CalderonCellTypesMetadata } from "./consts"; import { CellQueryValue } from "../../app/celllineage/types"; import { getCellColor, getCellDisplayName } from "../../app/celllineage/utils"; - -export const DEFAULT_TRACKS = ( - assembly: string -): Map => - new Map([ - [ - "adult bCREs", - { - url: "gs://gcp.wenglab.org/GTEx-psychscreen/tracks/data/adult_bCREs.bigBed", - }, - ], - [ - "PsychSCREEN aggregated NeuN+ ATAC-seq", - { - url: "gs://gcp.wenglab.org/GTEx-psychscreen/tracks/data/all-NeuN+-ATAC.bigWig", - }, - ], - [ - "PsychSCREEN aggregated NeuN- ATAC-seq", - { - url: "gs://gcp.wenglab.org/GTEx-psychscreen/tracks/data/all-NeuN--ATAC.bigWig", - }, - ], - [ - "PsychSCREEN aggregated non-sorted ATAC-seq", - { - url: "gs://gcp.wenglab.org/GTEx-psychscreen/tracks/data/all-mixed-ATAC.bigWig", - }, - ], - [ - "motifs", - { url: "gs://gcp.wenglab.org/all-conserved-motifs.merged.bigBed" }, - ], - ]); - -export const TRACK_ORDER = [ - "adult bCREs", - "PsychSCREEN aggregated NeuN+ ATAC-seq", - "PsychSCREEN aggregated NeuN- ATAC-seq", - "PsychSCREEN aggregated non-sorted ATAC-seq", - "motifs", -]; - -export const COLOR_MAP: Map = new Map([ - ["PsychSCREEN aggregated NeuN+ ATAC-seq", "#0d825d"], - ["PsychSCREEN aggregated NeuN- ATAC-seq", "#164182"], - ["PsychSCREEN aggregated non-sorted ATAC-seq", "#1c8099"], -]); - - -export const tracks = (assembly: string, pos: GenomicRange) => - TRACK_ORDER.map((x) => ({ - chr1: pos.chromosome!, - start: pos.start, - end: pos.end, - ...DEFAULT_TRACKS(assembly).get(x)!, - preRenderedWidth: 1400, - })); +import BulkAtacModal from "./bulkAtacSelector"; export const BIG_QUERY = gql` query BigRequests($bigRequests: [BigRequest!]!) { @@ -102,7 +43,6 @@ export type BigQueryResponse = { }; type BulkAtacTrackProps = { - //tracks: BigRequest[]; domain: GenomicRange; onHeightChanged?: (i: number) => void; cCREHighlight?: GenomicRange; @@ -178,56 +118,60 @@ export const TitledTrack: React.FC<{ ); }; - const BulkAtacTracks: React.FC = (props: BulkAtacTrackProps) => { +const BulkAtacTracks: React.FC = (props: BulkAtacTrackProps) => { + const [selectedCells, setSelectedCells] = useState(props.defaultcelltypes as CellQueryValue[] || []) + + // tracks -> [track name, track URL, track color] + const tracks: [string, string, string][] = useMemo(() => { + const x: [string, string, string][] = selectedCells.map(cell => { + return ( + [ + getCellDisplayName(cell, true, true) + (["HSC", "CD34_Cord_Blood", "CD34_Bone_Marrow"].find(x => x === cell) ? ` (${cell})` : ''), + `https://downloads.wenglab.org/${cell}.bigWig`, + getCellColor(cell) + ] + ) + }) || [] + x.sort() + x.unshift(["All Immune Cells (Aggregate Signal)", "https://downloads.wenglab.org/all_immune.bigWig", "#000000"]) + return x + }, [selectedCells]) + - const bulkAtacColors: {[key:string]: string} = {} - - const defaultTracks: [string, string][] = props.defaultcelltypes?.map((cell: CellQueryValue) => { - bulkAtacColors[getCellDisplayName(cell, true, true)] = getCellColor(cell) - return [getCellDisplayName(cell, true, true), `https://downloads.wenglab.org/${cell}.bigWig`] - }) || [] - - defaultTracks.sort() - defaultTracks.unshift(["All Immune Cells (Aggregate Signal)", "https://downloads.wenglab.org/all_immune.bigWig"]) + const [settingsMousedOver, setSettingsMousedOver] = useState(false); + const [settingsModalShown, setSettingsModalShown] = useState(false); - //Why is this this not working when you have a lot of tracks? Why did my changes matter? - const [cTracks, setTracks] = useState<[string, string][]>(defaultTracks); - const height = useMemo(() => cTracks.length * 80, [cTracks]); + const height = useMemo(() => tracks.length * 80, [tracks]); const bigRequests = useMemo( () => - cTracks.map((x) => ({ + tracks.map((x) => ({ chr1: props.domain.chromosome!, start: props.domain.start, end: props.domain.end, preRenderedWidth: 1400, url: x[1], })), - [cTracks, props] + [tracks, props] ); + const { data, loading } = useQuery(BIG_QUERY, { variables: { bigRequests }, client }); + useEffect(() => { props.onHeightChanged && props.onHeightChanged(height); }, [props.onHeightChanged, height, props]); - const [settingsMousedOver, setSettingsMousedOver] = useState(false); - const [settingsModalShown, setSettingsModalShown] = useState(false); - return loading || (data?.bigRequests.length || 0) < 1 ? ( ) : ( <> - {/* Need to add all cell types to this */} - setSettingsModalShown(false)} - onAccept={(x) => { - setTracks(x); - setSettingsModalShown(false); - }} - initialSelection={cTracks} + onAccept={(cells: CellQueryValue[]) => setSelectedCells(cells)} + selected={selectedCells} /> @@ -236,14 +180,13 @@ export const TitledTrack: React.FC<{ ))} @@ -284,7 +227,7 @@ export const TitledTrack: React.FC<{ textAnchor="middle" fill="#194023" > - Bulk Atac Tracks + Bulk ATAC ); diff --git a/immuscreen/src/common/gbview/chrombpnetatactracks.tsx b/immuscreen/src/common/gbview/chrombpnetatactracks.tsx index ad402eb..94c1aa2 100644 --- a/immuscreen/src/common/gbview/chrombpnetatactracks.tsx +++ b/immuscreen/src/common/gbview/chrombpnetatactracks.tsx @@ -63,22 +63,15 @@ const ChromBPNetAtacTracks: React.FC = ({ defaultcelltypes }) => { - console.log(defaultcelltypes) //Given a query value I want the corresponding list of studies const r = defaultcelltypes && CalderonBigWigTracksMetadata.filter(c => defaultcelltypes.includes(c.celltype_name)) - console.log(r) const chrombpnetColors: {[key:string]: string} = {} - - // const defaultTracks: [string, string][] = defaultcelltypes?.map((cell: CellQueryValue) => { - // chrombpnetColors[getCellDisplayName(cell, true, true)] = getCellColor(cell) - // return [getCellDisplayName(cell, true, true), `https://downloads.wenglab.org/${cell}.bigWig`] - // }) || [] const defaultTracks: [string, string][] = [] - for (let cell of defaultcelltypes) { + if (defaultcelltypes) for (let cell of defaultcelltypes) { //Currently this is slightly broken in that it includes all monocyte experiments when "Mono" is cell since Mono is substring of all Monocyte S and U experiments, need to fix const experiments = Object.entries(experimentInfo).filter(([experiment, info]) => experiment.includes(cell)) experiments.forEach(exp => { diff --git a/immuscreen/src/common/gbview/consts.ts b/immuscreen/src/common/gbview/consts.ts index d7a95fe..178fc57 100644 --- a/immuscreen/src/common/gbview/consts.ts +++ b/immuscreen/src/common/gbview/consts.ts @@ -275,14 +275,14 @@ export const CalderonBigWigTracks = [ ["6792-MEP-SRX1427809","Megakaryocyte Erythroid Progenitor","Megakaryocyte Erythroid Progenitor in donor 6792","Progenitors"], ["7256-MEP-SRX1427863","Megakaryocyte Erythroid Progenitor","Megakaryocyte Erythroid Progenitor in donor 7256","Progenitors"], ["7256-MEP-SRX1427864","Megakaryocyte Erythroid Progenitor","Megakaryocyte Erythroid Progenitor in donor 7256","Progenitors"], -["2596-Ery-SRX1427825","Erythrocyte","Erythrocyte in donor 2596","Myeloid"], -["2596-Ery-SRX1427826","Erythrocyte","Erythrocyte in donor 2596","Myeloid"], -["2596-Ery-SRX1427827","Erythrocyte","Erythrocyte in donor 2596","Myeloid"], -["5483-Ery-SRX1427846","Erythrocyte","Erythrocyte in donor 5483","Myeloid"], -["5483-Ery-SRX1427847","Erythrocyte","Erythrocyte in donor 5483","Myeloid"], -["5483-Ery-SRX1427848","Erythrocyte","Erythrocyte in donor 5483","Myeloid"], -["6926-Ery-SRX1427852","Erythrocyte","Erythrocyte in donor 6926","Myeloid"], -["6926-Ery-SRX1427853","Erythrocyte","Erythrocyte in donor 6926","Myeloid"], +["2596-Ery-SRX1427825","Erythroblast","Erythroblast in donor 2596","Myeloid"], +["2596-Ery-SRX1427826","Erythroblast","Erythroblast in donor 2596","Myeloid"], +["2596-Ery-SRX1427827","Erythroblast","Erythroblast in donor 2596","Myeloid"], +["5483-Ery-SRX1427846","Erythroblast","Erythroblast in donor 5483","Myeloid"], +["5483-Ery-SRX1427847","Erythroblast","Erythroblast in donor 5483","Myeloid"], +["5483-Ery-SRX1427848","Erythroblast","Erythroblast in donor 5483","Myeloid"], +["6926-Ery-SRX1427852","Erythroblast","Erythroblast in donor 6926","Myeloid"], +["6926-Ery-SRX1427853","Erythroblast","Erythroblast in donor 6926","Myeloid"], ["4983-LMPP-SRX1427791","Lymphocyte-Primed Multipotent Progenitor","Lymphocyte-Primed Multipotent Progenitor in donor 4983","Progenitors"], ["6792-LMPP-SRX1427803","Lymphocyte-Primed Multipotent Progenitor","Lymphocyte-Primed Multipotent Progenitor in donor 6792","Progenitors"], ["7256-LMPP-SRX1427858","Lymphocyte-Primed Multipotent Progenitor","Lymphocyte-Primed Multipotent Progenitor in donor 7256","Progenitors"], diff --git a/immuscreen/src/common/gbview/defaulttracks.tsx b/immuscreen/src/common/gbview/defaulttracks.tsx index 1018422..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.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 f7e3b19..c10d4c8 100644 --- a/immuscreen/src/common/gbview/genomebrowserview.tsx +++ b/immuscreen/src/common/gbview/genomebrowserview.tsx @@ -110,7 +110,6 @@ export const GenomeBrowserView: React.FC = (props: Genom ) const l = useCallback((c) => ((c - coordinates.start) * 1400) / (coordinates.end - coordinates.start), [coordinates]) - console.log(svgRef.current?.clientHeight) return ( <> @@ -148,11 +147,11 @@ export const GenomeBrowserView: React.FC = (props: Genom {props.accession && } - {props.gene && = 500000 ? true : false} - />} + /> = (props: Genom * @todo Need to make sure chrombpnet tracks also include Corces */ } - + /> */} diff --git a/immuscreen/src/common/lib/themes.ts b/immuscreen/src/common/lib/themes.ts index 0e1eca4..30ed58b 100644 --- a/immuscreen/src/common/lib/themes.ts +++ b/immuscreen/src/common/lib/themes.ts @@ -1,27 +1,15 @@ -import { ThemeProvider, createTheme } from "@mui/material/styles" +'use client' +import { createTheme } from "@mui/material/styles" // temp theme for toolbar color and accordion outline - UMass blue / empty secondary export const defaultTheme = createTheme({ palette: { mode: "light", primary: { - main: "#000F9F", - light: "#42a5f5", - dark: "#000F9F", - // contrastText: "#fff" - }, - secondary: { - main: "#nnn", - light: "#nnn", - dark: "#nnn", - // contrastText: "#fff" - }, - // background: { - // paper: "#fff", - // default: "#fff" - // } + // main: "#000F9F", + main: "#494d6b", + }, }, - components: { MuiAccordion: { defaultProps: { diff --git a/immuscreen/src/common/utils.ts b/immuscreen/src/common/utils.ts index e3660d2..77af733 100644 --- a/immuscreen/src/common/utils.ts +++ b/immuscreen/src/common/utils.ts @@ -10,8 +10,6 @@ export const StyledTab = styled(Tab)({ textTransform: "none", }) - - //https://stackoverflow.com/questions/3426404/create-a-hexadecimal-colour-based-on-a-string-with-javascript //generate uniq color based on given string export const stringToColour = (str: string) => { @@ -54,4 +52,28 @@ export const hex2rgb = (hex) => { return `${r},${g},${b}`; -} \ No newline at end of file +} + +export function toScientificNotation(num: number, sigFigs?: number) { + // Convert the number to scientific notation using toExponential + let scientific = num.toExponential(sigFigs ?? undefined); + + // Split the scientific notation into the coefficient and exponent parts + let [coefficient, exponent] = scientific.split('e'); + + // Format the exponent part + let expSign = exponent[0]; + exponent = exponent.slice(1); + + // Convert the exponent to a superscript string + let superscriptExponent = exponent + .split('') + .map(char => '⁰¹²³⁴⁵⁶⁷⁸⁹'[char] || char) + .join(''); + + // Add the sign back to the exponent + superscriptExponent = (expSign === '-' ? '⁻' : '') + superscriptExponent; + + // Combine the coefficient with the superscript exponent + return coefficient + '×10' + superscriptExponent; +}