Skip to content

Commit

Permalink
Redo how nearby genes are fetched
Browse files Browse the repository at this point in the history
  • Loading branch information
jpfisher72 committed Jul 9, 2024
1 parent c69460e commit 17dd9ee
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 88 deletions.
107 changes: 60 additions & 47 deletions screen2.0/src/app/search/_ccredetails/ccredetails.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client"
import React, { useCallback, useMemo, useState } from "react"
import { Typography, Stack, Divider } from "@mui/material"
import { Typography, Stack, Divider, CircularProgress } from "@mui/material"
import { GenomicRegion, MainQueryParams } from "../types"
import { InSpecificBiosamples } from "./inspecificbiosample"
import { NearByGenomicFeatures } from "./nearbygenomicfeatures"
Expand All @@ -17,6 +17,7 @@ import { ApolloQueryResult } from "@apollo/client"
import { BIOSAMPLE_Data } from "../../../common/lib/queries"
import { useQuery } from "@apollo/experimental-nextjs-app-support/ssr"
import { NEARBY_AND_LINKED_GENES } from "./queries"
import Error from "../../error"

//Passing these props through this file could be done with context to reduce prop drilling
type CcreDetailsProps = {
Expand Down Expand Up @@ -72,25 +73,23 @@ export type NearbyGeneInfoWithDistance = {
}

type NearbyAndLinked = {
nearbyGenes: NearbyGeneInfo[]
nearestGenes: [{ intersecting_genes: NearbyGeneInfo[] }]
linkedGenes: LinkedGeneInfo[]
}

export type NearbyWithDistanceAndLinked = {
nearbyGenes: NearbyGeneInfoWithDistance[]
nearestGenes: [{ intersecting_genes: NearbyGeneInfoWithDistance[] }]
linkedGenes: LinkedGeneInfo[]
}

type NearbyAndLinkedVariables = {
assembly: string
accession: string
geneChr: string
geneStart: number
geneEnd: number
genesVersion: number
coordinates: { chromosome: string, start: number, stop: number }
nearbyLimit: number
}

function calculateDistance(coord1: Coordinates, coord2: Coordinates): number {
function calculateDistanceFromEdges(coord1: Coordinates, coord2: Coordinates): number {
if (coord1.end < coord2.start) {
return coord2.start - coord1.end;
} else if (coord2.end < coord1.start) {
Expand All @@ -100,55 +99,52 @@ function calculateDistance(coord1: Coordinates, coord2: Coordinates): number {
}
}

const extractClosestGenes = (genesList: NearbyGeneInfo[], targetRegion: Coordinates, numGenes: number): NearbyGeneInfoWithDistance[] => {
return genesList
.map(gene => ({
...gene,
distance: calculateDistance(gene.coordinates, targetRegion)
}))
.sort((a, b) => a.distance - b.distance)
.slice(0, numGenes)
export function calculateDistanceFromMiddles(coord1: Coordinates, coord2: Coordinates): number {
const mid1 = (coord1.start + coord1.end) / 2
const mid2 = (coord2.start + coord2.end) / 2
return Math.floor(Math.abs(mid1 - mid2))
}


export const CcreDetails: React.FC<CcreDetailsProps> = ({ accession, region, biosampleData, assembly, page, handleOpencCRE }) => {
const { loading: loadingLinkedGenes, data: dataNearbyAndLinked }: { loading: boolean, data: NearbyAndLinked } = useQuery<NearbyAndLinked, NearbyAndLinkedVariables>(NEARBY_AND_LINKED_GENES, {

const { loading: loadingLinkedGenes, data: dataNearbyAndLinked, error: errorNearbyAndLinked, refetch } = useQuery<NearbyAndLinked, NearbyAndLinkedVariables>(NEARBY_AND_LINKED_GENES, {
variables: {
assembly: assembly.toLowerCase(),
accession: accession,
geneChr: region.chrom,
geneStart: region.start - 1000000,
geneEnd: region.end + 1000000,
genesVersion: assembly === "GRCh38" ? 40 : 25 //Version 40 for Human, 25 for Mouse
coordinates: { chromosome: region.chrom, start: region.start - 1000000, stop: region.end + 1000000 },
nearbyLimit: 3
},
fetchPolicy: "cache-and-network",
nextFetchPolicy: "cache-first",
})

const nearest3AndLinkedGenes: NearbyWithDistanceAndLinked = useMemo(() => {
return dataNearbyAndLinked ? {
linkedGenes: [...dataNearbyAndLinked.linkedGenes.map((g) => {return {...g, gene: g.gene.split(' ')[0]}})],
nearbyGenes: extractClosestGenes(dataNearbyAndLinked.nearbyGenes, { chromosome: region.chrom, start: region.start, end: region.end }, 3)
linkedGenes: [...dataNearbyAndLinked.linkedGenes.map((g) => { return { ...g, gene: g.gene.split(' ')[0] } })], //remove trailing space in return data
nearestGenes: [{
intersecting_genes: [...dataNearbyAndLinked.nearestGenes[0].intersecting_genes.map((gene) => {
return { ...gene, distance: calculateDistanceFromMiddles({ chromosome: region.chrom, start: region.start, end: region.end }, gene.coordinates) }
})]
}]
} : null
}, [dataNearbyAndLinked, region.chrom, region.end, region.start])

const combinedGenes: (LinkedGeneInfo | NearbyGeneInfoWithDistance)[] = []
if (nearest3AndLinkedGenes) {
combinedGenes.push(...nearest3AndLinkedGenes.nearbyGenes)
combinedGenes.push(...nearest3AndLinkedGenes.linkedGenes)
}
//Used to pass genes and their linking method to gene expression and RAMPAGE app
const uniqueGenes: { name: string; linkedBy: string[]; }[] = [];

const uniqueGenes: {
name: string;
linkedBy: string[];
}[] = [];

for (const gene of combinedGenes) {
const geneName = gene['gene'] ?? gene['name']
const methodToPush = gene['distance'] !== undefined ? `Distance - ${gene['distance']} bp` : gene['assay'] ?? gene['method']
const existingGeneEntry = uniqueGenes.find((uniqueGene) => uniqueGene.name === geneName)
if (existingGeneEntry) {
!existingGeneEntry.linkedBy.find(method => method === methodToPush) && existingGeneEntry.linkedBy.push(methodToPush) //deduplicate for linking methods with multiple tissues
} else uniqueGenes.push({name: geneName, linkedBy: [methodToPush]})
if (nearest3AndLinkedGenes) {
for (const gene of [
...nearest3AndLinkedGenes.nearestGenes[0].intersecting_genes,
...nearest3AndLinkedGenes.linkedGenes
]) {
const geneName = gene['gene'] ?? gene['name']
const methodToPush = gene['distance'] !== undefined ? `Distance - ${gene['distance']} bp` : gene['assay'] ?? gene['method']
const existingGeneEntry = uniqueGenes.find((uniqueGene) => uniqueGene.name === geneName)
if (existingGeneEntry) {
!existingGeneEntry.linkedBy.find(method => method === methodToPush) && existingGeneEntry.linkedBy.push(methodToPush) //deduplicate for linking methods with multiple tissues
} else uniqueGenes.push({ name: geneName, linkedBy: [methodToPush] })
}
}

return (
Expand All @@ -161,8 +157,14 @@ export const CcreDetails: React.FC<CcreDetailsProps> = ({ accession, region, bio
{page === 0 &&
<InSpecificBiosamples accession={accession} assembly={assembly} />
}
{page === 1 && assembly !== "mm10" && dataNearbyAndLinked &&
<LinkedGenes linkedGenes={nearest3AndLinkedGenes.linkedGenes} />
{(page === 1 && assembly !== "mm10") &&
(loadingLinkedGenes ?
<CircularProgress />
:
errorNearbyAndLinked ?
<Typography>{`Issue fetching Linked Genes for ${accession}.`}</Typography>
:
<LinkedGenes linkedGenes={nearest3AndLinkedGenes?.linkedGenes || []} />)
}
{page === 2 && (
<NearByGenomicFeatures
Expand All @@ -179,9 +181,14 @@ export const CcreDetails: React.FC<CcreDetailsProps> = ({ accession, region, bio
{page === 3 &&
<Ortholog accession={accession} assembly={assembly} />
}
{/* @todo replace genses here */}
{page === 4 && uniqueGenes.length > 0 &&
<GeneExpression assembly={assembly} genes={uniqueGenes} biosampleData={biosampleData} />
{(page === 4) &&
(loadingLinkedGenes ?
<CircularProgress />
:
errorNearbyAndLinked ?
<Typography>{`Issue fetching Linked Genes for ${accession}. Please use our Gene Expression Applet`}</Typography>
:
<GeneExpression assembly={assembly} genes={uniqueGenes || []} biosampleData={biosampleData} />)
}
{page === 5 &&
<FunctionData accession={accession} coordinates={{ chromosome: region.chrom, start: region.start, end: region.end }} assembly={assembly} />
Expand Down Expand Up @@ -214,8 +221,14 @@ export const CcreDetails: React.FC<CcreDetailsProps> = ({ accession, region, bio
{page === 9 && assembly !== "mm10" &&
<ChromHMM accession={accession} coordinates={{ chromosome: region.chrom, start: region.start, end: region.end }} assembly={assembly} />
}
{page === 8 && assembly !== "mm10" && uniqueGenes.length > 0 &&
<Rampage genes={uniqueGenes} biosampleData={biosampleData} />
{(page === 8 && assembly !== "mm10") &&
(loadingLinkedGenes ?
<CircularProgress />
:
errorNearbyAndLinked ?
<Typography>{`Issue fetching Linked Genes for ${accession}.`}</Typography>
:
<Rampage genes={uniqueGenes || []} biosampleData={biosampleData} />)
}
</>
)
Expand Down
4 changes: 2 additions & 2 deletions screen2.0/src/app/search/_ccredetails/geneexpression.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ export function GeneExpression(props: {
const pathname = usePathname()

//Use gene from url if specified
const [currentHumanGene, setCurrentHumanGene] = useState<string>(props.genes ? props.genes[0].name : (urlAssembly === "GRCh38" && urlGene) ? urlGene : "APOE")
const [currentMouseGene, setCurrentMouseGene] = useState<string>(props.genes ? props.genes[0].name : (urlAssembly === "mm10" && urlGene) ? urlGene : "Emid1")
const [currentHumanGene, setCurrentHumanGene] = useState<string>(props.genes ? props?.genes[0]?.name : (urlAssembly === "GRCh38" && urlGene) ? urlGene : "APOE")
const [currentMouseGene, setCurrentMouseGene] = useState<string>(props.genes ? props?.genes[0]?.name : (urlAssembly === "mm10" && urlGene) ? urlGene : "Emid1")

const [biosamples, setBiosamples] = useState<string[]>(["cell line", "in vitro differentiated cells", "primary cell", "tissue"])
const [group, setGroup] = useState<"byTissueMaxTPM" | "byExperimentTPM" | "byTissueTPM">("byTissueTPM")
Expand Down
16 changes: 8 additions & 8 deletions screen2.0/src/app/search/_ccredetails/linkedgenes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,15 +123,15 @@ export const LinkedGenes: React.FC<props> = (props) => {
render: (row: LinkedGeneInfo) => row.p_val === 0 ? '0' : toScientificNotationElement(row.p_val, 'body2')
},
]}
tableTitle="Intact-HiC Linked"
tableTitle="Intact Hi-C Loops"
rows={HiCLinked}
sortColumn={6}
sortDescending
itemsPerPage={5}
searchable
/>
:
<EmptyTile title="Intact-HiC Linked" body="No Data" />
<EmptyTile title="Intact Hi-C Loops" body="No intact Hi-C loops overlap this cCRE and the promoter of a gene" />
}
</Grid2>
<Grid2 xs={12}>
Expand Down Expand Up @@ -167,14 +167,14 @@ export const LinkedGenes: React.FC<props> = (props) => {
value: (row: LinkedGeneInfo) => row.score,
},
]}
tableTitle="ChIAPET Linked"
tableTitle="ChIA-PET Interactions"
rows={ChIAPETLinked}
sortColumn={5}
itemsPerPage={5}
searchable
/>
:
<EmptyTile title="ChIAPET Linked" body="No Data" />
<EmptyTile title="ChIA-PET Interactions" body="No ChIA-PET interactions overlap this cCRE and the promoter of a gene" />
}
</Grid2>
<Grid2 xs={12}>
Expand Down Expand Up @@ -220,7 +220,7 @@ export const LinkedGenes: React.FC<props> = (props) => {
render: (row: LinkedGeneInfo) => toScientificNotationElement(row.p_val, 'body2')
},
]}
tableTitle="CRISPR Linked"
tableTitle="CRISPRi-FlowFISH"
rows={crisprLinked}
emptyText="test"
sortColumn={7}
Expand All @@ -229,7 +229,7 @@ export const LinkedGenes: React.FC<props> = (props) => {
searchable
/>
:
<EmptyTile title="CRISPR Linked" body="No Data" />
<EmptyTile title="CRISPRi-FlowFISH" body="This cCRE was not targeted in a CRISPRi-FlowFISH experiment" />
}
</Grid2>
<Grid2 xs={12}>
Expand Down Expand Up @@ -269,15 +269,15 @@ export const LinkedGenes: React.FC<props> = (props) => {
render: (row: LinkedGeneInfo) => toScientificNotationElement(row.p_val, 'body2')
},
]}
tableTitle="eQTL Linked"
tableTitle="eQTLs"
rows={eqtlLinked}
sortColumn={6}
sortDescending
itemsPerPage={5}
searchable
/>
:
<EmptyTile title="eQTL Linked" body="No Data" />
<EmptyTile title="eQTLs" body="This cCRE does not overlap a variant associated with significant changes in gene expression" />
}
</Grid2>
</Grid2>
Expand Down
10 changes: 6 additions & 4 deletions screen2.0/src/app/search/_ccredetails/nearbygenomicfeatures.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ import { Typography } from "@mui/material"
import { DataTable } from "@weng-lab/psychscreen-ui-components"
import { LoadingMessage } from "../../../common/lib/utility"
import { usePathname, useRouter, useSearchParams } from "next/navigation"
import { calculateDistanceFromMiddles } from "./ccredetails"


//This produces a "distance" for cCREs which are inside gene bodies
const genesDistance = (
coordinates: { chromosome: string; start: number; end: number },
ccrecoord: { chromosome: string; start: number; end: number }
) => {
let c = Math.floor((ccrecoord.start + ccrecoord.end) / 2)
return Math.min(Math.abs(coordinates.start - c), Math.abs(coordinates.end - c))
let c = Math.floor((ccrecoord.start + ccrecoord.end) / 2) //find middle of ccre
return Math.min(Math.abs(coordinates.start - c), Math.abs(coordinates.end - c)) //return minimum of: distance to start of gene, distance to end of gene
}

const cCREDistance = (
Expand Down Expand Up @@ -101,7 +102,8 @@ export const NearByGenomicFeatures: React.FC<{
chrom: g.coordinates.chromosome,
start: g.coordinates.start,
stop: g.coordinates.end,
distance: genesDistance(g.coordinates, coordinates),
// distance: genesDistance(g.coordinates, coordinates),
distance: calculateDistanceFromMiddles(g.coordinates, coordinates),
}
})
let ccres =
Expand Down
30 changes: 14 additions & 16 deletions screen2.0/src/app/search/_ccredetails/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -276,25 +276,23 @@ export const NEARBY_AND_LINKED_GENES = gql`
query nearbyAndLinkedGenes(
$accession: String!
$assembly: String!
$geneChr: String!
$geneStart: Int!
$geneEnd: Int!
$genesVersion: Int!
$coordinates: ChromRange!
$nearbyLimit: Int!
) {
nearbyGenes: gene(
chromosome: $geneChr
start: $geneStart
end: $geneEnd
nearestGenes(
assembly: $assembly
version: $genesVersion
limit: $nearbyLimit
coordinates: [$coordinates]
) {
name
id
gene_type
coordinates {
chromosome
start
end
intersecting_genes {
name
id
gene_type
coordinates {
start
end
chromosome
}
}
}
linkedGenes: linkedGenesQuery(assembly: $assembly, accession: [$accession]) {
Expand Down
11 changes: 0 additions & 11 deletions screen2.0/src/app/search/mainresultsfilters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -752,17 +752,6 @@ export function MainResultsFilters(
</FormGroup>
</AccordionDetails>
</Accordion>
{/* Functional Characterization */}
{/* <Accordion square disableGutters>
<AccordionSummary expandIcon={<ExpandMoreIcon />} aria-controls="panel5a-content" id="panel5a-header">
<Typography>Functional Characterization</Typography>
</AccordionSummary>
<AccordionDetails>
<Typography>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse malesuada lacus ex, sit amet blandit leo lobortis eget.
</Typography>
</AccordionDetails>
</Accordion> */}
</>
}
</Paper>
Expand Down

0 comments on commit 17dd9ee

Please sign in to comment.