Skip to content

Commit

Permalink
BREAKING CHANGE: InjectionDynamics
Browse files Browse the repository at this point in the history
BREAKING CHANGE: InjectionDynamics
  • Loading branch information
dbirman authored Mar 7, 2025
2 parents 8811d94 + 5b9e8a3 commit eae6cf4
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 67 deletions.
19 changes: 17 additions & 2 deletions docs/source/example_workflow/example_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,18 @@
from aind_data_schema_models.organizations import Organization

from aind_data_schema.core.data_description import Funding, RawDataDescription
from aind_data_schema.core.procedures import NanojectInjection, Perfusion, Procedures, Surgery, ViralMaterial
from aind_data_schema.core.procedures import (
NanojectInjection,
Perfusion,
Procedures,
Surgery,
ViralMaterial,
InjectionDynamics,
InjectionProfile,
)
from aind_data_schema.core.subject import BreedingInfo, Housing, Species, Subject
from aind_data_schema_models.species import Strain
from aind_data_schema_models.units import VolumeUnit

from aind_data_schema.components.identifiers import Person

Expand Down Expand Up @@ -105,7 +114,13 @@
injection_angle=float(coords[3]),
# multiple injection volumes at different depths are allowed, but that's not happening here
injection_coordinate_depth=[float(coords[2])],
injection_volume=[float(proc_row["injection_volume"])],
dynamics=[
InjectionDynamics(
volume=proc_row["injection_volume"],
volume_unit=VolumeUnit.NL,
profile=InjectionProfile.BOLUS,
)
],
)
],
),
Expand Down
11 changes: 10 additions & 1 deletion examples/ophys_procedures.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@
Surgery,
ViralMaterial,
WaterRestriction,
InjectionDynamics,
InjectionProfile,
)
from aind_data_schema_models.units import VolumeUnit
from aind_data_schema_models.brain_atlas import CCFStructure

t = datetime.datetime(2022, 7, 12, 7, 00, 00)
Expand Down Expand Up @@ -68,7 +71,13 @@
injection_coordinate_depth=[-4.2],
injection_coordinate_reference="Bregma",
injection_angle=0,
injection_volume=[400],
dynamics=[
InjectionDynamics(
volume=400,
volume_unit=VolumeUnit.NL,
profile=InjectionProfile.BOLUS,
)
],
targeted_structure=CCFStructure.VTA,
),
FiberImplant(
Expand Down
11 changes: 10 additions & 1 deletion examples/procedures.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@
Surgery,
TarsVirusIdentifiers,
ViralMaterial,
InjectionDynamics,
InjectionProfile,
)
from aind_data_schema_models.brain_atlas import CCFStructure
from aind_data_schema_models.units import VolumeUnit

# If a timezone isn't specified, the timezone of the computer running this
# script will be used as default
Expand Down Expand Up @@ -62,7 +65,13 @@
injection_coordinate_reference="Lambda",
bregma_to_lambda_distance=4.1,
injection_angle=10,
injection_volume=[200],
dynamics=[
InjectionDynamics(
volume=200,
volume_unit=VolumeUnit.NL,
profile=InjectionProfile.BOLUS,
)
],
targeted_structure=CCFStructure.VISP,
),
],
Expand Down
79 changes: 37 additions & 42 deletions src/aind_data_schema/core/procedures.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,14 @@ class SampleType(str, Enum):
OTHER = "Other"


class InjectionProfile(str, Enum):
"""Injection profile"""

BOLUS = "Bolus"
CONTINUOUS = "Continuous"
PULSED = "Pulsed"


class Readout(Reagent):
"""Description of a readout"""

Expand Down Expand Up @@ -424,6 +432,25 @@ class NonViralMaterial(Reagent):
)


class InjectionDynamics(DataModel):
"""Description of the volume and rate of an injection"""

profile: InjectionProfile = Field(..., title="Injection profile")

volume: Optional[Decimal] = Field(default=None, title="Injection volume")
volume_unit: Optional[VolumeUnit] = Field(default=None, title="Injection volume unit")

rate: Optional[Decimal] = Field(default=None, title="Injection rate")
rate_unit: Optional[VolumeUnit] = Field(default=None, title="Injection rate unit")

duration: Optional[Decimal] = Field(default=None, title="Injection duration")
duration_unit: Optional[TimeUnit] = Field(default=None, title="Injection duration unit")

