Skip to content

Commit

Permalink
ESCKAN-20 notes and comments - Connection summary
Browse files Browse the repository at this point in the history
  • Loading branch information
D-GopalKrishna committed May 27, 2024
1 parent a3d6878 commit 88efea9
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 83 deletions.
38 changes: 20 additions & 18 deletions src/components/Connections.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import React, { useEffect, useMemo, useState } from "react";
import { Box, Chip, TextField, Typography } from "@mui/material";
import { ArrowRightIcon } from "./icons";
import { vars } from "../theme/variables";
import { HierarchicalItem, SubConnections, SummaryType, KsMapType, PhenotypeType } from "./common/Types";
import { HierarchicalItem, PhenotypeKsIdMap, SummaryType, KsMapType, PhenotypeType } from "./common/Types";
import { useDataContext } from "../context/DataContext.ts";
import {
calculateSecondaryConnections,
convertViaToString, generatePhenotypeColors,
getAllPhenotypes, getAllViasFromConnections, getNerveFilters,
getAllPhenotypes, getAllViasFromConnections, getDestinations, getNerveFilters,
getSecondaryHeatmapData,
getXAxisForHeatmap,
} from "../services/summaryHeatmapService.ts";
Expand All @@ -16,7 +16,7 @@ import SummaryHeader from "./connections/SummaryHeader";
import SummaryInstructions from "./connections/SummaryInstructions.tsx";
import PhenotypeLegend from "./connections/PhenotypeLegend.tsx";
import HeatmapGrid from "./common/Heatmap.tsx";
import { BaseEntity, Organ } from "../models/explorer.ts";
import { Organ } from "../models/explorer.ts";
import SummaryDetails from "./connections/SummaryDetails.tsx";
import SummaryFiltersDropdown from "./SummaryFiltersDropdown.tsx";

