Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Color tree by measurements #1924

Merged
merged 35 commits into from
Jan 21, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
d90c503
MeasurementsControlState: Remove unnecessary trailing commas
joverlee521 Dec 18, 2024
6c2e53b
measurements: Fix bug for numeric legend values in ordering
joverlee521 Dec 12, 2024
15dabdf
Add color tree by measurements feature
joverlee521 Dec 10, 2024
14a5650
ADD_EXTRA_METADATA: only use non-continuous colorings as filter traits
joverlee521 Dec 19, 2024
1391b9b
applyMeasurementsColorBy: Use multiple anchors for color scale
joverlee521 Dec 11, 2024
acf11a4
measurements: Refactor getting matching filters into separate function
joverlee521 Dec 12, 2024
a4b4d9c
applyMeasurementsColorBy: Only include measurements that pass filters
joverlee521 Dec 13, 2024
69853e2
measurements: Save color grouping value as a separate state
joverlee521 Dec 18, 2024
8b2773e
applyMeasurementsColorBy: remove old measurements coloring data
joverlee521 Dec 20, 2024
74eac4a
applyMeasurementsColorBy: batch dispatch actions
joverlee521 Dec 20, 2024
c0b7e91
Refactor `applyMeasurementsColorBy` into small functions
joverlee521 Dec 19, 2024
e1c74a4
Update measurements coloring when changing collection
joverlee521 Dec 24, 2024
9a5a183
Update measurements coloring when changing group by
joverlee521 Dec 24, 2024
3c35ed5
Update measurement coloring when updating measurements filters
joverlee521 Dec 21, 2024
c2db2bb
Update type `ColoringInfo`
joverlee521 Dec 24, 2024
17d411c
Refactor `addMeasurementsColorData` into smaller function
joverlee521 Dec 24, 2024
ade2c20
Support measurements coloring URL param `c=m-<grouping_value>`
joverlee521 Dec 24, 2024
440cddd
Add crosshair in measurements panel y-axis for coloring
joverlee521 Dec 30, 2024
ff28517
measurements: Allow click on grouping when current colorby is different
joverlee521 Dec 31, 2024
795efc7
Remove extra whitespace
joverlee521 Jan 2, 2025
9a4c328
tree: Add crosshair on tip matching measurements color grouping
joverlee521 Jan 2, 2025
5d51e9c
tree: re-draw measurements crosshair when modifying SVG
joverlee521 Jan 3, 2025
0dbc4e3
tree: update measurements crosshair when changing colorBy
joverlee521 Jan 3, 2025
fb3eba0
narratives: Ensure tree coloring is calculated for measurements colors
joverlee521 Jan 3, 2025
a2cfe54
narratives: Ensure old measurements coloring data is removed
joverlee521 Jan 3, 2025
bb44c2a
modifySVGInStages: remove crosshair in step 1
joverlee521 Jan 6, 2025
82e6f6d
Add comments for measurementColoringPrefix
joverlee521 Jan 7, 2025
9f6b032
Add tooltip to hint at color by measurements feature
joverlee521 Jan 7, 2025
27cdbb0
Click on measurements grouping to toggle back to previous coloring
joverlee521 Jan 8, 2025
e52f48d
Update type ColoringInfo: make `scale` optional
joverlee521 Jan 9, 2025
972ed91
Add `_hasMeasurementColor` attr and coloring for measurements coloring
joverlee521 Jan 9, 2025
e586a6c
Filter to colored tips when applying measurements coloring
joverlee521 Jan 9, 2025
921161c
measurements: Use `String` instead of `toString`
joverlee521 Jan 21, 2025
aead1cf
removeNodeAttrs: drop unnecessary conditional
joverlee521 Jan 21, 2025
daccd78
Update changelog
joverlee521 Jan 21, 2025
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
11 changes: 10 additions & 1 deletion src/actions/measurements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
CHANGE_MEASUREMENTS_COLOR_GROUPING,
CHANGE_MEASUREMENTS_DISPLAY,
CHANGE_MEASUREMENTS_GROUP_BY,
REMOVE_METADATA,
TOGGLE_MEASUREMENTS_OVERALL_MEAN,
TOGGLE_MEASUREMENTS_THRESHOLD,
} from "./types";
Expand Down Expand Up @@ -566,7 +567,12 @@ export const applyMeasurementsColorBy = (
groupingValue: string
): ThunkFunction => (dispatch, getState) => {
const { controls, measurements } = getState();
const measurementColorBy = `m-${groupingValue}`;

function encodeMeasurementColorBy(groupingValue: string): string {
const measurementColoringPrefix = "m-";
return `${measurementColoringPrefix}${groupingValue}`;
}
const measurementColorBy = encodeMeasurementColorBy(groupingValue);

const activeMeasurementFilters = getActiveMeasurementFilters(controls.measurementsFilters);
const strainMeasurementValues: {[strain: string]: number[]} = measurements.collectionToDisplay.measurements
Expand Down Expand Up @@ -605,6 +611,9 @@ export const applyMeasurementsColorBy = (
}
}

