From 51ab328b961dce358bfaa4cdb5b5184726b4fc82 Mon Sep 17 00:00:00 2001 From: aranega Date: Fri, 22 Aug 2025 09:45:55 -0600 Subject: [PATCH 1/2] CELE-144 Fix synapses that are not removed after the deletion of a related neuron --- .../components/ViewerContainer/Neurons.tsx | 3 +- .../ViewerContainer/SynapsesTreeView.tsx | 5 ++- .../SynapsesTreeViewHelpers.ts | 3 ++ .../frontend/src/models/workspace.ts | 44 +++++++++++++++++++ 4 files changed, 52 insertions(+), 3 deletions(-) diff --git a/applications/visualizer/frontend/src/components/ViewerContainer/Neurons.tsx b/applications/visualizer/frontend/src/components/ViewerContainer/Neurons.tsx index 9780e4f7..7a68a43b 100644 --- a/applications/visualizer/frontend/src/components/ViewerContainer/Neurons.tsx +++ b/applications/visualizer/frontend/src/components/ViewerContainer/Neurons.tsx @@ -57,7 +57,8 @@ const Neurons = ({ children }) => { } }; const handleDeleteNeuron = (neuronId: string) => { - currentWorkspace.deactivateNeuron(neuronId); + const workspace = currentWorkspace.deactivateSynapsesOfNeuron(neuronId); + workspace.deactivateNeuron(neuronId); }; const onSearchNeurons = (nameFragment) => { diff --git a/applications/visualizer/frontend/src/components/ViewerContainer/SynapsesTreeView.tsx b/applications/visualizer/frontend/src/components/ViewerContainer/SynapsesTreeView.tsx index e064bc6c..d53f2207 100644 --- a/applications/visualizer/frontend/src/components/ViewerContainer/SynapsesTreeView.tsx +++ b/applications/visualizer/frontend/src/components/ViewerContainer/SynapsesTreeView.tsx @@ -155,6 +155,7 @@ export default function BasicRichTreeView() { itemVisibilityStates, itemColorStates, openColorPicker, + currentWorkspace.activeSynapses, ]); // Update tree items when dependencies change @@ -254,7 +255,7 @@ export default function BasicRichTreeView() { } } }, - [currentWorkspace, treeItems], + [currentWorkspace, treeItems, currentWorkspace.visibilities.synapses, currentWorkspace.activeSynapses], ); useEffect(() => { @@ -346,7 +347,7 @@ export default function BasicRichTreeView() { ); }, }), - [handleColorClick, currentWorkspace, handleSynapseVisibilityToggle, treeItems], + [handleColorClick, currentWorkspace, handleSynapseVisibilityToggle, treeItems, currentWorkspace.visibilities.synapses, currentWorkspace.activeSynapses], ); return ( diff --git a/applications/visualizer/frontend/src/components/ViewerContainer/SynapsesTreeViewHelpers.ts b/applications/visualizer/frontend/src/components/ViewerContainer/SynapsesTreeViewHelpers.ts index 402fc21d..9a737bbb 100644 --- a/applications/visualizer/frontend/src/components/ViewerContainer/SynapsesTreeViewHelpers.ts +++ b/applications/visualizer/frontend/src/components/ViewerContainer/SynapsesTreeViewHelpers.ts @@ -18,6 +18,9 @@ export const transformSynapsesToTree = (synapses: any, availableNeurons: any, cu // Helper function to get synapse visibility const getSynapseVisibility = (synapseId: number): boolean => { const synapseVisibility = currentWorkspace.getSynapseVisibility(synapseId); + if (!synapseVisibility) { + return false; + } return Object.values(synapseVisibility).every((e: any) => e === undefined || e.visibility === Visibility.Visible); }; diff --git a/applications/visualizer/frontend/src/models/workspace.ts b/applications/visualizer/frontend/src/models/workspace.ts index db8e786c..a6812789 100644 --- a/applications/visualizer/frontend/src/models/workspace.ts +++ b/applications/visualizer/frontend/src/models/workspace.ts @@ -172,6 +172,25 @@ export class Workspace { return this; } + @triggerUpdate + deactivateSynapsesOfNeuron(neuronId: string) { + const neuronClass = this.availableNeurons?.[neuronId]?.nclass; + if (!neuronClass) { + return this; + } + const relatedSynapses = this.synapsesData?.synapses[neuronClass]; + if (!relatedSynapses) { + return this; + } + delete this.synapsesData.synapses[neuronClass]; + for (const synapseId of collectLeafProps(relatedSynapses, "id")) { + delete this.visibilities.synapses[synapseId]; + this.activeSynapses.delete(synapseId); + } + + return this; + } + @triggerUpdate hideNeuron(neuronId: string) { if (!(neuronId in this.visibilities.neurons)) { @@ -538,3 +557,28 @@ export class Workspace { return allSynapses; } } + +function collectLeafProps(obj: unknown, targetProp: keyof T): T[keyof T][] { + const results: T[keyof T][] = []; + + function recurse(node: unknown) { + if (node == null || typeof node !== "object") return; + + // We collect the target property + if (targetProp in (node as object)) { + results.push((node as T)[targetProp]); + } + + // Traverse every property + for (const value of Object.values(node)) { + if (Array.isArray(value)) { + for (const child of value) recurse(child); + } else if (typeof value === "object") { + recurse(value); + } + } + } + + recurse(obj); + return results; +} From fc267b6bda569e1d28d250ab7ab560094587d161 Mon Sep 17 00:00:00 2001 From: aranega Date: Fri, 22 Aug 2025 09:58:22 -0600 Subject: [PATCH 2/2] CELE-144 Fix synapses deletion order when a neuron is removed --- applications/visualizer/frontend/src/models/workspace.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/visualizer/frontend/src/models/workspace.ts b/applications/visualizer/frontend/src/models/workspace.ts index a6812789..d47b96a2 100644 --- a/applications/visualizer/frontend/src/models/workspace.ts +++ b/applications/visualizer/frontend/src/models/workspace.ts @@ -182,11 +182,11 @@ export class Workspace { if (!relatedSynapses) { return this; } - delete this.synapsesData.synapses[neuronClass]; for (const synapseId of collectLeafProps(relatedSynapses, "id")) { delete this.visibilities.synapses[synapseId]; this.activeSynapses.delete(synapseId); } + delete this.synapsesData.synapses[neuronClass]; return this; }