Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .infra/rdev/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ stack:
services:
explorer:
image:
tag: sha-4eb2b5d
tag: sha-b8d07c5
replicaCount: 1
env:
# env vars common to all deployment stages
Expand Down
27 changes: 16 additions & 11 deletions client/src/common/queries/cellType.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { useQuery, UseQueryOptions, UseQueryResult } from "@tanstack/react-query";
import {
useQuery,
UseQueryOptions,
UseQueryResult,
} from "@tanstack/react-query";
import { useSelector } from "react-redux";
import { RootState } from "reducers";
import { CategoricalAnnotationColumnSchema, Field } from "common/types/schema";
import { createCategorySummaryFromDfCol } from "util/stateManager/controlsHelpers";
import { isDataframeDictEncodedColumn } from "util/dataframe/types";
import { ENTITIES } from "./entites";
import { ENTITIES } from "./entities";

export const USE_CELL_TYPES = {
entities: [ENTITIES.CELL_TYPE],
Expand All @@ -13,35 +17,36 @@ export const USE_CELL_TYPES = {

const METADATA_FIELD = "cell_type";

export function useCellTypesQuery(options?: Partial<UseQueryOptions<string[]>>): UseQueryResult<string[]> {
export function useCellTypesQuery(
options?: Partial<UseQueryOptions<string[]>>
): UseQueryResult<string[]> {
const { annoMatrix } = useSelector((state: RootState) => ({
annoMatrix: state.annoMatrix,
}))
}));

return useQuery({
queryKey: [USE_CELL_TYPES],
queryFn: async () => {
const categoryData = await annoMatrix.fetch(Field.obs, METADATA_FIELD)
const categoryData = await annoMatrix.fetch(Field.obs, METADATA_FIELD);
const column = categoryData.icol(0);
const colSchema = annoMatrix.schema.annotations.obsByName[METADATA_FIELD];
const categorySummary = createCategorySummaryFromDfCol(
column,
colSchema as CategoricalAnnotationColumnSchema ,
colSchema as CategoricalAnnotationColumnSchema
);

const categoryIndices = Array
.from(categorySummary.categoryValueIndices)
const categoryIndices = Array.from(categorySummary.categoryValueIndices)
.filter(([, index]) => categorySummary.categoryValueCounts[index] > 0)
.map(([, index]) => index);

return categoryIndices.map(index => {
return categoryIndices.map((index) => {
const label = categorySummary.categoryValues[index];
const labelName = isDataframeDictEncodedColumn(column)
? column.codeMapping[parseInt(label as string, 10)]
: label;

return labelName as string;
})
return labelName as string;
});
},
...options,
});
Expand Down
2 changes: 1 addition & 1 deletion client/src/common/queries/coverage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
UseQueryResult,
} from "@tanstack/react-query";
import { fetchJson } from "util/fetch";
import { ENTITIES } from "./entites";
import { ENTITIES } from "./entities";

export type CoveragePlotData = [number, number, number][]; // [y, startBasePair, endBasePair]

Expand Down
14 changes: 1 addition & 13 deletions client/src/common/queries/useCytoband.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
UseQueryResult,
} from "@tanstack/react-query";
import { fetchJson } from "util/fetch";
import { ENTITIES } from "./entites";
import { ENTITIES } from "./entities";

export interface CytobandSegment {
start: number;
Expand Down Expand Up @@ -48,15 +48,3 @@ export function useCytobandQuery({
...options,
});
}

// export function useGeneInfoQuery({
// geneName,
// genomeVersion,
// ...options
// }: UseGeneInfoQueryOptions) {
// return useQuery<FetchGeneInfoResponse>({
// queryKey: ["geneInfo", geneName, genomeVersion],
// queryFn: () => fetchGeneInfo(geneName, genomeVersion),
// ...options,
// });
// }
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import { ScaleBar } from "../ScaleBar/ScaleBar";
import { CoveragePlot } from "../CoveragePlot/CoveragePlot";
import { GeneMap } from "../GeneMap/GeneMap";
import { Cytoband } from "../Cytoband/Cytoband";
import { CoverageAtScale } from "./style";
import { CoverageToScale } from "./style";

export const ChromosomeMap = () => {
const BAR_WIDTH = 6;
const BAR_WIDTH = 6; // Width of each bar in the coverage plot, adjust as needed
const scrollContainerRef = useRef<HTMLDivElement>(null);
const { selectedGene } = useChromatinViewerSelectedGene();

Expand All @@ -22,9 +22,13 @@ export const ChromosomeMap = () => {
})
);

const parts = selectedGene.split("_");
Comment thread
rainandbare marked this conversation as resolved.
const formatSelectedGenes =
parts.length <= 1 ? selectedGene : parts.slice(0, -1).join("_");

