Skip to content

Commit

Permalink
Merge pull request #37 from MetaCell/feature/ESCKAN-51
Browse files Browse the repository at this point in the history
Feature/esckan 51
  • Loading branch information
ddelpiano authored Jun 10, 2024
2 parents 89cb5cf + e2223ff commit f8bac30
Show file tree
Hide file tree
Showing 16 changed files with 733 additions and 220 deletions.
77 changes: 50 additions & 27 deletions src/components/Connections.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import {
HierarchicalItem,
PhenotypeKsIdMap,
SummaryType,
KsMapType,
KsRecord,
Option,
} from './common/Types';
import { useDataContext } from '../context/DataContext.ts';
import {
Expand Down Expand Up @@ -50,6 +51,14 @@ const styles = {
};

function Connections() {
const {
selectedConnectionSummary,
majorNerves,
hierarchicalNodes,
knowledgeStatements,
filters,
} = useDataContext();

const [showConnectionDetails, setShowConnectionDetails] =
useState<SummaryType>(SummaryType.Instruction);
const [connectionsMap, setConnectionsMap] = useState<
Expand All @@ -62,16 +71,19 @@ function Connections() {
y: number;
} | null>(null); // useful for coordinates
const [knowledgeStatementsMap, setKnowledgeStatementsMap] =
useState<KsMapType>({});
useState<KsRecord>({});
const [xAxis, setXAxis] = useState<string[]>([]);
const [nerveFilters, setNerveFilters] = useState<Option[]>([]);
const [phenotypeFilters, setPhenotypeFilters] = useState<Option[]>([]);

const {
selectedConnectionSummary,
majorNerves,
hierarchicalNodes,
knowledgeStatements,
summaryFilters,
} = useDataContext();
const summaryFilters = useMemo(
() => ({
...filters,
Nerve: nerveFilters,
Phenotype: phenotypeFilters,
}),
[filters, nerveFilters, phenotypeFilters],
);

useEffect(() => {
// By default on the first render, show the instruction/summary
Expand All @@ -82,28 +94,38 @@ function Connections() {

// Values from the selected connection - In the SummaryType.summary
const viasConnection = getAllViasFromConnections(
selectedConnectionSummary?.connections || ({} as KsMapType),
selectedConnectionSummary?.filteredKnowledgeStatements || ({} as KsRecord),
);
const viasStatement = convertViaToString(Object.values(viasConnection));
const totalConnectionCount = Object.keys(
selectedConnectionSummary?.connections || ({} as KsMapType),
selectedConnectionSummary?.filteredKnowledgeStatements || ({} as KsRecord),
).length;
const nerves = getNerveFilters(viasConnection, majorNerves);

const availableNerves = getNerveFilters(viasConnection, majorNerves);
const availablePhenotypes = useMemo(
() =>
selectedConnectionSummary
? getAllPhenotypes(
selectedConnectionSummary.filteredKnowledgeStatements,
)
: [],
[selectedConnectionSummary],
);

useEffect(() => {
// calculate the connectionsMap for the secondary heatmap
if (
selectedConnectionSummary &&
selectedConnectionSummary.hierarchy &&
selectedConnectionSummary.hierarchicalNode &&
hierarchicalNodes
) {
const destinations = getDestinations(selectedConnectionSummary);
const connections = calculateSecondaryConnections(
hierarchicalNodes,
destinations,
knowledgeStatements,
selectedConnectionSummary.filteredKnowledgeStatements,
summaryFilters,
selectedConnectionSummary.hierarchy,
selectedConnectionSummary.hierarchicalNode,
);
setConnectionsMap(connections);
}
Expand All @@ -114,11 +136,6 @@ function Connections() {
knowledgeStatements,
]);

const selectedPhenotypes = useMemo(
() => getAllPhenotypes(connectionsMap),
[connectionsMap],
);

useEffect(() => {
// set the xAxis for the heatmap
if (selectedConnectionSummary) {
Expand All @@ -133,8 +150,8 @@ function Connections() {
// set the yAxis for the heatmap
if (selectedConnectionSummary && hierarchicalNodes) {
const hierarchyNode = {
[selectedConnectionSummary.hierarchy.id]:
selectedConnectionSummary.hierarchy,
[selectedConnectionSummary.hierarchicalNode.id]:
selectedConnectionSummary.hierarchicalNode,
};
const yHierarchicalItem = getYAxis(hierarchicalNodes, hierarchyNode);
setYAxis(yHierarchicalItem);
Expand All @@ -153,7 +170,9 @@ function Connections() {

if (
selectedConnectionSummary &&
Object.keys(selectedConnectionSummary.connections).length !== 0
Object.keys(selectedConnectionSummary.filteredKnowledgeStatements)
.length !== 0 &&
ksIds.length > 0
) {
setShowConnectionDetails(SummaryType.DetailedSummary);
const ksMap = getKnowledgeStatementMap(ksIds, knowledgeStatements);
Expand Down Expand Up @@ -196,7 +215,7 @@ function Connections() {
Connection origin
</Typography>
<TextField
value={selectedConnectionSummary?.origin || ''}
value={selectedConnectionSummary?.hierarchicalNode.name || ''}
fullWidth
/>
</Box>
Expand Down Expand Up @@ -255,8 +274,12 @@ function Connections() {
</Typography>
</Box>
<SummaryFiltersDropdown
nerves={nerves}
phenotypes={selectedPhenotypes}
nerves={availableNerves}
nerveFilters={nerveFilters}
setNerveFilters={setNerveFilters}
phenotypes={availablePhenotypes}
phenotypeFilters={phenotypeFilters}
setPhenotypeFilters={setPhenotypeFilters}
/>
<HeatmapGrid
yAxis={yAxis}
Expand All @@ -270,7 +293,7 @@ function Connections() {
/>
</Box>

<PhenotypeLegend phenotypes={selectedPhenotypes} />
<PhenotypeLegend phenotypes={availablePhenotypes} />
</>
)}
</Box>
Expand Down
38 changes: 27 additions & 11 deletions src/components/ConnectivityGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { useDataContext } from '../context/DataContext.ts';
import {
calculateConnections,
getMinMaxConnections,
getHierarchyFromId,
getXAxisOrgans,
getYAxis,
getHeatmapData,
Expand All @@ -32,7 +31,8 @@ function ConnectivityGrid() {
organs,
knowledgeStatements,
filters,
setConnectionSummary,
setFilters,
setSelectedConnectionSummary,
} = useDataContext();

const [yAxis, setYAxis] = useState<HierarchicalItem[]>([]);
Expand All @@ -45,6 +45,7 @@ function ConnectivityGrid() {
x: number;
y: number;
} | null>(null);
const [initialYAxis, setInitialYAxis] = useState<HierarchicalItem[]>([]);

useEffect(() => {
const connections = calculateConnections(
Expand Down Expand Up @@ -72,13 +73,14 @@ function ConnectivityGrid() {
useEffect(() => {
const yAxis = getYAxis(hierarchicalNodes);
setYAxis(yAxis);
setInitialYAxis(yAxis);
}, [hierarchicalNodes]);

const { heatmapData, detailedHeatmapData } = useMemo(() => {
const heatmapdata = getHeatmapData(yAxis, connectionsMap);
const heatmapData = getHeatmapData(yAxis, connectionsMap);
return {
heatmapData: heatmapdata.heatmapMatrix,
detailedHeatmapData: heatmapdata.detailedHeatmap,
heatmapData: heatmapData.heatmapMatrix,
detailedHeatmapData: heatmapData.detailedHeatmap,
};
}, [yAxis, connectionsMap]);

Expand All @@ -88,18 +90,31 @@ function ConnectivityGrid() {
const row = connectionsMap.get(yId);
if (row) {
const endOrgan = xAxisOrgans[x];
const origin = detailedHeatmapData[y];
const hierarchy = getHierarchyFromId(origin.id, hierarchicalNodes);
const nodeData = detailedHeatmapData[y];
const hierarchicalNode = hierarchicalNodes[nodeData.id];
const ksMap = getKnowledgeStatementMap(row[x], knowledgeStatements);

setConnectionSummary({
origin: origin.label,
endOrgan: endOrgan,
setSelectedConnectionSummary({
connections: ksMap,
hierarchy: hierarchy,
endOrgan: endOrgan,
hierarchicalNode: hierarchicalNode,
});
}
};

const handleReset = () => {
setYAxis(initialYAxis);
setFilters({
Origin: [],
EndOrgan: [],
Species: [],
Phenotype: [],
apiNATOMY: [],
Via: [],
});
setSelectedCell(null);
};

const isLoading = yAxis.length == 0;

return isLoading ? (
Expand Down Expand Up @@ -156,6 +171,7 @@ function ConnectivityGrid() {
background: 'transparent',
},
}}
onClick={handleReset}
>
Reset grid
</Button>
Expand Down
57 changes: 36 additions & 21 deletions src/components/SummaryFiltersDropdown.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { useMemo } from 'react';
import { SummaryFilters, useDataContext } from '../context/DataContext';
import CustomFilterDropdown from './common/CustomFilterDropdown';
import { Option } from './common/Types';
import { Box } from '@mui/material';
Expand All @@ -9,8 +8,10 @@ import {
} from '../services/searchService';
import { OTHER_PHENOTYPE_LABEL } from '../settings';

type FilterKey = 'Phenotype' | 'Nerve';

interface FilterConfig {
id: keyof SummaryFilters;
id: FilterKey;
placeholder: string;
searchPlaceholder: string;
}
Expand All @@ -31,12 +32,18 @@ const filterConfig: FilterConfig[] = [
const SummaryFiltersDropdown = ({
nerves,
phenotypes,
nerveFilters,
setNerveFilters,
phenotypeFilters,
setPhenotypeFilters,
}: {
nerves: { [key: string]: string };
phenotypes: string[];
nerveFilters: Option[];
setNerveFilters: React.Dispatch<React.SetStateAction<Option[]>>;
phenotypeFilters: Option[];
setPhenotypeFilters: React.Dispatch<React.SetStateAction<Option[]>>;
}) => {
const { summaryFilters, setSummaryFilters } = useDataContext();

const convertNervesToOptions = (nerves: {
[key: string]: string;
}): Option[] => {
Expand All @@ -47,6 +54,7 @@ const SummaryFiltersDropdown = ({
content: [],
}));
};

const convertPhenotypesToOptions = (phenotypes: string[]): Option[] => {
return phenotypes
.map((phenotype) => ({
Expand All @@ -62,22 +70,31 @@ const SummaryFiltersDropdown = ({
() => convertPhenotypesToOptions(phenotypes),
[phenotypes],
);

const nerveOptions = useMemo(() => convertNervesToOptions(nerves), [nerves]);

const handleSelect = (
filterKey: keyof typeof summaryFilters,
selectedOptions: Option[],
) => {
setSummaryFilters((prevFilters) => ({
...prevFilters,
[filterKey]: selectedOptions,
}));
const filterStateMap: {
[K in FilterKey]: {
filters: Option[];
setFilters: React.Dispatch<React.SetStateAction<Option[]>>;
searchFunction: (value: string) => Option[];
};
} = {
Phenotype: {
filters: phenotypeFilters,
setFilters: setPhenotypeFilters,
searchFunction: (value: string) =>
searchPhenotypeFilter(value, phenotypeOptions),
},
Nerve: {
filters: nerveFilters,
setFilters: setNerveFilters,
searchFunction: (value: string) => searchNerveFilter(value, nerveOptions),
},
};

const searchFunctions = {
Phenotype: (value: string) =>
searchPhenotypeFilter(value, phenotypeOptions),
Nerve: (value: string) => searchNerveFilter(value, nerveOptions),
const handleSelect = (filterKey: FilterKey, selectedOptions: Option[]) => {
filterStateMap[filterKey].setFilters(selectedOptions);
};

return (
Expand All @@ -88,13 +105,11 @@ const SummaryFiltersDropdown = ({
id={filter.id}
placeholder={filter.placeholder}
searchPlaceholder={filter.searchPlaceholder}
selectedOptions={summaryFilters[filter.id]}
selectedOptions={filterStateMap[filter.id].filters}
onSearch={(searchValue: string) =>
searchFunctions[filter.id](searchValue)
}
onSelect={(options: Option[]) =>
handleSelect(filter.id as keyof SummaryFilters, options)
filterStateMap[filter.id].searchFunction(searchValue)
}
onSelect={(options: Option[]) => handleSelect(filter.id, options)}
/>
))}
</Box>
Expand Down
Loading

0 comments on commit f8bac30

Please sign in to comment.