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

Don't remove other volume layers when opening volume annotation #6186

Merged
merged 21 commits into from
May 16, 2022
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
acca454
don't remove segmentation layers when opening an annotation with a vo…
philippotto Apr 29, 2022
a2a9f42
improve some types
philippotto May 10, 2022
6f00b61
don't mutate layer visibilities in dataset settings when an annotatio…
philippotto May 10, 2022
96122b5
refactor to avoid mutating immutable data
philippotto May 10, 2022
6e48f64
update changelog
philippotto May 10, 2022
1452a18
clean up
philippotto May 10, 2022
156d2b7
Merge branch 'master' into keep-seg-layers
philippotto May 10, 2022
7e2dfcc
fix default layer visibility for (volume) tasks
philippotto May 10, 2022
03218eb
Merge branch 'keep-seg-layers' of github.com:scalableminds/webknossos…
philippotto May 10, 2022
9020f39
fix type issue
philippotto May 10, 2022
17522e5
Merge branch 'master' of github.com:scalableminds/webknossos into kee…
philippotto May 13, 2022
30cb149
clean up comments
philippotto May 13, 2022
722d47c
clean up typing in tests a bit
philippotto May 13, 2022
36efa6c
add two screenshot tests for hybrid annotations with and without fall…
philippotto May 13, 2022
510f467
enable nightly on each push
philippotto May 13, 2022
fb81718
fix linting
philippotto May 13, 2022
36071dc
fix linting
philippotto May 13, 2022
06aa5d9
Update frontend/javascripts/test/puppeteer/dataset_rendering.screensh…
philippotto May 16, 2022
d6b0036
undo nightly testing on CI push
philippotto May 16, 2022
3e3ad4f
Merge branch 'keep-seg-layers' of github.com:scalableminds/webknossos…
philippotto May 16, 2022
591247c
Merge branch 'master' of github.com:scalableminds/webknossos into kee…
philippotto May 16, 2022
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
4 changes: 4 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,10 @@ workflows:
version: 2
circleci_build:
jobs:
- nightly:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reminder to remove this before merging

