Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
ccb2a0d
refactor: rework coordinates
dbirman May 13, 2026
89b8246
update docs
github-actions[bot] May 13, 2026
f12b01d
refactor: replace Scale with Rectangle/Circle
dbirman Jun 5, 2026
ec6fb5e
Merge branch 'dev' into 1831-flexible-cs
dbirman Jun 5, 2026
3199651
fix: extrinsic/intrinsic -> global/local
dbirman Jun 5, 2026
138b946
fix: simplify
dbirman Jun 5, 2026
34e7226
test: repair tests
dbirman Jun 5, 2026
4f627c8
update docs
github-actions[bot] Jun 5, 2026
8ec5f7c
chore: lint
dbirman Jun 5, 2026
e820051
Merge branch '1831-flexible-cs' of https://github.com/AllenNeuralDyna…
dbirman Jun 5, 2026
f1a56c6
update docs
github-actions[bot] Jun 5, 2026
7263bf3
chore: lint
dbirman Jun 5, 2026
6978cf3
fix: repair outputs to match coordinate definitions
dbirman Jun 5, 2026
d1eb0ba
Merge branch '1831-flexible-cs' of https://github.com/AllenNeuralDyna…
dbirman Jun 5, 2026
34c7c90
update docs
github-actions[bot] Jun 5, 2026
aa6cf59
chore: lint
dbirman Jun 5, 2026
cad11a8
Merge branch '1831-flexible-cs' of https://github.com/AllenNeuralDyna…
dbirman Jun 5, 2026
1dff4a0
chore: lint
dbirman Jun 5, 2026
5680454
chore: lint
dbirman Jun 5, 2026
cc7f7e5
docs: small tweaks to the coordinate system viewer
dbirman Jun 5, 2026
179321d
feat: allow the use of EMAPA structures as origins
dbirman Jun 8, 2026
56181b6
update docs
github-actions[bot] Jun 8, 2026
4a0c3f5
chore: lint
dbirman Jun 8, 2026
3c088ac
Merge branch '1831-flexible-cs' of https://github.com/AllenNeuralDyna…
dbirman Jun 8, 2026
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,132 changes: 1,132 additions & 0 deletions docs/source/_static/coordinate_system_builder.html

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions docs/source/aind_data_schema_models/modalities.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Modalities
| `MAPSEQ` | `Multiplexed analysis of projections by sequencing` | `MAPseq` |
| `MERFISH` | `Multiplexed error-robust fluorescence in situ hybridization` | `merfish` |
| `MRI` | `Magnetic resonance imaging` | `MRI` |
| `ONE_PHOTON` | `One-photon imaging` | `one-photon` |
| `POPHYS` | `Planar optical physiology` | `pophys` |
| `SCRNASEQ` | `Single cell RNA sequencing` | `scRNAseq` |
| `SLAP2` | `Random access projection microscopy` | `slap2` |
Expand Down
8 changes: 4 additions & 4 deletions docs/source/components/configs.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ Description of an N-D image
| `channel_name` | `str` | Channel name |
| `dimensions_unit` | [SizeUnit](../aind_data_schema_models/units.md#sizeunit) | Dimensions unit |
| `image_to_acquisition_transform` | List[[Translation](coordinates.md#translation) or [Rotation](coordinates.md#rotation) or [Scale](coordinates.md#scale) or [Affine](coordinates.md#affine)] | Image to acquisition transform (Position, rotation, and scale of the image. Note that depth should be in the planes.) |
| `dimensions` | Optional[[Scale](coordinates.md#scale)] | Dimensions |
| `dimensions` | Optional[[Scale](coordinates.md#scale) or [Rectangle](geometry.md#rectangle)] | Dimensions |


### ImageSPIM
Expand All @@ -139,7 +139,7 @@ Description of an N-D image acquired with SPIM
| `channel_name` | `str` | Channel name |
| `dimensions_unit` | [SizeUnit](../aind_data_schema_models/units.md#sizeunit) | Dimensions unit |
| `image_to_acquisition_transform` | List[[Translation](coordinates.md#translation) or [Rotation](coordinates.md#rotation) or [Scale](coordinates.md#scale) or [Affine](coordinates.md#affine)] | Image to acquisition transform (Position, rotation, and scale of the image. Note that depth should be in the planes.) |
| `dimensions` | Optional[[Scale](coordinates.md#scale)] | Dimensions |
| `dimensions` | Optional[[Scale](coordinates.md#scale) or [Rectangle](geometry.md#rectangle)] | Dimensions |


### ImagingConfig
Expand Down Expand Up @@ -371,7 +371,7 @@ Description of an N-D image acquired in a specific imaging plane
| `channel_name` | `str` | Channel name |
| `dimensions_unit` | [SizeUnit](../aind_data_schema_models/units.md#sizeunit) | Dimensions unit |
| `image_to_acquisition_transform` | List[[Translation](coordinates.md#translation) or [Rotation](coordinates.md#rotation) or [Scale](coordinates.md#scale) or [Affine](coordinates.md#affine)] | Image to acquisition transform (Position, rotation, and scale of the image. Note that depth should be in the planes.) |
| `dimensions` | Optional[[Scale](coordinates.md#scale)] | Dimensions |
| `dimensions` | Optional[[Scale](coordinates.md#scale) or [Rectangle](geometry.md#rectangle)] | Dimensions |


### PlanarImageStack
Expand All @@ -389,7 +389,7 @@ Description of a stack of images acquired in a specific imaging plane
| `channel_name` | `str` | Channel name |
| `dimensions_unit` | [SizeUnit](../aind_data_schema_models/units.md#sizeunit) | Dimensions unit |
| `image_to_acquisition_transform` | List[[Translation](coordinates.md#translation) or [Rotation](coordinates.md#rotation) or [Scale](coordinates.md#scale) or [Affine](coordinates.md#affine)] | Image to acquisition transform (Position, rotation, and scale of the image. Note that depth should be in the planes.) |
| `dimensions` | Optional[[Scale](coordinates.md#scale)] | Dimensions |
| `dimensions` | Optional[[Scale](coordinates.md#scale) or [Rectangle](geometry.md#rectangle)] | Dimensions |


### Plane
Expand Down
51 changes: 46 additions & 5 deletions docs/source/components/coordinates.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ Definition an atlas
| `size_unit` | [SizeUnit](../aind_data_schema_models/units.md#sizeunit) | Size unit |
| `resolution` | `List[float]` | Resolution |
| `resolution_unit` | [SizeUnit](../aind_data_schema_models/units.md#sizeunit) | Resolution unit |
| `origin` | [Origin](../aind_data_schema_models/coordinates.md#origin) | Origin (Defines the position of (0,0,0) in the coordinate system) |
| `origin` | [MouseAnatomyModel](../aind_data_schema_models/external.md#mouseanatomymodel) | Origin (Defines the position of (0,0,0) in the coordinate system) |
| `axes` | List[[Axis](#axis)] | Axis names (Axis names and directions) |
| `axis_unit` | [SizeUnit](../aind_data_schema_models/units.md#sizeunit) | Size unit |
| `handedness` | Optional[[Handedness](#handedness)] | Handedness (Whether the coordinate system is right-handed or left-handed) |


### AtlasCoordinate
Expand All @@ -36,6 +37,7 @@ A point in an Atlas
|-------|------|-------------|
| `coordinate_system` | [Atlas](#atlas) | Atlas |
| `translation` | `List[float]` | Translation parameters |
| `frame` | [TransformFrame](#transformframe) | Reference frame |


### Axis
Expand All @@ -50,14 +52,25 @@ Linked direction and axis

### CoordinateSystem

Definition of a coordinate system relative to a brain
Definition of a coordinate system

| Field | Type | Title (Description) |
|-------|------|-------------|
| `name` | `str` | Name |
| `origin` | [Origin](../aind_data_schema_models/coordinates.md#origin) | Origin (Defines the position of (0,0,0) in the coordinate system) |
| `origin` | [MouseAnatomyModel](../aind_data_schema_models/external.md#mouseanatomymodel) | Origin (Defines the position of (0,0,0) in the coordinate system) |
| `axes` | List[[Axis](#axis)] | Axis names (Axis names and directions) |
| `axis_unit` | [SizeUnit](../aind_data_schema_models/units.md#sizeunit) | Size unit |
| `handedness` | Optional[[Handedness](#handedness)] | Handedness (Whether the coordinate system is right-handed or left-handed) |


### Handedness

Coordinate system handedness

| Name | Value |
|------|-------|
| `RIGHT` | `right` |
| `LEFT` | `left` |


### NonlinearTransform
Expand All @@ -73,14 +86,30 @@ Definition of a nonlinear transform

Rotation

Rotations are applied as Euler angles in order X/Y/Z
Rotations are applied as Euler angles in the specified axis order.

Angles follow right-hand rule, with positive angles rotating counter-clockwise.
The default convention is fixed global axes, right-hand rule (positive angles rotate
counter-clockwise when looking toward the origin from the positive axis),
xyz axis order, pivoting around the global origin.

| Field | Type | Title (Description) |
|-------|------|-------------|
| `angles` | `List[float]` | Angles and axes in 3D space (Right-hand rule, positive angles rotate CCW) |
| `angles_unit` | [AngleUnit](../aind_data_schema_models/units.md#angleunit) | Angle unit |
| `axis_order` | `str` | Axis order (Order of rotation axes as a string (e.g. 'xyz', 'zyx'). Must match the length of angles.) |
| `frame` | [TransformFrame](#transformframe) | Reference frame (Whether to rotate around global axes or local axes (which rotate with the device)) |
| `rotation_direction` | [RotationDirection](#rotationdirection) | Rotation direction (Right-hand rule: positive angles rotate CCW when looking toward the origin from the positive axis) |
| `pivot` | [TransformFrame](#transformframe) | Rotation pivot (Whether to rotate around the global origin or the local origin of the device) |


### RotationDirection

Rotation direction convention

| Name | Value |
|------|-------|
| `RIGHT_HAND` | `right_hand` |
| `LEFT_HAND` | `left_hand` |


### Scale
Expand All @@ -90,6 +119,17 @@ Scale
| Field | Type | Title (Description) |
|-------|------|-------------|
| `scale` | `List[float]` | Scale parameters |
| `pivot` | Optional[[TransformFrame](#transformframe)] | Scale pivot (Whether to scale around the global origin or the local origin of the device) |


### TransformFrame

Reference frame for applying transforms

| Name | Value |
|------|-------|
| `GLOBAL` | `global` |
| `LOCAL` | `local` |


### Translation
Expand All @@ -99,5 +139,6 @@ Translation
| Field | Type | Title (Description) |
|-------|------|-------------|
| `translation` | `List[float]` | Translation parameters |
| `frame` | [TransformFrame](#transformframe) | Reference frame |


12 changes: 7 additions & 5 deletions docs/source/components/devices.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,13 @@ Description of an air puff device

### Arena

Description of a rectangular arena
Description of an arena

| Field | Type | Title (Description) |
|-------|------|-------------|
| `size` | [Scale](coordinates.md#scale) | 3D Size |
| `size_unit` | [SizeUnit](../aind_data_schema_models/units.md#sizeunit) | Size unit |
| <del>`size`</del> | [Scale](coordinates.md#scale) | **[DEPRECATED]** Use shape. 3D Size |
| <del>`size_unit`</del> | [SizeUnit](../aind_data_schema_models/units.md#sizeunit) | **[DEPRECATED]** Use shape. Size unit |
| `shape` | Optional[[Rectangle](geometry.md#rectangle) or [Circle](geometry.md#circle)] | Shape of the arena |
| `objects_in_arena` | List[[Device](#device)] | Objects in arena |
| `name` | `str` | Device name |
| `serial_number` | `Optional[str]` | Serial number |
Expand Down Expand Up @@ -319,8 +320,9 @@ Description of an enclosure

| Field | Type | Title (Description) |
|-------|------|-------------|
| `size` | [Scale](coordinates.md#scale) | Size |
| `size_unit` | [SizeUnit](../aind_data_schema_models/units.md#sizeunit) | Size unit |
| <del>`size`</del> | [Scale](coordinates.md#scale) | **[DEPRECATED]** Use shape. Size |
| <del>`size_unit`</del> | [SizeUnit](../aind_data_schema_models/units.md#sizeunit) | **[DEPRECATED]** Use shape. Size unit |
| `shape` | Optional[[Rectangle](geometry.md#rectangle) or [Circle](geometry.md#circle)] | Shape of the enclosure |
| `internal_material` | `Optional[str]` | Internal material |
| `external_material` | `str` | External material |
| `grounded` | `bool` | Grounded |
Expand Down
25 changes: 25 additions & 0 deletions docs/source/components/geometry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Geometry

## Model definitions

### Circle

Circle geometry

| Field | Type | Title (Description) |
|-------|------|-------------|
| `radius` | `float` | Radius |
| `radius_unit` | [SizeUnit](../aind_data_schema_models/units.md#sizeunit) | Radius unit |


### Rectangle

Rectangle geometry

| Field | Type | Title (Description) |
|-------|------|-------------|
| `width` | `float` | Width |
| `height` | `float` | Height |
| `size_unit` | [SizeUnit](../aind_data_schema_models/units.md#sizeunit) | Size unit |


19 changes: 19 additions & 0 deletions docs/source/coordinate_systems.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,22 @@ CoordinateSystem(
The device is now defined in the instrument coordinate system, but at a physically impossible location overlapping the mouse. Now draw a second picture, which is the actual location of your monitor relative to the mouse. In our case, lets assume that this monitor is facing the mouse's right eye, at a 45 degree angle to the axis of the mouse's body (i.e. the eye to monitor vector is perpendicular to the monitor surface.), and at a viewing distance of 100 mm.

Now we calculate the transforms needed to correctly position the device in the acquisition coordinate system. First we translate the monitor to the correct position by applying `Translation(translation=70.7, 70.7, 0)`. Then, we rotate *clockwise* around the Z axis by applying `Rotation(angles=[0, 0, -45], angles_unit=AngleUnit.DEG)`.

## Interactive Coordinate System Builder

The builder below lets you set up your instrument coordinate system, add a probe or monitor device, and construct the transform list interactively. The 3D viewport shows a semi-transparent brain mesh with the device rendered in its final position. When you are satisfied, copy the generated Python code from the Export panel.

```{raw} html
<p style="margin-bottom:6px">
<a href="_static/coordinate_system_builder.html" target="_blank" rel="noopener">
Open builder in full screen ↗
</a>
</p>
<iframe
src="_static/coordinate_system_builder.html"
style="width:100%; min-width:820px; height:780px; border:1px solid #ddd; border-radius:6px; overflow:auto;"
scrolling="yes"
title="AIND Coordinate System Builder">
</iframe>
```

5 changes: 3 additions & 2 deletions src/aind_data_schema/components/configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from pydantic import Field, field_validator, model_validator
from pydantic_core.core_schema import ValidationInfo

from aind_data_schema.base import AwareDatetimeWithDefault, DataModel, DiscriminatedList, GenericModel
from aind_data_schema.base import AwareDatetimeWithDefault, DataModel, Discriminated, DiscriminatedList, GenericModel
from aind_data_schema.components.coordinates import (
TRANSFORM_TYPES,
AtlasCoordinate,
Expand All @@ -32,6 +32,7 @@
Translation,
)
from aind_data_schema.components.devices import DevicePosition
from aind_data_schema.components.geometry import Rectangle
from aind_data_schema.components.identifiers import Code
from aind_data_schema.components.wrappers import AssetPath

Expand Down Expand Up @@ -265,7 +266,7 @@ class Image(DataModel):
description="Position, rotation, and scale of the image. Note that depth should be in the planes.",
)

dimensions: Optional[Scale] = Field(default=None, title="Dimensions")
dimensions: Optional[Discriminated[Scale | Rectangle]] = Field(default=None, title="Dimensions")


class ImageSPIM(Image):
Expand Down
Loading
Loading