Skip to content

Commit a40db75

Browse files
fm3philippotto
andauthored
Create Annotation From View Mode: Keep Activated Mapping (#6647)
* [WIP] Create Annotation From View Mode: Keep Activated Mapping * fix typing errors * pass active mapping name when creating explorational from dataset view mode * clean up * changelog * also use potentially active mapping when making a segmentation layer editable (i.e., adding a volume annotation layer) Co-authored-by: Philipp Otto <philipp.4096@googlemail.com> Co-authored-by: Philipp Otto <philippotto@users.noreply.github.com>
1 parent 0b5c1f9 commit a40db75

File tree

9 files changed

+55
-6
lines changed

9 files changed

+55
-6
lines changed

CHANGELOG.unreleased.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.released
1919
- When adding remote Zarr datasets with multiple channels, channels are converted into layers. [#6609](https://github.com/scalableminds/webknossos/pull/6609)
2020
- When adding a remote OME-NGFF dataset with labels, these are added as segmentation layers. [#6638](https://github.com/scalableminds/webknossos/pull/6638)
2121
- The scale bar is now included in screenshots of the viewports made using the `Q` shortcut or the "Screenshot" menu entry. If the scale bar should not be included, disable it using "Settings - Viewport Options - Show Scalebars". [#6644](https://github.com/scalableminds/webknossos/pull/6644)
22+
- When creating an annotation from the dataset view, a previously selected mapping of the segmentation layer is now automatically selected in the volume annotation layer fallback segmentation as well. [#6647](https://github.com/scalableminds/webknossos/pull/6647)
2223

2324
### Changed
2425
- The log viewer in the Voxelytics workflow reporting now uses a virtualized list. [#6579](https://github.com/scalableminds/webknossos/pull/6579)

app/controllers/AnnotationController.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import scala.concurrent.duration._
3333

3434
case class AnnotationLayerParameters(typ: AnnotationLayerType,
3535
fallbackLayerName: Option[String],
36+
mappingName: Option[String] = None,
3637
resolutionRestrictions: Option[ResolutionRestrictions],
3738
name: String)
3839
object AnnotationLayerParameters {

app/controllers/LegacyApiController.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,7 @@ class LegacyApiController @Inject()(annotationController: AnnotationController,
427427
Some(
428428
AnnotationLayerParameters(AnnotationLayerType.Skeleton,
429429
request.body.fallbackLayerName,
430+
None,
430431
request.body.resolutionRestrictions,
431432
name = AnnotationLayer.defaultSkeletonLayerName))
432433
val volumeParameters =
@@ -435,6 +436,7 @@ class LegacyApiController @Inject()(annotationController: AnnotationController,
435436
Some(
436437
AnnotationLayerParameters(AnnotationLayerType.Volume,
437438
request.body.fallbackLayerName,
439+
None,
438440
request.body.resolutionRestrictions,
439441
name = AnnotationLayer.defaultVolumeLayerName))
440442
List(skeletonParameters, volumeParameters).flatten

app/models/annotation/AnnotationService.scala

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,8 @@ class AnnotationService @Inject()(
139139
boundingBox: Option[BoundingBox] = None,
140140
startPosition: Option[Vec3Int] = None,
141141
startRotation: Option[Vec3Double] = None,
142-
resolutionRestrictions: ResolutionRestrictions
142+
resolutionRestrictions: ResolutionRestrictions,
143+
mappingName: Option[String]
143144
): Fox[VolumeTracing] = {
144145
val resolutions = VolumeTracingDownsampling.resolutionsForVolumeTracing(dataSource, fallbackLayer)
145146
val resolutionsRestricted = resolutionRestrictions.filterAllowed(resolutions)
@@ -160,6 +161,7 @@ class AnnotationService @Inject()(
160161
0,
161162
VolumeTracingDefaults.zoomLevel,
162163
organizationName = Some(datasetOrganizationName),
164+
mappingName = mappingName,
163165
resolutions = resolutionsRestricted.map(vec3IntToProto)
164166
)
165167
}
@@ -249,7 +251,8 @@ class AnnotationService @Inject()(
249251
datasetOrganizationName,
250252
fallbackLayer,
251253
resolutionRestrictions =
252-
annotationLayerParameters.resolutionRestrictions.getOrElse(ResolutionRestrictions.empty)
254+
annotationLayerParameters.resolutionRestrictions.getOrElse(ResolutionRestrictions.empty),
255+
mappingName = annotationLayerParameters.mappingName
253256
)
254257
volumeTracingAdapted = oldPrecedenceLayerProperties.map { p =>
255258
volumeTracing.copy(
@@ -361,6 +364,7 @@ class AnnotationService @Inject()(
361364
newAnnotationLayerParameters = AnnotationLayerParameters(
362365
newAnnotationLayerType,
363366
usedFallbackLayerName,
367+
None,
364368
Some(ResolutionRestrictions.empty),
365369
AnnotationLayer.defaultNameForType(newAnnotationLayerType))
366370
_ <- addAnnotationLayer(annotation, organizationName, newAnnotationLayerParameters) ?~> "makeHybrid.createTracings.failed"
@@ -524,7 +528,8 @@ class AnnotationService @Inject()(
524528
},
525529
startPosition = Some(startPosition),
526530
startRotation = Some(startRotation),
527-
resolutionRestrictions = resolutionRestrictions
531+
resolutionRestrictions = resolutionRestrictions,
532+
mappingName = None
528533
)
529534
} yield volumeTracing
530535

frontend/javascripts/admin/admin_rest_api.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,7 @@ type AnnotationLayerCreateDescriptor = {
661661
typ: "Skeleton" | "Volume";
662662
name: string;
663663
fallbackLayerName?: string | null | undefined;
664+
mappingName?: string | null | undefined;
664665
resolutionRestrictions?: APIResolutionRestrictions | null | undefined;
665666
};
666667

@@ -789,6 +790,7 @@ export function createExplorational(
789790
datasetId: APIDatasetId,
790791
typ: TracingType,
791792
fallbackLayerName?: string | null | undefined,
793+
mappingName?: string | null | undefined,
792794
resolutionRestrictions?: APIResolutionRestrictions | null | undefined,
793795
options: RequestOptions = {},
794796
): Promise<APIAnnotation> {
@@ -808,6 +810,7 @@ export function createExplorational(
808810
typ: "Volume",
809811
name: fallbackLayerName || "Volume",
810812
fallbackLayerName,
813+
mappingName,
811814
resolutionRestrictions,
812815
},
813816
];
@@ -821,6 +824,7 @@ export function createExplorational(
821824
typ: "Volume",
822825
name: fallbackLayerName || "Volume",
823826
fallbackLayerName,
827+
mappingName,
824828
resolutionRestrictions,
825829
},
826830
];

frontend/javascripts/oxalis/view/action_bar_view.tsx

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
import { trackAction } from "oxalis/model/helpers/analytics";
1313
import AddNewLayoutModal from "oxalis/view/action-bar/add_new_layout_modal";
1414
import { withAuthentication } from "admin/auth/authentication_modal";
15-
import type { ViewMode, ControlMode } from "oxalis/constants";
15+
import { ViewMode, ControlMode, MappingStatusEnum } from "oxalis/constants";
1616
import constants, { ControlModeEnum } from "oxalis/constants";
1717
import DatasetPositionView from "oxalis/view/action-bar/dataset_position_view";
1818
import type { OxalisState } from "oxalis/store";
@@ -26,6 +26,7 @@ import {
2626
is2dDataset,
2727
doesSupportVolumeWithFallback,
2828
getVisibleSegmentationLayer,
29+
getMappingInfoForSupportedLayer,
2930
} from "oxalis/model/accessors/dataset_accessor";
3031
import { AsyncButton } from "components/async_clickables";
3132

@@ -96,7 +97,22 @@ class ActionBarView extends React.PureComponent<Props, State> {
9697
maybeSegmentationLayer && doesSupportVolumeWithFallback(dataset, maybeSegmentationLayer)
9798
? maybeSegmentationLayer.name
9899
: null;
99-
const annotation = await createExplorational(dataset, "hybrid", fallbackLayerName);
100+
101+
const mappingInfo = getMappingInfoForSupportedLayer(Store.getState());
102+
let maybeMappingName = null;
103+
if (
104+
mappingInfo.mappingStatus !== MappingStatusEnum.DISABLED &&
105+
mappingInfo.mappingType === "HDF5"
106+
) {
107+
maybeMappingName = mappingInfo.mappingName;
108+
}
109+
110+
const annotation = await createExplorational(
111+
dataset,
112+
"hybrid",
113+
fallbackLayerName,
114+
maybeMappingName,
115+
);
100116
trackAction("Create hybrid tracing (from view mode)");
101117
location.href = `${location.origin}/annotations/${annotation.typ}/${annotation.id}${location.hash}`;
102118
};

frontend/javascripts/oxalis/view/left-border-tabs/modals/add_volume_layer_modal.tsx

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@ import {
88
NewVolumeLayerSelection,
99
RestrictResolutionSlider,
1010
} from "dashboard/advanced_dataset/create_explorative_modal";
11-
import type { Tracing } from "oxalis/store";
11+
import Store, { type Tracing } from "oxalis/store";
1212
import { addAnnotationLayer } from "admin/admin_rest_api";
1313
import {
1414
getDatasetResolutionInfo,
1515
getLayerByName,
16+
getMappingInfo,
1617
getSegmentationLayers,
1718
} from "oxalis/model/accessors/dataset_accessor";
1819
import {
@@ -23,6 +24,7 @@ import messages from "messages";
2324
import InputComponent from "oxalis/view/components/input_component";
2425
import api from "oxalis/api/internal_api";
2526
import Toast from "libs/toast";
27+
import { MappingStatusEnum } from "oxalis/constants";
2628

2729
export type ValidationResult = { isValid: boolean; message: string };
2830
export function checkForLayerNameDuplication(
@@ -162,6 +164,19 @@ export default function AddVolumeLayerModal({
162164
} else {
163165
selectedSegmentationLayer = getLayerByName(dataset, selectedSegmentationLayerName);
164166
const fallbackLayerName = selectedSegmentationLayer.name;
167+
168+
const mappingInfo = getMappingInfo(
169+
Store.getState().temporaryConfiguration.activeMappingByLayer,
170+
selectedSegmentationLayerName,
171+
);
172+
let maybeMappingName = null;
173+
if (
174+
mappingInfo.mappingStatus !== MappingStatusEnum.DISABLED &&
175+
mappingInfo.mappingType === "HDF5"
176+
) {
177+
maybeMappingName = mappingInfo.mappingName;
178+
}
179+
165180
await addAnnotationLayer(tracing.annotationId, tracing.annotationType, {
166181
typ: "Volume",
167182
name: newLayerName,
@@ -170,6 +185,7 @@ export default function AddVolumeLayerModal({
170185
min: minResolutionAllowed,
171186
max: maxResolutionAllowed,
172187
},
188+
mappingName: maybeMappingName,
173189
});
174190
}
175191

frontend/javascripts/router.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,7 @@ class ReactRouter extends React.Component<Props> {
584584
dataset,
585585
type,
586586
fallbackLayerName,
587+
null,
587588
resolutionRestrictions,
588589
);
589590
trackAction(`Create ${type} tracing`);

frontend/javascripts/test/puppeteer/dataset_rendering_helpers.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ async function _screenshotAnnotationHelper(
8484
typ,
8585
fallbackLayerName,
8686
null,
87+
null,
8788
options,
8889
);
8990

@@ -107,6 +108,7 @@ export async function screenshotDatasetWithMapping(
107108
"skeleton",
108109
null,
109110
null,
111+
null,
110112
options,
111113
);
112114
await openTracingView(page, baseUrl, createdExplorational.id);
@@ -128,6 +130,7 @@ export async function screenshotDatasetWithMappingLink(
128130
"skeleton",
129131
null,
130132
null,
133+
null,
131134
options,
132135
);
133136
await openTracingView(page, baseUrl, createdExplorational.id, optionalViewOverride);

0 commit comments

Comments
 (0)