const coverageQueries = useCoverageQuery({
cellTypes: selectedCellTypes,
geneName: selectedGene,
geneName: formatSelectedGenes,
genomeVersion: "hg38", // TODO: (smccanny) make this dynamic
options: {
enabled: !bottomPanelHidden,
Expand Down Expand Up @@ -89,39 +93,41 @@ export const ChromosomeMap = () => {
}
return null;
}, [coverageQueries, selectedGene]);
useEffect(() => {
// Calculate scroll position for the selected gene
const scrollToGene = () => {
if (
!scrollContainerRef.current ||
!selectedGeneInfo ||
!startBasePair ||
!binSize
) {
return;
}

// Calculate the pixel position relative to the start of the coverage data
const relativePosition = selectedGeneInfo.geneStart - startBasePair;
const pixelPosition = (relativePosition / binSize) * BAR_WIDTH;
// Subtracting 20px to place the gene nicely in the viewport
const scrollPosition = Math.max(0, pixelPosition - 20);
useEffect(() => {
if (selectedGeneInfo && !isLoading && totalBasePairs > 0) {
const timeoutId = setTimeout(() => {
const geneId = `${selectedGeneInfo.geneName}-label`;
const geneElement = scrollContainerRef.current?.querySelector(
`#${geneId}`
);

// Smooth scroll to the position
scrollContainerRef.current.scrollTo({
left: scrollPosition,
behavior: "smooth",
});
};
if (geneElement) {
geneElement.scrollIntoView({
behavior: "smooth",
block: "center",
inline: "center",
});
}
}, 100);

// Auto-scroll when selected gene changes and data is loaded
if (selectedGeneInfo && !isLoading && totalBasePairs > 0) {
// Add a small delay to ensure the DOM is updated
const timeoutId = setTimeout(scrollToGene, 100);
return () => clearTimeout(timeoutId);
}
return () => {}; // Cleanup function
}, [selectedGeneInfo, isLoading, totalBasePairs, startBasePair, binSize]);
return () => {};
}, [selectedGeneInfo, isLoading, totalBasePairs]);

const yMax = useMemo(
() =>
Math.max(
...coverageQueries.map((q) => {
const coverage = q.data?.coverage;
if (!coverage || coverage.length === 0) return 0;
return Math.ceil(Math.max(...coverage.map((c) => c[0]))); // Get the max y value
}),
0 // Ensure we return at least 0
),
[coverageQueries]
);

if (isLoading) {
return (
Expand Down Expand Up @@ -152,9 +158,6 @@ export const ChromosomeMap = () => {
);
}

const coverageData = coverageQueries.map((q) => q.data);
console.log("coverage Data", coverageData); // TODO: (smccanny) remove this log

const chromosome = coverageQueries[0]?.data?.chromosome;
if (!chromosome) {
return (
Expand All @@ -172,35 +175,42 @@ export const ChromosomeMap = () => {
}
return (
<>
<Cytoband chromosomeId={chromosome} />
<CoverageAtScale ref={scrollContainerRef}>
<Cytoband
chromosomeId={chromosome}
startBasePair={startBasePair}
endBasePair={endBasePair}
/>
<CoverageToScale ref={scrollContainerRef}>
<div className="margin-overlay" />
<ScaleBar
svgWidth={totalBasePairs * BAR_WIDTH}
totalBPAtScale={totalBPAtScale}
startBasePair={startBasePair}
marginLeft={25}
labelScale="bp"
labelScale="kb"
labelFrequency={2}
/>
{selectedCellTypes.map((cellType) => (
<CoveragePlot
key={cellType}
chromosome={chromosome}
svgWidth={totalBasePairs * BAR_WIDTH}
barWidth={BAR_WIDTH}
yMax={yMax}
cellType={cellType}
coverageQuery={coverageQueries.find(
(q) => q.data?.cellType === cellType
)}
/>
))}
<GeneMap
chromosomeId={chromosome}
svgWidth={totalBasePairs * BAR_WIDTH}
geneInfo={coverageQueries[0]?.data?.geneInfo ?? undefined}
startBasePair={startBasePair}
endBasePair={endBasePair}
formatSelectedGenes={formatSelectedGenes}
/>
</CoverageAtScale>
</CoverageToScale>
</>
);
};
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
import styled from "@emotion/styled";

export const CoverageAtScale = styled.div`
export const CoverageToScale = styled.div`
width: 100%;
overflow-x: scroll;
padding: 16px 16px 16px 40px;
padding: 0px 16px 16px 40px;
div.margin-overlay {
position: absolute;
width: 34px;
height: 100%;
top: 0;
left: 0;
background-color: white;
z-index: 1;
}
`;
Loading
Loading