if (controls.measurementsColorGrouping !== undefined) {
dispatch({type: REMOVE_METADATA, nodeAttrsToRemove: [encodeMeasurementColorBy(controls.measurementsColorGrouping)]});
}
if (controls.measurementsColorGrouping !== groupingValue) {
dispatch({type: CHANGE_MEASUREMENTS_COLOR_GROUPING, controls:{measurementsColorGrouping: groupingValue}});
}
Expand Down
1 change: 1 addition & 0 deletions src/actions/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export const CHANGE_PANEL_LAYOUT = "CHANGE_PANEL_LAYOUT";
export const TOGGLE_PANEL_DISPLAY = "TOGGLE_PANEL_DISPLAY";
export const SET_MODAL = "SET_MODAL";
export const ADD_EXTRA_METADATA = "ADD_EXTRA_METADATA";
export const REMOVE_METADATA = "REMOVE_METADATA";
export const CHANGE_TREE_ROOT_IDX = "CHANGE_TREE_ROOT_IDX";
export const TOGGLE_NARRATIVE = "TOGGLE_NARRATIVE";
export const ENTROPY_DATA = "ENTROPY_DATA";
Expand Down
7 changes: 7 additions & 0 deletions src/reducers/controls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,13 @@ const Controls = (state: ControlsState = getDefaultControlsState(), action): Con
}
return newState;
}
case types.REMOVE_METADATA: {
const coloringsPresentOnTree = new Set(state.coloringsPresentOnTree);
action.nodeAttrsToRemove.forEach((colorBy: string): void => {
coloringsPresentOnTree.delete(colorBy);
})
return {...state, coloringsPresentOnTree};
}
case types.UPDATE_VISIBILITY_AND_BRANCH_THICKNESS: {
const colorScale = Object.assign({}, state.colorScale, { visibleLegendValues: action.visibleLegendValues });
return Object.assign({}, state, { colorScale: colorScale });
Expand Down
9 changes: 9 additions & 0 deletions src/reducers/metadata.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,15 @@ const Metadata = (state = {
}
return Object.assign({}, state, {colorings, geoResolutions});
}
case types.REMOVE_METADATA: {
const colorings = {...state.colorings};
action.nodeAttrsToRemove.forEach((colorBy) => {
if (colorBy in colorings) {
delete colorings[colorBy];
}
})
return {...state, colorings}
}
case types.SET_AVAILABLE: {
if (state.buildUrl) {
return state; // do not use data from getAvailable to overwrite a buildUrl set from a dataset JSON
Expand Down
19 changes: 18 additions & 1 deletion src/reducers/tree/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { AnyAction } from "@reduxjs/toolkit";
import { countTraitsAcrossTree } from "../../util/treeCountingHelpers";
import { addNodeAttrs } from "../../util/treeMiscHelpers";
import { addNodeAttrs, removeNodeAttrs } from "../../util/treeMiscHelpers";
import * as types from "../../actions/types";
import { TreeState, TreeTooState } from "./types";

Expand Down Expand Up @@ -92,6 +92,23 @@ const Tree = (
nodeAttrKeys
};
}
case types.REMOVE_METADATA: {
// remove data from `nodes` in-place, so no redux update will be triggered if you only listen to `nodes`
removeNodeAttrs(state.nodes, action.nodeAttrsToRemove);
const nodeAttrKeys = new Set(state.nodeAttrKeys);
const totalStateCounts = {...state.totalStateCounts};
action.nodeAttrsToRemove.forEach((attrKey: string): void => {
nodeAttrKeys.delete(attrKey);
if (attrKey in totalStateCounts) {
delete totalStateCounts[attrKey];
}
})
return {
...state,
totalStateCounts,
nodeAttrKeys,
}
}
default:
return state;
}
Expand Down
6 changes: 5 additions & 1 deletion src/reducers/tree/treeToo.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { AnyAction } from "@reduxjs/toolkit";
import { getDefaultTreeState } from ".";
import { addNodeAttrs } from "../../util/treeMiscHelpers";
import { addNodeAttrs, removeNodeAttrs } from "../../util/treeMiscHelpers";
import * as types from "../../actions/types";
import { TreeTooState } from "./types";

Expand Down Expand Up @@ -71,6 +71,10 @@ const treeToo = (
// add data into `nodes` in-place, so no redux update will be triggered if you only listen to `nodes`
addNodeAttrs(state.nodes, action.newNodeAttrs);
return state;
case types.REMOVE_METADATA:
// remove data from `nodes` in-place, so no redux update will be triggered if you only listen to `nodes`
removeNodeAttrs(state.nodes, action.nodeAttrsToRemove);
return state;
default:
return state;
}
Expand Down
17 changes: 17 additions & 0 deletions src/util/treeMiscHelpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -309,3 +309,20 @@ export const addNodeAttrs = (nodes, newAttrs) => {
}
});
};

/**
* Remove attrs from the `nodes` data structure.
* @param {Array} nodes
* @param {Array} attrsToRemove
*/
export const removeNodeAttrs = (nodes, attrsToRemove) => {
nodes.forEach((node) => {
if(!node.node_attrs) return;

attrsToRemove.forEach((attrName) => {
if(attrName in node.node_attrs){
delete node.node_attrs[attrName];
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can drop the conditional - delete doesn't throw if the attrName isn't a property

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, Python bleeding into JavaScript...dropped conditional in aead1cf.

})
})
}