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

ND Datasets #7136

Merged
merged 148 commits into from
Sep 5, 2023
Merged
Show file tree
Hide file tree
Changes from 105 commits
Commits
Show all changes
148 commits
Select commit Hold shift + click to select a range
4f2be0e
add UI for 4th dimension and mock 4D data when requesting buckets
philippotto Jun 12, 2023
f80301b
adapt bucket address space to incorporate higher dimension
philippotto Jun 12, 2023
3c8322a
clean up imports
philippotto Jun 12, 2023
a24fb58
add slider to Q input field; tune mocked 4D data retrieval
philippotto Jun 12, 2023
a38ece5
change max value of number slider
philippotto Jun 12, 2023
e19dd4d
Merge branch 'master' of github.com:scalableminds/webknossos into 4d
philippotto Jun 13, 2023
168d58e
make skeletons compatible with higher dimensions
philippotto Jun 14, 2023
8dd6c5f
fix tests; improve typing; create CubeEntry instances lazily
philippotto Jun 14, 2023
082af8b
fix linting
philippotto Jun 14, 2023
7b30efe
use n-dimensional generalization instead of fourth coordinate everywhere
philippotto Jun 14, 2023
6cc4372
fix resampling of buckets when annotating volume data in higher dimen…
philippotto Jun 14, 2023
5f11460
add additionalCoordinates parameter to several other places
philippotto Jun 15, 2023
275c7af
hardcode additionalCoords initialization
philippotto Jun 15, 2023
c25d61d
tackle more todo comments
philippotto Jun 15, 2023
38e0592
adapt additionalCoordinates input UI to arbitrary dimensions; use two…
philippotto Jun 15, 2023
b0b5b04
dynamically generate shaders for nodes and edges to deal with arbitra…
philippotto Jun 16, 2023
1f05545
make edges interpolate from alpha 1 to 0 if edge partner is on other …
philippotto Jun 16, 2023
6b7b3a5
Add additional coordinates for 4+D requests
frcroth Jun 19, 2023
ff3e37b
Merge branch 'timeseries' into 4d
frcroth Jun 19, 2023
54a4bf1
begin integration of backend additionalCoordinate interface
philippotto Jun 20, 2023
48b1605
change frontend format for additional coordinates from number-array t…
philippotto Jun 20, 2023
bfe839c
Merge branch 'master' into 4d
frcroth Jun 26, 2023
98c1e15
Add additional coords to db
frcroth Jun 27, 2023
4c84670
Fix naming
frcroth Jun 27, 2023
ce64fa9
Merge branch 'master' of github.com:scalableminds/webknossos into 4d
philippotto Jun 28, 2023
dad1652
remove hardcoded additional coordinates related to DataCube class
philippotto Jun 28, 2023
e5047ce
properly initialize flycam with additional coordinates
philippotto Jun 28, 2023
2b819b0
make that arrow keys in vector input increment/decrement element wher…
philippotto Jun 29, 2023
8f2eb14
fix onChange in additional-coordinate-input
philippotto Jun 29, 2023
a63da9e
use bounds of additional unified coordinates in slider
philippotto Jun 29, 2023
2ee89cd
don't hardcode additional coordinate length in skeleton.ts; guard aga…
philippotto Jun 29, 2023
b2423c3
fix rendering of skeletons in higher dimensions
philippotto Jun 29, 2023
f4c2726
export/import additional coordinates in NML (front-end import/export …
philippotto Jun 29, 2023
162de96
ensure api.getDataValue receives additionalCoordinates parameter ever…
philippotto Jun 29, 2023
93aa030
also fallback to stores additionalCoordinates when they are not provi…
philippotto Jun 29, 2023
00342ce
remove second-last todo comment
philippotto Jun 29, 2023
730427d
Add additional coords as paramters for volume actions
frcroth Jun 30, 2023
ba9d0c3
Add editPositionAdditionalCoordinates to tracings
frcroth Jun 30, 2023
503336e
Merge branch 'master' into 4d
frcroth Jun 30, 2023
c55097f
Implement n-dimensional morton code
frcroth Jul 3, 2023
6f5bba5
Start implementation of volume tracing n-d fossildb access
frcroth Jul 4, 2023
c558434
Add additional coordinates to skeleton nodes
frcroth Jul 18, 2023
debc1bf
Merge branch 'master' into 4d
frcroth Jul 18, 2023
42109ee
Merge branch '4d' of github.com:scalableminds/webknossos into 4d
philippotto Jul 18, 2023
a1166b9
fix runtime exception when no additional coordinates exist; fix initi…
philippotto Jul 18, 2023
370c3cb
remove todo comment
philippotto Jul 18, 2023
e9d6a8f
rename additionalCoords to additionalCoordinates everywhere
philippotto Jul 18, 2023
8b9be31
fix typing
philippotto Jul 18, 2023
1fae60e
fix delayed update
philippotto Jul 18, 2023
be24154
hotfix missing additionalCoordinates for volume layer
philippotto Jul 18, 2023
ff94f27
pass additionalCoordinates everywhere SegmentItem- and MeshItem-relat…
philippotto Jul 19, 2023
6abfbc1
clicking on a segment list should activate its additionalCoordinates …
philippotto Jul 19, 2023
2a41572
fix linting
philippotto Jul 19, 2023
ffdf3aa
fix cyclic dependencies
philippotto Jul 20, 2023
4a359d6
rename to someAdditionalCoordinates
philippotto Jul 20, 2023
066194c
also store additional coordinates in json-encoded url state
philippotto Jul 20, 2023
788be4a
show dimensions as addonBefore in AdditionalCoordinates input box
philippotto Jul 20, 2023
a2cf9ba
Merge branch 'master' of github.com:scalableminds/webknossos into 4d
philippotto Jul 20, 2023
1768a2e
clean up
philippotto Jul 21, 2023
e38933d
also maintain editPositionAdditionalCoordinates in frontend
philippotto Jul 21, 2023
263226a
Add additional coordinates to tracings
frcroth Jul 24, 2023
7d8e818
Read additional coordinate bounds from zarr header
frcroth Jul 24, 2023
a5e98b5
Store additional coordinate as a vec2int in proto
frcroth Jul 25, 2023
9c9f0a1
store additionalCoordinates for volume and skeleton layers
philippotto Jul 25, 2023
6670dd8
Increment evolution number
frcroth Jul 25, 2023
697d82b
fix cube.spec and volume_annotation_sampling.spec
philippotto Jul 25, 2023
140a8dd
fix wkstore_adapter spec
philippotto Jul 25, 2023
d0291d6
fix volumetracing_saga.spec
philippotto Jul 25, 2023
9db757f
fix nml.spec.ts
philippotto Jul 25, 2023
32868e8
fix url manager spec
philippotto Jul 25, 2023
2c6db3c
fix skeleton spec by ensuring singletons are set up
philippotto Jul 25, 2023
c6eb9ae
Merge branch 'master' into 4d
frcroth Jul 25, 2023
08842de
fix saga_integration.spec
philippotto Jul 25, 2023
bb99b30
Merge branch '4d' of github.com:scalableminds/webknossos into 4d
philippotto Jul 25, 2023
9da227d
Remove nd morton code, use 3d morton code always
frcroth Jul 25, 2023
14657f9
update documentation package to fix parser crash
philippotto Jul 25, 2023
4e5c687
Merge branch '4d' of github.com:scalableminds/webknossos into 4d
philippotto Jul 26, 2023
da43c15
Apply suggestions from code review
philippotto Jul 26, 2023
fe7e880
DRY assertion
philippotto Jul 26, 2023
5b6f2c2
fix camel case
philippotto Jul 26, 2023
df0a98d
Merge branch '4d' of github.com:scalableminds/webknossos into 4d
philippotto Jul 26, 2023
c1bb27b
undo changes in v2 api
philippotto Jul 26, 2023
46845b4
avoid several THREE.BufferAttribute casts
philippotto Jul 26, 2023
892e19c
add comment about additionalCoordinates = null in bucket pickers
philippotto Jul 26, 2023
47e934c
add emit-rerender comment
philippotto Jul 26, 2023
accd355
use bounds[0] as a fallback value when additional Coordinates are mis…
philippotto Jul 26, 2023
fd12bf5
warn when meshing >3d segmentations
philippotto Jul 26, 2023
cea417e
fix initialization of additional coordinates from url state
philippotto Jul 26, 2023
ace8582
change additional coordinates format in xml to sth like additionalCoo…
philippotto Jul 26, 2023
4c271d1
remove unneeded functions in nml_helpers
philippotto Jul 26, 2023
4472ac4
fix scala compilation on CI
philippotto Jul 26, 2023
4c6ff93
format
philippotto Jul 26, 2023
69470a6
format backend
philippotto Jul 26, 2023
97be640
test nml import/export with additional coordinates
philippotto Jul 27, 2023
05059fc
add test for setting additional coords in flycam
philippotto Jul 27, 2023
7126e37
Some sort of sorting
frcroth Jul 31, 2023
11d8c40
Merge branch 'master' into 4d
frcroth Aug 1, 2023
a76e358
Increment evolution number
frcroth Aug 1, 2023
f6d77ba
Add comment in datasetarray, remove todos
frcroth Aug 1, 2023
c3b95b5
fix linting
philippotto Aug 1, 2023
2cb1967
Update NML import/export for additional coordinates
frcroth Aug 1, 2023
c996f1f
Update snapshots
frcroth Aug 1, 2023
5c638f3
Sort additional coordinates when building bucket key
frcroth Aug 1, 2023
831c77e
Update snapshots again
frcroth Aug 1, 2023
0487c89
fix yarn.lock
philippotto Aug 1, 2023
fda8c52
Merge branch 'master' of github.com:scalableminds/webknossos into 4d
philippotto Aug 3, 2023
dbb504c
Fix volume tracing bucket key not including additional coordinates be…
frcroth Aug 3, 2023
83dc37e
fix styling of additional-coordinate UI in light theme
philippotto Aug 3, 2023
bd9bfea
also serialize additional coordinates for editPosition and layer itse…
philippotto Aug 3, 2023
cf32638
Merge branch '4d' of github.com:scalableminds/webknossos into 4d
philippotto Aug 3, 2023
84bc64f
show additional coords in context menu and status bar
philippotto Aug 3, 2023
a860d13
Add test for bucket keys with additional coordinates (and nml)
frcroth Aug 3, 2023
35e014b
Merge branch '4d' of github.com:scalableminds/webknossos into 4d
philippotto Aug 3, 2023
8d1769e
Merge branch 'master' into 4d
frcroth Aug 7, 2023
38e084c
Rename additionalCorrdinate to definition
frcroth Aug 7, 2023
85d10f3
Assert additional coordinates are the same when merging
frcroth Aug 7, 2023
9032daf
Add additional coordinate tests
frcroth Aug 7, 2023
1183521
Update changelog
frcroth Aug 7, 2023
469e05f
Remove TODOs
frcroth Aug 7, 2023
3982c3d
add warning for ai-quick-select for n-d datasets
philippotto Aug 8, 2023
53486e6
enforce valid values for additional coordinates in UI
philippotto Aug 8, 2023
9a252ab
fix tests
philippotto Aug 8, 2023
4d7bb41
Merge branch '4d' of github.com:scalableminds/webknossos into 4d
philippotto Aug 8, 2023
6839a18
Merge branch 'master' of github.com:scalableminds/webknossos into 4d
philippotto Aug 8, 2023
c51adf8
fix nml test and add a new one for additional coords
philippotto Aug 8, 2023
16cb377
Lint backend
frcroth Aug 8, 2023
f4883db
remove t from axis order, allow mag paths relative to dataset dir
fm3 Aug 15, 2023
8c8d138
Merge branch 'master' of github.com:scalableminds/webknossos into 4d
philippotto Aug 17, 2023
cb80f5c
improve and fix snapshot tests
philippotto Aug 17, 2023
099dc9f
prevent user from exporting/downloading layers with nd data
philippotto Aug 17, 2023
37cfbe5
Fix simple refactorings
frcroth Aug 21, 2023
8e39fc8
Merge branch 'master' into 4d
frcroth Aug 21, 2023
0bc6ebd
Rename additionalCoordinateDefinition to additionalAxis
frcroth Aug 21, 2023
a8e748b
Rename additionalCoordinateRequest to additionalCoordinate
frcroth Aug 21, 2023
1d51256
Continue renaming
frcroth Aug 21, 2023
6b56ba1
rename additionalCoordinateWithBounds to AdditionalAxis and adapt to …
philippotto Aug 21, 2023
5108f68
Merge branch '4d' of github.com:scalableminds/webknossos into 4d
philippotto Aug 21, 2023
a00b4bb
Do not require migration of bucket keys
frcroth Aug 21, 2023
532496c
Merge branch '4d' of github.com:scalableminds/webknossos into 4d
philippotto Aug 21, 2023
3d626a3
update snapshots
philippotto Aug 21, 2023
39aa8f3
Lint backend
frcroth Aug 21, 2023
465482e
Rename Segment->additionalCoordinates to anchorPositionadd..
frcroth Aug 21, 2023
b4d2b03
Remove unused method
frcroth Aug 21, 2023
a085d36
Remove exception throwing
frcroth Aug 23, 2023
dba09d4
Fix renaming issues
frcroth Sep 4, 2023
7c7d212
Merge branch 'master' into 4d
frcroth Sep 4, 2023
05fc2e5
Fix upload of annotations
frcroth Sep 4, 2023
7bb9547
Merge branch 'master' into 4d
fm3 Sep 5, 2023
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
1 change: 1 addition & 0 deletions MIGRATIONS.unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ UPDATE webknossos.multiUsers SET isEmailVerified = false;
### Postgres Evolutions:
- [105-verify-email.sql](conf/evolutions/105-verify-email.sql)
- [106-folder-no-slashes.sql](conf/evolutions/106-folder-no-slashes.sql)
- [107-additional-coordinates](conf/evolutions/107-additional-coordinates.sql)
4 changes: 3 additions & 1 deletion app/controllers/AnnotationController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.scalableminds.util.time.Instant
import com.scalableminds.util.tools.{Fox, FoxImplicits}
import com.scalableminds.webknossos.datastore.models.annotation.AnnotationLayerType.AnnotationLayerType
import com.scalableminds.webknossos.datastore.models.annotation.{AnnotationLayer, AnnotationLayerType}
import com.scalableminds.webknossos.datastore.models.datasource.AdditionalCoordinate
import com.scalableminds.webknossos.tracingstore.tracings.volume.ResolutionRestrictions
import com.scalableminds.webknossos.tracingstore.tracings.{TracingIds, TracingType}
import io.swagger.annotations._
Expand Down Expand Up @@ -39,7 +40,8 @@ case class AnnotationLayerParameters(typ: AnnotationLayerType,
autoFallbackLayer: Boolean = false,
mappingName: Option[String] = None,
resolutionRestrictions: Option[ResolutionRestrictions],
name: Option[String])
name: Option[String],
additionalCoordinate: Option[Seq[AdditionalCoordinate]])
object AnnotationLayerParameters {
implicit val jsonFormat: OFormat[AnnotationLayerParameters] =
Json.using[WithDefaultValues].format[AnnotationLayerParameters]
Expand Down
6 changes: 4 additions & 2 deletions app/controllers/LegacyApiController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,8 @@ class LegacyApiController @Inject()(annotationController: AnnotationController,
autoFallbackLayer = false,
None,
request.body.resolutionRestrictions,
name = Some(AnnotationLayer.defaultSkeletonLayerName)
name = Some(AnnotationLayer.defaultSkeletonLayerName),
None
))
val volumeParameters =
if (request.body.typ == "skeleton") None
Expand All @@ -443,7 +444,8 @@ class LegacyApiController @Inject()(annotationController: AnnotationController,
autoFallbackLayer = false,
None,
request.body.resolutionRestrictions,
name = Some(AnnotationLayer.defaultVolumeLayerName)
name = Some(AnnotationLayer.defaultVolumeLayerName),
None
))
List(skeletonParameters, volumeParameters).flatten
}
Expand Down
26 changes: 19 additions & 7 deletions app/models/annotation/AnnotationService.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import com.scalableminds.util.tools.{BoxImplicits, Fox, FoxImplicits, TextUtils}
import com.scalableminds.webknossos.datastore.SkeletonTracing._
import com.scalableminds.webknossos.datastore.VolumeTracing.{VolumeTracing, VolumeTracingOpt, VolumeTracings}
import com.scalableminds.webknossos.datastore.geometry.{
AdditionalCoordinateProto,
ColorProto,
NamedBoundingBoxProto,
Vec3DoubleProto,
Expand All @@ -24,6 +25,7 @@ import com.scalableminds.webknossos.datastore.models.annotation.{
FetchedAnnotationLayer
}
import com.scalableminds.webknossos.datastore.models.datasource.{
AdditionalCoordinate,
ElementClass,
DataSourceLike => DataSource,
SegmentationLayerLike => SegmentationLayer
Expand Down Expand Up @@ -77,7 +79,8 @@ case class RedundantTracingProperties(
editPosition: Vec3IntProto,
editRotation: Vec3DoubleProto,
zoomLevel: Double,
userBoundingBoxes: Seq[NamedBoundingBoxProto]
userBoundingBoxes: Seq[NamedBoundingBoxProto],
editPositionAdditionalCoordinates: Seq[AdditionalCoordinateProto],
)

class AnnotationService @Inject()(
Expand Down Expand Up @@ -144,6 +147,8 @@ class AnnotationService @Inject()(
): Fox[VolumeTracing] = {
val resolutions = VolumeTracingDownsampling.magsForVolumeTracing(dataSource, fallbackLayer)
val resolutionsRestricted = resolutionRestrictions.filterAllowed(resolutions)
val additionalCoordinates =
fallbackLayer.map(_.additionalCoordinates).getOrElse(dataSource.additionalCoordinatesUnion)
for {
_ <- bool2Fox(resolutionsRestricted.nonEmpty) ?~> "annotation.volume.resolutionRestrictionsTooTight"
} yield
Expand All @@ -163,7 +168,8 @@ class AnnotationService @Inject()(
organizationName = Some(datasetOrganizationName),
mappingName = mappingName,
resolutions = resolutionsRestricted.map(vec3IntToProto),
hasSegmentIndex = Some(fallbackLayer.isEmpty)
hasSegmentIndex = Some(fallbackLayer.isEmpty),
additionalCoordinates = AdditionalCoordinate.toProto(additionalCoordinates)
)
}

Expand Down Expand Up @@ -240,13 +246,15 @@ class AnnotationService @Inject()(
dataSetName = dataSet.name,
editPosition = dataSource.center,
organizationName = Some(datasetOrganizationName),
additionalCoordinates = AdditionalCoordinate.toProto(dataSource.additionalCoordinatesUnion)
)
val skeletonAdapted = oldPrecedenceLayerProperties.map { p =>
skeleton.copy(
editPosition = p.editPosition,
editRotation = p.editRotation,
zoomLevel = p.zoomLevel,
userBoundingBoxes = p.userBoundingBoxes
userBoundingBoxes = p.userBoundingBoxes,
editPositionAdditionalCoordinates = p.editPositionAdditionalCoordinates
)
}.getOrElse(skeleton)
for {
Expand All @@ -273,7 +281,8 @@ class AnnotationService @Inject()(
editPosition = p.editPosition,
editRotation = p.editRotation,
zoomLevel = p.zoomLevel,
userBoundingBoxes = p.userBoundingBoxes
userBoundingBoxes = p.userBoundingBoxes,
editPositionAdditionalCoordinates = p.editPositionAdditionalCoordinates
)
}.getOrElse(volumeTracing)
volumeTracingId <- client.saveVolumeTracing(volumeTracingAdapted)
Expand Down Expand Up @@ -305,15 +314,17 @@ class AnnotationService @Inject()(
s.editRotation,
s.zoomLevel,
s.userBoundingBoxes ++ s.userBoundingBox.map(
com.scalableminds.webknossos.datastore.geometry.NamedBoundingBoxProto(0, None, None, None, _))
com.scalableminds.webknossos.datastore.geometry.NamedBoundingBoxProto(0, None, None, None, _)),
s.editPositionAdditionalCoordinates
)
case Right(v) =>
RedundantTracingProperties(
v.editPosition,
v.editRotation,
v.zoomLevel,
v.userBoundingBoxes ++ v.userBoundingBox.map(
com.scalableminds.webknossos.datastore.geometry.NamedBoundingBoxProto(0, None, None, None, _))
com.scalableminds.webknossos.datastore.geometry.NamedBoundingBoxProto(0, None, None, None, _)),
v.editPositionAdditionalCoordinates
)
}

