From af2896507d69d52e070306bcec81132e5ce5e34e Mon Sep 17 00:00:00 2001 From: Dan Birman Date: Tue, 24 Feb 2026 11:40:17 -0800 Subject: [PATCH 1/7] feat: working on procedures_sectioning example --- examples/procedures_sectioning.py | 325 ++++++++++++++++++++++++++++++ 1 file changed, 325 insertions(+) create mode 100644 examples/procedures_sectioning.py diff --git a/examples/procedures_sectioning.py b/examples/procedures_sectioning.py new file mode 100644 index 000000000..1d6b3c93d --- /dev/null +++ b/examples/procedures_sectioning.py @@ -0,0 +1,325 @@ +"""Examples of BarSEQ/MapSEQ sectioning procedures""" + +from datetime import date +from typing import List, Optional + +from aind_data_schema_models.brain_atlas import CCFv3 +from aind_data_schema_models.units import SizeUnit +from aind_data_schema_models.coordinates import AnatomicalRelative + +from aind_data_schema.components.coordinates import AtlasLibrary, Translation +from aind_data_schema.components.specimen_procedures import ( + PlanarSectioning, + Section, + Sectioning, + SectionOrientation, + SpecimenProcedure, +) +from aind_data_schema.core.procedures import Procedures + + +def create_section( + specimen_id: str, + section_id: str, + coordinate_system_name: str, + start_um: float, + thickness: float, + thickness_unit: SizeUnit, + partial_slice: Optional[List[AnatomicalRelative]] = None, +) -> Section: + return Section( + output_specimen_id=f"{specimen_id}_{section_id}", + coordinate_system_name=coordinate_system_name, + start_coordinate=Translation(translation=[round(start_um), 0, 0]), + thickness=thickness, + thickness_unit=thickness_unit, + partial_slice=partial_slice, + ) + + +def create_uniform_sections( + specimen_id: str, + start_section_num: int, + num_sections: int, + start_um: float, + thickness: float, + thickness_unit: SizeUnit, + coordinate_system_name: str = "CCF", + section_prefix: str = "sec", + partial_slice: Optional[List[AnatomicalRelative]] = None, +) -> List[Section]: + return [ + create_section( + specimen_id=specimen_id, + section_id=f"{section_prefix}{start_section_num + i:03d}", + coordinate_system_name=coordinate_system_name, + start_um=start_um + i * thickness, + thickness=thickness, + thickness_unit=thickness_unit, + partial_slice=partial_slice, + ) + for i in range(num_sections) + ] + + +def create_nonuniform_sections( + specimen_id: str, + num_sections: int, + start_positions_um: List[float], + thickness: float, + thickness_unit: SizeUnit, + coordinate_system_name: str = "CCF", + section_prefix: str = "sec", + partial_slice: Optional[List[AnatomicalRelative]] = None, + start_section_num: int = 1, +) -> List[Section]: + if num_sections != len(start_positions_um): + raise ValueError("num_sections and start_positions_um must have same length") + + return [ + create_section( + specimen_id=specimen_id, + section_id=f"{section_prefix}{start_section_num + i:03d}", + coordinate_system_name=coordinate_system_name, + start_um=start_um, + thickness=thickness, + thickness_unit=thickness_unit, + partial_slice=partial_slice, + ) + for i, start_um in enumerate(start_positions_um) + ] + + +def create_planar_sectioning( + sections: List[Section], + section_orientation: SectionOrientation = SectionOrientation.CORONAL, +) -> PlanarSectioning: + return PlanarSectioning( + sections=sections, + section_orientation=section_orientation, + ) + + +def generate_mapseq_slides_780345_first_batch(start_section_num: int = 1) -> PlanarSectioning: + start_positions = [i * (9800 / 27) for i in range(27)] + + sections = create_nonuniform_sections( + specimen_id="780345", + num_sections=27, + start_positions_um=start_positions, + thickness=300, + thickness_unit=SizeUnit.UM, + section_prefix="map", + partial_slice=[AnatomicalRelative.LEFT], + start_section_num=start_section_num, + ) + + return create_planar_sectioning(sections) + + +def generate_barseq_lc_780345(start_section_num: int = 1) -> PlanarSectioning: + sections = create_uniform_sections( + specimen_id="780345", + start_section_num=start_section_num, + num_sections=44, + start_um=9900, + thickness=20, + thickness_unit=SizeUnit.UM, + section_prefix="bar", + ) + + return create_planar_sectioning(sections) + + +def generate_mapseq_slides_780345_second_batch(start_section_num: int = 28) -> PlanarSectioning: + start_positions = [11200 + i * (2000 / 12) for i in range(12)] + + sections = create_nonuniform_sections( + specimen_id="780345", + num_sections=12, + start_positions_um=start_positions, + thickness=300, + thickness_unit=SizeUnit.UM, + section_prefix="map", + partial_slice=[AnatomicalRelative.LEFT], + start_section_num=start_section_num, + ) + + return create_planar_sectioning(sections) + + +def generate_mapseq_spinal_780345() -> Sectioning: + return Sectioning( + sections=[ + Section( + output_specimen_id="780345_spinal", + targeted_structure=CCFv3.CST, + ) + ] + ) + + +def generate_mapseq_slides_780346_first_batch(start_section_num: int = 1) -> PlanarSectioning: + start_positions = [i * (9800 / 30) for i in range(30)] + + sections = create_nonuniform_sections( + specimen_id="780346", + num_sections=30, + start_positions_um=start_positions, + thickness=300, + thickness_unit=SizeUnit.UM, + section_prefix="map", + partial_slice=[AnatomicalRelative.LEFT], + start_section_num=start_section_num, + ) + + return create_planar_sectioning(sections) + + +def generate_barseq_lc_780346(start_section_num: int = 1) -> PlanarSectioning: + sections = create_uniform_sections( + specimen_id="780346", + start_section_num=start_section_num, + num_sections=51, + start_um=9900, + thickness=20, + thickness_unit=SizeUnit.UM, + section_prefix="bar", + ) + + return create_planar_sectioning(sections) + + +def generate_mapseq_slides_780346_second_batch(start_section_num: int = 31) -> PlanarSectioning: + start_positions = [11200 + i * (2000 / 9) for i in range(9)] + + sections = create_nonuniform_sections( + specimen_id="780346", + num_sections=9, + start_positions_um=start_positions, + thickness=300, + thickness_unit=SizeUnit.UM, + section_prefix="map", + partial_slice=[AnatomicalRelative.LEFT], + start_section_num=start_section_num, + ) + + return create_planar_sectioning(sections) + + +def generate_mapseq_spinal_780346() -> Sectioning: + return Sectioning( + sections=[ + Section( + output_specimen_id="780346_spinal", + targeted_structure=CCFv3.CST, + ) + ] + ) + + +def generate_procedures_780345() -> Procedures: + return Procedures( + subject_id="780345", + coordinate_system=AtlasLibrary.CCFv3_10um, + specimen_procedures=[ + SpecimenProcedure( + procedure_type="Sectioning", + specimen_id="780345", + start_date=date(2024, 1, 1), + end_date=date(2024, 1, 1), + experimenters=["Polina Kosillo"], + procedure_details=[generate_mapseq_slides_780345_first_batch()], + notes="MAPseq sections 1-27 covering plates 0-98 (300um thick, partial slices)", + ), + SpecimenProcedure( + procedure_type="Sectioning", + specimen_id="780345", + start_date=date(2024, 1, 1), + end_date=date(2024, 1, 1), + experimenters=["Polina Kosillo"], + procedure_details=[generate_barseq_lc_780345()], + notes="BARseq LC sections 1-44 covering plates 99-112 (20um thick)", + ), + SpecimenProcedure( + procedure_type="Sectioning", + specimen_id="780345", + start_date=date(2024, 1, 1), + end_date=date(2024, 1, 1), + experimenters=["Polina Kosillo"], + procedure_details=[generate_mapseq_slides_780345_second_batch()], + notes="MAPseq sections 28-39 covering plates 112-132 (300um thick, partial slices)", + ), + SpecimenProcedure( + procedure_type="Sectioning", + specimen_id="780345", + start_date=date(2024, 1, 1), + end_date=date(2024, 1, 1), + experimenters=["Polina Kosillo"], + procedure_details=[generate_mapseq_spinal_780345()], + notes="MAPseq spinal cord CST section, 1mm length", + ), + ], + ) + + +def generate_procedures_780346() -> Procedures: + return Procedures( + subject_id="780346", + coordinate_system=AtlasLibrary.CCFv3_10um, + specimen_procedures=[ + SpecimenProcedure( + procedure_type="Sectioning", + specimen_id="780346", + start_date=date(2024, 1, 1), + end_date=date(2024, 1, 1), + experimenters=["Polina Kosillo"], + procedure_details=[generate_mapseq_slides_780346_first_batch()], + notes="MAPseq sections 1-30 covering plates 0-98 (300um thick, partial slices)", + ), + SpecimenProcedure( + procedure_type="Sectioning", + specimen_id="780346", + start_date=date(2024, 1, 1), + end_date=date(2024, 1, 1), + experimenters=["Polina Kosillo"], + procedure_details=[generate_barseq_lc_780346()], + notes="BARseq LC sections 1-51 covering plates 99-112 (20um thick)", + ), + SpecimenProcedure( + procedure_type="Sectioning", + specimen_id="780346", + start_date=date(2024, 1, 1), + end_date=date(2024, 1, 1), + experimenters=["Polina Kosillo"], + procedure_details=[generate_mapseq_slides_780346_second_batch()], + notes="MAPseq sections 31-39 covering plates 112-132 (300um thick, partial slices)", + ), + SpecimenProcedure( + procedure_type="Sectioning", + specimen_id="780346", + start_date=date(2024, 1, 1), + end_date=date(2024, 1, 1), + experimenters=["Polina Kosillo"], + procedure_details=[generate_mapseq_spinal_780346()], + notes="MAPseq spinal cord CST section, 1mm length", + ), + ], + ) + + +if __name__ == "__main__": + procedures_780345 = generate_procedures_780345() + procedures_780346 = generate_procedures_780346() + + serialized_780345 = procedures_780345.model_dump_json(indent=2) + print("Specimen 780345:") + print(serialized_780345) + print("\n") + + serialized_780346 = procedures_780346.model_dump_json(indent=2) + print("Specimen 780346:") + print(serialized_780346) + + procedures_780345.write_standard_file(filename_suffix="780345") + procedures_780346.write_standard_file(filename_suffix="780346") From 352a5d802a144ed7e37297631bdfbe6da36ed148 Mon Sep 17 00:00:00 2001 From: Dan Birman Date: Wed, 25 Feb 2026 18:34:44 -0800 Subject: [PATCH 2/7] feat: continuing to develop chunk sections --- examples/mapseq_slide_regions.csv | 46 +++++++ examples/procedures_sectioning.py | 123 +++++++++++++++--- .../components/specimen_procedures.py | 2 +- src/aind_data_schema/core/procedures.py | 12 +- tests/test_procedures.py | 14 ++ 5 files changed, 172 insertions(+), 25 deletions(-) create mode 100644 examples/mapseq_slide_regions.csv diff --git a/examples/mapseq_slide_regions.csv b/examples/mapseq_slide_regions.csv new file mode 100644 index 000000000..306836395 --- /dev/null +++ b/examples/mapseq_slide_regions.csv @@ -0,0 +1,46 @@ +slide_num,section_start,section_end,chunk_name,ccf_acronym,includes_surrounding_tissue,notes +1,1,3,MOB,MOB,False,Main olfactory bulb +2,4,6,MOB,MOB,False,Main olfactory bulb +3,7,9,ORB,ORB,False,Orbital area (orbitofrontal cortex) +3,7,9,MO,MO,False,Somatomotor areas (motor cortex) +3,7,9,AON,AON,False,Anterior olfactory nucleus +4,10,12,ORB,ORB,False,Orbital area (orbitofrontal cortex) +4,10,12,MO,MO,False,Somatomotor areas (motor cortex) +4,10,12,AON,AON,False,Anterior olfactory nucleus +5,13,15,CP,CP,False,Caudoputamen +5,13,15,ACB,ACB,False,Nucleus accumbens +5,13,15,LSX,LSX,False,Lateral septal complex +5,13,15,ctx_1,CTX,True,Superior/dorsal cortex ribbon (ctx 1 in figure) +5,13,15,ctx_2,CTX,True,Lateral cortex ribbon (ctx 2 in figure) +5,13,15,ctx_3,CTX,True,Inferior/ventrolateral cortex ribbon (ctx 3 in figure) +6,16,18,CP,CP,False,Caudoputamen +6,16,18,ACB,ACB,False,Nucleus accumbens +6,16,18,LSX,LSX,False,Lateral septal complex +6,16,18,ctx_1,CTX,True,Superior/dorsal cortex ribbon (ctx 1 in figure) +6,16,18,ctx_2,CTX,True,Lateral cortex ribbon (ctx 2 in figure) +6,16,18,ctx_3,CTX,True,Inferior/ventrolateral cortex ribbon (ctx 3 in figure) +7,19,21,CP,CP,False,Caudoputamen +7,19,21,LSX,LSX,False,Lateral septal complex +7,19,21,BST,BST,False,Bed nuclei of the stria terminalis (BNST) +7,19,21,ctx_1,CTX,True,Superior/dorsal cortex ribbon (ctx 1 in figure) +7,19,21,ctx_2,CTX,True,Lateral cortex ribbon (ctx 2 in figure) +7,19,21,ctx_3,CTX,True,Inferior/ventrolateral cortex ribbon (ctx 3 in figure) +8,22,24,HPF,HPF,False,Hippocampal formation +8,22,24,TH,TH,False,Thalamus +8,22,24,HY,HY,False,Hypothalamus +8,22,24,amygdala,BLA,True,Amygdala (targeting whole structure via BLA + surrounding tissue) +8,22,24,GPE,GPe,False,Globus pallidus external segment (GPe) +8,22,24,ctx_1,CTX,True,Superior/dorsal cortex ribbon (ctx 1 in figure) +8,22,24,ctx_2,CTX,True,Lateral cortex ribbon (ctx 2 in figure) +8,22,24,ctx_3,CTX,True,Inferior/ventrolateral cortex ribbon (ctx 3 in figure) +9,25,27,MB,MB,False,Midbrain +9,25,27,ctx_1,CTX,True,Superior/dorsal cortex ribbon (ctx 1 in figure) +9,25,27,ctx_2,CTX,True,Lateral cortex ribbon (ctx 2 in figure) +9,25,27,ctx_3,CTX,True,Inferior/ventrolateral cortex ribbon (ctx 3 in figure) +10,28,30,MB,MB,False,Midbrain (more caudal) +10,28,30,HB,HB,False,Hindbrain +11,31,33,MB,MB,False,Midbrain (most caudal) +11,31,33,HB,HB,False,Hindbrain +12,34,36,CB,CB,False,Cerebellum +12,34,36,MY,MY,False,Medulla +13,37,39,MY,MY,False,Medulla diff --git a/examples/procedures_sectioning.py b/examples/procedures_sectioning.py index 1d6b3c93d..439472274 100644 --- a/examples/procedures_sectioning.py +++ b/examples/procedures_sectioning.py @@ -1,7 +1,9 @@ """Examples of BarSEQ/MapSEQ sectioning procedures""" +import csv from datetime import date -from typing import List, Optional +from pathlib import Path +from typing import Dict, List, Optional from aind_data_schema_models.brain_atlas import CCFv3 from aind_data_schema_models.units import SizeUnit @@ -10,6 +12,7 @@ from aind_data_schema.components.coordinates import AtlasLibrary, Translation from aind_data_schema.components.specimen_procedures import ( PlanarSectioning, + PlanarSection, Section, Sectioning, SectionOrientation, @@ -18,22 +21,90 @@ from aind_data_schema.core.procedures import Procedures -def create_section( + +def _load_slide_regions() -> Dict[int, dict]: + csv_path = Path(__file__).parent / "mapseq_slide_regions.csv" + slides: Dict[int, dict] = {} + with open(csv_path, newline="") as f: + for row in csv.DictReader(f): + slide = int(row["slide_num"]) + if slide not in slides: + slides[slide] = { + "section_start": int(row["section_start"]), + "section_end": int(row["section_end"]), + "chunks": [], + } + slides[slide]["chunks"].append({ + "chunk_name": row["chunk_name"], + "ccf_acronym": row["ccf_acronym"], + "includes_surrounding_tissue": row["includes_surrounding_tissue"] == "True", + "notes": row["notes"], + }) + return slides + + +def generate_mapseq_slide_chunks(specimen_id: str) -> List[SpecimenProcedure]: + slides = _load_slide_regions() + procedures = [] + for slide_num, slide_data in slides.items(): + section_start = slide_data["section_start"] + section_end = slide_data["section_end"] + chunks = slide_data["chunks"] + + input_ids = [ + f"{specimen_id}_map{i:03d}" + for i in range(section_start, section_end + 1) + ] + + output_sections = [] + for chunk_idx, chunk in enumerate(chunks, start=1): + structure = CCFv3.by_acronym(chunk["ccf_acronym"]) + surrounding = True if chunk["includes_surrounding_tissue"] else None + for sec_id in input_ids: + output_sections.append( + Section( + output_specimen_id=f"{sec_id}_{chunk_idx:03d}", + targeted_structure=structure, + includes_surrounding_tissue=surrounding, + ) + ) + + chunk_names = ", ".join(c["chunk_name"] for c in chunks) + ctx_notes = "; ".join( + c["notes"] for c in chunks if c["ccf_acronym"] == "CTX" + ) + note = f"Slide {slide_num}: sections {section_start}-{section_end} chunked into [{chunk_names}]" + if ctx_notes: + note += f". CTX chunks: {ctx_notes}" + + procedures.append( + SpecimenProcedure( + procedure_type="Sectioning", + specimen_id=input_ids, + start_date=date(2024, 1, 1), + end_date=date(2024, 1, 1), + experimenters=["Polina Kosillo"], + procedure_details=[Sectioning(sections=output_sections)], + notes=note, + ) + ) + return procedures + + +def create_planar_section( specimen_id: str, section_id: str, coordinate_system_name: str, start_um: float, thickness: float, thickness_unit: SizeUnit, - partial_slice: Optional[List[AnatomicalRelative]] = None, -) -> Section: - return Section( +) -> PlanarSection: + return PlanarSection( output_specimen_id=f"{specimen_id}_{section_id}", coordinate_system_name=coordinate_system_name, start_coordinate=Translation(translation=[round(start_um), 0, 0]), thickness=thickness, thickness_unit=thickness_unit, - partial_slice=partial_slice, ) @@ -46,17 +117,15 @@ def create_uniform_sections( thickness_unit: SizeUnit, coordinate_system_name: str = "CCF", section_prefix: str = "sec", - partial_slice: Optional[List[AnatomicalRelative]] = None, -) -> List[Section]: +) -> List[PlanarSection]: return [ - create_section( + create_planar_section( specimen_id=specimen_id, section_id=f"{section_prefix}{start_section_num + i:03d}", coordinate_system_name=coordinate_system_name, start_um=start_um + i * thickness, thickness=thickness, thickness_unit=thickness_unit, - partial_slice=partial_slice, ) for i in range(num_sections) ] @@ -70,28 +139,26 @@ def create_nonuniform_sections( thickness_unit: SizeUnit, coordinate_system_name: str = "CCF", section_prefix: str = "sec", - partial_slice: Optional[List[AnatomicalRelative]] = None, start_section_num: int = 1, -) -> List[Section]: +) -> List[PlanarSection]: if num_sections != len(start_positions_um): raise ValueError("num_sections and start_positions_um must have same length") return [ - create_section( + create_planar_section( specimen_id=specimen_id, section_id=f"{section_prefix}{start_section_num + i:03d}", coordinate_system_name=coordinate_system_name, start_um=start_um, thickness=thickness, thickness_unit=thickness_unit, - partial_slice=partial_slice, ) for i, start_um in enumerate(start_positions_um) ] def create_planar_sectioning( - sections: List[Section], + sections: List[PlanarSection], section_orientation: SectionOrientation = SectionOrientation.CORONAL, ) -> PlanarSectioning: return PlanarSectioning( @@ -110,7 +177,6 @@ def generate_mapseq_slides_780345_first_batch(start_section_num: int = 1) -> Pla thickness=300, thickness_unit=SizeUnit.UM, section_prefix="map", - partial_slice=[AnatomicalRelative.LEFT], start_section_num=start_section_num, ) @@ -141,7 +207,6 @@ def generate_mapseq_slides_780345_second_batch(start_section_num: int = 28) -> P thickness=300, thickness_unit=SizeUnit.UM, section_prefix="map", - partial_slice=[AnatomicalRelative.LEFT], start_section_num=start_section_num, ) @@ -154,6 +219,20 @@ def generate_mapseq_spinal_780345() -> Sectioning: Section( output_specimen_id="780345_spinal", targeted_structure=CCFv3.CST, + thickness=1000, + thickness_unit=SizeUnit.UM, + ), + Section( + output_specimen_id="780345_spinal", + targeted_structure=CCFv3.CST, + thickness=1000, + thickness_unit=SizeUnit.UM, + ), + Section( + output_specimen_id="780345_spinal", + targeted_structure=CCFv3.CST, + thickness=1000, + thickness_unit=SizeUnit.UM, ) ] ) @@ -169,7 +248,6 @@ def generate_mapseq_slides_780346_first_batch(start_section_num: int = 1) -> Pla thickness=300, thickness_unit=SizeUnit.UM, section_prefix="map", - partial_slice=[AnatomicalRelative.LEFT], start_section_num=start_section_num, ) @@ -200,7 +278,6 @@ def generate_mapseq_slides_780346_second_batch(start_section_num: int = 31) -> P thickness=300, thickness_unit=SizeUnit.UM, section_prefix="map", - partial_slice=[AnatomicalRelative.LEFT], start_section_num=start_section_num, ) @@ -213,6 +290,8 @@ def generate_mapseq_spinal_780346() -> Sectioning: Section( output_specimen_id="780346_spinal", targeted_structure=CCFv3.CST, + thickness=1000, + thickness_unit=SizeUnit.UM, ) ] ) @@ -257,8 +336,9 @@ def generate_procedures_780345() -> Procedures: end_date=date(2024, 1, 1), experimenters=["Polina Kosillo"], procedure_details=[generate_mapseq_spinal_780345()], - notes="MAPseq spinal cord CST section, 1mm length", + notes="MAPseq spinal cord sections, size is approximate (1/3rd length each)", ), + *generate_mapseq_slide_chunks("780345"), ], ) @@ -302,8 +382,9 @@ def generate_procedures_780346() -> Procedures: end_date=date(2024, 1, 1), experimenters=["Polina Kosillo"], procedure_details=[generate_mapseq_spinal_780346()], - notes="MAPseq spinal cord CST section, 1mm length", + notes="MAPseq spinal cord sections, size is approximate (1/3rd length each)", ), + *generate_mapseq_slide_chunks("780346"), ], ) diff --git a/src/aind_data_schema/components/specimen_procedures.py b/src/aind_data_schema/components/specimen_procedures.py index ed868a74f..4b26d0077 100644 --- a/src/aind_data_schema/components/specimen_procedures.py +++ b/src/aind_data_schema/components/specimen_procedures.py @@ -197,7 +197,7 @@ def validate_procedure_type(self): has_hcr_series = any(isinstance(detail, HCRSeries) for detail in self.procedure_details) has_fluorescent_stain = any(isinstance(detail, FluorescentStain) for detail in self.procedure_details) has_protein_probe = any(isinstance(detail, ProbeReagent) for detail in self.procedure_details) - has_sectioning = any(isinstance(detail, PlanarSectioning) for detail in self.procedure_details) + has_sectioning = any(isinstance(detail, Sectioning) for detail in self.procedure_details) has_geneprobeset = any(isinstance(detail, GeneProbeSet) for detail in self.procedure_details) if has_hcr_series + has_fluorescent_stain + has_sectioning + has_geneprobeset + has_protein_probe > 1: diff --git a/src/aind_data_schema/core/procedures.py b/src/aind_data_schema/core/procedures.py index a0a30d053..27ef4a9ee 100644 --- a/src/aind_data_schema/core/procedures.py +++ b/src/aind_data_schema/core/procedures.py @@ -79,9 +79,15 @@ def validate_subject_specimen_ids(self): # Return if no specimen procedures if self.specimen_procedures: subject_id = self.subject_id - specimen_ids = [spec_proc.specimen_id for spec_proc in self.specimen_procedures] - - if any(not subject_specimen_id_compatibility(subject_id, spec_id) for spec_id in specimen_ids): + flat_specimen_ids = [] + for spec_proc in self.specimen_procedures: + sid = spec_proc.specimen_id + if isinstance(sid, list): + flat_specimen_ids.extend(sid) + else: + flat_specimen_ids.append(sid) + + if any(not subject_specimen_id_compatibility(subject_id, spec_id) for spec_id in flat_specimen_ids): raise ValueError("specimen_id must be an extension of the subject_id.") return self diff --git a/tests/test_procedures.py b/tests/test_procedures.py index 2029cb33d..8d3c54adf 100644 --- a/tests/test_procedures.py +++ b/tests/test_procedures.py @@ -28,6 +28,7 @@ PlanarSection, PlanarSectioning, Section, + Sectioning, SectionOrientation, SpecimenProcedure, ) @@ -309,6 +310,19 @@ def test_validate_procedure_type(self): ) ) + self.assertIsNotNone( + SpecimenProcedure( + specimen_id="1000", + procedure_type="Sectioning", + start_date=date.fromisoformat("2020-10-10"), + end_date=date.fromisoformat("2020-10-11"), + experimenters=["Mam Moth"], + protocol_id=["10"], + notes=None, + procedure_details=[Sectioning(sections=[Section(output_specimen_id="1000_spinal")])], + ) + ) + def test_validate_procedure_type_multiple(self): """Test that error thrown when multiple types are passed to procedure_details""" From e0c534042b56b5e3dda0af895a89d47c05eace99 Mon Sep 17 00:00:00 2001 From: Dan Birman Date: Wed, 4 Mar 2026 13:06:45 -0800 Subject: [PATCH 3/7] chore: embed slide regions in python code --- examples/mapseq_slide_regions.csv | 46 ------------------ examples/procedures_sectioning.py | 81 ++++++++++++++++++++++++------- 2 files changed, 63 insertions(+), 64 deletions(-) delete mode 100644 examples/mapseq_slide_regions.csv diff --git a/examples/mapseq_slide_regions.csv b/examples/mapseq_slide_regions.csv deleted file mode 100644 index 306836395..000000000 --- a/examples/mapseq_slide_regions.csv +++ /dev/null @@ -1,46 +0,0 @@ -slide_num,section_start,section_end,chunk_name,ccf_acronym,includes_surrounding_tissue,notes -1,1,3,MOB,MOB,False,Main olfactory bulb -2,4,6,MOB,MOB,False,Main olfactory bulb -3,7,9,ORB,ORB,False,Orbital area (orbitofrontal cortex) -3,7,9,MO,MO,False,Somatomotor areas (motor cortex) -3,7,9,AON,AON,False,Anterior olfactory nucleus -4,10,12,ORB,ORB,False,Orbital area (orbitofrontal cortex) -4,10,12,MO,MO,False,Somatomotor areas (motor cortex) -4,10,12,AON,AON,False,Anterior olfactory nucleus -5,13,15,CP,CP,False,Caudoputamen -5,13,15,ACB,ACB,False,Nucleus accumbens -5,13,15,LSX,LSX,False,Lateral septal complex -5,13,15,ctx_1,CTX,True,Superior/dorsal cortex ribbon (ctx 1 in figure) -5,13,15,ctx_2,CTX,True,Lateral cortex ribbon (ctx 2 in figure) -5,13,15,ctx_3,CTX,True,Inferior/ventrolateral cortex ribbon (ctx 3 in figure) -6,16,18,CP,CP,False,Caudoputamen -6,16,18,ACB,ACB,False,Nucleus accumbens -6,16,18,LSX,LSX,False,Lateral septal complex -6,16,18,ctx_1,CTX,True,Superior/dorsal cortex ribbon (ctx 1 in figure) -6,16,18,ctx_2,CTX,True,Lateral cortex ribbon (ctx 2 in figure) -6,16,18,ctx_3,CTX,True,Inferior/ventrolateral cortex ribbon (ctx 3 in figure) -7,19,21,CP,CP,False,Caudoputamen -7,19,21,LSX,LSX,False,Lateral septal complex -7,19,21,BST,BST,False,Bed nuclei of the stria terminalis (BNST) -7,19,21,ctx_1,CTX,True,Superior/dorsal cortex ribbon (ctx 1 in figure) -7,19,21,ctx_2,CTX,True,Lateral cortex ribbon (ctx 2 in figure) -7,19,21,ctx_3,CTX,True,Inferior/ventrolateral cortex ribbon (ctx 3 in figure) -8,22,24,HPF,HPF,False,Hippocampal formation -8,22,24,TH,TH,False,Thalamus -8,22,24,HY,HY,False,Hypothalamus -8,22,24,amygdala,BLA,True,Amygdala (targeting whole structure via BLA + surrounding tissue) -8,22,24,GPE,GPe,False,Globus pallidus external segment (GPe) -8,22,24,ctx_1,CTX,True,Superior/dorsal cortex ribbon (ctx 1 in figure) -8,22,24,ctx_2,CTX,True,Lateral cortex ribbon (ctx 2 in figure) -8,22,24,ctx_3,CTX,True,Inferior/ventrolateral cortex ribbon (ctx 3 in figure) -9,25,27,MB,MB,False,Midbrain -9,25,27,ctx_1,CTX,True,Superior/dorsal cortex ribbon (ctx 1 in figure) -9,25,27,ctx_2,CTX,True,Lateral cortex ribbon (ctx 2 in figure) -9,25,27,ctx_3,CTX,True,Inferior/ventrolateral cortex ribbon (ctx 3 in figure) -10,28,30,MB,MB,False,Midbrain (more caudal) -10,28,30,HB,HB,False,Hindbrain -11,31,33,MB,MB,False,Midbrain (most caudal) -11,31,33,HB,HB,False,Hindbrain -12,34,36,CB,CB,False,Cerebellum -12,34,36,MY,MY,False,Medulla -13,37,39,MY,MY,False,Medulla diff --git a/examples/procedures_sectioning.py b/examples/procedures_sectioning.py index 439472274..fbedec31c 100644 --- a/examples/procedures_sectioning.py +++ b/examples/procedures_sectioning.py @@ -1,8 +1,6 @@ """Examples of BarSEQ/MapSEQ sectioning procedures""" -import csv from datetime import date -from pathlib import Path from typing import Dict, List, Optional from aind_data_schema_models.brain_atlas import CCFv3 @@ -22,24 +20,71 @@ +_SLIDE_REGIONS = [ + {"slide_num": 1, "section_start": 1, "section_end": 3, "chunk_name": "MOB", "ccf_acronym": "MOB", "includes_surrounding_tissue": False, "notes": "Main olfactory bulb"}, + {"slide_num": 2, "section_start": 4, "section_end": 6, "chunk_name": "MOB", "ccf_acronym": "MOB", "includes_surrounding_tissue": False, "notes": "Main olfactory bulb"}, + {"slide_num": 3, "section_start": 7, "section_end": 9, "chunk_name": "ORB", "ccf_acronym": "ORB", "includes_surrounding_tissue": False, "notes": "Orbital area (orbitofrontal cortex)"}, + {"slide_num": 3, "section_start": 7, "section_end": 9, "chunk_name": "MO", "ccf_acronym": "MO", "includes_surrounding_tissue": False, "notes": "Somatomotor areas (motor cortex)"}, + {"slide_num": 3, "section_start": 7, "section_end": 9, "chunk_name": "AON", "ccf_acronym": "AON", "includes_surrounding_tissue": False, "notes": "Anterior olfactory nucleus"}, + {"slide_num": 4, "section_start": 10, "section_end": 12, "chunk_name": "ORB", "ccf_acronym": "ORB", "includes_surrounding_tissue": False, "notes": "Orbital area (orbitofrontal cortex)"}, + {"slide_num": 4, "section_start": 10, "section_end": 12, "chunk_name": "MO", "ccf_acronym": "MO", "includes_surrounding_tissue": False, "notes": "Somatomotor areas (motor cortex)"}, + {"slide_num": 4, "section_start": 10, "section_end": 12, "chunk_name": "AON", "ccf_acronym": "AON", "includes_surrounding_tissue": False, "notes": "Anterior olfactory nucleus"}, + {"slide_num": 5, "section_start": 13, "section_end": 15, "chunk_name": "CP", "ccf_acronym": "CP", "includes_surrounding_tissue": False, "notes": "Caudoputamen"}, + {"slide_num": 5, "section_start": 13, "section_end": 15, "chunk_name": "ACB", "ccf_acronym": "ACB", "includes_surrounding_tissue": False, "notes": "Nucleus accumbens"}, + {"slide_num": 5, "section_start": 13, "section_end": 15, "chunk_name": "LSX", "ccf_acronym": "LSX", "includes_surrounding_tissue": False, "notes": "Lateral septal complex"}, + {"slide_num": 5, "section_start": 13, "section_end": 15, "chunk_name": "ctx_1", "ccf_acronym": "CTX", "includes_surrounding_tissue": True, "notes": "Superior/dorsal cortex ribbon (ctx 1 in figure)"}, + {"slide_num": 5, "section_start": 13, "section_end": 15, "chunk_name": "ctx_2", "ccf_acronym": "CTX", "includes_surrounding_tissue": True, "notes": "Lateral cortex ribbon (ctx 2 in figure)"}, + {"slide_num": 5, "section_start": 13, "section_end": 15, "chunk_name": "ctx_3", "ccf_acronym": "CTX", "includes_surrounding_tissue": True, "notes": "Inferior/ventrolateral cortex ribbon (ctx 3 in figure)"}, + {"slide_num": 6, "section_start": 16, "section_end": 18, "chunk_name": "CP", "ccf_acronym": "CP", "includes_surrounding_tissue": False, "notes": "Caudoputamen"}, + {"slide_num": 6, "section_start": 16, "section_end": 18, "chunk_name": "ACB", "ccf_acronym": "ACB", "includes_surrounding_tissue": False, "notes": "Nucleus accumbens"}, + {"slide_num": 6, "section_start": 16, "section_end": 18, "chunk_name": "LSX", "ccf_acronym": "LSX", "includes_surrounding_tissue": False, "notes": "Lateral septal complex"}, + {"slide_num": 6, "section_start": 16, "section_end": 18, "chunk_name": "ctx_1", "ccf_acronym": "CTX", "includes_surrounding_tissue": True, "notes": "Superior/dorsal cortex ribbon (ctx 1 in figure)"}, + {"slide_num": 6, "section_start": 16, "section_end": 18, "chunk_name": "ctx_2", "ccf_acronym": "CTX", "includes_surrounding_tissue": True, "notes": "Lateral cortex ribbon (ctx 2 in figure)"}, + {"slide_num": 6, "section_start": 16, "section_end": 18, "chunk_name": "ctx_3", "ccf_acronym": "CTX", "includes_surrounding_tissue": True, "notes": "Inferior/ventrolateral cortex ribbon (ctx 3 in figure)"}, + {"slide_num": 7, "section_start": 19, "section_end": 21, "chunk_name": "CP", "ccf_acronym": "CP", "includes_surrounding_tissue": False, "notes": "Caudoputamen"}, + {"slide_num": 7, "section_start": 19, "section_end": 21, "chunk_name": "LSX", "ccf_acronym": "LSX", "includes_surrounding_tissue": False, "notes": "Lateral septal complex"}, + {"slide_num": 7, "section_start": 19, "section_end": 21, "chunk_name": "BST", "ccf_acronym": "BST", "includes_surrounding_tissue": False, "notes": "Bed nuclei of the stria terminalis (BNST)"}, + {"slide_num": 7, "section_start": 19, "section_end": 21, "chunk_name": "ctx_1", "ccf_acronym": "CTX", "includes_surrounding_tissue": True, "notes": "Superior/dorsal cortex ribbon (ctx 1 in figure)"}, + {"slide_num": 7, "section_start": 19, "section_end": 21, "chunk_name": "ctx_2", "ccf_acronym": "CTX", "includes_surrounding_tissue": True, "notes": "Lateral cortex ribbon (ctx 2 in figure)"}, + {"slide_num": 7, "section_start": 19, "section_end": 21, "chunk_name": "ctx_3", "ccf_acronym": "CTX", "includes_surrounding_tissue": True, "notes": "Inferior/ventrolateral cortex ribbon (ctx 3 in figure)"}, + {"slide_num": 8, "section_start": 22, "section_end": 24, "chunk_name": "HPF", "ccf_acronym": "HPF", "includes_surrounding_tissue": False, "notes": "Hippocampal formation"}, + {"slide_num": 8, "section_start": 22, "section_end": 24, "chunk_name": "TH", "ccf_acronym": "TH", "includes_surrounding_tissue": False, "notes": "Thalamus"}, + {"slide_num": 8, "section_start": 22, "section_end": 24, "chunk_name": "HY", "ccf_acronym": "HY", "includes_surrounding_tissue": False, "notes": "Hypothalamus"}, + {"slide_num": 8, "section_start": 22, "section_end": 24, "chunk_name": "amygdala", "ccf_acronym": "BLA", "includes_surrounding_tissue": True, "notes": "Amygdala (targeting whole structure via BLA + surrounding tissue)"}, + {"slide_num": 8, "section_start": 22, "section_end": 24, "chunk_name": "GPE", "ccf_acronym": "GPe", "includes_surrounding_tissue": False, "notes": "Globus pallidus external segment (GPe)"}, + {"slide_num": 8, "section_start": 22, "section_end": 24, "chunk_name": "ctx_1", "ccf_acronym": "CTX", "includes_surrounding_tissue": True, "notes": "Superior/dorsal cortex ribbon (ctx 1 in figure)"}, + {"slide_num": 8, "section_start": 22, "section_end": 24, "chunk_name": "ctx_2", "ccf_acronym": "CTX", "includes_surrounding_tissue": True, "notes": "Lateral cortex ribbon (ctx 2 in figure)"}, + {"slide_num": 8, "section_start": 22, "section_end": 24, "chunk_name": "ctx_3", "ccf_acronym": "CTX", "includes_surrounding_tissue": True, "notes": "Inferior/ventrolateral cortex ribbon (ctx 3 in figure)"}, + {"slide_num": 9, "section_start": 25, "section_end": 27, "chunk_name": "MB", "ccf_acronym": "MB", "includes_surrounding_tissue": False, "notes": "Midbrain"}, + {"slide_num": 9, "section_start": 25, "section_end": 27, "chunk_name": "ctx_1", "ccf_acronym": "CTX", "includes_surrounding_tissue": True, "notes": "Superior/dorsal cortex ribbon (ctx 1 in figure)"}, + {"slide_num": 9, "section_start": 25, "section_end": 27, "chunk_name": "ctx_2", "ccf_acronym": "CTX", "includes_surrounding_tissue": True, "notes": "Lateral cortex ribbon (ctx 2 in figure)"}, + {"slide_num": 9, "section_start": 25, "section_end": 27, "chunk_name": "ctx_3", "ccf_acronym": "CTX", "includes_surrounding_tissue": True, "notes": "Inferior/ventrolateral cortex ribbon (ctx 3 in figure)"}, + {"slide_num": 10, "section_start": 28, "section_end": 30, "chunk_name": "MB", "ccf_acronym": "MB", "includes_surrounding_tissue": False, "notes": "Midbrain (more caudal)"}, + {"slide_num": 10, "section_start": 28, "section_end": 30, "chunk_name": "HB", "ccf_acronym": "HB", "includes_surrounding_tissue": False, "notes": "Hindbrain"}, + {"slide_num": 11, "section_start": 31, "section_end": 33, "chunk_name": "MB", "ccf_acronym": "MB", "includes_surrounding_tissue": False, "notes": "Midbrain (most caudal)"}, + {"slide_num": 11, "section_start": 31, "section_end": 33, "chunk_name": "HB", "ccf_acronym": "HB", "includes_surrounding_tissue": False, "notes": "Hindbrain"}, + {"slide_num": 12, "section_start": 34, "section_end": 36, "chunk_name": "CB", "ccf_acronym": "CB", "includes_surrounding_tissue": False, "notes": "Cerebellum"}, + {"slide_num": 12, "section_start": 34, "section_end": 36, "chunk_name": "MY", "ccf_acronym": "MY", "includes_surrounding_tissue": False, "notes": "Medulla"}, + {"slide_num": 13, "section_start": 37, "section_end": 39, "chunk_name": "MY", "ccf_acronym": "MY", "includes_surrounding_tissue": False, "notes": "Medulla"}, +] + + def _load_slide_regions() -> Dict[int, dict]: - csv_path = Path(__file__).parent / "mapseq_slide_regions.csv" slides: Dict[int, dict] = {} - with open(csv_path, newline="") as f: - for row in csv.DictReader(f): - slide = int(row["slide_num"]) - if slide not in slides: - slides[slide] = { - "section_start": int(row["section_start"]), - "section_end": int(row["section_end"]), - "chunks": [], - } - slides[slide]["chunks"].append({ - "chunk_name": row["chunk_name"], - "ccf_acronym": row["ccf_acronym"], - "includes_surrounding_tissue": row["includes_surrounding_tissue"] == "True", - "notes": row["notes"], - }) + for row in _SLIDE_REGIONS: + slide = row["slide_num"] + if slide not in slides: + slides[slide] = { + "section_start": row["section_start"], + "section_end": row["section_end"], + "chunks": [], + } + slides[slide]["chunks"].append({ + "chunk_name": row["chunk_name"], + "ccf_acronym": row["ccf_acronym"], + "includes_surrounding_tissue": row["includes_surrounding_tissue"], + "notes": row["notes"], + }) return slides From dc155abe0262da837402c4aa5661186016a56ec0 Mon Sep 17 00:00:00 2001 From: Dan Birman Date: Wed, 4 Mar 2026 13:07:06 -0800 Subject: [PATCH 4/7] chore: lint --- examples/procedures_sectioning.py | 496 +++++++++++++++++++++++++----- 1 file changed, 425 insertions(+), 71 deletions(-) diff --git a/examples/procedures_sectioning.py b/examples/procedures_sectioning.py index fbedec31c..89bf57f0d 100644 --- a/examples/procedures_sectioning.py +++ b/examples/procedures_sectioning.py @@ -1,11 +1,10 @@ """Examples of BarSEQ/MapSEQ sectioning procedures""" from datetime import date -from typing import Dict, List, Optional +from typing import Dict, List from aind_data_schema_models.brain_atlas import CCFv3 from aind_data_schema_models.units import SizeUnit -from aind_data_schema_models.coordinates import AnatomicalRelative from aind_data_schema.components.coordinates import AtlasLibrary, Translation from aind_data_schema.components.specimen_procedures import ( @@ -18,54 +17,412 @@ ) from aind_data_schema.core.procedures import Procedures - - _SLIDE_REGIONS = [ - {"slide_num": 1, "section_start": 1, "section_end": 3, "chunk_name": "MOB", "ccf_acronym": "MOB", "includes_surrounding_tissue": False, "notes": "Main olfactory bulb"}, - {"slide_num": 2, "section_start": 4, "section_end": 6, "chunk_name": "MOB", "ccf_acronym": "MOB", "includes_surrounding_tissue": False, "notes": "Main olfactory bulb"}, - {"slide_num": 3, "section_start": 7, "section_end": 9, "chunk_name": "ORB", "ccf_acronym": "ORB", "includes_surrounding_tissue": False, "notes": "Orbital area (orbitofrontal cortex)"}, - {"slide_num": 3, "section_start": 7, "section_end": 9, "chunk_name": "MO", "ccf_acronym": "MO", "includes_surrounding_tissue": False, "notes": "Somatomotor areas (motor cortex)"}, - {"slide_num": 3, "section_start": 7, "section_end": 9, "chunk_name": "AON", "ccf_acronym": "AON", "includes_surrounding_tissue": False, "notes": "Anterior olfactory nucleus"}, - {"slide_num": 4, "section_start": 10, "section_end": 12, "chunk_name": "ORB", "ccf_acronym": "ORB", "includes_surrounding_tissue": False, "notes": "Orbital area (orbitofrontal cortex)"}, - {"slide_num": 4, "section_start": 10, "section_end": 12, "chunk_name": "MO", "ccf_acronym": "MO", "includes_surrounding_tissue": False, "notes": "Somatomotor areas (motor cortex)"}, - {"slide_num": 4, "section_start": 10, "section_end": 12, "chunk_name": "AON", "ccf_acronym": "AON", "includes_surrounding_tissue": False, "notes": "Anterior olfactory nucleus"}, - {"slide_num": 5, "section_start": 13, "section_end": 15, "chunk_name": "CP", "ccf_acronym": "CP", "includes_surrounding_tissue": False, "notes": "Caudoputamen"}, - {"slide_num": 5, "section_start": 13, "section_end": 15, "chunk_name": "ACB", "ccf_acronym": "ACB", "includes_surrounding_tissue": False, "notes": "Nucleus accumbens"}, - {"slide_num": 5, "section_start": 13, "section_end": 15, "chunk_name": "LSX", "ccf_acronym": "LSX", "includes_surrounding_tissue": False, "notes": "Lateral septal complex"}, - {"slide_num": 5, "section_start": 13, "section_end": 15, "chunk_name": "ctx_1", "ccf_acronym": "CTX", "includes_surrounding_tissue": True, "notes": "Superior/dorsal cortex ribbon (ctx 1 in figure)"}, - {"slide_num": 5, "section_start": 13, "section_end": 15, "chunk_name": "ctx_2", "ccf_acronym": "CTX", "includes_surrounding_tissue": True, "notes": "Lateral cortex ribbon (ctx 2 in figure)"}, - {"slide_num": 5, "section_start": 13, "section_end": 15, "chunk_name": "ctx_3", "ccf_acronym": "CTX", "includes_surrounding_tissue": True, "notes": "Inferior/ventrolateral cortex ribbon (ctx 3 in figure)"}, - {"slide_num": 6, "section_start": 16, "section_end": 18, "chunk_name": "CP", "ccf_acronym": "CP", "includes_surrounding_tissue": False, "notes": "Caudoputamen"}, - {"slide_num": 6, "section_start": 16, "section_end": 18, "chunk_name": "ACB", "ccf_acronym": "ACB", "includes_surrounding_tissue": False, "notes": "Nucleus accumbens"}, - {"slide_num": 6, "section_start": 16, "section_end": 18, "chunk_name": "LSX", "ccf_acronym": "LSX", "includes_surrounding_tissue": False, "notes": "Lateral septal complex"}, - {"slide_num": 6, "section_start": 16, "section_end": 18, "chunk_name": "ctx_1", "ccf_acronym": "CTX", "includes_surrounding_tissue": True, "notes": "Superior/dorsal cortex ribbon (ctx 1 in figure)"}, - {"slide_num": 6, "section_start": 16, "section_end": 18, "chunk_name": "ctx_2", "ccf_acronym": "CTX", "includes_surrounding_tissue": True, "notes": "Lateral cortex ribbon (ctx 2 in figure)"}, - {"slide_num": 6, "section_start": 16, "section_end": 18, "chunk_name": "ctx_3", "ccf_acronym": "CTX", "includes_surrounding_tissue": True, "notes": "Inferior/ventrolateral cortex ribbon (ctx 3 in figure)"}, - {"slide_num": 7, "section_start": 19, "section_end": 21, "chunk_name": "CP", "ccf_acronym": "CP", "includes_surrounding_tissue": False, "notes": "Caudoputamen"}, - {"slide_num": 7, "section_start": 19, "section_end": 21, "chunk_name": "LSX", "ccf_acronym": "LSX", "includes_surrounding_tissue": False, "notes": "Lateral septal complex"}, - {"slide_num": 7, "section_start": 19, "section_end": 21, "chunk_name": "BST", "ccf_acronym": "BST", "includes_surrounding_tissue": False, "notes": "Bed nuclei of the stria terminalis (BNST)"}, - {"slide_num": 7, "section_start": 19, "section_end": 21, "chunk_name": "ctx_1", "ccf_acronym": "CTX", "includes_surrounding_tissue": True, "notes": "Superior/dorsal cortex ribbon (ctx 1 in figure)"}, - {"slide_num": 7, "section_start": 19, "section_end": 21, "chunk_name": "ctx_2", "ccf_acronym": "CTX", "includes_surrounding_tissue": True, "notes": "Lateral cortex ribbon (ctx 2 in figure)"}, - {"slide_num": 7, "section_start": 19, "section_end": 21, "chunk_name": "ctx_3", "ccf_acronym": "CTX", "includes_surrounding_tissue": True, "notes": "Inferior/ventrolateral cortex ribbon (ctx 3 in figure)"}, - {"slide_num": 8, "section_start": 22, "section_end": 24, "chunk_name": "HPF", "ccf_acronym": "HPF", "includes_surrounding_tissue": False, "notes": "Hippocampal formation"}, - {"slide_num": 8, "section_start": 22, "section_end": 24, "chunk_name": "TH", "ccf_acronym": "TH", "includes_surrounding_tissue": False, "notes": "Thalamus"}, - {"slide_num": 8, "section_start": 22, "section_end": 24, "chunk_name": "HY", "ccf_acronym": "HY", "includes_surrounding_tissue": False, "notes": "Hypothalamus"}, - {"slide_num": 8, "section_start": 22, "section_end": 24, "chunk_name": "amygdala", "ccf_acronym": "BLA", "includes_surrounding_tissue": True, "notes": "Amygdala (targeting whole structure via BLA + surrounding tissue)"}, - {"slide_num": 8, "section_start": 22, "section_end": 24, "chunk_name": "GPE", "ccf_acronym": "GPe", "includes_surrounding_tissue": False, "notes": "Globus pallidus external segment (GPe)"}, - {"slide_num": 8, "section_start": 22, "section_end": 24, "chunk_name": "ctx_1", "ccf_acronym": "CTX", "includes_surrounding_tissue": True, "notes": "Superior/dorsal cortex ribbon (ctx 1 in figure)"}, - {"slide_num": 8, "section_start": 22, "section_end": 24, "chunk_name": "ctx_2", "ccf_acronym": "CTX", "includes_surrounding_tissue": True, "notes": "Lateral cortex ribbon (ctx 2 in figure)"}, - {"slide_num": 8, "section_start": 22, "section_end": 24, "chunk_name": "ctx_3", "ccf_acronym": "CTX", "includes_surrounding_tissue": True, "notes": "Inferior/ventrolateral cortex ribbon (ctx 3 in figure)"}, - {"slide_num": 9, "section_start": 25, "section_end": 27, "chunk_name": "MB", "ccf_acronym": "MB", "includes_surrounding_tissue": False, "notes": "Midbrain"}, - {"slide_num": 9, "section_start": 25, "section_end": 27, "chunk_name": "ctx_1", "ccf_acronym": "CTX", "includes_surrounding_tissue": True, "notes": "Superior/dorsal cortex ribbon (ctx 1 in figure)"}, - {"slide_num": 9, "section_start": 25, "section_end": 27, "chunk_name": "ctx_2", "ccf_acronym": "CTX", "includes_surrounding_tissue": True, "notes": "Lateral cortex ribbon (ctx 2 in figure)"}, - {"slide_num": 9, "section_start": 25, "section_end": 27, "chunk_name": "ctx_3", "ccf_acronym": "CTX", "includes_surrounding_tissue": True, "notes": "Inferior/ventrolateral cortex ribbon (ctx 3 in figure)"}, - {"slide_num": 10, "section_start": 28, "section_end": 30, "chunk_name": "MB", "ccf_acronym": "MB", "includes_surrounding_tissue": False, "notes": "Midbrain (more caudal)"}, - {"slide_num": 10, "section_start": 28, "section_end": 30, "chunk_name": "HB", "ccf_acronym": "HB", "includes_surrounding_tissue": False, "notes": "Hindbrain"}, - {"slide_num": 11, "section_start": 31, "section_end": 33, "chunk_name": "MB", "ccf_acronym": "MB", "includes_surrounding_tissue": False, "notes": "Midbrain (most caudal)"}, - {"slide_num": 11, "section_start": 31, "section_end": 33, "chunk_name": "HB", "ccf_acronym": "HB", "includes_surrounding_tissue": False, "notes": "Hindbrain"}, - {"slide_num": 12, "section_start": 34, "section_end": 36, "chunk_name": "CB", "ccf_acronym": "CB", "includes_surrounding_tissue": False, "notes": "Cerebellum"}, - {"slide_num": 12, "section_start": 34, "section_end": 36, "chunk_name": "MY", "ccf_acronym": "MY", "includes_surrounding_tissue": False, "notes": "Medulla"}, - {"slide_num": 13, "section_start": 37, "section_end": 39, "chunk_name": "MY", "ccf_acronym": "MY", "includes_surrounding_tissue": False, "notes": "Medulla"}, + { + "slide_num": 1, + "section_start": 1, + "section_end": 3, + "chunk_name": "MOB", + "ccf_acronym": "MOB", + "includes_surrounding_tissue": False, + "notes": "Main olfactory bulb", + }, + { + "slide_num": 2, + "section_start": 4, + "section_end": 6, + "chunk_name": "MOB", + "ccf_acronym": "MOB", + "includes_surrounding_tissue": False, + "notes": "Main olfactory bulb", + }, + { + "slide_num": 3, + "section_start": 7, + "section_end": 9, + "chunk_name": "ORB", + "ccf_acronym": "ORB", + "includes_surrounding_tissue": False, + "notes": "Orbital area (orbitofrontal cortex)", + }, + { + "slide_num": 3, + "section_start": 7, + "section_end": 9, + "chunk_name": "MO", + "ccf_acronym": "MO", + "includes_surrounding_tissue": False, + "notes": "Somatomotor areas (motor cortex)", + }, + { + "slide_num": 3, + "section_start": 7, + "section_end": 9, + "chunk_name": "AON", + "ccf_acronym": "AON", + "includes_surrounding_tissue": False, + "notes": "Anterior olfactory nucleus", + }, + { + "slide_num": 4, + "section_start": 10, + "section_end": 12, + "chunk_name": "ORB", + "ccf_acronym": "ORB", + "includes_surrounding_tissue": False, + "notes": "Orbital area (orbitofrontal cortex)", + }, + { + "slide_num": 4, + "section_start": 10, + "section_end": 12, + "chunk_name": "MO", + "ccf_acronym": "MO", + "includes_surrounding_tissue": False, + "notes": "Somatomotor areas (motor cortex)", + }, + { + "slide_num": 4, + "section_start": 10, + "section_end": 12, + "chunk_name": "AON", + "ccf_acronym": "AON", + "includes_surrounding_tissue": False, + "notes": "Anterior olfactory nucleus", + }, + { + "slide_num": 5, + "section_start": 13, + "section_end": 15, + "chunk_name": "CP", + "ccf_acronym": "CP", + "includes_surrounding_tissue": False, + "notes": "Caudoputamen", + }, + { + "slide_num": 5, + "section_start": 13, + "section_end": 15, + "chunk_name": "ACB", + "ccf_acronym": "ACB", + "includes_surrounding_tissue": False, + "notes": "Nucleus accumbens", + }, + { + "slide_num": 5, + "section_start": 13, + "section_end": 15, + "chunk_name": "LSX", + "ccf_acronym": "LSX", + "includes_surrounding_tissue": False, + "notes": "Lateral septal complex", + }, + { + "slide_num": 5, + "section_start": 13, + "section_end": 15, + "chunk_name": "ctx_1", + "ccf_acronym": "CTX", + "includes_surrounding_tissue": True, + "notes": "Superior/dorsal cortex ribbon (ctx 1 in figure)", + }, + { + "slide_num": 5, + "section_start": 13, + "section_end": 15, + "chunk_name": "ctx_2", + "ccf_acronym": "CTX", + "includes_surrounding_tissue": True, + "notes": "Lateral cortex ribbon (ctx 2 in figure)", + }, + { + "slide_num": 5, + "section_start": 13, + "section_end": 15, + "chunk_name": "ctx_3", + "ccf_acronym": "CTX", + "includes_surrounding_tissue": True, + "notes": "Inferior/ventrolateral cortex ribbon (ctx 3 in figure)", + }, + { + "slide_num": 6, + "section_start": 16, + "section_end": 18, + "chunk_name": "CP", + "ccf_acronym": "CP", + "includes_surrounding_tissue": False, + "notes": "Caudoputamen", + }, + { + "slide_num": 6, + "section_start": 16, + "section_end": 18, + "chunk_name": "ACB", + "ccf_acronym": "ACB", + "includes_surrounding_tissue": False, + "notes": "Nucleus accumbens", + }, + { + "slide_num": 6, + "section_start": 16, + "section_end": 18, + "chunk_name": "LSX", + "ccf_acronym": "LSX", + "includes_surrounding_tissue": False, + "notes": "Lateral septal complex", + }, + { + "slide_num": 6, + "section_start": 16, + "section_end": 18, + "chunk_name": "ctx_1", + "ccf_acronym": "CTX", + "includes_surrounding_tissue": True, + "notes": "Superior/dorsal cortex ribbon (ctx 1 in figure)", + }, + { + "slide_num": 6, + "section_start": 16, + "section_end": 18, + "chunk_name": "ctx_2", + "ccf_acronym": "CTX", + "includes_surrounding_tissue": True, + "notes": "Lateral cortex ribbon (ctx 2 in figure)", + }, + { + "slide_num": 6, + "section_start": 16, + "section_end": 18, + "chunk_name": "ctx_3", + "ccf_acronym": "CTX", + "includes_surrounding_tissue": True, + "notes": "Inferior/ventrolateral cortex ribbon (ctx 3 in figure)", + }, + { + "slide_num": 7, + "section_start": 19, + "section_end": 21, + "chunk_name": "CP", + "ccf_acronym": "CP", + "includes_surrounding_tissue": False, + "notes": "Caudoputamen", + }, + { + "slide_num": 7, + "section_start": 19, + "section_end": 21, + "chunk_name": "LSX", + "ccf_acronym": "LSX", + "includes_surrounding_tissue": False, + "notes": "Lateral septal complex", + }, + { + "slide_num": 7, + "section_start": 19, + "section_end": 21, + "chunk_name": "BST", + "ccf_acronym": "BST", + "includes_surrounding_tissue": False, + "notes": "Bed nuclei of the stria terminalis (BNST)", + }, + { + "slide_num": 7, + "section_start": 19, + "section_end": 21, + "chunk_name": "ctx_1", + "ccf_acronym": "CTX", + "includes_surrounding_tissue": True, + "notes": "Superior/dorsal cortex ribbon (ctx 1 in figure)", + }, + { + "slide_num": 7, + "section_start": 19, + "section_end": 21, + "chunk_name": "ctx_2", + "ccf_acronym": "CTX", + "includes_surrounding_tissue": True, + "notes": "Lateral cortex ribbon (ctx 2 in figure)", + }, + { + "slide_num": 7, + "section_start": 19, + "section_end": 21, + "chunk_name": "ctx_3", + "ccf_acronym": "CTX", + "includes_surrounding_tissue": True, + "notes": "Inferior/ventrolateral cortex ribbon (ctx 3 in figure)", + }, + { + "slide_num": 8, + "section_start": 22, + "section_end": 24, + "chunk_name": "HPF", + "ccf_acronym": "HPF", + "includes_surrounding_tissue": False, + "notes": "Hippocampal formation", + }, + { + "slide_num": 8, + "section_start": 22, + "section_end": 24, + "chunk_name": "TH", + "ccf_acronym": "TH", + "includes_surrounding_tissue": False, + "notes": "Thalamus", + }, + { + "slide_num": 8, + "section_start": 22, + "section_end": 24, + "chunk_name": "HY", + "ccf_acronym": "HY", + "includes_surrounding_tissue": False, + "notes": "Hypothalamus", + }, + { + "slide_num": 8, + "section_start": 22, + "section_end": 24, + "chunk_name": "amygdala", + "ccf_acronym": "BLA", + "includes_surrounding_tissue": True, + "notes": "Amygdala (targeting whole structure via BLA + surrounding tissue)", + }, + { + "slide_num": 8, + "section_start": 22, + "section_end": 24, + "chunk_name": "GPE", + "ccf_acronym": "GPe", + "includes_surrounding_tissue": False, + "notes": "Globus pallidus external segment (GPe)", + }, + { + "slide_num": 8, + "section_start": 22, + "section_end": 24, + "chunk_name": "ctx_1", + "ccf_acronym": "CTX", + "includes_surrounding_tissue": True, + "notes": "Superior/dorsal cortex ribbon (ctx 1 in figure)", + }, + { + "slide_num": 8, + "section_start": 22, + "section_end": 24, + "chunk_name": "ctx_2", + "ccf_acronym": "CTX", + "includes_surrounding_tissue": True, + "notes": "Lateral cortex ribbon (ctx 2 in figure)", + }, + { + "slide_num": 8, + "section_start": 22, + "section_end": 24, + "chunk_name": "ctx_3", + "ccf_acronym": "CTX", + "includes_surrounding_tissue": True, + "notes": "Inferior/ventrolateral cortex ribbon (ctx 3 in figure)", + }, + { + "slide_num": 9, + "section_start": 25, + "section_end": 27, + "chunk_name": "MB", + "ccf_acronym": "MB", + "includes_surrounding_tissue": False, + "notes": "Midbrain", + }, + { + "slide_num": 9, + "section_start": 25, + "section_end": 27, + "chunk_name": "ctx_1", + "ccf_acronym": "CTX", + "includes_surrounding_tissue": True, + "notes": "Superior/dorsal cortex ribbon (ctx 1 in figure)", + }, + { + "slide_num": 9, + "section_start": 25, + "section_end": 27, + "chunk_name": "ctx_2", + "ccf_acronym": "CTX", + "includes_surrounding_tissue": True, + "notes": "Lateral cortex ribbon (ctx 2 in figure)", + }, + { + "slide_num": 9, + "section_start": 25, + "section_end": 27, + "chunk_name": "ctx_3", + "ccf_acronym": "CTX", + "includes_surrounding_tissue": True, + "notes": "Inferior/ventrolateral cortex ribbon (ctx 3 in figure)", + }, + { + "slide_num": 10, + "section_start": 28, + "section_end": 30, + "chunk_name": "MB", + "ccf_acronym": "MB", + "includes_surrounding_tissue": False, + "notes": "Midbrain (more caudal)", + }, + { + "slide_num": 10, + "section_start": 28, + "section_end": 30, + "chunk_name": "HB", + "ccf_acronym": "HB", + "includes_surrounding_tissue": False, + "notes": "Hindbrain", + }, + { + "slide_num": 11, + "section_start": 31, + "section_end": 33, + "chunk_name": "MB", + "ccf_acronym": "MB", + "includes_surrounding_tissue": False, + "notes": "Midbrain (most caudal)", + }, + { + "slide_num": 11, + "section_start": 31, + "section_end": 33, + "chunk_name": "HB", + "ccf_acronym": "HB", + "includes_surrounding_tissue": False, + "notes": "Hindbrain", + }, + { + "slide_num": 12, + "section_start": 34, + "section_end": 36, + "chunk_name": "CB", + "ccf_acronym": "CB", + "includes_surrounding_tissue": False, + "notes": "Cerebellum", + }, + { + "slide_num": 12, + "section_start": 34, + "section_end": 36, + "chunk_name": "MY", + "ccf_acronym": "MY", + "includes_surrounding_tissue": False, + "notes": "Medulla", + }, + { + "slide_num": 13, + "section_start": 37, + "section_end": 39, + "chunk_name": "MY", + "ccf_acronym": "MY", + "includes_surrounding_tissue": False, + "notes": "Medulla", + }, ] @@ -79,12 +436,14 @@ def _load_slide_regions() -> Dict[int, dict]: "section_end": row["section_end"], "chunks": [], } - slides[slide]["chunks"].append({ - "chunk_name": row["chunk_name"], - "ccf_acronym": row["ccf_acronym"], - "includes_surrounding_tissue": row["includes_surrounding_tissue"], - "notes": row["notes"], - }) + slides[slide]["chunks"].append( + { + "chunk_name": row["chunk_name"], + "ccf_acronym": row["ccf_acronym"], + "includes_surrounding_tissue": row["includes_surrounding_tissue"], + "notes": row["notes"], + } + ) return slides @@ -96,10 +455,7 @@ def generate_mapseq_slide_chunks(specimen_id: str) -> List[SpecimenProcedure]: section_end = slide_data["section_end"] chunks = slide_data["chunks"] - input_ids = [ - f"{specimen_id}_map{i:03d}" - for i in range(section_start, section_end + 1) - ] + input_ids = [f"{specimen_id}_map{i:03d}" for i in range(section_start, section_end + 1)] output_sections = [] for chunk_idx, chunk in enumerate(chunks, start=1): @@ -115,9 +471,7 @@ def generate_mapseq_slide_chunks(specimen_id: str) -> List[SpecimenProcedure]: ) chunk_names = ", ".join(c["chunk_name"] for c in chunks) - ctx_notes = "; ".join( - c["notes"] for c in chunks if c["ccf_acronym"] == "CTX" - ) + ctx_notes = "; ".join(c["notes"] for c in chunks if c["ccf_acronym"] == "CTX") note = f"Slide {slide_num}: sections {section_start}-{section_end} chunked into [{chunk_names}]" if ctx_notes: note += f". CTX chunks: {ctx_notes}" @@ -238,7 +592,7 @@ def generate_barseq_lc_780345(start_section_num: int = 1) -> PlanarSectioning: thickness_unit=SizeUnit.UM, section_prefix="bar", ) - + return create_planar_sectioning(sections) @@ -254,7 +608,7 @@ def generate_mapseq_slides_780345_second_batch(start_section_num: int = 28) -> P section_prefix="map", start_section_num=start_section_num, ) - + return create_planar_sectioning(sections) @@ -278,7 +632,7 @@ def generate_mapseq_spinal_780345() -> Sectioning: targeted_structure=CCFv3.CST, thickness=1000, thickness_unit=SizeUnit.UM, - ) + ), ] ) @@ -295,7 +649,7 @@ def generate_mapseq_slides_780346_first_batch(start_section_num: int = 1) -> Pla section_prefix="map", start_section_num=start_section_num, ) - + return create_planar_sectioning(sections) @@ -309,7 +663,7 @@ def generate_barseq_lc_780346(start_section_num: int = 1) -> PlanarSectioning: thickness_unit=SizeUnit.UM, section_prefix="bar", ) - + return create_planar_sectioning(sections) @@ -325,7 +679,7 @@ def generate_mapseq_slides_780346_second_batch(start_section_num: int = 31) -> P section_prefix="map", start_section_num=start_section_num, ) - + return create_planar_sectioning(sections) @@ -437,15 +791,15 @@ def generate_procedures_780346() -> Procedures: if __name__ == "__main__": procedures_780345 = generate_procedures_780345() procedures_780346 = generate_procedures_780346() - + serialized_780345 = procedures_780345.model_dump_json(indent=2) print("Specimen 780345:") print(serialized_780345) print("\n") - + serialized_780346 = procedures_780346.model_dump_json(indent=2) print("Specimen 780346:") print(serialized_780346) - + procedures_780345.write_standard_file(filename_suffix="780345") procedures_780346.write_standard_file(filename_suffix="780346") From 4c04fdecd9951ac4d12fc5f4ec65592fc6bd4c94 Mon Sep 17 00:00:00 2001 From: Dan Birman Date: Fri, 3 Apr 2026 15:29:04 -0700 Subject: [PATCH 5/7] chore: docstrings --- examples/procedures_sectioning.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/examples/procedures_sectioning.py b/examples/procedures_sectioning.py index 89bf57f0d..e63fe3381 100644 --- a/examples/procedures_sectioning.py +++ b/examples/procedures_sectioning.py @@ -427,6 +427,7 @@ def _load_slide_regions() -> Dict[int, dict]: + """Load slide region data from _SLIDE_REGIONS and organize by slide number""" slides: Dict[int, dict] = {} for row in _SLIDE_REGIONS: slide = row["slide_num"] @@ -448,6 +449,7 @@ def _load_slide_regions() -> Dict[int, dict]: def generate_mapseq_slide_chunks(specimen_id: str) -> List[SpecimenProcedure]: + """Generate specimen procedures for the MAPseq slide chunking based on _SLIDE_REGIONS data""" slides = _load_slide_regions() procedures = [] for slide_num, slide_data in slides.items(): @@ -498,6 +500,7 @@ def create_planar_section( thickness: float, thickness_unit: SizeUnit, ) -> PlanarSection: + """Helper function to create a PlanarSection with the given parameters""" return PlanarSection( output_specimen_id=f"{specimen_id}_{section_id}", coordinate_system_name=coordinate_system_name, @@ -517,6 +520,7 @@ def create_uniform_sections( coordinate_system_name: str = "CCF", section_prefix: str = "sec", ) -> List[PlanarSection]: + """Create a list of PlanarSections with uniform spacing based on the given parameters""" return [ create_planar_section( specimen_id=specimen_id, @@ -540,6 +544,7 @@ def create_nonuniform_sections( section_prefix: str = "sec", start_section_num: int = 1, ) -> List[PlanarSection]: + """Create a list of PlanarSections with non-uniform spacing based on the given parameters""" if num_sections != len(start_positions_um): raise ValueError("num_sections and start_positions_um must have same length") @@ -560,6 +565,7 @@ def create_planar_sectioning( sections: List[PlanarSection], section_orientation: SectionOrientation = SectionOrientation.CORONAL, ) -> PlanarSectioning: + """Helper function to create a PlanarSectioning procedure with the given sections and orientation""" return PlanarSectioning( sections=sections, section_orientation=section_orientation, @@ -567,6 +573,7 @@ def create_planar_sectioning( def generate_mapseq_slides_780345_first_batch(start_section_num: int = 1) -> PlanarSectioning: + """Generate the first batch of MAPseq slides for specimen 780345 with non-uniform section spacing based on plate boundaries""" start_positions = [i * (9800 / 27) for i in range(27)] sections = create_nonuniform_sections( @@ -583,6 +590,7 @@ def generate_mapseq_slides_780345_first_batch(start_section_num: int = 1) -> Pla def generate_barseq_lc_780345(start_section_num: int = 1) -> PlanarSectioning: + """Generate the BARseq LC slides for specimen 780345 with uniform section spacing (20um)""" sections = create_uniform_sections( specimen_id="780345", start_section_num=start_section_num, @@ -597,6 +605,7 @@ def generate_barseq_lc_780345(start_section_num: int = 1) -> PlanarSectioning: def generate_mapseq_slides_780345_second_batch(start_section_num: int = 28) -> PlanarSectioning: + """Generate the second batch of MAPseq slides for specimen 780345 with non-uniform section spacing based on plate boundaries""" start_positions = [11200 + i * (2000 / 12) for i in range(12)] sections = create_nonuniform_sections( @@ -613,6 +622,7 @@ def generate_mapseq_slides_780345_second_batch(start_section_num: int = 28) -> P def generate_mapseq_spinal_780345() -> Sectioning: + """Generate the MAPseq spinal cord sections for specimen 780345, with approximate size (1/3rd length each)""" return Sectioning( sections=[ Section( @@ -638,6 +648,7 @@ def generate_mapseq_spinal_780345() -> Sectioning: def generate_mapseq_slides_780346_first_batch(start_section_num: int = 1) -> PlanarSectioning: + """Generate the first batch of MAPseq slides for specimen 780346 with non-uniform section spacing based on plate boundaries""" start_positions = [i * (9800 / 30) for i in range(30)] sections = create_nonuniform_sections( @@ -654,6 +665,7 @@ def generate_mapseq_slides_780346_first_batch(start_section_num: int = 1) -> Pla def generate_barseq_lc_780346(start_section_num: int = 1) -> PlanarSectioning: + """Generate the BARseq LC slides for specimen 780346 with uniform section spacing (20um)""" sections = create_uniform_sections( specimen_id="780346", start_section_num=start_section_num, @@ -668,6 +680,7 @@ def generate_barseq_lc_780346(start_section_num: int = 1) -> PlanarSectioning: def generate_mapseq_slides_780346_second_batch(start_section_num: int = 31) -> PlanarSectioning: + """Generate the second batch of MAPseq slides for specimen 780346 with non-uniform section spacing based on plate boundaries""" start_positions = [11200 + i * (2000 / 9) for i in range(9)] sections = create_nonuniform_sections( @@ -684,6 +697,7 @@ def generate_mapseq_slides_780346_second_batch(start_section_num: int = 31) -> P def generate_mapseq_spinal_780346() -> Sectioning: + """Generate the MAPseq spinal cord sections for specimen 780346, with approximate size (1/3rd length each)""" return Sectioning( sections=[ Section( @@ -697,6 +711,7 @@ def generate_mapseq_spinal_780346() -> Sectioning: def generate_procedures_780345() -> Procedures: + """Generate the Procedures for specimen 780345, including multiple sectioning procedures with different parameters and notes""" return Procedures( subject_id="780345", coordinate_system=AtlasLibrary.CCFv3_10um, @@ -743,6 +758,7 @@ def generate_procedures_780345() -> Procedures: def generate_procedures_780346() -> Procedures: + """Generate the Procedures for specimen 780346, including multiple sectioning procedures with different parameters and notes""" return Procedures( subject_id="780346", coordinate_system=AtlasLibrary.CCFv3_10um, From caf50f18d478b7f882b700b27ad12bebcc25c475 Mon Sep 17 00:00:00 2001 From: Dan Birman Date: Fri, 1 May 2026 14:23:46 -0700 Subject: [PATCH 6/7] chore: lint --- examples/procedures_sectioning.py | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/examples/procedures_sectioning.py b/examples/procedures_sectioning.py index e63fe3381..91682ea8b 100644 --- a/examples/procedures_sectioning.py +++ b/examples/procedures_sectioning.py @@ -573,7 +573,8 @@ def create_planar_sectioning( def generate_mapseq_slides_780345_first_batch(start_section_num: int = 1) -> PlanarSectioning: - """Generate the first batch of MAPseq slides for specimen 780345 with non-uniform section spacing based on plate boundaries""" + """Generate the first batch of MAPseq slides for specimen 780345 + with non-uniform section spacing based on plate boundaries""" start_positions = [i * (9800 / 27) for i in range(27)] sections = create_nonuniform_sections( @@ -590,7 +591,8 @@ def generate_mapseq_slides_780345_first_batch(start_section_num: int = 1) -> Pla def generate_barseq_lc_780345(start_section_num: int = 1) -> PlanarSectioning: - """Generate the BARseq LC slides for specimen 780345 with uniform section spacing (20um)""" + """Generate the BARseq LC slides for specimen 780345 with uniform + section spacing (20um)""" sections = create_uniform_sections( specimen_id="780345", start_section_num=start_section_num, @@ -605,7 +607,8 @@ def generate_barseq_lc_780345(start_section_num: int = 1) -> PlanarSectioning: def generate_mapseq_slides_780345_second_batch(start_section_num: int = 28) -> PlanarSectioning: - """Generate the second batch of MAPseq slides for specimen 780345 with non-uniform section spacing based on plate boundaries""" + """Generate the second batch of MAPseq slides for specimen 780345 + with non-uniform section spacing based on plate boundaries""" start_positions = [11200 + i * (2000 / 12) for i in range(12)] sections = create_nonuniform_sections( @@ -622,7 +625,8 @@ def generate_mapseq_slides_780345_second_batch(start_section_num: int = 28) -> P def generate_mapseq_spinal_780345() -> Sectioning: - """Generate the MAPseq spinal cord sections for specimen 780345, with approximate size (1/3rd length each)""" + """Generate the MAPseq spinal cord sections for specimen 780345, + with approximate size (1/3rd length each)""" return Sectioning( sections=[ Section( @@ -648,7 +652,8 @@ def generate_mapseq_spinal_780345() -> Sectioning: def generate_mapseq_slides_780346_first_batch(start_section_num: int = 1) -> PlanarSectioning: - """Generate the first batch of MAPseq slides for specimen 780346 with non-uniform section spacing based on plate boundaries""" + """Generate the first batch of MAPseq slides for specimen + 780346 with non-uniform section spacing based on plate boundaries""" start_positions = [i * (9800 / 30) for i in range(30)] sections = create_nonuniform_sections( @@ -665,7 +670,8 @@ def generate_mapseq_slides_780346_first_batch(start_section_num: int = 1) -> Pla def generate_barseq_lc_780346(start_section_num: int = 1) -> PlanarSectioning: - """Generate the BARseq LC slides for specimen 780346 with uniform section spacing (20um)""" + """Generate the BARseq LC slides for specimen 780346 with + uniform section spacing (20um)""" sections = create_uniform_sections( specimen_id="780346", start_section_num=start_section_num, @@ -680,7 +686,8 @@ def generate_barseq_lc_780346(start_section_num: int = 1) -> PlanarSectioning: def generate_mapseq_slides_780346_second_batch(start_section_num: int = 31) -> PlanarSectioning: - """Generate the second batch of MAPseq slides for specimen 780346 with non-uniform section spacing based on plate boundaries""" + """Generate the second batch of MAPseq slides for specimen + 780346 with non-uniform section spacing based on plate boundaries""" start_positions = [11200 + i * (2000 / 9) for i in range(9)] sections = create_nonuniform_sections( @@ -697,7 +704,8 @@ def generate_mapseq_slides_780346_second_batch(start_section_num: int = 31) -> P def generate_mapseq_spinal_780346() -> Sectioning: - """Generate the MAPseq spinal cord sections for specimen 780346, with approximate size (1/3rd length each)""" + """Generate the MAPseq spinal cord sections for specimen 780346, + with approximate size (1/3rd length each)""" return Sectioning( sections=[ Section( @@ -711,7 +719,8 @@ def generate_mapseq_spinal_780346() -> Sectioning: def generate_procedures_780345() -> Procedures: - """Generate the Procedures for specimen 780345, including multiple sectioning procedures with different parameters and notes""" + """Generate the Procedures for specimen 780345, including multiple + sectioning procedures with different parameters and notes""" return Procedures( subject_id="780345", coordinate_system=AtlasLibrary.CCFv3_10um, @@ -758,7 +767,8 @@ def generate_procedures_780345() -> Procedures: def generate_procedures_780346() -> Procedures: - """Generate the Procedures for specimen 780346, including multiple sectioning procedures with different parameters and notes""" + """Generate the Procedures for specimen 780346, including + multiple sectioning procedures with different parameters and notes""" return Procedures( subject_id="780346", coordinate_system=AtlasLibrary.CCFv3_10um, From c6562372df7765d360b4e04ba0d5ede026707b1d Mon Sep 17 00:00:00 2001 From: Dan Birman Date: Tue, 5 May 2026 21:31:46 -0700 Subject: [PATCH 7/7] chore: remove full sectioning file --- examples/procedures_sectioning.py | 831 ------------------------------ 1 file changed, 831 deletions(-) delete mode 100644 examples/procedures_sectioning.py diff --git a/examples/procedures_sectioning.py b/examples/procedures_sectioning.py deleted file mode 100644 index 91682ea8b..000000000 --- a/examples/procedures_sectioning.py +++ /dev/null @@ -1,831 +0,0 @@ -"""Examples of BarSEQ/MapSEQ sectioning procedures""" - -from datetime import date -from typing import Dict, List - -from aind_data_schema_models.brain_atlas import CCFv3 -from aind_data_schema_models.units import SizeUnit - -from aind_data_schema.components.coordinates import AtlasLibrary, Translation -from aind_data_schema.components.specimen_procedures import ( - PlanarSectioning, - PlanarSection, - Section, - Sectioning, - SectionOrientation, - SpecimenProcedure, -) -from aind_data_schema.core.procedures import Procedures - -_SLIDE_REGIONS = [ - { - "slide_num": 1, - "section_start": 1, - "section_end": 3, - "chunk_name": "MOB", - "ccf_acronym": "MOB", - "includes_surrounding_tissue": False, - "notes": "Main olfactory bulb", - }, - { - "slide_num": 2, - "section_start": 4, - "section_end": 6, - "chunk_name": "MOB", - "ccf_acronym": "MOB", - "includes_surrounding_tissue": False, - "notes": "Main olfactory bulb", - }, - { - "slide_num": 3, - "section_start": 7, - "section_end": 9, - "chunk_name": "ORB", - "ccf_acronym": "ORB", - "includes_surrounding_tissue": False, - "notes": "Orbital area (orbitofrontal cortex)", - }, - { - "slide_num": 3, - "section_start": 7, - "section_end": 9, - "chunk_name": "MO", - "ccf_acronym": "MO", - "includes_surrounding_tissue": False, - "notes": "Somatomotor areas (motor cortex)", - }, - { - "slide_num": 3, - "section_start": 7, - "section_end": 9, - "chunk_name": "AON", - "ccf_acronym": "AON", - "includes_surrounding_tissue": False, - "notes": "Anterior olfactory nucleus", - }, - { - "slide_num": 4, - "section_start": 10, - "section_end": 12, - "chunk_name": "ORB", - "ccf_acronym": "ORB", - "includes_surrounding_tissue": False, - "notes": "Orbital area (orbitofrontal cortex)", - }, - { - "slide_num": 4, - "section_start": 10, - "section_end": 12, - "chunk_name": "MO", - "ccf_acronym": "MO", - "includes_surrounding_tissue": False, - "notes": "Somatomotor areas (motor cortex)", - }, - { - "slide_num": 4, - "section_start": 10, - "section_end": 12, - "chunk_name": "AON", - "ccf_acronym": "AON", - "includes_surrounding_tissue": False, - "notes": "Anterior olfactory nucleus", - }, - { - "slide_num": 5, - "section_start": 13, - "section_end": 15, - "chunk_name": "CP", - "ccf_acronym": "CP", - "includes_surrounding_tissue": False, - "notes": "Caudoputamen", - }, - { - "slide_num": 5, - "section_start": 13, - "section_end": 15, - "chunk_name": "ACB", - "ccf_acronym": "ACB", - "includes_surrounding_tissue": False, - "notes": "Nucleus accumbens", - }, - { - "slide_num": 5, - "section_start": 13, - "section_end": 15, - "chunk_name": "LSX", - "ccf_acronym": "LSX", - "includes_surrounding_tissue": False, - "notes": "Lateral septal complex", - }, - { - "slide_num": 5, - "section_start": 13, - "section_end": 15, - "chunk_name": "ctx_1", - "ccf_acronym": "CTX", - "includes_surrounding_tissue": True, - "notes": "Superior/dorsal cortex ribbon (ctx 1 in figure)", - }, - { - "slide_num": 5, - "section_start": 13, - "section_end": 15, - "chunk_name": "ctx_2", - "ccf_acronym": "CTX", - "includes_surrounding_tissue": True, - "notes": "Lateral cortex ribbon (ctx 2 in figure)", - }, - { - "slide_num": 5, - "section_start": 13, - "section_end": 15, - "chunk_name": "ctx_3", - "ccf_acronym": "CTX", - "includes_surrounding_tissue": True, - "notes": "Inferior/ventrolateral cortex ribbon (ctx 3 in figure)", - }, - { - "slide_num": 6, - "section_start": 16, - "section_end": 18, - "chunk_name": "CP", - "ccf_acronym": "CP", - "includes_surrounding_tissue": False, - "notes": "Caudoputamen", - }, - { - "slide_num": 6, - "section_start": 16, - "section_end": 18, - "chunk_name": "ACB", - "ccf_acronym": "ACB", - "includes_surrounding_tissue": False, - "notes": "Nucleus accumbens", - }, - { - "slide_num": 6, - "section_start": 16, - "section_end": 18, - "chunk_name": "LSX", - "ccf_acronym": "LSX", - "includes_surrounding_tissue": False, - "notes": "Lateral septal complex", - }, - { - "slide_num": 6, - "section_start": 16, - "section_end": 18, - "chunk_name": "ctx_1", - "ccf_acronym": "CTX", - "includes_surrounding_tissue": True, - "notes": "Superior/dorsal cortex ribbon (ctx 1 in figure)", - }, - { - "slide_num": 6, - "section_start": 16, - "section_end": 18, - "chunk_name": "ctx_2", - "ccf_acronym": "CTX", - "includes_surrounding_tissue": True, - "notes": "Lateral cortex ribbon (ctx 2 in figure)", - }, - { - "slide_num": 6, - "section_start": 16, - "section_end": 18, - "chunk_name": "ctx_3", - "ccf_acronym": "CTX", - "includes_surrounding_tissue": True, - "notes": "Inferior/ventrolateral cortex ribbon (ctx 3 in figure)", - }, - { - "slide_num": 7, - "section_start": 19, - "section_end": 21, - "chunk_name": "CP", - "ccf_acronym": "CP", - "includes_surrounding_tissue": False, - "notes": "Caudoputamen", - }, - { - "slide_num": 7, - "section_start": 19, - "section_end": 21, - "chunk_name": "LSX", - "ccf_acronym": "LSX", - "includes_surrounding_tissue": False, - "notes": "Lateral septal complex", - }, - { - "slide_num": 7, - "section_start": 19, - "section_end": 21, - "chunk_name": "BST", - "ccf_acronym": "BST", - "includes_surrounding_tissue": False, - "notes": "Bed nuclei of the stria terminalis (BNST)", - }, - { - "slide_num": 7, - "section_start": 19, - "section_end": 21, - "chunk_name": "ctx_1", - "ccf_acronym": "CTX", - "includes_surrounding_tissue": True, - "notes": "Superior/dorsal cortex ribbon (ctx 1 in figure)", - }, - { - "slide_num": 7, - "section_start": 19, - "section_end": 21, - "chunk_name": "ctx_2", - "ccf_acronym": "CTX", - "includes_surrounding_tissue": True, - "notes": "Lateral cortex ribbon (ctx 2 in figure)", - }, - { - "slide_num": 7, - "section_start": 19, - "section_end": 21, - "chunk_name": "ctx_3", - "ccf_acronym": "CTX", - "includes_surrounding_tissue": True, - "notes": "Inferior/ventrolateral cortex ribbon (ctx 3 in figure)", - }, - { - "slide_num": 8, - "section_start": 22, - "section_end": 24, - "chunk_name": "HPF", - "ccf_acronym": "HPF", - "includes_surrounding_tissue": False, - "notes": "Hippocampal formation", - }, - { - "slide_num": 8, - "section_start": 22, - "section_end": 24, - "chunk_name": "TH", - "ccf_acronym": "TH", - "includes_surrounding_tissue": False, - "notes": "Thalamus", - }, - { - "slide_num": 8, - "section_start": 22, - "section_end": 24, - "chunk_name": "HY", - "ccf_acronym": "HY", - "includes_surrounding_tissue": False, - "notes": "Hypothalamus", - }, - { - "slide_num": 8, - "section_start": 22, - "section_end": 24, - "chunk_name": "amygdala", - "ccf_acronym": "BLA", - "includes_surrounding_tissue": True, - "notes": "Amygdala (targeting whole structure via BLA + surrounding tissue)", - }, - { - "slide_num": 8, - "section_start": 22, - "section_end": 24, - "chunk_name": "GPE", - "ccf_acronym": "GPe", - "includes_surrounding_tissue": False, - "notes": "Globus pallidus external segment (GPe)", - }, - { - "slide_num": 8, - "section_start": 22, - "section_end": 24, - "chunk_name": "ctx_1", - "ccf_acronym": "CTX", - "includes_surrounding_tissue": True, - "notes": "Superior/dorsal cortex ribbon (ctx 1 in figure)", - }, - { - "slide_num": 8, - "section_start": 22, - "section_end": 24, - "chunk_name": "ctx_2", - "ccf_acronym": "CTX", - "includes_surrounding_tissue": True, - "notes": "Lateral cortex ribbon (ctx 2 in figure)", - }, - { - "slide_num": 8, - "section_start": 22, - "section_end": 24, - "chunk_name": "ctx_3", - "ccf_acronym": "CTX", - "includes_surrounding_tissue": True, - "notes": "Inferior/ventrolateral cortex ribbon (ctx 3 in figure)", - }, - { - "slide_num": 9, - "section_start": 25, - "section_end": 27, - "chunk_name": "MB", - "ccf_acronym": "MB", - "includes_surrounding_tissue": False, - "notes": "Midbrain", - }, - { - "slide_num": 9, - "section_start": 25, - "section_end": 27, - "chunk_name": "ctx_1", - "ccf_acronym": "CTX", - "includes_surrounding_tissue": True, - "notes": "Superior/dorsal cortex ribbon (ctx 1 in figure)", - }, - { - "slide_num": 9, - "section_start": 25, - "section_end": 27, - "chunk_name": "ctx_2", - "ccf_acronym": "CTX", - "includes_surrounding_tissue": True, - "notes": "Lateral cortex ribbon (ctx 2 in figure)", - }, - { - "slide_num": 9, - "section_start": 25, - "section_end": 27, - "chunk_name": "ctx_3", - "ccf_acronym": "CTX", - "includes_surrounding_tissue": True, - "notes": "Inferior/ventrolateral cortex ribbon (ctx 3 in figure)", - }, - { - "slide_num": 10, - "section_start": 28, - "section_end": 30, - "chunk_name": "MB", - "ccf_acronym": "MB", - "includes_surrounding_tissue": False, - "notes": "Midbrain (more caudal)", - }, - { - "slide_num": 10, - "section_start": 28, - "section_end": 30, - "chunk_name": "HB", - "ccf_acronym": "HB", - "includes_surrounding_tissue": False, - "notes": "Hindbrain", - }, - { - "slide_num": 11, - "section_start": 31, - "section_end": 33, - "chunk_name": "MB", - "ccf_acronym": "MB", - "includes_surrounding_tissue": False, - "notes": "Midbrain (most caudal)", - }, - { - "slide_num": 11, - "section_start": 31, - "section_end": 33, - "chunk_name": "HB", - "ccf_acronym": "HB", - "includes_surrounding_tissue": False, - "notes": "Hindbrain", - }, - { - "slide_num": 12, - "section_start": 34, - "section_end": 36, - "chunk_name": "CB", - "ccf_acronym": "CB", - "includes_surrounding_tissue": False, - "notes": "Cerebellum", - }, - { - "slide_num": 12, - "section_start": 34, - "section_end": 36, - "chunk_name": "MY", - "ccf_acronym": "MY", - "includes_surrounding_tissue": False, - "notes": "Medulla", - }, - { - "slide_num": 13, - "section_start": 37, - "section_end": 39, - "chunk_name": "MY", - "ccf_acronym": "MY", - "includes_surrounding_tissue": False, - "notes": "Medulla", - }, -] - - -def _load_slide_regions() -> Dict[int, dict]: - """Load slide region data from _SLIDE_REGIONS and organize by slide number""" - slides: Dict[int, dict] = {} - for row in _SLIDE_REGIONS: - slide = row["slide_num"] - if slide not in slides: - slides[slide] = { - "section_start": row["section_start"], - "section_end": row["section_end"], - "chunks": [], - } - slides[slide]["chunks"].append( - { - "chunk_name": row["chunk_name"], - "ccf_acronym": row["ccf_acronym"], - "includes_surrounding_tissue": row["includes_surrounding_tissue"], - "notes": row["notes"], - } - ) - return slides - - -def generate_mapseq_slide_chunks(specimen_id: str) -> List[SpecimenProcedure]: - """Generate specimen procedures for the MAPseq slide chunking based on _SLIDE_REGIONS data""" - slides = _load_slide_regions() - procedures = [] - for slide_num, slide_data in slides.items(): - section_start = slide_data["section_start"] - section_end = slide_data["section_end"] - chunks = slide_data["chunks"] - - input_ids = [f"{specimen_id}_map{i:03d}" for i in range(section_start, section_end + 1)] - - output_sections = [] - for chunk_idx, chunk in enumerate(chunks, start=1): - structure = CCFv3.by_acronym(chunk["ccf_acronym"]) - surrounding = True if chunk["includes_surrounding_tissue"] else None - for sec_id in input_ids: - output_sections.append( - Section( - output_specimen_id=f"{sec_id}_{chunk_idx:03d}", - targeted_structure=structure, - includes_surrounding_tissue=surrounding, - ) - ) - - chunk_names = ", ".join(c["chunk_name"] for c in chunks) - ctx_notes = "; ".join(c["notes"] for c in chunks if c["ccf_acronym"] == "CTX") - note = f"Slide {slide_num}: sections {section_start}-{section_end} chunked into [{chunk_names}]" - if ctx_notes: - note += f". CTX chunks: {ctx_notes}" - - procedures.append( - SpecimenProcedure( - procedure_type="Sectioning", - specimen_id=input_ids, - start_date=date(2024, 1, 1), - end_date=date(2024, 1, 1), - experimenters=["Polina Kosillo"], - procedure_details=[Sectioning(sections=output_sections)], - notes=note, - ) - ) - return procedures - - -def create_planar_section( - specimen_id: str, - section_id: str, - coordinate_system_name: str, - start_um: float, - thickness: float, - thickness_unit: SizeUnit, -) -> PlanarSection: - """Helper function to create a PlanarSection with the given parameters""" - return PlanarSection( - output_specimen_id=f"{specimen_id}_{section_id}", - coordinate_system_name=coordinate_system_name, - start_coordinate=Translation(translation=[round(start_um), 0, 0]), - thickness=thickness, - thickness_unit=thickness_unit, - ) - - -def create_uniform_sections( - specimen_id: str, - start_section_num: int, - num_sections: int, - start_um: float, - thickness: float, - thickness_unit: SizeUnit, - coordinate_system_name: str = "CCF", - section_prefix: str = "sec", -) -> List[PlanarSection]: - """Create a list of PlanarSections with uniform spacing based on the given parameters""" - return [ - create_planar_section( - specimen_id=specimen_id, - section_id=f"{section_prefix}{start_section_num + i:03d}", - coordinate_system_name=coordinate_system_name, - start_um=start_um + i * thickness, - thickness=thickness, - thickness_unit=thickness_unit, - ) - for i in range(num_sections) - ] - - -def create_nonuniform_sections( - specimen_id: str, - num_sections: int, - start_positions_um: List[float], - thickness: float, - thickness_unit: SizeUnit, - coordinate_system_name: str = "CCF", - section_prefix: str = "sec", - start_section_num: int = 1, -) -> List[PlanarSection]: - """Create a list of PlanarSections with non-uniform spacing based on the given parameters""" - if num_sections != len(start_positions_um): - raise ValueError("num_sections and start_positions_um must have same length") - - return [ - create_planar_section( - specimen_id=specimen_id, - section_id=f"{section_prefix}{start_section_num + i:03d}", - coordinate_system_name=coordinate_system_name, - start_um=start_um, - thickness=thickness, - thickness_unit=thickness_unit, - ) - for i, start_um in enumerate(start_positions_um) - ] - - -def create_planar_sectioning( - sections: List[PlanarSection], - section_orientation: SectionOrientation = SectionOrientation.CORONAL, -) -> PlanarSectioning: - """Helper function to create a PlanarSectioning procedure with the given sections and orientation""" - return PlanarSectioning( - sections=sections, - section_orientation=section_orientation, - ) - - -def generate_mapseq_slides_780345_first_batch(start_section_num: int = 1) -> PlanarSectioning: - """Generate the first batch of MAPseq slides for specimen 780345 - with non-uniform section spacing based on plate boundaries""" - start_positions = [i * (9800 / 27) for i in range(27)] - - sections = create_nonuniform_sections( - specimen_id="780345", - num_sections=27, - start_positions_um=start_positions, - thickness=300, - thickness_unit=SizeUnit.UM, - section_prefix="map", - start_section_num=start_section_num, - ) - - return create_planar_sectioning(sections) - - -def generate_barseq_lc_780345(start_section_num: int = 1) -> PlanarSectioning: - """Generate the BARseq LC slides for specimen 780345 with uniform - section spacing (20um)""" - sections = create_uniform_sections( - specimen_id="780345", - start_section_num=start_section_num, - num_sections=44, - start_um=9900, - thickness=20, - thickness_unit=SizeUnit.UM, - section_prefix="bar", - ) - - return create_planar_sectioning(sections) - - -def generate_mapseq_slides_780345_second_batch(start_section_num: int = 28) -> PlanarSectioning: - """Generate the second batch of MAPseq slides for specimen 780345 - with non-uniform section spacing based on plate boundaries""" - start_positions = [11200 + i * (2000 / 12) for i in range(12)] - - sections = create_nonuniform_sections( - specimen_id="780345", - num_sections=12, - start_positions_um=start_positions, - thickness=300, - thickness_unit=SizeUnit.UM, - section_prefix="map", - start_section_num=start_section_num, - ) - - return create_planar_sectioning(sections) - - -def generate_mapseq_spinal_780345() -> Sectioning: - """Generate the MAPseq spinal cord sections for specimen 780345, - with approximate size (1/3rd length each)""" - return Sectioning( - sections=[ - Section( - output_specimen_id="780345_spinal", - targeted_structure=CCFv3.CST, - thickness=1000, - thickness_unit=SizeUnit.UM, - ), - Section( - output_specimen_id="780345_spinal", - targeted_structure=CCFv3.CST, - thickness=1000, - thickness_unit=SizeUnit.UM, - ), - Section( - output_specimen_id="780345_spinal", - targeted_structure=CCFv3.CST, - thickness=1000, - thickness_unit=SizeUnit.UM, - ), - ] - ) - - -def generate_mapseq_slides_780346_first_batch(start_section_num: int = 1) -> PlanarSectioning: - """Generate the first batch of MAPseq slides for specimen - 780346 with non-uniform section spacing based on plate boundaries""" - start_positions = [i * (9800 / 30) for i in range(30)] - - sections = create_nonuniform_sections( - specimen_id="780346", - num_sections=30, - start_positions_um=start_positions, - thickness=300, - thickness_unit=SizeUnit.UM, - section_prefix="map", - start_section_num=start_section_num, - ) - - return create_planar_sectioning(sections) - - -def generate_barseq_lc_780346(start_section_num: int = 1) -> PlanarSectioning: - """Generate the BARseq LC slides for specimen 780346 with - uniform section spacing (20um)""" - sections = create_uniform_sections( - specimen_id="780346", - start_section_num=start_section_num, - num_sections=51, - start_um=9900, - thickness=20, - thickness_unit=SizeUnit.UM, - section_prefix="bar", - ) - - return create_planar_sectioning(sections) - - -def generate_mapseq_slides_780346_second_batch(start_section_num: int = 31) -> PlanarSectioning: - """Generate the second batch of MAPseq slides for specimen - 780346 with non-uniform section spacing based on plate boundaries""" - start_positions = [11200 + i * (2000 / 9) for i in range(9)] - - sections = create_nonuniform_sections( - specimen_id="780346", - num_sections=9, - start_positions_um=start_positions, - thickness=300, - thickness_unit=SizeUnit.UM, - section_prefix="map", - start_section_num=start_section_num, - ) - - return create_planar_sectioning(sections) - - -def generate_mapseq_spinal_780346() -> Sectioning: - """Generate the MAPseq spinal cord sections for specimen 780346, - with approximate size (1/3rd length each)""" - return Sectioning( - sections=[ - Section( - output_specimen_id="780346_spinal", - targeted_structure=CCFv3.CST, - thickness=1000, - thickness_unit=SizeUnit.UM, - ) - ] - ) - - -def generate_procedures_780345() -> Procedures: - """Generate the Procedures for specimen 780345, including multiple - sectioning procedures with different parameters and notes""" - return Procedures( - subject_id="780345", - coordinate_system=AtlasLibrary.CCFv3_10um, - specimen_procedures=[ - SpecimenProcedure( - procedure_type="Sectioning", - specimen_id="780345", - start_date=date(2024, 1, 1), - end_date=date(2024, 1, 1), - experimenters=["Polina Kosillo"], - procedure_details=[generate_mapseq_slides_780345_first_batch()], - notes="MAPseq sections 1-27 covering plates 0-98 (300um thick, partial slices)", - ), - SpecimenProcedure( - procedure_type="Sectioning", - specimen_id="780345", - start_date=date(2024, 1, 1), - end_date=date(2024, 1, 1), - experimenters=["Polina Kosillo"], - procedure_details=[generate_barseq_lc_780345()], - notes="BARseq LC sections 1-44 covering plates 99-112 (20um thick)", - ), - SpecimenProcedure( - procedure_type="Sectioning", - specimen_id="780345", - start_date=date(2024, 1, 1), - end_date=date(2024, 1, 1), - experimenters=["Polina Kosillo"], - procedure_details=[generate_mapseq_slides_780345_second_batch()], - notes="MAPseq sections 28-39 covering plates 112-132 (300um thick, partial slices)", - ), - SpecimenProcedure( - procedure_type="Sectioning", - specimen_id="780345", - start_date=date(2024, 1, 1), - end_date=date(2024, 1, 1), - experimenters=["Polina Kosillo"], - procedure_details=[generate_mapseq_spinal_780345()], - notes="MAPseq spinal cord sections, size is approximate (1/3rd length each)", - ), - *generate_mapseq_slide_chunks("780345"), - ], - ) - - -def generate_procedures_780346() -> Procedures: - """Generate the Procedures for specimen 780346, including - multiple sectioning procedures with different parameters and notes""" - return Procedures( - subject_id="780346", - coordinate_system=AtlasLibrary.CCFv3_10um, - specimen_procedures=[ - SpecimenProcedure( - procedure_type="Sectioning", - specimen_id="780346", - start_date=date(2024, 1, 1), - end_date=date(2024, 1, 1), - experimenters=["Polina Kosillo"], - procedure_details=[generate_mapseq_slides_780346_first_batch()], - notes="MAPseq sections 1-30 covering plates 0-98 (300um thick, partial slices)", - ), - SpecimenProcedure( - procedure_type="Sectioning", - specimen_id="780346", - start_date=date(2024, 1, 1), - end_date=date(2024, 1, 1), - experimenters=["Polina Kosillo"], - procedure_details=[generate_barseq_lc_780346()], - notes="BARseq LC sections 1-51 covering plates 99-112 (20um thick)", - ), - SpecimenProcedure( - procedure_type="Sectioning", - specimen_id="780346", - start_date=date(2024, 1, 1), - end_date=date(2024, 1, 1), - experimenters=["Polina Kosillo"], - procedure_details=[generate_mapseq_slides_780346_second_batch()], - notes="MAPseq sections 31-39 covering plates 112-132 (300um thick, partial slices)", - ), - SpecimenProcedure( - procedure_type="Sectioning", - specimen_id="780346", - start_date=date(2024, 1, 1), - end_date=date(2024, 1, 1), - experimenters=["Polina Kosillo"], - procedure_details=[generate_mapseq_spinal_780346()], - notes="MAPseq spinal cord sections, size is approximate (1/3rd length each)", - ), - *generate_mapseq_slide_chunks("780346"), - ], - ) - - -if __name__ == "__main__": - procedures_780345 = generate_procedures_780345() - procedures_780346 = generate_procedures_780346() - - serialized_780345 = procedures_780345.model_dump_json(indent=2) - print("Specimen 780345:") - print(serialized_780345) - print("\n") - - serialized_780346 = procedures_780346.model_dump_json(indent=2) - print("Specimen 780346:") - print(serialized_780346) - - procedures_780345.write_standard_file(filename_suffix="780345") - procedures_780346.write_standard_file(filename_suffix="780346")