-
Notifications
You must be signed in to change notification settings - Fork 29
Reupload exported editable mapping annotation zip #8969
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
base: master
Are you sure you want to change the base?
Changes from all commits
c6adc16
b1091e6
c874e70
83509f2
c6a85da
034c28a
a7ff6ad
d077ef7
b69baaa
95d04e8
758a5d7
e944f1a
1ec08e8
8c54c06
1641619
79221c4
a639433
055078a
27e8cde
2d7f68a
5874ce5
3d0288e
e07251f
b42cf2b
8fcf0bb
80e8a1d
1889fc4
feb8eba
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -132,25 +132,25 @@ class AnnotationIOController @Inject()( | |||||||
volumeLayersGrouped <- adaptVolumeTracingsToFallbackLayer(volumeLayersGroupedRaw, dataset, usableDataSource) | ||||||||
tracingStoreClient <- tracingStoreService.clientFor(dataset) | ||||||||
newAnnotationId = ObjectId.generate | ||||||||
mergedVolumeLayers <- mergeAndSaveVolumeLayers(newAnnotationId, | ||||||||
volumeLayersGrouped, | ||||||||
tracingStoreClient, | ||||||||
parsedFiles.otherFiles, | ||||||||
usableDataSource, | ||||||||
dataset._id) | ||||||||
(mergedVolumeLayers, earliestAccessibleVersion) <- mergeAndSaveVolumeLayers(newAnnotationId, | ||||||||
volumeLayersGrouped, | ||||||||
tracingStoreClient, | ||||||||
parsedFiles.otherFiles, | ||||||||
usableDataSource, | ||||||||
dataset._id) | ||||||||
mergedSkeletonLayers <- mergeAndSaveSkeletonLayers(skeletonTracings, tracingStoreClient) | ||||||||
annotation <- annotationService.createFrom(request.identity, | ||||||||
dataset, | ||||||||
mergedSkeletonLayers ::: mergedVolumeLayers, | ||||||||
AnnotationType.Explorational, | ||||||||
name, | ||||||||
description, | ||||||||
ObjectId.generate) | ||||||||
newAnnotationId) | ||||||||
annotationProto = AnnotationProto( | ||||||||
description = annotation.description, | ||||||||
version = 0L, | ||||||||
annotationLayers = annotation.annotationLayers.map(_.toProto), | ||||||||
earliestAccessibleVersion = 0L | ||||||||
earliestAccessibleVersion = earliestAccessibleVersion | ||||||||
) | ||||||||
_ <- tracingStoreClient.saveAnnotationProto(annotation._id, annotationProto) | ||||||||
_ <- annotationDAO.insertOne(annotation) | ||||||||
|
@@ -168,32 +168,55 @@ class AnnotationIOController @Inject()( | |||||||
client: WKRemoteTracingStoreClient, | ||||||||
otherFiles: Map[String, File], | ||||||||
dataSource: UsableDataSource, | ||||||||
datasetId: ObjectId): Fox[List[AnnotationLayer]] = | ||||||||
datasetId: ObjectId): Fox[(List[AnnotationLayer], Long)] = | ||||||||
if (volumeLayersGrouped.isEmpty) | ||||||||
Fox.successful(List()) | ||||||||
Fox.successful(List(), 0L) | ||||||||
else if (volumeLayersGrouped.exists(layersOfAnnotation => | ||||||||
layersOfAnnotation.length != layersOfAnnotation.distinctBy(_.tracing.fallbackLayer).length)) | ||||||||
Fox.failure("Cannot save annotation with multiple volume layers that have the same fallback segmentation layer.") | ||||||||
else if (volumeLayersGrouped.length > 1 && volumeLayersGrouped.exists(_.length > 1)) | ||||||||
Fox.failure("Cannot merge multiple annotations that each have multiple volume layers.") | ||||||||
else if (volumeLayersGrouped.length == 1) { // Just one annotation was uploaded, keep its layers separate | ||||||||
Fox.serialCombined(volumeLayersGrouped.toList.flatten.zipWithIndex) { volumeLayerWithIndex => | ||||||||
val uploadedVolumeLayer = volumeLayerWithIndex._1 | ||||||||
val idx = volumeLayerWithIndex._2 | ||||||||
val newTracingId = TracingId.generate | ||||||||
for { | ||||||||
_ <- client.saveVolumeTracing(newAnnotationId, | ||||||||
newTracingId, | ||||||||
uploadedVolumeLayer.tracing, | ||||||||
uploadedVolumeLayer.getDataZipFrom(otherFiles), | ||||||||
dataSource = dataSource, | ||||||||
datasetId = datasetId) | ||||||||
} yield | ||||||||
AnnotationLayer( | ||||||||
newTracingId, | ||||||||
AnnotationLayerType.Volume, | ||||||||
uploadedVolumeLayer.name.getOrElse(AnnotationLayer.defaultVolumeLayerName + idx.toString), | ||||||||
AnnotationLayerStatistics.unknown | ||||||||
) | ||||||||
} | ||||||||
} else { // Multiple annotations with volume layers (but at most one each) was uploaded merge those volume layers into one | ||||||||
else if (volumeLayersGrouped.length > 1 && volumeLayersGrouped.exists( | ||||||||
_.exists(_.editedMappingEdgesLocation.isDefined))) { | ||||||||
Fox.failure("Cannot merge multiple annotations with editable mapping (proofreading) edges.") | ||||||||
} else if (volumeLayersGrouped.length == 1) { // Just one annotation was uploaded, keep its layers separate | ||||||||
var layerUpdatesStartVersionMutable = 1L | ||||||||
for { | ||||||||
annotationLayers <- Fox.serialCombined(volumeLayersGrouped.toList.flatten.zipWithIndex) { | ||||||||
volumeLayerWithIndex => | ||||||||
val uploadedVolumeLayer = volumeLayerWithIndex._1 | ||||||||
val idx = volumeLayerWithIndex._2 | ||||||||
val newTracingId = TracingId.generate | ||||||||
for { | ||||||||
numberOfSavedVersions <- client.saveEditableMappingIfPresent( | ||||||||
newAnnotationId, | ||||||||
newTracingId, | ||||||||
uploadedVolumeLayer.getEditableMappingEdgesZipFrom(otherFiles), | ||||||||
uploadedVolumeLayer.editedMappingBaseMappingName, | ||||||||
startVersion = layerUpdatesStartVersionMutable | ||||||||
) | ||||||||
// The next layer’s update actions then need to start after this one | ||||||||
_ = layerUpdatesStartVersionMutable = layerUpdatesStartVersionMutable + numberOfSavedVersions | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is there an assignment to _? I think this is unnecessary
Suggested change
|
||||||||
mappingName = if (uploadedVolumeLayer.editedMappingEdgesLocation.isDefined) Some(newTracingId) | ||||||||
else uploadedVolumeLayer.tracing.mappingName | ||||||||
_ <- client.saveVolumeTracing( | ||||||||
newAnnotationId, | ||||||||
newTracingId, | ||||||||
uploadedVolumeLayer.tracing.copy(mappingName = mappingName), | ||||||||
uploadedVolumeLayer.getDataZipFrom(otherFiles), | ||||||||
dataSource = dataSource, | ||||||||
datasetId = datasetId | ||||||||
) | ||||||||
} yield | ||||||||
AnnotationLayer( | ||||||||
newTracingId, | ||||||||
AnnotationLayerType.Volume, | ||||||||
uploadedVolumeLayer.name.getOrElse(AnnotationLayer.defaultVolumeLayerName + idx.toString), | ||||||||
AnnotationLayerStatistics.unknown | ||||||||
) | ||||||||
} | ||||||||
} yield (annotationLayers, layerUpdatesStartVersionMutable) | ||||||||
} else { // Multiple annotations with volume layers (but at most one each) was uploaded, they have no editable mappings. merge those volume layers into one | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Grammar / punctuation is a little off in the comment. Maybe something like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why can't there be more than one volume layer per annotation? Is such an upload not supported in general? In that case, my comment above regarding the assertion is wrong. |
||||||||
val uploadedVolumeLayersFlat = volumeLayersGrouped.toList.flatten | ||||||||
val newTracingId = TracingId.generate | ||||||||
for { | ||||||||
|
@@ -206,13 +229,14 @@ class AnnotationIOController @Inject()( | |||||||
uploadedVolumeLayersFlat.map(v => v.getDataZipFrom(otherFiles)) | ||||||||
) | ||||||||
} yield | ||||||||
List( | ||||||||
AnnotationLayer( | ||||||||
newTracingId, | ||||||||
AnnotationLayerType.Volume, | ||||||||
AnnotationLayer.defaultVolumeLayerName, | ||||||||
AnnotationLayerStatistics.unknown | ||||||||
)) | ||||||||
(List( | ||||||||
AnnotationLayer( | ||||||||
newTracingId, | ||||||||
AnnotationLayerType.Volume, | ||||||||
AnnotationLayer.defaultVolumeLayerName, | ||||||||
AnnotationLayerStatistics.unknown | ||||||||
)), | ||||||||
0L) | ||||||||
} | ||||||||
|
||||||||
private def mergeAndSaveSkeletonLayers(skeletonTracings: List[SkeletonTracing], | ||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -91,10 +91,13 @@ class NmlParser @Inject()(datasetDAO: DatasetDAO) | |
segmentGroups = v.segmentGroups, | ||
hasSegmentIndex = None, // Note: this property may be adapted later in adaptPropertiesToFallbackLayer | ||
editPositionAdditionalCoordinates = nmlParams.editPositionAdditionalCoordinates, | ||
additionalAxes = nmlParams.additionalAxisProtos | ||
additionalAxes = nmlParams.additionalAxisProtos, | ||
hasEditableMapping = if (v.editedMappingEdgesLocation.isDefined) Some(true) else None | ||
), | ||
basePath.getOrElse("") + v.dataZipPath, | ||
v.name, | ||
v.editedMappingEdgesLocation.map(location => basePath.getOrElse("") + location), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't this preferably use UPath or so to use a |
||
v.editedMappingBaseMappingName | ||
) | ||
} | ||
skeletonTracing: SkeletonTracing = SkeletonTracing( | ||
|
@@ -220,7 +223,9 @@ class NmlParser @Inject()(datasetDAO: DatasetDAO) | |
getSingleAttributeOpt(node, "name"), | ||
parseVolumeSegmentMetadata(node \ "segments" \ "segment"), | ||
getSingleAttributeOpt(node, "largestSegmentId").flatMap(_.toLongOpt), | ||
extractSegmentGroups(node \ "groups").getOrElse(List()) | ||
extractSegmentGroups(node \ "groups").getOrElse(List()), | ||
getSingleAttributeOpt(node, "editedMappingEdgesLocation"), | ||
getSingleAttributeOpt(node, "editedMappingBaseMappingName") | ||
) | ||
} | ||
) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -167,7 +167,7 @@ const descriptionFns: Record< | |
? `at position ${action.value.segmentPosition1}` | ||
: (action.value.segmentId1 ?? "unknown"); | ||
const segment2Description = | ||
action.value.segmentPosition2 ?? action.value.segmentId1 ?? "unknown"; | ||
action.value.segmentPosition2 ?? action.value.segmentId2 ?? "unknown"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. uff xD, thanks for fixing this |
||
const description = `Split agglomerate ${action.value.agglomerateId} by separating the segments ${segment1Description} and ${segment2Description}.`; | ||
return { | ||
description, | ||
|
@@ -180,7 +180,7 @@ const descriptionFns: Record< | |
? `at position ${action.value.segmentPosition1}` | ||
: (action.value.segmentId1 ?? "unknown"); | ||
const segment2Description = | ||
action.value.segmentPosition2 ?? action.value.segmentId1 ?? "unknown"; | ||
action.value.segmentPosition2 ?? action.value.segmentId2 ?? "unknown"; | ||
const description = `Merged agglomerates ${action.value.agglomerateId1} and ${action.value.agglomerateId2} by combining the segments ${segment1Description} and ${segment2Description}.`; | ||
return { | ||
description, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
### Added | ||
- Editable mapping (aka proofreading) annotations can now be downloaded as zipfile and re-uploaded. |
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 think this assertion here is not correct. What if I upload an annotation with 2 "custom" volume layers where each has no fallback layer? In that case this assertion would fail but the annotation should be correct 🤔