Expand Down Expand Up @@ -384,7 +395,8 @@ class AnnotationService @Inject()(
autoFallbackLayer = false,
None,
Some(ResolutionRestrictions.empty),
Some(AnnotationLayer.defaultNameForType(newAnnotationLayerType))
Some(AnnotationLayer.defaultNameForType(newAnnotationLayerType)),
None
)
_ <- addAnnotationLayer(annotation, organizationName, newAnnotationLayerParameters) ?~> "makeHybrid.createTracings.failed"
} yield ()
Expand Down
85 changes: 75 additions & 10 deletions app/models/annotation/nml/NmlParser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,14 @@ import com.scalableminds.util.geometry.{BoundingBox, Vec3Double, Vec3Int}
import com.scalableminds.util.tools.ExtendedTypes.{ExtendedDouble, ExtendedString}
import com.scalableminds.webknossos.datastore.SkeletonTracing._
import com.scalableminds.webknossos.datastore.VolumeTracing.{Segment, SegmentGroup, VolumeTracing}
import com.scalableminds.webknossos.datastore.geometry.{ColorProto, NamedBoundingBoxProto, Vec3IntProto}
import com.scalableminds.webknossos.datastore.geometry.{
AdditionalCoordinateDefinitionProto,
AdditionalCoordinateProto,
ColorProto,
NamedBoundingBoxProto,
Vec2IntProto,
Vec3IntProto
}
import com.scalableminds.webknossos.datastore.helpers.{NodeDefaults, ProtoGeometryImplicits, SkeletonTracingDefaults}
import com.scalableminds.webknossos.datastore.models.datasource.ElementClass
import com.scalableminds.webknossos.tracingstore.tracings.ColorGenerator
Expand All @@ -19,7 +26,7 @@ import play.api.i18n.{Messages, MessagesProvider}