filters:
tags:
only: /.*/
- build_test_deploy:
filters:
tags:
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.released
### Changed
- When creating a new annotation with a volume layer (without fallback) for a dataset which has an existing segmentation layer, the original segmentation layer is still listed (and viewable) in the left sidebar. Earlier versions simply hid the original segmentation layer. [#6186](https://github.com/scalableminds/webknossos/pull/6186)
- Changing the visibility of a layer within an annotation does not change the visibility of the layer when viewing the corresponding dataset. [#6186](https://github.com/scalableminds/webknossos/pull/6186)
- While viewing tracings in read-only mode, the options to manipulate the tracing are now disabled. This leads to less confusion as previously the input was silently discarded. [#6140](https://github.com/scalableminds/webknossos/pull/6140).
- Changed default of `dynamicSpaceDirection` property to false to avoid confusion. [#6162](https://github.com/scalableminds/webknossos/pull/6162)
- Changed the internal protocol for requesting image data. The zoomStep parameter has been replaced by mag. This increases the datastore API version to 2.0 [#6159](https://github.com/scalableminds/webknossos/pull/6159)
- In annotation list in dashboard, replaced the non-standard word “Trace” by “Open”. [#6191](https://github.com/scalableminds/webknossos/pull/6191)
Expand Down
4 changes: 2 additions & 2 deletions frontend/javascripts/admin/admin_rest_api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1237,7 +1237,7 @@ export function updateDatasetConfiguration(
datasetId: APIDatasetId,
datasetConfig: PartialDatasetConfiguration,
options: RequestOptions = {},
): Record<string, any> {
): Promise<Record<string, any>> {
return Request.sendJSONReceiveJSON(
`/api/dataSetConfigurations/${datasetId.owningOrganization}/${datasetId.name}`,
{ ...options, method: "PUT", data: datasetConfig },
Expand Down Expand Up @@ -1616,7 +1616,7 @@ export function getUserConfiguration(): Promise<UserConfiguration> {

export function updateUserConfiguration(
userConfiguration: Record<string, any>,
): Record<string, any> {
): Promise<Record<string, any>> {
return Request.sendJSONReceiveJSON("/api/user/userConfiguration", {
method: "PUT",
data: userConfiguration,
Expand Down
2 changes: 1 addition & 1 deletion frontend/javascripts/oxalis/model/sagas/settings_saga.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ function* showUserSettingToast(action: UpdateUserSettingAction): Saga<void> {
export default function* watchPushSettingsAsync(): Saga<void> {
const action = yield* take("INITIALIZE_SETTINGS");
if (action.type !== "INITIALIZE_SETTINGS") {
throw new Error("Unexpected action. Satisfy flow.");
throw new Error("Unexpected action. Satisfy typescript.");
}

const { originalDatasetSettings } = action;
Expand Down
11 changes: 2 additions & 9 deletions frontend/javascripts/oxalis/model_initialization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -488,16 +488,9 @@ function setupLayerForVolumeTracing(
tracings: Array<ServerVolumeTracing>,
): Array<APIDataLayer> {
// This method adds/merges the segmentation layers of the tracing into the dataset layers.
// This is done by
// 1) removing all segmentation data layers (gathered in newLayers)
// 2) appending new tracing layers (using the original layers for fallback information)

const originalLayers = dataset.dataSource.dataLayers;
// Remove other segmentation layers, since we are adding new ones.
// This is a temporary workaround. Even though we support multiple segmentation
// layers, we cannot render both at the same time. Hiding the existing segmentation
// layer would be good, but this information is stored per dataset and not per annotation
// currently. Also, see https://github.com/scalableminds/webknossos/issues/5695
const newLayers = originalLayers.slice(); // .filter((layer) => layer.category !== "segmentation");
const newLayers = originalLayers.slice();

for (const tracing of tracings) {
// The tracing always contains the layer information for the user segmentation.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ user_A, user_B, user_C, user_D, user_E
*/
// Teams
test("teams_userDefault", async (t) => {
await setCurrToken(tokenUserA);
setCurrToken(tokenUserA);

const teams = _.sortBy(await api.getTeams(), (team) => team.name);

Expand All @@ -50,15 +50,15 @@ test("teams_userDefault", async (t) => {
t.is(teams.length, 4);
});
test("teams_user_D", async (t) => {
await setCurrToken(tokenUserD);
setCurrToken(tokenUserD);

const teams = _.sortBy(await api.getTeams(), (team) => team.name);

t.is(teams[0].name, "team_X2");
t.is(teams.length, 1);
});
test("teams_user_E", async (t) => {
await setCurrToken(tokenUserE);
setCurrToken(tokenUserE);

const teams = _.sortBy(await api.getTeams(), (team) => team.name);

Expand All @@ -67,15 +67,15 @@ test("teams_user_E", async (t) => {
});
test("teams_delete_user_D", async (t) => {
// the teamManager is not allowed to delete the team
await setCurrToken(tokenUserD);
setCurrToken(tokenUserD);
t.plan(1);
await api.deleteTeam("69882b370d889b84020efd4f").catch((err) => {
t.is(err.messages[0].error, "Access denied. Only admin users can execute this operation.");
});
});
test("teams_create_user_D", async (t) => {
// the teamManager is not allowed to create a new team
await setCurrToken(tokenUserD);
setCurrToken(tokenUserD);
t.plan(1);
const newTeam = {
name: "test-team-name",
Expand All @@ -86,51 +86,51 @@ test("teams_create_user_D", async (t) => {
});
// TaskTypes
test("taskTypes_userDefault", async (t) => {
await setCurrToken(tokenUserA);
setCurrToken(tokenUserA);

const taskTypes = _.sortBy(await api.getTaskTypes(), (taskType) => taskType.id);

t.is(taskTypes[0].description, "Check those cells out!");
t.is(taskTypes.length, 2);
});
test("taskTypes_user_D", async (t) => {
await setCurrToken(tokenUserD);
setCurrToken(tokenUserD);

const taskTypes = _.sortBy(await api.getTaskTypes(), (taskType) => taskType.id);

t.is(taskTypes.length, 1);
});
test("taskTypes_user_E", async (t) => {
await setCurrToken(tokenUserE);
setCurrToken(tokenUserE);

const taskTypes = _.sortBy(await api.getTaskTypes(), (taskType) => taskType.id);

t.is(taskTypes.length, 0);
});
// Tasks
test("tasks_user_D", async (t) => {
await setCurrToken(tokenUserD);
setCurrToken(tokenUserD);
t.plan(1);
await api.getTask("58135c192faeb34c0081c058").catch((err) => {
t.is(err.messages[0].error, "Task couldn’t be found");
});
});
test("tasks_user_E", async (t) => {
await setCurrToken(tokenUserE);
setCurrToken(tokenUserE);
t.plan(1);
await api.getTask("58135c192faeb34c0081c058").catch((err) => {
t.is(err.messages[0].error, "Task couldn’t be found");
});
});
test("tasks_user_C", async (t) => {
await setCurrToken(tokenUserC);
setCurrToken(tokenUserC);
const task = await api.getTask("58135c192faeb34c0081c058");
t.is(task.id, "58135c192faeb34c0081c058");
});
// User
test("user_user_B", async (t) => {
// teamMng are not allowed to de-/activate a user (if they are not an admin)
await setCurrToken(tokenUserB);
setCurrToken(tokenUserB);
t.plan(2);
const userIdC = "770b9f4d2a7c0e4d008da6ef";
const user = await api.getUser(userIdC);
Expand All @@ -145,7 +145,7 @@ test("user_user_B", async (t) => {
// Project
test("project_user_B", async (t) => {
// teamMng are not allowed to delete a project (if they are not an admin and they are not the owner)
await setCurrToken(tokenUserE);
setCurrToken(tokenUserE);
t.plan(1);
const projectId = "58135bfd2faeb3190181c057";
await api.deleteProject(projectId).catch((err) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type { Browser } from "puppeteer";
import puppeteer from "puppeteer";
import { compareScreenshot, isPixelEquivalent } from "./screenshot_helpers";
import {
screenshotAnnotation,
screenshotDataset,
screenshotDatasetWithMapping,
screenshotDatasetWithMappingLink,
Expand Down Expand Up @@ -39,8 +40,8 @@ if (!process.env.URL) {
}

console.log(`[Info] Executing tests on URL ${URL}.`);
// Ava's recommendation for Flow types
// https://github.com/avajs/ava/blob/master/docs/recipes/flow.md#typing-tcontext
// Ava's recommendation for Typescript types
// https://github.com/avajs/ava/blob/main/docs/recipes/typescript.md#typing-tcontext
const test: TestInterface<{
browser: Browser;
}> = anyTest as any;
Expand Down Expand Up @@ -89,6 +90,14 @@ const datasetNames = [
"Multi-Channel-Test",
"connectome_file_test_dataset",
];

type DatasetName = string;
type FallbackLayerName = string | null;
const annotationSpecs: Array<[DatasetName, FallbackLayerName]> = [
["ROI2017_wkw_fallback", "segmentation"],
["ROI2017_wkw_fallback", null],
];

const viewOverrides: Record<string, string> = {
"2017-05-31_mSEM_scMS109_bk_100um_v01-aniso": "4608,4543,386,0,4.00",
ROI2017_wkw_fallback: "535,536,600,0,1.18",
Expand Down Expand Up @@ -182,6 +191,51 @@ datasetNames.map(async (datasetName) => {
);
});
});

annotationSpecs.map(async (annotationSpec) => {
const [datasetName, fallbackLayerName] = annotationSpec;

test.serial.only(
`It should render an annotation for ${datasetName} with fallback_layer=${fallbackLayerName} correctly`,
async (t) => {
console.log(
`It should render an annotation for ${datasetName} with fallback_layer=${fallbackLayerName} correctly`,
);
await withRetry(
3,
async () => {
const datasetId = {
name: datasetName,
owningOrganization: "sample_organization",
};
const { screenshot, width, height } = await screenshotAnnotation(
await getNewPage(t.context.browser),
URL,
datasetId,
fallbackLayerName,
viewOverrides[datasetName],
datasetConfigOverrides[datasetName],
);
const changedPixels = await compareScreenshot(
screenshot,
width,
height,
BASE_PATH,
`annotation_${datasetName}_${fallbackLayerName}`,
);
return isPixelEquivalent(changedPixels, width, height);
},
(condition) => {
t.true(
condition,
`Dataset with name: "${datasetName}" does not look the same, see ${datasetName}.diff.png for the difference and ${datasetName}.new.png for the new screenshot.`,
philippotto marked this conversation as resolved.
Show resolved Hide resolved
);
},
);
},
);
});

test.serial("it should render a dataset with mappings correctly", async (t) => {
const datasetName = "ROI2017_wkw";
const mappingName = "astrocyte";
Expand Down Expand Up @@ -299,7 +353,6 @@ test.serial(
name: datasetName,
owningOrganization: "sample_organization",
};
// @ts-expect-error ts-migrate(2554) FIXME: Expected 5 arguments, but got 4.
const { screenshot, width, height } = await screenshotDataset(
await getNewPage(t.context.browser),
URL,
Expand Down
Loading