Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Segment group batch actions #7164

Merged
merged 51 commits into from
Jul 20, 2023
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
4e86f6d
start: change group color
dieknolle3333 Jun 20, 2023
b97c9d8
change group color
dieknolle3333 Jun 20, 2023
ea18ffd
[very broken] first implementation to hide/load all meshes of a segme…
dieknolle3333 Jun 20, 2023
98e458f
show/hide all msehes for group
dieknolle3333 Jun 23, 2023
071d0e1
add batch actions: download, show/hide, load meshes for segment group
dieknolle3333 Jun 25, 2023
d2d8861
fix code duplication and lint
dieknolle3333 Jun 26, 2023
e6ed640
add warning if position of segments in unknown
dieknolle3333 Jun 26, 2023
5472e53
push WIP before I leave
dieknolle3333 Jun 27, 2023
0a4c7d2
zip multiple meshes
dieknolle3333 Jun 27, 2023
31c3f87
undo zip.js upgrade
dieknolle3333 Jun 27, 2023
e829f1e
batch actions to set colour and remove and refresh meshes option
dieknolle3333 Jun 27, 2023
0f0f402
Merge branch 'master' into segment-group-batch-actions
dieknolle3333 Jun 27, 2023
c879a10
lint
dieknolle3333 Jun 27, 2023
e0440d3
remove TODOs
dieknolle3333 Jun 27, 2023
8cab227
add chagelog entry
dieknolle3333 Jun 27, 2023
ea8b1c9
refactor code
dieknolle3333 Jun 30, 2023
5944d85
WIP: start refactoring
dieknolle3333 Jun 30, 2023
8781956
WIP: add helper method
dieknolle3333 Jul 2, 2023
e809bca
WIP: address review
dieknolle3333 Jul 3, 2023
ca20df1
WIP: add lost method call
dieknolle3333 Jul 3, 2023
a4b89e2
WIP: trying to improve areSegmentsInGroupVisible
dieknolle3333 Jul 3, 2023
b5a2e99
WIP: fix getDerivedStateFromProps
dieknolle3333 Jul 4, 2023
9db1f1e
veryWIP: trying to fix tests by mocking zipjs
dieknolle3333 Jul 4, 2023
6c7bedd
WIP: trying to fix tests
dieknolle3333 Jul 7, 2023
cc866f5
WIP: fix small typo
dieknolle3333 Jul 7, 2023
c8ca503
fix merge conflicts
dieknolle3333 Jul 7, 2023
180bddb
WIP: trying to fix tests again
dieknolle3333 Jul 10, 2023
b9a11ed
WIP: trying to fix tests again
dieknolle3333 Jul 10, 2023
4939928
WIP: trying to fix tests (I really hope its the last time)
dieknolle3333 Jul 10, 2023
5f872b1
fix comment
dieknolle3333 Jul 10, 2023
ecdf655
change order of menu items
dieknolle3333 Jul 10, 2023
fc65635
Merge branch 'master' into segment-group-batch-actions
dieknolle3333 Jul 10, 2023
f3156ea
WIP: address PR review
dieknolle3333 Jul 11, 2023
1198f1d
WIP: address refactoring
dieknolle3333 Jul 12, 2023
9c1c06f
WIP: change icons
dieknolle3333 Jul 14, 2023
cdf453a
address review and lint
dieknolle3333 Jul 14, 2023
2803c61
merge master
dieknolle3333 Jul 14, 2023
76a09af
fix capitalization
dieknolle3333 Jul 14, 2023
720e052
fix spacing
dieknolle3333 Jul 14, 2023
bb1e286
fx method name
dieknolle3333 Jul 14, 2023
3baa2aa
fix icon spacing
dieknolle3333 Jul 17, 2023
caa361a
Merge branch 'master' into segment-group-batch-actions
dieknolle3333 Jul 17, 2023
a78963f
improve typing
philippotto Jul 17, 2023
bebb08f
Merge branch 'segment-group-batch-actions' of github.com:scalablemind…
philippotto Jul 17, 2023
a4dd2cd
WIP: fix spacing of font awesome icons and fix linting
dieknolle3333 Jul 17, 2023
e3892db
Merge branch 'segment-group-batch-actions' of github.com:scalablemind…
dieknolle3333 Jul 17, 2023
4d35fca
address review
dieknolle3333 Jul 17, 2023
eef4546
remove TODO comment and improve naming
dieknolle3333 Jul 18, 2023
414455e
Merge branch 'master' into segment-group-batch-actions
dieknolle3333 Jul 18, 2023
41034cc
merge master
dieknolle3333 Jul 18, 2023
eddc45e
merge master
dieknolle3333 Jul 20, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 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 warning when using WEBKNOSSOS in an outdated browser. [#7165](https://github.com/scalableminds/webknossos/pull/7165)
- Added support for transformations with thin plate splines. [#7131](https://github.com/scalableminds/webknossos/pull/7131)
- WEBKNOSSOS can now read S3 remote dataset credentials from environment variables `AWS_ACCESS_KEY_ID` and `AWS_SECRET_KEY`. Those will be used, if available, when accessing remote datasets for which no explicit credentials are supplied. [#7170](https://github.com/scalableminds/webknossos/pull/7170)
- Added batch actions for segment groups, such as changing the color and loading or downloading all corresponding meshes. [#7164](https://github.com/scalableminds/webknossos/pull/7164).

### Changed
- Redesigned the info tab in the right-hand sidebar to be fit the new branding and design language. [#7110](https://github.com/scalableminds/webknossos/pull/7110)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type DeleteUserBoundingBox = ReturnType<typeof deleteUserBoundingBoxAction>;
export type UpdateIsosurfaceVisibilityAction = ReturnType<typeof updateIsosurfaceVisibilityAction>;
export type MaybeFetchMeshFilesAction = ReturnType<typeof maybeFetchMeshFilesAction>;
export type TriggerIsosurfaceDownloadAction = ReturnType<typeof triggerIsosurfaceDownloadAction>;
export type TriggerIsosurfacesDownloadAction = ReturnType<typeof triggerIsosurfacesDownloadAction>;
export type RefreshIsosurfacesAction = ReturnType<typeof refreshIsosurfacesAction>;
export type RefreshIsosurfaceAction = ReturnType<typeof refreshIsosurfaceAction>;
export type StartedLoadingIsosurfaceAction = ReturnType<typeof startedLoadingIsosurfaceAction>;
Expand Down Expand Up @@ -223,6 +224,14 @@ export const triggerIsosurfaceDownloadAction = (
layerName,
} as const);

export const triggerIsosurfacesDownloadAction = (
surfaceArray: { cellName: string; segmentId: number; layerName: string }[],
dieknolle3333 marked this conversation as resolved.
Show resolved Hide resolved
) =>
({
type: "TRIGGER_ISOSURFACES_DOWNLOAD",
surfaceArray,
} as const);

export const refreshIsosurfacesAction = () =>
({
type: "REFRESH_ISOSURFACES",
Expand Down
48 changes: 47 additions & 1 deletion frontend/javascripts/oxalis/model/sagas/isosurface_saga.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,11 @@ import {
addPrecomputedIsosurfaceAction,
finishedLoadingIsosurfaceAction,
startedLoadingIsosurfaceAction,
TriggerIsosurfacesDownloadAction,
} from "oxalis/model/actions/annotation_actions";
import type { Saga } from "oxalis/model/sagas/effect-generators";
import { select } from "oxalis/model/sagas/effect-generators";
import { actionChannel, takeEvery, call, take, race, put } from "typed-redux-saga";
import { actionChannel, takeEvery, call, take, race, put, all } from "typed-redux-saga";
import { stlIsosurfaceConstants } from "oxalis/view/right-border-tabs/segments_tab/segments_view";
import {
computeIsosurface,
Expand Down Expand Up @@ -73,6 +74,7 @@ import processTaskWithPool from "libs/task_pool";
import { getBaseSegmentationName } from "oxalis/view/right-border-tabs/segments_tab/segments_view_helper";
import { RemoveSegmentAction, UpdateSegmentAction } from "../actions/volumetracing_actions";
import { ResolutionInfo } from "../helpers/resolution_info";
import { BlobReader, BlobWriter, ZipWriter } from "@zip.js/zip.js";

export const NO_LOD_MESH_INDEX = -1;
const MAX_RETRY_COUNT = 5;
Expand Down Expand Up @@ -962,10 +964,53 @@ function* downloadIsosurfaceCellById(
}
}

function* downloadIsosurfaceCellsAsZIP(
arrayOfCells: { cellName: string; segmentId: number; layerName: string }[],
dieknolle3333 marked this conversation as resolved.
Show resolved Hide resolved
): Saga<void> {
const { segmentMeshController } = getSceneController();
const zipWriter = new ZipWriter(new BlobWriter("application/zip"));
try {
const promises = arrayOfCells.map((element) => {
const geometry = segmentMeshController.getIsosurfaceGeometryInBestLOD(
element.segmentId,
element.layerName,
);

if (geometry == null) {
const errorMessage = messages["tracing.not_isosurface_available_to_download"];
Toast.error(errorMessage, {
sticky: false,
});
return;
}
const stlDataViews = exportToStl(geometry);
// Encode isosurface and cell id property
const { isosurfaceMarker, segmentIdIndex } = stlIsosurfaceConstants;
isosurfaceMarker.forEach((marker, index) => {
stlDataViews[0].setUint8(index, marker);
});
stlDataViews[0].setUint32(segmentIdIndex, element.segmentId, true);
const stlDataReader = new BlobReader(new Blob(stlDataViews));
dieknolle3333 marked this conversation as resolved.
Show resolved Hide resolved
return zipWriter.add(`${element.cellName}-${element.segmentId}.stl`, stlDataReader);
dieknolle3333 marked this conversation as resolved.
Show resolved Hide resolved
});
yield all(promises);
const result = yield* call([zipWriter, zipWriter.close]);
saveAs(result, "mesh-export.zip");
dieknolle3333 marked this conversation as resolved.
Show resolved Hide resolved
} catch (exception) {
ErrorHandling.notify(exception as Error);
console.error(exception);
Toast.error("Could not export to STL. See console for details");
dieknolle3333 marked this conversation as resolved.
Show resolved Hide resolved
}
}

function* downloadIsosurfaceCell(action: TriggerIsosurfaceDownloadAction): Saga<void> {
yield* call(downloadIsosurfaceCellById, action.cellName, action.segmentId, action.layerName);
}

function* downloadIsosurfaceCells(action: TriggerIsosurfacesDownloadAction): Saga<void> {
yield* call(downloadIsosurfaceCellsAsZIP, action.surfaceArray);
}

function* importIsosurfaceFromStl(action: ImportIsosurfaceFromStlAction): Saga<void> {
const { layerName, buffer } = action;
const dataView = new DataView(buffer);
Expand Down Expand Up @@ -1035,6 +1080,7 @@ export default function* isosurfaceSaga(): Saga<void> {
yield* takeEvery(loadAdHocMeshActionChannel, loadAdHocIsosurfaceFromAction);
yield* takeEvery(loadPrecomputedMeshActionChannel, loadPrecomputedMesh);
yield* takeEvery("TRIGGER_ISOSURFACE_DOWNLOAD", downloadIsosurfaceCell);
yield* takeEvery("TRIGGER_ISOSURFACES_DOWNLOAD", downloadIsosurfaceCells);
yield* takeEvery("IMPORT_ISOSURFACE_FROM_STL", importIsosurfaceFromStl);
yield* takeEvery("REMOVE_ISOSURFACE", removeIsosurface);
yield* takeEvery("REMOVE_SEGMENT", handleRemoveSegment);
Expand Down