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 frontend and backend part for job to materialize a volume annotation #6086

Merged
merged 39 commits into from
May 9, 2022

Conversation

MichaelBuessemeyer
Copy link
Contributor

@MichaelBuessemeyer MichaelBuessemeyer commented Feb 28, 2022

This PR adds the frontend and backend part for the job that applies the results of a merger mode tracing to a segmentation layer.

Open TODOs:

  • Properly support and test the support for tracings with multiple segmentation layers.
  • Add a preview image for the apply merger mode job
  • Test selecting from multiple segmentation layers and whether the worker also chooses the correct segmentation layer and applies the segment merging to it.
  • See my mentions below :)

URL of deployed dev instance (used for testing):

  • https://___.webknossos.xyz

Steps to test:

  • As this pr is closely connected to the counter part pr in the worker's repo, the testing instructions can be taken from the wk-worker pr as they would be the same for this pr.

Issues:


(Please delete unneeded items, merge only when none are left open)

@@ -72,7 +72,7 @@ case class Job(
}
case "export_tiff" =>
Some(s"$dataStorePublicUrl/data/exports/${_id.id}/download")
case "infer_nuclei" | "infer_neurons" =>
case "infer_nuclei" | "infer_neurons" | "apply_merger_mode" =>
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am not sure, whether this is everything I need to do here for the new job. I did not test the jobs list view and therefore this is likely untested.

Copy link
Contributor Author

@MichaelBuessemeyer MichaelBuessemeyer left a comment

Choose a reason for hiding this comment

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

These are all the comments that seemed helpful to me. If you got questions about the code, just let me know.

