Skip to content

Commit

Permalink
Merge pull request #112 from weng-lab/Add-More-Linked-Genes
Browse files Browse the repository at this point in the history
Add More Linked Genes
  • Loading branch information
NishiPhalke authored Aug 29, 2023
2 parents d16beed + be1eda3 commit a907377
Show file tree
Hide file tree
Showing 13 changed files with 426 additions and 193 deletions.
3 changes: 2 additions & 1 deletion screen2.0/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"@types/node": "^20.5.0",
"@types/react": "^18.2.20",
"@types/react-dom": "18.2.7",
"@weng-lab/psychscreen-ui-components": "^0.7.8",
"@weng-lab/psychscreen-ui-components": "^0.8.0-a.2",
"@weng-lab/ts-ztable": "^4.0.1",
"autoprefixer": "10.4.15",
"eslint": "8.47.0",
Expand All @@ -58,6 +58,7 @@
"postcss": "8.4.27",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-dropzone": "^14.2.3",
"server": "^1.0.38",
"sharp": "^0.32.4",
"tailwindcss": "3.3.3",
Expand Down
4 changes: 3 additions & 1 deletion screen2.0/src/app/applets/multi-region-search/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
"use client"
import { Typography } from "@mui/material"
import BedUpload from "../../../common/components/BedUpload"

export default function MultiRegionSearch() {
return (
<main>
<Typography>This is the Multi-Region Search page</Typography>
<Typography variant="h6" mt={2}>Find Intersecting cCREs from BED file</Typography>
<BedUpload />
</main>
)
}
4 changes: 1 addition & 3 deletions screen2.0/src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@

"use client"
import { Typography } from "@mui/material"

import MainSearch from "../common/components/MainSearch"

// Grid v2 isn't declared stable yet, but using it now as it's what MUI is currently developing out
import Grid2 from "@mui/material/Unstable_Grid2/Grid2"

import homeImage from "../../public/homeImage.png"

import Image from "next/image"
import BedUpload from "../common/components/BedUpload"

