Skip to content

Commit 1f9007c

Browse files
Make "Registering of All Segments for a BBox"- feature mag aware (#8082)
* mag register all segments for bbox feature mag aware * remove console.logs * add error toasts for missing mag or segmentation layer * add changelog * improve changelog * move line * bubble up API error to open toast in view * fix mag-related edge case * register segments for segmentation layers without volume annotation layers * add warning toast if segmentation layer isnt editable
1 parent a4cf17c commit 1f9007c

File tree

3 files changed

+55
-25
lines changed

3 files changed

+55
-25
lines changed

CHANGELOG.unreleased.md

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.released
1414
- It is now possible to focus a bounding box in the bounding box tab by clicking its edges in a viewport or via a newly added context menu entry. [#8054](https://github.com/scalableminds/webknossos/pull/8054)
1515
- Added the option to export nd datasets as ome tiff or tiff stack. Previously, this was only possible for 3d datasets. [#7971](https://github.com/scalableminds/webknossos/pull/7971)
1616
- Added an assertion to the backend to ensure unique keys in the metadata info of datasets and folders. [#8068](https://github.com/scalableminds/webknossos/issues/8068)
17+
- The feature to register all segments within a bounding box now takes the current magnification into consideration, e.g. for calculating the volume limit for a bounding box. [#8082](https://github.com/scalableminds/webknossos/pull/8082)
1718

1819
### Changed
1920
- Clicking on a bounding box within the bounding box tab centers it within the viewports and focusses it in the list. [#8049](https://github.com/scalableminds/webknossos/pull/8049)

frontend/javascripts/oxalis/api/api_latest.ts

+49-24
Original file line numberDiff line numberDiff line change
@@ -656,35 +656,55 @@ class TracingApi {
656656
bbName: string,
657657
options?: { maximumSegmentCount?: number; maximumVolume?: number },
658658
) => {
659+
const state = Store.getState();
659660
const maximumVolume = options?.maximumVolume ?? Constants.REGISTER_SEGMENTS_BB_MAX_VOLUME_VX;
660661
const maximumSegmentCount =
661662
options?.maximumSegmentCount ?? Constants.REGISTER_SEGMENTS_BB_MAX_SEGMENT_COUNT;
662663
const shape = Utils.computeShapeFromBoundingBox({ min, max });
663-
const volume = Math.ceil(shape[0] * shape[1] * shape[2]);
664+
665+
const segmentationLayerName = api.data.getVisibleSegmentationLayerName();
666+
if (segmentationLayerName == null) {
667+
throw new Error(
668+
"No segmentation layer is currently visible. Enable the one you want to register segments for.",
669+
);
670+
}
671+
672+
const resolutionInfo = getResolutionInfo(
673+
getLayerByName(state.dataset, segmentationLayerName).resolutions,
674+
);
675+
const theoreticalMagIndex = getActiveMagIndexForLayer(state, segmentationLayerName);
676+
const existingMagIndex = resolutionInfo.getIndexOrClosestHigherIndex(theoreticalMagIndex);
677+
if (existingMagIndex == null) {
678+
throw new Error("The index of the current mag could not be found.");
679+
}
680+
const currentMag = resolutionInfo.getResolutionByIndex(existingMagIndex);
681+
if (currentMag == null) {
682+
throw new Error("No mag could be found.");
683+
}
684+
685+
const volume =
686+
Math.ceil(shape[0] / currentMag[0]) *
687+
Math.ceil(shape[1] / currentMag[1]) *
688+
Math.ceil(shape[2] / currentMag[2]);
664689
if (volume > maximumVolume) {
665-
Toast.error(
666-
`The volume of the bounding box exceeds ${maximumVolume} Vx, please make it smaller.`,
690+
throw new Error(
691+
`The volume of the bounding box exceeds ${maximumVolume} vx, please make it smaller. Currently, the bounding box has a volume of ${volume} vx in the active resolution (${currentMag.join("-")}).`,
667692
);
668-
return;
669693
} else if (volume > maximumVolume / 8) {
670694
Toast.warning(
671695
"The volume of the bounding box is very large, registering all segments might take a while.",
672696
);
673697
}
674698

675-
const segmentationLayerName = api.data.getSegmentationLayerNames()[0];
676-
const layer = getLayerByName(Store.getState().dataset, segmentationLayerName);
677-
678-
const resolutionInfo = getResolutionInfo(layer.resolutions);
679-
const finestResolution = resolutionInfo.getFinestResolution();
680-
// By default, getDataForBoundingBox uses the finest existing magnification.
681-
// We use that as strides to traverse the data array properly.
682-
const [dx, dy, dz] = finestResolution;
683-
684-
const data = await api.data.getDataForBoundingBox(segmentationLayerName, {
685-
min,
686-
max,
687-
});
699+
const data = await api.data.getDataForBoundingBox(
700+
segmentationLayerName,
701+
{
702+
min,
703+
max,
704+
},
705+
existingMagIndex,
706+
);
707+
const [dx, dy, dz] = currentMag;
688708

689709
const segmentIdToPosition = new Map();
690710
let idx = 0;
@@ -703,21 +723,26 @@ class TracingApi {
703723
const segmentIdCount = Array.from(segmentIdToPosition.entries()).length;
704724
const halfMaxNoSegments = maximumSegmentCount / 2;
705725
if (segmentIdCount > maximumSegmentCount) {
706-
Toast.error(
726+
throw new Error(
707727
`The given bounding box contains ${segmentIdCount} segments, but only ${maximumSegmentCount} segments can be registered at once. Please reduce the size of the bounding box.`,
708728
);
709-
return;
710729
} else if (segmentIdCount > halfMaxNoSegments) {
711730
Toast.warning(
712731
`The bounding box contains more than ${halfMaxNoSegments} segments. Registering all segments might take a while.`,
713732
);
714733
}
715734

716-
const groupId = api.tracing.createSegmentGroup(
717-
`Segments for ${bbName}`,
718-
-1,
719-
segmentationLayerName,
720-
);
735+
let groupId = MISSING_GROUP_ID;
736+
try {
737+
groupId = api.tracing.createSegmentGroup(`Segments for ${bbName}`, -1, segmentationLayerName);
738+
} catch (_e) {
739+
console.info(
740+
`Volume tracing could not be found for the currently visible segmentation layer, registering segments for ${bbName} within root group.`,
741+
);
742+
Toast.warning(
743+
"The current segmentation layer is not editable and the segment list will not be persisted across page reloads. You can make it editable by clicking on the lock symbol to the right of the layer name.",
744+
);
745+
}
721746
const updateSegmentActions: BatchableUpdateSegmentAction[] = [];
722747
for (const [segmentId, position] of segmentIdToPosition.entries()) {
723748
api.tracing.registerSegment(segmentId, position, undefined, segmentationLayerName);

frontend/javascripts/oxalis/view/components/setting_input_views.tsx

+5-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ import type { OxalisState } from "oxalis/store";
3131
import type { APISegmentationLayer } from "types/api_flow_types";
3232
import { api } from "oxalis/singletons";
3333
import FastTooltip from "components/fast_tooltip";
34+
import Toast from "libs/toast";
35+
import { handleGenericError } from "libs/error_handling";
3436

3537
const ROW_GUTTER = 1;
3638

@@ -488,7 +490,9 @@ class UserBoundingBoxInput extends React.PureComponent<UserBoundingBoxInputProps
488490
onRegisterSegmentsForBB(value: Vector6, name: string): void {
489491
const min: Vector3 = [value[0], value[1], value[2]];
490492
const max: Vector3 = [value[0] + value[3], value[1] + value[4], value[2] + value[5]];
491-
api.tracing.registerSegmentsForBoundingBox(min, max, name);
493+
api.tracing
494+
.registerSegmentsForBoundingBox(min, max, name)
495+
.catch((error) => Toast.error(error.message));
492496
this.maybeCloseContextMenu();
493497
}
494498

0 commit comments

Comments
 (0)