Comment on lines 38 to 40
function StartingJobModal(props: StartingJobModalProps) {
const isBoundingBoxConfigurable = props.isBoundingBoxConfigurable || false;
const chooseSegmentationLayer = props.chooseSegmentationLayer || false;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The main changes here and below are that I enabled StartingJobModal to not only select color layers but also segmentation layers when chooseSegmentationLayer=true is passed to the component. The changes are mainly removing "color" from that variable names as the layers the component now works with might also be of kind segmentation.

Add potential volume annotation layer to params of merger mode job all potential annotation cases
…t as the other job starting modals

- Add volume annotation layer name to flood fill job to make it work when there are multiple annotation layers
@MichaelBuessemeyer MichaelBuessemeyer changed the title [WIP] Add frontend and backend part for job to apply merger mode tracing Add frontend and backend part for job to apply merger mode tracing Mar 31, 2022
@MichaelBuessemeyer MichaelBuessemeyer self-assigned this Apr 4, 2022
Copy link
Member

@philippotto philippotto left a comment

Choose a reason for hiding this comment

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

Great stuff! Didn't test yet, but the code looks good overall 👍 Mainly left feedback for naming and maybe usability.

@philippotto
Copy link
Member

philippotto commented Apr 6, 2022

Great stuff! Testing went mostly smooth, but I noticed a few things:

@MichaelBuessemeyer
Copy link
Contributor Author

@fm3 I think I need some help in this pr because I changed the long-running jobs routes a little. Do you think bumping the API version is needed here or can we somehow circumvent this?

Also: wklibs does not contain any methods that work with the backend long-running jobs routes, or does it? IF it does, wklibs might also need some slight adjustments.

@MichaelBuessemeyer
Copy link
Contributor Author

MichaelBuessemeyer commented Apr 25, 2022

TODOs

  • Check other long-running jobs and make them "overwrite proof" in case multiple jobs are running at the same time which have the same output dataset name given by the user
    • Only the inferral jobs and the new merger mode job got the new property new_dataset_name. For both, I ensured before creating the output dataset to check whether the name is still available. If the name is not available anymore an index number is added to the name to avoid name collisions.

@fm3
Copy link
Member

fm3 commented Apr 25, 2022

As far as I know the /jobs/run routes are currently only called by the javascript front-end. Because of this, I’d say we do not need to provide backwards compatibility / bump the api version or adapt the python client

@MichaelBuessemeyer MichaelBuessemeyer changed the title Add frontend and backend part for job to apply merger mode tracing Add frontend and backend part for job to materialize a volume annotation May 5, 2022
Copy link
Contributor Author

@MichaelBuessemeyer MichaelBuessemeyer left a comment

Choose a reason for hiding this comment

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

@daniel-wer I just added comments to the code parts I'd like some feedback on before merging. Could you please do that 🙏 🥨 ?

Comment on lines +183 to +191
<span>
Materialize annotation for {job.layerName ? ` layer ${job.layerName} of ` : " "}
<Link to={`/datasets/${job.organizationName}/${job.datasetName}/view`}>
{job.datasetName}
</Link>
{job.mergeSegments
? ". This includes merging the segments that were merged via merger mode."
: null}
</span>
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Feedback about this part / formulation would be nice.

And whether it is readable enough or should be refactored in a certain way.

Comment on lines 184 to 222
export function OutputSegmentationLayerNameFormItem({
hasOutputSegmentationLayer,
layers,
additionalAllowedNames,
}: OutputSegmentationLayerNameProps) {
return (
<Form.Item
label="Name of output segmentation layer"
name="outputSegmentationLayerName"
rules={[
{ required: hasOutputSegmentationLayer },
{
min: 3,
},
{
pattern: /[0-9a-zA-Z_-]+$/,
},
{
validator: async (_rule, newOutputLayerName) => {
if (
layers.some((layer) => layer.name === newOutputLayerName) &&
!additionalAllowedNames.includes(newOutputLayerName)
) {
const reason =
"This name is already used by another segmentation layer of this dataset.";
return Promise.reject(reason);
} else {
return Promise.resolve();
}
},
},
]}
hidden={!hasOutputSegmentationLayer}
>
<Input />
</Form.Item>
);
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This new Form.Item is new and wasn't reviewed by @philippotto. Could you please do that @daniel-wer?

Copy link
Member

Choose a reason for hiding this comment

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

Could you explain the rationale behind additionalAllowedNames? I didn't understand why this is needed from looking at the code.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

additionalAllowedNames is a list of names that are allowed to enter although the dataset already has a layer with that name. In the modal this is used to allow the user to let the output segmentation layer have the exact same name as the input segmentation layer. This is possible because the output segmentation layer replaces the input segmentation layer in the output dataset. Therefore non _corrected or something like this at the end of the output layer name is needed.

Does this behaviour make sense to you?

Copy link
Member

Choose a reason for hiding this comment

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

Ah yes that makes sense. One could also remove the extra parameter additionalAllowedNames and filter the layers before handing them as a prop to OutputSegmentationLayerNameFormItem (to filter out the segmentation layer that is replaced). A small comment could be added at the filtering spot to explain why this is done.
I feel like this would be cleaner and easier to understand, what do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

what do you think?

Sounds good to me :)

initialOutputSegmentationLayerName = `${
initialOutputSegmentationLayerName || "segmentation"
}_corrected`;
// TODO: Other jobs also have an output segmentation layer. The names for these jobs should also be configurable.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This TODO needs to be kept, as the new OutputSegmentationLayerNameFormItem should also be used for the inferral jobs. I did not do it in this pr to avoid making this pr even bigger.

Copy link
Member

Choose a reason for hiding this comment

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

please open a follow-up issue for this :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

issue: #6197

Copy link
Member

@daniel-wer daniel-wer left a comment

Choose a reason for hiding this comment

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

Please check my comments. The biggest issue in my opinion is that the code assumes that there always is a fallback layer. In my understanding, that's not the case, annotations can also be created without a fallback layer 🤔

@@ -457,6 +473,9 @@ class DatasetSettings extends React.PureComponent<DatasetSettingsProps, State> {
<div className="flex-item">
{hasHistogram && !isDisabled ? this.getEditMinMaxButton(layerName, isInEditMode) : null}
</div>
<div className="flex-item">
{isVolumeTracing && !isDisabled ? this.getMergeWithFallbackLayerButton(layer) : null}
Copy link
Member

Choose a reason for hiding this comment

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

Not every volume annotation has a fallback layer. Shouldn't this be checked before showing this button?

…ayer without a fallback layer

- also incoperate other feedback
@MichaelBuessemeyer
Copy link
Contributor Author

@daniel-wer I incorporated your feedback, could you please check the changes 💇 ?

@MichaelBuessemeyer
Copy link
Contributor Author

I also just changed the docs a little. Do you think this is enough documentation for the new job @daniel-wer @fm3?

Copy link
Member

@daniel-wer daniel-wer left a comment

Choose a reason for hiding this comment

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

Please also see my comment regarding additionalAllowedNames.

docs/volume_annotation.md Outdated Show resolved Hide resolved
docs/volume_annotation.md Outdated Show resolved Hide resolved
docs/volume_annotation.md Outdated Show resolved Hide resolved
MichaelBuessemeyer and others added 2 commits May 5, 2022 16:56
 - pass unallowed layer names directly to form item
@MichaelBuessemeyer
Copy link
Contributor Author

@daniel-wer I finished your last feedback, could you please have a look again? Maybe Monday so this pr can be merged on that day?

Copy link
Member

@philippotto philippotto left a comment

Choose a reason for hiding this comment

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

See my few nitpicks, but other than that everything looks great :)

docs/volume_annotation.md Outdated Show resolved Hide resolved
initialOutputSegmentationLayerName = `${
initialOutputSegmentationLayerName || "segmentation"
}_corrected`;
// TODO: Other jobs also have an output segmentation layer. The names for these jobs should also be configurable.
Copy link
Member

Choose a reason for hiding this comment

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

please open a follow-up issue for this :)

