Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
f7c5de3
allow to toggle visibility of each segment via custom segment colors
philippotto Apr 16, 2025
8b0dda2
Merge remote-tracking branch 'origin/master' into segment-checkboxes
philippotto Apr 17, 2025
0907106
allow to toggle segments and groups
philippotto Apr 22, 2025
a3f42df
linting
philippotto Apr 22, 2025
17d7e75
backend: add UpdateSegmentVisibilityVolumeAction, UpdateSegmentGroupV…
fm3 Apr 22, 2025
41dff63
Merge branch 'master' of github.com:scalableminds/webknossos into seg…
philippotto Apr 23, 2025
5b788a9
integrate updateSegmentVisibility update action
philippotto Apr 23, 2025
7fd0fe3
implement toggle compaction and integrate updateSegmentGroupVisibilit…
philippotto Apr 24, 2025
cfed403
warn user when too many custom segment colors exist; don't show check…
philippotto Apr 24, 2025
c5c7057
move titleRender to own method
philippotto Apr 24, 2025
38e94e1
implement hideUnregisteredSegments and only-show-this-segment etc in …
philippotto Apr 24, 2025
ff5eeba
fix saving of hideUnregisteredSegments
philippotto Apr 24, 2025
887d983
fix typing
philippotto Apr 24, 2025
f96979a
Merge branch 'master' of github.com:scalableminds/webknossos into seg…
philippotto Apr 29, 2025
1ab070b
remove unlisted segments group prototype again
philippotto Apr 29, 2025
8947bd8
expose hide unlisted segments in left sidebar and add show-all-segmen…
philippotto Apr 29, 2025
ef8db6d
remove -2 handling for unlisted group stuff
philippotto Apr 29, 2025
41ae2f8
fix visibility when removing segment from list; refactor toggling
philippotto Apr 29, 2025
2c814ac
hide checkboxes when proofreading and selectiveVisibilityInProofreadi…
philippotto Apr 29, 2025
bcf42d2
write and parse tree and segment isVisible in NMLs
fm3 Apr 29, 2025
aa22e0a
fix support for view only
philippotto Apr 29, 2025
f17e101
add missing volumetracing_action_helpers.ts module
philippotto Apr 29, 2025
f0f7c40
fix warning because of non-string value in radio button component for…
philippotto Apr 29, 2025
91f1ec5
use fast tooltip to avoid findDOMNode warning
philippotto Apr 29, 2025
8d3b12f
fmt backend
philippotto Apr 29, 2025
221489c
fix warning when opening context menu by restructuring hooks
philippotto Apr 30, 2025
963f55e
refactor context info in context menu
philippotto Apr 30, 2025
e6f75e2
lint
philippotto Apr 30, 2025
e600a26
add some position when a segment is registered by toggling its visibi…
philippotto Apr 30, 2025
f70d32e
update screenshots (the selective rendering is done via hovering where
philippotto May 2, 2025
ff63e2c
Merge branch 'master' of github.com:scalableminds/webknossos into seg…
philippotto May 2, 2025
28ee637
implement benchmark for segment list scrolling; improve perf a little…
philippotto May 2, 2025
47006a6
Merge branch 'master' of github.com:scalableminds/webknossos into seg…
philippotto May 7, 2025
a0ed2c5
clean up unnecessary isChecked property
philippotto May 7, 2025
59be1b2
use extracted vars
philippotto May 8, 2025
64a7cc8
add comments
philippotto May 8, 2025
ca9d106
linting
philippotto May 8, 2025
ed407f8
integrate some code rabbit feedback
philippotto May 8, 2025
2f9ee91
Merge branch 'master' of github.com:scalableminds/webknossos into seg…
philippotto May 9, 2025
3387f1e
format
philippotto May 9, 2025
d989686
Merge branch 'master' of github.com:scalableminds/webknossos into seg…
hotzenklotz May 13, 2025
bb5d7c6
add missing type to merge
hotzenklotz May 13, 2025
1704be9
delete commented code
philippotto May 14, 2025
ea1ca80
merge defaultDatasetViewConfiguration with defaultDatasetViewConfigur…
philippotto May 15, 2025
5021bef
incorporate feedback
philippotto May 15, 2025
8d16784
update changelog
philippotto May 19, 2025
e5aa4b1
unify proto property setting using withIsVisible
fm3 May 20, 2025
2c8c849
Merge branch 'master' into segment-checkboxes
philippotto May 20, 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
2 changes: 2 additions & 0 deletions CHANGELOG.unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.released
- Added that "Create Animation" jobs will now use the correct segment colors for rendering meshes. [#8605](https://github.com/scalableminds/webknossos/pull/8605)
- In the NML upload route, the additional form field `description` can be specified. If so, it will overwrite the description contained in the NML files. [#8631](https://github.com/scalableminds/webknossos/pull/8631)
- Added the possibility for super users to retry manually cancelled jobs from the jobs list. [#8629](https://github.com/scalableminds/webknossos/pull/8629)
- Added checkboxes to the segments tab that allow to show/hide individual segments. The visibility of segments that are not listed in the segments list can be controlled with a new "Hide unlisted segments" toggle in the layer settings. Additionally, you can right-click a segment in a data viewport and select "Only show this segment" (and similar functionality). [#8546](https://github.com/scalableminds/webknossos/pull/8546)

### Changed
- Remove `data.maybe` dependency and replaced with regular Typescript types. [#8563](https://github.com/scalableminds/webknossos/pull/8563)
Expand All @@ -42,5 +43,6 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.released
- Fixed that deletion of dataset would lead to an error. [#8639](https://github.com/scalableminds/webknossos/pull/8639)

### Removed
- The old "Selective Segment Visibility" feature that allowed to only see the active and the hovered segment was removed. From now on the visibility of segments can be controlled with checkboxes in the segment list and with the "Hide unlisted segments" toggle in the layer settings. [#8546](https://github.com/scalableminds/webknossos/pull/8546)

### Breaking Changes
5 changes: 4 additions & 1 deletion app/models/annotation/nml/NmlParser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,8 @@ class NmlParser @Inject()(datasetDAO: DatasetDAO)
}
val anchorPositionAdditionalCoordinates = parseAdditionalCoordinateValues(node)
val metadata = parseMetadata(node \ "metadata" \ "metadataEntry")
val color = parseColorOpt(node)
val isVisible = parseVisibility(node, color)
Segment(
segmentId = getSingleAttribute(node, "id").toLong,
anchorPosition = anchorPosition,
Expand All @@ -260,7 +262,8 @@ class NmlParser @Inject()(datasetDAO: DatasetDAO)
color = parseColorOpt(node),
groupId = getSingleAttribute(node, "groupId").toIntOpt,
anchorPositionAdditionalCoordinates = anchorPositionAdditionalCoordinates,
metadata = metadata
metadata = metadata,
isVisible = isVisible
)
})

Expand Down
2 changes: 2 additions & 0 deletions app/models/annotation/nml/NmlWriter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ class NmlWriter @Inject()(implicit ec: ExecutionContext) extends FoxImplicits wi
s.name.foreach { n =>
writer.writeAttribute("name", n)
}
s.isVisible.foreach(isVisible => writer.writeAttribute("isVisible", isVisible.toString))
s.creationTime.foreach { t =>
writer.writeAttribute("created", t.toString)
}
Expand Down Expand Up @@ -341,6 +342,7 @@ class NmlWriter @Inject()(implicit ec: ExecutionContext) extends FoxImplicits wi
writer.writeAttribute("id", t.treeId.toString)
writeColor(t.color)
writer.writeAttribute("name", t.name)
t.isVisible.foreach(isVisible => writer.writeAttribute("isVisible", isVisible.toString))
t.groupId.foreach(groupId => writer.writeAttribute("groupId", groupId.toString))
t.`type`.foreach(t => writer.writeAttribute("type", t.toString))
Xml.withinElementSync("nodes")(writeNodesAsXml(t.nodes.sortBy(_.id)))
Expand Down
5 changes: 3 additions & 2 deletions frontend/javascripts/dashboard/dataset_view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
Tooltip,
} from "antd";
import type { ItemType } from "antd/es/menu/interface";
import FastTooltip from "components/fast_tooltip";
import FormattedDate from "components/formatted_date";
import { PricingEnforcedButton } from "components/pricing_enforcers";
import DatasetTable from "dashboard/advanced_dataset/dataset_table";
Expand Down Expand Up @@ -302,7 +303,7 @@ export function DatasetRefreshButton({ context }: { context: DatasetCollectionCo
const showLoadingIndicator = context.isLoading || context.isChecking;

return (
<Tooltip
<FastTooltip
title={showLoadingIndicator ? "Refreshing the dataset list." : "Refresh the dataset list."}
>
<Dropdown.Button
Expand All @@ -313,7 +314,7 @@ export function DatasetRefreshButton({ context }: { context: DatasetCollectionCo
>
{showLoadingIndicator ? <LoadingOutlined /> : <ReloadOutlined />} Refresh
</Dropdown.Button>
</Tooltip>
</FastTooltip>
);
}

Expand Down
11 changes: 11 additions & 0 deletions frontend/javascripts/libs/cuckoo/abstract_cuckoo_table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ let cachedNullTexture: UpdatableTexture | undefined;

export abstract class AbstractCuckooTable<K, V, Entry extends [K, V]> {
entryCapacity: number;
entryCount: number = 0;
protected table!: Uint32Array;
protected seeds!: number[];
protected seedSubscribers: Array<SeedSubscriberFn> = [];
Expand Down Expand Up @@ -61,6 +62,10 @@ export abstract class AbstractCuckooTable<K, V, Entry extends [K, V]> {
this.getClass().getElementsPerEntry(),
);

this.clear();
}

clear() {
this.initializeTableArray();
// Initialize the texture once to avoid undefined behavior
this.flushTableToTexture();
Expand Down Expand Up @@ -100,6 +105,7 @@ export abstract class AbstractCuckooTable<K, V, Entry extends [K, V]> {
}

private initializeTableArray() {
this.entryCount = 0;
this.table = new Uint32Array(this.getClass().getElementsPerEntry() * this.entryCapacity).fill(
EMPTY_KEY_VALUE,
);
Expand Down Expand Up @@ -204,6 +210,10 @@ export abstract class AbstractCuckooTable<K, V, Entry extends [K, V]> {
return null;
}

// The key does not exist yet, therefore already increment the entry count (if the
// internalSet does not succeed, a rehash will happen that resets entryCount to 0).
this.entryCount++;

let seedIndex = Math.floor(Math.random() * this.seeds.length);
while (iterationCounter++ < this.entryCapacity) {
const seed = this.seeds[seedIndex];
Expand Down Expand Up @@ -243,6 +253,7 @@ export abstract class AbstractCuckooTable<K, V, Entry extends [K, V]> {
hashedAddress,
!this.autoTextureUpdate,
);
this.entryCount--;
return;
}
}
Expand Down
2 changes: 0 additions & 2 deletions frontend/javascripts/messages.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ export const settings: Partial<Record<keyof RecommendedConfiguration, string>> =
renderWatermark: "Logo in Screenshots",
antialiasRendering: "Antialiasing",
colorLayerOrder: "Color Layer Order",
selectiveSegmentVisibility: "Selective Visibility",
};
export const settingsTooltips: Partial<Record<keyof RecommendedConfiguration, string>> = {
loadingStrategy: `You can choose between loading the best quality first
Expand Down Expand Up @@ -82,7 +81,6 @@ export const settingsTooltips: Partial<Record<keyof RecommendedConfiguration, st
antialiasRendering: "Antialias rendering (can impact performance)",
colorLayerOrder:
"Set the order in which color layers are rendered. This setting is only relevant if the cover blend mode is active.",
selectiveSegmentVisibility: "When enabled, only the active and hovered segments are visible.",
};
export const layerViewConfigurations: Partial<Record<keyof DatasetLayerConfiguration, string>> = {
color: "Color",
Expand Down
6 changes: 6 additions & 0 deletions frontend/javascripts/test/helpers/saveHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,9 @@ export function withoutUpdateTree(
): UpdateActionWithoutIsolationRequirement[] {
return items.filter((item) => item.name !== "updateTree");
}

export function withoutUpdateSegment(
items: UpdateActionWithoutIsolationRequirement[],
): UpdateActionWithoutIsolationRequirement[] {
return items.filter((item) => item.name !== "updateSegment");
}
8 changes: 8 additions & 0 deletions frontend/javascripts/test/model/cuckoo_table.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,11 @@ describe("CuckooTableVec3", () => {
ct.set(entry[0], entry[1]);
const readValue = ct.get(entry[0]);
isValueEqual(entry[1], readValue);
expect(ct.entryCount).toBe(1);
}
}
ct.unset(1);
expect(ct.entryCount).toBe(0);
});

it("Should throw error when exceeding capacity", () => {
Expand All @@ -112,8 +115,13 @@ describe("CuckooTableVec3", () => {

ct = new CuckooTableVec3(textureWidth);
entries = generateRandomCuckooEntrySet(generateRandomEntry, ct.getCriticalCapacity());
let count = 0;
for (const entry of entries) {
ct.set(entry[0], entry[1]);
ct.unset(entry[0]);
ct.set(entry[0], entry[1]);
count++;
expect(ct.entryCount).toBe(count);
}

// Check that all previously set items are still intact
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ import {
getSupportedValueRangeForElementClass,
} from "viewer/model/bucket_data_handling/data_rendering_logic";
import {
updateDatasetSettingAction,
updateLayerSettingAction,
updateTemporarySettingAction,
} from "viewer/model/actions/settings_actions";
import { setPositionAction, setZoomStepAction } from "viewer/model/actions/flycam_actions";
import type { Action } from "viewer/model/actions/actions";
import { describe, it, beforeAll, beforeEach, afterEach, expect, test } from "vitest";
import { setHideUnregisteredSegmentsAction } from "viewer/model/actions/volumetracing_actions";

const testColor = true;
const testSegmentation = true;
Expand Down Expand Up @@ -225,7 +225,7 @@ describe("DType Dataset Rendering", () => {
.map((el) => Number.parseFloat(el));

const actions: Action[] = [
updateDatasetSettingAction("selectiveSegmentVisibility", false),
setHideUnregisteredSegmentsAction(false),
updateTemporarySettingAction("hoveredSegmentId", null),
setPositionAction([x, y, z]),
setZoomStepAction(zoomValue),
Expand Down Expand Up @@ -274,7 +274,7 @@ describe("DType Dataset Rendering", () => {
let success = true;
if (spec.alsoTestSelectiveSegmentId && selectiveSegmentIdByDtype[spec.dtype] != null) {
const actions = [
updateDatasetSettingAction("selectiveSegmentVisibility", true),
setHideUnregisteredSegmentsAction(true),
updateTemporarySettingAction(
"hoveredSegmentId",
selectiveSegmentIdByDtype[spec.dtype] ?? null,
Expand Down
Loading
Loading