Skip to content

Commit 275fc63

Browse files
authored
Expose setActiveTree and setTreeColorIndex in API (#2997)
* Expose setActiveTree and setTreeColorIndex in API (fixes #2996) * update changelog * add test for setTreeColor action and adapt typing of the corresponding function
1 parent 5284339 commit 275fc63

File tree

7 files changed

+76
-3
lines changed

7 files changed

+76
-3
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.md).
2020
- Added placeholders and functionality hints to (nearly) empty lists and tables in the admin views. [#2969](https://github.com/scalableminds/webknossos/pull/2969)
2121
- Added the possibility to import multiple NML files into the active tracing. This can be done by dragging and dropping the files directly into the tracing view. [#2908](https://github.com/scalableminds/webknossos/pull/2908)
2222
- During the import of multiple NML files, the user can select an option to automatically create a group per file so that the imported trees are organized in a hierarchy. [#2908](https://github.com/scalableminds/webknossos/pull/2908)
23+
- Added functions to the front-end API to activate a tree and to change the color of a tree. [#2997](https://github.com/scalableminds/webknossos/pull/2997)
2324

2425
### Changed
2526

app/assets/javascripts/libs/color_generator.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1509,7 +1509,7 @@ const rawRgbs = [
15091509
9,
15101510
];
15111511

1512-
const rgbs: Array<Vector3> = chunk3(rawRgbs).map(rgb =>
1512+
export const rgbs: Array<Vector3> = chunk3(rawRgbs).map(rgb =>
15131513
// $FlowFixMe Flow has troubles with understanding that mapping a tuple, returns another tuple
15141514
rgb.map(el => el / 255),
15151515
);

app/assets/javascripts/oxalis/api/api_latest.js

+27
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import {
2020
deleteTreeAction,
2121
setNodeRadiusAction,
2222
setTreeNameAction,
23+
setActiveTreeAction,
24+
setTreeColorIndexAction,
2325
} from "oxalis/model/actions/skeletontracing_actions";
2426
import {
2527
findTreeByNodeId,
@@ -243,6 +245,31 @@ class TracingApi {
243245
});
244246
}
245247

248+
/**
249+
* Makes the specified tree active. Within the tree, the node with the highest ID will be activated.
250+
*
251+
* @example
252+
* api.tracing.setActiveTree(3);
253+
*/
254+
setActiveTree(treeId: number) {
255+
const tracing = Store.getState().tracing;
256+
assertSkeleton(tracing);
257+
Store.dispatch(setActiveTreeAction(treeId));
258+
}
259+
260+
/**
261+
* Changes the color of the referenced tree. Internally, a pre-defined array of colors is used which is
262+
* why this function uses a colorIndex (between 0 and 500) instead of a proper color.
263+
*
264+
* @example
265+
* api.tracing.setTreeColorIndex(3, 10);
266+
*/
267+
setTreeColorIndex(treeId: ?number, colorIndex: number) {
268+
const tracing = Store.getState().tracing;
269+
assertSkeleton(tracing);
270+
Store.dispatch(setTreeColorIndexAction(treeId, colorIndex));
271+
}
272+
246273
/**
247274
* Returns the name for a given tree id. If none is given, the name of the active tree is returned.
248275
*

app/assets/javascripts/oxalis/model/actions/skeletontracing_actions.js

+15
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ type SetActiveTreeActionType = { type: "SET_ACTIVE_TREE", treeId: number };
7272
type MergeTreesActionType = { type: "MERGE_TREES", sourceNodeId: number, targetNodeId: number };
7373
type SetTreeNameActionType = { type: "SET_TREE_NAME", name: ?string, treeId: ?number };
7474
type SelectNextTreeActionType = { type: "SELECT_NEXT_TREE", forward: ?boolean };
75+
type SetTreeColorIndexActionType = {
76+
type: "SET_TREE_COLOR_INDEX",
77+
treeId: ?number,
78+
colorIndex: number,
79+
};
7580
type ShuffleTreeColorActionType = { type: "SHUFFLE_TREE_COLOR", treeId?: number };
7681
type ShuffleAllTreeColorsActionType = { type: "SHUFFLE_ALL_TREE_COLORS", treeId?: number };
7782
type CreateCommentActionType = {
@@ -106,6 +111,7 @@ export type SkeletonTracingActionType =
106111
| SelectNextTreeActionType
107112
| ShuffleTreeColorActionType
108113
| ShuffleAllTreeColorsActionType
114+
| SetTreeColorIndexActionType
109115
| CreateCommentActionType
110116
| DeleteCommentActionType
111117
| ToggleTreeActionType
@@ -310,6 +316,15 @@ export const selectNextTreeAction = (forward: ?boolean = true): SelectNextTreeAc
310316
forward,
311317
});
312318

319+
export const setTreeColorIndexAction = (
320+
treeId: ?number,
321+
colorIndex: number,
322+
): SetTreeColorIndexActionType => ({
323+
type: "SET_TREE_COLOR_INDEX",
324+
treeId,
325+
colorIndex,
326+
});
327+
313328
export const shuffleTreeColorAction = (treeId: number): ShuffleTreeColorActionType => ({
314329
type: "SHUFFLE_TREE_COLOR",
315330
treeId,

app/assets/javascripts/oxalis/model/reducers/skeletontracing_reducer.js

+11
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
deleteNode,
1717
deleteEdge,
1818
shuffleTreeColor,
19+
setTreeColorIndex,
1920
createComment,
2021
deleteComment,
2122
mergeTrees,
@@ -376,6 +377,16 @@ function SkeletonTracingReducer(state: OxalisState, action: ActionType): OxalisS
376377
});
377378
}
378379

380+
case "SET_TREE_COLOR_INDEX": {
381+
const { colorIndex } = action;
382+
return getTree(skeletonTracing, action.treeId)
383+
.chain(tree => setTreeColorIndex(skeletonTracing, tree, colorIndex))
384+
.map(([tree, treeId]) =>
385+
update(state, { tracing: { trees: { [treeId]: { $set: tree } } } }),
386+
)
387+
.getOrElse(state);
388+
}
389+
379390
case "SHUFFLE_TREE_COLOR": {
380391
return getTree(skeletonTracing, action.treeId)
381392
.chain(tree => shuffleTreeColor(skeletonTracing, tree))

app/assets/javascripts/oxalis/model/reducers/skeletontracing_reducer_helpers.js

+9-2
Original file line numberDiff line numberDiff line change
@@ -605,8 +605,15 @@ export function shuffleTreeColor(
605605
tree: TreeType,
606606
): Maybe<[TreeType, number]> {
607607
const randomId = _.random(0, 10000, false);
608-
// ColorGenerator fails to produce distinct color for huge ids (Infinity)
609-
const newTree = update(tree, { color: { $set: ColorGenerator.distinctColorForId(randomId) } });
608+
return setTreeColorIndex(skeletonTracing, tree, randomId);
609+
}
610+
611+
export function setTreeColorIndex(
612+
skeletonTracing: SkeletonTracingType,
613+
tree: TreeType,
614+
colorIndex: number,
615+
): Maybe<[TreeType, number]> {
616+
const newTree = update(tree, { color: { $set: ColorGenerator.distinctColorForId(colorIndex) } });
610617
return Maybe.Just([newTree, tree.treeId]);
611618
}
612619

app/assets/javascripts/test/reducers/skeletontracing_reducer.spec.js

+12
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import ChainReducer from "test/helpers/chainReducer";
1313
import update from "immutability-helper";
1414
import DiffableMap from "libs/diffable_map";
1515
import EdgeCollection from "oxalis/model/edge_collection";
16+
import { rgbs as colors } from "libs/color_generator";
1617

1718
mock.stopAll();
1819
mock("app", { currentUser: { firstName: "SCM", lastName: "Boy" } });
@@ -1368,3 +1369,14 @@ test("SkeletonTracing should delete a comment for a specified node (1/2)", t =>
13681369
t.deepEqual(newState.tracing.trees[1].comments[0].nodeId, 1);
13691370
t.deepEqual(newState.tracing.trees[1].comments[1].nodeId, 3);
13701371
});
1372+
1373+
test("SkeletonTracing should change the color of a specified tree", t => {
1374+
const colorIndex = 10;
1375+
const newState = SkeletonTracingReducer(
1376+
initialState,
1377+
SkeletonTracingActions.setTreeColorIndexAction(1, colorIndex),
1378+
);
1379+
1380+
t.not(newState, initialState);
1381+
t.is(newState.tracing.trees[1].color, colors[colorIndex - 1]);
1382+
});

0 commit comments

Comments
 (0)