Comment on lines 309 to 310
// Filtering out the layer that is currently selected as this name is allowed
// because the output layer overwrites the selected layer.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// Filtering out the layer that is currently selected as this name is allowed
// because the output layer overwrites the selected layer.
// Filtering out the layer that is currently selected as this name is not allowed
// because the output layer would overwrite the selected layer.

if I understood it correctly

Copy link
Contributor Author

@MichaelBuessemeyer MichaelBuessemeyer May 9, 2022

Choose a reason for hiding this comment

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

No sorry, that is exactly not the case here.
All layer names are forbidden !except! the name of the selected volume layer, because this volume layer will don't exist in the output dataset, but it will be replaced with the modified version of this layer. The modified version then will have the name given by the OutputSegmentationLayerNameFormItem.
The list of these names is passed to OutputSegmentationLayerNameFormItem so that this form item can check against these names. In the case of a match, the form item is not submittable / in an error state to prevent the job running in the backend from having problems because of duplicate layer names.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As you misunderstood this comment, do you have a different way to express this, that might be easier to understand / not misunderstand?

Comment on lines 309 to 310
// Filtering out the layer that is currently selected as this name is allowed
// because the output layer overwrites the selected layer.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// Filtering out the layer that is currently selected as this name is allowed
// because the output layer overwrites the selected layer.
// Existing layer names may not be used for the output layer. The only exception is the name of the currently selected layer.
// If that layer name is chosen, the original layer data won't exist in the output dataset, since it will be replaced by the new output.

Maybe like this? Needs prettier-formatting, though. You could also keep the comment as is. My interpretation didn't really make sense, which is why I'd hope I won't question the veracity of the comment in the future 😆

Copy link
Contributor Author

Choose a reason for hiding this comment

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

// If that layer name is chosen, the original layer data won't exist in the output dataset, since it will be replaced by the new output.

Technically speaking, this is not correct. The selected layer will never directly exist in the output dataset, if the job has an output layer. Therefore, this is even the case if the layer name is not chosen. But your 3rd sentence reads like it is only the case when the layer name is chosen.

I rephrased your suggestion a little and made it more expressive:

   // is the name of the currently selected layer. This layer is the only one not
   // copied over from the original dataset to the output dataset.
   // Therefore, this name is available as the name for the output layer name.
   // That is why that layer is filtered out here.

Copy link
Member

Choose a reason for hiding this comment

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

Makes sense 👍

@MichaelBuessemeyer MichaelBuessemeyer merged commit 95ec9e1 into master May 9, 2022
@MichaelBuessemeyer MichaelBuessemeyer deleted the add-apply-merger-mode-job branch May 9, 2022 12:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Allow applying result of merger mode tracing
4 participants