Skip to content
2 changes: 1 addition & 1 deletion docs/source/acquisition.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ while the StimulusEpoch represents all stimuli being presented.
| `instrument_name` | `Optional[str]` | Instrument name (Should match the Instrument.instrument_name. Required when instrument metadata is available.) |
| `acquisition_type` | `str` | Acquisition type (Descriptive string detailing the type of acquisition, should be consistent across similar acquisitions for the same experiment.) |
| `notes` | `Optional[str]` | Notes |
| `global_coordinate_system` | Optional[[CoordinateSystem](components/coordinates.md#coordinatesystem)] | Global coordinate system (Origin and axis definitions for determining the configured position of devices during acquisition. Required when coordinates are provided within the Acquisition) |
| `global_coordinate_system` | [CoordinateSystem](components/coordinates.md#coordinatesystem) or "Not applicable" | Global coordinate system (Origin and axis definitions for determining the configured position of devices during acquisition. Required when coordinates are provided within the Acquisition. Use 'Not applicable' when no global coordinate system applies.) |
| `calibrations` | List[[Calibration](components/measurements.md#calibration) or [VolumeCalibration](components/measurements.md#volumecalibration) or [PowerCalibration](components/measurements.md#powercalibration)] | Calibrations (List of calibration measurements taken prior to acquisition.) |
| `maintenance` | List[[Maintenance](components/measurements.md#maintenance)] | Maintenance (List of maintenance on instrument prior to acquisition.) |
| `data_streams` | List[[DataStream](acquisition.md#datastream) or [ExternalDataStream](acquisition.md#externaldatastream)] | Data streams (A data stream is a collection of devices that are acquiring data simultaneously. Each acquisition can include multiple streams. Streams should be split when configurations are changed. Use ExternalDataStream for acquisitions where instrument metadata is unavailable.) |
Expand Down
2 changes: 1 addition & 1 deletion docs/source/components/specimen_procedures.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ Description of a sectioning procedure performed on the coronal, sagittal, or tra

| Field | Type | Title (Description) |
|-------|------|-------------|
| `global_coordinate_system` | [CoordinateSystem](coordinates.md#coordinatesystem) or [Atlas](coordinates.md#atlas) or NoneType | Sectioning global coordinate system (Only required if different from the Procedures.global_coordinate_system) |
| `global_coordinate_system` | [CoordinateSystem](coordinates.md#coordinatesystem) or "Not applicable" or [Atlas](coordinates.md#atlas) | Sectioning global coordinate system (Origin and axis definitions for section coordinates. Required when coordinates are provided. Use 'Not applicable' when no global coordinate system applies.) |
| `sections` | List[[Section](#section) or [PlanarSection](#planarsection)] | Planar sections (Use PlanarSection for new implementations) |
| `section_orientation` | [SectionOrientation](#sectionorientation) | Sectioning orientation |

Expand Down
2 changes: 1 addition & 1 deletion docs/source/components/subject_procedures.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ Description of subject procedures performed at one time
| `weight_unit` | [MassUnit](../biodata_models/units.md#massunit) | Weight unit |
| `anaesthesia` | Optional[[Anaesthetic](surgery_procedures.md#anaesthetic)] | Anaesthesia |
| `workstation_id` | `Optional[str]` | Workstation ID |
| `global_coordinate_system` | Optional[[CoordinateSystem](coordinates.md#coordinatesystem)] | Surgery global coordinate system (Only required when the Surgery.global_coordinate_system is different from the Procedures.global_coordinate_system) |
| `global_coordinate_system` | [CoordinateSystem](coordinates.md#coordinatesystem) or "Not applicable" | Surgery global coordinate system (Origin and axis definitions for coordinates within this surgery. Required when coordinates are provided. Use 'Not applicable' when no global coordinate system applies.) |
| `measured_coordinates` | Optional[Dict[[Origin](../biodata_models/coordinates.md#origin), [Translation](coordinates.md#translation)]] | Measured coordinates (Coordinates measured during the procedure, for example Bregma and Lambda) |
| `procedures` | List[[CatheterImplant](surgery_procedures.md#catheterimplant) or [Craniotomy](surgery_procedures.md#craniotomy) or [DeviceImplant](surgery_procedures.md#deviceimplant) or [ProbeImplant](surgery_procedures.md#probeimplant) or [Headframe](surgery_procedures.md#headframe) or [BrainInjection](surgery_procedures.md#braininjection) or [Injection](injection_procedures.md#injection) or [MyomatrixInsertion](surgery_procedures.md#myomatrixinsertion) or [GenericSurgeryProcedure](surgery_procedures.md#genericsurgeryprocedure) or [Perfusion](surgery_procedures.md#perfusion) or [SampleCollection](surgery_procedures.md#samplecollection)] | Procedures |
| `notes` | `Optional[str]` | Notes |
Expand Down
32 changes: 29 additions & 3 deletions docs/source/coordinate_systems.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ The metadata schema supports flexible definitions of coordinate systems. This al

Unlike many parts of the metadata schema where fields are just floats or strings, it is critical to understand **how coordinate systems are stored in the schema** to be able to use them properly. There are two rules to be aware of:

1. Each [Instrument](instrument.md), [Acquisition](acquisition.md), and [Procedures](procedures.md) has its own `.global_coordinate_system` field. In most assets, the global coordinate system is the same in all three files.
2. Local to global transforms (i.e. a [Translation](components/coordinates.md#translation), [Rotation](components/coordinates.md#rotation), or [Scale](components/coordinates.md#scale)) that position devices or configurations of devices **must be defined in it's core file's coordinate system**. To help you avoid mistakes, these transform fields are paired with a `.coordinate_system_name` field which must match the name of the global coordinate system defined in the core file.
1. Each [Instrument](instrument.md) and [Acquisition](acquisition.md) has its own `.global_coordinate_system` field. In the Procedures, [Surgery](components/subject_procedures.md#surgery) and [PlanarSectioning](components/specimen_procedures.md#planarsectioning) each define their `.global_coordinate_system`.
2. Local to global transforms (i.e. a [Translation](components/coordinates.md#translation), [Rotation](components/coordinates.md#rotation), or [Scale](components/coordinates.md#scale)) that position devices or configurations of devices **must use the global coordinate system of their instrument, acquisition, or individual procedure**. Where a `.coordinate_system_name` field accompanies transforms, it must match that frame's name.

The top-level coordinate systems in the instrument, acquisition, and procedures are generally defined in *in vivo* space, usually relative to an origin on an animal's skull. Often when targeting coordinates in the brain we plan our experiments in a **standardized atlas** like the mouse common coordinate framework. When you encounter a field that that requires an atlas transform (i.e. a point or vector in an atlas), you'll see that an [Atlas](components/coordinates.md#atlas) will have to be defined alongside that transform. An Atlas library is available in `biodata_schema.components.coordinates.AtlasLibrary` for your convenience.
The global coordinate systems in the instrument, acquisition, and individual procedures are generally defined in *in vivo* space, usually relative to an origin on an animal's skull. Often when targeting coordinates in the brain we plan our experiments in a **standardized atlas** like the mouse common coordinate framework. When you encounter a field that that requires an atlas transform (i.e. a point or vector in an atlas), you'll see that an [Atlas](components/coordinates.md#atlas) will have to be defined alongside that transform. An Atlas library is available in `biodata_schema.components.coordinates.AtlasLibrary` for your convenience.

## CoordinateSystem

Expand All @@ -26,6 +26,32 @@ CoordinateSystem(
)
```

### Not Applicable

Global coordinate-system fields accept either a `CoordinateSystem` (including an `Atlas` where supported) or `CoordinateSystem.NotApplicable`, and default to `NotApplicable`. `None` is not accepted, and procedure frames are not inherited from a parent procedure collection.

Set a real frame on each instrument, acquisition, or individual procedure that contains transforms requiring that global frame. Validation rejects those transforms when the frame is `NotApplicable`. Local-reference transforms with an explicit local frame and atlas coordinates with their own frame can still be used without a global frame. A real coordinate system is also allowed when there are no transforms.

```{code} python
from biodata_schema.components.coordinates import CoordinateSystem
from biodata_schema.components.subject_procedures import Surgery
from biodata_schema.components.surgery_procedures import GenericSurgeryProcedure
from biodata_schema.core.procedures import Procedures

procedures = Procedures(
subject_name="12345",
subject_procedures=[
Surgery(
start_date="2026-10-15",
global_coordinate_system=CoordinateSystem.NotApplicable,
procedures=[GenericSurgeryProcedure(description="Non-coordinate procedure")],
)
],
)
```

To migrate existing metadata, move `Procedures.global_coordinate_system` onto each surgery or planar sectioning operation that previously relied on it. Replace `None` global frames with a real frame where coordinates require one, or with `NotApplicable` otherwise. Optional local coordinate-system fields are unchanged.

### Origin

An [Origin](biodata_models/coordinates.md#origin) is a point in space, often relative to the mouse's anatomy but it can also be a point on a device. The Origin defines the (0, 0, 0) coordinate in a coordinate system. Standard anatomical references are positions like Bregma or Lambda
Expand Down
2 changes: 1 addition & 1 deletion docs/source/instrument.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ Description of an instrument
| `modification_date` | `datetime.date` | Date of modification (Date of the last change to the instrument, hardware addition/removal, calibration, etc.) |
| `modalities` | List[[Modality](biodata_models/modalities.md#modality)] | Modalities (List of all possible modalities that the instrument is capable of acquiring) |
| `calibrations` | Optional[List[[Calibration](components/measurements.md#calibration) or [VolumeCalibration](components/measurements.md#volumecalibration) or [PowerCalibration](components/measurements.md#powercalibration)]] | Calibrations (List of calibration measurements takend during instrument setup and maintenance) |
| `global_coordinate_system` | [CoordinateSystem](components/coordinates.md#coordinatesystem) | Global coordinate system (Origin and axis definitions for determining the position of the instrument's components) |
| `global_coordinate_system` | [CoordinateSystem](components/coordinates.md#coordinatesystem) or "Not applicable" | Global coordinate system (Origin and axis definitions for determining the position of the instrument's components. Use 'Not applicable' when no global coordinate system applies.) |
| `temperature_control` | `Optional[bool]` | Temperature control (Does the instrument maintain a constant temperature?) |
| `notes` | `Optional[str]` | Notes |
| `connections` | List[[Connection](components/connections.md#connection)] | Connections (List of all connections between devices in the instrument) |
Expand Down
1 change: 0 additions & 1 deletion docs/source/procedures.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,4 @@ Description of all procedures performed on a subject, including surgeries, injec
| `subject_name` | `str` | Subject name (Unique name for the subject of data acquisition) |
| `subject_procedures` | List[[Surgery](components/subject_procedures.md#surgery) or [NonSurgicalInjection](components/subject_procedures.md#nonsurgicalinjection) or [TrainingProtocol](components/subject_procedures.md#trainingprotocol) or [WaterRestriction](components/subject_procedures.md#waterrestriction) or [GenericSubjectProcedure](components/subject_procedures.md#genericsubjectprocedure)] | Subject Procedures (Procedures performed on a live subject) |
| `specimen_procedures` | List[[SpecimenProcedure](components/specimen_procedures.md#specimenprocedure)] | Specimen Procedures (Procedures performed on tissue extracted after perfusion) |
| `global_coordinate_system` | Optional[[CoordinateSystem](components/coordinates.md#coordinatesystem)] | Global Coordinate System (Origin and axis definitions for determining the configured position of devices implanted during procedures. Required when coordinates are provided within the Procedures) |
| `notes` | `Optional[str]` | Notes |
17 changes: 2 additions & 15 deletions examples/aibs_smartspim_instrument.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@
import argparse
import datetime

from biodata_models.coordinates import AxisName, Direction, Origin
from biodata_models.modalities import Modality
from biodata_models.organizations import Organization
from biodata_models.units import SizeUnit

from biodata_schema.components.connections import Connection
from biodata_schema.components.coordinates import Axis, CoordinateSystem
from biodata_schema.components.coordinates import CoordinateSystem
from biodata_schema.components.devices import (
AdditionalImagingDevice,
Detector,
Expand All @@ -23,17 +21,6 @@
)
from biodata_schema.core.instrument import Instrument

SIPE_MONITOR_RTF = CoordinateSystem(
name="SIPE_MONITOR_RTF",
origin=Origin.FRONT_CENTER,
axis_unit=SizeUnit.MM,
axes=[
Axis(name=AxisName.X, direction=Direction.LR),
Axis(name=AxisName.Y, direction=Direction.DU),
Axis(name=AxisName.Z, direction=Direction.BF),
],
)

objective = Objective(
name="TLX Objective",
numerical_aperture=0.2,
Expand Down Expand Up @@ -222,7 +209,7 @@
location="440",
instrument_name="SmartSPIM2",
modification_date=datetime.date(2023, 10, 4),
global_coordinate_system=SIPE_MONITOR_RTF,
global_coordinate_system=CoordinateSystem.NotApplicable,
modalities=[Modality.SPIM],
temperature_control=False,
components=[
Expand Down
17 changes: 2 additions & 15 deletions examples/aibs_smartspim_procedures.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,13 @@
import argparse
from datetime import date

from biodata_models.coordinates import AxisName, Direction, Origin
from biodata_models.organizations import Organization
from biodata_models.units import SizeUnit

from biodata_schema.components.coordinates import Axis, CoordinateSystem
from biodata_schema.components.coordinates import CoordinateSystem
from biodata_schema.components.reagent import Reagent
from biodata_schema.components.subject_procedures import Perfusion
from biodata_schema.core import procedures

BREGMA_ARI = CoordinateSystem(
name="BREGMA_ARI",
origin=Origin.BREGMA,
axis_unit=SizeUnit.MM,
axes=[
Axis(name=AxisName.AP, direction=Direction.PA),
Axis(name=AxisName.ML, direction=Direction.LR),
Axis(name=AxisName.SI, direction=Direction.SI),
],
)

experimenters = ["John Smith"]
specimen_name = "651286"

Expand All @@ -43,7 +30,7 @@
start_date=date(2022, 11, 17),
experimenters=["LAS"],
ethics_review_id="2234",
global_coordinate_system=BREGMA_ARI,
global_coordinate_system=CoordinateSystem.NotApplicable,
procedures=[
Perfusion(
protocol_id="dx.doi.org/10.17504/protocols.io.8epv51bejl1b/v6",
Expand Down
17 changes: 2 additions & 15 deletions examples/aind_smartspim_instrument.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@
import argparse
from datetime import date

from biodata_models.coordinates import AxisName, Direction, Origin
from biodata_models.modalities import Modality
from biodata_models.organizations import Organization
from biodata_models.units import SizeUnit

from biodata_schema.components.connections import Connection
from biodata_schema.components.coordinates import Axis, CoordinateSystem
from biodata_schema.components.coordinates import CoordinateSystem
from biodata_schema.components.devices import (
Device,
Filter,
Expand All @@ -24,17 +22,6 @@
Objective,
)

SPIM_RPI = CoordinateSystem(
name="SPIM_RPI",
origin=Origin.ORIGIN,
axis_unit=SizeUnit.MM,
axes=[
Axis(name=AxisName.X, direction=Direction.LR),
Axis(name=AxisName.Y, direction=Direction.AP),
Axis(name=AxisName.Z, direction=Direction.SI),
],
)

objective_1 = Objective(
name="TLX Objective 1",
numerical_aperture=0.2,
Expand Down Expand Up @@ -264,7 +251,7 @@
location="440",
instrument_name="SmartSPIM1",
modification_date=date(2023, 10, 4),
global_coordinate_system=SPIM_RPI,
global_coordinate_system=CoordinateSystem.NotApplicable,
modalities=[Modality.SPIM],
components=[
scope,
Expand Down
2 changes: 2 additions & 0 deletions examples/barseq_acquisition.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@

from biodata_models.modalities import Modality

from biodata_schema.components.coordinates import CoordinateSystem
from biodata_schema.core.acquisition import Acquisition, ExternalDataStream

acquisition = Acquisition(
subject_name="123456",
global_coordinate_system=CoordinateSystem.NotApplicable,
specimen_name=["123456_bar001", "123456_bar002"],
acquisition_start_time=datetime(2025, 1, 1, 9, 0, 0, tzinfo=ZoneInfo("America/Los_Angeles")),
acquisition_end_time=datetime(2025, 1, 31, 17, 0, 0, tzinfo=ZoneInfo("America/Los_Angeles")),
Expand Down
16 changes: 2 additions & 14 deletions examples/barseq_instrument.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@
import argparse
from datetime import date

from biodata_models.coordinates import AxisName, Direction, Origin
from biodata_models.modalities import Modality
from biodata_models.organizations import Organization
from biodata_models.units import SizeUnit

from biodata_schema.components.coordinates import Axis, CoordinateSystem
from biodata_schema.components.coordinates import CoordinateSystem
from biodata_schema.components.devices import (
BinMode,
Camera,
Expand All @@ -24,17 +23,6 @@
)
from biodata_schema.core.instrument import Instrument

IMAGE_XYZ = CoordinateSystem(
name="IMAGE_XYZ",
origin=Origin.ORIGIN,
axis_unit=SizeUnit.PX,
axes=[
Axis(name=AxisName.X, direction=Direction.POS),
Axis(name=AxisName.Y, direction=Direction.POS),
Axis(name=AxisName.Z, direction=Direction.POS),
],
)

objectives = [
Objective(
name="20x Objective",
Expand Down Expand Up @@ -228,7 +216,7 @@
location="243",
instrument_name="Dogwood",
modification_date=date(2024, 7, 9),
global_coordinate_system=IMAGE_XYZ,
global_coordinate_system=CoordinateSystem.NotApplicable,
modalities=[Modality.BARSEQ],
notes=(
"BarSEQ imaging system with Nikon Ti2-E inverted microscope, X-Light V3 spinning disk confocal, "
Expand Down
1 change: 1 addition & 0 deletions examples/exaspim_acquisition.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@

acq = Acquisition(
experimenters=["John Smith"],
global_coordinate_system=SPIM_RPI,
specimen_name="123456-123",
subject_name="123456",
instrument_name="exaSPIM1",
Expand Down
18 changes: 3 additions & 15 deletions examples/exaspim_instrument.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@
import argparse
import datetime

from biodata_models.coordinates import AxisName, Direction, Origin
from biodata_models.modalities import Modality
from biodata_models.organizations import Organization
from biodata_models.units import FrequencyUnit, SizeUnit
from biodata_models.units import FrequencyUnit

from biodata_schema.components.connections import Connection
from biodata_schema.components.coordinates import Axis, CoordinateSystem
from biodata_schema.components.coordinates import CoordinateSystem
from biodata_schema.components.devices import (
AdditionalImagingDevice,
Computer,
Expand All @@ -25,17 +24,6 @@
)
from biodata_schema.core.instrument import Instrument

SPIM_RPI = CoordinateSystem(
name="SPIM_RPI",
origin=Origin.ORIGIN,
axis_unit=SizeUnit.MM,
axes=[
Axis(name=AxisName.X, direction=Direction.LR),
Axis(name=AxisName.Y, direction=Direction.AP),
Axis(name=AxisName.Z, direction=Direction.SI),
],
)

objectives = [
Objective(
name="Custom Objective",
Expand Down Expand Up @@ -284,7 +272,7 @@
instrument_name="exaSPIM1",
modalities=[Modality.SPIM],
modification_date=datetime.date(2023, 10, 4),
global_coordinate_system=SPIM_RPI,
global_coordinate_system=CoordinateSystem.NotApplicable,
components=[
*objectives,
*detectors,
Expand Down
Loading
Loading