diff --git a/screen2.0/public/Human2.png b/screen2.0/public/Human2.png new file mode 100644 index 00000000..60098ce5 Binary files /dev/null and b/screen2.0/public/Human2.png differ diff --git a/screen2.0/public/Mouse2.png b/screen2.0/public/Mouse2.png new file mode 100644 index 00000000..4c735185 Binary files /dev/null and b/screen2.0/public/Mouse2.png differ diff --git a/screen2.0/src/app/applets/gwas/page.tsx b/screen2.0/src/app/applets/gwas/page.tsx index 3e6ba146..ac654493 100644 --- a/screen2.0/src/app/applets/gwas/page.tsx +++ b/screen2.0/src/app/applets/gwas/page.tsx @@ -2,7 +2,7 @@ import { Typography } from "@mui/material" import React, { useEffect, useState } from "react" -import { DataTable } from "@weng-lab/ts-ztable" +import { DataTable } from "@weng-lab/psychscreen-ui-components" import { createLink, ErrorMessage, LoadingMessage } from "../../../common/lib/utility" import Grid2 from "@mui/material/Unstable_Grid2/Grid2" import { Box } from "@mui/material" diff --git a/screen2.0/src/app/applets/page.tsx b/screen2.0/src/app/applets/page.tsx index f09e0237..612df94a 100644 --- a/screen2.0/src/app/applets/page.tsx +++ b/screen2.0/src/app/applets/page.tsx @@ -1,6 +1,8 @@ "use client" + import { Typography } from "@mui/material" + export default function Applets() { return (
diff --git a/screen2.0/src/app/downloads/data-matrices.tsx b/screen2.0/src/app/downloads/data-matrices.tsx new file mode 100644 index 00000000..28d7ace6 --- /dev/null +++ b/screen2.0/src/app/downloads/data-matrices.tsx @@ -0,0 +1,497 @@ +import { ChangeEvent, useEffect, useMemo, useState } from "react"; +import { Accordion, AccordionDetails, AccordionSummary, Autocomplete, Button, Divider, FormControl, FormControlLabel, FormLabel, Grid, Modal, Radio, RadioGroup, Select, TextField, Typography, Box, Stack } from "@mui/material"; +import Grid2 from "@mui/material/Unstable_Grid2/Grid2"; +import { ArrowForward, Clear, Download, ExpandMore, Visibility } from "@mui/icons-material"; +import Image from "next/image"; +import Human from "../../../public/Human2.png" +import Mouse from "../../../public/Mouse2.png" +import { useRouter } from "next/navigation"; +import { Chart, Scatter, Legend, Annotation, Range2D } from "jubilant-carnival" +import { DataTable, DataTableColumn } from "@weng-lab/psychscreen-ui-components"; +import Config from "../../config.json" +import { BiosampleUMAP } from "./types"; +import { DNase_seq } from "../../common/lib/colors"; +import { H3K4me3 } from "../../common/lib/colors"; +import { H3K27ac } from "../../common/lib/colors"; +import { CA_CTCF } from "../../common/lib/colors"; +import { ApolloQueryResult } from "@apollo/client"; + +//Need to type these +interface TabPanelProps { + children?: React.ReactNode; + value: number; + biosamples: -1 | ApolloQueryResult, + matrices: -1 | ApolloQueryResult, + searchParams: { [key: string]: string | string[] | undefined } +} + +type Selected = { + assembly: "Human" | "Mouse" + assay: "DNase" | "H3K4me3" | "H3K27ac" | "CTCF" +} + +// Direct copy from old SCREEN but changed low to be optional +function nearest5(x, low?) { + if (low) return Math.floor(x) - (x > 0 ? Math.floor(x) % 5 : 5 + (Math.floor(x) % 5)) + return Math.ceil(x) + (x > 0 ? Math.ceil(x) % 5 : 5 + (Math.ceil(x) % 5)) +} + +// Direct copy from old SCREEN +function fiveRange(min, max) { + const r = [] + for (let i = min; i <= max; i += 5) r.push(i) + return r +} + +// Direct copy from old SCREEN +function tenRange(min, max) { + const r = [] + for (let i = min; i <= max; i += 10) r.push(i) + return r +} + +// Direct copy from old SCREEN +function oneRange(min, max) { + const r = [] + for (let i = min; i <= max; ++i) r.push(i) + return r +} + +// Direct copy from old SCREEN +function spacedColors(n) { + const r = [] + for (let i = 0; i < 360; i += 360 / n) r.push(`hsl(${i},50%,40%)`) + return r +} + +// Direct copy from old SCREEN +function colorMap(strings) { + const c = {} + strings.forEach((x) => (c[x] = c[x] ? c[x] + 1 : 1)) + strings = [...new Set(strings)] + const r = {} + const colors = spacedColors(strings.length) + strings.forEach((x, i) => { + r[x] = colors[i] + }) + return [r, c] +} + +// Styling for selected biosamples modal +const style = { + position: 'absolute' as 'absolute', + top: '50%', + left: '50%', + transform: 'translate(-50%, -50%)', + width: '80%', + boxShadow: 24, +}; + +export function DataMatrices(props: TabPanelProps) { + const [selectedAssay, setSelectedAssay] = useState(() => { + if ((props.searchParams.assembly === "Human" || props.searchParams.assembly === "Mouse") + && (props.searchParams.assay === "DNase" || props.searchParams.assay === "H3K4me3" || props.searchParams.assay === "H3K27ac" || props.searchParams.assay === "CTCF")) { + return { assembly: props.searchParams.assembly, assay: props.searchParams.assay } + } + else { + return { assembly: "Human", assay: "DNase" } + } + }) + const [bounds, setBounds] = useState(undefined) + const [data, setData] = useState<{ ccREBiosampleQuery: { biosamples: BiosampleUMAP[] } }>(props.matrices != -1 ? props.matrices.data : {}) + const [lifeStage, setLifeStage] = useState("all") + const [colorBy, setColorBy] = useState("sampleType") + const [tSelected, setTSelected] = useState(new Set([])) + const [searched, setSearched] = useState(null) + const [biosamples, setBiosamples] = useState([]) + const [selectMode, setSelectMode] = useState<"select" | "zoom">("select") + const [tooltip, setTooltip] = useState(-1) + + const [open, setOpen] = useState(false); + const handleOpenModal = () => { biosamples.length !== 0 && setOpen(true) }; + const handleCloseModal = () => setOpen(false); + + const router = useRouter() + + //Update data state variable whenever the data changes + useEffect(() => setData(props.matrices != -1 ? props.matrices.data : {}), [props.matrices]) + + // Direct copy from old SCREEN + const [scMap, scc] = useMemo( + () => + colorMap( + (data && + data.ccREBiosampleQuery && + data.ccREBiosampleQuery.biosamples.filter((x) => x.umap_coordinates).map((x) => x.sampleType)) || + [] + ), + [data] + ) + const [oMap, occ] = useMemo( + () => + colorMap( + (data && data.ccREBiosampleQuery && data.ccREBiosampleQuery.biosamples.filter((x) => x.umap_coordinates).map((x) => x.ontology)) || + [] + ), + [data] + ) + const fData = useMemo( + () => { + return ( + data && + data.ccREBiosampleQuery && + data.ccREBiosampleQuery.biosamples + .filter((x) => x.umap_coordinates) + .filter((x) => (lifeStage === "all" || lifeStage === x.lifeStage) && (tSelected.size === 0 || tSelected.has(x[colorBy]))) + ) + } + , + [data, lifeStage, colorBy, tSelected] + ) + const xMin = useMemo( + () => (bounds ? Math.floor(bounds.x.start) : nearest5(Math.min(...((fData && fData.map((x) => x.umap_coordinates[0])) || [0])), true)), + [fData, bounds] + ) + const yMin = useMemo( + () => (bounds ? Math.floor(bounds.y.start) : nearest5(Math.min(...((fData && fData.map((x) => x.umap_coordinates[1])) || [0])), true)), + [fData, bounds] + ) + const xMax = useMemo( + () => (bounds ? Math.ceil(bounds.x.end) : nearest5(Math.max(...((fData && fData.map((x) => x.umap_coordinates[0])) || [0])))), + [fData, bounds] + ) + const yMax = useMemo( + () => (bounds ? Math.ceil(bounds.y.end) : nearest5(Math.max(...((fData && fData.map((x) => x.umap_coordinates[1])) || [0])))), + [fData, bounds] + ) + const scatterData = useMemo( + () => + (fData && fData + .filter((x) => (xMin <= x.umap_coordinates[0] && x.umap_coordinates[0] <= xMax) && (yMin <= x.umap_coordinates[1] && x.umap_coordinates[1] <= yMax)) + .map((x) => ({ + x: x.umap_coordinates[0], + y: x.umap_coordinates[1], + svgProps: { + r: searched && x.experimentAccession === searched.experimentAccession ? 10 : 3, + fill: + searched === null || x.experimentAccession === searched.experimentAccession + ? (colorBy === "sampleType" ? scMap : oMap)[x[colorBy]] + : "#aaaaaa", + fillOpacity: searched === null || x.experimentAccession === searched.experimentAccession ? 1 : 0.2, + }, + }))) || + [], + [fData, scMap, colorBy, searched, oMap, xMin, xMax, yMin, yMax] + ) + + // Direct copy from old SCREEN + const [legendEntries, height] = useMemo(() => { + const g = colorBy === "sampleType" ? scMap : oMap + const gc = colorBy === "sampleType" ? scc : occ + return [Object.keys(g).map((x) => ({ label: x, color: g[x], value: `${gc[x]} experiments` })), Object.keys(g).length * 50] + }, [scMap, oMap, colorBy, occ, scc]) + + /** + * Checks and reverses the order of coordinates provided by Jubilant Carnival selection if needed, then calls setBounds() + * @param bounds a Range2D object to check + */ + function handleSetBounds(bounds: Range2D) { + if (bounds.x.start > bounds.x.end) { + const tempX = bounds.x.start; + bounds.x.start = bounds.x.end; + bounds.x.end = tempX; + } + if (bounds.y.start > bounds.y.end) { + const tempY = bounds.y.start; + bounds.y.start = bounds.y.end; + bounds.y.end = tempY; + } + console.log(bounds) + setBounds(bounds) + } + + /** + * @param assay an assay + * @returns the corresponding color for the given assay + */ + function borderColor(assay: Selected["assay"]) { + switch (assay) { + case ("DNase"): + return DNase_seq + case ("H3K4me3"): + return H3K4me3 + case ("H3K27ac"): + return H3K27ac + case ("CTCF"): + return CA_CTCF + } + } + + // Assay selectors + const selectorButton = (variant: Selected) => { + return ( + + ) + } + + /** + * + * @param selectedAssay The selected assembly & assay + * @param variant "signal" or "zScore" + * @returns The corresponding download URL + */ + const matrixDownloadURL = (selectedAssay: Selected, variant: "signal" | "zScore") => { + const matrices = { + Human: { + signal: { + DNase: Config.Downloads.HumanDNaseSignalMatrix, + H3K4me3: Config.Downloads.HumanPromoterSignalMatrix, + H3K27ac: Config.Downloads.HumanEnhancerSignalMatrix, + CTCF: Config.Downloads.HumanCTCFSignalMatrix, + }, + zScore: { + DNase: Config.Downloads.HumanDNaseZScoreMatrix, + H3K4me3: Config.Downloads.HumanPromoterZScoreMatrix, + H3K27ac: Config.Downloads.HumanEnhancerZScoreMatrix, + CTCF: Config.Downloads.HumanCTCFZScoreMatrix, + }, + }, + Mouse: { + signal: { + DNase: Config.Downloads.MouseDNaseSignalMatrix, + H3K4me3: Config.Downloads.MousePromoterSignalMatrix, + H3K27ac: Config.Downloads.MouseEnhancerSignalMatrix, + CTCF: Config.Downloads.MouseCTCFSignalMatrix, + }, + zScore: { + DNase: Config.Downloads.MouseDNaseZScoreMatrix, + H3K4me3: Config.Downloads.MousePromoterZScoreMatrix, + H3K27ac: Config.Downloads.MouseEnhancerZScoreMatrix, + CTCF: Config.Downloads.MouseCTCFZScoreMatrix, + }, + }, + }; + return matrices[selectedAssay.assembly][variant][selectedAssay.assay]; + }; + + // Columns for selected biosample modal + const modalCols: DataTableColumn[] = [ + { + header: "Experimental Accession", + value: (row: BiosampleUMAP) => row.experimentAccession, + }, + { + header: "Biosample Name", + value: (row: BiosampleUMAP) => row.displayname, + }, + { + header: "Tissue", + value: (row: BiosampleUMAP) => row.ontology ?? "" + } + ] + + return ( + <> + {props.value === 2 && +
+ + + + Human + + 2,348,854 cCREs + 1,678 cell types + + + {"Human + + + {selectorButton({ assembly: "Human", assay: "DNase" })} + {selectorButton({ assembly: "Human", assay: "H3K4me3" })} + {selectorButton({ assembly: "Human", assay: "H3K27ac" })} + {selectorButton({ assembly: "Human", assay: "CTCF" })} + + + Mouse + + 926,843 cCREs + 366 cell types + + + {"Mouse + + + {selectorButton({ assembly: "Mouse", assay: "DNase" })} + {selectorButton({ assembly: "Mouse", assay: "H3K4me3" })} + {selectorButton({ assembly: "Mouse", assay: "H3K27ac" })} + {selectorButton({ assembly: "Mouse", assay: "CTCF" })} + + + + + + + } + getOptionLabel={(biosample: BiosampleUMAP) => biosample.displayname + " — Exp ID: " + biosample.experimentAccession} + blurOnSelect + onChange={(_, value: any) => setSearched(value)} + size="small" + /> + + Color By: + , value: string) => setColorBy(value)} + > + } label="Sample Type" /> + } label="Ontology" /> + + + + Show: + , value: string) => setLifeStage(value)} + > + } label="All" /> + } label="Adult" /> + } label="Embyronic" /> + + + + Hold shift, click, and draw a selection to: + , value: "select" | "zoom") => setSelectMode(value)} + > + } label="Select Experiments" /> + } label="Zoom In" /> + + + {bounds && } + + + setBiosamples(c[0].map((x) => fData[x])), + onSelectionEnd: (x) => handleSetBounds(x), + freeformSelection: selectMode === "select", + }} + > + setTooltip(-1)} + onPointClick={(i) => setBiosamples([fData[i]])} + /> + {tooltip !== -1 && ( + //X and Y attributes added due to error. Not sure if setting to zero has unintended consequences + + + + + {fData[tooltip].name.replace(/_/g, " ").slice(0, 45)} + {fData[tooltip].name.length > 45 ? "..." : ""} + + + {fData[tooltip].experimentAccession} + + + )} + + {biosamples.length !== 0 && + + + + + } + + }> + Legend + + + {legendEntries.map((element, index) => { + return ( + + {`${element.label}: ${element.value}`} + + ) + }) + } + + + + + + + + + + +
+ } + + ); +} \ No newline at end of file diff --git a/screen2.0/src/app/downloads/detailed-elements.tsx b/screen2.0/src/app/downloads/detailed-elements.tsx new file mode 100644 index 00000000..00a20821 --- /dev/null +++ b/screen2.0/src/app/downloads/detailed-elements.tsx @@ -0,0 +1,277 @@ +import { Button, ButtonProps, IconButton, Paper, Tooltip, Typography, Modal, Container, Divider } from "@mui/material"; +import Grid2 from "@mui/material/Unstable_Grid2/Grid2"; +import { Box } from "@mui/system"; +import React, { useMemo } from "react"; +import Config from "../../config.json" +import DownloadIcon from '@mui/icons-material/Download'; +import SearchIcon from '@mui/icons-material/Search'; +import { CA_CTCF, CA_H3K4me3, CA_TF, CA_only, PLS, TF_only, dELS, pELS } from "../../common/lib/colors"; +import { DataTable, DataTableColumn, DataTableProps } from "@weng-lab/psychscreen-ui-components"; +import { Biosample } from "./types"; +import Image from "next/image"; +import Human from "../../../public/Human2.png" +import Mouse from "../../../public/Mouse2.png" +import { ApolloQueryResult } from "@apollo/client"; +import { downloadTSV } from "./utils"; + +interface TabPanelProps { + children?: React.ReactNode; + value: number; + biosamples: -1 | ApolloQueryResult; +} + +//For all Human/Mouse cCREs +const DownloadButton = (props: ButtonProps & { label: string }) => { + return ( + + ) +} + +//Download tiles +const InlineDownloadButton = (props: ButtonProps & { label: string, bordercolor: string, mode: "download" | "search" }) => { + return ( + + + + + ) +} + +// Styling for By Cell Type Modal +const style = { + position: 'absolute' as 'absolute', + top: '50%', + left: '50%', + transform: 'translate(-50%, -50%)', + width: '80%', + boxShadow: 24, +}; + +// Render for URL in modal table +function bioTableColsRender(row: Biosample, x: "dnase" | "h3k4me3" | "h3k27ac" | "ctcf") { + if (row[x]) { + let url: string; + let fileName: string; + switch (x) { + case "dnase": + url = `https://downloads.wenglab.org/Registry-V4/Signal-Files/${row.dnase}-${row.dnase_signal}.txt` + fileName = `${row.dnase}-${row.dnase_signal}.txt` + break + case "h3k4me3": + url = `https://downloads.wenglab.org/Registry-V4/Signal-Files/${row.h3k4me3}-${row.h3k4me3_signal}.txt` + fileName = `${row.h3k4me3}-${row.h3k4me3_signal}.txt` + break + case "h3k27ac": + url = `https://downloads.wenglab.org/Registry-V4/Signal-Files/${row.h3k27ac}-${row.h3k27ac_signal}.txt` + fileName = `${row.h3k27ac}-${row.h3k27ac_signal}.txt` + break + case "ctcf": + url = `https://downloads.wenglab.org/Registry-V4/Signal-Files/${row.ctcf}-${row.ctcf_signal}.txt` + fileName = `${row.ctcf}-${row.ctcf_signal}.txt` + break + } + + const handleDL = () => + fetch(url) + .then((x) => x.text()) + .then((x) => { + downloadTSV( + x, + fileName + ) + }) + + return ( + + + + ) + } + else return null +} + +// Modal Columns +const bioTableCols: DataTableColumn[] = [ + { + header: "Tissue", + value: (row: Biosample) => row.ontology, + }, + { + header: "Cell Type", + value: (row: Biosample) => row.displayname, + }, + { + header: "DNase", + value: (row: Biosample) => row.dnase ?? "", + render: (row: Biosample) => bioTableColsRender(row, "dnase") + }, + { + header: "H3K4me3", + value: (row: Biosample) => row.h3k4me3 ?? "", + render: (row: Biosample) => bioTableColsRender(row, "h3k4me3") + }, + { + header: "H3K27ac", + value: (row: Biosample) => row.h3k27ac ?? "", + render: (row: Biosample) => bioTableColsRender(row, "h3k27ac") + }, + { + header: "CTCF", + value: (row: Biosample) => row.ctcf ?? "", + render: (row: Biosample) => bioTableColsRender(row, "ctcf") + } +] + +// By Cell Type Modal +function BiosampleModals(props: { rows: Biosample[]; open: boolean; tableTitle: string, handleClose: (event: {}, reason: "backdropClick" | "escapeKeyDown") => void; }): React.JSX.Element { + return ( + + + + + + ); +} + +export function DetailedElements(props: TabPanelProps) { + // Each of these handles one modal + const [open0, setOpen0] = React.useState(false); + const handleOpen0 = () => setOpen0(true); + const handleClose0 = () => setOpen0(false); + + const [open1, setOpen1] = React.useState(false); + const handleOpen1 = () => setOpen1(true); + const handleClose1 = () => setOpen1(false); + + const [open2, setOpen2] = React.useState(false); + const handleOpen2 = () => setOpen2(true); + const handleClose2 = () => setOpen2(false); + + const [open3, setOpen3] = React.useState(false); + const handleOpen3 = () => setOpen3(true); + const handleClose3 = () => setOpen3(false); + + const [open4, setOpen4] = React.useState(false); + const handleOpen4 = () => setOpen4(true); + const handleClose4 = () => setOpen4(false); + + const [open5, setOpen5] = React.useState(false); + const handleOpen5 = () => setOpen5(true); + const handleClose5 = () => setOpen5(false); + + const biosamples = props.biosamples != -1 ? props.biosamples.data : null + + //This is written with the assumption there's no lifeStage besides Embryonic and Adult + const humanCellLines: Biosample[] = useMemo(() => ((biosamples && biosamples.human && biosamples.human.biosamples) || []).filter((x: Biosample) => x.sampleType === "cell line"), [biosamples]) + const humanAdult: Biosample[] = useMemo(() => ((biosamples && biosamples.human && biosamples.human.biosamples) || []).filter((x: Biosample) => (x.sampleType !== "cell line") && (x.lifeStage === "adult")), [biosamples]) + const humanEmbryo: Biosample[] = useMemo(() => ((biosamples && biosamples.human && biosamples.human.biosamples) || []).filter((x: Biosample) => (x.sampleType !== "cell line") && (x.lifeStage === "embryonic")), [biosamples]) + const mouseCellLines: Biosample[] = useMemo(() => ((biosamples && biosamples.mouse && biosamples.mouse.biosamples) || []).filter((x: Biosample) => x.sampleType === "cell line"), [biosamples]) + const mouseAdult: Biosample[] = useMemo(() => ((biosamples && biosamples.mouse && biosamples.mouse.biosamples) || []).filter((x: Biosample) => (x.sampleType !== "cell line") && (x.lifeStage === "adult")), [biosamples]) + const mouseEmbryo: Biosample[] = useMemo(() => ((biosamples && biosamples.mouse && biosamples.mouse.biosamples) || []).filter((x: Biosample) => (x.sampleType !== "cell line") && (x.lifeStage === "embryonic")), [biosamples]) + + return ( + <> + {props.value === 1 && +
+ + + + Human (GRCh38/hg38) + {/* These are not showing up because of the flex container */} + + 2,348,854 cCREs • 1,678 cell types + + + {"Human + + + + + + + + + + + + + + {/* Box added to align last row */} + + + + + + Mouse (GRCm38/mm10) + + 926,843 cCREs • 366 cell types + + + {"Mouse + + + + + + + + + + + + + + {/* Box added to align last row */} + + + + + Human cCREs by Cell Type + + + Mouse cCREs by Cell Type + + + + + + + + + + + + + + + + + + +
+ } + + ); +} \ No newline at end of file diff --git a/screen2.0/src/app/downloads/downloads.tsx b/screen2.0/src/app/downloads/downloads.tsx new file mode 100644 index 00000000..0d0de9e8 --- /dev/null +++ b/screen2.0/src/app/downloads/downloads.tsx @@ -0,0 +1,79 @@ +"use client" + +import * as React from 'react'; +import { + Typography, + Tabs, + Tab, + Box, + Container, + ThemeProvider, +} from "@mui/material" + +import Grid2 from "@mui/material/Unstable_Grid2/Grid2" + +import { QuickStart } from './quick-start'; +import { DetailedElements } from './detailed-elements'; +import { DataMatrices } from './data-matrices'; +import { useMemo, useState } from 'react'; +import { defaultTheme } from '../../common/lib/themes'; +import { useRouter } from 'next/navigation'; +import { ApolloQueryResult } from '@apollo/client'; + +function a11yProps(index: number) { + return { + id: `simple-tab-${index}`, + 'aria-controls': `simple-tabpanel-${index}`, + }; +} + +export default function DownloadsPage(props: { + biosamples: -1 | ApolloQueryResult, + matrices: -1 | ApolloQueryResult, + searchParams: { [key: string]: string | string[] | undefined } +}) { + const [page, setPage] = useState(props.searchParams.tab ? Number(props.searchParams.tab) : 0); + const [matricesState, setMatricesState] = useState<{assembly: "Human" | "Mouse", assay: "DNase" | "H3K4me3" | "H3K27ac" | "CTCF"} | null>(null) + + const router = useRouter() + + const handleChange = (event: React.SyntheticEvent, newValue: number) => { + if ( + (props.searchParams.assembly === "Human" || props.searchParams.assembly === "Mouse") + && + (props.searchParams.assay === "DNase" || props.searchParams.assay === "H3K4me3" || props.searchParams.assay === "H3K27ac" || props.searchParams.assay === "CTCF") + ) { + setMatricesState({ assembly: props.searchParams.assembly, assay: props.searchParams.assay }) + } + if (newValue === 2 && matricesState !== null) { + router.push(`/downloads?tab=${newValue}&assembly=${matricesState.assembly}&assay=${matricesState.assay}`) + } else { + router.push(`/downloads?tab=${newValue}`) + } + setPage(newValue); + }; + + return ( + + + + + + + + + + + + + + + + {/* Matrices being fed biosamples might be redundant */} + + + + + + ) +} diff --git a/screen2.0/src/app/downloads/page.tsx b/screen2.0/src/app/downloads/page.tsx index dcab9ce2..80f73a01 100644 --- a/screen2.0/src/app/downloads/page.tsx +++ b/screen2.0/src/app/downloads/page.tsx @@ -1,10 +1,25 @@ -"use client" -import { Typography } from "@mui/material" +import * as React from 'react'; +import DownloadsPage from './downloads'; +import { UMAPQuery, biosampleQuery } from '../../common/lib/queries'; +import { ThemeProvider } from '@mui/material'; +import { defaultTheme } from '../../common/lib/themes'; +import { ApolloQueryResult } from '@apollo/client'; -export default function Downloads() { + +export default async function Downloads({ + searchParams, +}: { + searchParams: { [key: string]: string | string[] | undefined } +}) { + const biosamples: any = await biosampleQuery() + const assembly = searchParams.assembly === "Mouse" ? "mm10" : "grch38" + const assay = (searchParams.assay === "DNase" || searchParams.assay === "H3K4me3" || searchParams.assay === "H3K27ac" || searchParams.assay === "CTCF") ? searchParams.assay : "DNase" + + const matrices: any = await UMAPQuery(assembly, assay) + return (
- This is the downloads page +
) } diff --git a/screen2.0/src/app/downloads/quick-start.tsx b/screen2.0/src/app/downloads/quick-start.tsx new file mode 100644 index 00000000..0c753159 --- /dev/null +++ b/screen2.0/src/app/downloads/quick-start.tsx @@ -0,0 +1,274 @@ +import { + Typography, + Button, + ButtonProps, + Stack, + OutlinedInput, + InputAdornment, + IconButton, + Autocomplete, + TextField, + Tooltip, + Modal, + Box, + Divider +} from "@mui/material"; +import InfoIcon from '@mui/icons-material/Info'; +import Grid2 from "@mui/material/Unstable_Grid2/Grid2" +import LoadingButton from '@mui/lab/LoadingButton' +import DownloadIcon from '@mui/icons-material/Download'; +import Human from "../../../public/Human2.png" +import Mouse from "../../../public/Mouse2.png" +import Config from "../../config.json" +import { useEffect, useMemo, useState } from "react"; +import { Biosample } from "./types"; +import React from "react"; +import Image from "next/image"; +import { ApolloQueryResult } from "@apollo/client"; +import { downloadTSV } from "./utils"; + +interface TabPanelProps { + children?: React.ReactNode; + value: number; + biosamples: -1 | ApolloQueryResult; +} + +const PROMOTER_MESSAGE = + "cCREs with promoter-like signatures have high DNase-seq signal, high H3K4me3 signal, and have centers within 200 bp of an annotated GENCODE TSS." +const ENHANCER_MESSAGE = + "cCREs with enhancer-like signatures have high DNase-seq signal and high H3K27ac signal. These cCREs can either be TSS-proximal (within 2kb) or TSS-distal and do not include promoter annotations." +const CTCF_MESSAGE = "cCREs with high CTCF-signal. These cCRE may also be classified as promoters, enhancer, or CTCF-only elements." +const LINK_MESSAGE = "cCRE-gene links curated from Hi-C, ChIA-PET, CRISPR perturbations and eQTL data." + +/** + * + * @param selected The selected biosample + * @returns The link to download biosample-specific cCREs + */ +function generateBiosampleURL(selected: Biosample): URL { + const r = [selected.dnase_signal, selected.h3k4me3_signal, selected.h3k27ac_signal, selected.ctcf_signal].filter((x) => !!x) + return new URL(`https://downloads.wenglab.org/Registry-V4/${r.join("_")}.bed`) +} + +const DownloadButton = (props: ButtonProps & { label: string }) => { + return ( + + ) +} + +function ComboBox(props: { options: Biosample[], label: string, mode: "H-promoter" | "H-enhancer" | "H-ctcf" | "M-promoter" | "M-enhancer" | "M-ctcf" }): JSX.Element { + const [toDownload, setToDownload] = useState(null) + const [selectedBiosample, setSelectedBiosample] = useState(null) + + //Not sure if this is strictly necessary to use useMemo + const stringToMatch: string = useMemo(() => { + switch (props.mode) { + case "H-promoter": + return "PLS" + case "M-promoter": + return "PLS" + case "H-enhancer": + return "ELS" + case "M-enhancer": + return "ELS" + case "H-ctcf": + return "CTCF" + case "M-ctcf": + return "CTCF" + } + }, [props.mode] + ) + + useEffect(() => { + toDownload && + fetch(toDownload) + .then((x) => x.text()) + .then((x) => { + downloadTSV( + x + .split("\n") + .filter((x) => x.includes(stringToMatch)) + .join("\n"), + `${selectedBiosample.name}.${props.mode === "H-promoter" || props.mode === "M-promoter" ? "promoters" : props.mode === "H-enhancer" || props.mode === "M-enhancer" ? "enhancers" : "CTCF-bound cCREs"}.bed` + ) + setToDownload(null) + }) + }, [toDownload, props.mode, selectedBiosample, stringToMatch]) + + return ( + + {/* As an important note, since all the biosample names are getting their underscores removed, you can't search with the original names with the underscores without customizing search function. Maybe we could look into being able to search for a tissue category also or group them */} + } + getOptionLabel={(biosample: Biosample) => biosample.name.replace(/_/g, " ") + " — Exp ID: " + (props.mode === "H-promoter" || props.mode === "M-promoter" ? biosample.h3k4me3 : props.mode === "H-enhancer" || props.mode === "M-enhancer" ? biosample.h3k27ac : biosample.ctcf)} + blurOnSelect + onChange={(event, value: any) => setSelectedBiosample(value)} + size="small" + /> + {selectedBiosample && + setToDownload(generateBiosampleURL(selectedBiosample))} + variant="contained" + color="primary" + endIcon={} + > + {`Download ${props.mode === "H-promoter" || props.mode === "M-promoter" ? "promoters" : props.mode === "H-enhancer" || props.mode === "M-enhancer" ? "enhancers" : "CTCF-bound cCREs"} active in ${selectedBiosample.name.replace(/_/g, " ")}`} + + } + + ); +} + +export function QuickStart(props: TabPanelProps) { + const biosamples = props.biosamples !== -1 && props.biosamples.data + + //Filter query return + const humanPromoters: Biosample[] = useMemo(() => ((biosamples && biosamples.human && biosamples.human.biosamples) || []).filter((x: Biosample) => x.h3k4me3 !== null), [biosamples]) + const humanEnhancers: Biosample[] = useMemo(() => ((biosamples && biosamples.human && biosamples.human.biosamples) || []).filter((x: Biosample) => x.h3k27ac !== null), [biosamples]) + const humanCTCF: Biosample[] = useMemo(() => ((biosamples && biosamples.human && biosamples.human.biosamples) || []).filter((x: Biosample) => x.ctcf !== null), [biosamples]) + const mousePromoters: Biosample[] = useMemo(() => ((biosamples && biosamples.mouse && biosamples.mouse.biosamples) || []).filter((x: Biosample) => x.h3k4me3 !== null), [biosamples]) + const mouseEnhancers: Biosample[] = useMemo(() => ((biosamples && biosamples.mouse && biosamples.mouse.biosamples) || []).filter((x: Biosample) => x.h3k27ac !== null), [biosamples]) + const mouseCTCF: Biosample[] = useMemo(() => ((biosamples && biosamples.mouse && biosamples.mouse.biosamples) || []).filter((x: Biosample) => x.ctcf !== null), [biosamples]) + + return ( +
+ {props.value === 0 && + + {/* Titles */} + + Human (GRCh38/hg38) + {/* These are not showing up because of the flex container */} + + 2,348,854 cCREs • 1,678 cell types + + + {"Human + + + Mouse (GRCm38/mm10) + + 926,843 cCREs • 366 cell types + + + {"Mouse + + {/* All cCREs */} + + All cCREs + + + + + + + + {/* Promoters */} + + + Candidate Promoters + + + + + + + + + + + + + + + + + + + + {/* Enhancers */} + + + Candidate Enhancers + + + + + + + + + + + + + + + + + + + + {/* CTCF-Bound */} + + + CTCF-Bound + + + + + + + + + + + + + + + + + + + + {/* Gene Links */} + + + Gene Links + + + + + + + + + + + + } +
+ ); +} \ No newline at end of file diff --git a/screen2.0/src/app/downloads/types.ts b/screen2.0/src/app/downloads/types.ts new file mode 100644 index 00000000..d3edbda2 --- /dev/null +++ b/screen2.0/src/app/downloads/types.ts @@ -0,0 +1,25 @@ +export type Biosample = { + ctcf: string | null + ctcf_signal: string | null + dnase: string | null + dnase_signal: string | null + h3k27ac: string | null + h3k27ac_signal: string | null + h3k4me3: string | null + h3k4me3_signal: string | null + name: string | null + lifeStage: string + sampleType: string + ontology: string + displayname: string + } + + export type BiosampleUMAP = { + name: string; + displayname: string; + ontology: string; + sampleType: string; + lifeStage: string; + umap_coordinates: number[]; + experimentAccession: string; + } \ No newline at end of file diff --git a/screen2.0/src/app/downloads/utils.tsx b/screen2.0/src/app/downloads/utils.tsx new file mode 100644 index 00000000..045e4ce8 --- /dev/null +++ b/screen2.0/src/app/downloads/utils.tsx @@ -0,0 +1,16 @@ +//Imported from old SCREEN +function downloadBlob(blob, filename) { + const url = URL.createObjectURL(blob) + const downloadLink = document.createElement("a") + downloadLink.href = url + downloadLink.download = filename + document.body.appendChild(downloadLink) + downloadLink.click() + document.body.removeChild(downloadLink) +} + +//Imported from old SCREEN +//Move to utils +export function downloadTSV(text, filename) { + downloadBlob(new Blob([text], { type: "text/plain" }), filename) +} \ No newline at end of file diff --git a/screen2.0/src/app/globals.css b/screen2.0/src/app/globals.css index b0e275f3..53fea210 100644 --- a/screen2.0/src/app/globals.css +++ b/screen2.0/src/app/globals.css @@ -7,17 +7,17 @@ --foreground-rgb: 0, 0, 0; --background-start-rgb: 214, 219, 220; --background-end-rgb: 255, 255, 255; -} +} */ -@media (prefers-color-scheme: dark) { +/* @media (prefers-color-scheme: dark) { :root { --foreground-rgb: 255, 255, 255; --background-start-rgb: 0, 0, 0; --background-end-rgb: 0, 0, 0; } -} +} */ -body { +/* body { color: rgb(var(--foreground-rgb)); background: linear-gradient( to bottom, diff --git a/screen2.0/src/app/icon.png b/screen2.0/src/app/icon.png new file mode 100644 index 00000000..f2b71cbb Binary files /dev/null and b/screen2.0/src/app/icon.png differ diff --git a/screen2.0/src/app/search/ccredetails/linkedgenes.tsx b/screen2.0/src/app/search/ccredetails/linkedgenes.tsx index 5fd05a24..caaca989 100644 --- a/screen2.0/src/app/search/ccredetails/linkedgenes.tsx +++ b/screen2.0/src/app/search/ccredetails/linkedgenes.tsx @@ -27,7 +27,7 @@ export const LinkedGenes: React.FC<{ accession: string; assembly: string }> = ({ const { loading: loading_linked, data: data_linked } = useQuery(LINKED_GENES, { variables: { assembly, - accession, + accession: [accession], }, fetchPolicy: "cache-and-network", nextFetchPolicy: "cache-first", diff --git a/screen2.0/src/app/search/ccredetails/queries.ts b/screen2.0/src/app/search/ccredetails/queries.ts index 6aa59bf6..f3498f54 100644 --- a/screen2.0/src/app/search/ccredetails/queries.ts +++ b/screen2.0/src/app/search/ccredetails/queries.ts @@ -29,7 +29,7 @@ export const TOP_TISSUES = gql` } ` export const LINKED_GENES = gql` - query ($assembly: String!, $accession: String!) { + query ($assembly: String!, $accession: [String]!) { linkedGenesQuery(assembly: $assembly, accession: $accession) { assembly accession diff --git a/screen2.0/src/app/search/page.tsx b/screen2.0/src/app/search/page.tsx index b86d6171..77715c09 100644 --- a/screen2.0/src/app/search/page.tsx +++ b/screen2.0/src/app/search/page.tsx @@ -1,6 +1,6 @@ // Search Results Page import { CcreSearch } from "./ccresearch" -import MainQuery, { getGlobals } from "../../common/lib/queries" +import { getGlobals, MainQuery } from "../../common/lib/queries" import { ApolloQueryResult } from "@apollo/client" import { cCREData, CellTypeData, MainQueryParams } from "./types" import { checkTrueFalse, passesCriteria } from "../../common/lib/filter-helpers" diff --git a/screen2.0/src/app/search/types.ts b/screen2.0/src/app/search/types.ts index 1847955f..6cefc6d0 100644 --- a/screen2.0/src/app/search/types.ts +++ b/screen2.0/src/app/search/types.ts @@ -109,4 +109,4 @@ export type FilteredBiosampleData = [ h3k4me3: boolean } }[] -][] +][] \ No newline at end of file diff --git a/screen2.0/src/common/components/MainResultsTable.tsx b/screen2.0/src/common/components/MainResultsTable.tsx index d748ac84..de38be95 100644 --- a/screen2.0/src/common/components/MainResultsTable.tsx +++ b/screen2.0/src/common/components/MainResultsTable.tsx @@ -123,7 +123,6 @@ function MainResultsTable(props: Partial>) { }, [searchParams] ) - console.log(props.rows) return ( (false) - // Hamburger Menu, deals with setting it's position + // Hamburger Menu, deals with setting its position const [anchorElNav_Hamburger, setAnchorElNav_Hamburger] = React.useState(null) - // Hover dropdowns, deals with setting it's position + // Hover dropdowns, deals with setting its position const [anchorElNav_Dropdown0, setAnchorElNav_Dropdown0] = React.useState(null) const [anchorElNav_Dropdown1, setAnchorElNav_Dropdown1] = React.useState(null) @@ -120,12 +118,12 @@ function ResponsiveAppBar() { } } - const toggleDrawer = (open) => (event) => { - if (event.type === "keydown" && (event.key === "Tab" || event.key === "Shift")) { - return - } - setState(open) - } + // const toggleDrawer = (open) => (event) => { + // if (event.type === "keydown" && (event.key === "Tab" || event.key === "Shift")) { + // return + // } + // setState(open) + // } return ( @@ -279,7 +277,7 @@ function ResponsiveAppBar() { {/* Settings */} - + {/* Settings - + */} diff --git a/screen2.0/src/common/lib/colors.ts b/screen2.0/src/common/lib/colors.ts index 940ace8a..92e17a69 100644 --- a/screen2.0/src/common/lib/colors.ts +++ b/screen2.0/src/common/lib/colors.ts @@ -1,10 +1,10 @@ /** * cCRE Groups */ -export const PLS = "#FFCD00" +export const PLS = "#FF0000" export const pELS = "#FFA700" export const dELS = "#FFCD00" -export const CAH3K4me3 = "#ffaaaa" +export const CA_H3K4me3 = "#ffaaaa" export const CA_CTCF = "#00B0F0" export const CA_only = "#06DA93" export const CA_TF = "#be28e5" diff --git a/screen2.0/src/common/lib/filter-helpers.ts b/screen2.0/src/common/lib/filter-helpers.ts index cfed7110..97d9e17e 100644 --- a/screen2.0/src/common/lib/filter-helpers.ts +++ b/screen2.0/src/common/lib/filter-helpers.ts @@ -185,7 +185,7 @@ export function filterBiosamples( return filteredBiosamples } -export function assayHoverInfo(assays: { dnase: boolean; h3k27ac: boolean; h3k4me3: any; ctcf: boolean; atac: boolean }) { +export function assayHoverInfo(assays: { dnase: boolean; h3k27ac: boolean; h3k4me3: boolean; ctcf: boolean; atac: boolean }) { const dnase = assays.dnase const h3k27ac = assays.h3k27ac const h3k4me3 = assays.h3k4me3 diff --git a/screen2.0/src/common/lib/queries.ts b/screen2.0/src/common/lib/queries.ts index ef1a4406..78040c85 100644 --- a/screen2.0/src/common/lib/queries.ts +++ b/screen2.0/src/common/lib/queries.ts @@ -189,6 +189,91 @@ const cCRE_QUERY_WITH_BIOSAMPLES = gql` } } ` + +const BIOSAMPLE_QUERY = gql` + query biosamples { + human: ccREBiosampleQuery(assembly: "grch38") { + biosamples { + name + ontology + lifeStage + sampleType + displayname + dnase: experimentAccession(assay: "DNase") + h3k4me3: experimentAccession(assay: "H3K4me3") + h3k27ac: experimentAccession(assay: "H3K27ac") + ctcf: experimentAccession(assay: "CTCF") + dnase_signal: fileAccession(assay: "DNase") + h3k4me3_signal: fileAccession(assay: "H3K4me3") + h3k27ac_signal: fileAccession(assay: "H3K27ac") + ctcf_signal: fileAccession(assay: "CTCF") + } + } + mouse: ccREBiosampleQuery(assembly: "mm10") { + biosamples { + name + ontology + lifeStage + sampleType + displayname + dnase: experimentAccession(assay: "DNase") + h3k4me3: experimentAccession(assay: "H3K4me3") + h3k27ac: experimentAccession(assay: "H3K27ac") + ctcf: experimentAccession(assay: "CTCF") + dnase_signal: fileAccession(assay: "DNase") + h3k4me3_signal: fileAccession(assay: "H3K4me3") + h3k27ac_signal: fileAccession(assay: "H3K27ac") + ctcf_signal: fileAccession(assay: "CTCF") + } + } + } +` + +const UMAP_QUERY = gql` + query q($assembly: String!, $assay: [String!], $a: String!) { + ccREBiosampleQuery(assay: $assay, assembly: $assembly) { + biosamples { + name + displayname + ontology + sampleType + lifeStage + umap_coordinates(assay: $a) + experimentAccession(assay: $a) + } + } + } +` + +export const TOP_TISSUES = gql` + query q($accession: [String!], $assembly: String!) { + ccREBiosampleQuery(assembly: $assembly) { + biosamples { + sampleType + cCREZScores(accession: $accession) { + score + assay + experiment_accession + } + name + ontology + } + } + cCREQuery(assembly: $assembly, accession: $accession) { + accession + group + zScores { + score + experiment + } + dnase: maxZ(assay: "DNase") + h3k4me3: maxZ(assay: "H3K4me3") + h3k27ac: maxZ(assay: "H3K27ac") + ctcf: maxZ(assay: "CTCF") + } + } +` + function cCRE_QUERY_VARIABLES(assembly: string, chromosome: string, start: number, end: number, biosample?: string) { return { uuid: null, @@ -223,7 +308,7 @@ function cCRE_QUERY_VARIABLES(assembly: string, chromosome: string, start: numbe * @param biosample optional - a biosample selection. If not specified or "undefined", will be marked as "null" in gql query * @returns cCREs matching the search */ -export default async function MainQuery(assembly: string, chromosome: string, start: number, end: number, biosample: string = null) { +export async function MainQuery(assembly: string, chromosome: string, start: number, end: number, biosample: string = null) { console.log("queried with: " + assembly, chromosome, start, end, biosample) var data: ApolloQueryResult | -1 @@ -240,34 +325,43 @@ export default async function MainQuery(assembly: string, chromosome: string, st } } -export const TOP_TISSUES = gql` - query q($accession: [String!], $assembly: String!) { - ccREBiosampleQuery(assembly: $assembly) { - biosamples { - sampleType - cCREZScores(accession: $accession) { - score - assay - experiment_accession - } - name - ontology - } - } - cCREQuery(assembly: $assembly, accession: $accession) { - accession - group - zScores { - score - experiment +export async function biosampleQuery() { + var data: ApolloQueryResult | -1 + try { + data = await getClient().query({ + query: BIOSAMPLE_QUERY + }) + } catch (error) { + console.log(error) + data = -1 + } finally { + return data + } +} + +export async function UMAPQuery( + assembly: "grch38" | "mm10", + assay: "DNase" | "H3K4me3" | "H3K27ac" | "CTCF" +) { + var data: ApolloQueryResult | -1 + try { + data = await getClient().query({ + query: UMAP_QUERY, + variables: { + assembly: assembly, + assay: assay, + a: assay.toLocaleLowerCase() } - dnase: maxZ(assay: "DNase") - h3k4me3: maxZ(assay: "H3K4me3") - h3k27ac: maxZ(assay: "H3K27ac") - ctcf: maxZ(assay: "CTCF") - } + }) + } catch (error) { + console.log(error) + data = -1 + } finally { + return data } -` +} + + /** * * @returns the shortened byCellType file from https://downloads.wenglab.org/databyct.json diff --git a/screen2.0/src/config.json b/screen2.0/src/config.json index d2558e65..e58e9f3c 100644 --- a/screen2.0/src/config.json +++ b/screen2.0/src/config.json @@ -29,5 +29,47 @@ "bed_intersect": "https://api.wenglab.org/screen_v13/postws/lines", "staticServer": "/assets", "overrides": {} + }, + "Downloads": { + "HumanCCREs": "https://downloads.wenglab.org/Registry-V4/GRCh38-cCREs.bed", + "HumanPromoters": "https://downloads.wenglab.org/Registry-V4/GRCh38-cCREs.PLS.bed", + "HumanProximalEnhancers": "https://downloads.wenglab.org/Registry-V4/GRCh38-cCREs.pELS.bed", + "HumanDistalEnhancers": "https://downloads.wenglab.org/Registry-V4/GRCh38-cCREs.dELS.bed", + "HumanCA_CTCF": "https://downloads.wenglab.org/Registry-V4/GRCh38-cCREs.CTCF-only.bed", + "HumanCA_H3K4me3": "https://downloads.wenglab.org/Registry-V4/GRCh38-cCREs.CA-H3K4me3.bed", + "HumanCA_TF": "https://downloads.wenglab.org/Registry-V4/GRCh38-cCREs.CA-TF.bed", + "HumanCA_only": "https://downloads.wenglab.org/Registry-V4/GRCh38-cCREs.CA.bed", + "HumanTF_only": "https://downloads.wenglab.org/Registry-V4/GRCh38-cCREs.TF.bed", + "HumanGeneLinks": "https://downloads.wenglab.org/GRCh38-Gene-Links.txt", + + "MouseCCREs": "https://downloads.wenglab.org/Registry-V4/mm10-cCREs.bed", + "MousePromoters": "https://downloads.wenglab.org/Registry-V4/mm10-cCREs.PLS.bed", + "MouseProximalEnhancers": "https://downloads.wenglab.org/Registry-V4/mm10-cCREs.pELS.bed", + "MouseDistalEnhancers": "https://downloads.wenglab.org/Registry-V4/mm10-cCREs.dELS.bed", + "MouseCA_CTCF": "https://downloads.wenglab.org/Registry-V4/mm10-cCREs.CTCF-only.bed", + "MouseCA_H3K4me3": "https://downloads.wenglab.org/Registry-V4/mm10-cCREs.CA-H3K4me3.bed", + "MouseCA_TF": "https://downloads.wenglab.org/Registry-V4/mm10-cCREs.CA-TF.bed", + "MouseCA_only": "https://downloads.wenglab.org/Registry-V4/mm10-cCREs.CA.bed", + "MouseTF_only": "https://downloads.wenglab.org/Registry-V4/mm10-cCREs.TF.bed", + + "HumanDNaseSignalMatrix": "https://www.encodeproject.org/files/ENCFF434ORT/@@download/ENCFF434ORT.txt.gz", + "HumanPromoterSignalMatrix": "https://www.encodeproject.org/files/ENCFF015SIE/@@download/ENCFF015SIE.txt.gz", + "HumanEnhancerSignalMatrix": "https://www.encodeproject.org/files/ENCFF701TDA/@@download/ENCFF701TDA.txt.gz", + "HumanCTCFSignalMatrix": "https://www.encodeproject.org/files/ENCFF590RSL/@@download/ENCFF590RSL.txt.gz", + + "HumanDNaseZScoreMatrix": "https://www.encodeproject.org/files/ENCFF833CSA/@@download/ENCFF833CSA.txt.gz", + "HumanPromoterZScoreMatrix": "https://www.encodeproject.org/files/ENCFF508PCP/@@download/ENCFF508PCP.txt.gz", + "HumanEnhancerZScoreMatrix": "https://www.encodeproject.org/files/ENCFF560UZM/@@download/ENCFF560UZM.txt.gz", + "HumanCTCFZScoreMatrix": "https://www.encodeproject.org/files/ENCFF392IXG/@@download/ENCFF392IXG.txt.gz", + + "MouseDNaseSignalMatrix": "https://www.encodeproject.org/files/ENCFF313KGL/@@download/ENCFF313KGL.txt.gz", + "MousePromoterSignalMatrix": "https://www.encodeproject.org/files/ENCFF129EIW/@@download/ENCFF129EIW.txt.gz", + "MouseEnhancerSignalMatrix": "https://www.encodeproject.org/files/ENCFF745TSW/@@download/ENCFF745TSW.txt.gz", + "MouseCTCFSignalMatrix": "https://www.encodeproject.org/files/ENCFF784AEB/@@download/ENCFF784AEB.txt.gz", + + "MouseDNaseZScoreMatrix": "https://www.encodeproject.org/files/ENCFF397LSK/@@download/ENCFF397LSK.txt.gz", + "MousePromoterZScoreMatrix": "https://www.encodeproject.org/files/ENCFF754PUU/@@download/ENCFF754PUU.txt.gz", + "MouseEnhancerZScoreMatrix": "https://www.encodeproject.org/files/ENCFF816ISW/@@download/ENCFF816ISW.txt.gz", + "MouseCTCFZScoreMatrix": "https://www.encodeproject.org/files/ENCFF101BYE/@@download/ENCFF101BYE.txt.gz" } } diff --git a/screen2.0/yarn.lock b/screen2.0/yarn.lock index f8cc1549..6dd96bb9 100644 --- a/screen2.0/yarn.lock +++ b/screen2.0/yarn.lock @@ -8151,4 +8151,4 @@ __metadata: resolution: "zod@npm:3.21.4" checksum: f185ba87342ff16f7a06686767c2b2a7af41110c7edf7c1974095d8db7a73792696bcb4a00853de0d2edeb34a5b2ea6a55871bc864227dace682a0a28de33e1f languageName: node - linkType: hard + linkType: hard \ No newline at end of file