Skip to content

Commit

Permalink
Fix bar plot issues
Browse files Browse the repository at this point in the history
  • Loading branch information
jpfisher72 committed Jan 13, 2025
1 parent c920bfb commit dc47ce5
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 25 deletions.
2 changes: 1 addition & 1 deletion screen2.0/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,4 @@
"typescript-eslint": "^8.18.0"
},
"packageManager": "[email protected]"
}
}
31 changes: 24 additions & 7 deletions screen2.0/src/app/_barPlot/BarPlot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,10 @@ const VerticalBarPlot = <T,>({
onBarClicked,
TooltipContents
}: BarPlotProps<T>) => {
const [spaceForLabel, setSpaceForLabel] = useState(200) //this needs to be initialized with zero. Will break useEffect if changed
const [spaceForLabel, setSpaceForLabel] = useState(200)
const [labelSpaceDecided, setLabelSpaceDecided] = useState(false)
// Unique ID needed to not mix up getElementByID calls if multiple charts are in DOM
const [uniqueID] = useState(topAxisLabel + String(Math.random()))
const { tooltipOpen, tooltipLeft, tooltipTop, tooltipData, hideTooltip, showTooltip } = useTooltip<BarData<T>>({});
const requestRef = useRef<number | null>(null);
const tooltipDataRef = useRef<{ top: number; left: number; data: BarData<T> } | null>(null);
Expand All @@ -48,6 +50,8 @@ const VerticalBarPlot = <T,>({
const Portal = VisxPortal as unknown as React.FC<PortalProps>;
const TooltipWithBounds = VisxTooltipWithBounds as unknown as React.FC<TooltipWithBoundsProps>;

const outerSvgRef = useRef<SVGSVGElement>(null)

const handleMouseMove = useCallback((event: React.MouseEvent, barData: BarData<T>) => {
tooltipDataRef.current = {
top: event.pageY,
Expand Down Expand Up @@ -91,19 +95,21 @@ const VerticalBarPlot = <T,>({
range: [0, Math.max(width - spaceForCategory - spaceForLabel, 0)],
}), [data, spaceForLabel, width])


//use prop ref or fallback if ref not passed
const containerWidth = SVGref ? SVGref.current?.clientWidth : outerSvgRef.current?.clientWidth

//This feels really dumb but I couldn't figure out a better way to have the labels not overflow sometimes - JF 11/8/24
//Whenever xScale is adjusted, it checks to see if any of the labels overflow the container, and if so
//it sets the spaceForLabel to be the amount overflowed.
useEffect(() => {
const containerWidth = document.getElementById('outerSVG')?.clientWidth
if (!containerWidth) { return }

let maxOverflow = 0
let minUnderflow: number = null
// let maxOverflowingPoint: [BarData<T>, { textWidth: number, barWidth: number, totalWidth: number, overflow: number }]

data.forEach((d, i) => {
const textElement = document.getElementById(`label-${i}`) as unknown as SVGSVGElement;
const textElement = document.getElementById(`label-${i}-${uniqueID}`) as unknown as SVGSVGElement;

if (textElement) {
const textWidth = textElement.getBBox().width;
Expand Down Expand Up @@ -137,14 +143,25 @@ const VerticalBarPlot = <T,>({
setLabelSpaceDecided(true)
}

}, [data, xScale]);
}, [data, xScale, spaceForLabel, labelSpaceDecided, SVGref, containerWidth, topAxisLabel, uniqueID]);

return (
<div ref={parentRef} style={{position: "relative"}}>
{data.length === 0 ?
<p>No Data To Display</p>
:
<svg ref={SVGref} width={width} height={totalHeight} opacity={(labelSpaceDecided && ParentWidth > 0) ? 1 : 0.3} id={'outerSVG'}>
<svg
//define fallback ref if not passed through props
ref={(node) => {
if (SVGref) {
SVGref.current = node;
}
outerSvgRef.current = node;
}}
width={width}
height={totalHeight}
opacity={(labelSpaceDecided && ParentWidth > 0) ? 1 : 0.3}
>
<Group left={spaceForCategory} top={spaceForTopAxis} >
{/* Top Axis with Label */}
<AxisTop scale={xScale} top={0} label={topAxisLabel} labelProps={{ dy: -5, fontSize: 16, fontFamily: fontFamily }} numTicks={width < 600 ? 4 : undefined} />
Expand Down Expand Up @@ -185,7 +202,7 @@ const VerticalBarPlot = <T,>({
/>
{/* Value label next to the bar */}
<Text
id={`label-${i}`}
id={`label-${i}-${uniqueID}`}
x={barX + barWidth + gapBetweenTextAndBar} // Position label slightly after the end of the bar
y={(barY ?? 0) + barHeight / 2}
dy=".35em" // Vertically align to the middle of the bar
Expand Down
16 changes: 7 additions & 9 deletions screen2.0/src/app/applets/gene-expression/geneexpression.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -601,15 +601,13 @@ export function GeneExpression(props: {
</Grid>
:
dataExperiments ?
// <Grid size={12}>
<VerticalBarPlot
data={plotData}
topAxisLabel={(gene + " Gene Expression in " + assembly + ' - ') + (scale === "linearTPM" ? "Linear TPM" : "Log10(TPM + 1)")}
SVGref={plotRef}
onBarClicked={(x) => window.open("https://www.encodeproject.org/experiments/" + x.metadata.accession, "_blank", "noopener,noreferrer")}
TooltipContents={(bar) => <PlotTooltip {...bar} />}
/>
// </Grid>
<VerticalBarPlot
data={plotData}
topAxisLabel={(gene + " Gene Expression in " + assembly + ' - ') + (scale === "linearTPM" ? "Linear TPM" : "Log10(TPM + 1)")}
SVGref={plotRef}
onBarClicked={(x) => window.open("https://www.encodeproject.org/experiments/" + x.metadata.accession, "_blank", "noopener,noreferrer")}
TooltipContents={(bar) => <PlotTooltip {...bar} />}
/>
:
<Typography variant="h5">
Please Select a Gene
Expand Down
17 changes: 9 additions & 8 deletions screen2.0/src/app/search/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { BIOSAMPLE_Data, biosampleQuery } from "../../common/lib/queries"
import { FilterCriteria, MainQueryData, MainQueryParams, RegistryBiosample } from "./types"
import { constructFilterCriteriaFromURL, constructMainQueryParamsFromURL, constructSearchURL, downloadBED, fetchcCREData } from "./searchhelpers"
import React, { useEffect, useMemo, useRef, useState } from "react"
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react"
import { styled } from '@mui/material/styles';
import { Divider, IconButton, Tab, Tabs, Typography, Box, Button, CircularProgressProps, CircularProgress, Stack } from "@mui/material"
import { MainResultsTable } from "./mainresultstable"
Expand Down Expand Up @@ -264,6 +264,7 @@ export default function Search({ searchParams }: { searchParams: { [key: string]
/**
* Backwards compatibility for ENCODE
* This is for sure going to be buggy, need to test many edge cases
* @todo move this to it's own file. Taking up way too much space
*/
useEffect(() => {
const fetchCoordinates = async () => {
Expand Down Expand Up @@ -511,8 +512,12 @@ export default function Search({ searchParams }: { searchParams: { [key: string]
const handleDrawerOpen = () => { setOpen(true) }
const handleDrawerClose = () => { setOpen(false) }

const findTabByID = useCallback((id: string, numberOfTable: number = 2) => {
return (opencCREs.findIndex((x) => x.ID === id) + numberOfTable)
}, [opencCREs])

//Handle opening a cCRE or navigating to its open tab
const handlecCREClick = (item) => {
const handlecCREClick = useCallback((item) => {
const newcCRE = { ID: item.name || item.accession, region: { start: item.start, end: item.end, chrom: item.chromosome } }
const color = item.color || GROUP_COLOR_MAP.get(item.class).split(":")[1] || "#8c8c8c"
browserDispatch({ type: BrowserActionType.ADD_HIGHLIGHT, highlight: { domain: { chromosome: item.chromosome, start: item.start, end: item.end }, color, id: item.name || item.accession } })
Expand All @@ -523,7 +528,8 @@ export default function Search({ searchParams }: { searchParams: { [key: string]
} else {
setPage(findTabByID(newcCRE.ID, numberOfDefaultTabs))
}
}
}, [browserDispatch, opencCREs, numberOfDefaultTabs, findTabByID])

//Handle closing cCRE, and changing page if needed
const handleClosecCRE = (closedID: string) => {
browserDispatch({ type: BrowserActionType.REMOVE_HIGHLIGHT, id: closedID })
Expand Down Expand Up @@ -725,10 +731,6 @@ export default function Search({ searchParams }: { searchParams: { [key: string]
}
}, [mainQueryData, dataLinkedGenes, filterCriteria, mainQueryParams.gene.nearTSS, TSSranges])

const findTabByID = (id: string, numberOfTable: number = 2) => {
return (opencCREs.findIndex((x) => x.ID === id) + numberOfTable)
}

/**
* @todo Make this (and other download tool) properly download new linked genes
*/
Expand Down Expand Up @@ -898,7 +900,6 @@ export default function Search({ searchParams }: { searchParams: { [key: string]
setTSSranges={setTSSranges}
genomeBrowserView={page === 1}
useLinkedGenes={useLinkedGenes}

/>
:
<Tabs
Expand Down

0 comments on commit dc47ce5

Please sign in to comment.