Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gene expression app & RAMPAGE tab #76

Merged
merged 47 commits into from
Jul 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
2df29b6
initial upload, added fetch, buttons, title
jordanvelezbomba Jul 13, 2023
7c4c477
added types for gene exp
jordanvelezbomba Jul 17, 2023
276bf8b
added expression plot, fixed buttons, and added gene autocomplete
jordanvelezbomba Jul 17, 2023
b740517
fixed gene autocomplete
jordanvelezbomba Jul 17, 2023
d73b724
Merge branch 'main' of https://github.com/weng-lab/SCREEN2.0 into gen…
jordanvelezbomba Jul 17, 2023
ee5de76
added rampage tab and adjusted spacing
jordanvelezbomba Jul 18, 2023
8b85494
fixed scaling and adjusted dimensions
jordanvelezbomba Jul 18, 2023
d3e2364
changed tab name
jordanvelezbomba Jul 18, 2023
f11fda0
added sort, zero switch, and transcript select
jordanvelezbomba Jul 18, 2023
09cce9d
formatted numbers
jordanvelezbomba Jul 18, 2023
6fb4c27
Merge branch 'main' of https://github.com/weng-lab/SCREEN2.0 into gen…
jordanvelezbomba Jul 18, 2023
3458efc
spacing, prettier
jordanvelezbomba Jul 19, 2023
73a224d
Merge branch 'gene-expression' of https://github.com/weng-lab/SCREEN2…
jordanvelezbomba Jul 19, 2023
04a44ee
change rampage tab name
jordanvelezbomba Jul 20, 2023
2103e32
added dropdowns to graph, added drawer, and fixed scaling
jordanvelezbomba Jul 20, 2023
187fb99
added settings
jordanvelezbomba Jul 24, 2023
645f9d6
replaced details tab with hamburger
jordanvelezbomba Jul 24, 2023
bf96d05
updated error logger
jordanvelezbomba Jul 24, 2023
17cd31f
hyperlinked genes in main table
jordanvelezbomba Jul 24, 2023
1063bba
added gene expression tab to details
jordanvelezbomba Jul 24, 2023
39a22ff
upated types
jordanvelezbomba Jul 24, 2023
f9514d5
added collapse all, removed outline, and fixed scaling
jordanvelezbomba Jul 24, 2023
0739ae9
added toolbar, added url nav, fixed search, and added collapse all
jordanvelezbomba Jul 24, 2023
1dcabc3
added header and updated descriptions
jordanvelezbomba Jul 24, 2023
728be11
adjusted buttons / spacing, fixed plot scaling, and added collapse all
jordanvelezbomba Jul 24, 2023
d8b36fa
prettier
jordanvelezbomba Jul 24, 2023
a1ec233
fixed link pathname and error utility
jordanvelezbomba Jul 25, 2023
3076a81
added keys, cleaned types
jordanvelezbomba Jul 25, 2023
d1d17a6
fixed hamburger height and width, cleaned types
jordanvelezbomba Jul 25, 2023
ef2baff
changed error util
jordanvelezbomba Jul 25, 2023
24897f5
changed default export for build
jordanvelezbomba Jul 25, 2023
be2b9b6
Merge branch 'main' into gene-expression
jordanvelezbomba Jul 25, 2023
d97421d
moved gene-expression tab
jordanvelezbomba Jul 25, 2023
13e2f91
fixed default export
jordanvelezbomba Jul 25, 2023
f9adecc
fixed error handler
jordanvelezbomba Jul 25, 2023
7c4fc16
rerun checks
jordanvelezbomba Jul 25, 2023
ba1a059
changed header color
jordanvelezbomba Jul 25, 2023
719a777
added theme
jordanvelezbomba Jul 26, 2023
cb47d69
fixed collapse all, changed theme
jordanvelezbomba Jul 26, 2023
47a28ea
added all track colors
jordanvelezbomba Jul 26, 2023
03fbb87
updated theme
jordanvelezbomba Jul 26, 2023
918f361
updated theme
jordanvelezbomba Jul 26, 2023
678fdb7
updated theme
jordanvelezbomba Jul 26, 2023
ef41315
cleaned up code, moved utils
jordanvelezbomba Jul 26, 2023
a2e123e
replaced autocomplete with select
jordanvelezbomba Jul 26, 2023
53044f2
cleaned up
jordanvelezbomba Jul 26, 2023
b6b901e
updated collapse all
jordanvelezbomba Jul 26, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 17 additions & 17 deletions screen2.0/src/app/applets/differential-gene-expression/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ export default function DifferentialGeneExpression() {
if (!response.ok) {
// throw new Error(response.statusText)
setError(true)
return ErrorMessage(new Error(response.statusText))
return <ErrorMessage error={new Error(response.statusText)} />
}
return response.json()
})
Expand All @@ -99,7 +99,7 @@ export default function DifferentialGeneExpression() {
.catch((error: Error) => {
// logging
// throw error
return ErrorMessage(error)
return <ErrorMessage error={error} />
})
setLoading(true)
}, [])
Expand All @@ -124,7 +124,7 @@ export default function DifferentialGeneExpression() {
if (!response.ok) {
// throw new Error(response.statusText)
setError(true)
return ErrorMessage(new Error(response.statusText))
return <ErrorMessage error={new Error(response.statusText)} />
}
return response.json()
})
Expand Down Expand Up @@ -170,7 +170,7 @@ export default function DifferentialGeneExpression() {
.catch((error: Error) => {
// logging
// throw error
return ErrorMessage(error)
return <ErrorMessage error={error} />
})
setLoadingChart(true)
}, [ct1, ct2, gene])
Expand Down Expand Up @@ -243,7 +243,7 @@ export default function DifferentialGeneExpression() {
// const cellTypes2 = await getCellTypes()

return loading ? (
LoadingMessage()
<LoadingMessage />
) : (
<main>
<Grid2 container spacing={3} sx={{ mt: "2rem" }}>
Expand Down Expand Up @@ -291,9 +291,9 @@ export default function DifferentialGeneExpression() {
<Grid2 xs={9}>
<Box mb={1}>
{errorLoading
? ErrorMessage(new Error("Error loading data"))
? <ErrorMessage error={new Error("Error loading")} />
: loadingChart
? LoadingMessage()
? <LoadingMessage />
: data &&
data.gene &&
data[data.gene] &&
Expand Down Expand Up @@ -429,7 +429,7 @@ export default function DifferentialGeneExpression() {
})
setSlider([dr1, range.x.end + 1200000])
setMin(dr1)
} else ErrorMessage(new Error("invalid range"))
} else return <ErrorMessage error={(new Error("invalid range"))} />
}
}}
/>
Expand Down Expand Up @@ -459,7 +459,7 @@ export default function DifferentialGeneExpression() {
})
setSlider([range.x.start - 1200000, dr2])
setMax(dr2)
} else ErrorMessage(new Error("invalid range"))
} else return <ErrorMessage error={(new Error("invalid range"))} />
}
}}
/>
Expand Down Expand Up @@ -587,24 +587,24 @@ export default function DifferentialGeneExpression() {
{!toggleFC ? (
<></>
) : (
data[data.gene].nearbyDEs.data.map((point, i: number) =>
BarPoint(point, i, range, dimensions)
data[data.gene].nearbyDEs.data.map(
(point, i: number) => BarPoint(point, i, range, dimensions)
// <BarPoint point={point} i={i} range={range} dimensions={dimensions} />
)
)}
{!toggleccres ? (
<></>
) : (
data[data.gene].diffCREs.data.map((point, i: number) =>
Point(point, i, range, dimensions)
data[data.gene].diffCREs.data.map(
(point, i: number) => Point(point, i, range, dimensions)
// <Point point={point} i={i} range={range} dimensions={dimensions} />
)
)}
{!toggleGenes ? (
<></>
) : (
data[data.gene].nearbyDEs.genes.map((point, i: number) =>
GenePoint(point, i, range, dimensions, toggleGenes)
data[data.gene].nearbyDEs.genes.map(
(point, i: number) => GenePoint(point, i, range, dimensions, toggleGenes)
// <GenePoint point={point} i={i} range={range} dimensions={dimensions} toggleGenes={toggleGenes} />
)
)}
Expand Down Expand Up @@ -674,8 +674,8 @@ export default function DifferentialGeneExpression() {
</text>
</g>
<g className="data">
{data[data.gene].nearbyDEs.genes.map((point, i: number) =>
GenePoint(point, i, range, dimensions, false)
{data[data.gene].nearbyDEs.genes.map(
(point, i: number) => GenePoint(point, i, range, dimensions, false)
// <GenePoint point={point} i={i} range={range} dimensions={dimensions} toggleGenes={false} />
)}
</g>
Expand Down
177 changes: 177 additions & 0 deletions screen2.0/src/app/applets/gene-expression/gene-autocomplete.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
"use client"
import React, { useState, useEffect, useCallback } from "react"
import { useRouter } from "next/navigation"

import { Autocomplete, TextField, Box, Button, debounce, Typography } from "@mui/material"

import Grid2 from "@mui/material/Unstable_Grid2/Grid2"
import { gene } from "./types"
import { QueryResponse } from "../../../../types/types"
import { Dispatch, SetStateAction } from "react"

const GENE_AUTOCOMPLETE_QUERY = `
query ($assembly: String!, $name_prefix: [String!], $limit: Int) {
gene(assembly: $assembly, name_prefix: $name_prefix, limit: $limit) {
name
id
coordinates {
start
chromosome
end
}
}
}
`

export default function GeneAutoComplete(props: {
assembly: string
gene: string
pathname: string
setGene: Dispatch<SetStateAction<string>>
}) {
const router = useRouter()

const [options, setOptions] = useState<string[]>([])
const [geneDesc, setgeneDesc] = useState<{ name: string; desc: string }[]>()
const [geneList, setGeneList] = useState<gene[]>([])
const [geneID, setGeneID] = useState<string>(props.gene ? props.gene : "OR51AB1P")
const [assembly, setAssembly] = useState<string>(props.assembly)
// const [current_gene, setGene] = useState<string>(props.gene ? props.gene : "OR51AB1P")

// gene descriptions
useEffect(() => {
const fetchData = async () => {
let f = await Promise.all(
options.map((gene) =>
fetch("https://clinicaltables.nlm.nih.gov/api/ncbi_genes/v3/search?authenticity_token=&terms=" + gene.toUpperCase())
.then((x) => x && x.json())
.then((x) => {
const matches = (x as QueryResponse)[3] && (x as QueryResponse)[3].filter((x) => x[3] === gene.toUpperCase())
return {
desc: matches && matches.length >= 1 ? matches[0][4] : "(no description available)",
name: gene,
}
})
.catch(() => {
return { desc: "(no description available)", name: gene }
})
)
)
setgeneDesc(f)
}

options && fetchData()
}, [options])

// gene list
const onSearchChange = async (value: string) => {
setOptions([])
const response = await fetch("https://ga.staging.wenglab.org/graphql", {
method: "POST",
body: JSON.stringify({
query: GENE_AUTOCOMPLETE_QUERY,
variables: {
assembly: props.assembly,
name_prefix: value,
limit: 100,
},
}),
headers: { "Content-Type": "application/json" },
})
const genesSuggestion = (await response.json()).data?.gene
if (genesSuggestion && genesSuggestion.length > 0) {
const r = genesSuggestion.map((g) => g.name)
const g = genesSuggestion.map((g) => {
return {
chrom: g.coordinates.chromosome,
start: g.coordinates.start,
end: g.coordinates.end,
id: g.id,
name: g.name,
}
})
setOptions(r)
setGeneList(g)
} else if (genesSuggestion && genesSuggestion.length === 0) {
setOptions([])
setGeneList([])
}
}

// delay fetch
const debounceFn = useCallback(debounce(onSearchChange, 500), [])

return (
<Box>
<Autocomplete
disablePortal
freeSolo={true}
id="gene-ids"
noOptionsText="e.g. Gm25142"
options={options}
size="small"
sx={{ width: 200 }}
ListboxProps={{
style: {
maxHeight: "120px",
},
}}
onChange={(event: React.ChangeEvent<HTMLInputElement>, value: string) => {
if (value != "") debounceFn(value)
setGeneID(value)
}}
onInputChange={(event: React.ChangeEvent<HTMLInputElement>, value: string) => {
if (value != "") debounceFn(value)
setGeneID(value)
}}
onKeyDown={(e) => {
if (e.key == "Enter") {
for (let g of geneList) {
if (g.name === geneID && g.end - g.start > 0) {
props.setGene(g.name)
// replace url if ge applet
if (props.pathname.split("/").includes("gene-expression")) router.replace(props.pathname + "?gene=" + g.name)
break
}
}
}
}}
renderInput={(props) => <TextField {...props} label={geneID} />}
renderOption={(props, opt) => {
return (
<li {...props} key={props.id}>
<Grid2 container alignItems="center">
<Grid2 sx={{ width: "calc(100% - 44px)" }}>
<Box component="span" sx={{ fontWeight: "regular" }}>
{opt}
</Box>
{geneDesc && geneDesc.find((g) => g.name === opt) && (
<Typography variant="body2" color="text.secondary">
{geneDesc.find((g) => g.name === opt)?.desc}
</Typography>
)}
</Grid2>
</Grid2>
</li>
)
}}
/>
<Button
variant="text"
onClick={() => {
for (let g of geneList) {
if (g.name === geneID && g.end - g.start > 0) {
props.setGene(g.name)
// replace url if ge applet
if (props.pathname.split("/").includes("gene-expression")) router.replace(props.pathname + "?gene=" + g.name)
break
}
}
}}
color="primary"
>
Search
</Button>
</Box>
)
}
Loading
Loading