export default function Home() {
return (
Expand Down
17 changes: 4 additions & 13 deletions screen2.0/src/app/search/ccredetails/ccredetails.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client"
import React from "react"
import { Tabs, Typography, Paper, ThemeProvider, AppBar, Toolbar, IconButton, Drawer, Box } from "@mui/material"
import { GenomicRegion } from "../types"
import { GenomicRegion, LinkedGenesData } from "../types"
import Grid2 from "@mui/material/Unstable_Grid2/Grid2"
import { StyledTab } from "../ccresearch"
import { InSpecificBiosamples } from "./inspecificbiosample"
Expand All @@ -22,16 +22,7 @@ type CcreDetailsProps = {
assembly: string
region: GenomicRegion
globals: any
genes: {
pc: {
name: string
__typename: string
}[]
all: {
name: string
__typename: string
}[]
}
genes: LinkedGenesData
}

export const CcreDetails: React.FC<CcreDetailsProps> = ({ accession, region, globals, assembly, genes }) => {
Expand Down Expand Up @@ -154,8 +145,8 @@ export const CcreDetails: React.FC<CcreDetailsProps> = ({ accession, region, glo
assembly={assembly}
coordinates={{
chromosome: region.chrom,
start: +region.start.toString().replace(/\D/g, ""),
end: +region.end.toString().replace(/\D/g, ""),
start: +region.start.replace(/\D/g, ""),
end: +region.end.replace(/\D/g, ""),
}}
/>
)}
Expand Down
9 changes: 5 additions & 4 deletions screen2.0/src/app/search/ccredetails/gene-expression.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,12 @@ import {
OptionsScale,
} from "../../applets/gene-expression/options"
import { GeneExpressionInfoTooltip } from "../../applets/gene-expression/const"
import { LinkedGenesData } from "../types"

export function GeneExpression(props: {
accession: string
assembly: string
genes: { pc: { name: string; __typename: string }[]; all: { name: string; __typename: string }[] }
genes: LinkedGenesData
hamburger: boolean
}) {
const pathname = usePathname()
Expand All @@ -43,7 +44,7 @@ export function GeneExpression(props: {
const [open, setState] = useState<boolean>(true)

const [current_assembly, setAssembly] = useState<string>(props.assembly ? props.assembly : "GRCh38")
const [current_gene, setGene] = useState<string>(props.genes.pc[0].name)
const [current_gene, setGene] = useState<string>(props.genes.distancePC[0].name)

const [biosamples, setBiosamples] = useState<string[]>(["cell line", "in vitro differentiated cells", "primary cell", "tissue"])
const [cell_components, setCellComponents] = useState<string[]>(["cell"])
Expand Down Expand Up @@ -88,8 +89,8 @@ export function GeneExpression(props: {
.then((data) => {
setData(data)
let geneList: string[] = []
for (let g of props.genes.pc) if (!geneList.includes(g.name)) geneList.push(g.name)
for (let g of props.genes.all) if (!geneList.includes(g.name)) geneList.push(g.name)
for (let g of props.genes.distancePC) if (!geneList.includes(g.name)) geneList.push(g.name)
for (let g of props.genes.distanceAll) if (!geneList.includes(g.name)) geneList.push(g.name)
setOptions(geneList)
setLoading(false)
})
Expand Down
22 changes: 11 additions & 11 deletions screen2.0/src/app/search/ccresearch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,26 @@ import { CcreDetails } from "./ccredetails/ccredetails"
import Grid2 from "../../common/mui-client-wrappers/Grid2"
import { ReadonlyURLSearchParams, useSearchParams } from "next/navigation"
import styled from "@emotion/styled"
import { MainResultTableRows } from "./types"
export const StyledTab = styled(Tab)(() => ({
textTransform: "none",
}))
export const CcreSearch = ({ mainQueryParams, ccrerows, globals, assembly }) => {
export const CcreSearch = (props: { mainQueryParams, ccrerows: MainResultTableRows, globals, assembly }) => {
const searchParams: ReadonlyURLSearchParams = useSearchParams()!
const [value, setValue] = React.useState(searchParams.get("accession") ? 1 : 0)

const handleChange = (_, newValue: number) => {
setValue(newValue)
}

//This needs to be changed, this will switch to the details tab anytime filter is updated
useEffect(() => {
if (searchParams.get("accession")) {
setValue(1)
}
}, [searchParams])

//Need meaningful variable names please
let f = ccrerows.find((c) => c.accession === searchParams.get("accession"))
//Need meaningful variable names please, is showing that this is undefined and throwing an error when using back button on details page since accession is undefined
let f = props.ccrerows.find((c) => c.accession === searchParams.get("accession"))
const region = { start: f?.start, chrom: f?.chromosome, end: f?.end }

return (
Expand All @@ -42,14 +42,14 @@ export const CcreSearch = ({ mainQueryParams, ccrerows, globals, assembly }) =>
{value === 0 && (
<Grid2 container spacing={3} sx={{ mt: "1rem", mb: "1rem" }}>
<Grid2 xs={12} lg={3}>
<MainResultsFilters mainQueryParams={mainQueryParams} byCellType={globals} />
<MainResultsFilters mainQueryParams={props.mainQueryParams} byCellType={props.globals} />
</Grid2>
<Grid2 xs={12} lg={9}>
<MainResultsTable
rows={ccrerows}
tableTitle={`Searching ${mainQueryParams.chromosome} in ${
mainQueryParams.assembly
} from ${mainQueryParams.start.toLocaleString("en-US")} to ${mainQueryParams.end.toLocaleString("en-US")}`}
rows={props.ccrerows}
tableTitle={`Searching ${props.mainQueryParams.chromosome} in ${
props.mainQueryParams.assembly
} from ${props.mainQueryParams.start.toLocaleString("en-US")} to ${props.mainQueryParams.end.toLocaleString("en-US")}`}
itemsPerPage={10}
/>
</Grid2>
Expand All @@ -61,8 +61,8 @@ export const CcreSearch = ({ mainQueryParams, ccrerows, globals, assembly }) =>
<CcreDetails
accession={searchParams.get("accession")}
region={region}
globals={globals}
assembly={assembly}
globals={props.globals}
assembly={props.assembly}
genes={f.linkedGenes}
/>
</Grid2>
Expand Down
70 changes: 36 additions & 34 deletions screen2.0/src/app/search/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
// Search Results Page
import { CcreSearch } from "./ccresearch"
import { getGlobals, MainQuery } from "../../common/lib/queries"
import { MainQuery, getGlobals, linkedGenesQuery } from "../../common/lib/queries"
import { ApolloQueryResult } from "@apollo/client"
import { cCREData, CellTypeData, MainQueryParams } from "./types"
import { cCREData, CellTypeData, MainQueryParams, MainResultTableRow, MainResultTableRows } from "./types"
import { checkTrueFalse, passesCriteria } from "../../common/lib/filter-helpers"
import { LinkedGenes } from "./ccredetails/linkedgenes"

export default async function Search({
// Object from URL, see https://nextjs.org/docs/app/api-reference/file-conventions/page#searchparams-optional
Expand All @@ -26,11 +27,11 @@ export default async function Search({
InVitro: searchParams.InVitro ? checkTrueFalse(searchParams.InVitro) : true,
Biosample: searchParams.Biosample
? {
selected: true,
biosample: searchParams.Biosample,
tissue: searchParams.BiosampleTissue,
summaryName: searchParams.BiosampleSummary,
}
selected: true,
biosample: searchParams.Biosample,
tissue: searchParams.BiosampleTissue,
summaryName: searchParams.BiosampleSummary,
}
: { selected: false, biosample: null, tissue: null, summaryName: null },
// Chromatin Filters
// "[...]_s" = start, "[...]_e" = end.
Expand All @@ -55,8 +56,8 @@ export default async function Search({
TF: searchParams.TF ? checkTrueFalse(searchParams.TF) : true,
}

//Main query. Returns -1 if query returns an error
const mainQueryResult: ApolloQueryResult<any> | -1 = await MainQuery(
//Main query
const mainQueryResult: ApolloQueryResult<any> = await MainQuery(
mainQueryParams.assembly,
mainQueryParams.chromosome,
mainQueryParams.start,
Expand All @@ -72,26 +73,14 @@ export default async function Search({
* @param QueryResult Result from Main Query
* @returns rows usable by the DataTable component
*/
const generateRows = (QueryResult: ApolloQueryResult<any>, biosample: string | null) => {
const rows: {
//atac will need to be changed from string to number when that data is available
accession: string
class: string
chromosome: string
start: string
end: string
dnase?: number
atac: string
h3k4me3?: number
h3k27ac?: number
ctcf?: number
linkedGenes: { pc: { name: string }[]; all: { name: string }[] }
}[] = []
async function generateRows(QueryResult: ApolloQueryResult<any>, biosample: string | null) {
const cCRE_data: cCREData[] = QueryResult.data.cCRESCREENSearch
let offset = 0
cCRE_data.forEach((currentElement, index) => {
const rows: MainResultTableRows = []
// Used for Linked Gene Query
const accessions: string[] = []
cCRE_data.forEach((currentElement) => {
if (passesCriteria(currentElement, biosample, mainQueryParams)) {
rows[index - offset] = {
rows.push({
accession: currentElement.info.accession,
class: currentElement.pct,
chromosome: currentElement.chrom,
Expand All @@ -103,14 +92,27 @@ export default async function Search({
h3k4me3: biosample ? currentElement.ctspecific.h3k4me3_zscore : currentElement.promoter_zscore,
h3k27ac: biosample ? currentElement.ctspecific.h3k27ac_zscore : currentElement.enhancer_zscore,
ctcf: biosample ? currentElement.ctspecific.ctcf_zscore : currentElement.ctcf_zscore,
linkedGenes: { pc: currentElement.genesallpc.pc.intersecting_genes, all: currentElement.genesallpc.all.intersecting_genes },
}
}
// Offset incremented to account for missing rows which do not meet filter criteria
else {
offset += 1
linkedGenes: { distancePC: currentElement.genesallpc.pc.intersecting_genes, distanceAll: currentElement.genesallpc.all.intersecting_genes, CTCF_ChIAPET: [], RNAPII_ChIAPET: [] },
})
accessions.push(currentElement.info.accession)
}
})
const otherLinked = await linkedGenesQuery(mainQueryParams.assembly, accessions)
//Need to add in biosample information for the hover
rows.forEach((row: MainResultTableRow) => {
const accession = row.accession
const genesToAdd = otherLinked[accession] ?? null

genesToAdd && genesToAdd.genes.forEach(gene => {
if (gene.linkedBy === "CTCF-ChIAPET") {
row.linkedGenes.CTCF_ChIAPET.push({name: gene.geneName, biosample: gene.biosample})
}
else if (gene.linkedBy === "RNAPII-ChIAPET"){
row.linkedGenes.RNAPII_ChIAPET.push({name: gene.geneName, biosample: gene.biosample})
}
});

})

return rows
}
Expand All @@ -120,7 +122,7 @@ export default async function Search({
<CcreSearch
mainQueryParams={mainQueryParams}
globals={globals}
ccrerows={mainQueryResult === -1 ? [] : generateRows(mainQueryResult, mainQueryParams.Biosample.biosample)}
ccrerows={(mainQueryResult.error || mainQueryResult.loading) ? [] : await generateRows(mainQueryResult, mainQueryParams.Biosample.biosample)}
assembly={mainQueryParams.assembly}
/>
</main>
Expand Down
28 changes: 26 additions & 2 deletions screen2.0/src/app/search/types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export type GenomicRegion = {
chrom: string
start: number
end: number
start: string
end: string
}

export type cCREData = {
Expand Down Expand Up @@ -110,3 +110,27 @@ export type FilteredBiosampleData = [
}
}[],
][]

export type MainResultTableRows = MainResultTableRow[]

export type MainResultTableRow = {
//atac will need to be changed from string to number when that data is available
accession: string
class: string
chromosome: string
start: string
end: string
dnase?: number
atac: string
h3k4me3?: number
h3k27ac?: number
ctcf?: number
linkedGenes: LinkedGenesData
}

export type LinkedGenesData = {
distancePC: { name: string }[],
distanceAll: { name: string }[],
CTCF_ChIAPET: { name: string, biosample: string }[],
RNAPII_ChIAPET: { name: string, biosample: string }[]
}
42 changes: 42 additions & 0 deletions screen2.0/src/common/components/BedUpload.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"use client"

import React, { useState } from "react"
import { Button, Typography, Box } from "@mui/material"
import Dropzone from "react-dropzone"


/**
* Things to improve upon old upload:
* - Prevent upload of non BED files
* - Clear files
* - Convert byte size to mb/gb
*/
const BedUpload = () => {
const [files, setFiles] = useState<File[]>([])

function handleFileUploads(uploads){
setFiles([...files, ...uploads])
}

return (
<Box mt="1rem">
<Dropzone onDrop={acceptedFiles => handleFileUploads(acceptedFiles)}>
{({ getRootProps, getInputProps }) => (
<section>
<div {...getRootProps()}>
<input {...getInputProps()} />
<Button>Drag and drop some files here, or click to select files</Button>
</div>
</section>
)}
</Dropzone>
<br />
{files.map((file: File, index: number) => {
return <Typography key={index}>{file.name} - {file.size} bytes</Typography>
})}
{files.length > 0 && <Button onClick={() => setFiles([])}>Clear Files</Button>}
</Box>
)
}

export default BedUpload
Loading

0 comments on commit a907377

Please sign in to comment.