import java.io.InputStream
import scala.collection.{immutable, mutable}
import scala.xml.{NodeSeq, XML, Node => XMLNode}
import scala.xml.{Attribute, NodeSeq, XML, Node => XMLNode}

object NmlParser extends LazyLogging with ProtoGeometryImplicits with ColorGenerator {

Expand Down Expand Up @@ -58,13 +65,15 @@ object NmlParser extends LazyLogging with ProtoGeometryImplicits with ColorGener
val organizationName =
if (overwritingDataSetName.isDefined) None else parseOrganizationName(parameters \ "experiment")
val activeNodeId = parseActiveNode(parameters \ "activeNode")
val editPosition =
parseEditPosition(parameters \ "editPosition").getOrElse(SkeletonTracingDefaults.editPosition)
val (editPosition, editPositionAdditionalCoordinates) =
parseEditPosition(parameters \ "editPosition").getOrElse((SkeletonTracingDefaults.editPosition, Seq()))
val editRotation =
parseEditRotation(parameters \ "editRotation").getOrElse(SkeletonTracingDefaults.editRotation)
val zoomLevel = parseZoomLevel(parameters \ "zoomLevel").getOrElse(SkeletonTracingDefaults.zoomLevel)
var userBoundingBoxes = parseBoundingBoxes(parameters \ "userBoundingBox")
var taskBoundingBox: Option[BoundingBox] = None
val additionalCoordinates =
parseAdditionalCoordinateDefinitions(parameters \ "additionalCoordinates").getOrElse(Seq())
parseTaskBoundingBox(parameters \ "taskBoundingBox", isTaskUpload, userBoundingBoxes).foreach {
case Left(value) => taskBoundingBox = Some(value)
case Right(value) => userBoundingBoxes = userBoundingBoxes :+ value
Expand Down Expand Up @@ -92,7 +101,9 @@ object NmlParser extends LazyLogging with ProtoGeometryImplicits with ColorGener
organizationName,
segments = v.segments,
segmentGroups = v.segmentGroups,
hasSegmentIndex = VolumeSegmentIndexService.canHaveSegmentIndex(v.fallbackLayerName)
hasSegmentIndex = VolumeSegmentIndexService.canHaveSegmentIndex(v.fallbackLayerName),
editPositionAdditionalCoordinates = editPositionAdditionalCoordinates,
additionalCoordinates = additionalCoordinates
),
basePath.getOrElse("") + v.dataZipPath,
v.name,
Expand All @@ -116,7 +127,9 @@ object NmlParser extends LazyLogging with ProtoGeometryImplicits with ColorGener
None,
treeGroupsAfterSplit,
userBoundingBoxes,
organizationName
organizationName,
editPositionAdditionalCoordinates,
additionalCoordinates = additionalCoordinates
)
)

