-
Notifications
You must be signed in to change notification settings - Fork 24
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
Conversation
app/models/job/Job.scala
Outdated
@@ -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" => |
There was a problem hiding this comment.
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.
There was a problem hiding this 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.
function StartingJobModal(props: StartingJobModalProps) { | ||
const isBoundingBoxConfigurable = props.isBoundingBoxConfigurable || false; | ||
const chooseSegmentationLayer = props.chooseSegmentationLayer || false; |
There was a problem hiding this comment.
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.
frontend/javascripts/oxalis/view/right-border-tabs/starting_job_modals.js
Outdated
Show resolved
Hide resolved
make start job modals a form
Add potential volume annotation layer to params of merger mode job all potential annotation cases
…-apply-merger-mode-job
…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
There was a problem hiding this 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.
frontend/javascripts/oxalis/view/right-border-tabs/starting_job_modals.js
Outdated
Show resolved
Hide resolved
frontend/javascripts/oxalis/view/right-border-tabs/starting_job_modals.js
Outdated
Show resolved
Hide resolved
frontend/javascripts/oxalis/view/right-border-tabs/starting_job_modals.js
Outdated
Show resolved
Hide resolved
Co-authored-by: Philipp Otto <[email protected]>
…-apply-merger-mode-job
…webknossos into add-apply-merger-mode-job
Great stuff! Testing went mostly smooth, but I noticed a few things:
|
@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.
|
TODOs
|
As far as I know the |
- and apply some feedback
…-apply-merger-mode-job
…-apply-merger-mode-job
There was a problem hiding this 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 🙏 🥨 ?
<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> |
There was a problem hiding this comment.
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.
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> | ||
); | ||
} | ||
|
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue: #6197
frontend/javascripts/oxalis/view/right-border-tabs/starting_job_modals.tsx
Outdated
Show resolved
Hide resolved
There was a problem hiding this 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} |
There was a problem hiding this comment.
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?
frontend/javascripts/oxalis/view/right-border-tabs/starting_job_modals.tsx
Outdated
Show resolved
Hide resolved
frontend/javascripts/oxalis/view/right-border-tabs/starting_job_modals.tsx
Outdated
Show resolved
Hide resolved
frontend/javascripts/oxalis/view/right-border-tabs/starting_job_modals.tsx
Outdated
Show resolved
Hide resolved
frontend/javascripts/oxalis/view/right-border-tabs/starting_job_modals.tsx
Outdated
Show resolved
Hide resolved
…ayer without a fallback layer - also incoperate other feedback
@daniel-wer I incorporated your feedback, could you please check the changes 💇 ? |
I also just changed the docs a little. Do you think this is enough documentation for the new job @daniel-wer @fm3? |
There was a problem hiding this 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
.
Co-authored-by: Daniel <[email protected]>
- pass unallowed layer names directly to form item
@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? |
There was a problem hiding this 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 :)
frontend/javascripts/oxalis/view/right-border-tabs/starting_job_modals.tsx
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. |
There was a problem hiding this comment.
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 :)
// Filtering out the layer that is currently selected as this name is allowed | ||
// because the output layer overwrites the selected layer. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// 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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
frontend/javascripts/oxalis/view/right-border-tabs/starting_job_modals.tsx
Outdated
Show resolved
Hide resolved
Co-authored-by: Philipp Otto <[email protected]>
…-apply-merger-mode-job
…webknossos into add-apply-merger-mode-job
// Filtering out the layer that is currently selected as this name is allowed | ||
// because the output layer overwrites the selected layer. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// 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 😆
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense 👍
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:
URL of deployed dev instance (used for testing):
Steps to test:
Issues:
(Please delete unneeded items, merge only when none are left open)
[ ] Updated (unreleased) migration guide if applicable[ ] Adapted wk-connect if datastore API changes[ ] Adapted wk-libs python client if relevant API parts change[ ] Needs datastore update after deployment