From d1834f9a0a1be014f10ae035713f2e5d9d05d692 Mon Sep 17 00:00:00 2001 From: Dan Birman Date: Tue, 29 Sep 2026 17:19:06 -0700 Subject: [PATCH 1/2] refactor: scanner_coordinate_system -> local_coordinate_system --- src/biodata_schema/components/configs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/biodata_schema/components/configs.py b/src/biodata_schema/components/configs.py index ef8b18c2..c2b54dcf 100644 --- a/src/biodata_schema/components/configs.py +++ b/src/biodata_schema/components/configs.py @@ -585,7 +585,7 @@ class MRIScan(DeviceConfig): repetition_time_unit: TimeUnit = Field(default=TimeUnit.S, title="Repetition time unit") # fields required to get correct orientation - scanner_coordinate_system: Optional[CoordinateSystem] = Field(default=None, title="Scanner coordinate system") + local_coordinate_system: Optional[CoordinateSystem] = Field(default=None, title="Scanner coordinate system") affine_transform: Optional[TRANSFORM_TYPES] = Field( default=None, title="MRI Scan affine transform", description="NIFTI sform/qform, Bruker vc_transform, etc" ) From e4680791db753beea2473262d1c11b9daed2c3e8 Mon Sep 17 00:00:00 2001 From: Dan Birman Date: Mon, 5 Oct 2026 20:17:44 -0700 Subject: [PATCH 2/2] feat: cell line --- src/biodata_schema/components/subjects.py | 16 +++++++++ src/biodata_schema/core/subject.py | 16 ++++++--- tests/test_subjects.py | 41 +++++++++++++++++++++++ 3 files changed, 68 insertions(+), 5 deletions(-) diff --git a/src/biodata_schema/components/subjects.py b/src/biodata_schema/components/subjects.py index 749ca46a..6deac61a 100644 --- a/src/biodata_schema/components/subjects.py +++ b/src/biodata_schema/components/subjects.py @@ -5,6 +5,7 @@ from enum import Enum from typing import Annotated, List, Optional +from biodata_models.cell_line import CellLineModel from biodata_models.organizations import Organization from biodata_models.pid_names import PIDName from biodata_models.species import Species, Strain @@ -195,3 +196,18 @@ class CalibrationObject(DataModel): objects: Optional[list[Device]] = Field( default=None, title="Objects", description="For calibration objects that are built up from one or more devices." ) + + +class CellLine(DataModel): + """Description of a cultured cell line""" + + cell_line_name: str = Field(..., title="Cell line name") + cell_line_type: CellLineModel = Field( + ..., title="Cell line type", description="Use CellLineLookup.get_by_name/search_by_name to populate" + ) + species: Species.ONE_OF = Field(..., title="Species") + protein: PIDName = Field(..., title="Protein labeled", description="Protein uses UniProt registry") + gene: PIDName = Field(..., title="Gene targeted", description="Gene uses NCBI taxonomy") + cell_structure: str = Field(..., title="Cell structure protein found in") + fluorescent_protein: PIDName = Field(..., title="Fluorescent protein", description="Uses FPbase") + clone_number: Optional[int] = Field(default=None, title="Clone number") diff --git a/src/biodata_schema/core/subject.py b/src/biodata_schema/core/subject.py index 913ab53b..bba7927b 100644 --- a/src/biodata_schema/core/subject.py +++ b/src/biodata_schema/core/subject.py @@ -1,11 +1,17 @@ -"""schema for mostly mouse metadata""" +"""schema for subject metadata""" from typing import Annotated, Literal, Optional from pydantic import Field, SkipValidation from biodata_schema.base import DataCoreModel, Discriminated, DraftRequirement -from biodata_schema.components.subjects import CalibrationObject, HumanSubject, MouseSubject, NonHumanPrimateSubject +from biodata_schema.components.subjects import ( + CalibrationObject, + CellLine, + HumanSubject, + MouseSubject, + NonHumanPrimateSubject, +) class Subject(DataCoreModel): @@ -20,8 +26,8 @@ class Subject(DataCoreModel): title="Subject ID", ) - subject_details: Discriminated[MouseSubject | HumanSubject | NonHumanPrimateSubject | CalibrationObject] = Field( - ..., title="Subject Details" - ) + subject_details: Discriminated[ + MouseSubject | HumanSubject | NonHumanPrimateSubject | CellLine | CalibrationObject + ] = Field(..., title="Subject Details") notes: Optional[str] = Field(default=None, title="Notes") diff --git a/tests/test_subjects.py b/tests/test_subjects.py index d21db829..7be3a8b9 100644 --- a/tests/test_subjects.py +++ b/tests/test_subjects.py @@ -3,6 +3,7 @@ from datetime import datetime import pytest +from biodata_models.cell_line import CellLineModel from biodata_models.organizations import Organization from biodata_models.pid_names import PIDName from biodata_models.registries import Registry @@ -11,6 +12,7 @@ from biodata_schema.components.subjects import ( BreedingInfo, CalibrationObject, + CellLine, Housing, HumanSubject, LightCycle, @@ -230,3 +232,42 @@ def test_breeding_info(self): assert breeding_info.maternal_genotype == "wt/wt" assert breeding_info.paternal_id == "P001" assert breeding_info.paternal_genotype == "wt/wt" + + +class TestCellLine: + """Test the Cell Line model""" + + def test_cellline(self): + """Test of cell line""" + + subject = CellLine( + cell_line_name="AICS-0005", + cell_line_type=CellLineModel( + name="Human induced pluripotent stem cell line cell", + registry=Registry.CLO, + registry_identifier="CLO:0037308", + ), + species=Species.HUMAN, + protein=PIDName( + name="paxilin", + registry=Registry.UNIPROT, + registry_identifier="P49023", + ), + gene=PIDName( + name="paxilin", + abbreviation="PXN", + registry=Registry.NCBI, + registry_identifier="NM_0028593", + ), + cell_structure="cytoskeleton", + fluorescent_protein=PIDName( + name="enhanced GFP", + abbreviation="EGFP", + registry=Registry.FPbase, + registry_identifier="R9NL8", + ), + clone_number=1, + ) + + assert subject.cell_structure == "cytoskeleton" + assert subject.species == Species.HUMAN