Expand Down Expand Up @@ -189,13 +202,15 @@ object NmlParser extends LazyLogging with ProtoGeometryImplicits with ColorGener
case (Some(x), Some(y), Some(z)) => Some(Vec3IntProto(x.toInt, y.toInt, z.toInt))
case _ => None
}
val additionalCoordinates = parseAdditionalCoordinateValues(node)
Segment(
segmentId = getSingleAttribute(node, "id").toLong,
anchorPosition = anchorPosition,
name = getSingleAttributeOpt(node, "name"),
creationTime = getSingleAttributeOpt(node, "created").flatMap(_.toLongOpt),
color = parseColorOpt(node),
groupId = getSingleAttribute(node, "groupId").toIntOpt
groupId = getSingleAttribute(node, "groupId").toIntOpt,
additionalCoordinates = additionalCoordinates
)
})

Expand Down Expand Up @@ -248,6 +263,23 @@ object NmlParser extends LazyLogging with ProtoGeometryImplicits with ColorGener
depth <- getSingleAttribute(node, "depth").toIntOpt
} yield BoundingBox(Vec3Int(topLeftX, topLeftY, topLeftZ), width, height, depth)

def parseAdditionalCoordinateDefinitions(nodes: NodeSeq) =
nodes.headOption.map(
_.child.flatMap(
additionalCoordinateNode => {
for {
name <- getSingleAttributeOpt(additionalCoordinateNode, "name")
indexStr <- getSingleAttributeOpt(additionalCoordinateNode, "index")
index <- indexStr.toIntOpt
minStr <- getSingleAttributeOpt(additionalCoordinateNode, "min")
min <- minStr.toIntOpt
maxStr <- getSingleAttributeOpt(additionalCoordinateNode, "max")
max <- maxStr.toIntOpt
} yield new AdditionalCoordinateDefinitionProto(name, index, Vec2IntProto(min, max))
}
)
)

