Skip to content

Commit a1c816d

Browse files
authored
Merge branch 'master' into suport-ngff-translate
2 parents eb7af06 + 5a556be commit a1c816d

File tree

58 files changed

+1136
-711
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+1136
-711
lines changed

CHANGELOG.unreleased.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.released
1313
### Added
1414
- Added the total volume of a dataset to a tooltip in the dataset info tab. [#8229](https://github.com/scalableminds/webknossos/pull/8229)
1515
- Optimized performance of data loading with “fill value“ chunks. [#8271](https://github.com/scalableminds/webknossos/pull/8271)
16+
- The fill tool can now be adapted so that it only acts within a specified bounding box. Use the new "Restrict Floodfill" mode for that in the toolbar. [#8267](https://github.com/scalableminds/webknossos/pull/8267)
17+
- Added the option for "Selective Segment Visibility" for segmentation layers. Select this option in the left sidebar to only show segments that are currently active or hovered. [#8281](https://github.com/scalableminds/webknossos/pull/8281)
18+
- A segment can be activated with doubleclick now. [#8281](https://github.com/scalableminds/webknossos/pull/8281)
19+
- It is now possible to select the magnification of the layers on which an AI model will be trained. [#8266](https://github.com/scalableminds/webknossos/pull/8266)
1620
- Added support for translations in OME NGFF zarr datasets (translation within coordinateTransformations on datasets). [#8311](https://github.com/scalableminds/webknossos/pull/8311)
1721

1822
### Changed
@@ -22,6 +26,7 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.released
2226
- Improved the default colors for skeleton trees. [#8228](https://github.com/scalableminds/webknossos/pull/8228)
2327
- Allowed to train an AI model using differently sized bounding boxes. We recommend all bounding boxes to have equal dimensions or to have dimensions which are multiples of the smallest bounding box. [#8222](https://github.com/scalableminds/webknossos/pull/8222)
2428
- Within the bounding box tool, the cursor updates immediately after pressing `ctrl`, indicating that a bounding box can be moved instead of resized. [#8253](https://github.com/scalableminds/webknossos/pull/8253)
29+
- Improved the styling of active tools and modes in the toolbar. [#8295](https://github.com/scalableminds/webknossos/pull/8295)
2530

2631
### Fixed
2732
- Fixed that listing datasets with the `api/datasets` route without compression failed due to missing permissions regarding public datasets. [#8249](https://github.com/scalableminds/webknossos/pull/8249)
@@ -37,8 +42,12 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.released
3742
- Fixed some layout issues in the upload view. [#8231](https://github.com/scalableminds/webknossos/pull/8231)
3843
- Fixed `FATAL: role "postgres" does not exist` error message in Docker compose. [#8240](https://github.com/scalableminds/webknossos/pull/8240)
3944
- Fixed the Zarr 3 implementation not accepting BytesCodec without "configuration" key. [#8282](https://github.com/scalableminds/webknossos/pull/8282)
45+
- Fixed that reloading the data of a volume annotation layer did not work properly. [#8298](https://github.com/scalableminds/webknossos/pull/8298)
46+
- Removed the magnification slider for the TIFF export within the download modal if only one magnification is available for the selected layer. [#8297](https://github.com/scalableminds/webknossos/pull/8297)
47+
- Fixed regression in styling of segment and skeleton tree tab. [#8307](https://github.com/scalableminds/webknossos/pull/8307)
4048

4149
### Removed
4250
- Removed support for HTTP API versions 3 and 4. [#8075](https://github.com/scalableminds/webknossos/pull/8075)
51+
- Removed that a warning is shown when a dataset is served from a datastore that was marked with isScratch=true. [#8296](https://github.com/scalableminds/webknossos/pull/8296)
4352

4453
### Breaking Changes

app/models/dataset/DataStore.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ class DataStoreService @Inject()(dataStoreDAO: DataStoreDAO, jobService: JobServ
7171
Json.obj(
7272
"name" -> dataStore.name,
7373
"url" -> dataStore.publicUrl,
74-
"isScratch" -> dataStore.isScratch,
7574
"allowsUpload" -> dataStore.allowsUpload,
7675
"jobsSupportedByAvailableWorkers" -> Json.toJson(jobsSupportedByAvailableWorkers),
7776
"jobsEnabled" -> jobsEnabled

docs/ui/layers.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ In addition to the general layer properties mentioned above, `color` and `segmen
3131

3232
- `Color`: Every `color` layer can be re-colored to make it easily identifiable. By default, all layers have a white overlay, showing the true, raw black & white data. Clicking on the square color indicator brings up your system's color palette to choose from. Note, there is an icon button for inverting all color values in this layer.
3333
- `Pattern Opacity`: Adjust the visibility of the texture/pattern on each segment. To make segments easier to distinguish and more unique, a pattern is applied to each in addition to its base color. 0% hides the pattern. 100% makes the pattern very prominent. Great for increasing the visual contrast between segments.
34+
- `Selective Visibility`: When activated, only segments are shown that are currently active or hovered.
3435
- `ID Mapping`: WEBKNOSSOS supports applying pre-computed agglomerations/groupings of segmentation IDs for a given segmentation layer. This is a very powerful feature to explore and compare different segmentation strategies for a given segmentation layer. Mappings need to be pre-computed and stored together with a dataset for WEBKNOSSOS to download and apply. [Read more about this here](../proofreading/segmentation_mappings.md).
3536

3637

22.2 KB
Loading

docs/volume_annotation/tools.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ The following interactions and modes become available when working with some of
6868
![3D Fill Modifier](./images/3d-modifier.jpg){align=left width="60"}
6969
**2D/3D Fill**: Modifies the flood filling tool to work in 2D (in-plane only) or 3D (volumetric fill/re-labeling). 3D flood fill is constrained to a small, regional bounding box for performance reasons. Read more about [flood fills](#volume-flood-fills) below.
7070

71+
![Restrict Fill](./images/icon_restricted_floodfill.jpg){align=left width="60"}
72+
**Restrict Fill by Bounding Box**: When enabled, the fill operation will be restricted by the smallest bounding box that encloses the clicked position. This feature can be useful when correcting segmentation in a small bounding box (e.g., when curating training data).
7173

7274
## Quick-select tool
7375
The Quick Select tool offers AI-powered automatic segmentation, powered by [Segment Anything Model 2](https://ai.meta.com/blog/segment-anything-2/). Simply draw a selection around your target structure, and WEBKNOSSOS will automatically segment it for you.

frontend/javascripts/admin/voxelytics/ai_model_list_view.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ function TrainNewAiJobModal({ onClose }: { onClose: () => void }) {
109109
AnnotationInfoForAIJob<APIAnnotation>[]
110110
>([]);
111111

112-
const getMagForSegmentationLayer = async (annotationId: string, layerName: string) => {
112+
const getMagsForSegmentationLayer = (annotationId: string, layerName: string) => {
113113
// The layer name is a human-readable one. It can either belong to an annotationLayer
114114
// (therefore, also to a volume tracing) or to the actual dataset.
115115
// Both are checked below. This won't be ambiguous because annotationLayers must not
@@ -130,10 +130,10 @@ function TrainNewAiJobModal({ onClose }: { onClose: () => void }) {
130130
(tracing) => tracing.tracingId === annotationLayer.tracingId,
131131
);
132132
const mags = volumeTracingMags[volumeTracingIndex] || ([[1, 1, 1]] as Vector3[]);
133-
return getMagInfo(mags).getFinestMag();
133+
return getMagInfo(mags);
134134
} else {
135135
const segmentationLayer = getSegmentationLayerByName(dataset, layerName);
136-
return getMagInfo(segmentationLayer.resolutions).getFinestMag();
136+
return getMagInfo(segmentationLayer.resolutions);
137137
}
138138
};
139139

@@ -152,7 +152,7 @@ function TrainNewAiJobModal({ onClose }: { onClose: () => void }) {
152152
maskClosable={false}
153153
>
154154
<TrainAiModelTab
155-
getMagForSegmentationLayer={getMagForSegmentationLayer}
155+
getMagsForSegmentationLayer={getMagsForSegmentationLayer}
156156
onClose={onClose}
157157
annotationInfos={annotationInfosForAiJob}
158158
onAddAnnotationsInfos={(newItems) => {

frontend/javascripts/components/async_clickables.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Button, type ButtonProps } from "antd";
1+
import { Button, ConfigProvider, type ButtonProps } from "antd";
22
import { LoadingOutlined } from "@ant-design/icons";
33
import * as React from "react";
44
import FastTooltip from "./fast_tooltip";
@@ -47,9 +47,12 @@ export function AsyncButton(props: AsyncButtonProps) {
4747
const effectiveChildren = hideContentWhenLoading && isLoading ? null : children;
4848
return (
4949
<FastTooltip title={title}>
50-
<Button {...rest} loading={isLoading} onClick={onClick}>
51-
{effectiveChildren}
52-
</Button>
50+
{/* Avoid weird animation when icons swap */}
51+
<ConfigProvider theme={{ token: { motion: false } }}>
52+
<Button {...rest} loading={isLoading} onClick={onClick}>
53+
{effectiveChildren}
54+
</Button>
55+
</ConfigProvider>
5356
</FastTooltip>
5457
);
5558
}

frontend/javascripts/components/fast_tooltip.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import { Tooltip as ReactTooltip } from "react-tooltip";
3232
const ROOT_TOOLTIP_IDS = {
3333
DEFAULT: "main-tooltip",
3434
DYNAMIC: "main-tooltip-dynamic",
35-
};
35+
} as const;
3636

3737
export type FastTooltipPlacement =
3838
| "top"

frontend/javascripts/components/layer_selection.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ type LayerSelectionProps<L extends { name: string }> = {
88
getReadableNameForLayer: (layer: L) => string;
99
fixedLayerName?: string;
1010
label?: string;
11+
onChange?: (a: string) => void;
1112
};
1213

1314
export function LayerSelection<L extends { name: string }>({
@@ -65,6 +66,7 @@ export function LayerSelectionFormItem<L extends { name: string }>({
6566
getReadableNameForLayer,
6667
fixedLayerName,
6768
label,
69+
onChange,
6870
}: LayerSelectionProps<L>): JSX.Element {
6971
const layerType = chooseSegmentationLayer ? "segmentation" : "color";
7072
return (
@@ -85,6 +87,7 @@ export function LayerSelectionFormItem<L extends { name: string }>({
8587
fixedLayerName={fixedLayerName}
8688
layerType={layerType}
8789
getReadableNameForLayer={getReadableNameForLayer}
90+
onChange={onChange}
8891
/>
8992
</Form.Item>
9093
);
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { Form, Select } from "antd";
2+
import { V3 } from "libs/mjs";
3+
import { clamp } from "libs/utils";
4+
import type { Vector3 } from "oxalis/constants";
5+
import type { MagInfo } from "oxalis/model/helpers/mag_info";
6+
7+
export function MagSelectionFormItem({
8+
name,
9+
magInfo,
10+
}: {
11+
name: string | Array<string | number>;
12+
magInfo: MagInfo | undefined;
13+
}): JSX.Element {
14+
return (
15+
<Form.Item
16+
name={name}
17+
label={"Magnification"}
18+
rules={[
19+
{
20+
required: true,
21+
message: "Please select the magnification.",
22+
},
23+
]}
24+
>
25+
<MagSelection magInfo={magInfo} />
26+
</Form.Item>
27+
);
28+
}
29+
30+
function MagSelection({
31+
magInfo,
32+
value,
33+
onChange,
34+
}: {
35+
magInfo: MagInfo | undefined;
36+
value?: Vector3;
37+
onChange?: (newValue: Vector3) => void;
38+
}): JSX.Element {
39+
const allMags = magInfo != null ? magInfo.getMagList() : [];
40+
41+
const onSelect = (index: number | undefined) => {
42+
if (onChange == null || index == null) return;
43+
const newMag = allMags[index];
44+
if (newMag != null) onChange(newMag);
45+
};
46+
47+
return (
48+
<Select
49+
placeholder="Select a magnification"
50+
value={
51+
// Using the index of the mag *in the mag list* as value internally,
52+
// this is different from the mag index.
53+
value == null || magInfo == null
54+
? null
55+
: clamp(
56+
0,
57+
allMags.findIndex((v) => V3.equals(v, value)),
58+
allMags.length - 1,
59+
)
60+
}
61+
onSelect={onSelect}
62+
>
63+
{allMags.map((mag, index) => {
64+
const readableName = mag.join("-");
65+
return (
66+
<Select.Option key={index} value={index}>
67+
{readableName}
68+
</Select.Option>
69+
);
70+
})}
71+
</Select>
72+
);
73+
}

0 commit comments

Comments
 (0)