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

Add (minimal) UI for auto brush and allow it for white-listed datasets #4053

Merged
merged 8 commits into from
May 6, 2019
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.md).

### Added
- BossDB datasets can now be added to webKnossos using the webknossos-connect service. [#4036](https://github.com/scalableminds/webknossos/pull/4036)
-
- Added an auto-brush feature for selected datasets. [#4053](https://github.com/scalableminds/webknossos/pull/4053)

### Changed
- The NML parser now rounds floating point values in node coordinates. [#4045](https://github.com/scalableminds/webknossos/pull/4045)
Expand Down
1 change: 1 addition & 0 deletions conf/application.conf
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ features {
# if it is false, / will be the login page, if not logged in, and the dashboard otherwise
enableFrontpage = false
isDemoInstance = false
autoBrushReadyDatasets = []
}

# Actor settings
Expand Down
1 change: 1 addition & 0 deletions frontend/javascripts/admin/api_flow_types.js
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,7 @@ export type APIFeatureToggles = {
+hideNavbarLogin: boolean,
+addMissingDatasetButtonEnabled: boolean,
+enableFrontpage: boolean,
+autoBrushReadyDatasets: Array<string>,
+isDemoInstance: boolean,
};

Expand Down
2 changes: 1 addition & 1 deletion frontend/javascripts/libs/toast.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ const Toast = {
notification[type](toastConfig);
},

info(message: string, config: ToastConfig = {}): void {
info(message: string | React$Element<any>, config: ToastConfig = {}): void {
return this.message("info", message, config);
},

Expand Down
1 change: 1 addition & 0 deletions frontend/javascripts/messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export const settings = {
but it will take more time until the best quality is shown).`,
mergerMode: "Enable Merger Mode",
gpuMemoryFactor: "Quality",
autoBrush: "Automatic Brush (Beta)",
};

export default {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ import * as Utils from "libs/utils";

// TODO: Build proper UI for this
window.isAutomaticBrushEnabled = false;
const isAutomaticBrushEnabled = () =>
window.isAutomaticBrushEnabled || Store.getState().temporaryConfiguration.isAutoBrushEnabled;

// eslint-disable-next-line no-unused-vars
const simulateTracing = async (): Promise<void> => {
Expand Down Expand Up @@ -95,7 +97,7 @@ export function getPlaneMouseControls(_planeId: OrthoView): * {

if (!event.shiftKey && (tool === VolumeToolEnum.TRACE || tool === VolumeToolEnum.BRUSH)) {
if (event.ctrlKey) {
if (window.isAutomaticBrushEnabled) {
if (isAutomaticBrushEnabled()) {
return;
}
Store.dispatch(setContourTracingMode(ContourModeEnum.DRAW));
Expand Down Expand Up @@ -169,7 +171,7 @@ export function getPlaneMouseControls(_planeId: OrthoView): * {
Store.dispatch(setActiveCellAction(cellId));
}
} else if (event.ctrlKey) {
if (window.isAutomaticBrushEnabled) {
if (isAutomaticBrushEnabled()) {
Store.dispatch(inferSegmentationInViewportAction(calculateGlobalPos(pos)));
}
}
Expand Down
1 change: 1 addition & 0 deletions frontend/javascripts/oxalis/default_state.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ const defaultState: OxalisState = {
mappingSize: 0,
},
isMergerModeEnabled: false,
isAutoBrushEnabled: false,
gpuSetup: {
smallestCommonBucketCapacity:
Constants.GPU_FACTOR_MULTIPLIER * Constants.DEFAULT_GPU_MEMORY_FACTOR,
Expand Down
23 changes: 19 additions & 4 deletions frontend/javascripts/oxalis/model/sagas/automatic_brush_saga.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// @flow
import * as tf from "@tensorflow/tfjs";
import memoizeOne from "memoize-one";

import React from "react";
import { type Saga, call, fork, select, take, _cancel } from "oxalis/model/sagas/effect-generators";
import floodfill from "libs/floodfill";
import { FlycamActions } from "oxalis/model/actions/flycam_actions";
Expand All @@ -18,6 +18,7 @@ import Model from "oxalis/model";
import Toast from "libs/toast";
import { enforceVolumeTracing } from "oxalis/model/accessors/volumetracing_accessor";
import Dimensions from "oxalis/model/dimensions";
import Shortcut from "libs/shortcut_component";
import api from "oxalis/api/internal_api";
import {
getPosition,
Expand Down Expand Up @@ -138,9 +139,21 @@ export default function* inferSegmentInViewport(
sticky: true,
key: "automatic-brush",
};
const toastDescription = "Automatic brush is active. Close the toast to stop using it.";
const getEscapableToast = text => (
<div>
{text}
<Shortcut
keys="esc"
onTrigger={() => {
aborted = true;
Toast.close(toastConfig.key);
}}
/>
</div>
);

Toast.info(toastDescription, toastConfig);
const brushIsActiveText = "Automatic brush is active. Close the toast to stop using it.";
Toast.info(getEscapableToast(brushIsActiveText), toastConfig);

const colorLayers = yield* call([Model, Model.getColorLayers]);
const colorLayerName = colorLayers[0].name;
Expand Down Expand Up @@ -209,7 +222,9 @@ export default function* inferSegmentInViewport(
console.time("predict");
const thirdDimension = Dimensions.thirdDimensionForPlane(activeViewport);
Toast.info(
`${toastDescription}\nLabeling ${["x", "y", "z"][thirdDimension]}=${z}.`,
getEscapableToast(
`${brushIsActiveText}\nLabeling ${["x", "y", "z"][thirdDimension]}=${z}.`,
),
toastConfig,
);
predictions.set(
Expand Down
1 change: 1 addition & 0 deletions frontend/javascripts/oxalis/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ export type TemporaryConfiguration = {
+mappingSize: number,
},
+isMergerModeEnabled: boolean,
+isAutoBrushEnabled: boolean,
+gpuSetup: {
// These rendering-related variables are set up
// during startup and cannot change (with the current
Expand Down
43 changes: 42 additions & 1 deletion frontend/javascripts/oxalis/view/settings/user_settings_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* @flow
*/

import features from "features";
import { Collapse } from "antd";
import type { Dispatch } from "redux";
import { connect } from "react-redux";
Expand Down Expand Up @@ -37,14 +38,18 @@ import {
import { setUserBoundingBoxAction } from "oxalis/model/actions/annotation_actions";
import { setZoomStepAction } from "oxalis/model/actions/flycam_actions";
import { settings as settingsLabels } from "messages";
import { updateUserSettingAction } from "oxalis/model/actions/settings_actions";
import {
updateTemporarySettingAction,
updateUserSettingAction,
} from "oxalis/model/actions/settings_actions";
import { userSettings } from "libs/user_settings.schema";
import Constants, {
type ControlMode,
ControlModeEnum,
type ViewMode,
type Vector6,
} from "oxalis/constants";
import Toast from "libs/toast";
import * as Utils from "libs/utils";

import MergerModeModalView from "./merger_mode_modal_view";
Expand All @@ -64,7 +69,9 @@ type UserSettingsViewProps = {
onChangeRadius: (value: number) => void,
onChangeZoomStep: (value: number) => void,
onChangeEnableMergerMode: (active: boolean) => void,
onChangeEnableAutoBrush: (active: boolean) => void,
isMergerModeEnabled: boolean,
isAutoBrushEnabled: boolean,
viewMode: ViewMode,
controlMode: ControlMode,
dataset: APIDataset,
Expand Down Expand Up @@ -109,6 +116,15 @@ class UserSettingsView extends PureComponent<UserSettingsViewProps, State> {
}
};

handleAutoBrushChange = async (active: boolean) => {
this.props.onChangeEnableAutoBrush(active);
if (active) {
Toast.info(
"You enabled the experimental automatic brush feature. Activate the brush tool and use CTRL+Click to use it.",
);
}
};

getViewportOptions = () => {
switch (this.props.viewMode) {
case Constants.MODE_PLANE_TRACING:
Expand Down Expand Up @@ -321,6 +337,7 @@ class UserSettingsView extends PureComponent<UserSettingsViewProps, State> {
value={this.props.userConfiguration.brushSize}
onChange={this.onChangeUser.brushSize}
/>
{this.maybeGetAutoBrushUi()}
<NumberInputSetting
label="Active Cell ID"
value={volumeTracing.activeCellId}
Expand All @@ -332,6 +349,26 @@ class UserSettingsView extends PureComponent<UserSettingsViewProps, State> {
return panels;
};

maybeGetAutoBrushUi() {
const { autoBrushReadyDatasets } = features();
if (
autoBrushReadyDatasets == null ||
!autoBrushReadyDatasets.includes(this.props.dataset.name)
) {
return null;
}

return (
<SwitchSetting
label={settingsLabels.autoBrush}
value={this.props.isAutoBrushEnabled}
onChange={value => {
this.handleAutoBrushChange(value);
}}
/>
);
}

render() {
const { isMergerModeModalVisible, isMergerModeModalClosable } = this.state;
const moveValueSetting = Constants.MODES_ARBITRARY.includes(this.props.viewMode) ? (
Expand Down Expand Up @@ -409,6 +446,7 @@ const mapStateToProps = (state: OxalisState) => ({
viewMode: state.temporaryConfiguration.viewMode,
controlMode: state.temporaryConfiguration.controlMode,
isMergerModeEnabled: state.temporaryConfiguration.isMergerModeEnabled,
isAutoBrushEnabled: state.temporaryConfiguration.isAutoBrushEnabled,
dataset: state.dataset,
});

Expand Down Expand Up @@ -437,6 +475,9 @@ const mapDispatchToProps = (dispatch: Dispatch<*>) => ({
onChangeEnableMergerMode(active: boolean) {
dispatch(setMergerModeEnabledAction(active));
},
onChangeEnableAutoBrush(active: boolean) {
dispatch(updateTemporarySettingAction("isAutoBrushEnabled", active));
},
});

export default connect<UserSettingsViewProps, {||}, _, _, _, _>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ Generated by [AVA](https://ava.li).
addForeignDataset: false,
addMissingDatasetButtonEnabled: false,
allowOrganizationCreation: false,
autoBrushReadyDatasets: [],
defaultOrganization: '',
discussionBoard: 'https://support.webknossos.org',
discussionBoardRequiresAdmin: false,
Expand Down
Binary file not shown.