private def parseDataSetName(nodes: NodeSeq): String =
nodes.headOption.map(node => getSingleAttribute(node, "name")).getOrElse("")

Expand All @@ -266,8 +298,15 @@ object NmlParser extends LazyLogging with ProtoGeometryImplicits with ColorGener
private def parseTime(nodes: NodeSeq): Long =
nodes.headOption.flatMap(node => getSingleAttribute(node, "ms").toLongOpt).getOrElse(DEFAULT_TIME)

private def parseEditPosition(nodes: NodeSeq): Option[Vec3Int] =
nodes.headOption.flatMap(parseVec3Int)
private def parseEditPosition(nodes: NodeSeq): Option[(Vec3Int, Seq[AdditionalCoordinateProto])] =
nodes.headOption.flatMap(n => {
val xyz = parseVec3Int(n)
val additionalCoordinates = parseAdditionalCoordinateValues(n)
xyz match {
case Some(value) => Some(value, additionalCoordinates)
case None => None
}
})

private def parseEditRotation(nodes: NodeSeq): Option[Vec3Double] =
nodes.headOption.flatMap(parseRotationForParams)
Expand Down Expand Up @@ -451,6 +490,7 @@ object NmlParser extends LazyLogging with ProtoGeometryImplicits with ColorGener
for {
id <- nodeIdText.toIntOpt ?~ Messages("nml.node.id.invalid", "", nodeIdText)
radius = getSingleAttribute(node, "radius").toFloatOpt.getOrElse(NodeDefaults.radius)
additionalCoordinates = parseAdditionalCoordinateValues(node)
position <- parseVec3Int(node) ?~ Messages("nml.node.attribute.invalid", "position", id)
} yield {
val viewport = parseViewport(node)
Expand All @@ -459,8 +499,33 @@ object NmlParser extends LazyLogging with ProtoGeometryImplicits with ColorGener
val bitDepth = parseBitDepth(node)
val interpolation = parseInterpolation(node)
val rotation = parseRotationForNode(node).getOrElse(NodeDefaults.rotation)
Node(id, position, rotation, radius, viewport, resolution, bitDepth, interpolation, timestamp)
Node(id,
position,
rotation,
radius,
viewport,
resolution,
bitDepth,
interpolation,
timestamp,
additionalCoordinates)
}
}

