From fce91d9aed6df02046dc4b4780349c16bca08606 Mon Sep 17 00:00:00 2001 From: Jonathan Fisher Date: Tue, 25 Jul 2023 12:07:22 -0400 Subject: [PATCH 01/29] Quick Start Downloads --- screen2.0/src/app/downloads/data-matrices.tsx | 26 ++++ .../src/app/downloads/detailed-elements.tsx | 26 ++++ screen2.0/src/app/downloads/page.tsx | 42 +++++- screen2.0/src/app/downloads/quick-start.tsx | 128 ++++++++++++++++++ screen2.0/src/common/lib/filter-helpers.ts | 2 +- screen2.0/src/config.json | 11 ++ 6 files changed, 232 insertions(+), 3 deletions(-) create mode 100644 screen2.0/src/app/downloads/data-matrices.tsx create mode 100644 screen2.0/src/app/downloads/detailed-elements.tsx create mode 100644 screen2.0/src/app/downloads/quick-start.tsx 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..48599c04 --- /dev/null +++ b/screen2.0/src/app/downloads/data-matrices.tsx @@ -0,0 +1,26 @@ +import { Typography } from "@mui/material"; +import { Box } from "@mui/system"; + +interface TabPanelProps { + children?: React.ReactNode; + value: number; +} + +export function DataMatrices(props: TabPanelProps) { + const { children, value, ...other } = props; + + return ( +
+ {value === 2 && + + Data Matrices + + } +
+ ); +} \ 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..615a6dcb --- /dev/null +++ b/screen2.0/src/app/downloads/detailed-elements.tsx @@ -0,0 +1,26 @@ +import { Typography } from "@mui/material"; +import { Box } from "@mui/system"; + +interface TabPanelProps { + children?: React.ReactNode; + value: number; +} + +export function DetailedElements(props: TabPanelProps) { + const { children, value, ...other } = props; + + return ( +
+ {value === 1 && + + Detailed Elements + + } +
+ ); +} \ No newline at end of file diff --git a/screen2.0/src/app/downloads/page.tsx b/screen2.0/src/app/downloads/page.tsx index dcab9ce2..004d43fb 100644 --- a/screen2.0/src/app/downloads/page.tsx +++ b/screen2.0/src/app/downloads/page.tsx @@ -1,10 +1,48 @@ "use client" -import { Typography } from "@mui/material" + +import * as React from 'react'; +import { + Typography, + Tabs, + Tab, + Box +} 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'; + +function a11yProps(index: number) { + return { + id: `simple-tab-${index}`, + 'aria-controls': `simple-tabpanel-${index}`, + }; +} + export default function Downloads() { + const [value, setValue] = React.useState(0); + + const handleChange = (event: React.SyntheticEvent, newValue: number) => { + setValue(newValue); + }; + 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..17ce8dea --- /dev/null +++ b/screen2.0/src/app/downloads/quick-start.tsx @@ -0,0 +1,128 @@ +import { + Typography, + Button, + Stack, + OutlinedInput, + InputAdornment, + IconButton +} from "@mui/material"; + +import SearchIcon from '@mui/icons-material/Search'; + +import Grid2 from "@mui/material/Unstable_Grid2/Grid2" +import Downloads from "./page"; +import Config from "../../config.json" + +interface TabPanelProps { + children?: React.ReactNode; + value: number; +} + +export function QuickStart(props: TabPanelProps) { + const { children, value, ...other } = props; + + return ( +
+ {value === 0 && + + + + Human + + + + + + + } + /> + + + + + + } + /> + + + + + + } + /> + + + + + + Mouse + + + + + + + } + /> + + + + + + } + /> + + + + + + } + /> + + + + } +
+ ); +} \ No newline at end of file diff --git a/screen2.0/src/common/lib/filter-helpers.ts b/screen2.0/src/common/lib/filter-helpers.ts index 63b633c6..f56c58f9 100644 --- a/screen2.0/src/common/lib/filter-helpers.ts +++ b/screen2.0/src/common/lib/filter-helpers.ts @@ -184,7 +184,7 @@ export function filterBiosamples(biosamples: UnfilteredBiosampleData, Tissue: bo 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/config.json b/screen2.0/src/config.json index d2558e65..59ee00ba 100644 --- a/screen2.0/src/config.json +++ b/screen2.0/src/config.json @@ -29,5 +29,16 @@ "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-PLS.bed", + "HumanEnhancers": "https://downloads.wenglab.org/Registry-V4/GRCh38-ELS.bed", + "HumanCTCF": "https://downloads.wenglab.org/Registry-V4/GRCh38-CTCF.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-PLS.bed", + "MouseEnhancers": "https://downloads.wenglab.org/Registry-V4/mm10-ELS.bed", + "MouseCTCF": "https://downloads.wenglab.org/Registry-V4/mm10-CTCF.bed" } } From e3988b64ed473dea24b9a27d793e603bdc858f0e Mon Sep 17 00:00:00 2001 From: Jonathan Fisher Date: Wed, 26 Jul 2023 11:58:31 -0400 Subject: [PATCH 02/29] Fetch Data, Icon --- screen2.0/src/app/downloads/downloads.tsx | 53 ++++++++++++++++++++++ screen2.0/src/app/downloads/page.tsx | 44 ++---------------- screen2.0/src/app/icon.png | Bin 0 -> 31424 bytes screen2.0/src/app/search/page.tsx | 2 +- screen2.0/src/common/lib/queries.ts | 50 +++++++++++++++++++- 5 files changed, 108 insertions(+), 41 deletions(-) create mode 100644 screen2.0/src/app/downloads/downloads.tsx create mode 100644 screen2.0/src/app/icon.png diff --git a/screen2.0/src/app/downloads/downloads.tsx b/screen2.0/src/app/downloads/downloads.tsx new file mode 100644 index 00000000..7e975152 --- /dev/null +++ b/screen2.0/src/app/downloads/downloads.tsx @@ -0,0 +1,53 @@ +"use client" + +import * as React from 'react'; +import { + Typography, + Tabs, + Tab, + Box +} 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 } from 'react'; + +function a11yProps(index: number) { + return { + id: `simple-tab-${index}`, + 'aria-controls': `simple-tabpanel-${index}`, + }; +} + +export default function DownloadsPage(props: {biosamples: any}) { + const [value, setValue] = React.useState(0); + + const handleChange = (event: React.SyntheticEvent, newValue: number) => { + setValue(newValue); + }; + + const biosamples = props.biosamples.data + + const h3k4me3H = useMemo(() => ((biosamples && biosamples.human && biosamples.human.biosamples) || []).filter((x) => x.h3k4me3 !== null), [biosamples]) + + console.log(biosamples) + console.log(h3k4me3H) + + return ( + + + + + + + + + + + + + ) +} diff --git a/screen2.0/src/app/downloads/page.tsx b/screen2.0/src/app/downloads/page.tsx index 004d43fb..49423fbe 100644 --- a/screen2.0/src/app/downloads/page.tsx +++ b/screen2.0/src/app/downloads/page.tsx @@ -1,48 +1,14 @@ -"use client" - import * as React from 'react'; -import { - Typography, - Tabs, - Tab, - Box -} 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'; - -function a11yProps(index: number) { - return { - id: `simple-tab-${index}`, - 'aria-controls': `simple-tabpanel-${index}`, - }; -} - +import DownloadsPage from './downloads'; +import { biosampleQuery } from '../../common/lib/queries'; -export default function Downloads() { - const [value, setValue] = React.useState(0); - const handleChange = (event: React.SyntheticEvent, newValue: number) => { - setValue(newValue); - }; +export default async function Downloads() { + const biosamples: any = await biosampleQuery() return (
- - - - - - - - - - - - +
) } diff --git a/screen2.0/src/app/icon.png b/screen2.0/src/app/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f2b71cbbdb9c7b4f619ef97f5f8db82bd5d70f82 GIT binary patch literal 31424 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 literal 0 HcmV?d00001 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/common/lib/queries.ts b/screen2.0/src/common/lib/queries.ts index ef1a4406..08645581 100644 --- a/screen2.0/src/common/lib/queries.ts +++ b/screen2.0/src/common/lib/queries.ts @@ -189,6 +189,39 @@ const cCRE_QUERY_WITH_BIOSAMPLES = gql` } } ` + +const BIOSAMPLE_QUERY = gql` + query biosamples { + human: ccREBiosampleQuery(assembly: "grch38") { + biosamples { + name + 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 + 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") + } + } + } +` + + function cCRE_QUERY_VARIABLES(assembly: string, chromosome: string, start: number, end: number, biosample?: string) { return { uuid: null, @@ -223,7 +256,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,6 +273,21 @@ export default async function MainQuery(assembly: string, chromosome: string, st } } +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 const TOP_TISSUES = gql` query q($accession: [String!], $assembly: String!) { ccREBiosampleQuery(assembly: $assembly) { From 5229ff7f457063dcff865512aa53f473dda1bf40 Mon Sep 17 00:00:00 2001 From: Jonathan Fisher Date: Wed, 26 Jul 2023 16:54:03 -0400 Subject: [PATCH 03/29] Biosample autocompletes filled --- screen2.0/src/app/downloads/downloads.tsx | 29 +-- screen2.0/src/app/downloads/quick-start.tsx | 247 ++++++++++++++------ screen2.0/src/app/search/types.ts | 13 ++ 3 files changed, 194 insertions(+), 95 deletions(-) diff --git a/screen2.0/src/app/downloads/downloads.tsx b/screen2.0/src/app/downloads/downloads.tsx index 7e975152..2014b3c0 100644 --- a/screen2.0/src/app/downloads/downloads.tsx +++ b/screen2.0/src/app/downloads/downloads.tsx @@ -5,7 +5,7 @@ import { Typography, Tabs, Tab, - Box + Box, } from "@mui/material" import Grid2 from "@mui/material/Unstable_Grid2/Grid2" @@ -15,12 +15,12 @@ import { DetailedElements } from './detailed-elements'; import { DataMatrices } from './data-matrices'; import { useMemo } from 'react'; -function a11yProps(index: number) { - return { - id: `simple-tab-${index}`, - 'aria-controls': `simple-tabpanel-${index}`, - }; -} +// function a11yProps(index: number) { +// return { +// id: `simple-tab-${index}`, +// 'aria-controls': `simple-tabpanel-${index}`, +// }; +// } export default function DownloadsPage(props: {biosamples: any}) { const [value, setValue] = React.useState(0); @@ -29,23 +29,16 @@ export default function DownloadsPage(props: {biosamples: any}) { setValue(newValue); }; - const biosamples = props.biosamples.data - - const h3k4me3H = useMemo(() => ((biosamples && biosamples.human && biosamples.human.biosamples) || []).filter((x) => x.h3k4me3 !== null), [biosamples]) - - console.log(biosamples) - console.log(h3k4me3H) - return ( - - - + + + - + diff --git a/screen2.0/src/app/downloads/quick-start.tsx b/screen2.0/src/app/downloads/quick-start.tsx index 17ce8dea..942fd001 100644 --- a/screen2.0/src/app/downloads/quick-start.tsx +++ b/screen2.0/src/app/downloads/quick-start.tsx @@ -4,7 +4,9 @@ import { Stack, OutlinedInput, InputAdornment, - IconButton + IconButton, + Autocomplete, + TextField } from "@mui/material"; import SearchIcon from '@mui/icons-material/Search'; @@ -12,113 +14,204 @@ import SearchIcon from '@mui/icons-material/Search'; import Grid2 from "@mui/material/Unstable_Grid2/Grid2" import Downloads from "./page"; import Config from "../../config.json" +import { useMemo } from "react"; + +import { Biosample } from "../search/types"; interface TabPanelProps { children?: React.ReactNode; value: number; + biosamples: any; +} + +const top100Films = [ + { label: 'The Shawshank Redemption', year: 1994 }, + { label: 'The Godfather', year: 1972 }, + { label: 'The Godfather: Part II', year: 1974 }, + { label: 'The Dark Knight', year: 2008 }, + { label: '12 Angry Men', year: 1957 }, + { label: "Schindler's List", year: 1993 }, + { label: 'Pulp Fiction', year: 1994 }, + { + label: 'The Lord of the Rings: The Return of the King', + year: 2003, + }, + { label: 'The Good, the Bad and the Ugly', year: 1966 }, + { label: 'Fight Club', year: 1999 }, + { + label: 'The Lord of the Rings: The Fellowship of the Ring', + year: 2001, + }, + { + label: 'Star Wars: Episode V - The Empire Strikes Back', + year: 1980, + }, + { label: 'Forrest Gump', year: 1994 }, + { label: 'Inception', year: 2010 }, + { + label: 'The Lord of the Rings: The Two Towers', + year: 2002, + }, + { label: "One Flew Over the Cuckoo's Nest", year: 1975 }, + { label: 'Goodfellas', year: 1990 }, + { label: 'The Matrix', year: 1999 }, + { label: 'Seven Samurai', year: 1954 }, + { + label: 'Star Wars: Episode IV - A New Hope', + year: 1977, + }, + { label: 'City of God', year: 2002 }, + { label: 'Se7en', year: 1995 }, + { label: 'The Silence of the Lambs', year: 1991 }, + { label: "It's a Wonderful Life", year: 1946 }, + { label: 'Life Is Beautiful', year: 1997 }, + { label: 'The Usual Suspects', year: 1995 }, + { label: 'Léon: The Professional', year: 1994 }, + { label: 'Spirited Away', year: 2001 }, + { label: 'Saving Private Ryan', year: 1998 }, + { label: 'Once Upon a Time in the West', year: 1968 }, + { label: 'American History X', year: 1998 }, + { label: 'Interstellar', year: 2014 }, + { label: 'Casablanca', year: 1942 }, + { label: 'City Lights', year: 1931 }, + { label: 'Psycho', year: 1960 }, + { label: 'The Green Mile', year: 1999 }, + { label: 'The Intouchables', year: 2011 }, + { label: 'Modern Times', year: 1936 }, + { label: 'Raiders of the Lost Ark', year: 1981 }, + { label: 'Rear Window', year: 1954 }, + { label: 'The Pianist', year: 2002 }, + { label: 'The Departed', year: 2006 }, + { label: 'Terminator 2: Judgment Day', year: 1991 }, + { label: 'Back to the Future', year: 1985 }, + { label: 'Whiplash', year: 2014 }, + { label: 'Gladiator', year: 2000 }, + { label: 'Memento', year: 2000 }, + { label: 'The Prestige', year: 2006 }, + { label: 'The Lion King', year: 1994 }, + { label: 'Apocalypse Now', year: 1979 }, + { label: 'Alien', year: 1979 }, + { label: 'Sunset Boulevard', year: 1950 }, + { + label: 'Dr. Strangelove or: How I Learned to Stop Worrying and Love the Bomb', + year: 1964, + }, + { label: 'The Great Dictator', year: 1940 }, + { label: 'Cinema Paradiso', year: 1988 }, + { label: 'The Lives of Others', year: 2006 }, + { label: 'Grave of the Fireflies', year: 1988 }, + { label: 'Paths of Glory', year: 1957 }, + { label: 'Django Unchained', year: 2012 }, + { label: 'The Shining', year: 1980 }, + { label: 'WALL·E', year: 2008 }, + { label: 'American Beauty', year: 1999 }, + { label: 'The Dark Knight Rises', year: 2012 }, + { label: 'Princess Mononoke', year: 1997 }, + { label: 'Aliens', year: 1986 }, + { label: 'Oldboy', year: 2003 }, + { label: 'Once Upon a Time in America', year: 1984 }, + { label: 'Witness for the Prosecution', year: 1957 }, + { label: 'Das Boot', year: 1981 }, + { label: 'Citizen Kane', year: 1941 }, + { label: 'North by Northwest', year: 1959 }, + { label: 'Vertigo', year: 1958 }, + { + label: 'Star Wars: Episode VI - Return of the Jedi', + year: 1983, + }, + { label: 'Reservoir Dogs', year: 1992 }, + { label: 'Braveheart', year: 1995 }, + { label: 'M', year: 1931 }, + { label: 'Requiem for a Dream', year: 2000 }, + { label: 'Amélie', year: 2001 }, + { label: 'A Clockwork Orange', year: 1971 }, + { label: 'Like Stars on Earth', year: 2007 }, + { label: 'Taxi Driver', year: 1976 }, + { label: 'Lawrence of Arabia', year: 1962 }, + { label: 'Double Indemnity', year: 1944 }, + { + label: 'Eternal Sunshine of the Spotless Mind', + year: 2004, + }, + { label: 'Amadeus', year: 1984 }, + { label: 'To Kill a Mockingbird', year: 1962 }, + { label: 'Toy Story 3', year: 2010 }, + { label: 'Logan', year: 2017 }, + { label: 'Full Metal Jacket', year: 1987 }, + { label: 'Dangal', year: 2016 }, + { label: 'The Sting', year: 1973 }, + { label: '2001: A Space Odyssey', year: 1968 }, + { label: "Singin' in the Rain", year: 1952 }, + { label: 'Toy Story', year: 1995 }, + { label: 'Bicycle Thieves', year: 1948 }, + { label: 'The Kid', year: 1921 }, + { label: 'Inglourious Basterds', year: 2009 }, + { label: 'Snatch', year: 2000 }, + { label: '3 Idiots', year: 2009 }, + { label: 'Monty Python and the Holy Grail', year: 1975 }, +]; + +//So I don't forget, I think that using PascalCase is useful when defining JSX-returning functions since JSX elements are PascalCase +function ComboBox(options: Biosample[], label: string, mode: "promoter" | "enhancer" | "ctcf") { + return ( + } + //Replace underlines with space using regex + getOptionLabel={(biosample: Biosample) => biosample.name.replace(/_/g, " ") + " — Exp ID: " + (((mode == "promoter") && biosample.h3k4me3) || ((mode == "enhancer") && biosample.h3k27ac) || ((mode === "ctcf") && biosample.ctcf))} + blurOnSelect + /> + ); } export function QuickStart(props: TabPanelProps) { - const { children, value, ...other } = props; + const biosamples = props.biosamples.data + + const humanPromoters: Biosample[] = useMemo(() => ((biosamples && biosamples.human && biosamples.human.biosamples) || []).filter((x) => x.h3k4me3 !== null), [biosamples]) + const humanEnhancers: Biosample[] = useMemo(() => ((biosamples && biosamples.human && biosamples.human.biosamples) || []).filter((x) => x.h3k27ac !== null), [biosamples]) + const humanCTCF: Biosample[] = useMemo(() => ((biosamples && biosamples.human && biosamples.human.biosamples) || []).filter((x) => x.ctcf !== null), [biosamples]) + const mousePromoters: Biosample[] = useMemo(() => ((biosamples && biosamples.mouse && biosamples.mouse.biosamples) || []).filter((x) => x.h3k4me3 !== null), [biosamples]) + const mouseEnhancers: Biosample[] = useMemo(() => ((biosamples && biosamples.mouse && biosamples.mouse.biosamples) || []).filter((x) => x.h3k27ac !== null), [biosamples]) + const mouseCTCF: Biosample[] = useMemo(() => ((biosamples && biosamples.mouse && biosamples.mouse.biosamples) || []).filter((x) => x.ctcf !== null), [biosamples]) + + console.log(biosamples) + console.log(humanPromoters) return (
- {value === 0 && + {props.value === 0 && Human - - - - - } - /> + {ComboBox(humanPromoters, "Search for a Biosample", "promoter")} - - - - - } - /> + {ComboBox(humanEnhancers, "Search for a Biosample", "enhancer")} - - - - - } - /> + {ComboBox(humanCTCF, "Search for a Biosample", "ctcf")} - + Mouse - - - - - } - /> + {ComboBox(mousePromoters, "Search for a Biosample", "promoter")} - - - - - } - /> + {ComboBox(mouseEnhancers, "Search for a Biosample", "enhancer")} - - - - - } - /> + {ComboBox(mouseCTCF, "Search for a Biosample", "ctcf")} diff --git a/screen2.0/src/app/search/types.ts b/screen2.0/src/app/search/types.ts index 1847955f..790374ab 100644 --- a/screen2.0/src/app/search/types.ts +++ b/screen2.0/src/app/search/types.ts @@ -110,3 +110,16 @@ export type FilteredBiosampleData = [ } }[] ][] + +//What is a good name for this? +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 +} \ No newline at end of file From 05183f43dffb8b6f4b8f2772258131c67842a868 Mon Sep 17 00:00:00 2001 From: Jonathan Fisher Date: Thu, 27 Jul 2023 12:31:31 -0400 Subject: [PATCH 04/29] Biosample downloads, maybe bugged --- screen2.0/src/app/downloads/quick-start.tsx | 219 ++++++-------------- 1 file changed, 68 insertions(+), 151 deletions(-) diff --git a/screen2.0/src/app/downloads/quick-start.tsx b/screen2.0/src/app/downloads/quick-start.tsx index 942fd001..d44fdaed 100644 --- a/screen2.0/src/app/downloads/quick-start.tsx +++ b/screen2.0/src/app/downloads/quick-start.tsx @@ -14,7 +14,7 @@ import SearchIcon from '@mui/icons-material/Search'; import Grid2 from "@mui/material/Unstable_Grid2/Grid2" import Downloads from "./page"; import Config from "../../config.json" -import { useMemo } from "react"; +import { useMemo, useState } from "react"; import { Biosample } from "../search/types"; @@ -24,153 +24,16 @@ interface TabPanelProps { biosamples: any; } -const top100Films = [ - { label: 'The Shawshank Redemption', year: 1994 }, - { label: 'The Godfather', year: 1972 }, - { label: 'The Godfather: Part II', year: 1974 }, - { label: 'The Dark Knight', year: 2008 }, - { label: '12 Angry Men', year: 1957 }, - { label: "Schindler's List", year: 1993 }, - { label: 'Pulp Fiction', year: 1994 }, - { - label: 'The Lord of the Rings: The Return of the King', - year: 2003, - }, - { label: 'The Good, the Bad and the Ugly', year: 1966 }, - { label: 'Fight Club', year: 1999 }, - { - label: 'The Lord of the Rings: The Fellowship of the Ring', - year: 2001, - }, - { - label: 'Star Wars: Episode V - The Empire Strikes Back', - year: 1980, - }, - { label: 'Forrest Gump', year: 1994 }, - { label: 'Inception', year: 2010 }, - { - label: 'The Lord of the Rings: The Two Towers', - year: 2002, - }, - { label: "One Flew Over the Cuckoo's Nest", year: 1975 }, - { label: 'Goodfellas', year: 1990 }, - { label: 'The Matrix', year: 1999 }, - { label: 'Seven Samurai', year: 1954 }, - { - label: 'Star Wars: Episode IV - A New Hope', - year: 1977, - }, - { label: 'City of God', year: 2002 }, - { label: 'Se7en', year: 1995 }, - { label: 'The Silence of the Lambs', year: 1991 }, - { label: "It's a Wonderful Life", year: 1946 }, - { label: 'Life Is Beautiful', year: 1997 }, - { label: 'The Usual Suspects', year: 1995 }, - { label: 'Léon: The Professional', year: 1994 }, - { label: 'Spirited Away', year: 2001 }, - { label: 'Saving Private Ryan', year: 1998 }, - { label: 'Once Upon a Time in the West', year: 1968 }, - { label: 'American History X', year: 1998 }, - { label: 'Interstellar', year: 2014 }, - { label: 'Casablanca', year: 1942 }, - { label: 'City Lights', year: 1931 }, - { label: 'Psycho', year: 1960 }, - { label: 'The Green Mile', year: 1999 }, - { label: 'The Intouchables', year: 2011 }, - { label: 'Modern Times', year: 1936 }, - { label: 'Raiders of the Lost Ark', year: 1981 }, - { label: 'Rear Window', year: 1954 }, - { label: 'The Pianist', year: 2002 }, - { label: 'The Departed', year: 2006 }, - { label: 'Terminator 2: Judgment Day', year: 1991 }, - { label: 'Back to the Future', year: 1985 }, - { label: 'Whiplash', year: 2014 }, - { label: 'Gladiator', year: 2000 }, - { label: 'Memento', year: 2000 }, - { label: 'The Prestige', year: 2006 }, - { label: 'The Lion King', year: 1994 }, - { label: 'Apocalypse Now', year: 1979 }, - { label: 'Alien', year: 1979 }, - { label: 'Sunset Boulevard', year: 1950 }, - { - label: 'Dr. Strangelove or: How I Learned to Stop Worrying and Love the Bomb', - year: 1964, - }, - { label: 'The Great Dictator', year: 1940 }, - { label: 'Cinema Paradiso', year: 1988 }, - { label: 'The Lives of Others', year: 2006 }, - { label: 'Grave of the Fireflies', year: 1988 }, - { label: 'Paths of Glory', year: 1957 }, - { label: 'Django Unchained', year: 2012 }, - { label: 'The Shining', year: 1980 }, - { label: 'WALL·E', year: 2008 }, - { label: 'American Beauty', year: 1999 }, - { label: 'The Dark Knight Rises', year: 2012 }, - { label: 'Princess Mononoke', year: 1997 }, - { label: 'Aliens', year: 1986 }, - { label: 'Oldboy', year: 2003 }, - { label: 'Once Upon a Time in America', year: 1984 }, - { label: 'Witness for the Prosecution', year: 1957 }, - { label: 'Das Boot', year: 1981 }, - { label: 'Citizen Kane', year: 1941 }, - { label: 'North by Northwest', year: 1959 }, - { label: 'Vertigo', year: 1958 }, - { - label: 'Star Wars: Episode VI - Return of the Jedi', - year: 1983, - }, - { label: 'Reservoir Dogs', year: 1992 }, - { label: 'Braveheart', year: 1995 }, - { label: 'M', year: 1931 }, - { label: 'Requiem for a Dream', year: 2000 }, - { label: 'Amélie', year: 2001 }, - { label: 'A Clockwork Orange', year: 1971 }, - { label: 'Like Stars on Earth', year: 2007 }, - { label: 'Taxi Driver', year: 1976 }, - { label: 'Lawrence of Arabia', year: 1962 }, - { label: 'Double Indemnity', year: 1944 }, - { - label: 'Eternal Sunshine of the Spotless Mind', - year: 2004, - }, - { label: 'Amadeus', year: 1984 }, - { label: 'To Kill a Mockingbird', year: 1962 }, - { label: 'Toy Story 3', year: 2010 }, - { label: 'Logan', year: 2017 }, - { label: 'Full Metal Jacket', year: 1987 }, - { label: 'Dangal', year: 2016 }, - { label: 'The Sting', year: 1973 }, - { label: '2001: A Space Odyssey', year: 1968 }, - { label: "Singin' in the Rain", year: 1952 }, - { label: 'Toy Story', year: 1995 }, - { label: 'Bicycle Thieves', year: 1948 }, - { label: 'The Kid', year: 1921 }, - { label: 'Inglourious Basterds', year: 2009 }, - { label: 'Snatch', year: 2000 }, - { label: '3 Idiots', year: 2009 }, - { label: 'Monty Python and the Holy Grail', year: 1975 }, -]; - -//So I don't forget, I think that using PascalCase is useful when defining JSX-returning functions since JSX elements are PascalCase -function ComboBox(options: Biosample[], label: string, mode: "promoter" | "enhancer" | "ctcf") { - return ( - } - //Replace underlines with space using regex - getOptionLabel={(biosample: Biosample) => biosample.name.replace(/_/g, " ") + " — Exp ID: " + (((mode == "promoter") && biosample.h3k4me3) || ((mode == "enhancer") && biosample.h3k27ac) || ((mode === "ctcf") && biosample.ctcf))} - blurOnSelect - /> - ); -} - export function QuickStart(props: TabPanelProps) { const biosamples = props.biosamples.data + const [hPromoterSelected, setHPromoterSelected] = useState(null) + const [hEnhancerSelected, setHEnhancerSelected] = useState(null) + const [hCTCFSelected, setHCTCFSelected] = useState(null) + const [mPromoterSelected, setMPromoterSelected] = useState(null) + const [mEnhancerSelected, setMEnhancerSelected] = useState(null) + const [mCTCFSelected, setMCTCFSelected] = useState(null) + const humanPromoters: Biosample[] = useMemo(() => ((biosamples && biosamples.human && biosamples.human.biosamples) || []).filter((x) => x.h3k4me3 !== null), [biosamples]) const humanEnhancers: Biosample[] = useMemo(() => ((biosamples && biosamples.human && biosamples.human.biosamples) || []).filter((x) => x.h3k27ac !== null), [biosamples]) const humanCTCF: Biosample[] = useMemo(() => ((biosamples && biosamples.human && biosamples.human.biosamples) || []).filter((x) => x.ctcf !== null), [biosamples]) @@ -181,6 +44,54 @@ export function QuickStart(props: TabPanelProps) { console.log(biosamples) console.log(humanPromoters) + function generateBiosampleURL(selected: Biosample){ + const r = [selected.dnase_signal, selected.h3k4me3_signal, selected.h3k27ac_signal, selected.ctcf_signal].filter((x) => !!x) + return `https://downloads.wenglab.org/Registry-V4/${r.join("_")}.bed` + } + + //So I don't forget, I think that using PascalCase is useful when defining JSX-returning functions since JSX elements are PascalCase + function ComboBox(options: Biosample[], label: string, mode: "H-promoter" | "H-enhancer" | "H-ctcf" | "M-promoter" | "M-enhancer" | "M-ctcf") { + return ( + } + //Replace underlines with space using regex. Can the logic be simplified it's kinda gross looking with all the parentheses? If not make separate function + getOptionLabel={(biosample: Biosample) => biosample.name.replace(/_/g, " ") + " — Exp ID: " + ((((mode === "H-promoter") || (mode === "M-promoter")) && biosample.h3k4me3) || (((mode === "H-enhancer") || (mode === "M-enhancer")) && biosample.h3k27ac) || (((mode === "H-ctcf") || (mode === "M-ctcf")) && biosample.ctcf))} + blurOnSelect + onChange={(event, value: any) => { + switch (mode) { + case "H-promoter": + setHPromoterSelected(value) + break + case "H-enhancer": + setHEnhancerSelected(value) + break + case "H-ctcf": + setHCTCFSelected(value) + break + case "M-promoter": + setMPromoterSelected(value) + break + case "M-enhancer": + setMEnhancerSelected(value) + break + case "M-ctcf": + setMCTCFSelected(value) + break + default: + console.log("Something went wrong in quick-start.tsx in ComboBox") + break + } + + }} + /> + ); + } + return (
Human - {ComboBox(humanPromoters, "Search for a Biosample", "promoter")} + {ComboBox(humanPromoters, "Search for a Biosample", "H-promoter")} + {hPromoterSelected && } - {ComboBox(humanEnhancers, "Search for a Biosample", "enhancer")} + {ComboBox(humanEnhancers, "Search for a Biosample", "H-enhancer")} + {hEnhancerSelected && } - {ComboBox(humanCTCF, "Search for a Biosample", "ctcf")} + {ComboBox(humanCTCF, "Search for a Biosample", "H-ctcf")} + {hCTCFSelected && } @@ -207,11 +121,14 @@ export function QuickStart(props: TabPanelProps) { Mouse - {ComboBox(mousePromoters, "Search for a Biosample", "promoter")} + {ComboBox(mousePromoters, "Search for a Biosample", "M-promoter")} + {mPromoterSelected && } - {ComboBox(mouseEnhancers, "Search for a Biosample", "enhancer")} + {ComboBox(mouseEnhancers, "Search for a Biosample", "M-enhancer")} + {mEnhancerSelected && } - {ComboBox(mouseCTCF, "Search for a Biosample", "ctcf")} + {ComboBox(mouseCTCF, "Search for a Biosample", "M-ctcf")} + {mCTCFSelected && } From 81e58a5ba0b5a92100c87b94535165a721422d08 Mon Sep 17 00:00:00 2001 From: Jonathan Fisher Date: Thu, 27 Jul 2023 23:16:22 -0400 Subject: [PATCH 05/29] Biosample downloads working --- screen2.0/src/app/downloads/downloads.tsx | 33 +-- screen2.0/src/app/downloads/quick-start.tsx | 223 +++++++++++++------- 2 files changed, 171 insertions(+), 85 deletions(-) diff --git a/screen2.0/src/app/downloads/downloads.tsx b/screen2.0/src/app/downloads/downloads.tsx index 2014b3c0..7d272ab8 100644 --- a/screen2.0/src/app/downloads/downloads.tsx +++ b/screen2.0/src/app/downloads/downloads.tsx @@ -6,6 +6,7 @@ import { Tabs, Tab, Box, + Container, } from "@mui/material" import Grid2 from "@mui/material/Unstable_Grid2/Grid2" @@ -22,7 +23,7 @@ import { useMemo } from 'react'; // }; // } -export default function DownloadsPage(props: {biosamples: any}) { +export default function DownloadsPage(props: { biosamples: any }) { const [value, setValue] = React.useState(0); const handleChange = (event: React.SyntheticEvent, newValue: number) => { @@ -30,17 +31,23 @@ export default function DownloadsPage(props: {biosamples: any}) { }; return ( - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + ) } diff --git a/screen2.0/src/app/downloads/quick-start.tsx b/screen2.0/src/app/downloads/quick-start.tsx index d44fdaed..465ee684 100644 --- a/screen2.0/src/app/downloads/quick-start.tsx +++ b/screen2.0/src/app/downloads/quick-start.tsx @@ -14,7 +14,7 @@ import SearchIcon from '@mui/icons-material/Search'; import Grid2 from "@mui/material/Unstable_Grid2/Grid2" import Downloads from "./page"; import Config from "../../config.json" -import { useMemo, useState } from "react"; +import { useEffect, useMemo, useState } from "react"; import { Biosample } from "../search/types"; @@ -27,13 +27,6 @@ interface TabPanelProps { export function QuickStart(props: TabPanelProps) { const biosamples = props.biosamples.data - const [hPromoterSelected, setHPromoterSelected] = useState(null) - const [hEnhancerSelected, setHEnhancerSelected] = useState(null) - const [hCTCFSelected, setHCTCFSelected] = useState(null) - const [mPromoterSelected, setMPromoterSelected] = useState(null) - const [mEnhancerSelected, setMEnhancerSelected] = useState(null) - const [mCTCFSelected, setMCTCFSelected] = useState(null) - const humanPromoters: Biosample[] = useMemo(() => ((biosamples && biosamples.human && biosamples.human.biosamples) || []).filter((x) => x.h3k4me3 !== null), [biosamples]) const humanEnhancers: Biosample[] = useMemo(() => ((biosamples && biosamples.human && biosamples.human.biosamples) || []).filter((x) => x.h3k27ac !== null), [biosamples]) const humanCTCF: Biosample[] = useMemo(() => ((biosamples && biosamples.human && biosamples.human.biosamples) || []).filter((x) => x.ctcf !== null), [biosamples]) @@ -41,54 +34,99 @@ export function QuickStart(props: TabPanelProps) { const mouseEnhancers: Biosample[] = useMemo(() => ((biosamples && biosamples.mouse && biosamples.mouse.biosamples) || []).filter((x) => x.h3k27ac !== null), [biosamples]) const mouseCTCF: Biosample[] = useMemo(() => ((biosamples && biosamples.mouse && biosamples.mouse.biosamples) || []).filter((x) => x.ctcf !== null), [biosamples]) - console.log(biosamples) - console.log(humanPromoters) - - function generateBiosampleURL(selected: Biosample){ + function generateBiosampleURL(selected: Biosample): URL { const r = [selected.dnase_signal, selected.h3k4me3_signal, selected.h3k27ac_signal, selected.ctcf_signal].filter((x) => !!x) - return `https://downloads.wenglab.org/Registry-V4/${r.join("_")}.bed` + return new URL(`https://downloads.wenglab.org/Registry-V4/${r.join("_")}.bed`) } //So I don't forget, I think that using PascalCase is useful when defining JSX-returning functions since JSX elements are PascalCase - function ComboBox(options: Biosample[], label: string, mode: "H-promoter" | "H-enhancer" | "H-ctcf" | "M-promoter" | "M-enhancer" | "M-ctcf") { - return ( - } - //Replace underlines with space using regex. Can the logic be simplified it's kinda gross looking with all the parentheses? If not make separate function - getOptionLabel={(biosample: Biosample) => biosample.name.replace(/_/g, " ") + " — Exp ID: " + ((((mode === "H-promoter") || (mode === "M-promoter")) && biosample.h3k4me3) || (((mode === "H-enhancer") || (mode === "M-enhancer")) && biosample.h3k27ac) || (((mode === "H-ctcf") || (mode === "M-ctcf")) && biosample.ctcf))} - blurOnSelect - onChange={(event, value: any) => { - switch (mode) { - case "H-promoter": - setHPromoterSelected(value) - break - case "H-enhancer": - setHEnhancerSelected(value) - break - case "H-ctcf": - setHCTCFSelected(value) - break - case "M-promoter": - setMPromoterSelected(value) - break - case "M-enhancer": - setMEnhancerSelected(value) - break - case "M-ctcf": - setMCTCFSelected(value) - break - default: - console.log("Something went wrong in quick-start.tsx in ComboBox") - break - } + function ComboBox(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) + + //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 + function downloadTSV(text, filename) { + downloadBlob(new Blob([text], { type: "text/plain" }), filename) + } - }} - /> + //Not sure if this is necessary. All I want is to prevent this switch case block from being executed for each line of the file + const stringToMatch: string = useMemo(() => { + switch (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" + } + }, [mode] + ) + + useEffect(() => { + toDownload && + fetch(toDownload) + .then((x) => x.text()) + .then((x) => { + downloadTSV( + x + .split("\n") + .filter((x) => x.includes(stringToMatch)) + .join("\n"), + // `${result.name}.${props.title}.bed` + //Need to customize this file name + "testPromoter.bed" + ) + setToDownload(null) + }) + }, [toDownload]) + + 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 */} + } + //Replace underlines with space using regex. Can the logic be simplified it's kinda gross looking with all the parentheses? If not make separate function. Yes! change to the logic used un the button template string + getOptionLabel={(biosample: Biosample) => biosample.name.replace(/_/g, " ") + " — Exp ID: " + (mode === "H-promoter" || mode === "M-promoter" ? biosample.h3k4me3 : mode === "H-enhancer" || mode === "M-enhancer" ? biosample.h3k27ac : biosample.ctcf)} + blurOnSelect + onChange={(event, value: any) => setSelectedBiosample(value)} + /> + {selectedBiosample && + + } + {toDownload && + Loading... + } + ); } @@ -100,37 +138,78 @@ export function QuickStart(props: TabPanelProps) { > {props.value === 0 && - + {/* Titles */} + + Human + + + Mouse + + {/* All cCREs */} + + All cCREs + + + + + + + + {/* Promoters */} + + Candidate Promoters + + - Human - - + {ComboBox(humanPromoters, "Search for a Biosample", "H-promoter")} - {hPromoterSelected && } - - {ComboBox(humanEnhancers, "Search for a Biosample", "H-enhancer")} - {hEnhancerSelected && } - - {ComboBox(humanCTCF, "Search for a Biosample", "H-ctcf")} - {hCTCFSelected && } - - + - Mouse - - + {ComboBox(mousePromoters, "Search for a Biosample", "M-promoter")} - {mPromoterSelected && } - + + + {/* Enhancers */} + + Candidate Enhancers + + + + + {ComboBox(humanEnhancers, "Search for a Biosample", "H-enhancer")} + + + + + {ComboBox(mouseEnhancers, "Search for a Biosample", "M-enhancer")} - {mEnhancerSelected && } - + + + {/* CTCF-Bound */} + + CTCF-Bound + + + + + {ComboBox(humanCTCF, "Search for a Biosample", "H-ctcf")} + + + + + {ComboBox(mouseCTCF, "Search for a Biosample", "M-ctcf")} - {mCTCFSelected && } + {/* Gene Links */} + + Gene Links + + + + }
From 2480304f34f0c3a62d7ce0a1c58bf5d13adfcacb Mon Sep 17 00:00:00 2001 From: Jonathan Fisher Date: Fri, 28 Jul 2023 10:12:03 -0400 Subject: [PATCH 06/29] Tooltips and named download --- screen2.0/src/app/downloads/downloads.tsx | 18 +- screen2.0/src/app/downloads/quick-start.tsx | 254 +++++++++++--------- 2 files changed, 155 insertions(+), 117 deletions(-) diff --git a/screen2.0/src/app/downloads/downloads.tsx b/screen2.0/src/app/downloads/downloads.tsx index 7d272ab8..df865a9f 100644 --- a/screen2.0/src/app/downloads/downloads.tsx +++ b/screen2.0/src/app/downloads/downloads.tsx @@ -16,12 +16,12 @@ import { DetailedElements } from './detailed-elements'; import { DataMatrices } from './data-matrices'; import { useMemo } from 'react'; -// function a11yProps(index: number) { -// return { -// id: `simple-tab-${index}`, -// 'aria-controls': `simple-tabpanel-${index}`, -// }; -// } +function a11yProps(index: number) { + return { + id: `simple-tab-${index}`, + 'aria-controls': `simple-tabpanel-${index}`, + }; +} export default function DownloadsPage(props: { biosamples: any }) { const [value, setValue] = React.useState(0); @@ -36,9 +36,9 @@ export default function DownloadsPage(props: { biosamples: any }) { - - - + + + diff --git a/screen2.0/src/app/downloads/quick-start.tsx b/screen2.0/src/app/downloads/quick-start.tsx index 465ee684..1c7ec8f1 100644 --- a/screen2.0/src/app/downloads/quick-start.tsx +++ b/screen2.0/src/app/downloads/quick-start.tsx @@ -6,10 +6,11 @@ import { InputAdornment, IconButton, Autocomplete, - TextField + TextField, + Tooltip } from "@mui/material"; -import SearchIcon from '@mui/icons-material/Search'; +import InfoIcon from '@mui/icons-material/Info'; import Grid2 from "@mui/material/Unstable_Grid2/Grid2" import Downloads from "./page"; @@ -24,6 +25,110 @@ interface TabPanelProps { biosamples: any; } +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." + + +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`) +} + +//So I don't forget, I think that using PascalCase is useful when defining JSX-returning functions since JSX elements are PascalCase +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) + + //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 + function downloadTSV(text, filename) { + downloadBlob(new Blob([text], { type: "text/plain" }), filename) + } + + //Not sure if this is necessary to use useMemo. All I want is to prevent this switch case block from being executed for each line of the file + 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"), + // `${result.name}.${props.title}.bed` + //Need to customize this file name + `${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]) + + 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 */} + } + //Replace underlines with space using regex. Can the logic be simplified it's kinda gross looking with all the parentheses? If not make separate function. Yes! change to the logic used un the button template string + 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)} + /> + {selectedBiosample && + + } + {toDownload && + Loading... + } + + ); +} + export function QuickStart(props: TabPanelProps) { const biosamples = props.biosamples.data @@ -34,102 +139,6 @@ export function QuickStart(props: TabPanelProps) { const mouseEnhancers: Biosample[] = useMemo(() => ((biosamples && biosamples.mouse && biosamples.mouse.biosamples) || []).filter((x) => x.h3k27ac !== null), [biosamples]) const mouseCTCF: Biosample[] = useMemo(() => ((biosamples && biosamples.mouse && biosamples.mouse.biosamples) || []).filter((x) => x.ctcf !== null), [biosamples]) - 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`) - } - - //So I don't forget, I think that using PascalCase is useful when defining JSX-returning functions since JSX elements are PascalCase - function ComboBox(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) - - //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 - function downloadTSV(text, filename) { - downloadBlob(new Blob([text], { type: "text/plain" }), filename) - } - - //Not sure if this is necessary. All I want is to prevent this switch case block from being executed for each line of the file - const stringToMatch: string = useMemo(() => { - switch (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" - } - }, [mode] - ) - - useEffect(() => { - toDownload && - fetch(toDownload) - .then((x) => x.text()) - .then((x) => { - downloadTSV( - x - .split("\n") - .filter((x) => x.includes(stringToMatch)) - .join("\n"), - // `${result.name}.${props.title}.bed` - //Need to customize this file name - "testPromoter.bed" - ) - setToDownload(null) - }) - }, [toDownload]) - - 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 */} - } - //Replace underlines with space using regex. Can the logic be simplified it's kinda gross looking with all the parentheses? If not make separate function. Yes! change to the logic used un the button template string - getOptionLabel={(biosample: Biosample) => biosample.name.replace(/_/g, " ") + " — Exp ID: " + (mode === "H-promoter" || mode === "M-promoter" ? biosample.h3k4me3 : mode === "H-enhancer" || mode === "M-enhancer" ? biosample.h3k27ac : biosample.ctcf)} - blurOnSelect - onChange={(event, value: any) => setSelectedBiosample(value)} - /> - {selectedBiosample && - - } - {toDownload && - Loading... - } - - ); - } - return (
All cCREs + @@ -157,55 +167,83 @@ export function QuickStart(props: TabPanelProps) { {/* Promoters */} - Candidate Promoters + + Candidate Promoters + + + + + + - {ComboBox(humanPromoters, "Search for a Biosample", "H-promoter")} + - {ComboBox(mousePromoters, "Search for a Biosample", "M-promoter")} + {/* Enhancers */} - Candidate Enhancers + + Candidate Enhancers + + + + + + - {ComboBox(humanEnhancers, "Search for a Biosample", "H-enhancer")} + - {ComboBox(mouseEnhancers, "Search for a Biosample", "M-enhancer")} + {/* CTCF-Bound */} - CTCF-Bound + + CTCF-Bound + + + + + + - {ComboBox(humanCTCF, "Search for a Biosample", "H-ctcf")} + - {ComboBox(mouseCTCF, "Search for a Biosample", "M-ctcf")} + {/* Gene Links */} - Gene Links + + Gene Links + + + + + + From f55381b67adb0c07f446772bfad8c1bd2f98541b Mon Sep 17 00:00:00 2001 From: Jonathan Fisher Date: Mon, 31 Jul 2023 10:43:20 -0400 Subject: [PATCH 07/29] Button w/ loading --- screen2.0/package.json | 1 + screen2.0/src/app/downloads/downloads.tsx | 2 +- screen2.0/src/app/downloads/quick-start.tsx | 62 ++++++++----- screen2.0/yarn.lock | 99 ++++++++++++++++++++- 4 files changed, 140 insertions(+), 24 deletions(-) diff --git a/screen2.0/package.json b/screen2.0/package.json index 6965d11e..139844df 100644 --- a/screen2.0/package.json +++ b/screen2.0/package.json @@ -40,6 +40,7 @@ "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", "@mui/icons-material": "^5.11.16", + "@mui/lab": "^5.0.0-alpha.137", "@mui/material": "^5.13.6", "@types/node": "^20.4.2", "@types/react": "^18.2.14", diff --git a/screen2.0/src/app/downloads/downloads.tsx b/screen2.0/src/app/downloads/downloads.tsx index df865a9f..85fcda7a 100644 --- a/screen2.0/src/app/downloads/downloads.tsx +++ b/screen2.0/src/app/downloads/downloads.tsx @@ -32,7 +32,7 @@ export default function DownloadsPage(props: { biosamples: any }) { return ( - + diff --git a/screen2.0/src/app/downloads/quick-start.tsx b/screen2.0/src/app/downloads/quick-start.tsx index 1c7ec8f1..9d986abd 100644 --- a/screen2.0/src/app/downloads/quick-start.tsx +++ b/screen2.0/src/app/downloads/quick-start.tsx @@ -1,23 +1,27 @@ import { Typography, Button, + ButtonProps, Stack, OutlinedInput, InputAdornment, IconButton, Autocomplete, TextField, - Tooltip + Tooltip, + Modal } 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 Downloads from "./page"; import Config from "../../config.json" import { useEffect, useMemo, useState } from "react"; import { Biosample } from "../search/types"; +import React from "react"; interface TabPanelProps { children?: React.ReactNode; @@ -38,6 +42,21 @@ function generateBiosampleURL(selected: Biosample): URL { return new URL(`https://downloads.wenglab.org/Registry-V4/${r.join("_")}.bed`) } +const DownloadButton = (props: ButtonProps & { label: string }) => { + return ( + + ) +} + + //So I don't forget, I think that using PascalCase is useful when defining JSX-returning functions since JSX elements are PascalCase 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) @@ -97,7 +116,7 @@ function ComboBox(props: {options: Biosample[], label: string, mode: "H-promoter }, [toDownload]) 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 */} 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 && - - } - {toDownload && - Loading... + } - + ); } @@ -146,24 +165,23 @@ export function QuickStart(props: TabPanelProps) { aria-labelledby={`simple-tab-${0}`} > {props.value === 0 && - + {/* Titles */} - Human + Human - Mouse + Mouse {/* All cCREs */} All cCREs - - + - + {/* Promoters */} @@ -178,13 +196,13 @@ export function QuickStart(props: TabPanelProps) { - + - + @@ -201,13 +219,13 @@ export function QuickStart(props: TabPanelProps) { - + - + @@ -224,13 +242,13 @@ export function QuickStart(props: TabPanelProps) { - + - + @@ -246,7 +264,7 @@ export function QuickStart(props: TabPanelProps) { - + } diff --git a/screen2.0/yarn.lock b/screen2.0/yarn.lock index d370a53a..d22329db 100644 --- a/screen2.0/yarn.lock +++ b/screen2.0/yarn.lock @@ -121,7 +121,7 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.22.5, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.7": +"@babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.22.5, @babel/runtime@npm:^7.22.6, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.7": version: 7.22.6 resolution: "@babel/runtime@npm:7.22.6" dependencies: @@ -473,6 +473,29 @@ __metadata: languageName: node linkType: hard +"@mui/base@npm:5.0.0-beta.8": + version: 5.0.0-beta.8 + resolution: "@mui/base@npm:5.0.0-beta.8" + dependencies: + "@babel/runtime": ^7.22.6 + "@emotion/is-prop-valid": ^1.2.1 + "@mui/types": ^7.2.4 + "@mui/utils": ^5.14.1 + "@popperjs/core": ^2.11.8 + clsx: ^1.2.1 + prop-types: ^15.8.1 + react-is: ^18.2.0 + peerDependencies: + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 669f99a92d403dd74eccf419d12fbe5061ce1cec4621a72376f176f220a5be61fe8cd496da20afdbf6f5377a22a6ffe79442970926db96a44241d38cc5fbc4e4 + languageName: node + linkType: hard + "@mui/core-downloads-tracker@npm:^5.14.0": version: 5.14.0 resolution: "@mui/core-downloads-tracker@npm:5.14.0" @@ -496,6 +519,36 @@ __metadata: languageName: node linkType: hard +"@mui/lab@npm:^5.0.0-alpha.137": + version: 5.0.0-alpha.137 + resolution: "@mui/lab@npm:5.0.0-alpha.137" + dependencies: + "@babel/runtime": ^7.22.6 + "@mui/base": 5.0.0-beta.8 + "@mui/system": ^5.14.1 + "@mui/types": ^7.2.4 + "@mui/utils": ^5.14.1 + clsx: ^1.2.1 + prop-types: ^15.8.1 + react-is: ^18.2.0 + peerDependencies: + "@emotion/react": ^11.5.0 + "@emotion/styled": ^11.3.0 + "@mui/material": ^5.0.0 + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@emotion/react": + optional: true + "@emotion/styled": + optional: true + "@types/react": + optional: true + checksum: 0301cf28834853aa5eb13d33841b0c243820c53e373d84d7755eb3a5ab5a51713f668336db3b816220e5dd11382e20ca88f8c5b9620d917d78a6b0eb3f13f2fb + languageName: node + linkType: hard + "@mui/material@npm:^5.11.7, @mui/material@npm:^5.13.6": version: 5.14.0 resolution: "@mui/material@npm:5.14.0" @@ -595,6 +648,34 @@ __metadata: languageName: node linkType: hard +"@mui/system@npm:^5.14.1": + version: 5.14.1 + resolution: "@mui/system@npm:5.14.1" + dependencies: + "@babel/runtime": ^7.22.6 + "@mui/private-theming": ^5.13.7 + "@mui/styled-engine": ^5.13.2 + "@mui/types": ^7.2.4 + "@mui/utils": ^5.14.1 + clsx: ^1.2.1 + csstype: ^3.1.2 + prop-types: ^15.8.1 + peerDependencies: + "@emotion/react": ^11.5.0 + "@emotion/styled": ^11.3.0 + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@emotion/react": + optional: true + "@emotion/styled": + optional: true + "@types/react": + optional: true + checksum: d3ab547bdba9544dda51c62e081481caafe5e64ea64cf4a58c8b060f83705a7aa53ebfd843f946567db6a65755635adf80ed3f4103e29dcc7ba1839381583c53 + languageName: node + linkType: hard + "@mui/types@npm:^7.2.4": version: 7.2.4 resolution: "@mui/types@npm:7.2.4" @@ -622,6 +703,21 @@ __metadata: languageName: node linkType: hard +"@mui/utils@npm:^5.14.1": + version: 5.14.1 + resolution: "@mui/utils@npm:5.14.1" + dependencies: + "@babel/runtime": ^7.22.6 + "@types/prop-types": ^15.7.5 + "@types/react-is": ^18.2.1 + prop-types: ^15.8.1 + react-is: ^18.2.0 + peerDependencies: + react: ^17.0.0 || ^18.0.0 + checksum: 39b1ab8d428f1783d0f7621b4ab284f7d035920c43c527114d865ba2d7d467ead850528a042ea986b76d4bac1ad6fc9cb0541add0d17d29d5ad59460c69106d1 + languageName: node + linkType: hard + "@next/env@npm:13.4.10": version: 13.4.10 resolution: "@next/env@npm:13.4.10" @@ -6386,6 +6482,7 @@ __metadata: "@emotion/react": ^11.11.1 "@emotion/styled": ^11.11.0 "@mui/icons-material": ^5.11.16 + "@mui/lab": ^5.0.0-alpha.137 "@mui/material": ^5.13.6 "@types/node": ^20.4.2 "@types/react": ^18.2.14 From 243846d88f79bb549edeb3f79405e569835b0281 Mon Sep 17 00:00:00 2001 From: Jonathan Fisher Date: Tue, 1 Aug 2023 01:52:04 -0400 Subject: [PATCH 08/29] Cleanup tab 1, UI for tab 2 --- .../src/app/downloads/detailed-elements.tsx | 94 ++++++++++++++++--- screen2.0/src/app/downloads/quick-start.tsx | 82 ++++++++-------- screen2.0/src/common/lib/colors.ts | 4 +- screen2.0/src/config.json | 3 +- 4 files changed, 130 insertions(+), 53 deletions(-) diff --git a/screen2.0/src/app/downloads/detailed-elements.tsx b/screen2.0/src/app/downloads/detailed-elements.tsx index 615a6dcb..9b36085c 100644 --- a/screen2.0/src/app/downloads/detailed-elements.tsx +++ b/screen2.0/src/app/downloads/detailed-elements.tsx @@ -1,26 +1,98 @@ -import { Typography } from "@mui/material"; +import { Button, ButtonProps, IconButton, Tooltip, Typography } from "@mui/material"; +import Grid2 from "@mui/material/Unstable_Grid2/Grid2"; import { Box } from "@mui/system"; +import React from "react"; +import InfoIcon from '@mui/icons-material/Info'; +import Config from "../../config.json" +import { DownloadButton } from "./quick-start"; +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"; interface TabPanelProps { children?: React.ReactNode; value: number; } +const InlineDownloadButton = (props: ButtonProps & { label: string, borderColor: string , search?: boolean}) => { + return ( + + + + + ) +} + export function DetailedElements(props: TabPanelProps) { const { children, value, ...other } = props; return ( -
+ {value === 1 && - - Detailed Elements - + + {/* Titles */} + + Human (GRCh38/hg38) + 2,348,854 cCREs • 1,678 cell types + + + Mouse (GRCm38/mm10) + 926,843 cCREs • 366 cell types + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Human cCREs by Cell Type + + + Mouse cCREs by Cell Type + + + + + + + + + + + + } -
+ ); } \ No newline at end of file diff --git a/screen2.0/src/app/downloads/quick-start.tsx b/screen2.0/src/app/downloads/quick-start.tsx index 9d986abd..2e39facf 100644 --- a/screen2.0/src/app/downloads/quick-start.tsx +++ b/screen2.0/src/app/downloads/quick-start.tsx @@ -9,14 +9,15 @@ import { Autocomplete, TextField, Tooltip, - Modal + Modal, + Box } 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 Downloads from "./page"; import Config from "../../config.json" import { useEffect, useMemo, useState } from "react"; @@ -42,7 +43,8 @@ function generateBiosampleURL(selected: Biosample): URL { return new URL(`https://downloads.wenglab.org/Registry-V4/${r.join("_")}.bed`) } -const DownloadButton = (props: ButtonProps & { label: string }) => { +// This needs to be moved and imports +export const DownloadButton = (props: ButtonProps & { label: string }) => { return ( @@ -107,8 +110,6 @@ function ComboBox(props: {options: Biosample[], label: string, mode: "H-promoter .split("\n") .filter((x) => x.includes(stringToMatch)) .join("\n"), - // `${result.name}.${props.title}.bed` - //Need to customize this file name `${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) @@ -140,6 +141,7 @@ function ComboBox(props: {options: Biosample[], label: string, mode: "H-promoter onClick={() => 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, " ")}`} @@ -165,106 +167,108 @@ export function QuickStart(props: TabPanelProps) { aria-labelledby={`simple-tab-${0}`} > {props.value === 0 && - + {/* Titles */} - Human + Human (GRCh38/hg38) + 2,348,854 cCREs • 1,678 cell types - Mouse + Mouse (GRCm38/mm10) + 926,843 cCREs • 366 cell types {/* All cCREs */} - + All cCREs - + - + {/* Promoters */} - - - Candidate Promoters - - - - - - + + + Candidate Promoters + + + + + + - + - + {/* Enhancers */} - - - Candidate Enhancers + + + Candidate Enhancers - + - + - + {/* CTCF-Bound */} - - - CTCF-Bound + + + CTCF-Bound - + - + - + {/* Gene Links */} - - - Gene Links + + + Gene Links - + - + } 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/config.json b/screen2.0/src/config.json index 59ee00ba..f47e5f8c 100644 --- a/screen2.0/src/config.json +++ b/screen2.0/src/config.json @@ -39,6 +39,7 @@ "MouseCCREs": "https://downloads.wenglab.org/Registry-V4/mm10-cCREs.bed", "MousePromoters": "https://downloads.wenglab.org/Registry-V4/mm10-PLS.bed", "MouseEnhancers": "https://downloads.wenglab.org/Registry-V4/mm10-ELS.bed", - "MouseCTCF": "https://downloads.wenglab.org/Registry-V4/mm10-CTCF.bed" + "MouseCTCF": "https://downloads.wenglab.org/Registry-V4/mm10-CTCF.bed", + "Human_PLS": "https://downloads.wenglab.org/Registry-V4/GRCh38-cCREs.PLS.bed" } } From 5f63756936fc58472f39dfaab842bc5216d31316 Mon Sep 17 00:00:00 2001 From: Jonathan Fisher Date: Tue, 1 Aug 2023 13:09:38 -0400 Subject: [PATCH 09/29] Correct Links, styling --- .../src/app/downloads/detailed-elements.tsx | 42 ++++++++++--------- screen2.0/src/app/downloads/quick-start.tsx | 10 ++--- screen2.0/src/config.json | 24 +++++++---- 3 files changed, 44 insertions(+), 32 deletions(-) diff --git a/screen2.0/src/app/downloads/detailed-elements.tsx b/screen2.0/src/app/downloads/detailed-elements.tsx index 9b36085c..af6489a9 100644 --- a/screen2.0/src/app/downloads/detailed-elements.tsx +++ b/screen2.0/src/app/downloads/detailed-elements.tsx @@ -1,4 +1,4 @@ -import { Button, ButtonProps, IconButton, Tooltip, Typography } from "@mui/material"; +import { Button, ButtonProps, IconButton, Paper, Tooltip, Typography, Modal } from "@mui/material"; import Grid2 from "@mui/material/Unstable_Grid2/Grid2"; import { Box } from "@mui/system"; import React from "react"; @@ -16,7 +16,7 @@ interface TabPanelProps { const InlineDownloadButton = (props: ButtonProps & { label: string, borderColor: string , search?: boolean}) => { return ( - + - + ) } @@ -37,7 +37,7 @@ export function DetailedElements(props: TabPanelProps) { return ( {value === 1 && - + {/* Titles */} Human (GRCh38/hg38) @@ -54,25 +54,27 @@ export function DetailedElements(props: TabPanelProps) { - - - - - - - - + + + + + + + + + {/* Box added to align last row */} - - - - - - - - + + + + + + + + + {/* Box added to align last row */} diff --git a/screen2.0/src/app/downloads/quick-start.tsx b/screen2.0/src/app/downloads/quick-start.tsx index 2e39facf..e08f453a 100644 --- a/screen2.0/src/app/downloads/quick-start.tsx +++ b/screen2.0/src/app/downloads/quick-start.tsx @@ -167,7 +167,7 @@ export function QuickStart(props: TabPanelProps) { aria-labelledby={`simple-tab-${0}`} > {props.value === 0 && - + {/* Titles */} Human (GRCh38/hg38) @@ -223,13 +223,13 @@ export function QuickStart(props: TabPanelProps) { - + - + @@ -246,13 +246,13 @@ export function QuickStart(props: TabPanelProps) { - + - + diff --git a/screen2.0/src/config.json b/screen2.0/src/config.json index f47e5f8c..7ff60975 100644 --- a/screen2.0/src/config.json +++ b/screen2.0/src/config.json @@ -32,14 +32,24 @@ }, "Downloads": { "HumanCCREs": "https://downloads.wenglab.org/Registry-V4/GRCh38-cCREs.bed", - "HumanPromoters": "https://downloads.wenglab.org/Registry-V4/GRCh38-PLS.bed", - "HumanEnhancers": "https://downloads.wenglab.org/Registry-V4/GRCh38-ELS.bed", - "HumanCTCF": "https://downloads.wenglab.org/Registry-V4/GRCh38-CTCF.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-PLS.bed", - "MouseEnhancers": "https://downloads.wenglab.org/Registry-V4/mm10-ELS.bed", - "MouseCTCF": "https://downloads.wenglab.org/Registry-V4/mm10-CTCF.bed", - "Human_PLS": "https://downloads.wenglab.org/Registry-V4/GRCh38-cCREs.PLS.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" } } From b1b3471fdf6c605a3cce32b6223cc6568ef54284 Mon Sep 17 00:00:00 2001 From: Jonathan Fisher Date: Tue, 1 Aug 2023 17:35:26 -0400 Subject: [PATCH 10/29] Lots of small things, accessing data in new tab --- screen2.0/package.json | 1 - screen2.0/src/app/downloads/data-matrices.tsx | 1 + .../src/app/downloads/detailed-elements.tsx | 187 ++++++++++++------ screen2.0/src/app/downloads/downloads.tsx | 4 +- screen2.0/src/app/downloads/quick-start.tsx | 13 +- screen2.0/src/app/search/types.ts | 3 + screen2.0/src/common/lib/queries.ts | 6 + screen2.0/yarn.lock | 25 +-- 8 files changed, 148 insertions(+), 92 deletions(-) diff --git a/screen2.0/package.json b/screen2.0/package.json index 139844df..1ce22b8b 100644 --- a/screen2.0/package.json +++ b/screen2.0/package.json @@ -46,7 +46,6 @@ "@types/react": "^18.2.14", "@types/react-dom": "18.2.6", "@weng-lab/psychscreen-ui-components": "^0.7.6", - "@weng-lab/ts-ztable": "^4.0.1", "autoprefixer": "10.4.14", "eslint": "8.44.0", "eslint-config-next": "13.4.10", diff --git a/screen2.0/src/app/downloads/data-matrices.tsx b/screen2.0/src/app/downloads/data-matrices.tsx index 48599c04..d6c5c102 100644 --- a/screen2.0/src/app/downloads/data-matrices.tsx +++ b/screen2.0/src/app/downloads/data-matrices.tsx @@ -4,6 +4,7 @@ import { Box } from "@mui/system"; interface TabPanelProps { children?: React.ReactNode; value: number; + biosamples: any; } export function DataMatrices(props: TabPanelProps) { diff --git a/screen2.0/src/app/downloads/detailed-elements.tsx b/screen2.0/src/app/downloads/detailed-elements.tsx index af6489a9..11c1d89b 100644 --- a/screen2.0/src/app/downloads/detailed-elements.tsx +++ b/screen2.0/src/app/downloads/detailed-elements.tsx @@ -1,22 +1,25 @@ -import { Button, ButtonProps, IconButton, Paper, Tooltip, Typography, Modal } from "@mui/material"; +import { Button, ButtonProps, IconButton, Paper, Tooltip, Typography, Modal, Container } from "@mui/material"; import Grid2 from "@mui/material/Unstable_Grid2/Grid2"; import { Box } from "@mui/system"; -import React from "react"; +import React, { useMemo } from "react"; import InfoIcon from '@mui/icons-material/Info'; import Config from "../../config.json" import { DownloadButton } from "./quick-start"; 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 } from "@weng-lab/psychscreen-ui-components"; +import { Biosample } from "../search/types"; interface TabPanelProps { children?: React.ReactNode; value: number; + biosamples: any; } -const InlineDownloadButton = (props: ButtonProps & { label: string, borderColor: string , search?: boolean}) => { +const InlineDownloadButton = (props: ButtonProps & { label: string, borderColor: string, search?: boolean }) => { return ( - + @@ -91,7 +91,7 @@ function BiosampleModals(props: { rows: Biosample[]; open: boolean; tableTitle: aria-describedby="modal-modal-description" > - + ); @@ -128,6 +128,13 @@ const bioTableCols: DataTableColumn[] = [ } ] +const bioTableCols1: DataTableColumn[] = [ + { + header: "Tissue", + value: (row: Biosample) => "x", + }, +] + export function DetailedElements(props: TabPanelProps) { const [open0, setOpen0] = React.useState(false); const handleOpen0 = () => setOpen0(true); @@ -164,7 +171,7 @@ export function DetailedElements(props: TabPanelProps) { 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 &&
@@ -190,26 +197,26 @@ export function DetailedElements(props: TabPanelProps) { - - - - - - - - + + + + + + + + {/* Box added to align last row */} - - - - - - - - + + + + + + + + {/* Box added to align last row */} @@ -220,14 +227,14 @@ export function DetailedElements(props: TabPanelProps) { Mouse cCREs by Cell Type - - - + + + - - - + + + @@ -238,6 +245,6 @@ export function DetailedElements(props: TabPanelProps) {
} -
+ ); } \ No newline at end of file diff --git a/screen2.0/src/app/downloads/quick-start.tsx b/screen2.0/src/app/downloads/quick-start.tsx index c3f22763..2114a8e3 100644 --- a/screen2.0/src/app/downloads/quick-start.tsx +++ b/screen2.0/src/app/downloads/quick-start.tsx @@ -176,18 +176,18 @@ export function QuickStart(props: TabPanelProps) { {props.value === 0 && {/* Titles */} - + Human (GRCh38/hg38) 2,348,854 cCREs • 1,678 cell types - + {"Human - + Mouse (GRCm38/mm10) 926,843 cCREs • 366 cell types - + {"Mouse {/* All cCREs */} diff --git a/screen2.0/yarn.lock b/screen2.0/yarn.lock index 545d8fbb..930638ae 100644 --- a/screen2.0/yarn.lock +++ b/screen2.0/yarn.lock @@ -203,7 +203,7 @@ __metadata: languageName: node linkType: hard -"@emotion/react@npm:^11.11.1": +"@emotion/react@npm:^11.10.5, @emotion/react@npm:^11.11.1": version: 11.11.1 resolution: "@emotion/react@npm:11.11.1" dependencies: @@ -244,7 +244,7 @@ __metadata: languageName: node linkType: hard -"@emotion/styled@npm:^11.11.0": +"@emotion/styled@npm:^11.10.5, @emotion/styled@npm:^11.11.0": version: 11.11.0 resolution: "@emotion/styled@npm:11.11.0" dependencies: @@ -496,6 +496,29 @@ __metadata: languageName: node linkType: hard +"@mui/base@npm:5.0.0-beta.9": + version: 5.0.0-beta.9 + resolution: "@mui/base@npm:5.0.0-beta.9" + dependencies: + "@babel/runtime": ^7.22.6 + "@emotion/is-prop-valid": ^1.2.1 + "@mui/types": ^7.2.4 + "@mui/utils": ^5.14.3 + "@popperjs/core": ^2.11.8 + clsx: ^2.0.0 + prop-types: ^15.8.1 + react-is: ^18.2.0 + peerDependencies: + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: f01e7f4e9959650a06378cfe072bdddc5dbda2cde7d85f725a6113a8252c9c788c950146eae0baf8f35a42ed5592afd2149841b2ea273ca3536093c38af50d76 + languageName: node + linkType: hard + "@mui/core-downloads-tracker@npm:^5.14.0": version: 5.14.0 resolution: "@mui/core-downloads-tracker@npm:5.14.0" @@ -503,6 +526,29 @@ __metadata: languageName: node linkType: hard +"@mui/core-downloads-tracker@npm:^5.14.3": + version: 5.14.3 + resolution: "@mui/core-downloads-tracker@npm:5.14.3" + checksum: bf8290f2d7486b964467ff91bd23adb14164a51e52bf5044084cac8c11b226a324e77952a66403038bc5052591db8bcd98f5ce5791a48e8589109368a311b8af + languageName: node + linkType: hard + +"@mui/icons-material@npm:^5.11.0": + version: 5.14.3 + resolution: "@mui/icons-material@npm:5.14.3" + dependencies: + "@babel/runtime": ^7.22.6 + peerDependencies: + "@mui/material": ^5.0.0 + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 25ff0261dcbcdde9967779f844d12c85c3ffc79227e50d8c03eade1081c2be855e88d2dbe2a587aa57b5c5c2b742af14f70b1767f7ccfd539d89876a6fc580fb + languageName: node + linkType: hard + "@mui/icons-material@npm:^5.11.16": version: 5.14.0 resolution: "@mui/icons-material@npm:5.14.0" @@ -549,6 +595,39 @@ __metadata: languageName: node linkType: hard +"@mui/material@npm:^5.11.7": + version: 5.14.3 + resolution: "@mui/material@npm:5.14.3" + dependencies: + "@babel/runtime": ^7.22.6 + "@mui/base": 5.0.0-beta.9 + "@mui/core-downloads-tracker": ^5.14.3 + "@mui/system": ^5.14.3 + "@mui/types": ^7.2.4 + "@mui/utils": ^5.14.3 + "@types/react-transition-group": ^4.4.6 + clsx: ^2.0.0 + csstype: ^3.1.2 + prop-types: ^15.8.1 + react-is: ^18.2.0 + react-transition-group: ^4.4.5 + peerDependencies: + "@emotion/react": ^11.5.0 + "@emotion/styled": ^11.3.0 + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@emotion/react": + optional: true + "@emotion/styled": + optional: true + "@types/react": + optional: true + checksum: a3d098b473e71b9d9d0adbf5f0d977df9f090658422229b8eafa21a39f1304d21ebe85d938465094b335de456a8ac3ce7afef16b6148c6be4869c1dbe9d02f21 + languageName: node + linkType: hard + "@mui/material@npm:^5.13.6": version: 5.14.0 resolution: "@mui/material@npm:5.14.0" @@ -676,6 +755,34 @@ __metadata: languageName: node linkType: hard +"@mui/system@npm:^5.14.3": + version: 5.14.3 + resolution: "@mui/system@npm:5.14.3" + dependencies: + "@babel/runtime": ^7.22.6 + "@mui/private-theming": ^5.13.7 + "@mui/styled-engine": ^5.13.2 + "@mui/types": ^7.2.4 + "@mui/utils": ^5.14.3 + clsx: ^2.0.0 + csstype: ^3.1.2 + prop-types: ^15.8.1 + peerDependencies: + "@emotion/react": ^11.5.0 + "@emotion/styled": ^11.3.0 + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@emotion/react": + optional: true + "@emotion/styled": + optional: true + "@types/react": + optional: true + checksum: ba09fdd97bff3d1d29af2189bb49645664e2324b64b722e6ec1599f392e4a2af88410c7d2237caf3edc2ae01083dc3b7880dcb84542e5c3f3fa197f6c92889e5 + languageName: node + linkType: hard + "@mui/types@npm:^7.2.4": version: 7.2.4 resolution: "@mui/types@npm:7.2.4" @@ -718,6 +825,21 @@ __metadata: languageName: node linkType: hard +"@mui/utils@npm:^5.14.3": + version: 5.14.3 + resolution: "@mui/utils@npm:5.14.3" + dependencies: + "@babel/runtime": ^7.22.6 + "@types/prop-types": ^15.7.5 + "@types/react-is": ^18.2.1 + prop-types: ^15.8.1 + react-is: ^18.2.0 + peerDependencies: + react: ^17.0.0 || ^18.0.0 + checksum: 1f82fe28b6a25b5c51f810438217f5a7ce82aebe734d41334b25a39fb35a8d0a4c39c5db3ef2621b211543deba1ee203ca9b1d70b131438262a2a14591e055d6 + languageName: node + linkType: hard + "@next/env@npm:13.4.10": version: 13.4.10 resolution: "@next/env@npm:13.4.10" @@ -1267,12 +1389,28 @@ __metadata: languageName: node linkType: hard -"@weng-lab/psychscreen-ui-components@npm:^0.7.6": - version: 0.7.6 - resolution: "@weng-lab/psychscreen-ui-components@npm:0.7.6" +"@weng-lab/psychscreen-ui-components@npm:^0.7.8-a.1": + version: 0.7.8-a.1 + resolution: "@weng-lab/psychscreen-ui-components@npm:0.7.8-a.1" peerDependencies: react: ">=16" - checksum: 3eba99d5a40f2571c5a3dd8513824420882a63235feb3377c087ccbddc9d0d9c2398b3edad67854057664684a1283291726045f8d9683d619cba77ea7e188e0c + checksum: 0529299084a7d3343051bce3ecd6ec8b2b5e4366e736f9b2357dac6078cf7728e2dd410ddab9f345dcc013db998ae7494d173a8e1a618cd0c0590864f25afb1e + languageName: node + linkType: hard + +"@weng-lab/ts-ztable@npm:^4.0.1": + version: 4.0.1 + resolution: "@weng-lab/ts-ztable@npm:4.0.1" + dependencies: + "@emotion/react": ^11.10.5 + "@emotion/styled": ^11.10.5 + "@mui/icons-material": ^5.11.0 + "@mui/material": ^5.11.7 + tslib: ^2.5.0 + peerDependencies: + react: ">=17.0.0" + react-dom: ">17.0.0" + checksum: cdb4909eb96a36583ff31cc93900cbc2c924541a3e54d0b6c31730d740cebfae49eb6e6b42a45257a1d9ec49260934bf2a09277f024976a147df2e772fb0ac80 languageName: node linkType: hard @@ -2092,6 +2230,13 @@ __metadata: languageName: node linkType: hard +"clsx@npm:^2.0.0": + version: 2.0.0 + resolution: "clsx@npm:2.0.0" + checksum: a2cfb2351b254611acf92faa0daf15220f4cd648bdf96ce369d729813b85336993871a4bf6978ddea2b81b5a130478339c20d9d0b5c6fc287e5147f0c059276e + languageName: node + linkType: hard + "cluster-key-slot@npm:^1.1.0": version: 1.1.2 resolution: "cluster-key-slot@npm:1.1.2" @@ -6471,7 +6616,8 @@ __metadata: "@types/node": ^20.4.2 "@types/react": ^18.2.14 "@types/react-dom": 18.2.6 - "@weng-lab/psychscreen-ui-components": ^0.7.6 + "@weng-lab/psychscreen-ui-components": ^0.7.8-a.1 + "@weng-lab/ts-ztable": ^4.0.1 autoprefixer: 10.4.14 eslint: 8.44.0 eslint-config-next: 13.4.10 From 346b6a0bcc5c2a76249f9f5a52fd172d6efbd28d Mon Sep 17 00:00:00 2001 From: Jonathan Fisher Date: Tue, 8 Aug 2023 09:02:22 -0700 Subject: [PATCH 14/29] Data Matrices Initial UI --- screen2.0/src/app/downloads/data-matrices.tsx | 137 +++++++++++++++++- .../src/app/downloads/detailed-elements.tsx | 5 +- screen2.0/src/app/downloads/quick-start.tsx | 92 ++++++------ 3 files changed, 182 insertions(+), 52 deletions(-) diff --git a/screen2.0/src/app/downloads/data-matrices.tsx b/screen2.0/src/app/downloads/data-matrices.tsx index d6c5c102..9ca95c04 100644 --- a/screen2.0/src/app/downloads/data-matrices.tsx +++ b/screen2.0/src/app/downloads/data-matrices.tsx @@ -1,5 +1,12 @@ -import { Typography } from "@mui/material"; +import { Button, Divider, FormControl, FormControlLabel, FormLabel, Grid, Radio, RadioGroup, Select, TextField, Typography } from "@mui/material"; +import Grid2 from "@mui/material/Unstable_Grid2/Grid2"; import { Box } from "@mui/system"; +import Image from "next/image"; +import Human from "../../../public/Human2.png" +import Mouse from "../../../public/Mouse2.png" +import { useState } from "react"; + +import { ArrowForward, Clear, Download } from "@mui/icons-material"; interface TabPanelProps { children?: React.ReactNode; @@ -7,20 +14,136 @@ interface TabPanelProps { biosamples: any; } +type Selected = { + assembly: "Human" | "Mouse" + assay: "DNase" | "H3K4me3" | "H3K27ac" | "CTCF" +} + export function DataMatrices(props: TabPanelProps) { - const { children, value, ...other } = props; + const [selected, setSelected] = useState(null) + + const selectorButton = (variant: Selected) => { + return ( + + ) + } return (
- {value === 2 && - - Data Matrices - + {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" })} + + + + {selected ? + <> + + {`UMAP Embedding: ${selected.assay} in ${selected.assembly}`} + + + + + Color By: + + } label="Sample Type" /> + } label="Ontology" /> + + + + Show: + + } label="All" /> + } label="Adult" /> + } label="Embyronic" /> + + + + Hold shift, click, and draw a selection to: + + } label="Select Experiments" /> + } label="Zoom In" /> + + + + + + + : + Please select an assay (???) + } + + }
); diff --git a/screen2.0/src/app/downloads/detailed-elements.tsx b/screen2.0/src/app/downloads/detailed-elements.tsx index 0f345bf5..2c04beb1 100644 --- a/screen2.0/src/app/downloads/detailed-elements.tsx +++ b/screen2.0/src/app/downloads/detailed-elements.tsx @@ -1,4 +1,4 @@ -import { Button, ButtonProps, IconButton, Paper, Tooltip, Typography, Modal, Container } from "@mui/material"; +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"; @@ -178,6 +178,8 @@ export function DetailedElements(props: TabPanelProps) { {/* Titles */} Human (GRCh38/hg38) + {/* These are not showing up because of the flex container */} + 2,348,854 cCREs • 1,678 cell types @@ -185,6 +187,7 @@ export function DetailedElements(props: TabPanelProps) { Mouse (GRCm38/mm10) + 926,843 cCREs • 366 cell types diff --git a/screen2.0/src/app/downloads/quick-start.tsx b/screen2.0/src/app/downloads/quick-start.tsx index 2114a8e3..3351b237 100644 --- a/screen2.0/src/app/downloads/quick-start.tsx +++ b/screen2.0/src/app/downloads/quick-start.tsx @@ -10,7 +10,8 @@ import { TextField, Tooltip, Modal, - Box + Box, + Divider } from "@mui/material"; import InfoIcon from '@mui/icons-material/Info'; @@ -64,7 +65,7 @@ export const DownloadButton = (props: ButtonProps & { label: string }) => { ) } - //Imported from old SCREEN +//Imported from old SCREEN function downloadBlob(blob, filename) { const url = URL.createObjectURL(blob) const downloadLink = document.createElement("a") @@ -83,7 +84,7 @@ export function downloadTSV(text, filename) { //So I don't forget, I think that using PascalCase is useful when defining JSX-returning functions since JSX elements are PascalCase -function ComboBox(props: {options: Biosample[], label: string, mode: "H-promoter" | "H-enhancer" | "H-ctcf" | "M-promoter" | "M-enhancer" | "M-ctcf"}): JSX.Element { +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) @@ -124,7 +125,7 @@ function ComboBox(props: {options: Biosample[], label: string, mode: "H-promoter 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 */} + {/* 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 */} setToDownload(generateBiosampleURL(selectedBiosample))} variant="contained" @@ -177,28 +178,31 @@ export function QuickStart(props: TabPanelProps) { {/* Titles */} - Human (GRCh38/hg38) - 2,348,854 cCREs • 1,678 cell types - - - {"Human - - - Mouse (GRCm38/mm10) - 926,843 cCREs • 366 cell types - - - {"Mouse - + 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 */} @@ -213,36 +217,36 @@ export function QuickStart(props: TabPanelProps) { - + - - + + {/* Enhancers */} Candidate Enhancers - - - - - + + + + + - + - + @@ -250,22 +254,22 @@ export function QuickStart(props: TabPanelProps) { CTCF-Bound - - - - - + + + + + - + - + @@ -273,15 +277,15 @@ export function QuickStart(props: TabPanelProps) { Gene Links - - - - - + + + + + - + } From b610120db1f744277c7bcb5488acf6e25ee70e3b Mon Sep 17 00:00:00 2001 From: Jonathan Fisher Date: Tue, 8 Aug 2023 12:50:05 -0700 Subject: [PATCH 15/29] Fetching data, conserving matrices tab state --- screen2.0/package.json | 2 +- screen2.0/src/app/downloads/data-matrices.tsx | 18 +++- screen2.0/src/app/downloads/downloads.tsx | 38 ++++++-- screen2.0/src/app/downloads/page.tsx | 16 +++- screen2.0/src/common/lib/queries.ts | 91 +++++++++++++------ 5 files changed, 123 insertions(+), 42 deletions(-) diff --git a/screen2.0/package.json b/screen2.0/package.json index 5613728b..b1e16b1d 100644 --- a/screen2.0/package.json +++ b/screen2.0/package.json @@ -45,7 +45,7 @@ "@types/node": "^20.4.2", "@types/react": "^18.2.14", "@types/react-dom": "18.2.6", - "@weng-lab/psychscreen-ui-components": "^0.7.8-a.1", + "@weng-lab/psychscreen-ui-components": "^0.7.8", "@weng-lab/ts-ztable": "^4.0.1", "autoprefixer": "10.4.14", "eslint": "8.44.0", diff --git a/screen2.0/src/app/downloads/data-matrices.tsx b/screen2.0/src/app/downloads/data-matrices.tsx index 9ca95c04..307d8710 100644 --- a/screen2.0/src/app/downloads/data-matrices.tsx +++ b/screen2.0/src/app/downloads/data-matrices.tsx @@ -7,11 +7,12 @@ import Mouse from "../../../public/Mouse2.png" import { useState } from "react"; import { ArrowForward, Clear, Download } from "@mui/icons-material"; +import { useRouter } from "next/navigation"; interface TabPanelProps { children?: React.ReactNode; value: number; - biosamples: any; + matrices: any; } type Selected = { @@ -22,14 +23,24 @@ type Selected = { export function DataMatrices(props: TabPanelProps) { const [selected, setSelected] = useState(null) + const router = useRouter() + const selectorButton = (variant: Selected) => { return ( @@ -81,6 +92,7 @@ export function DataMatrices(props: TabPanelProps) { <> {`UMAP Embedding: ${selected.assay} in ${selected.assembly}`} + {props.matrices.data.ccREBiosampleQuery.biosamples[0].name} diff --git a/screen2.0/src/app/downloads/downloads.tsx b/screen2.0/src/app/downloads/downloads.tsx index 4690b369..c70696ec 100644 --- a/screen2.0/src/app/downloads/downloads.tsx +++ b/screen2.0/src/app/downloads/downloads.tsx @@ -15,8 +15,10 @@ 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 } from 'react'; +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 { @@ -25,11 +27,31 @@ function a11yProps(index: number) { }; } -export default function DownloadsPage(props: { biosamples: any }) { - const [value, setValue] = React.useState(0); +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() + + //This works as I want except mouse DNase is always flashed for the tiniest bit? const handleChange = (event: React.SyntheticEvent, newValue: number) => { - setValue(newValue); + 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 ( @@ -38,7 +60,7 @@ export default function DownloadsPage(props: { biosamples: any }) { - + @@ -46,9 +68,9 @@ export default function DownloadsPage(props: { biosamples: any }) { - - - + + +
diff --git a/screen2.0/src/app/downloads/page.tsx b/screen2.0/src/app/downloads/page.tsx index 4a26dd1b..0fac71ff 100644 --- a/screen2.0/src/app/downloads/page.tsx +++ b/screen2.0/src/app/downloads/page.tsx @@ -1,16 +1,26 @@ import * as React from 'react'; import DownloadsPage from './downloads'; -import { biosampleQuery } from '../../common/lib/queries'; +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 async function Downloads() { +export default async function Downloads({ + searchParams, +}: { + searchParams: { [key: string]: string | string[] | undefined } +}) { const biosamples: any = await biosampleQuery() + //I would feed the data from searchParams into the fetch here. I think all that needs to be done is to push the relevant info to the ULR on the matrices tab + const assembly = searchParams.assembly === "Human" ? "grch38" : "mm10" + 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 (
- +
) } diff --git a/screen2.0/src/common/lib/queries.ts b/screen2.0/src/common/lib/queries.ts index 4785ed7a..1a8065d7 100644 --- a/screen2.0/src/common/lib/queries.ts +++ b/screen2.0/src/common/lib/queries.ts @@ -229,6 +229,49 @@ const BIOSAMPLE_QUERY = gql` } ` +const UMAP_QUERY = gql` + query q($assembly: String!, $assay: [String!], $a: String!) { + ccREBiosampleQuery(assay: $assay, assembly: $assembly) { + biosamples { + name + 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 { @@ -282,7 +325,6 @@ export async function MainQuery(assembly: string, chromosome: string, start: num } export async function biosampleQuery() { - var data: ApolloQueryResult | -1 try { data = await getClient().query({ @@ -296,34 +338,29 @@ export async function biosampleQuery() { } } -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 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 From e3bf309f95811d7b75d3b74b2f5620768b51a31f Mon Sep 17 00:00:00 2001 From: Jonathan Fisher Date: Wed, 9 Aug 2023 11:47:53 -0700 Subject: [PATCH 16/29] Data updating, empty plot --- screen2.0/src/app/downloads/data-matrices.tsx | 197 ++++++++++++++++-- screen2.0/src/app/globals.css | 8 +- screen2.0/tailwind.config.js | 4 + screen2.0/yarn.lock | 10 +- 4 files changed, 197 insertions(+), 22 deletions(-) diff --git a/screen2.0/src/app/downloads/data-matrices.tsx b/screen2.0/src/app/downloads/data-matrices.tsx index 307d8710..297b6051 100644 --- a/screen2.0/src/app/downloads/data-matrices.tsx +++ b/screen2.0/src/app/downloads/data-matrices.tsx @@ -4,11 +4,13 @@ import { Box } from "@mui/system"; import Image from "next/image"; import Human from "../../../public/Human2.png" import Mouse from "../../../public/Mouse2.png" -import { useState } from "react"; +import { useEffect, useMemo, useState } from "react"; import { ArrowForward, Clear, Download } from "@mui/icons-material"; import { useRouter } from "next/navigation"; +import { Chart, Scatter, Legend, Annotation } from "jubilant-carnival" + interface TabPanelProps { children?: React.ReactNode; value: number; @@ -20,26 +22,158 @@ type Selected = { assay: "DNase" | "H3K4me3" | "H3K27ac" | "CTCF" } +// Direct Copy but changed low to be optional since it gives error otherwise +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)) +} + +function fiveRange(min, max) { + const r = [] + for (let i = min; i <= max; i += 5) r.push(i) + return r +} + +function tenRange(min, max) { + const r = [] + for (let i = min; i <= max; i += 10) r.push(i) + return r +} + +function oneRange(min, max) { + const r = [] + for (let i = min; i <= max; ++i) r.push(i) + return r +} + +function spacedColors(n) { + const r = [] + for (let i = 0; i < 360; i += 360 / n) r.push(`hsl(${i},50%,40%)`) + return r +} + +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] +} + +//When the buttons are clicked, slected is updated but data is not. The URL params change, but it seems like there is no refresh in the query. Why? +// props.matrices is getting updated, but since data is only initialized with it once, it never receives the change + export function DataMatrices(props: TabPanelProps) { - const [selected, setSelected] = useState(null) + const [selectedAssay, setSelectedAssay] = useState(null) + // Direct copy + const [bounds, setBounds] = useState(undefined) + // Direct copy, put any since typing was lacking in js file + const [data, setData] = useState(props.matrices ?? {}) + const [lifeStage, setLifeStage] = useState("all") + const [colorBy, setColorBy] = useState("sampleType") + const [tSelected, setTSelected] = useState(new Set([])) + const [searched, setSearched] = useState(undefined) + const [biosamples, setBiosamples] = useState([]) + const [selectMode, setSelectMode] = useState("select") + const [tooltip, setTooltip] = useState(-1) const router = useRouter() + //Update data state variable whenever the data changes + useEffect(() => setData(props.matrices), [props.matrices]) + + // Direct Copy + 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] + ) + + // Direct Copy + const fData = useMemo( + () => + 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, selectedAssay] + ) + + // Direct Copy + const scatterData = useMemo( + () => + (fData && + fData.map((x) => ({ + x: x.umap_coordinates[0], + y: x.umap_coordinates[1], + svgProps: { + r: searched && x.experimentAccession === searched.experimentAccession ? 10 : 3, + fill: + searched === undefined || x.experimentAccession === searched.experimentAccession + ? (colorBy === "sampleType" ? scMap : oMap)[x[colorBy]] + : "#aaaaaa", + fillOpacity: searched === undefined || x.experimentAccession === searched.experimentAccession ? 1 : 0.2, + }, + }))) || + [], + [fData, scMap, colorBy, searched, oMap] + ) + + + + console.log(scatterData) + + // Direct copy + 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.ceil(bounds.y.end) : 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.floor(bounds.y.start) : nearest5(Math.max(...((fData && fData.map((x) => x.umap_coordinates[1])) || [0])))), + [fData, bounds] + ) + const selectorButton = (variant: Selected) => { return ( @@ -150,6 +284,43 @@ export function DataMatrices(props: TabPanelProps) { Z-Score Matrix
+ + {/* Direct copy */} + setBiosamples(c[0].map((x) => fData[x])), + onSelectionEnd: (x) => setBounds(x), + freeformSelection: selectMode === "select", + }} + > + setTooltip(-1)} + onPointClick={(i) => setBiosamples([fData[i]])} + /> + {tooltip !== -1 && ( + //X and Y attributes added due to error. What should these be? + + + + + {fData[tooltip].name.replace(/_/g, " ").slice(0, 45)} + {fData[tooltip].name.length > 45 ? "..." : ""} + + + {fData[tooltip].experimentAccession} · click for associated downloads + + + )} + + : Please select an assay (???) 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/tailwind.config.js b/screen2.0/tailwind.config.js index 079941e9..347bfdb9 100644 --- a/screen2.0/tailwind.config.js +++ b/screen2.0/tailwind.config.js @@ -11,4 +11,8 @@ module.exports = { }, }, plugins: [require("prettier-plugin-tailwindcss")], + // corePlugins: { + // preflight: false, + // }, + // important: '#root', } diff --git a/screen2.0/yarn.lock b/screen2.0/yarn.lock index 930638ae..4efbde25 100644 --- a/screen2.0/yarn.lock +++ b/screen2.0/yarn.lock @@ -1389,12 +1389,12 @@ __metadata: languageName: node linkType: hard -"@weng-lab/psychscreen-ui-components@npm:^0.7.8-a.1": - version: 0.7.8-a.1 - resolution: "@weng-lab/psychscreen-ui-components@npm:0.7.8-a.1" +"@weng-lab/psychscreen-ui-components@npm:^0.7.8": + version: 0.7.8 + resolution: "@weng-lab/psychscreen-ui-components@npm:0.7.8" peerDependencies: react: ">=16" - checksum: 0529299084a7d3343051bce3ecd6ec8b2b5e4366e736f9b2357dac6078cf7728e2dd410ddab9f345dcc013db998ae7494d173a8e1a618cd0c0590864f25afb1e + checksum: 516eed3de77f161f65f7c3e2af230faa9cc6218456d8d6123d1226da1c745f2b2458d1c9a0562ccd9c0bbc5ba7dd9b657ee8d9aac6532fdf10fcb728036f6e92 languageName: node linkType: hard @@ -6616,7 +6616,7 @@ __metadata: "@types/node": ^20.4.2 "@types/react": ^18.2.14 "@types/react-dom": 18.2.6 - "@weng-lab/psychscreen-ui-components": ^0.7.8-a.1 + "@weng-lab/psychscreen-ui-components": ^0.7.8 "@weng-lab/ts-ztable": ^4.0.1 autoprefixer: 10.4.14 eslint: 8.44.0 From b99c09763d6860488ce89be2535eb8f85cfbe4c5 Mon Sep 17 00:00:00 2001 From: Jonathan Fisher Date: Wed, 9 Aug 2023 11:51:36 -0700 Subject: [PATCH 17/29] Fix Merge from Main --- screen2.0/package.json | 6 -- screen2.0/yarn.lock | 151 +++++++++++++++++++++++++++++++---------- 2 files changed, 116 insertions(+), 41 deletions(-) diff --git a/screen2.0/package.json b/screen2.0/package.json index ee4886db..78814482 100644 --- a/screen2.0/package.json +++ b/screen2.0/package.json @@ -39,12 +39,6 @@ "@apollo/experimental-nextjs-app-support": "^0.3.1", "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", - "@mui/icons-material": "^5.14.3", - "@mui/material": "^5.14.2", - "@types/node": "^20.4.9", - "@types/react": "^18.2.19", - "@types/react-dom": "18.2.7", - "@weng-lab/psychscreen-ui-components": "^0.7.8", "@mui/icons-material": "^5.11.16", "@mui/lab": "^5.0.0-alpha.137", "@mui/material": "^5.13.6", diff --git a/screen2.0/yarn.lock b/screen2.0/yarn.lock index 072c6091..ecd99854 100644 --- a/screen2.0/yarn.lock +++ b/screen2.0/yarn.lock @@ -450,6 +450,29 @@ __metadata: languageName: node linkType: hard +"@mui/base@npm:5.0.0-beta.10": + version: 5.0.0-beta.10 + resolution: "@mui/base@npm:5.0.0-beta.10" + dependencies: + "@babel/runtime": ^7.22.6 + "@emotion/is-prop-valid": ^1.2.1 + "@mui/types": ^7.2.4 + "@mui/utils": ^5.14.4 + "@popperjs/core": ^2.11.8 + clsx: ^2.0.0 + prop-types: ^15.8.1 + react-is: ^18.2.0 + peerDependencies: + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 4190213fea4715fb3928828339389aeb69620d3f992d42c79422ddaa76540890d3df3468658e4aa071712ec6efc0bba286ef6c7820daeaad6f1d22fedd692afd + languageName: node + linkType: hard + "@mui/base@npm:5.0.0-beta.7": version: 5.0.0-beta.7 resolution: "@mui/base@npm:5.0.0-beta.7" @@ -496,25 +519,22 @@ __metadata: languageName: node linkType: hard -"@mui/material@npm:^5.11.7, @mui/material@npm:^5.13.6": - version: 5.14.0 - resolution: "@mui/material@npm:5.14.0" +"@mui/lab@npm:^5.0.0-alpha.137": + version: 5.0.0-alpha.139 + resolution: "@mui/lab@npm:5.0.0-alpha.139" dependencies: - "@babel/runtime": ^7.22.5 - "@mui/base": 5.0.0-beta.7 - "@mui/core-downloads-tracker": ^5.14.0 - "@mui/system": ^5.14.0 + "@babel/runtime": ^7.22.6 + "@mui/base": 5.0.0-beta.10 + "@mui/system": ^5.14.4 "@mui/types": ^7.2.4 - "@mui/utils": ^5.13.7 - "@types/react-transition-group": ^4.4.6 - clsx: ^1.2.1 - csstype: ^3.1.2 + "@mui/utils": ^5.14.4 + clsx: ^2.0.0 prop-types: ^15.8.1 react-is: ^18.2.0 - react-transition-group: ^4.4.5 peerDependencies: "@emotion/react": ^11.5.0 "@emotion/styled": ^11.3.0 + "@mui/material": ^5.0.0 "@types/react": ^17.0.0 || ^18.0.0 react: ^17.0.0 || ^18.0.0 react-dom: ^17.0.0 || ^18.0.0 @@ -525,20 +545,20 @@ __metadata: optional: true "@types/react": optional: true - checksum: f1b1060b46fdcae6f4515f464bfab58f186fa1dd2e68e5bae0b0c3f42aafc9a73a08411141f870694c00b590a2593caa8fa6dc5b9e68be9d38eeaeda839ca716 + checksum: 99974aaef49abc942a14558df50bdc7fbd1d9d2613d039017b605f6e4188e1a78e639a687d0d6531ce21af9350f2250a5e8906055dead262d1f6dd55fbef92ae languageName: node linkType: hard -"@mui/material@npm:^5.14.2": - version: 5.14.2 - resolution: "@mui/material@npm:5.14.2" +"@mui/material@npm:^5.11.7, @mui/material@npm:^5.13.6": + version: 5.14.0 + resolution: "@mui/material@npm:5.14.0" dependencies: - "@babel/runtime": ^7.22.6 - "@mui/base": 5.0.0-beta.8 - "@mui/core-downloads-tracker": ^5.14.2 - "@mui/system": ^5.14.1 + "@babel/runtime": ^7.22.5 + "@mui/base": 5.0.0-beta.7 + "@mui/core-downloads-tracker": ^5.14.0 + "@mui/system": ^5.14.0 "@mui/types": ^7.2.4 - "@mui/utils": ^5.14.1 + "@mui/utils": ^5.13.7 "@types/react-transition-group": ^4.4.6 clsx: ^1.2.1 csstype: ^3.1.2 @@ -558,7 +578,7 @@ __metadata: optional: true "@types/react": optional: true - checksum: 271ccb56133c43b98338240dfa169c781c8dc9e8cc6e51188d539b30f1744957bda903d24684e532f213184f2522b5120457ceb3fc85e97ba84c1df637dce66a + checksum: f1b1060b46fdcae6f4515f464bfab58f186fa1dd2e68e5bae0b0c3f42aafc9a73a08411141f870694c00b590a2593caa8fa6dc5b9e68be9d38eeaeda839ca716 languageName: node linkType: hard @@ -579,6 +599,23 @@ __metadata: languageName: node linkType: hard +"@mui/private-theming@npm:^5.14.4": + version: 5.14.4 + resolution: "@mui/private-theming@npm:5.14.4" + dependencies: + "@babel/runtime": ^7.22.6 + "@mui/utils": ^5.14.4 + prop-types: ^15.8.1 + peerDependencies: + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 822487a6bd2cc06397b4158dd79283fa6829410d3abd16aa7c12d8569512bfa5f2b6db707b2b2e2f4fa59fc62286057b8184428c7e1cf8147eb1649c426b164c + languageName: node + linkType: hard + "@mui/styled-engine@npm:^5.13.2": version: 5.13.2 resolution: "@mui/styled-engine@npm:5.13.2" @@ -628,6 +665,34 @@ __metadata: languageName: node linkType: hard +"@mui/system@npm:^5.14.4": + version: 5.14.4 + resolution: "@mui/system@npm:5.14.4" + dependencies: + "@babel/runtime": ^7.22.6 + "@mui/private-theming": ^5.14.4 + "@mui/styled-engine": ^5.13.2 + "@mui/types": ^7.2.4 + "@mui/utils": ^5.14.4 + clsx: ^2.0.0 + csstype: ^3.1.2 + prop-types: ^15.8.1 + peerDependencies: + "@emotion/react": ^11.5.0 + "@emotion/styled": ^11.3.0 + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@emotion/react": + optional: true + "@emotion/styled": + optional: true + "@types/react": + optional: true + checksum: 1f0df9872456f3876d6963bb661212e5030ca7218f4687b649d1a969f9c27f707c1cc4687d375257c75cbabd39cd402c5a16d4739b37e94f89f0a5eb9827edd1 + languageName: node + linkType: hard + "@mui/types@npm:^7.2.4": version: 7.2.4 resolution: "@mui/types@npm:7.2.4" @@ -655,10 +720,25 @@ __metadata: languageName: node linkType: hard -"@next/env@npm:13.4.10": - version: 13.4.10 - resolution: "@next/env@npm:13.4.10" - checksum: a3e1ca0fe2e58288a9747a279d168a5d2cdda68bd72174d4c8b6746e5172f261174401d787ec356ac424504f967f0a47bffeffcfdabd6fa73a9e2bd0ff851a73 +"@mui/utils@npm:^5.14.4": + version: 5.14.4 + resolution: "@mui/utils@npm:5.14.4" + dependencies: + "@babel/runtime": ^7.22.6 + "@types/prop-types": ^15.7.5 + "@types/react-is": ^18.2.1 + prop-types: ^15.8.1 + react-is: ^18.2.0 + peerDependencies: + react: ^17.0.0 || ^18.0.0 + checksum: b0084c55dc15c304e93832a23c567e41f2b152242dee3dc2578ce4b3d5177d604994abe1fd39b38a23d049592126a71ecf5ac9fe9f141155aeb4cce06241df92 + languageName: node + linkType: hard + +"@next/env@npm:13.4.12": + version: 13.4.12 + resolution: "@next/env@npm:13.4.12" + checksum: 2ccb2e271b3c42697c1e807cdf988429fcb563f80fa0ca72512f65f47cbbcc46c44fc53bf055814d4b467f1394de8c1a1ef6aad14d35f9993004faa956466d02 languageName: node linkType: hard @@ -892,7 +972,7 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:^20.4.9": +"@types/node@npm:^20.4.2": version: 20.4.9 resolution: "@types/node@npm:20.4.9" checksum: 504e3da96274f3865c1251830f4750bb0a8f6ef6f8648902cd3bba33370c5f219235471bfbf55cce726b25c8eacfcc8e2aad0ec3b13e27ea6708b00d4a9a46c8 @@ -913,12 +993,12 @@ __metadata: languageName: node linkType: hard -"@types/react-dom@npm:18.2.7": - version: 18.2.7 - resolution: "@types/react-dom@npm:18.2.7" +"@types/react-dom@npm:18.2.6": + version: 18.2.6 + resolution: "@types/react-dom@npm:18.2.6" dependencies: "@types/react": "*" - checksum: e02ea908289a7ad26053308248d2b87f6aeafd73d0e2de2a3d435947bcea0422599016ffd1c3e38ff36c42f5e1c87c7417f05b0a157e48649e4a02f21727d54f + checksum: b56e42efab121a3a8013d2eb8c1688e6028a25ea6d33c4362d2846f0af3760b164b4d7c34846614024cfb8956cca70dd1743487f152e32ff89a00fe6fbd2be54 languageName: node linkType: hard @@ -951,7 +1031,7 @@ __metadata: languageName: node linkType: hard -"@types/react@npm:^18.2.19": +"@types/react@npm:^18.2.14": version: 18.2.19 resolution: "@types/react@npm:18.2.19" dependencies: @@ -6460,11 +6540,12 @@ __metadata: "@emotion/react": ^11.11.1 "@emotion/styled": ^11.11.0 "@mui/icons-material": ^5.11.16 + "@mui/lab": ^5.0.0-alpha.137 "@mui/material": ^5.13.6 "@types/node": ^20.4.2 "@types/react": ^18.2.14 "@types/react-dom": 18.2.6 - "@weng-lab/psychscreen-ui-components": ^0.7.6 + "@weng-lab/psychscreen-ui-components": ^0.7.8 "@weng-lab/ts-ztable": ^4.0.1 autoprefixer: 10.4.14 eslint: 8.46.0 @@ -7511,11 +7592,11 @@ __metadata: "typescript@patch:typescript@5.1.6#~builtin": version: 5.1.6 - resolution: "typescript@patch:typescript@npm%3A5.1.6#~builtin::version=5.1.6&hash=5da071" + resolution: "typescript@patch:typescript@npm%3A5.1.6#~builtin::version=5.1.6&hash=85af82" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: f53bfe97f7c8b2b6d23cf572750d4e7d1e0c5fff1c36d859d0ec84556a827b8785077bc27676bf7e71fae538e517c3ecc0f37e7f593be913d884805d931bc8be + checksum: 21e88b0a0c0226f9cb9fd25b9626fb05b4c0f3fddac521844a13e1f30beb8f14e90bd409a9ac43c812c5946d714d6e0dee12d5d02dfc1c562c5aacfa1f49b606 languageName: node linkType: hard From 79dd03c6763bdacaf668365e13713f575d06ee24 Mon Sep 17 00:00:00 2001 From: Jonathan Fisher Date: Thu, 10 Aug 2023 10:42:30 -0700 Subject: [PATCH 18/29] Radio Buttons Working --- screen2.0/src/app/downloads/data-matrices.tsx | 50 +++++++++++-------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/screen2.0/src/app/downloads/data-matrices.tsx b/screen2.0/src/app/downloads/data-matrices.tsx index 297b6051..7b628777 100644 --- a/screen2.0/src/app/downloads/data-matrices.tsx +++ b/screen2.0/src/app/downloads/data-matrices.tsx @@ -4,7 +4,7 @@ import { Box } from "@mui/system"; import Image from "next/image"; import Human from "../../../public/Human2.png" import Mouse from "../../../public/Mouse2.png" -import { useEffect, useMemo, useState } from "react"; +import { ChangeEvent, useEffect, useMemo, useState } from "react"; import { ArrowForward, Clear, Download } from "@mui/icons-material"; import { useRouter } from "next/navigation"; @@ -72,7 +72,7 @@ export function DataMatrices(props: TabPanelProps) { // Direct copy const [bounds, setBounds] = useState(undefined) // Direct copy, put any since typing was lacking in js file - const [data, setData] = useState(props.matrices ?? {}) + const [data, setData] = useState(props.matrices.data ?? {}) const [lifeStage, setLifeStage] = useState("all") const [colorBy, setColorBy] = useState("sampleType") const [tSelected, setTSelected] = useState(new Set([])) @@ -84,7 +84,7 @@ export function DataMatrices(props: TabPanelProps) { const router = useRouter() //Update data state variable whenever the data changes - useEffect(() => setData(props.matrices), [props.matrices]) + useEffect(() => setData(props.matrices.data), [props.matrices]) // Direct Copy const [scMap, scc] = useMemo( @@ -106,15 +106,21 @@ export function DataMatrices(props: TabPanelProps) { [data] ) - // Direct Copy + // fData is not being updated properly + + // Direct Copy, FilterData? const fData = useMemo( - () => - 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, selectedAssay] + () => { + 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, selectedAssay, props.matrices] ) // Direct Copy @@ -137,10 +143,6 @@ export function DataMatrices(props: TabPanelProps) { [fData, scMap, colorBy, searched, oMap] ) - - - console.log(scatterData) - // Direct copy const xMin = useMemo( () => (bounds ? Math.floor(bounds.x.start) : nearest5(Math.min(...((fData && fData.map((x) => x.umap_coordinates[0])) || [0])), true)), @@ -226,7 +228,7 @@ export function DataMatrices(props: TabPanelProps) { <> {`UMAP Embedding: ${selectedAssay.assay} in ${selectedAssay.assembly}`} - {data.data.ccREBiosampleQuery.biosamples[0].name} + {data.ccREBiosampleQuery.biosamples[0].name} @@ -234,11 +236,12 @@ export function DataMatrices(props: TabPanelProps) { Color By: , value: string) => setColorBy(value)} > - } label="Sample Type" /> + } label="Sample Type" /> } label="Ontology" /> @@ -249,23 +252,26 @@ export function DataMatrices(props: TabPanelProps) { defaultValue="all" name="radio-buttons-group" sx={{ mb: 2 }} + onChange={(event: ChangeEvent, value: string) => setLifeStage(value)} > } label="All" /> } label="Adult" /> - } label="Embyronic" /> + } label="Embyronic" /> Hold shift, click, and draw a selection to: , value: string) => setSelectMode(value)} > - } label="Select Experiments" /> - } label="Zoom In" /> + } label="Select Experiments" /> + } label="Zoom In" /> + {bounds && } } - - - - - {/* Direct copy */} - setBiosamples(c[0].map((x) => fData[x])), - onSelectionEnd: (x) => setBounds(x), - freeformSelection: selectMode === "select", - }} - > - setTooltip(-1)} - onPointClick={(i) => setBiosamples([fData[i]])} - /> - {tooltip !== -1 && ( - //X and Y attributes added due to error. What should these be? - - - - - {fData[tooltip].name.replace(/_/g, " ").slice(0, 45)} - {fData[tooltip].name.length > 45 ? "..." : ""} - - - {fData[tooltip].experimentAccession} · click for associated downloads - - - )} - - - - : - Please select an assay (???) - } + + {`UMAP Embedding: ${selectedAssay.assay} in ${selectedAssay.assembly}`} + + + {/* Search box is being fed fData, the data used to populate the table */} + } + getOptionLabel={(biosample: { + name: string, + ontology: string, + sampleType: string, + lifeStage: string, + umap_coordinates: [ number, number ], + experimentAccession: string + }) => biosample.name.replace(/_/g, " ") + " — Exp ID: " + biosample.experimentAccession} + blurOnSelect + onChange={(event, 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: string) => setSelectMode(value)} + > + } label="Select Experiments" /> + } label="Zoom In" /> + + + {bounds && } + + + + + {/* Direct copy */} + setBiosamples(c[0].map((x) => fData[x])), + onSelectionEnd: (x) => setBounds(x), + freeformSelection: selectMode === "select", + }} + > + setTooltip(-1)} + onPointClick={(i) => setBiosamples([fData[i]])} + /> + {tooltip !== -1 && ( + //X and Y attributes added due to error. What should these be? + + + + + {fData[tooltip].name.replace(/_/g, " ").slice(0, 45)} + {fData[tooltip].name.length > 45 ? "..." : ""} + + + {fData[tooltip].experimentAccession} · click for associated downloads + + + )} + + } diff --git a/screen2.0/src/app/downloads/downloads.tsx b/screen2.0/src/app/downloads/downloads.tsx index c70696ec..b945f4df 100644 --- a/screen2.0/src/app/downloads/downloads.tsx +++ b/screen2.0/src/app/downloads/downloads.tsx @@ -70,7 +70,8 @@ export default function DownloadsPage(props: { - + {/* Matrices being fed biosamples might be redundant */} + diff --git a/screen2.0/src/config.json b/screen2.0/src/config.json index 7ff60975..e58e9f3c 100644 --- a/screen2.0/src/config.json +++ b/screen2.0/src/config.json @@ -50,6 +50,26 @@ "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" + "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" } } From 1446693a0ac71f1d887be64a81a97ebedffe4be9 Mon Sep 17 00:00:00 2001 From: Jonathan Fisher Date: Fri, 11 Aug 2023 11:32:58 -0700 Subject: [PATCH 20/29] Legend, selected biosample tables --- screen2.0/src/app/downloads/data-matrices.tsx | 381 ++++++++++-------- .../src/app/downloads/detailed-elements.tsx | 2 +- screen2.0/src/app/search/types.ts | 10 + screen2.0/src/common/lib/queries.ts | 1 + screen2.0/src/common/lib/themes.ts | 10 +- 5 files changed, 239 insertions(+), 165 deletions(-) diff --git a/screen2.0/src/app/downloads/data-matrices.tsx b/screen2.0/src/app/downloads/data-matrices.tsx index ff0bc8ad..dc5fd0b0 100644 --- a/screen2.0/src/app/downloads/data-matrices.tsx +++ b/screen2.0/src/app/downloads/data-matrices.tsx @@ -1,4 +1,4 @@ -import { Autocomplete, Button, Divider, FormControl, FormControlLabel, FormLabel, Grid, Radio, RadioGroup, Select, TextField, Typography } from "@mui/material"; +import { Accordion, AccordionDetails, AccordionSummary, Autocomplete, Button, Divider, FormControl, FormControlLabel, FormLabel, Grid, Modal, Radio, RadioGroup, Select, TextField, Typography } from "@mui/material"; import Grid2 from "@mui/material/Unstable_Grid2/Grid2"; import { Box } from "@mui/system"; import Image from "next/image"; @@ -6,12 +6,14 @@ import Human from "../../../public/Human2.png" import Mouse from "../../../public/Mouse2.png" import { ChangeEvent, useEffect, useMemo, useState } from "react"; -import { ArrowForward, Clear, Download } from "@mui/icons-material"; +import { ArrowForward, Clear, Download, ExpandMore } from "@mui/icons-material"; import { useRouter } from "next/navigation"; import { Chart, Scatter, Legend, Annotation } from "jubilant-carnival" import Config from "../../config.json" +import { DataTable, DataTableColumn } from "@weng-lab/psychscreen-ui-components"; +import { Biosample, BiosampleUMAP } from "../search/types"; interface TabPanelProps { children?: React.ReactNode; @@ -67,6 +69,15 @@ function colorMap(strings) { return [r, c] } +const style = { + position: 'absolute' as 'absolute', + top: '50%', + left: '50%', + transform: 'translate(-50%, -50%)', + width: '80%', + boxShadow: 24, +}; + //When the buttons are clicked, slected is updated but data is not. The URL params change, but it seems like there is no refresh in the query. Why? // props.matrices is getting updated, but since data is only initialized with it once, it never receives the change @@ -84,6 +95,10 @@ export function DataMatrices(props: TabPanelProps) { const [selectMode, setSelectMode] = useState("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 @@ -162,6 +177,13 @@ export function DataMatrices(props: TabPanelProps) { [fData, bounds] ) + // Direct Copy, this does not update properly when filtering by lifeStage + 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]) + const selectorButton = (variant: Selected) => { return ( @@ -212,173 +234,214 @@ export function DataMatrices(props: TabPanelProps) { }, }, }; - + return matrices[selectedAssay.assembly][variant][selectedAssay.assay]; }; + 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" })} +
+ + + + 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" })} + - - 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" })} - - - - - {`UMAP Embedding: ${selectedAssay.assay} in ${selectedAssay.assembly}`} - - - {/* Search box is being fed fData, the data used to populate the table */} - } - getOptionLabel={(biosample: { - name: string, - ontology: string, - sampleType: string, - lifeStage: string, - umap_coordinates: [ number, number ], - experimentAccession: string - }) => biosample.name.replace(/_/g, " ") + " — Exp ID: " + biosample.experimentAccession} - blurOnSelect - onChange={(event, value: any) => setSearched(value)} - size="small" - /> - - Color By: - , value: string) => setColorBy(value)} + + + {/* Search box is being fed fData, the data used to populate the table */} + {`UMAP Embedding: ${selectedAssay.assay} in ${selectedAssay.assembly}`} + } + getOptionLabel={(biosample: BiosampleUMAP) => biosample.displayname + " — Exp ID: " + biosample.experimentAccession} + blurOnSelect + onChange={(event, 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: string) => setSelectMode(value)} + > + } label="Select Experiments" /> + } label="Zoom In" /> + + + {bounds && } + + + + + {/* Direct copy */} + + {biosamples.length !== 0 && + + } + setBiosamples(c[0].map((x) => fData[x])), + onSelectionEnd: (x) => setBounds(x), + freeformSelection: selectMode === "select", + }} > - } label="Select Experiments" /> - } label="Zoom In" /> - - - {bounds && } - - - - - {/* Direct copy */} - setBiosamples(c[0].map((x) => fData[x])), - onSelectionEnd: (x) => setBounds(x), - freeformSelection: selectMode === "select", - }} - > - setTooltip(-1)} - onPointClick={(i) => setBiosamples([fData[i]])} - /> - {tooltip !== -1 && ( - //X and Y attributes added due to error. What should these be? - - - - - {fData[tooltip].name.replace(/_/g, " ").slice(0, 45)} - {fData[tooltip].name.length > 45 ? "..." : ""} - - - {fData[tooltip].experimentAccession} · click for associated downloads - - - )} - + setTooltip(-1)} + onPointClick={(i) => setBiosamples([fData[i]])} + /> + {tooltip !== -1 && ( + //X and Y attributes added due to error. What should these be? + + + + + {fData[tooltip].name.replace(/_/g, " ").slice(0, 45)} + {fData[tooltip].name.length > 45 ? "..." : ""} + + + {fData[tooltip].experimentAccession} · click for associated downloads + + + )} + + + }> + 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 index 2c04beb1..d0d3e5b2 100644 --- a/screen2.0/src/app/downloads/detailed-elements.tsx +++ b/screen2.0/src/app/downloads/detailed-elements.tsx @@ -91,7 +91,7 @@ function BiosampleModals(props: { rows: Biosample[]; open: boolean; tableTitle: aria-describedby="modal-modal-description" > - + ); diff --git a/screen2.0/src/app/search/types.ts b/screen2.0/src/app/search/types.ts index 7834d95c..76d55427 100644 --- a/screen2.0/src/app/search/types.ts +++ b/screen2.0/src/app/search/types.ts @@ -126,4 +126,14 @@ export type Biosample = { 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/common/lib/queries.ts b/screen2.0/src/common/lib/queries.ts index 1a8065d7..78040c85 100644 --- a/screen2.0/src/common/lib/queries.ts +++ b/screen2.0/src/common/lib/queries.ts @@ -234,6 +234,7 @@ const UMAP_QUERY = gql` ccREBiosampleQuery(assay: $assay, assembly: $assembly) { biosamples { name + displayname ontology sampleType lifeStage diff --git a/screen2.0/src/common/lib/themes.ts b/screen2.0/src/common/lib/themes.ts index 90d8fa18..223d25a2 100644 --- a/screen2.0/src/common/lib/themes.ts +++ b/screen2.0/src/common/lib/themes.ts @@ -22,11 +22,11 @@ export const defaultTheme = createTheme({ // } }, components: { - MuiAccordion: { - defaultProps: { - elevation: 0, // outline - }, - }, + // MuiAccordion: { + // defaultProps: { + // elevation: 0, // outline + // }, + // }, }, transitions: { easing: { From 62a4bed8de707effd9659943fb0b8582e72b7625 Mon Sep 17 00:00:00 2001 From: Jonathan Fisher Date: Fri, 11 Aug 2023 16:41:47 -0700 Subject: [PATCH 21/29] Lots of small changes --- screen2.0/src/app/downloads/data-matrices.tsx | 118 ++++++++++-------- .../src/app/downloads/detailed-elements.tsx | 2 +- screen2.0/src/app/downloads/quick-start.tsx | 2 +- screen2.0/src/app/downloads/types.ts | 25 ++++ screen2.0/src/app/search/types.ts | 29 +---- .../common/components/MainResultsTable.tsx | 1 - .../common/components/ResponsiveAppBar.tsx | 24 ++-- 7 files changed, 106 insertions(+), 95 deletions(-) create mode 100644 screen2.0/src/app/downloads/types.ts diff --git a/screen2.0/src/app/downloads/data-matrices.tsx b/screen2.0/src/app/downloads/data-matrices.tsx index dc5fd0b0..9768474b 100644 --- a/screen2.0/src/app/downloads/data-matrices.tsx +++ b/screen2.0/src/app/downloads/data-matrices.tsx @@ -6,14 +6,19 @@ import Human from "../../../public/Human2.png" import Mouse from "../../../public/Mouse2.png" import { ChangeEvent, useEffect, useMemo, useState } from "react"; -import { ArrowForward, Clear, Download, ExpandMore } from "@mui/icons-material"; +import { ArrowForward, Clear, Download, ExpandMore, Visibility } from "@mui/icons-material"; import { useRouter } from "next/navigation"; import { Chart, Scatter, Legend, Annotation } from "jubilant-carnival" import Config from "../../config.json" import { DataTable, DataTableColumn } from "@weng-lab/psychscreen-ui-components"; -import { Biosample, BiosampleUMAP } from "../search/types"; +import { Biosample, 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"; interface TabPanelProps { children?: React.ReactNode; @@ -85,8 +90,8 @@ export function DataMatrices(props: TabPanelProps) { const [selectedAssay, setSelectedAssay] = useState({ assembly: "Human", assay: "DNase" }) // Direct copy const [bounds, setBounds] = useState(undefined) - // Direct copy, put any since typing was lacking in js file - const [data, setData] = useState(props.matrices.data ?? {}) + // This typing is not clear due to the structure of the code I copied + const [data, setData] = useState<{ ccREBiosampleQuery: { biosamples: BiosampleUMAP[] } }>(props.matrices.data ?? {}) const [lifeStage, setLifeStage] = useState("all") const [colorBy, setColorBy] = useState("sampleType") const [tSelected, setTSelected] = useState(new Set([])) @@ -96,7 +101,7 @@ export function DataMatrices(props: TabPanelProps) { const [tooltip, setTooltip] = useState(-1) const [open, setOpen] = useState(false); - const handleOpenModal = () => {biosamples.length !== 0 && setOpen(true)}; + const handleOpenModal = () => { biosamples.length !== 0 && setOpen(true) }; const handleCloseModal = () => setOpen(false); const router = useRouter() @@ -139,26 +144,6 @@ export function DataMatrices(props: TabPanelProps) { [data, lifeStage, colorBy, tSelected, selectedAssay, props.matrices] ) - // Direct Copy - const scatterData = useMemo( - () => - (fData && - fData.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] - ) - // Direct copy const xMin = useMemo( () => (bounds ? Math.floor(bounds.x.start) : nearest5(Math.min(...((fData && fData.map((x) => x.umap_coordinates[0])) || [0])), true)), @@ -177,6 +162,26 @@ export function DataMatrices(props: TabPanelProps) { [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, bounds] + ) + // Direct Copy, this does not update properly when filtering by lifeStage const [legendEntries, height] = useMemo(() => { const g = colorBy === "sampleType" ? scMap : oMap @@ -184,10 +189,23 @@ export function DataMatrices(props: TabPanelProps) { 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]) + 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 + } + } + const selectorButton = (variant: Selected) => { return ( @@ -262,7 +280,7 @@ export function DataMatrices(props: TabPanelProps) { aria-labelledby={`simple-tab-${2}`} > - + Human @@ -296,8 +314,25 @@ export function DataMatrices(props: TabPanelProps) { - {/* Search box is being fed fData, the data used to populate the table */} - {`UMAP Embedding: ${selectedAssay.assay} in ${selectedAssay.assembly}`} + + {bounds && } - - - {/* Direct copy */} - {biosamples.length !== 0 && - } diff --git a/screen2.0/src/app/downloads/detailed-elements.tsx b/screen2.0/src/app/downloads/detailed-elements.tsx index d0d3e5b2..12faaf14 100644 --- a/screen2.0/src/app/downloads/detailed-elements.tsx +++ b/screen2.0/src/app/downloads/detailed-elements.tsx @@ -8,7 +8,7 @@ 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 "../search/types"; +import { Biosample } from "./types"; import Image from "next/image"; import Human from "../../../public/Human2.png" import Mouse from "../../../public/Mouse2.png" diff --git a/screen2.0/src/app/downloads/quick-start.tsx b/screen2.0/src/app/downloads/quick-start.tsx index 3351b237..ee21e693 100644 --- a/screen2.0/src/app/downloads/quick-start.tsx +++ b/screen2.0/src/app/downloads/quick-start.tsx @@ -25,7 +25,7 @@ import Mouse from "../../../public/Mouse2.png" import Config from "../../config.json" import { useEffect, useMemo, useState } from "react"; -import { Biosample } from "../search/types"; +import { Biosample } from "./types"; import React from "react"; import Image from "next/image"; 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/search/types.ts b/screen2.0/src/app/search/types.ts index 76d55427..6cefc6d0 100644 --- a/screen2.0/src/app/search/types.ts +++ b/screen2.0/src/app/search/types.ts @@ -109,31 +109,4 @@ export type FilteredBiosampleData = [ h3k4me3: boolean } }[] -][] - -//This needs to be moved to avoid confusion probably -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 +][] \ 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 - + */} From b49a26aeae2f5c772e969314b5c8f492f47e7c86 Mon Sep 17 00:00:00 2001 From: Jonathan Fisher Date: Mon, 14 Aug 2023 15:38:13 -0400 Subject: [PATCH 22/29] Fix zoom bug, matrices file cleanup --- screen2.0/src/app/downloads/data-matrices.tsx | 132 +++++++++++------- screen2.0/src/app/downloads/downloads.tsx | 9 +- screen2.0/src/app/downloads/page.tsx | 3 +- 3 files changed, 88 insertions(+), 56 deletions(-) diff --git a/screen2.0/src/app/downloads/data-matrices.tsx b/screen2.0/src/app/downloads/data-matrices.tsx index 9768474b..4896e19b 100644 --- a/screen2.0/src/app/downloads/data-matrices.tsx +++ b/screen2.0/src/app/downloads/data-matrices.tsx @@ -1,30 +1,28 @@ -import { Accordion, AccordionDetails, AccordionSummary, Autocomplete, Button, Divider, FormControl, FormControlLabel, FormLabel, Grid, Modal, Radio, RadioGroup, Select, TextField, Typography } from "@mui/material"; +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 { Box } from "@mui/system"; +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 { ChangeEvent, useEffect, useMemo, useState } from "react"; - -import { ArrowForward, Clear, Download, ExpandMore, Visibility } from "@mui/icons-material"; import { useRouter } from "next/navigation"; - -import { Chart, Scatter, Legend, Annotation } from "jubilant-carnival" - -import Config from "../../config.json" +import { Chart, Scatter, Legend, Annotation, Range2D } from "jubilant-carnival" import { DataTable, DataTableColumn } from "@weng-lab/psychscreen-ui-components"; -import { Biosample, BiosampleUMAP } from "./types"; - +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: any; - matrices: any; + biosamples: -1 | ApolloQueryResult, + matrices: -1 | ApolloQueryResult, + searchParams: { [key: string]: string | string[] | undefined } } type Selected = { @@ -32,36 +30,41 @@ type Selected = { assay: "DNase" | "H3K4me3" | "H3K27ac" | "CTCF" } -// Direct Copy but changed low to be optional since it gives error otherwise +// 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)) @@ -74,6 +77,7 @@ function colorMap(strings) { return [r, c] } +// Styling for selected biosamples modal const style = { position: 'absolute' as 'absolute', top: '50%', @@ -83,21 +87,24 @@ const style = { boxShadow: 24, }; -//When the buttons are clicked, slected is updated but data is not. The URL params change, but it seems like there is no refresh in the query. Why? -// props.matrices is getting updated, but since data is only initialized with it once, it never receives the change - export function DataMatrices(props: TabPanelProps) { - const [selectedAssay, setSelectedAssay] = useState({ assembly: "Human", assay: "DNase" }) - // Direct copy + 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) - // This typing is not clear due to the structure of the code I copied - const [data, setData] = useState<{ ccREBiosampleQuery: { biosamples: BiosampleUMAP[] } }>(props.matrices.data ?? {}) + 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") + 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); @@ -107,9 +114,9 @@ export function DataMatrices(props: TabPanelProps) { const router = useRouter() //Update data state variable whenever the data changes - useEffect(() => setData(props.matrices.data), [props.matrices]) + useEffect(() => setData(props.matrices != -1 ? props.matrices.data : {}), [props.matrices]) - // Direct Copy + // Direct copy from old SCREEN const [scMap, scc] = useMemo( () => colorMap( @@ -128,8 +135,6 @@ export function DataMatrices(props: TabPanelProps) { ), [data] ) - - // Direct Copy, FilterData? const fData = useMemo( () => { return ( @@ -143,14 +148,12 @@ export function DataMatrices(props: TabPanelProps) { , [data, lifeStage, colorBy, tSelected, selectedAssay, props.matrices] ) - - // Direct copy 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.ceil(bounds.y.end) : nearest5(Math.min(...((fData && fData.map((x) => x.umap_coordinates[1])) || [0])), true)), + () => (bounds ? Math.floor(bounds.y.start) : nearest5(Math.min(...((fData && fData.map((x) => x.umap_coordinates[1])) || [0])), true)), [fData, bounds] ) const xMax = useMemo( @@ -158,10 +161,9 @@ export function DataMatrices(props: TabPanelProps) { [fData, bounds] ) const yMax = useMemo( - () => (bounds ? Math.floor(bounds.y.start) : nearest5(Math.max(...((fData && fData.map((x) => x.umap_coordinates[1])) || [0])))), + () => (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 @@ -182,14 +184,37 @@ export function DataMatrices(props: TabPanelProps) { [fData, scMap, colorBy, searched, oMap, bounds] ) - // Direct Copy, this does not update properly when filtering by lifeStage + // 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]) - function borderColor(assay: Selected["assay"]){ + /** + * 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 @@ -202,6 +227,7 @@ export function DataMatrices(props: TabPanelProps) { } } + // 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: { @@ -252,10 +284,10 @@ export function DataMatrices(props: TabPanelProps) { }, }, }; - return matrices[selectedAssay.assembly][variant][selectedAssay.assay]; }; + // Columns for selected biosample modal const modalCols: DataTableColumn[] = [ { header: "Experimental Accession", @@ -377,7 +409,7 @@ export function DataMatrices(props: TabPanelProps) { aria-labelledby="demo-radio-buttons-group-label" defaultValue="select" name="radio-buttons-group" - onChange={(event: ChangeEvent, value: string) => setSelectMode(value)} + onChange={(event: ChangeEvent, value: "select" | "zoom") => setSelectMode(value)} > } label="Select Experiments" /> } label="Zoom In" /> @@ -386,14 +418,6 @@ export function DataMatrices(props: TabPanelProps) { {bounds && } - - {biosamples.length !== 0 && - - } setBiosamples(c[0].map((x) => fData[x])), - onSelectionEnd: (x) => setBounds(x), + onSelectionEnd: (x) => handleSetBounds(x), freeformSelection: selectMode === "select", }} > @@ -414,7 +438,7 @@ export function DataMatrices(props: TabPanelProps) { onPointClick={(i) => setBiosamples([fData[i]])} /> {tooltip !== -1 && ( - //X and Y attributes added due to error. What should these be? + //X and Y attributes added due to error. Not sure if setting to zero has unintended consequences @@ -423,11 +447,21 @@ export function DataMatrices(props: TabPanelProps) { {fData[tooltip].name.length > 45 ? "..." : ""} - {fData[tooltip].experimentAccession} · click for associated downloads + {fData[tooltip].experimentAccession} )} + {biosamples.length !== 0 && + + + + + } }> Legend diff --git a/screen2.0/src/app/downloads/downloads.tsx b/screen2.0/src/app/downloads/downloads.tsx index b945f4df..0d0de9e8 100644 --- a/screen2.0/src/app/downloads/downloads.tsx +++ b/screen2.0/src/app/downloads/downloads.tsx @@ -37,7 +37,6 @@ export default function DownloadsPage(props: { const router = useRouter() - //This works as I want except mouse DNase is always flashed for the tiniest bit? const handleChange = (event: React.SyntheticEvent, newValue: number) => { if ( (props.searchParams.assembly === "Human" || props.searchParams.assembly === "Mouse") @@ -61,9 +60,9 @@ export default function DownloadsPage(props: { - - - + + + @@ -71,7 +70,7 @@ export default function DownloadsPage(props: { {/* 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 0fac71ff..80f73a01 100644 --- a/screen2.0/src/app/downloads/page.tsx +++ b/screen2.0/src/app/downloads/page.tsx @@ -12,8 +12,7 @@ export default async function Downloads({ searchParams: { [key: string]: string | string[] | undefined } }) { const biosamples: any = await biosampleQuery() - //I would feed the data from searchParams into the fetch here. I think all that needs to be done is to push the relevant info to the ULR on the matrices tab - const assembly = searchParams.assembly === "Human" ? "grch38" : "mm10" + 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) From 98293529400e9d54cb44dbb64aae30d54a065081 Mon Sep 17 00:00:00 2001 From: Jonathan Fisher Date: Mon, 14 Aug 2023 22:38:10 -0400 Subject: [PATCH 23/29] Cleanup, responsiveness --- screen2.0/src/app/downloads/data-matrices.tsx | 6 +- .../src/app/downloads/detailed-elements.tsx | 176 ++++++++++-------- screen2.0/src/app/downloads/quick-start.tsx | 50 ++--- screen2.0/src/app/downloads/utils.tsx | 16 ++ 4 files changed, 134 insertions(+), 114 deletions(-) create mode 100644 screen2.0/src/app/downloads/utils.tsx diff --git a/screen2.0/src/app/downloads/data-matrices.tsx b/screen2.0/src/app/downloads/data-matrices.tsx index 4896e19b..578b9d64 100644 --- a/screen2.0/src/app/downloads/data-matrices.tsx +++ b/screen2.0/src/app/downloads/data-matrices.tsx @@ -146,7 +146,7 @@ export function DataMatrices(props: TabPanelProps) { ) } , - [data, lifeStage, colorBy, tSelected, selectedAssay, props.matrices] + [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)), @@ -181,7 +181,7 @@ export function DataMatrices(props: TabPanelProps) { }, }))) || [], - [fData, scMap, colorBy, searched, oMap, bounds] + [fData, scMap, colorBy, searched, oMap, xMin, xMax, yMin, yMax] ) // Direct copy from old SCREEN @@ -240,7 +240,7 @@ export function DataMatrices(props: TabPanelProps) { } }} endIcon={(selectedAssay && selectedAssay.assembly === variant.assembly && selectedAssay.assay === variant.assay) ? : null} - sx={{ mb: 1, textTransform: "none", borderLeft: `${(selectedAssay && selectedAssay.assembly === variant.assembly && selectedAssay.assay === variant.assay) ? "1.5rem" : "0.75rem"} solid ${borderColor(variant.assay)}`, '&:hover': { borderLeft: `1.5rem solid ${borderColor(variant.assay)}` } }} + sx={{ mb: 1, textTransform: "none", borderLeft: `${(selectedAssay && selectedAssay.assembly === variant.assembly && selectedAssay.assay === variant.assay) ? "1.5rem" : "0.40rem"} solid ${borderColor(variant.assay)}`, '&:hover': { borderLeft: `1.5rem solid ${borderColor(variant.assay)}` } }} > {`${variant.assay}`} diff --git a/screen2.0/src/app/downloads/detailed-elements.tsx b/screen2.0/src/app/downloads/detailed-elements.tsx index 12faaf14..00a20821 100644 --- a/screen2.0/src/app/downloads/detailed-elements.tsx +++ b/screen2.0/src/app/downloads/detailed-elements.tsx @@ -3,7 +3,6 @@ import Grid2 from "@mui/material/Unstable_Grid2/Grid2"; import { Box } from "@mui/system"; import React, { useMemo } from "react"; import Config from "../../config.json" -import { DownloadButton, downloadTSV } from "./quick-start"; 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"; @@ -12,13 +11,32 @@ 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: any; + 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 ( @@ -36,6 +54,7 @@ const InlineDownloadButton = (props: ButtonProps & { label: string, bordercolor: ) } +// Styling for By Cell Type Modal const style = { position: 'absolute' as 'absolute', top: '50%', @@ -45,21 +64,27 @@ const style = { boxShadow: 24, }; -function bioTableColsRender(row: Biosample, x: "dnase" | "h3k4me3" | "h3k27ac" | "ctcf"){ +// 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 } @@ -69,10 +94,10 @@ function bioTableColsRender(row: Biosample, x: "dnase" | "h3k4me3" | "h3k27ac" | .then((x) => { downloadTSV( x, - `what file convention should be used.txt` + fileName ) }) - + return ( @@ -82,21 +107,7 @@ function bioTableColsRender(row: Biosample, x: "dnase" | "h3k4me3" | "h3k27ac" | else return null } -function BiosampleModals(props: { rows: Biosample[]; open: boolean; tableTitle: string, handleClose: (event: {}, reason: "backdropClick" | "escapeKeyDown") => void; }): React.JSX.Element { - return ( - - - - - - ); -} - +// Modal Columns const bioTableCols: DataTableColumn[] = [ { header: "Tissue", @@ -104,7 +115,7 @@ const bioTableCols: DataTableColumn[] = [ }, { header: "Cell Type", - value: (row: Biosample) => row.name.replace(/_/g, " "), + value: (row: Biosample) => row.displayname, }, { header: "DNase", @@ -128,14 +139,24 @@ const bioTableCols: DataTableColumn[] = [ } ] -const bioTableCols1: DataTableColumn[] = [ - { - header: "Tissue", - value: (row: Biosample) => "x", - }, -] +// 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); @@ -147,7 +168,7 @@ export function DetailedElements(props: TabPanelProps) { 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); @@ -160,9 +181,9 @@ export function DetailedElements(props: TabPanelProps) { const handleOpen5 = () => setOpen5(true); const handleClose5 = () => setOpen5(false); - const biosamples = props.biosamples.data + const biosamples = props.biosamples != -1 ? props.biosamples.data : null - //QUESTION: Is there a lifeStage besides embryonic and adult? If so need to change adult logic back + //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]) @@ -175,53 +196,56 @@ export function DetailedElements(props: TabPanelProps) { {props.value === 1 &&
- {/* 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 - - - - - - + + + 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 */} + + - - - - - - - - - - {/* Box added to align last row */} - - - - - - - - - - - - {/* 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 diff --git a/screen2.0/src/app/downloads/quick-start.tsx b/screen2.0/src/app/downloads/quick-start.tsx index ee21e693..0c753159 100644 --- a/screen2.0/src/app/downloads/quick-start.tsx +++ b/screen2.0/src/app/downloads/quick-start.tsx @@ -13,27 +13,24 @@ import { 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: any; + biosamples: -1 | ApolloQueryResult; } const PROMOTER_MESSAGE = @@ -43,14 +40,17 @@ const ENHANCER_MESSAGE = 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`) } -// This needs to be moved and imports -export const DownloadButton = (props: ButtonProps & { label: string }) => { +const DownloadButton = (props: ButtonProps & { label: string }) => { return ( } - + }> Legend diff --git a/screen2.0/src/common/lib/themes.ts b/screen2.0/src/common/lib/themes.ts index 223d25a2..90d8fa18 100644 --- a/screen2.0/src/common/lib/themes.ts +++ b/screen2.0/src/common/lib/themes.ts @@ -22,11 +22,11 @@ export const defaultTheme = createTheme({ // } }, components: { - // MuiAccordion: { - // defaultProps: { - // elevation: 0, // outline - // }, - // }, + MuiAccordion: { + defaultProps: { + elevation: 0, // outline + }, + }, }, transitions: { easing: { From b510847cc3c374af037d2ded87f4570b6905f000 Mon Sep 17 00:00:00 2001 From: Jonathan Fisher Date: Tue, 15 Aug 2023 10:23:19 -0400 Subject: [PATCH 25/29] More Cleanup --- screen2.0/src/app/search/ccredetails/linkedgenes.tsx | 2 +- screen2.0/src/app/search/ccredetails/queries.ts | 2 +- screen2.0/tailwind.config.js | 4 ---- 3 files changed, 2 insertions(+), 6 deletions(-) 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/tailwind.config.js b/screen2.0/tailwind.config.js index 347bfdb9..079941e9 100644 --- a/screen2.0/tailwind.config.js +++ b/screen2.0/tailwind.config.js @@ -11,8 +11,4 @@ module.exports = { }, }, plugins: [require("prettier-plugin-tailwindcss")], - // corePlugins: { - // preflight: false, - // }, - // important: '#root', } From 3112ff8532c47f555afdf3894fce6ceb0f4a3be9 Mon Sep 17 00:00:00 2001 From: Jonathan Fisher Date: Tue, 15 Aug 2023 10:46:11 -0400 Subject: [PATCH 26/29] Attempt to sync package with main --- screen2.0/package.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/screen2.0/package.json b/screen2.0/package.json index 78814482..982e0546 100644 --- a/screen2.0/package.json +++ b/screen2.0/package.json @@ -39,12 +39,12 @@ "@apollo/experimental-nextjs-app-support": "^0.3.1", "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", - "@mui/icons-material": "^5.11.16", + "@mui/icons-material": "^5.14.3", "@mui/lab": "^5.0.0-alpha.137", - "@mui/material": "^5.13.6", - "@types/node": "^20.4.2", - "@types/react": "^18.2.14", - "@types/react-dom": "18.2.6", + "@mui/material": "^5.14.2", + "@types/node": "^20.4.9", + "@types/react": "^18.2.19", + "@types/react-dom": "18.2.7", "@weng-lab/psychscreen-ui-components": "^0.7.8", "@weng-lab/ts-ztable": "^4.0.1", "autoprefixer": "10.4.14", @@ -86,4 +86,4 @@ "not ie <= 11", "not op_mini all" ] -} +} \ No newline at end of file From c208fcda890f411b7e6c5780040bbc7b4743788d Mon Sep 17 00:00:00 2001 From: Jonathan Fisher <49597360+jpfisher72@users.noreply.github.com> Date: Tue, 15 Aug 2023 10:48:18 -0400 Subject: [PATCH 27/29] Update package.json --- screen2.0/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/screen2.0/package.json b/screen2.0/package.json index 982e0546..3088bc8c 100644 --- a/screen2.0/package.json +++ b/screen2.0/package.json @@ -86,4 +86,4 @@ "not ie <= 11", "not op_mini all" ] -} \ No newline at end of file +} From d939c860f61051bfe22e3687f06e002d07268906 Mon Sep 17 00:00:00 2001 From: Jonathan Fisher Date: Thu, 17 Aug 2023 12:43:36 -0400 Subject: [PATCH 28/29] Small update --- screen2.0/src/app/downloads/data-matrices.tsx | 4 +- screen2.0/yarn.lock | 177 ++++++++++++++++-- 2 files changed, 160 insertions(+), 21 deletions(-) diff --git a/screen2.0/src/app/downloads/data-matrices.tsx b/screen2.0/src/app/downloads/data-matrices.tsx index bac0c3b0..28d7ace6 100644 --- a/screen2.0/src/app/downloads/data-matrices.tsx +++ b/screen2.0/src/app/downloads/data-matrices.tsx @@ -235,7 +235,7 @@ export function DataMatrices(props: TabPanelProps) { fullWidth onClick={() => { if (selectedAssay && selectedAssay.assembly !== variant.assembly || selectedAssay.assay !== variant.assay) { - router.push(`./downloads?tab=2&assembly=${variant.assembly}&assay=${variant.assay}`) + router.push(`/downloads?tab=2&assembly=${variant.assembly}&assay=${variant.assay}`) setSelectedAssay(variant) } }} @@ -373,7 +373,7 @@ export function DataMatrices(props: TabPanelProps) { renderInput={(params) => } getOptionLabel={(biosample: BiosampleUMAP) => biosample.displayname + " — Exp ID: " + biosample.experimentAccession} blurOnSelect - onChange={(event, value: any) => setSearched(value)} + onChange={(_, value: any) => setSearched(value)} size="small" /> diff --git a/screen2.0/yarn.lock b/screen2.0/yarn.lock index ecd99854..8f3133b2 100644 --- a/screen2.0/yarn.lock +++ b/screen2.0/yarn.lock @@ -473,6 +473,29 @@ __metadata: languageName: node linkType: hard +"@mui/base@npm:5.0.0-beta.11": + version: 5.0.0-beta.11 + resolution: "@mui/base@npm:5.0.0-beta.11" + dependencies: + "@babel/runtime": ^7.22.6 + "@emotion/is-prop-valid": ^1.2.1 + "@mui/types": ^7.2.4 + "@mui/utils": ^5.14.5 + "@popperjs/core": ^2.11.8 + clsx: ^2.0.0 + prop-types: ^15.8.1 + react-is: ^18.2.0 + peerDependencies: + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 7a60421c427f3561d3e58abfa223a08ba6fc00e5587ff13c2ebbad52c3ea6bb45bdfa6e8a5cf673be4e90af0aef96b3253ec9098446ba94f5a414eb81e0c3d1a + languageName: node + linkType: hard + "@mui/base@npm:5.0.0-beta.7": version: 5.0.0-beta.7 resolution: "@mui/base@npm:5.0.0-beta.7" @@ -503,7 +526,14 @@ __metadata: languageName: node linkType: hard -"@mui/icons-material@npm:^5.11.0, @mui/icons-material@npm:^5.11.16": +"@mui/core-downloads-tracker@npm:^5.14.5": + version: 5.14.5 + resolution: "@mui/core-downloads-tracker@npm:5.14.5" + checksum: 934fe49cf1a14db380727a83fcd559771b82480ebbbe36ea476e219b91cf08224ca3f0b50b3f218aeb10b537cc61e096d3c3048fd93ae7a17238631b144da241 + languageName: node + linkType: hard + +"@mui/icons-material@npm:^5.11.0": version: 5.14.0 resolution: "@mui/icons-material@npm:5.14.0" dependencies: @@ -519,6 +549,22 @@ __metadata: languageName: node linkType: hard +"@mui/icons-material@npm:^5.14.3": + version: 5.14.3 + resolution: "@mui/icons-material@npm:5.14.3" + dependencies: + "@babel/runtime": ^7.22.6 + peerDependencies: + "@mui/material": ^5.0.0 + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 25ff0261dcbcdde9967779f844d12c85c3ffc79227e50d8c03eade1081c2be855e88d2dbe2a587aa57b5c5c2b742af14f70b1767f7ccfd539d89876a6fc580fb + languageName: node + linkType: hard + "@mui/lab@npm:^5.0.0-alpha.137": version: 5.0.0-alpha.139 resolution: "@mui/lab@npm:5.0.0-alpha.139" @@ -549,7 +595,7 @@ __metadata: languageName: node linkType: hard -"@mui/material@npm:^5.11.7, @mui/material@npm:^5.13.6": +"@mui/material@npm:^5.11.7": version: 5.14.0 resolution: "@mui/material@npm:5.14.0" dependencies: @@ -582,6 +628,39 @@ __metadata: languageName: node linkType: hard +"@mui/material@npm:^5.14.2": + version: 5.14.5 + resolution: "@mui/material@npm:5.14.5" + dependencies: + "@babel/runtime": ^7.22.6 + "@mui/base": 5.0.0-beta.11 + "@mui/core-downloads-tracker": ^5.14.5 + "@mui/system": ^5.14.5 + "@mui/types": ^7.2.4 + "@mui/utils": ^5.14.5 + "@types/react-transition-group": ^4.4.6 + clsx: ^2.0.0 + csstype: ^3.1.2 + prop-types: ^15.8.1 + react-is: ^18.2.0 + react-transition-group: ^4.4.5 + peerDependencies: + "@emotion/react": ^11.5.0 + "@emotion/styled": ^11.3.0 + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@emotion/react": + optional: true + "@emotion/styled": + optional: true + "@types/react": + optional: true + checksum: a3889143be3a5eff0bb7cfce66f677eb6a441f17a958abb2ace09f20cbfd4edb6ade3d63aa616eca0c774abc7167c63b57a05bb172355f3b6f7ac90ce31f55d2 + languageName: node + linkType: hard + "@mui/private-theming@npm:^5.13.7": version: 5.13.7 resolution: "@mui/private-theming@npm:5.13.7" @@ -616,6 +695,23 @@ __metadata: languageName: node linkType: hard +"@mui/private-theming@npm:^5.14.5": + version: 5.14.5 + resolution: "@mui/private-theming@npm:5.14.5" + dependencies: + "@babel/runtime": ^7.22.6 + "@mui/utils": ^5.14.5 + prop-types: ^15.8.1 + peerDependencies: + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 0d42a858725ee52369689f51c5237cd7d296bf2af380954b7406b62f41a09c34820ac698e53475caf1115adb3849b346945fe2dd867d637be7ae182a84c92b56 + languageName: node + linkType: hard + "@mui/styled-engine@npm:^5.13.2": version: 5.13.2 resolution: "@mui/styled-engine@npm:5.13.2" @@ -693,6 +789,34 @@ __metadata: languageName: node linkType: hard +"@mui/system@npm:^5.14.5": + version: 5.14.5 + resolution: "@mui/system@npm:5.14.5" + dependencies: + "@babel/runtime": ^7.22.6 + "@mui/private-theming": ^5.14.5 + "@mui/styled-engine": ^5.13.2 + "@mui/types": ^7.2.4 + "@mui/utils": ^5.14.5 + clsx: ^2.0.0 + csstype: ^3.1.2 + prop-types: ^15.8.1 + peerDependencies: + "@emotion/react": ^11.5.0 + "@emotion/styled": ^11.3.0 + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@emotion/react": + optional: true + "@emotion/styled": + optional: true + "@types/react": + optional: true + checksum: a177012914cf6f86af17e45e15ad489f5203ce5c055d40e77e5152ea0584fa01092c5b27fde956c8d7079b40d9ffd92270edf9c3a5249d4cd217b0dbccadd32d + languageName: node + linkType: hard + "@mui/types@npm:^7.2.4": version: 7.2.4 resolution: "@mui/types@npm:7.2.4" @@ -735,6 +859,21 @@ __metadata: languageName: node linkType: hard +"@mui/utils@npm:^5.14.5": + version: 5.14.5 + resolution: "@mui/utils@npm:5.14.5" + dependencies: + "@babel/runtime": ^7.22.6 + "@types/prop-types": ^15.7.5 + "@types/react-is": ^18.2.1 + prop-types: ^15.8.1 + react-is: ^18.2.0 + peerDependencies: + react: ^17.0.0 || ^18.0.0 + checksum: 7044d73ae41bdfd9c7c6287a3c1391ec4c5395c8f0092eac3ca4f1fd5359068fad29366f39d8072f68493eb5225399463935bbca266c879d630f8ebaa3db96d7 + languageName: node + linkType: hard + "@next/env@npm:13.4.12": version: 13.4.12 resolution: "@next/env@npm:13.4.12" @@ -972,10 +1111,10 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:^20.4.2": - version: 20.4.9 - resolution: "@types/node@npm:20.4.9" - checksum: 504e3da96274f3865c1251830f4750bb0a8f6ef6f8648902cd3bba33370c5f219235471bfbf55cce726b25c8eacfcc8e2aad0ec3b13e27ea6708b00d4a9a46c8 +"@types/node@npm:^20.4.9": + version: 20.5.0 + resolution: "@types/node@npm:20.5.0" + checksum: 659bc5fc93b5c02bd88ca4bfae4f6b9dc307d45884d1dd9d69df85819a9943cdc00cd3c87eec3048866df6a67f52297f74d170e47a44f61edb3e8f770d94e85e languageName: node linkType: hard @@ -993,12 +1132,12 @@ __metadata: languageName: node linkType: hard -"@types/react-dom@npm:18.2.6": - version: 18.2.6 - resolution: "@types/react-dom@npm:18.2.6" +"@types/react-dom@npm:18.2.7": + version: 18.2.7 + resolution: "@types/react-dom@npm:18.2.7" dependencies: "@types/react": "*" - checksum: b56e42efab121a3a8013d2eb8c1688e6028a25ea6d33c4362d2846f0af3760b164b4d7c34846614024cfb8956cca70dd1743487f152e32ff89a00fe6fbd2be54 + checksum: e02ea908289a7ad26053308248d2b87f6aeafd73d0e2de2a3d435947bcea0422599016ffd1c3e38ff36c42f5e1c87c7417f05b0a157e48649e4a02f21727d54f languageName: node linkType: hard @@ -1031,14 +1170,14 @@ __metadata: languageName: node linkType: hard -"@types/react@npm:^18.2.14": - version: 18.2.19 - resolution: "@types/react@npm:18.2.19" +"@types/react@npm:^18.2.19": + version: 18.2.20 + resolution: "@types/react@npm:18.2.20" dependencies: "@types/prop-types": "*" "@types/scheduler": "*" csstype: ^3.0.2 - checksum: 1ef657b90c7413451bbac2fd2fbce4f8a093941bc5041d344ab9833bc113c8eebf6318dae8aeeb1a0f922f15bc772507e6aaa0c7b51847b5f7302921c8dd6740 + checksum: 30f699c60e5e4bfef273ce64d320651cdd60f5c6a08361c6c7eca8cebcccda1ac953d2ee57c9f321b5ae87f8a62c72b6d35ca42df0e261d337849952daab2141 languageName: node linkType: hard @@ -6539,12 +6678,12 @@ __metadata: "@apollo/experimental-nextjs-app-support": ^0.3.1 "@emotion/react": ^11.11.1 "@emotion/styled": ^11.11.0 - "@mui/icons-material": ^5.11.16 + "@mui/icons-material": ^5.14.3 "@mui/lab": ^5.0.0-alpha.137 - "@mui/material": ^5.13.6 - "@types/node": ^20.4.2 - "@types/react": ^18.2.14 - "@types/react-dom": 18.2.6 + "@mui/material": ^5.14.2 + "@types/node": ^20.4.9 + "@types/react": ^18.2.19 + "@types/react-dom": 18.2.7 "@weng-lab/psychscreen-ui-components": ^0.7.8 "@weng-lab/ts-ztable": ^4.0.1 autoprefixer: 10.4.14 From 069f16e518ce7a654007a2ce6c8fab13c458897e Mon Sep 17 00:00:00 2001 From: Jonathan Fisher Date: Fri, 18 Aug 2023 16:13:41 -0400 Subject: [PATCH 29/29] Sync lockfile --- screen2.0/yarn.lock | 306 +++++++++++++++++++++++--------------------- 1 file changed, 157 insertions(+), 149 deletions(-) diff --git a/screen2.0/yarn.lock b/screen2.0/yarn.lock index 8f3133b2..6dd96bb9 100644 --- a/screen2.0/yarn.lock +++ b/screen2.0/yarn.lock @@ -312,9 +312,9 @@ __metadata: languageName: node linkType: hard -"@eslint/eslintrc@npm:^2.1.1": - version: 2.1.1 - resolution: "@eslint/eslintrc@npm:2.1.1" +"@eslint/eslintrc@npm:^2.1.2": + version: 2.1.2 + resolution: "@eslint/eslintrc@npm:2.1.2" dependencies: ajv: ^6.12.4 debug: ^4.3.2 @@ -325,14 +325,14 @@ __metadata: js-yaml: ^4.1.0 minimatch: ^3.1.2 strip-json-comments: ^3.1.1 - checksum: bf909ea183d27238c257a82d4ffdec38ca94b906b4b8dfae02ecbe7ecc9e5a8182ef5e469c808bb8cb4fea4750f43ac4ca7c4b4a167b6cd7e3aaacd386b2bd25 + checksum: bc742a1e3b361f06fedb4afb6bf32cbd27171292ef7924f61c62f2aed73048367bcc7ac68f98c06d4245cd3fabc43270f844e3c1699936d4734b3ac5398814a7 languageName: node linkType: hard -"@eslint/js@npm:^8.46.0": - version: 8.46.0 - resolution: "@eslint/js@npm:8.46.0" - checksum: 7aed479832302882faf5bec37e9d068f270f84c19b3fb529646a7c1b031e73a312f730569c78806492bc09cfce3d7651dfab4ce09a56cbb06bc6469449e56377 +"@eslint/js@npm:^8.47.0": + version: 8.47.0 + resolution: "@eslint/js@npm:8.47.0" + checksum: 0ef57fe27b6d4c305b33f3b2d2fee1ab397a619006f1d6f4ce5ee4746b8f03d11a4e098805a7d78601ca534cf72917d37f0ac19896c992a32e26299ecb9f9de1 languageName: node linkType: hard @@ -450,14 +450,14 @@ __metadata: languageName: node linkType: hard -"@mui/base@npm:5.0.0-beta.10": - version: 5.0.0-beta.10 - resolution: "@mui/base@npm:5.0.0-beta.10" +"@mui/base@npm:5.0.0-beta.11": + version: 5.0.0-beta.11 + resolution: "@mui/base@npm:5.0.0-beta.11" dependencies: "@babel/runtime": ^7.22.6 "@emotion/is-prop-valid": ^1.2.1 "@mui/types": ^7.2.4 - "@mui/utils": ^5.14.4 + "@mui/utils": ^5.14.5 "@popperjs/core": ^2.11.8 clsx: ^2.0.0 prop-types: ^15.8.1 @@ -469,20 +469,20 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: 4190213fea4715fb3928828339389aeb69620d3f992d42c79422ddaa76540890d3df3468658e4aa071712ec6efc0bba286ef6c7820daeaad6f1d22fedd692afd + checksum: 7a60421c427f3561d3e58abfa223a08ba6fc00e5587ff13c2ebbad52c3ea6bb45bdfa6e8a5cf673be4e90af0aef96b3253ec9098446ba94f5a414eb81e0c3d1a languageName: node linkType: hard -"@mui/base@npm:5.0.0-beta.11": - version: 5.0.0-beta.11 - resolution: "@mui/base@npm:5.0.0-beta.11" +"@mui/base@npm:5.0.0-beta.7": + version: 5.0.0-beta.7 + resolution: "@mui/base@npm:5.0.0-beta.7" dependencies: - "@babel/runtime": ^7.22.6 + "@babel/runtime": ^7.22.5 "@emotion/is-prop-valid": ^1.2.1 "@mui/types": ^7.2.4 - "@mui/utils": ^5.14.5 + "@mui/utils": ^5.13.7 "@popperjs/core": ^2.11.8 - clsx: ^2.0.0 + clsx: ^1.2.1 prop-types: ^15.8.1 react-is: ^18.2.0 peerDependencies: @@ -492,18 +492,18 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: 7a60421c427f3561d3e58abfa223a08ba6fc00e5587ff13c2ebbad52c3ea6bb45bdfa6e8a5cf673be4e90af0aef96b3253ec9098446ba94f5a414eb81e0c3d1a + checksum: 2b524f2a334818c6abe2419e24ded29b6fdb78375077ea6d16bfc55fd6e173cc21f6fb6286feb29215632e7f247b523244b5a1c809303570854fb15de5e83f47 languageName: node linkType: hard -"@mui/base@npm:5.0.0-beta.7": - version: 5.0.0-beta.7 - resolution: "@mui/base@npm:5.0.0-beta.7" +"@mui/base@npm:5.0.0-beta.8": + version: 5.0.0-beta.8 + resolution: "@mui/base@npm:5.0.0-beta.8" dependencies: - "@babel/runtime": ^7.22.5 + "@babel/runtime": ^7.22.6 "@emotion/is-prop-valid": ^1.2.1 "@mui/types": ^7.2.4 - "@mui/utils": ^5.13.7 + "@mui/utils": ^5.14.1 "@popperjs/core": ^2.11.8 clsx: ^1.2.1 prop-types: ^15.8.1 @@ -515,7 +515,7 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: 2b524f2a334818c6abe2419e24ded29b6fdb78375077ea6d16bfc55fd6e173cc21f6fb6286feb29215632e7f247b523244b5a1c809303570854fb15de5e83f47 + checksum: 669f99a92d403dd74eccf419d12fbe5061ce1cec4621a72376f176f220a5be61fe8cd496da20afdbf6f5377a22a6ffe79442970926db96a44241d38cc5fbc4e4 languageName: node linkType: hard @@ -526,10 +526,10 @@ __metadata: languageName: node linkType: hard -"@mui/core-downloads-tracker@npm:^5.14.5": - version: 5.14.5 - resolution: "@mui/core-downloads-tracker@npm:5.14.5" - checksum: 934fe49cf1a14db380727a83fcd559771b82480ebbbe36ea476e219b91cf08224ca3f0b50b3f218aeb10b537cc61e096d3c3048fd93ae7a17238631b144da241 +"@mui/core-downloads-tracker@npm:^5.14.2": + version: 5.14.2 + resolution: "@mui/core-downloads-tracker@npm:5.14.2" + checksum: ea8032d101b190c2eb5bc67378a9142a56c15d6341ef6f9ad244921f1ba042e301328a132ecfc7a1473a09c56b11333b83859d12e50c12d1ee7a6a26eff27e36 languageName: node linkType: hard @@ -566,14 +566,14 @@ __metadata: linkType: hard "@mui/lab@npm:^5.0.0-alpha.137": - version: 5.0.0-alpha.139 - resolution: "@mui/lab@npm:5.0.0-alpha.139" + version: 5.0.0-alpha.140 + resolution: "@mui/lab@npm:5.0.0-alpha.140" dependencies: "@babel/runtime": ^7.22.6 - "@mui/base": 5.0.0-beta.10 - "@mui/system": ^5.14.4 + "@mui/base": 5.0.0-beta.11 + "@mui/system": ^5.14.5 "@mui/types": ^7.2.4 - "@mui/utils": ^5.14.4 + "@mui/utils": ^5.14.5 clsx: ^2.0.0 prop-types: ^15.8.1 react-is: ^18.2.0 @@ -591,7 +591,7 @@ __metadata: optional: true "@types/react": optional: true - checksum: 99974aaef49abc942a14558df50bdc7fbd1d9d2613d039017b605f6e4188e1a78e639a687d0d6531ce21af9350f2250a5e8906055dead262d1f6dd55fbef92ae + checksum: 8eb8115b8def96b2a7da16dc4e5e80edd24ca9c0d62c450692668ac6eecd838fc7dd71e0b1a9b20575396f8c311518e6cc851f6c28b1690dff7fbb8e39a5dd63 languageName: node linkType: hard @@ -629,17 +629,17 @@ __metadata: linkType: hard "@mui/material@npm:^5.14.2": - version: 5.14.5 - resolution: "@mui/material@npm:5.14.5" + version: 5.14.2 + resolution: "@mui/material@npm:5.14.2" dependencies: "@babel/runtime": ^7.22.6 - "@mui/base": 5.0.0-beta.11 - "@mui/core-downloads-tracker": ^5.14.5 - "@mui/system": ^5.14.5 + "@mui/base": 5.0.0-beta.8 + "@mui/core-downloads-tracker": ^5.14.2 + "@mui/system": ^5.14.1 "@mui/types": ^7.2.4 - "@mui/utils": ^5.14.5 + "@mui/utils": ^5.14.1 "@types/react-transition-group": ^4.4.6 - clsx: ^2.0.0 + clsx: ^1.2.1 csstype: ^3.1.2 prop-types: ^15.8.1 react-is: ^18.2.0 @@ -657,7 +657,7 @@ __metadata: optional: true "@types/react": optional: true - checksum: a3889143be3a5eff0bb7cfce66f677eb6a441f17a958abb2ace09f20cbfd4edb6ade3d63aa616eca0c774abc7167c63b57a05bb172355f3b6f7ac90ce31f55d2 + checksum: 271ccb56133c43b98338240dfa169c781c8dc9e8cc6e51188d539b30f1744957bda903d24684e532f213184f2522b5120457ceb3fc85e97ba84c1df637dce66a languageName: node linkType: hard @@ -678,23 +678,6 @@ __metadata: languageName: node linkType: hard -"@mui/private-theming@npm:^5.14.4": - version: 5.14.4 - resolution: "@mui/private-theming@npm:5.14.4" - dependencies: - "@babel/runtime": ^7.22.6 - "@mui/utils": ^5.14.4 - prop-types: ^15.8.1 - peerDependencies: - "@types/react": ^17.0.0 || ^18.0.0 - react: ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 822487a6bd2cc06397b4158dd79283fa6829410d3abd16aa7c12d8569512bfa5f2b6db707b2b2e2f4fa59fc62286057b8184428c7e1cf8147eb1649c426b164c - languageName: node - linkType: hard - "@mui/private-theming@npm:^5.14.5": version: 5.14.5 resolution: "@mui/private-theming@npm:5.14.5" @@ -761,16 +744,16 @@ __metadata: languageName: node linkType: hard -"@mui/system@npm:^5.14.4": - version: 5.14.4 - resolution: "@mui/system@npm:5.14.4" +"@mui/system@npm:^5.14.1": + version: 5.14.1 + resolution: "@mui/system@npm:5.14.1" dependencies: "@babel/runtime": ^7.22.6 - "@mui/private-theming": ^5.14.4 + "@mui/private-theming": ^5.13.7 "@mui/styled-engine": ^5.13.2 "@mui/types": ^7.2.4 - "@mui/utils": ^5.14.4 - clsx: ^2.0.0 + "@mui/utils": ^5.14.1 + clsx: ^1.2.1 csstype: ^3.1.2 prop-types: ^15.8.1 peerDependencies: @@ -785,7 +768,7 @@ __metadata: optional: true "@types/react": optional: true - checksum: 1f0df9872456f3876d6963bb661212e5030ca7218f4687b649d1a969f9c27f707c1cc4687d375257c75cbabd39cd402c5a16d4739b37e94f89f0a5eb9827edd1 + checksum: d3ab547bdba9544dda51c62e081481caafe5e64ea64cf4a58c8b060f83705a7aa53ebfd843f946567db6a65755635adf80ed3f4103e29dcc7ba1839381583c53 languageName: node linkType: hard @@ -844,9 +827,9 @@ __metadata: languageName: node linkType: hard -"@mui/utils@npm:^5.14.4": - version: 5.14.4 - resolution: "@mui/utils@npm:5.14.4" +"@mui/utils@npm:^5.14.1": + version: 5.14.1 + resolution: "@mui/utils@npm:5.14.1" dependencies: "@babel/runtime": ^7.22.6 "@types/prop-types": ^15.7.5 @@ -855,7 +838,7 @@ __metadata: react-is: ^18.2.0 peerDependencies: react: ^17.0.0 || ^18.0.0 - checksum: b0084c55dc15c304e93832a23c567e41f2b152242dee3dc2578ce4b3d5177d604994abe1fd39b38a23d049592126a71ecf5ac9fe9f141155aeb4cce06241df92 + checksum: 39b1ab8d428f1783d0f7621b4ab284f7d035920c43c527114d865ba2d7d467ead850528a042ea986b76d4bac1ad6fc9cb0541add0d17d29d5ad59460c69106d1 languageName: node linkType: hard @@ -874,10 +857,10 @@ __metadata: languageName: node linkType: hard -"@next/env@npm:13.4.12": - version: 13.4.12 - resolution: "@next/env@npm:13.4.12" - checksum: 2ccb2e271b3c42697c1e807cdf988429fcb563f80fa0ca72512f65f47cbbcc46c44fc53bf055814d4b467f1394de8c1a1ef6aad14d35f9993004faa956466d02 +"@next/env@npm:13.4.18": + version: 13.4.18 + resolution: "@next/env@npm:13.4.18" + checksum: 7e9361df74d9dd3a9f691ba4f950fec68de0b0e392f7751dab3039ccea74261060440a6bb1b7e4f093ed2d8d0530fa51852285469eff2c9dc9c432e9a6a7f936 languageName: node linkType: hard @@ -890,65 +873,65 @@ __metadata: languageName: node linkType: hard -"@next/swc-darwin-arm64@npm:13.4.12": - version: 13.4.12 - resolution: "@next/swc-darwin-arm64@npm:13.4.12" +"@next/swc-darwin-arm64@npm:13.4.18": + version: 13.4.18 + resolution: "@next/swc-darwin-arm64@npm:13.4.18" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@next/swc-darwin-x64@npm:13.4.12": - version: 13.4.12 - resolution: "@next/swc-darwin-x64@npm:13.4.12" +"@next/swc-darwin-x64@npm:13.4.18": + version: 13.4.18 + resolution: "@next/swc-darwin-x64@npm:13.4.18" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@next/swc-linux-arm64-gnu@npm:13.4.12": - version: 13.4.12 - resolution: "@next/swc-linux-arm64-gnu@npm:13.4.12" +"@next/swc-linux-arm64-gnu@npm:13.4.18": + version: 13.4.18 + resolution: "@next/swc-linux-arm64-gnu@npm:13.4.18" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@next/swc-linux-arm64-musl@npm:13.4.12": - version: 13.4.12 - resolution: "@next/swc-linux-arm64-musl@npm:13.4.12" +"@next/swc-linux-arm64-musl@npm:13.4.18": + version: 13.4.18 + resolution: "@next/swc-linux-arm64-musl@npm:13.4.18" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@next/swc-linux-x64-gnu@npm:13.4.12": - version: 13.4.12 - resolution: "@next/swc-linux-x64-gnu@npm:13.4.12" +"@next/swc-linux-x64-gnu@npm:13.4.18": + version: 13.4.18 + resolution: "@next/swc-linux-x64-gnu@npm:13.4.18" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@next/swc-linux-x64-musl@npm:13.4.12": - version: 13.4.12 - resolution: "@next/swc-linux-x64-musl@npm:13.4.12" +"@next/swc-linux-x64-musl@npm:13.4.18": + version: 13.4.18 + resolution: "@next/swc-linux-x64-musl@npm:13.4.18" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@next/swc-win32-arm64-msvc@npm:13.4.12": - version: 13.4.12 - resolution: "@next/swc-win32-arm64-msvc@npm:13.4.12" +"@next/swc-win32-arm64-msvc@npm:13.4.18": + version: 13.4.18 + resolution: "@next/swc-win32-arm64-msvc@npm:13.4.18" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@next/swc-win32-ia32-msvc@npm:13.4.12": - version: 13.4.12 - resolution: "@next/swc-win32-ia32-msvc@npm:13.4.12" +"@next/swc-win32-ia32-msvc@npm:13.4.18": + version: 13.4.18 + resolution: "@next/swc-win32-ia32-msvc@npm:13.4.18" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@next/swc-win32-x64-msvc@npm:13.4.12": - version: 13.4.12 - resolution: "@next/swc-win32-x64-msvc@npm:13.4.12" +"@next/swc-win32-x64-msvc@npm:13.4.18": + version: 13.4.18 + resolution: "@next/swc-win32-x64-msvc@npm:13.4.18" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -1111,7 +1094,7 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:^20.4.9": +"@types/node@npm:^20.5.0": version: 20.5.0 resolution: "@types/node@npm:20.5.0" checksum: 659bc5fc93b5c02bd88ca4bfae4f6b9dc307d45884d1dd9d69df85819a9943cdc00cd3c87eec3048866df6a67f52297f74d170e47a44f61edb3e8f770d94e85e @@ -1170,7 +1153,7 @@ __metadata: languageName: node linkType: hard -"@types/react@npm:^18.2.19": +"@types/react@npm:^18.2.20": version: 18.2.20 resolution: "@types/react@npm:18.2.20" dependencies: @@ -1818,12 +1801,12 @@ __metadata: languageName: node linkType: hard -"autoprefixer@npm:10.4.14": - version: 10.4.14 - resolution: "autoprefixer@npm:10.4.14" +"autoprefixer@npm:10.4.15": + version: 10.4.15 + resolution: "autoprefixer@npm:10.4.15" dependencies: - browserslist: ^4.21.5 - caniuse-lite: ^1.0.30001464 + browserslist: ^4.21.10 + caniuse-lite: ^1.0.30001520 fraction.js: ^4.2.0 normalize-range: ^0.1.2 picocolors: ^1.0.0 @@ -1832,7 +1815,7 @@ __metadata: postcss: ^8.1.0 bin: autoprefixer: bin/autoprefixer - checksum: e9f18e664a4e4a54a8f4ec5f6b49ed228ec45afaa76efcae361c93721795dc5ab644f36d2fdfc0dea446b02a8067b9372f91542ea431994399e972781ed46d95 + checksum: d490b14fb098c043e109fc13cd23628f146af99a493d35b9df3a26f8ec0b4dd8937c5601cdbaeb465b98ea31d3ea05aa7184711d4d93dfb52358d073dcb67032 languageName: node linkType: hard @@ -2023,7 +2006,7 @@ __metadata: languageName: node linkType: hard -"browserslist@npm:^4.14.5, browserslist@npm:^4.21.5": +"browserslist@npm:^4.14.5": version: 4.21.9 resolution: "browserslist@npm:4.21.9" dependencies: @@ -2037,6 +2020,20 @@ __metadata: languageName: node linkType: hard +"browserslist@npm:^4.21.10": + version: 4.21.10 + resolution: "browserslist@npm:4.21.10" + dependencies: + caniuse-lite: ^1.0.30001517 + electron-to-chromium: ^1.4.477 + node-releases: ^2.0.13 + update-browserslist-db: ^1.0.11 + bin: + browserslist: cli.js + checksum: 1e27c0f111a35d1dd0e8fc2c61781b0daefabc2c9471b0b10537ce54843014bceb2a1ce4571af1a82b2bf1e6e6e05d38865916689a158f03bc2c7a4ec2577db8 + languageName: node + linkType: hard + "buffer-from@npm:^1.0.0": version: 1.1.2 resolution: "buffer-from@npm:1.1.2" @@ -2130,13 +2127,20 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.30001406, caniuse-lite@npm:^1.0.30001464, caniuse-lite@npm:^1.0.30001503": +"caniuse-lite@npm:^1.0.30001406, caniuse-lite@npm:^1.0.30001503": version: 1.0.30001515 resolution: "caniuse-lite@npm:1.0.30001515" checksum: ec5d51785aea6af5cf62ca9d35821d36ab7fa0f85e3e7f752d532025ad59e07131fa3cb3a0a6c486b5ac8620c8c3440e761dc5b38c990d49c17655906f216123 languageName: node linkType: hard +"caniuse-lite@npm:^1.0.30001517, caniuse-lite@npm:^1.0.30001520": + version: 1.0.30001521 + resolution: "caniuse-lite@npm:1.0.30001521" + checksum: be2a2b2cd3be03401887aaa31b89f3e7c6230289e6ef704e224268389cc136480fca502ac9e5001a65ff1e50459d3d95f8c4b2d39f878ab9843af3d6f372c8bb + languageName: node + linkType: hard + "chalk@npm:5.2.0": version: 5.2.0 resolution: "chalk@npm:5.2.0" @@ -2843,6 +2847,13 @@ __metadata: languageName: node linkType: hard +"electron-to-chromium@npm:^1.4.477": + version: 1.4.495 + resolution: "electron-to-chromium@npm:1.4.495" + checksum: b076b1f5ef61f45ca03f4dce47ec280c705405b0cfd3741cc791ef0172a73122846bdf4bddddc4120dece693166e17fe0d6efc847664ecc5852fbec4df9c3153 + languageName: node + linkType: hard + "emoji-regex@npm:^8.0.0": version: 8.0.0 resolution: "emoji-regex@npm:8.0.0" @@ -3242,21 +3253,21 @@ __metadata: languageName: node linkType: hard -"eslint-visitor-keys@npm:^3.4.2": - version: 3.4.2 - resolution: "eslint-visitor-keys@npm:3.4.2" - checksum: 9e0e7e4aaea705c097ae37c97410e5f167d4d2193be2edcb1f0760762ede3df01545e4820ae314f42dcec687745f2c6dcaf6d83575c4a2a241eb0c8517d724f2 +"eslint-visitor-keys@npm:^3.4.3": + version: 3.4.3 + resolution: "eslint-visitor-keys@npm:3.4.3" + checksum: 36e9ef87fca698b6fd7ca5ca35d7b2b6eeaaf106572e2f7fd31c12d3bfdaccdb587bba6d3621067e5aece31c8c3a348b93922ab8f7b2cbc6aaab5e1d89040c60 languageName: node linkType: hard -"eslint@npm:8.46.0": - version: 8.46.0 - resolution: "eslint@npm:8.46.0" +"eslint@npm:8.47.0": + version: 8.47.0 + resolution: "eslint@npm:8.47.0" dependencies: "@eslint-community/eslint-utils": ^4.2.0 "@eslint-community/regexpp": ^4.6.1 - "@eslint/eslintrc": ^2.1.1 - "@eslint/js": ^8.46.0 + "@eslint/eslintrc": ^2.1.2 + "@eslint/js": ^8.47.0 "@humanwhocodes/config-array": ^0.11.10 "@humanwhocodes/module-importer": ^1.0.1 "@nodelib/fs.walk": ^1.2.8 @@ -3267,7 +3278,7 @@ __metadata: doctrine: ^3.0.0 escape-string-regexp: ^4.0.0 eslint-scope: ^7.2.2 - eslint-visitor-keys: ^3.4.2 + eslint-visitor-keys: ^3.4.3 espree: ^9.6.1 esquery: ^1.4.2 esutils: ^2.0.2 @@ -3292,7 +3303,7 @@ __metadata: text-table: ^0.2.0 bin: eslint: bin/eslint.js - checksum: 7a7d36b1a3bbc12e08fbb5bc36fd482a7a5a1797e62e762499dd45601b9e45aaa53a129f31ce0b4444551a9639b8b681ad535f379893dd1e3ae37b31dccd82aa + checksum: 1988617f703eadc5c7540468d54dc8e5171cf2bb9483f6172799cd1ff54a9a5e4470f003784e8cef92687eaa14de37172732787040e67817581a20bcb9c15970 languageName: node linkType: hard @@ -5312,20 +5323,20 @@ __metadata: languageName: node linkType: hard -"next@npm:13.4.12": - version: 13.4.12 - resolution: "next@npm:13.4.12" +"next@npm:13.4.18": + version: 13.4.18 + resolution: "next@npm:13.4.18" dependencies: - "@next/env": 13.4.12 - "@next/swc-darwin-arm64": 13.4.12 - "@next/swc-darwin-x64": 13.4.12 - "@next/swc-linux-arm64-gnu": 13.4.12 - "@next/swc-linux-arm64-musl": 13.4.12 - "@next/swc-linux-x64-gnu": 13.4.12 - "@next/swc-linux-x64-musl": 13.4.12 - "@next/swc-win32-arm64-msvc": 13.4.12 - "@next/swc-win32-ia32-msvc": 13.4.12 - "@next/swc-win32-x64-msvc": 13.4.12 + "@next/env": 13.4.18 + "@next/swc-darwin-arm64": 13.4.18 + "@next/swc-darwin-x64": 13.4.18 + "@next/swc-linux-arm64-gnu": 13.4.18 + "@next/swc-linux-arm64-musl": 13.4.18 + "@next/swc-linux-x64-gnu": 13.4.18 + "@next/swc-linux-x64-musl": 13.4.18 + "@next/swc-win32-arm64-msvc": 13.4.18 + "@next/swc-win32-ia32-msvc": 13.4.18 + "@next/swc-win32-x64-msvc": 13.4.18 "@swc/helpers": 0.5.1 busboy: 1.6.0 caniuse-lite: ^1.0.30001406 @@ -5335,7 +5346,6 @@ __metadata: zod: 3.21.4 peerDependencies: "@opentelemetry/api": ^1.1.0 - fibers: ">= 3.1.0" react: ^18.2.0 react-dom: ^18.2.0 sass: ^1.3.0 @@ -5361,13 +5371,11 @@ __metadata: peerDependenciesMeta: "@opentelemetry/api": optional: true - fibers: - optional: true sass: optional: true bin: next: dist/bin/next - checksum: 50bd443ffe09424c1a94d6606d41886ccd1d65185e125aa199957ea92c5e4d1c226f1675f3e5ea92e88f43f8355824ba50db52a8aeae225f7a86b6c901d25527 + checksum: cd3ac740d6111cabdfe8b8396c35314cf95d02df1b984e046f166b7d26fe5a0a99c58730d8b7d15da33eb6d8e5b6e3276e19c616417794b44681bf3ac1e669db languageName: node linkType: hard @@ -5410,7 +5418,7 @@ __metadata: languageName: node linkType: hard -"node-releases@npm:^2.0.12": +"node-releases@npm:^2.0.12, node-releases@npm:^2.0.13": version: 2.0.13 resolution: "node-releases@npm:2.0.13" checksum: 17ec8f315dba62710cae71a8dad3cd0288ba943d2ece43504b3b1aa8625bf138637798ab470b1d9035b0545996f63000a8a926e0f6d35d0996424f8b6d36dda3 @@ -6682,18 +6690,18 @@ __metadata: "@mui/lab": ^5.0.0-alpha.137 "@mui/material": ^5.14.2 "@types/node": ^20.4.9 - "@types/react": ^18.2.19 + "@types/react": ^18.2.20 "@types/react-dom": 18.2.7 "@weng-lab/psychscreen-ui-components": ^0.7.8 "@weng-lab/ts-ztable": ^4.0.1 - autoprefixer: 10.4.14 - eslint: 8.46.0 + autoprefixer: 10.4.15 + eslint: 8.47.0 eslint-config-next: 13.4.10 file-loader: ^6.2.0 graphql: ^16.7.1 jubilant-carnival: ^0.6.0 lint-staged: ^13.2.3 - next: 13.4.12 + next: 13.4.18 normalize.css: ^8.0.1 only: ^0.0.2 postcss: 8.4.27 @@ -7731,11 +7739,11 @@ __metadata: "typescript@patch:typescript@5.1.6#~builtin": version: 5.1.6 - resolution: "typescript@patch:typescript@npm%3A5.1.6#~builtin::version=5.1.6&hash=85af82" + resolution: "typescript@patch:typescript@npm%3A5.1.6#~builtin::version=5.1.6&hash=5da071" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 21e88b0a0c0226f9cb9fd25b9626fb05b4c0f3fddac521844a13e1f30beb8f14e90bd409a9ac43c812c5946d714d6e0dee12d5d02dfc1c562c5aacfa1f49b606 + checksum: f53bfe97f7c8b2b6d23cf572750d4e7d1e0c5fff1c36d859d0ec84556a827b8785077bc27676bf7e71fae538e517c3ecc0f37e7f593be913d884805d931bc8be languageName: node linkType: hard @@ -8143,4 +8151,4 @@ __metadata: resolution: "zod@npm:3.21.4" checksum: f185ba87342ff16f7a06686767c2b2a7af41110c7edf7c1974095d8db7a73792696bcb4a00853de0d2edeb34a5b2ea6a55871bc864227dace682a0a28de33e1f languageName: node - linkType: hard + linkType: hard \ No newline at end of file