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

Multi-Resolution Volume Tracings #4755

Merged
merged 157 commits into from
Nov 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
157 commits
Select commit Hold shift + click to select a range
429b18b
keep fixed zoom during td rotation to planes
MichaelBuessemeyer Jul 31, 2020
14eb2a1
refactor 3d rotation method to keep the zoom and simplify it
MichaelBuessemeyer Aug 3, 2020
fc278a9
fix position and up vector not getting interpolated correctly
MichaelBuessemeyer Aug 3, 2020
3419287
add changelog entry
MichaelBuessemeyer Aug 3, 2020
39884d4
Merge branch 'master' into keep-zoom-during-td-button-rotation
MichaelBuessemeyer Aug 5, 2020
88ef65b
Apply suggestions from code review
MichaelBuessemeyer Aug 6, 2020
58bd2f9
remove zReductionFactor
MichaelBuessemeyer Aug 6, 2020
a6facc4
Merge branch 'keep-zoom-during-td-button-rotation' of github.com:scal…
MichaelBuessemeyer Aug 6, 2020
59b490c
backend: support anisotropic resolutions in volume bucket keys
fm3 Aug 6, 2020
0298bf4
fix 3d rotation preset
MichaelBuessemeyer Aug 7, 2020
7801896
remove useless check for valid values
MichaelBuessemeyer Aug 7, 2020
50ae8b9
remove reassignment of width and height
MichaelBuessemeyer Aug 10, 2020
a118495
do volume annotation in all resolutions
MichaelBuessemeyer Aug 11, 2020
618b471
Update frontend/javascripts/oxalis/controller/camera_controller.js
MichaelBuessemeyer Aug 11, 2020
0217232
Merge branch 'master' into keep-zoom-during-td-button-rotation
MichaelBuessemeyer Aug 11, 2020
83fee8b
made code pretty
MichaelBuessemeyer Aug 11, 2020
e9591e7
reduce max brush size
MichaelBuessemeyer Aug 11, 2020
3c3abbf
disallow trace tool in higher resolutions
MichaelBuessemeyer Aug 11, 2020
190dc84
Merge branch 'keep-zoom-during-td-button-rotation' into multires-volumes
MichaelBuessemeyer Aug 11, 2020
2003863
enable brushing in high again
MichaelBuessemeyer Aug 11, 2020
2552863
do not block resolution loading
fm3 Aug 12, 2020
1e8c32d
Merge branch 'master' of github.com:scalableminds/webknossos into mul…
MichaelBuessemeyer Aug 12, 2020
283075c
annotate z many slices at once when z resolution is > 1
MichaelBuessemeyer Aug 12, 2020
d60aff3
Merge branch 'master' into multires-volumes
MichaelBuessemeyer Aug 13, 2020
bf81003
fixing a few tests
MichaelBuessemeyer Aug 13, 2020
23b83c0
hopefully fixed all tests
MichaelBuessemeyer Aug 13, 2020
fbf6e55
Merge branch 'multires-volumes' of github.com:scalableminds/webknosso…
MichaelBuessemeyer Aug 13, 2020
eb098be
Merge branch 'master' of github.com:scalableminds/webknossos into mul…
MichaelBuessemeyer Aug 25, 2020
bb715b7
Add info about annotating multiple slices
MichaelBuessemeyer Aug 25, 2020
edfec9c
limit area that gets autofilled
MichaelBuessemeyer Aug 27, 2020
cea260c
Merge branch 'master' of github.com:scalableminds/webknossos into mul…
Aug 28, 2020
81e4459
[WIP] lazy downscaling of volume buckets
Aug 31, 2020
7f21c7f
merge master into multires-volumes
fm3 Sep 2, 2020
8520506
lookup-based live downsampling
fm3 Sep 7, 2020
ee3a989
[WIP] downsample volume tracings on upload
fm3 Sep 7, 2020
5bb3dd0
merge master
fm3 Sep 7, 2020
5380b19
[WIP] downscale during upload
fm3 Sep 7, 2020
fd114f3
fix offsets, switch to mode
fm3 Sep 7, 2020
15ca6b0
determine which mags to downsample
fm3 Sep 8, 2020
b9fb589
adapt nml unit test suite
fm3 Sep 8, 2020
3f9a38b
fix backend dummy tracing
fm3 Sep 8, 2020
5346eae
Merge branch 'master' of github.com:scalableminds/webknossos into mul…
MichaelBuessemeyer Sep 8, 2020
07e2a0a
move function to get number of slices to accessor
MichaelBuessemeyer Sep 9, 2020
bd335e1
WIP: applying flood fill to all resolutions
MichaelBuessemeyer Sep 9, 2020
4d1ece0
[WIP] track mags in volumetracing object
fm3 Sep 10, 2020
e511e65
fix calculating error during downsampling
MichaelBuessemeyer Sep 10, 2020
3cdabfb
fix flood fill for all source resolutions
MichaelBuessemeyer Sep 10, 2020
cedb9b4
Merge branch 'multires-volumes' of github.com:scalableminds/webknosso…
MichaelBuessemeyer Sep 10, 2020
3751541
fixed flood fill for all resolutions
MichaelBuessemeyer Sep 10, 2020
52f28f2
handle differing resolutions during volume merging + upload
fm3 Sep 11, 2020
8f0dfb9
Merge branch 'multires-volumes' of github.com:scalableminds/webknosso…
fm3 Sep 11, 2020
387b0db
add up and downsampling of LabeledVoxelsMap
MichaelBuessemeyer Sep 11, 2020
f6d71a5
Merge branch 'multires-volumes' of github.com:scalableminds/webknosso…
MichaelBuessemeyer Sep 11, 2020
7192375
add unlinkFallback route
fm3 Sep 14, 2020
a662d0f
changelog
fm3 Sep 14, 2020
04cb83e
cleanup backend code
fm3 Sep 14, 2020
3dfd131
fixed up and downsampling and added tests
MichaelBuessemeyer Sep 14, 2020
17172a2
Merge branch 'multires-volumes' of github.com:scalableminds/webknosso…
MichaelBuessemeyer Sep 14, 2020
163da04
added method to apply a voxel map
MichaelBuessemeyer Sep 14, 2020
0f009a6
fixed upsampling and added regression test
MichaelBuessemeyer Sep 14, 2020
e58fafb
add comments to sampling methods
MichaelBuessemeyer Sep 14, 2020
21d2428
make copylayer work in multi resolutions
MichaelBuessemeyer Sep 14, 2020
8ae88ba
while upsampling annotate mutliple slices
MichaelBuessemeyer Sep 14, 2020
bf65a24
Add todo about refactoring labeling voxels
MichaelBuessemeyer Sep 15, 2020
4b5adae
adjusted voxel labeling method to label in all resolutions the segmen…
MichaelBuessemeyer Sep 15, 2020
97676a2
added some comments with todos
MichaelBuessemeyer Sep 15, 2020
bc8e97e
Update frontend/javascripts/oxalis/model/accessors/volumetracing_acce…
philippotto Sep 23, 2020
14c1b95
always label in all resolutions when using api; show stack-icon when …
philippotto Sep 23, 2020
cb26599
Merge branch 'multires-volumes' of github.com:scalableminds/webknosso…
philippotto Sep 23, 2020
367810f
more comments
philippotto Sep 23, 2020
13eefc2
replace old unlinkFallbackLayer with new API for that (keep old Updat…
philippotto Sep 23, 2020
120a588
fix wrong parameter format
philippotto Sep 24, 2020
0e922ef
refactor resolution handling to deal with sparse resolutions better (…
philippotto Sep 24, 2020
c086353
undo temporary new_resolutions change
philippotto Sep 24, 2020
56a229d
continue refactoring resolution handling to deal with sparse resoluti…
philippotto Sep 25, 2020
dfdd944
fix picking segment color when being in a not-existing segmentation mag
philippotto Sep 25, 2020
0f6699a
ensure that prefetch saga, bucket picker and pull queue don't try to …
philippotto Sep 25, 2020
3bccd0e
ensure legacy getResolutions method provides dense resolution set; cl…
philippotto Sep 25, 2020
f5c6160
fix initialization and volume annotation sampling spec
philippotto Sep 25, 2020
af7fc16
fix CI
philippotto Sep 25, 2020
f1f6eb9
update snapshots
philippotto Sep 25, 2020
ff1a4de
tune warning text
philippotto Sep 28, 2020
4074ea8
make merger mode work in higher resolutions
philippotto Sep 28, 2020
b293c2a
show a status indicator in the viewports if a layer cannot be rendere…
philippotto Sep 29, 2020
4005e7d
reduce tooltip rerenderings by making styles constant
philippotto Sep 29, 2020
b6442cd
fix enabled 'Render Missing Data Black' for missing mags
philippotto Sep 29, 2020
adc1c94
add issue links to todo comments
philippotto Sep 29, 2020
1e2a474
implement some feedback
philippotto Sep 30, 2020
b090643
Apply suggestions from code review
philippotto Sep 30, 2020
1b888e0
more PR feedback
philippotto Sep 30, 2020
2e831b3
Merge branch 'multires-volumes' of github.com:scalableminds/webknosso…
philippotto Sep 30, 2020
12e785f
merge master with backend files
Sep 30, 2020
ebc10aa
also implement getIndexOrClosestHigherIndex for ResolutionInfo and us…
philippotto Sep 30, 2020
f16777e
return true in isVolumeTraceToolDisallowed if no volume tracing exists
philippotto Sep 30, 2020
3fe1160
fix front-end merge conflicts
philippotto Sep 30, 2020
87d61e0
Merge branch 'multires-volume-merge' into multires-volumes
philippotto Sep 30, 2020
74aa5fd
reduce usages of getResolutionByIndexWithFallback and make that funct…
philippotto Sep 30, 2020
a5e7987
simplify is2DVoxelInsideBucket method in Bucket
philippotto Sep 30, 2020
717fe2e
Apply suggestions from code review
philippotto Oct 2, 2020
9bad842
integrate more PR feedback; resolve merge conflict in changelog; rena…
philippotto Oct 2, 2020
55b6941
Merge branch 'multires-volumes' of github.com:scalableminds/webknosso…
philippotto Oct 2, 2020
d01cace
refactor applyLabeledVoxelMapToAllMissingResolutions
philippotto Oct 2, 2020
a313fc3
further refactoring of applyLabeledVoxelMapToAllMissingResolutions
philippotto Oct 2, 2020
125b329
Merge branch 'master' of github.com:scalableminds/webknossos into mul…
philippotto Oct 2, 2020
043af12
remove unused import
philippotto Oct 2, 2020
c91432c
fix flow after upgrade
philippotto Oct 2, 2020
f5b62be
improve comment for LabeledVoxelsMap
philippotto Oct 2, 2020
6cd2187
fix uniform definion
philippotto Oct 2, 2020
942c4ba
fix getDataValue for missing resolution
philippotto Oct 2, 2020
3c9f4fa
Merge branch 'master' into multires-volumes
philippotto Oct 6, 2020
a216729
Improve performance of volume annotation tools (#4848)
philippotto Oct 7, 2020
01d8061
ensure that rendered volume magnification is also the mag in which is
philippotto Oct 7, 2020
9cfc522
Update frontend/javascripts/oxalis/model/sagas/volumetracing_saga.js
philippotto Oct 7, 2020
0f0c74e
Resolve Merge Conflicts and Merge branch 'master' of github.com:scala…
philippotto Oct 7, 2020
185b5d9
fix issues from merging master
philippotto Oct 7, 2020
2b329ce
Merge branch 'multires-volumes' of github.com:scalableminds/webknosso…
philippotto Oct 7, 2020
e4d22fa
fix upload/download
fm3 Oct 7, 2020
2826d71
Merge branch 'multires-volumes' of github.com:scalableminds/webknosso…
fm3 Oct 7, 2020
b662143
fix issues after merge
fm3 Oct 7, 2020
35dd31e
disable continuous drawing for now since its performance needs to be …
philippotto Oct 7, 2020
bc97327
Merge branch 'multires-volumes' of github.com:scalableminds/webknosso…
philippotto Oct 7, 2020
b5ceaed
fix linting
philippotto Oct 7, 2020
0d11203
adapt headline in import modal
philippotto Oct 7, 2020
7b5831b
change tracing to annotation
philippotto Oct 7, 2020
b6fb784
change magnification to resolution in user-facing strings and some in…
philippotto Oct 7, 2020
8c9d8e6
make resolution-warning less verbose
philippotto Oct 7, 2020
0893310
try to fix e.trigger is not a function
philippotto Oct 7, 2020
4abf801
fix linting
philippotto Oct 7, 2020
b739cee
fix bug in applyLabeledVoxelMap
philippotto Oct 7, 2020
b724847
fix flow
philippotto Oct 7, 2020
74fc763
show fallback-not-included warning only when there is fallback data
philippotto Oct 7, 2020
2d8c9db
fix anisotropic bucket adresses
fm3 Oct 8, 2020
43efca6
treat empty resolution list as no resolution list
fm3 Oct 8, 2020
b69d062
change Boolean() to != null
philippotto Oct 8, 2020
20e10fd
fix flow in model initialization
philippotto Oct 8, 2020
76f0e51
ensure volume layer is saved before reloading; fixes #4857
philippotto Oct 8, 2020
a3785b2
format
philippotto Oct 8, 2020
1a34d50
disable copy-segmentation feature for higher mags due to performance
philippotto Oct 8, 2020
89a3cfb
merge master
fm3 Oct 8, 2020
bd78caa
merge master
fm3 Oct 19, 2020
6038a9f
Merge branch 'master' into multires-volumes
philippotto Oct 22, 2020
b61904b
Merge branch 'master' of github.com:scalableminds/webknossos into mul…
philippotto Oct 22, 2020
9f7ef92
fix some merge-related problems
philippotto Oct 22, 2020
30728fe
fix styling of multi-slice-icon
philippotto Oct 23, 2020
d06143f
throw an exception if the resolution could not be looked up instead o…
philippotto Oct 23, 2020
675e74e
look up volume bucket resolution by zoom step ** 2 rather than index
fm3 Oct 23, 2020
1d3a980
merge
fm3 Oct 23, 2020
ba4772a
fix that toolbar rerendered on every state change
philippotto Oct 23, 2020
13224ed
improve handling of volume-is-disabled case in toolbar
philippotto Oct 23, 2020
c22f8ca
Merge branch 'multires-volumes' of github.com:scalableminds/webknosso…
philippotto Oct 23, 2020
afe796a
replace exception by fox.failure if volume resolution lookup fails
fm3 Oct 26, 2020
1d963a2
show data type and resolutions of layer in tooltip next to layer name…
philippotto Oct 26, 2020
2551a4f
Merge branch 'multires-volumes' of github.com:scalableminds/webknosso…
philippotto Oct 26, 2020
03bd51a
Merge branch 'master' of github.com:scalableminds/webknossos into mul…
philippotto Nov 3, 2020
8370cfe
fix syntax error
philippotto Nov 3, 2020
302ce06
Merge branch 'master' into multires-volumes
fm3 Nov 5, 2020
c9e7531
Enforce TaskType Resolution Restrictions for Multi-Res Volume Tasks (…
fm3 Nov 5, 2020
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
3 changes: 3 additions & 0 deletions CHANGELOG.unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.released
- The total length of skeletons can now be measured using the dropdown in the tree list tab. Also, the frontend API received the methods `api.tracing.measureTreeLength` and `api.tracing.measureAllTrees`. [#4898](https://github.com/scalableminds/webknossos/pull/4898)
- Introduced an indeterminate visibility state for groups in the tree tab if not all but only some of the group's children are visible. Before, the visibility of those groups was shown as not visible which made it hard to find the visible trees. [#4897](https://github.com/scalableminds/webknossos/pull/4897)
- Dataset uploads on a specific Datastore can now be restricted to a single organization. [#4892](https://github.com/scalableminds/webknossos/pull/4892)
- Added multi-resolution volume annotations. Note that already existing volume tracings will still only contain data in the first magnification. If you want to migrate an old volume tracing, you can download and re-import it. [#4755](https://github.com/scalableminds/webknossos/pull/4755)

### Changed
- In the tree tab, all groups but the root group are now collapsed instead of expanded when opening a tracing. [#4897](https://github.com/scalableminds/webknossos/pull/4897)
- New volume/hybrid annotations are now automatically multi-resolution volume annotations. [#4755](https://github.com/scalableminds/webknossos/pull/4755)
- Improved performance of volume annotations (brush and trace tool). [#4848](https://github.com/scalableminds/webknossos/pull/4848)

### Fixed
- Fixed the disappearing of dataset settings after switching between view mode and annotation mode. [#4845](https://github.com/scalableminds/webknossos/pull/4845)
Expand Down
8 changes: 7 additions & 1 deletion MIGRATIONS.unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@ This project adheres to [Calendar Versioning](http://calver.org/) `0Y.0M.MICRO`.
User-facing changes are documented in the [changelog](CHANGELOG.released.md).

## Unreleased
-
- As volume annotations in arbitrary magnifications are now supported and the behavior of magnification restrictions of tasks has changed (allow full zoom, but disable tools unless in correct magnification), you may want to restrict all volume and hybrid task types to mag 1 to achieve the old behavior (mag1-only):
```
update webknossos.tasktypes
set settings_allowedmagnifications = '{"min":1,"max":1,"shouldRestrict":true}'
where (tracingtype = 'volume' or tracingtype = 'hybrid')
and (settings_allowedmagnifications is null or settings_allowedmagnifications::json->>'shouldRestrict'='false');
```

### Postgres Evolutions:
- [057-add-layer-specific-view-configs.sql](conf/evolutions/056-add-layer-specific-view-configs.sql)
Expand Down
31 changes: 30 additions & 1 deletion app/controllers/AnnotationController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -166,14 +166,43 @@ class AnnotationController @Inject()(
for {
_ <- bool2Fox(AnnotationType.Explorational.toString == typ) ?~> "annotation.makeHybrid.explorationalsOnly"
annotation <- provider.provideAnnotation(typ, id, request.identity)
_ <- annotationService.makeAnnotationHybrid(annotation) ?~> "annotation.makeHybrid.failed"
organization <- organizationDAO.findOne(request.identity._organization)
_ <- annotationService.makeAnnotationHybrid(annotation, organization.name) ?~> "annotation.makeHybrid.failed"
updated <- provider.provideAnnotation(typ, id, request.identity)
json <- annotationService.publicWrites(updated, Some(request.identity)) ?~> "annotation.write.failed"
} yield {
JsonOk(json)
}
}

def downsample(typ: String, id: String) = sil.SecuredAction.async { implicit request =>
for {
_ <- bool2Fox(AnnotationType.Explorational.toString == typ) ?~> "annotation.downsample.explorationalsOnly"
annotation <- provider.provideAnnotation(typ, id, request.identity)
_ <- annotationService.downsampleAnnotation(annotation) ?~> "annotation.downsample.failed"
updated <- provider.provideAnnotation(typ, id, request.identity)
json <- annotationService.publicWrites(updated, Some(request.identity)) ?~> "annotation.write.failed"
} yield {
JsonOk(json)
}
}

def unlinkFallback(typ: String, id: String) = sil.SecuredAction.async { implicit request =>
for {
_ <- bool2Fox(AnnotationType.Explorational.toString == typ) ?~> "annotation.unlinkFallback.explorationalsOnly"
annotation <- provider.provideAnnotation(typ, id, request.identity)
volumeTracingId <- annotation.volumeTracingId.toFox ?~> "annotation.unlinkFallback.noVolume"
dataSet <- dataSetDAO
.findOne(annotation._dataSet)(GlobalAccessContext) ?~> "dataSet.notFoundForAnnotation" ~> NOT_FOUND
dataSource <- dataSetService.dataSourceFor(dataSet).flatMap(_.toUsable) ?~> "dataSet.notImported"
tracingStoreClient <- tracingStoreService.clientFor(dataSet)
newTracingId <- tracingStoreClient.unlinkFallback(volumeTracingId, dataSource)
_ <- annotationDAO.updateVolumeTracingId(annotation._id, newTracingId)
updatedAnnotation <- provider.provideAnnotation(typ, id, request.identity)
js <- annotationService.publicWrites(updatedAnnotation, Some(request.identity))
} yield JsonOk(js)
}

private def finishAnnotation(typ: String, id: String, issuingUser: User, timestamp: Long)(
implicit ctx: DBAccessContext): Fox[(Annotation, String)] =
for {
Expand Down
27 changes: 13 additions & 14 deletions app/controllers/AnnotationIOController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,7 @@ class AnnotationIOController @Inject()(nmlWriter: NmlWriter,

for {
_ <- bool2Fox(skeletonTracings.nonEmpty || volumeTracingsWithDataLocations.nonEmpty) ?~> "nml.file.noFile"
dataSet <- findDataSetForUploadedAnnotations(skeletonTracings,
volumeTracingsWithDataLocations.map(_._1),
parseSuccesses)
dataSet <- findDataSetForUploadedAnnotations(skeletonTracings, volumeTracingsWithDataLocations.map(_._1))
tracingStoreClient <- tracingStoreService.clientFor(dataSet)
mergedVolumeTracingIdOpt <- Fox.runOptional(volumeTracingsWithDataLocations.headOption) { _ =>
for {
Expand Down Expand Up @@ -120,11 +118,10 @@ class AnnotationIOController @Inject()(nmlWriter: NmlWriter,

private def findDataSetForUploadedAnnotations(
skeletonTracings: List[SkeletonTracing],
volumeTracings: List[VolumeTracing],
parseSuccesses: List[NmlParseResult])(implicit mp: MessagesProvider, ctx: DBAccessContext): Fox[DataSet] =
volumeTracings: List[VolumeTracing])(implicit mp: MessagesProvider, ctx: DBAccessContext): Fox[DataSet] =
for {
dataSetName <- assertAllOnSameDataSet(skeletonTracings, volumeTracings) ?~> "nml.file.differentDatasets"
organizationNameOpt <- assertAllOnSameOrganization(parseSuccesses.flatMap(s => s.organizationName)) ?~> "nml.file.differentDatasets"
organizationNameOpt <- assertAllOnSameOrganization(skeletonTracings, volumeTracings) ?~> "nml.file.differentDatasets"
organizationIdOpt <- Fox.runOptional(organizationNameOpt) {
organizationDAO.findOneByName(_)(GlobalAccessContext).map(_._id)
} ?~> Messages("organization.notFound", organizationNameOpt.getOrElse("")) ~> NOT_FOUND
Expand Down Expand Up @@ -172,14 +169,16 @@ class AnnotationIOController @Inject()(nmlWriter: NmlWriter,
_ <- bool2Fox(volumes.forall(_.dataSetName == dataSetName))
} yield dataSetName

private def assertAllOnSameOrganization(organizationNames: List[String]): Fox[Option[String]] =
if (organizationNames.isEmpty) Fox.successful(None)
else {
for {
organizationName <- organizationNames.headOption.toFox
_ <- bool2Fox(organizationNames.forall(name => name == organizationName))
} yield Some(organizationName)
}
private def assertAllOnSameOrganization(skeletons: List[SkeletonTracing],
volumes: List[VolumeTracing]): Fox[Option[String]] =
for {
organizationName: Option[String] <- volumes.headOption
.map(_.organizationName)
.orElse(skeletons.headOption.map(_.organizationName))
.toFox
_ <- bool2Fox(skeletons.forall(_.organizationName == organizationName))
_ <- bool2Fox(volumes.forall(_.organizationName == organizationName))
} yield organizationName

private def adaptPropertiesToFallbackLayer(volumeTracing: VolumeTracing, dataSet: DataSet)(
implicit ctx: DBAccessContext): Fox[VolumeTracing] =
Expand Down
75 changes: 49 additions & 26 deletions app/controllers/TaskController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ import com.scalableminds.util.geometry.{BoundingBox, Point3D, Vector3D}
import com.scalableminds.util.mvc.ResultBox
import com.scalableminds.util.tools.{Fox, FoxImplicits, JsonHelper}
import com.scalableminds.webknossos.tracingstore.SkeletonTracing.{SkeletonTracing, SkeletonTracingOpt, SkeletonTracings}
import com.scalableminds.webknossos.tracingstore.VolumeTracing.{VolumeTracing, VolumeTracingOpt, VolumeTracings}
import com.scalableminds.webknossos.tracingstore.VolumeTracing.VolumeTracing
import com.scalableminds.webknossos.tracingstore.tracings.volume.ResolutionRestrictions
import com.scalableminds.webknossos.tracingstore.tracings.{ProtoGeometryImplicits, TracingType}
import javax.inject.Inject
import models.annotation.nml.NmlResults.NmlParseResult
import models.annotation.nml.NmlService
import models.annotation._
import models.binary.{DataSet, DataSetDAO, DataSetService}
import models.binary.{DataSet, DataSetDAO}
import models.project.{Project, ProjectDAO}
import models.task._
import models.team.{Team, TeamDAO}
Expand Down Expand Up @@ -74,7 +74,6 @@ class TaskController @Inject()(annotationDAO: AnnotationDAO,
dataSetDAO: DataSetDAO,
userTeamRolesDAO: UserTeamRolesDAO,
userService: UserService,
dataSetService: DataSetService,
tracingStoreService: TracingStoreService,
teamDAO: TeamDAO,
taskDAO: TaskDAO,
Expand All @@ -88,7 +87,7 @@ class TaskController @Inject()(annotationDAO: AnnotationDAO,
with ProtoGeometryImplicits
with FoxImplicits {

val MAX_OPEN_TASKS = conf.WebKnossos.Tasks.maxOpenPerUser
private val MAX_OPEN_TASKS: Int = conf.WebKnossos.Tasks.maxOpenPerUser

def read(taskId: String) = sil.SecuredAction.async { implicit request =>
for {
Expand All @@ -114,8 +113,9 @@ class TaskController @Inject()(annotationDAO: AnnotationDAO,
} yield result
}

def duplicateAllBaseTracings(taskParametersList: List[TaskParameters],
organizationId: ObjectId)(implicit ctx: DBAccessContext, m: MessagesProvider) =
private def duplicateAllBaseTracings(taskParametersList: List[TaskParameters], organizationId: ObjectId)(
implicit ctx: DBAccessContext,
m: MessagesProvider): Fox[List[TaskParameters]] =
Fox.serialCombined(taskParametersList)(
params =>
Fox
Expand All @@ -141,9 +141,10 @@ class TaskController @Inject()(annotationDAO: AnnotationDAO,
annotation: Annotation,
params: TaskParameters,
tracingStoreClient: TracingStoreRpcClient,
organizationId: ObjectId)(implicit ctx: DBAccessContext, m: MessagesProvider): Fox[String] =
organizationId: ObjectId,
resolutionRestrictions: ResolutionRestrictions)(implicit ctx: DBAccessContext, m: MessagesProvider): Fox[String] =
annotation.volumeTracingId
.map(id => tracingStoreClient.duplicateVolumeTracing(id))
.map(id => tracingStoreClient.duplicateVolumeTracing(id, resolutionRestrictions = resolutionRestrictions))
.getOrElse(
annotationService
.createVolumeTracingBase(
Expand All @@ -152,13 +153,15 @@ class TaskController @Inject()(annotationDAO: AnnotationDAO,
params.boundingBox,
params.editPosition,
params.editRotation,
false
volumeShowFallbackLayer = false,
resolutionRestrictions = resolutionRestrictions
)
.flatMap(tracingStoreClient.saveVolumeTracing(_)))
.flatMap(tracingStoreClient.saveVolumeTracing(_, resolutionRestrictions = resolutionRestrictions)))

def duplicateBaseTracings(baseAnnotation: BaseAnnotation, taskParameters: TaskParameters, organizationId: ObjectId)(
implicit ctx: DBAccessContext,
m: MessagesProvider) = {
private def duplicateBaseTracings(
baseAnnotation: BaseAnnotation,
taskParameters: TaskParameters,
organizationId: ObjectId)(implicit ctx: DBAccessContext, m: MessagesProvider): Fox[BaseAnnotation] = {

@SuppressWarnings(Array("TraversableHead")) // We check if nonCancelledTaskAnnotations are empty before so head always works
def checkForTask(taskId: ObjectId): Fox[Annotation] =
Expand Down Expand Up @@ -196,13 +199,16 @@ class TaskController @Inject()(annotationDAO: AnnotationDAO,
duplicateSkeletonTracingOrCreateSkeletonTracingBase(annotation, taskParameters, tracingStoreClient).map(Some(_))
else Fox.successful(None)
newVolumeId <- if (taskType.tracingType == TracingType.volume || taskType.tracingType == TracingType.hybrid)
duplicateVolumeTracingOrCreateVolumeTracingBase(annotation, taskParameters, tracingStoreClient, organizationId)
.map(Some(_))
duplicateVolumeTracingOrCreateVolumeTracingBase(annotation,
taskParameters,
tracingStoreClient,
organizationId,
taskType.settings.resolutionRestrictions).map(Some(_))
else Fox.successful(None)
} yield BaseAnnotation(baseAnnotationIdValidated.id, newSkeletonId, newVolumeId)
}

def createTaskSkeletonTracingBases(paramsList: List[TaskParameters])(
private def createTaskSkeletonTracingBases(paramsList: List[TaskParameters])(
implicit ctx: DBAccessContext,
m: MessagesProvider): Fox[List[Option[SkeletonTracing]]] =
Fox.serialCombined(paramsList) { params =>
Expand All @@ -221,7 +227,7 @@ class TaskController @Inject()(annotationDAO: AnnotationDAO,
} yield skeletonTracingOpt
}

def createTaskVolumeTracingBases(paramsList: List[TaskParameters], organizationId: ObjectId)(
private def createTaskVolumeTracingBases(paramsList: List[TaskParameters], organizationId: ObjectId)(
implicit ctx: DBAccessContext,
m: MessagesProvider): Fox[List[Option[(VolumeTracing, Option[File])]]] =
Fox.serialCombined(paramsList) { params =>
Expand All @@ -236,7 +242,8 @@ class TaskController @Inject()(annotationDAO: AnnotationDAO,
params.boundingBox,
params.editPosition,
params.editRotation,
volumeShowFallbackLayer = false
volumeShowFallbackLayer = false,
resolutionRestrictions = taskType.settings.resolutionRestrictions
)
.map(v => Some((v, None)))
} else Fox.successful(None)
Expand Down Expand Up @@ -296,7 +303,8 @@ class TaskController @Inject()(annotationDAO: AnnotationDAO,
params.boundingBox,
params.editPosition,
params.editRotation,
volumeShowFallbackLayer = false
volumeShowFallbackLayer = false,
resolutionRestrictions = taskType.settings.resolutionRestrictions
)
.map(v => (v, None)))

Expand Down Expand Up @@ -449,6 +457,7 @@ class TaskController @Inject()(annotationDAO: AnnotationDAO,
bool2Fox(fullTasks.forall(tuple => tuple._1.baseAnnotation.isDefined || tuple._2.isDefined || tuple._3.isDefined))

def assertAllOnSameDataset(firstDatasetName: String): Fox[String] = {
@scala.annotation.tailrec
def allOnSameDatasetIter(
requestedTasksRest: List[(TaskParameters, Option[SkeletonTracing], Option[(VolumeTracing, Option[File])])],
dataSetName: String): Boolean =
Expand Down Expand Up @@ -490,12 +499,8 @@ class TaskController @Inject()(annotationDAO: AnnotationDAO,
case _ => savedId
}
}
volumeTracingIds: List[Box[Option[String]]] <- Fox.sequence(requestedTasks.map(_.map(_._3)).map {
case Full(Some((tracing, initialFile))) =>
tracingStoreClient.saveVolumeTracing(tracing, initialFile).map(Some(_))
case f: Failure => box2Fox(f)
case _ => Fox.successful(None)
})
volumeTracingIds: List[Box[Option[String]]] <- Fox.sequence(
requestedTasks.map(requestedTask => saveVolumeTracingIfPresent(requestedTask, tracingStoreClient)))
skeletonTracingsIdsMerged = mergeTracingIds((requestedTasks.map(_.map(_._1)), skeletonTracingIds).zipped.toList,
isSkeletonId = true)
volumeTracingsIdsMerged = mergeTracingIds((requestedTasks.map(_.map(_._1)), volumeTracingIds).zipped.toList,
Expand Down Expand Up @@ -526,6 +531,24 @@ class TaskController @Inject()(annotationDAO: AnnotationDAO,
} yield Ok(Json.toJson(result))
}

private def saveVolumeTracingIfPresent(
requestedTaskBox: Box[(TaskParameters, Option[SkeletonTracing], Option[(VolumeTracing, Option[File])])],
tracingStoreClient: TracingStoreRpcClient)(implicit ctx: DBAccessContext): Fox[Option[String]] =
requestedTaskBox.map { tuple =>
(tuple._1, tuple._3)
} match {
case Full((params: TaskParameters, Some((tracing, initialFile)))) =>
for {
taskTypeIdValidated <- ObjectId.parse(params.taskTypeId) ?~> "taskType.id.invalid"
taskType <- taskTypeDAO.findOne(taskTypeIdValidated) ?~> "taskType.notFound"
saveResult <- tracingStoreClient
.saveVolumeTracing(tracing, initialFile, resolutionRestrictions = taskType.settings.resolutionRestrictions)
.map(Some(_))
} yield saveResult
case f: Failure => box2Fox(f)
case _ => Fox.successful(None)
}

private def warnIfTeamHasNoAccess(requestedTasks: List[TaskParameters], dataSet: DataSet)(
implicit ctx: DBAccessContext): Fox[List[String]] = {
val projectNames = requestedTasks.map(_.projectName).distinct
Expand Down
1 change: 1 addition & 0 deletions app/controllers/TaskTypeController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class TaskTypeController @Inject()(taskTypeDAO: TaskTypeDAO,
taskTypeIdValidated <- ObjectId.parse(taskTypeId) ?~> "taskType.id.invalid"
taskType <- taskTypeDAO.findOne(taskTypeIdValidated) ?~> "taskType.notFound" ~> NOT_FOUND
_ <- bool2Fox(taskTypeFromForm.tracingType == taskType.tracingType) ?~> "taskType.tracingTypeImmutable"
_ <- bool2Fox(taskTypeFromForm.settings.allowedMagnifications == taskType.settings.allowedMagnifications) ?~> "taskType.allowedMagnificationsImmutable"
updatedTaskType = taskTypeFromForm.copy(_id = taskType._id)
_ <- Fox.assertTrue(userService.isTeamManagerOrAdminOf(request.identity, taskType._team)) ?~> "notAllowed" ~> FORBIDDEN
_ <- Fox
Expand Down
1 change: 1 addition & 0 deletions app/controllers/TracingStoreController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,5 @@ class TracingStoreController @Inject()(tracingStoreService: TracingStoreService,
} yield { Ok(Json.toJson(js)) }
}
}

}
Loading