private def parseAdditionalCoordinateValues(node: XMLNode): Seq[AdditionalCoordinateProto] = {
val regex = "additionalCoordinate-(\\w)".r("name")
node.attributes.flatMap {
case attribute: Attribute => {
if (attribute.key.startsWith("additionalCoordinate")) {
Some(
new AdditionalCoordinateProto(regex.findAllIn(attribute.key).group("name"),
attribute.value.toString().toInt))
} else {
None
}
}
case _ => None
}.toSeq
}

}
31 changes: 28 additions & 3 deletions app/models/annotation/nml/NmlWriter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ case class NmlParameters(
zoomLevel: Double,
activeNodeId: Option[Int],
userBoundingBoxes: Seq[NamedBoundingBoxProto],
taskBoundingBox: Option[BoundingBoxProto]
taskBoundingBox: Option[BoundingBoxProto],
additionalCoordinates: Seq[AdditionalCoordinateDefinitionProto],
editPositionAdditionalCoordinates: Seq[AdditionalCoordinateProto]
)

class NmlWriter @Inject()(implicit ec: ExecutionContext) extends FoxImplicits {
Expand Down Expand Up @@ -127,7 +129,9 @@ class NmlWriter @Inject()(implicit ec: ExecutionContext) extends FoxImplicits {
s.zoomLevel,
s.activeNodeId,
s.userBoundingBoxes ++ s.userBoundingBox.map(NamedBoundingBoxProto(0, None, None, None, _)),
s.boundingBox
s.boundingBox,
s.additionalCoordinates,
s.editPositionAdditionalCoordinates
)
case Right(v) =>
NmlParameters(
Expand All @@ -142,7 +146,9 @@ class NmlWriter @Inject()(implicit ec: ExecutionContext) extends FoxImplicits {
v.zoomLevel,
None,
v.userBoundingBoxes ++ v.userBoundingBox.map(NamedBoundingBoxProto(0, None, None, None, _)),
if (annotation.exists(_._task.isDefined)) Some(v.boundingBox) else None
if (annotation.exists(_._task.isDefined)) Some(v.boundingBox) else None,
v.additionalCoordinates,
v.editPositionAdditionalCoordinates
)
}
} yield nmlParameters
Expand Down Expand Up @@ -181,6 +187,7 @@ class NmlWriter @Inject()(implicit ec: ExecutionContext) extends FoxImplicits {
writer.writeAttribute("x", parameters.editPosition.x.toString)
writer.writeAttribute("y", parameters.editPosition.y.toString)
writer.writeAttribute("z", parameters.editPosition.z.toString)
parameters.editPositionAdditionalCoordinates.foreach(writeAdditionalCoordinateValue)
}
Xml.withinElementSync("editRotation") {
writer.writeAttribute("xRot", parameters.editRotation.x.toString)
Expand All @@ -207,6 +214,18 @@ class NmlWriter @Inject()(implicit ec: ExecutionContext) extends FoxImplicits {
parameters.taskBoundingBox.foreach { b =>
Xml.withinElementSync("taskBoundingBox")(writeBoundingBox(b))
}
if (parameters.additionalCoordinates.nonEmpty) {
Xml.withinElementSync("additionalCoordinates") {
parameters.additionalCoordinates.foreach(a => {
Xml.withinElementSync("additionalCoordinate") {
writer.writeAttribute("name", a.name)
writer.writeAttribute("index", a.index.toString)
writer.writeAttribute("min", a.bounds.x.toString)
writer.writeAttribute("max", a.bounds.y.toString)
}
})
}
}
}

// Write volume things from FetchedAnnotationLayer. Caller must ensure that it is a volume annotation layer
Expand Down Expand Up @@ -249,6 +268,7 @@ class NmlWriter @Inject()(implicit ec: ExecutionContext) extends FoxImplicits {
writer.writeAttribute("anchorPositionX", a.x.toString)
writer.writeAttribute("anchorPositionY", a.y.toString)
writer.writeAttribute("anchorPositionZ", a.z.toString)
s.additionalCoordinates.foreach(writeAdditionalCoordinateValue)
}
s.color.foreach(_ => writeColor(s.color))
s.groupId.foreach(groupId => writer.writeAttribute("groupId", groupId.toString))
Expand Down Expand Up @@ -293,6 +313,7 @@ class NmlWriter @Inject()(implicit ec: ExecutionContext) extends FoxImplicits {
writer.writeAttribute("bitDepth", n.bitDepth.toString)
writer.writeAttribute("interpolation", n.interpolation.toString)
writer.writeAttribute("time", n.createdTimestamp.toString)
n.additionalCoordinates.foreach(writeAdditionalCoordinateValue)
}
}

Expand Down Expand Up @@ -387,4 +408,8 @@ class NmlWriter @Inject()(implicit ec: ExecutionContext) extends FoxImplicits {
writer.writeAttribute("color.b", color.map(_.b.toString).getOrElse(""))
writer.writeAttribute("color.a", color.map(_.a.toString).getOrElse(""))
}

def writeAdditionalCoordinateValue(additionalCoordinate: AdditionalCoordinateProto)(
implicit writer: XMLStreamWriter): Unit =
writer.writeAttribute(s"additionalCoordinate-${additionalCoordinate.name}", additionalCoordinate.value.toString)
}
Loading