Skip to content

Commit cc0509d

Browse files
authored
Merge branch 'master' into s3-upload
2 parents 631bc4a + d907f38 commit cc0509d

File tree

23 files changed

+76
-51
lines changed

23 files changed

+76
-51
lines changed

app/controllers/AnnotationController.scala

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -276,17 +276,6 @@ class AnnotationController @Inject()(
276276
} yield JsonOk(Messages("annotation.edit.success"))
277277
}
278278

279-
def editAnnotationLayer(typ: String, id: ObjectId, tracingId: String): Action[JsValue] =
280-
sil.SecuredAction.async(parse.json) { implicit request =>
281-
for {
282-
annotation <- provider.provideAnnotation(typ, id, request.identity) ~> NOT_FOUND
283-
restrictions <- provider.restrictionsFor(typ, id) ?~> "restrictions.notFound" ~> NOT_FOUND
284-
_ <- restrictions.allowUpdate(request.identity) ?~> "notAllowed" ~> FORBIDDEN
285-
newLayerName = (request.body \ "name").as[String]
286-
_ <- annotationLayerDAO.updateName(annotation._id, tracingId, newLayerName) ?~> "annotation.edit.failed"
287-
} yield JsonOk(Messages("annotation.edit.success"))
288-
}
289-
290279
def annotationsForTask(taskId: ObjectId): Action[AnyContent] =
291280
sil.SecuredAction.async { implicit request =>
292281
for {

app/controllers/WKRemoteTracingStoreController.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,11 @@ class WKRemoteTracingStoreController @Inject()(tracingStoreService: TracingStore
6161
layerIdsToUpdate = existingLayerIds.intersect(newLayerIds)
6262
layerIdsToInsert = newLayerIds.diff(existingLayerIds)
6363
_ <- Fox.serialCombined(layerIdsToDelete.toList)(annotationLayerDAO.deleteOneByTracingId(annotationId, _))
64-
_ <- Fox.serialCombined(newLayersProto.filter(l => layerIdsToInsert.contains(l.tracingId))) { layerProto =>
65-
annotationLayerDAO.insertOne(annotationId, AnnotationLayer.fromProto(layerProto))
66-
}
67-
_ <- Fox.serialCombined(newLayersProto.filter(l => layerIdsToUpdate.contains(l.tracingId)))(l =>
68-
annotationLayerDAO.updateName(annotationId, l.tracingId, l.name))
64+
_ <- annotationLayerDAO.updateLayers(
65+
annotationId,
66+
newLayersProto.filter(l => layerIdsToInsert.contains(l.tracingId)).map(AnnotationLayer.fromProto),
67+
newLayersProto.filter(l => layerIdsToUpdate.contains(l.tracingId)).map(AnnotationLayer.fromProto)
68+
)
6969
// Layer stats are ignored here, they are sent eagerly when saving updates
7070
_ <- annotationDAO.updateDescription(annotationId, request.body.description)
7171
} yield Ok

app/models/annotation/Annotation.scala

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import slick.jdbc.TransactionIsolation.Serializable
1616
import slick.lifted.Rep
1717
import slick.sql.SqlAction
1818
import com.scalableminds.util.objectid.ObjectId
19+
import slick.dbio.DBIO
1920
import utils.sql.{SQLDAO, SimpleSQLDAO, SqlClient, SqlToken}
2021

2122
import javax.inject.Inject
@@ -131,8 +132,7 @@ class AnnotationLayerDAO @Inject()(SQLClient: SqlClient)(implicit ec: ExecutionC
131132
_ <- run(insertOneQuery(annotationId, annotationLayer))
132133
} yield ()
133134

134-
def insertLayerQueries(annotationId: ObjectId,
135-
layers: List[AnnotationLayer]): List[SqlAction[Int, NoStream, Effect]] =
135+
def insertLayerQueries(annotationId: ObjectId, layers: Seq[AnnotationLayer]): Seq[SqlAction[Int, NoStream, Effect]] =
136136
layers.map { annotationLayer =>
137137
insertOneQuery(annotationId, annotationLayer)
138138
}
@@ -161,13 +161,20 @@ class AnnotationLayerDAO @Inject()(SQLClient: SqlClient)(implicit ec: ExecutionC
161161
head <- rList.headOption.toFox
162162
} yield head
163163

164-
def updateName(annotationId: ObjectId, tracingId: String, newName: String): Fox[Unit] =
164+
def updateLayers(annotationId: ObjectId,
165+
newLayers: Seq[AnnotationLayer],
166+
updatedLayers: Seq[AnnotationLayer]): Fox[Unit] = {
167+
val insertQueries = insertLayerQueries(annotationId, newLayers)
168+
val updateQueries = updatedLayers.map { updatedLayer =>
169+
q"""UPDATE webknossos.annotation_layers
170+
SET name = ${updatedLayer.name}
171+
WHERE _annotation = $annotationId
172+
AND tracingId = ${updatedLayer.tracingId}""".asUpdate
173+
}
165174
for {
166-
_ <- run(q"""UPDATE webknossos.annotation_layers
167-
SET name = $newName
168-
WHERE _annotation = $annotationId
169-
AND tracingId = $tracingId""".asUpdate)
175+
_ <- run(DBIO.sequence(insertQueries ++ updateQueries).transactionally)
170176
} yield ()
177+
}
171178

172179
def deleteAllForAnnotationQuery(annotationId: ObjectId): SqlAction[Int, NoStream, Effect] =
173180
q"DELETE FROM webknossos.annotation_layers WHERE _annotation = $annotationId".asUpdate
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
START TRANSACTION;
2+
3+
do $$ begin ASSERT (select schemaVersion from webknossos.releaseInformation) = 139, 'Previous schema version mismatch'; end; $$ LANGUAGE plpgsql;
4+
5+
ALTER TABLE webknossos.annotation_layers DROP CONSTRAINT annotation_layers_name__annotation_key;
6+
ALTER TABLE webknossos.annotation_layers ADD CONSTRAINT annotation_layers_name__annotation_key UNIQUE (name, _annotation) DEFERRABLE INITIALLY DEFERRED;
7+
8+
UPDATE webknossos.releaseInformation SET schemaVersion = 140;
9+
10+
COMMIT TRANSACTION;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
START TRANSACTION;
2+
3+
do $$ begin ASSERT (select schemaVersion from webknossos.releaseInformation) = 140, 'Previous schema version mismatch'; end; $$ LANGUAGE plpgsql;
4+
5+
ALTER TABLE webknossos.annotation_layers DROP CONSTRAINT annotation_layers_name__annotation_key;
6+
ALTER TABLE webknossos.annotation_layers ADD CONSTRAINT annotation_layers_name__annotation_key UNIQUE (name, _annotation);
7+
8+
UPDATE webknossos.releaseInformation SET schemaVersion = 139;
9+
10+
COMMIT TRANSACTION;

conf/webknossos.latest.routes

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,6 @@ POST /userToken/generate
156156
POST /annotations/upload controllers.AnnotationIOController.upload()
157157
POST /annotations/:typ/:id/duplicate controllers.AnnotationController.duplicate(typ: String, id: ObjectId)
158158
PATCH /annotations/:typ/:id/edit controllers.AnnotationController.editAnnotation(typ: String, id: ObjectId)
159-
PATCH /annotations/:typ/:id/editLayer/:tracingId controllers.AnnotationController.editAnnotationLayer(typ: String, id: ObjectId, tracingId: String)
160159

161160
PATCH /annotations/:typ/:id/finish controllers.AnnotationController.finish(typ: String, id: ObjectId, timestamp: Long)
162161
PATCH /annotations/:typ/finish controllers.AnnotationController.finishAll(typ: String, timestamp: Long)

docs/data/concepts.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ The term "magnifications" is used synonymously for mags throughout the UI.
105105
At the moment, WEBKNOSSOS guarantees correct rendering of data with non-uniform mag factors only if the z-component between two mags changes by a factor of 1 or 2.
106106

107107
Most users do not create these metadata files manually.
108-
When using the [WEBKNOSSOS CLI](https://docs.webknossos.org/cli), a metadata file is automatically generated. Alternatively, you can create and edit WEBKNOSSOS datasets using the [WEBKNOSSOS Python library](https://github.com/scalableminds/webknossos-libs/).
108+
When using the [WEBKNOSSOS CLI](https://docs.webknossos.org/cli/), a metadata file is automatically generated. Alternatively, you can create and edit WEBKNOSSOS datasets using the [WEBKNOSSOS Python library](https://github.com/scalableminds/webknossos-libs/).
109109
During the data import process, WEBKNOSSOS will ask for the necessary properties.
110110

111111
[See below for the full specification](#dataset-metadata-specification).

docs/data/export_python.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
## Data Export through Python
22

3-
The [WEBKNOSSOS Python library](https://docs.webknossos.org/webknossos-py/index.html) makes it very easy to download/upload any of your organization's datasets, and annotations. For detailed info, please refer to the `webknossos-libs` [documentation website for guides and tutorials](https://docs.webknossos.org/webknossos-py/index.html).
3+
The [WEBKNOSSOS Python library](https://docs.webknossos.org/webknossos-py/) makes it very easy to download/upload any of your organization's datasets, and annotations. For detailed info, please refer to the `webknossos-libs` [documentation website for guides and tutorials](https://docs.webknossos.org/webknossos-py/).
44

55
There are also quick start instructions for Python download available directly from the [WEBKNOSSOS UI](./export_ui.md).

docs/data/image_stacks.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ WEBKNOSSOS understands most modern bio-imaging file formats and uses the [BioFor
5454

5555
You can manually convert image stacks through:
5656

57-
- [WEBKNOSSOS CLI](https://docs.webknossos.org/cli)
58-
- [WEBKNOSSOS Python library](https://docs.webknossos.org/webknossos-py)
57+
- [WEBKNOSSOS CLI](https://docs.webknossos.org/cli/)
58+
- [WEBKNOSSOS Python library](https://docs.webknossos.org/webknossos-py/)
5959

6060
### Conversion with CLI
6161
You can easily convert image stacks manually with the WEBKNOSSOS CLI.
@@ -75,11 +75,11 @@ This snippet converts an image stack that is located in directory called `data/s
7575
It will create a so called `color` layer containing your raw greyscale/color image.
7676
The supplied `--voxel-size` is specified in nanometers.
7777

78-
Read the full documentation at [WEBKNOSSOS CLI](https://docs.webknossos.org/cli).
78+
Read the full documentation at [WEBKNOSSOS CLI](https://docs.webknossos.org/cli/).
7979

8080
### Conversion with Python
8181

82-
You can use the free [WEBKNOSSOS Python library](https://docs.webknossos.org/webknossos-py) to convert image stacks to Zarr v3 or integrate the conversion as part of an existing workflow.
82+
You can use the free [WEBKNOSSOS Python library](https://docs.webknossos.org/webknossos-py/) to convert image stacks to Zarr v3 or integrate the conversion as part of an existing workflow.
8383

8484
```python
8585
import webknossos as wk

docs/data/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@ WEBKNOSSOS natively supports loading and streaming data in the following formats
1212

1313
The Zarr3 format is used for all internal voxel data representations - both for the raw (microscopy) image datasets and segmentations. Skeleton annotations are saved as NML files.
1414

15-
Any dataset uploaded to webknossos.org will automatically be converted to Zarr3 on upload - given its source file format is supported by WEBKNOSSOS. Alternatively, you can manually convert your datasets using the [WEBKNOSSOS CLI tool](https://docs.webknossos.org/cli) or use a custom script based on the [WEBKNOSSOS Python library](https://docs.webknossos.org/webknossos-py/index.html).
15+
Any dataset uploaded to webknossos.org will automatically be converted to Zarr3 on upload - given its source file format is supported by WEBKNOSSOS. Alternatively, you can manually convert your datasets using the [WEBKNOSSOS CLI tool](https://docs.webknossos.org/cli/) or use a custom script based on the [WEBKNOSSOS Python library](https://docs.webknossos.org/webknossos-py/).
1616

1717
Read more about uploading and configuring datasets on the [datasets page](../datasets/settings.md).

0 commit comments

Comments
 (0)