Expand All @@ -41,27 +41,32 @@ const styles = {

function Connections() {
const [showConnectionDetails, setShowConnectionDetails] = useState<SummaryType>(SummaryType.Instruction);
const [connectionsMap, setConnectionsMap] = useState<Map<string, SubConnections[]>>(new Map());
const [connectionsMap, setConnectionsMap] = useState<Map<string, PhenotypeKsIdMap[]>>(new Map());
const [connectionPage, setConnectionPage] = useState(1); // represents the page number / index of the connections - if (x,y) has 4 connections, then connectionPage will be 1, 2, 3, 4
const [yAxis, setYAxis] = useState<HierarchicalItem[]>([]);
const [selectedCell, setSelectedCell] = useState<{ x: number, y: number } | null>(null);
const [selectedCell, setSelectedCell] = useState<{ x: number, y: number } | null>(null); // useful for coordinates
const [phenotypes, setPhenotypes] = useState<PhenotypeType>({});
const [uniqueKS, setUniqueKS] = useState<KsMapType>({});
const [xAxis, setXAxis] = useState<string[]>([]);

const { selectedConnectionSummary, majorNerves, hierarchicalNodes, knowledgeStatements, summaryFilters } = useDataContext();

useEffect(() => {
// By default on the first render, show the instruction/summary
if (selectedConnectionSummary) {
setShowConnectionDetails(SummaryType.Summary);
}
}, [selectedConnectionSummary])

// Values from the selected connection - In the SummaryType.summary
const viasConnection = getAllViasFromConnections(selectedConnectionSummary?.connections || {} as KsMapType);
const viasStatement = convertViaToString(Object.values(viasConnection))
const totalConnectionCount = Object.keys(selectedConnectionSummary?.connections || {} as KsMapType).length;
const phenotypeNamesArray = useMemo(() => getAllPhenotypes(selectedConnectionSummary?.connections || {} as KsMapType), [selectedConnectionSummary]);
const [phenotypes, setPhenotypes] = useState<PhenotypeType>({});


useEffect(() => {
// Generate the phenotype colors and set the phenotypes
if (selectedConnectionSummary && phenotypeNamesArray && phenotypeNamesArray.length > 0) {
const phenotypeColors: string[] = generatePhenotypeColors(phenotypeNamesArray.length)
const phenotypes: PhenotypeType = {};
Expand All @@ -79,27 +84,25 @@ function Connections() {


useEffect(() => {
// calculate the connectionsMap for the secondary heatmap
if (selectedConnectionSummary && phenotypes && selectedConnectionSummary.hierarchy && hierarchicalNodes) {
const destinations = Array.from(selectedConnectionSummary.endOrgan?.children?.values()).reduce((acc, organ, index) => {
acc[organ.id] = { ...organ, children: new Map<string, BaseEntity>(), order: index };
return acc;
}, {} as Record<string, Organ>);

const destinations = getDestinations(selectedConnectionSummary);
const connections = calculateSecondaryConnections(hierarchicalNodes, destinations, knowledgeStatements, summaryFilters, selectedConnectionSummary.hierarchy)
setConnectionsMap(connections);
}
}, [hierarchicalNodes, selectedConnectionSummary, summaryFilters, knowledgeStatements, phenotypes]);


const [xAxis, setXAxis] = useState<string[]>([]);
useEffect(() => {
// set the xAxis for the heatmap
if (selectedConnectionSummary) {
const xAxis = getXAxisForHeatmap(selectedConnectionSummary?.endOrgan || {} as Organ)
setXAxis(xAxis);
}
}, [selectedConnectionSummary]);

useEffect(() => {
// set the yAxis for the heatmap
if (selectedConnectionSummary && hierarchicalNodes) {
const hierarchyNode = {
[selectedConnectionSummary.hierarchy.id]: selectedConnectionSummary.hierarchy
Expand All @@ -110,13 +113,8 @@ function Connections() {
}, [selectedConnectionSummary, hierarchicalNodes]);


const heatmapData = useMemo(() => {
return getSecondaryHeatmapData(yAxis, connectionsMap);
}, [yAxis, connectionsMap]);

const [uniqueKS, setUniqueKS] = useState<KsMapType>({});

const handleCellClick = (x: number, y: number, yId: string): void => {
// when the heatmap cell is clicked
setSelectedCell({ x, y });
setConnectionPage(1)
const row = connectionsMap.get(yId);
Expand All @@ -127,6 +125,10 @@ function Connections() {
}
}

const heatmapData = useMemo(() => {
return getSecondaryHeatmapData(yAxis, connectionsMap);
}, [yAxis, connectionsMap]);

return (
<Box display='flex' flexDirection='column' minHeight={1}>
<SummaryHeader
Expand Down
1 change: 1 addition & 0 deletions src/components/ConnectivityGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ function ConnectivityGrid() {
}, [yAxis, connectionsMap]);

const handleClick = (x: number, y: number, yId: string): void => {
// When the primary heatmap cell is clicked - this sets the react-context state for Connections in SummaryType.summary
setSelectedCell({ x, y });
const row = connectionsMap.get(yId);
if (row) {
Expand Down
1 change: 0 additions & 1 deletion src/components/SummaryFiltersDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ const SummaryFiltersDropdown = ({ nerves, phenotypes }: {
}));
}
const convertPhenotypesToOptions = (phenotypes: PhenotypeType): Option[] => {
// filter the phenotype where label is other
return Object.values(phenotypes).map(phenotype => ({
id: phenotype.label,
label: phenotype.label,
Expand Down
11 changes: 6 additions & 5 deletions src/components/common/Heatmap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { vars } from "../../theme/variables";
import CollapsibleList from "./CollapsibleList";
import HeatMap from "react-heatmap-grid";
import HeatmapTooltip from "./HeatmapTooltip";
import { HierarchicalItem, PhenotypeType, SubConnections } from "./Types.ts";
import { HierarchicalItem, PhenotypeType, PhenotypeKsIdMap } from "./Types.ts";
import { getNormalizedValueForMinMax } from "../../services/summaryHeatmapService.ts";
import { generateYLabelsAndIds, getPhenotypeColors } from "../../services/heatmapService.ts";
import { OTHER_PHENOTYPE_LABEL } from "../../settings.ts";
Expand All @@ -21,11 +21,11 @@ interface HeatmapGridProps {
yAxisLabel?: string;
selectedCell?: { x: number, y: number } | null;
heatmapData?: number[][];
secondaryHeatmapData?: SubConnections[][];
secondaryHeatmapData?: PhenotypeKsIdMap[][];
phenotypes?: PhenotypeType;
}

const prepareSecondaryHeatmapData = (data?: SubConnections[][]): number[][] => {
const prepareSecondaryHeatmapData = (data?: PhenotypeKsIdMap[][]): number[][] => {
if (!data) return [];
return data.map(row => row.map(cell => cell.ksIds.size));
}
Expand Down Expand Up @@ -72,11 +72,12 @@ const HeatmapGrid: FC<HeatmapGridProps> = ({
_x: number,
_y: number
) => {
// Gets the color for secondary heatmap cell based on the phenotypes
if (phenotypes && secondary && secondaryHeatmapData && secondaryHeatmapData[_y] && secondaryHeatmapData[_y][_x]) {
const matrixCellPhenotypes = secondaryHeatmapData[_y][_x]?.phenotypes;
const heatmapCellPhenotypes = secondaryHeatmapData[_y][_x]?.phenotypes;

const phenotypeColorsSet = new Set<string>();
matrixCellPhenotypes.forEach(phenotype => {
heatmapCellPhenotypes.forEach(phenotype => {
const phnColor = phenotypes[phenotype]?.color
if (phnColor) {
phenotypeColorsSet.add(phnColor);
Expand Down
9 changes: 7 additions & 2 deletions src/components/common/Types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@ export type Option = {
export type LabelIdPair = { labels: string[], ids: string[] };

export type KsMapType = Record<string, KnowledgeStatement>;
export type SubConnections = { phenotypes: string[], ksIds: Set<string> };

export type PhenotypeKsIdMap = { phenotypes: string[], ksIds: Set<string> };

// SummaryType - Three types of summary views - default - instruction.
// When user clicks the primary heatmap, the summary view will be displayed.
// When user clicks the secondary heatmap, the detailed summary view will be displayed.
export enum SummaryType {
Summary = 'summary',
DetailedSummary = 'detailedSummary',
Expand All @@ -23,7 +28,7 @@ export enum SummaryType {

export type DetailedHeatmapData = { label: string, data: Set<string>[], id: string }[];

export interface IHeatmapMatrixInformation {
export interface HeatmapMatrixInformation {
heatmapMatrix: number[][];
detailedHeatmap: DetailedHeatmapData;
}
Expand Down
19 changes: 11 additions & 8 deletions src/components/connections/SummaryDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import CommonAccordion from "../common/Accordion.tsx";
import CommonChip from "../common/CommonChip.tsx";
import { ArrowOutward } from "../icons/index.tsx";
import { KsMapType } from '../common/Types.ts';
import { KnowledgeStatement } from '../../models/explorer.ts';
import { getConnectionDetails } from '../../services/summaryHeatmapService.ts';

const { gray500, gray700, gray800 } = vars;

Expand All @@ -37,17 +37,20 @@ const RowStack = ({ label, value, Icon }: { label: string, value: string, Icon?:
</Stack>
);


type SummaryDetailsProps = {
uniqueKS: KsMapType,
connectionPage: number
}

const SummaryDetails = ({
uniqueKS,
connectionPage
}: {
uniqueKS: KsMapType,
connectionPage: number
}) => {
const connectionDetails = uniqueKS !== undefined ?
uniqueKS[Object.keys(uniqueKS)[connectionPage - 1]]
: {} as KnowledgeStatement;
}: SummaryDetailsProps) => {
const connectionDetails = getConnectionDetails(uniqueKS, connectionPage);
const phenotype = connectionDetails?.phenotype || ''

// Details shown in the dropdown - from composer
const detailsObject = [
{
label: 'Laterality',
Expand Down
20 changes: 12 additions & 8 deletions src/components/connections/SummaryHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,25 @@ import { SummaryType, KsMapType } from '../common/Types';

const { gray100, gray600A, gray500 } = vars;


type SummaryHeaderProps = {
showDetails: SummaryType,
setShowDetails: (showDetails: SummaryType) => void,
uniqueKS: KsMapType,
connectionPage: number,
setConnectionPage: (connectionPage: number) => void,
totalConnectionCount: number
}


const SummaryHeader = ({
showDetails,
setShowDetails,
uniqueKS,
connectionPage,
setConnectionPage,
totalConnectionCount
}: {
showDetails: SummaryType,
setShowDetails: (showDetails: SummaryType) => void,
uniqueKS: KsMapType,
connectionPage: number,
setConnectionPage: (connectionPage: number) => void,
totalConnectionCount: number
}) => {
}: SummaryHeaderProps) => {
const totalUniqueKS = Object.keys(uniqueKS).length;

function getConnectionId() {
Expand Down
4 changes: 2 additions & 2 deletions src/services/heatmapService.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { HierarchicalNode, KnowledgeStatement, Organ } from "../models/explorer.ts";
import {ROOTS} from "./hierarchyService.ts";
import { HierarchicalItem, IHeatmapMatrixInformation, Option, KsMapType, LabelIdPair } from "../components/common/Types.ts";
import { HierarchicalItem, HeatmapMatrixInformation, Option, KsMapType, LabelIdPair } from "../components/common/Types.ts";
import {Filters} from "../context/DataContext.ts";

export function getYAxis(hierarchicalNodes: Record<string, HierarchicalNode>, hierarchyNode?: Record<string, HierarchicalNode>): HierarchicalItem[] {
Expand Down Expand Up @@ -98,7 +98,7 @@ export function calculateConnections(hierarchicalNodes: Record<string, Hierarchi


export function getHeatmapData(yAxis: HierarchicalItem[], connections: Map<string, Set<string>[]>) {
const heatmapInformation: IHeatmapMatrixInformation = {
const heatmapInformation: HeatmapMatrixInformation = {
heatmapMatrix: [],
detailedHeatmap: []
}
Expand Down
Loading

0 comments on commit 88efea9

Please sign in to comment.