injection_current: Optional[Decimal] = Field(default=None, title="Injection current (uA)")
injection_current_unit: Optional[CurrentUnit] = Field(default=None, title="Injection current unit")
alternating_current: Optional[str] = Field(default=None, title="Alternating current")


class Injection(DataModel):
"""Description of an injection procedure"""

Expand All @@ -432,26 +459,24 @@ class Injection(DataModel):
] = Field(..., title="Injection material", min_length=1)
recovery_time: Optional[Decimal] = Field(default=None, title="Recovery time")
recovery_time_unit: Optional[TimeUnit] = Field(default=None, title="Recovery time unit")
injection_duration: Optional[Decimal] = Field(default=None, title="Injection duration")
injection_duration_unit: Optional[TimeUnit] = Field(default=None, title="Injection duration unit")
# [TODO] Placeholder for injection target/coordinate information
dynamics: List[InjectionDynamics] = Field(
..., title="Injection dynamics", description="List of injection events, one per location/depth"
)
instrument_id: Optional[str] = Field(default=None, title="Instrument ID")
protocol_id: str = Field(..., title="Protocol ID", description="DOI for protocols.io")


class RetroOrbitalInjection(Injection):
"""Description of a retro-orbital injection procedure"""

injection_volume: Decimal = Field(..., title="Injection volume (uL)")
injection_volume_unit: VolumeUnit = Field(default=VolumeUnit.UL, title="Injection volume unit")
injection_eye: Side = Field(..., title="Injection eye")


class IntraperitonealInjection(Injection):
"""Description of an intraperitoneal injection procedure"""

time: Optional[AwareDatetimeWithDefault] = Field(default=None, title="Injection time")
injection_volume: Decimal = Field(..., title="Injection volume (uL)")
injection_volume_unit: VolumeUnit = Field(default=VolumeUnit.UL, title="Injection volume unit")


class BrainInjection(Injection):
Expand All @@ -477,54 +502,25 @@ class BrainInjection(Injection):
class NanojectInjection(BrainInjection):
"""Description of a nanoject injection procedure"""

injection_volume: List[Decimal] = Field(
...,
title="Injection volume (nL)",
description="Injection volume, one value per location",
)
injection_volume_unit: VolumeUnit = Field(VolumeUnit.NL, title="Injection volume unit")

@field_validator("injection_volume")
def check_dv_and_vol_list_lengths(cls, v, info: ValidationInfo):
@model_validator(mode="after")
def check_dv_and_vol_list_lengths(values):
"""Validator for list length of injection volumes and depths"""

injection_vol_len = len(v)
coords_len = len(info.data["injection_coordinate_depth"])
dynamics_len = len(values.dynamics)
coords_len = len(values.injection_coordinate_depth)

if injection_vol_len != coords_len:
if dynamics_len != coords_len:
raise AssertionError("Unmatched list sizes for injection volumes and coordinate depths")
return v


class IontophoresisInjection(BrainInjection):
"""Description of an iotophoresis injection procedure"""

injection_current: Decimal = Field(..., title="Injection current (uA)")
injection_current_unit: CurrentUnit = Field(default=CurrentUnit.UA, title="Injection current unit")
alternating_current: str = Field(..., title="Alternating current")
return values


class IntraCerebellarVentricleInjection(BrainInjection):
"""Description of an interacerebellar ventricle injection"""

injection_volume: List[Decimal] = Field(
...,
title="Injection volume (nL)",
description="Injection volume, one value per location",
)
injection_volume_unit: VolumeUnit = Field(VolumeUnit.NL, title="Injection volume unit")


class IntraCisternalMagnaInjection(BrainInjection):
"""Description of an interacisternal magna injection"""

injection_volume: List[Decimal] = Field(
...,
title="Injection volume (nL)",
description="Injection volume, one value per location",
)
injection_volume_unit: VolumeUnit = Field(VolumeUnit.NL, title="Injection volume unit")


class SampleCollection(DataModel):
"""Description of a single sample collection"""
Expand Down Expand Up @@ -668,7 +664,6 @@ class Surgery(DataModel):
IntraCerebellarVentricleInjection,
IntraCisternalMagnaInjection,
IntraperitonealInjection,
IontophoresisInjection,
MyomatrixInsertion,
NanojectInjection,
OtherSubjectProcedure,
Expand Down
Loading

0 comments on commit eae6cf4

Please sign in to comment.