From 4dd7614a2785423e7bc817511f40a0f31642065e Mon Sep 17 00:00:00 2001 From: Mike Gevaert Date: Fri, 23 May 2025 11:04:03 +0200 Subject: [PATCH 1/5] Initial implementation of `brain-atlas` endpoints See https://github.com/openbraininstitute/entitycore/pull/168 for the specification. Briefly; a `BrainAtlas` is an named entity that has an asset `annotation.nrrd` attached to it. It is associated with a particular `BrainRegionHierarchy` In addition, `BrainAtlasRegion` gives metadata for all the regions within a `BrainAtlas`; * their volume in the `annotation.nrrd` if they are a leaf, -1 otherwise. * an attached asset with the .obj mesh --- ...20250523_111526_4a2e856cf2db_brainatlas.py | 203 +++ app/cli/brain_region_data.py | 1430 +++++++++++++++++ app/cli/curate.py | 452 +----- app/cli/import_data.py | 172 +- app/cli/utils.py | 17 +- app/db/model.py | 29 +- app/db/types.py | 1 + app/filters/brain_atlas.py | 27 + app/routers/__init__.py | 2 + app/routers/brain_atlas.py | 13 + app/schemas/brain_atlas.py | 31 + app/service/brain_atlas.py | 72 + app/service/brain_region_hierarchy.py | 2 +- docs/schema.md | 1 - tests/test_brain_atlas.py | 162 ++ tests/test_brain_region.py | 41 +- tests/test_brain_region_hierarchy.py | 11 +- tests/utils.py | 32 + 18 files changed, 2106 insertions(+), 592 deletions(-) create mode 100644 alembic/versions/20250523_111526_4a2e856cf2db_brainatlas.py create mode 100644 app/cli/brain_region_data.py create mode 100644 app/filters/brain_atlas.py create mode 100644 app/routers/brain_atlas.py create mode 100644 app/schemas/brain_atlas.py create mode 100644 app/service/brain_atlas.py create mode 100644 tests/test_brain_atlas.py diff --git a/alembic/versions/20250523_111526_4a2e856cf2db_brainatlas.py b/alembic/versions/20250523_111526_4a2e856cf2db_brainatlas.py new file mode 100644 index 00000000..07eb25fe --- /dev/null +++ b/alembic/versions/20250523_111526_4a2e856cf2db_brainatlas.py @@ -0,0 +1,203 @@ +"""brainatlas + +Revision ID: 4a2e856cf2db +Revises: 7699329e803f +Create Date: 2025-05-23 11:15:26.847117 + +""" + +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa +from alembic_postgresql_enum import TableReference +from alembic_utils.pg_trigger import PGTrigger +from sqlalchemy import text as sql_text +from sqlalchemy.dialects import postgresql + +from sqlalchemy import Text +import app.db.types + +# revision identifiers, used by Alembic. +revision: str = "4a2e856cf2db" +down_revision: Union[str, None] = "7699329e803f" +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.create_table( + "brain_atlas_region", + sa.Column("id", sa.Uuid(), nullable=False), + sa.Column("volume", sa.Float(), nullable=True), + sa.Column("leaf_region", sa.Boolean(), nullable=False), + sa.Column("brain_atlas_id", sa.Uuid(), nullable=False), + sa.Column("brain_region_id", sa.Uuid(), nullable=False), + sa.ForeignKeyConstraint( + ["brain_atlas_id"], + ["brain_atlas.id"], + name=op.f("fk_brain_atlas_region_brain_atlas_id_brain_atlas"), + ), + sa.ForeignKeyConstraint( + ["brain_region_id"], + ["brain_region.id"], + name=op.f("fk_brain_atlas_region_brain_region_id_brain_region"), + ), + sa.ForeignKeyConstraint( + ["id"], ["entity.id"], name=op.f("fk_brain_atlas_region_id_entity") + ), + sa.PrimaryKeyConstraint("id", name=op.f("pk_brain_atlas_region")), + ) + op.create_index( + op.f("ix_brain_atlas_region_brain_atlas_id"), + "brain_atlas_region", + ["brain_atlas_id"], + unique=False, + ) + op.create_index( + op.f("ix_brain_atlas_region_brain_region_id"), + "brain_atlas_region", + ["brain_region_id"], + unique=False, + ) + op.drop_index("ix_mesh_brain_region_id", table_name="mesh") + op.drop_index("ix_mesh_description_vector", table_name="mesh", postgresql_using="gin") + op.drop_index("ix_mesh_name", table_name="mesh") + op.drop_table("mesh") + op.add_column("brain_atlas", sa.Column("hierarchy_id", sa.Uuid(), nullable=False)) + op.drop_index("ix_brain_atlas_brain_region_id", table_name="brain_atlas") + op.create_index( + op.f("ix_brain_atlas_hierarchy_id"), "brain_atlas", ["hierarchy_id"], unique=False + ) + op.drop_constraint( + "fk_brain_atlas_brain_region_id_brain_region", "brain_atlas", type_="foreignkey" + ) + op.create_foreign_key( + op.f("fk_brain_atlas_hierarchy_id_brain_region_hierarchy"), + "brain_atlas", + "brain_region_hierarchy", + ["hierarchy_id"], + ["id"], + ) + op.drop_column("brain_atlas", "brain_region_id") + op.sync_enum_values( + enum_schema="public", + enum_name="entitytype", + new_values=[ + "analysis_software_source_code", + "brain_atlas", + "brain_atlas_region", + "emodel", + "cell_composition", + "experimental_bouton_density", + "experimental_neuron_density", + "experimental_synapses_per_connection", + "memodel", + "mesh", + "me_type_density", + "reconstruction_morphology", + "electrical_cell_recording", + "electrical_recording_stimulus", + "single_neuron_simulation", + "single_neuron_synaptome", + "single_neuron_synaptome_simulation", + "ion_channel_model", + "subject", + "validation_result", + ], + affected_columns=[ + TableReference(table_schema="public", table_name="entity", column_name="type") + ], + enum_values_to_rename=[], + ) + + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + public_mesh_mesh_description_vector = PGTrigger( + schema="public", + signature="mesh_description_vector", + on_entity="public.mesh", + is_constraint=False, + definition="BEFORE INSERT OR UPDATE ON public.mesh FOR EACH ROW EXECUTE FUNCTION tsvector_update_trigger('description_vector', 'pg_catalog.english', 'description', 'name')", + ) + op.create_entity(public_mesh_mesh_description_vector) + + op.sync_enum_values( + enum_schema="public", + enum_name="entitytype", + new_values=[ + "analysis_software_source_code", + "brain_atlas", + "emodel", + "cell_composition", + "experimental_bouton_density", + "experimental_neuron_density", + "experimental_synapses_per_connection", + "memodel", + "mesh", + "me_type_density", + "reconstruction_morphology", + "electrical_cell_recording", + "electrical_recording_stimulus", + "single_neuron_simulation", + "single_neuron_synaptome", + "single_neuron_synaptome_simulation", + "ion_channel_model", + "subject", + "validation_result", + ], + affected_columns=[ + TableReference(table_schema="public", table_name="entity", column_name="type") + ], + enum_values_to_rename=[], + ) + op.add_column( + "brain_atlas", sa.Column("brain_region_id", sa.UUID(), autoincrement=False, nullable=False) + ) + op.drop_constraint( + op.f("fk_brain_atlas_hierarchy_id_brain_region_hierarchy"), + "brain_atlas", + type_="foreignkey", + ) + op.create_foreign_key( + "fk_brain_atlas_brain_region_id_brain_region", + "brain_atlas", + "brain_region", + ["brain_region_id"], + ["id"], + ) + op.drop_index(op.f("ix_brain_atlas_hierarchy_id"), table_name="brain_atlas") + op.create_index( + "ix_brain_atlas_brain_region_id", "brain_atlas", ["brain_region_id"], unique=False + ) + op.drop_column("brain_atlas", "hierarchy_id") + op.create_table( + "mesh", + sa.Column("id", sa.UUID(), autoincrement=False, nullable=False), + sa.Column("brain_region_id", sa.UUID(), autoincrement=False, nullable=False), + sa.Column("name", sa.VARCHAR(), autoincrement=False, nullable=False), + sa.Column("description", sa.VARCHAR(), autoincrement=False, nullable=False), + sa.Column("description_vector", postgresql.TSVECTOR(), autoincrement=False, nullable=True), + sa.ForeignKeyConstraint( + ["brain_region_id"], ["brain_region.id"], name="fk_mesh_brain_region_id_brain_region" + ), + sa.ForeignKeyConstraint(["id"], ["entity.id"], name="fk_mesh_id_entity"), + sa.PrimaryKeyConstraint("id", name="pk_mesh"), + ) + op.create_index("ix_mesh_name", "mesh", ["name"], unique=False) + op.create_index( + "ix_mesh_description_vector", + "mesh", + ["description_vector"], + unique=False, + postgresql_using="gin", + ) + op.create_index("ix_mesh_brain_region_id", "mesh", ["brain_region_id"], unique=False) + op.drop_index(op.f("ix_brain_atlas_region_brain_region_id"), table_name="brain_atlas_region") + op.drop_index(op.f("ix_brain_atlas_region_brain_atlas_id"), table_name="brain_atlas_region") + op.drop_table("brain_atlas_region") + # ### end Alembic commands ### diff --git a/app/cli/brain_region_data.py b/app/cli/brain_region_data.py new file mode 100644 index 00000000..7db11f03 --- /dev/null +++ b/app/cli/brain_region_data.py @@ -0,0 +1,1430 @@ +BRAIN_REGION_REPLACEMENTS = { + "Accessory supraoptic group: Other": "2218808594", + "Agranular insular area, dorsal part, layer 2": "3250982806", + "Agranular insular area, dorsal part, layer 3": "3088876178", + "Agranular insular area, posterior part, layer 2": "1672280517", + "Agranular insular area, posterior part, layer 3": "2414821463", + "Agranular insular area, ventral part, layer 2": "2224619882", + "Agranular insular area, ventral part, layer 3": "3376791707", + "Anterior area, layer 2": "1695203883", + "Anterior area, layer 3": "1160721590", + "Anterior cingulate area, dorsal part, layer 2": "3095364455", + "Anterior cingulate area, dorsal part, layer 3": "2862362532", + "Anterior cingulate area, ventral part, layer 2": "2949903222", + "Anterior cingulate area, ventral part, layer 3": "3582239403", + "Anterior hypothalamic nucleus: Other": "1690235425", + "Anterior olfactory nucleus: Other": "2561915647", + "Anterolateral visual area, layer 2": "1463157755", + "Anterolateral visual area, layer 3": "2845253318", + "Anteromedial visual area, layer 2": "1645194511", + "Anteromedial visual area, layer 3": "2292194787", + "Bed nuclei of the stria terminalis: Other": "2791423253", + "Cerebellum: Other": "3092369320", + "Cortical amygdalar area, anterior part: Other": "1466095084", + "Cortical amygdalar area, posterior part, lateral zone: Other": "1992072790", + "Cortical amygdalar area, posterior part, medial zone: Other": "1375046773", + "Cortical subplate: Other": "2416897036", + "Dorsal auditory area, layer 2": "3781663036", + "Dorsal auditory area, layer 3": "2186168811", + "Dorsal peduncular area: Other": "1953921139", + "Dorsomedial nucleus of the hypothalamus: Other": "1463730273", + "Ectorhinal area, layer 2": "2218254883", + "Ectorhinal area, layer 3": "3516629919", + "Frontal pole, layer 2": "2646114338", + "Frontal pole, layer 3": "2536061413", + "Gustatory areas, layer 2": "3683796018", + "Gustatory areas, layer 3": "3893800328", + "Hippocampal formation: Other": "3263488087", + "Hypothalamus: Other": "1842735199", + "Infralimbic area, layer 3": "2078623765", + "Interpeduncular nucleus: Other": "2183090366", + "Lateral visual area, layer 2": "3927629261", + "Lateral visual area, layer 3": "3962734174", + "Laterointermediate area, layer 2": "3808183566", + "Laterointermediate area, layer 3": "2985091592", + "Main olfactory bulb: Other": "2358040414", + "Medial amygdalar nucleus: Other": "2445320853", + "Medial preoptic nucleus: Other": "2254557934", + "Mediodorsal nucleus of thalamus: Other": "3009745967", + "Medulla: Other": "1557651847", + "Midbrain reticular nucleus: Other": "1040222935", + "Midbrain: Other": "3101970431", + "Nucleus of the lateral lemniscus: Other": "2127067043", + "Nucleus of the solitary tract: Other": "2316153360", + "Olfactory areas: Other": "1024543562", + "Olfactory tubercle: Other": "3672106733", + "Orbital area, lateral part, layer 2": "3803368771", + "Orbital area, lateral part, layer 3": "1037481934", + "Orbital area, medial part, layer 3": "2012716980", + "Orbital area, ventrolateral part, layer 2": "3653590473", + "Orbital area, ventrolateral part, layer 3": "2413172686", + "Pallidum: Other": "2165415682", + "Parabrachial nucleus: Other": "3409505442", + "Parapyramidal nucleus: Other": "2114704803", + "Parasubiculum: Other": "2952544119", + "Paraventricular hypothalamic nucleus, descending division: Other": "3467149620", + "Paraventricular hypothalamic nucleus: Other": "2869757686", + "Periaqueductal gray: Other": "2956165934", + "Perirhinal area, layer 2": "3132124329", + "Perirhinal area, layer 3": "2668242174", + "Piriform area: Other": "1668688439", + "Piriform-amygdalar area: Other": "1203939479", + "Pons: Other": "1140764290", + "Posterior auditory area, layer 2": "1307372013", + "Posterior auditory area, layer 3": "1598869030", + "Posterolateral visual area, layer 2": "2153924985", + "Posterolateral visual area, layer 3": "1431942459", + "Postpiriform transition area: Other": "1209357605", + "Postrhinal area, layer 2": "2782023316", + "Postrhinal area, layer 3": "3920533696", + "Postsubiculum: Other": "2063775638", + "Prelimbic area, layer 3": "2790124484", + "Presubiculum: Other": "1580329576", + "Primary auditory area, layer 2": "2927119608", + "Primary auditory area, layer 3": "1165809076", + "Primary motor area, layer 2": "3718675619", + "Primary motor area, layer 3": "1758306548", + "Primary somatosensory area, barrel field, A1 barrel layer 1": "1344105173", + "Primary somatosensory area, barrel field, A1 barrel layer 2": "3116469840", + "Primary somatosensory area, barrel field, A1 barrel layer 2/3": "2615618683", + "Primary somatosensory area, barrel field, A1 barrel layer 3": "3379356047", + "Primary somatosensory area, barrel field, A1 barrel layer 4": "1315119484", + "Primary somatosensory area, barrel field, A1 barrel layer 5": "2436888515", + "Primary somatosensory area, barrel field, A1 barrel layer 6a": "3577346235", + "Primary somatosensory area, barrel field, A1 barrel layer 6b": "3902978127", + "Primary somatosensory area, barrel field, A1 barrel": "1370229894", + "Primary somatosensory area, barrel field, A2 barrel layer 1": "1310126712", + "Primary somatosensory area, barrel field, A2 barrel layer 2": "3324056088", + "Primary somatosensory area, barrel field, A2 barrel layer 2/3": "1446874462", + "Primary somatosensory area, barrel field, A2 barrel layer 3": "2593521448", + "Primary somatosensory area, barrel field, A2 barrel layer 4": "3685934448", + "Primary somatosensory area, barrel field, A2 barrel layer 5": "3575805529", + "Primary somatosensory area, barrel field, A2 barrel layer 6a": "1210837267", + "Primary somatosensory area, barrel field, A2 barrel layer 6b": "1258169895", + "Primary somatosensory area, barrel field, A2 barrel": "3651721123", + "Primary somatosensory area, barrel field, A3 barrel layer 1": "1994494334", + "Primary somatosensory area, barrel field, A3 barrel layer 2": "2590882612", + "Primary somatosensory area, barrel field, A3 barrel layer 2/3": "1447791371", + "Primary somatosensory area, barrel field, A3 barrel layer 3": "3761146439", + "Primary somatosensory area, barrel field, A3 barrel layer 4": "3139552203", + "Primary somatosensory area, barrel field, A3 barrel layer 5": "2692580507", + "Primary somatosensory area, barrel field, A3 barrel layer 6a": "1677451927", + "Primary somatosensory area, barrel field, A3 barrel layer 6b": "3379749055", + "Primary somatosensory area, barrel field, A3 barrel": "2732283703", + "Primary somatosensory area, barrel field, Alpha barrel layer 1": "2835342929", + "Primary somatosensory area, barrel field, Alpha barrel layer 2": "3173729836", + "Primary somatosensory area, barrel field, Alpha barrel layer 2/3": "1897248316", + "Primary somatosensory area, barrel field, Alpha barrel layer 3": "3926962776", + "Primary somatosensory area, barrel field, Alpha barrel layer 4": "2168807353", + "Primary somatosensory area, barrel field, Alpha barrel layer 5": "3137025327", + "Primary somatosensory area, barrel field, Alpha barrel layer 6a": "2406188897", + "Primary somatosensory area, barrel field, Alpha barrel layer 6b": "3670777223", + "Primary somatosensory area, barrel field, Alpha barrel": "3896406483", + "Primary somatosensory area, barrel field, B1 barrel layer 1": "1516851569", + "Primary somatosensory area, barrel field, B1 barrel layer 2": "2196657368", + "Primary somatosensory area, barrel field, B1 barrel layer 2/3": "3913053667", + "Primary somatosensory area, barrel field, B1 barrel layer 3": "3986345576", + "Primary somatosensory area, barrel field, B1 barrel layer 4": "3495145594", + "Primary somatosensory area, barrel field, B1 barrel layer 5": "1644849336", + "Primary somatosensory area, barrel field, B1 barrel layer 6a": "3289019263", + "Primary somatosensory area, barrel field, B1 barrel layer 6b": "2194674250", + "Primary somatosensory area, barrel field, B1 barrel": "2525641171", + "Primary somatosensory area, barrel field, B2 barrel layer 1": "3853526235", + "Primary somatosensory area, barrel field, B2 barrel layer 2": "1311366798", + "Primary somatosensory area, barrel field, B2 barrel layer 2/3": "3456985752", + "Primary somatosensory area, barrel field, B2 barrel layer 3": "1126601402", + "Primary somatosensory area, barrel field, B2 barrel layer 4": "3966633210", + "Primary somatosensory area, barrel field, B2 barrel layer 5": "2812530569", + "Primary somatosensory area, barrel field, B2 barrel layer 6a": "1641347046", + "Primary somatosensory area, barrel field, B2 barrel layer 6b": "3416776496", + "Primary somatosensory area, barrel field, B2 barrel": "1673450198", + "Primary somatosensory area, barrel field, B3 barrel layer 1": "3565367498", + "Primary somatosensory area, barrel field, B3 barrel layer 2": "1881029055", + "Primary somatosensory area, barrel field, B3 barrel layer 2/3": "2657138906", + "Primary somatosensory area, barrel field, B3 barrel layer 3": "3080022137", + "Primary somatosensory area, barrel field, B3 barrel layer 4": "1547817274", + "Primary somatosensory area, barrel field, B3 barrel layer 5": "2369238059", + "Primary somatosensory area, barrel field, B3 barrel layer 6a": "2478012832", + "Primary somatosensory area, barrel field, B3 barrel layer 6b": "2739084189", + "Primary somatosensory area, barrel field, B3 barrel": "1626685236", + "Primary somatosensory area, barrel field, B4 barrel layer 1": "2006047173", + "Primary somatosensory area, barrel field, B4 barrel layer 2": "1456682260", + "Primary somatosensory area, barrel field, B4 barrel layer 2/3": "2180527067", + "Primary somatosensory area, barrel field, B4 barrel layer 3": "3562601313", + "Primary somatosensory area, barrel field, B4 barrel layer 4": "1970686062", + "Primary somatosensory area, barrel field, B4 barrel layer 5": "3890169311", + "Primary somatosensory area, barrel field, B4 barrel layer 6a": "2936441103", + "Primary somatosensory area, barrel field, B4 barrel layer 6b": "3215542274", + "Primary somatosensory area, barrel field, B4 barrel": "3347675430", + "Primary somatosensory area, barrel field, Beta barrel layer 1": "3486673188", + "Primary somatosensory area, barrel field, Beta barrel layer 2": "3970522306", + "Primary somatosensory area, barrel field, Beta barrel layer 2/3": "3783583602", + "Primary somatosensory area, barrel field, Beta barrel layer 3": "1054221329", + "Primary somatosensory area, barrel field, Beta barrel layer 4": "3895794866", + "Primary somatosensory area, barrel field, Beta barrel layer 5": "1496257237", + "Primary somatosensory area, barrel field, Beta barrel layer 6a": "2152572352", + "Primary somatosensory area, barrel field, Beta barrel layer 6b": "3048883337", + "Primary somatosensory area, barrel field, Beta barrel": "1521759875", + "Primary somatosensory area, barrel field, C1 barrel layer 1": "1337935688", + "Primary somatosensory area, barrel field, C1 barrel layer 2": "1558550786", + "Primary somatosensory area, barrel field, C1 barrel layer 2/3": "1667660763", + "Primary somatosensory area, barrel field, C1 barrel layer 3": "2563782304", + "Primary somatosensory area, barrel field, C1 barrel layer 4": "3219108088", + "Primary somatosensory area, barrel field, C1 barrel layer 5": "1420546517", + "Primary somatosensory area, barrel field, C1 barrel layer 6a": "1945434117", + "Primary somatosensory area, barrel field, C1 barrel layer 6b": "2866280389", + "Primary somatosensory area, barrel field, C1 barrel": "1013068637", + "Primary somatosensory area, barrel field, C2 barrel layer 1": "1082141991", + "Primary somatosensory area, barrel field, C2 barrel layer 2": "2525505631", + "Primary somatosensory area, barrel field, C2 barrel layer 2/3": "2157537321", + "Primary somatosensory area, barrel field, C2 barrel layer 3": "1714311201", + "Primary somatosensory area, barrel field, C2 barrel layer 4": "2930307508", + "Primary somatosensory area, barrel field, C2 barrel layer 5": "3188993656", + "Primary somatosensory area, barrel field, C2 barrel layer 6a": "1843338795", + "Primary somatosensory area, barrel field, C2 barrel layer 6b": "3291535006", + "Primary somatosensory area, barrel field, C2 barrel": "2072239244", + "Primary somatosensory area, barrel field, C3 barrel layer 1": "3835740469", + "Primary somatosensory area, barrel field, C3 barrel layer 2": "2629778705", + "Primary somatosensory area, barrel field, C3 barrel layer 2/3": "1125438717", + "Primary somatosensory area, barrel field, C3 barrel layer 3": "3581771805", + "Primary somatosensory area, barrel field, C3 barrel layer 4": "3877358805", + "Primary somatosensory area, barrel field, C3 barrel layer 5": "1667278413", + "Primary somatosensory area, barrel field, C3 barrel layer 6a": "2743616995", + "Primary somatosensory area, barrel field, C3 barrel layer 6b": "1093211310", + "Primary somatosensory area, barrel field, C3 barrel": "2937437636", + "Primary somatosensory area, barrel field, C4 barrel layer 1": "2151167540", + "Primary somatosensory area, barrel field, C4 barrel layer 2": "3167765177", + "Primary somatosensory area, barrel field, C4 barrel layer 2/3": "2460702429", + "Primary somatosensory area, barrel field, C4 barrel layer 3": "1639524986", + "Primary somatosensory area, barrel field, C4 barrel layer 4": "1549069626", + "Primary somatosensory area, barrel field, C4 barrel layer 5": "3085221154", + "Primary somatosensory area, barrel field, C4 barrel layer 6a": "2659044087", + "Primary somatosensory area, barrel field, C4 barrel layer 6b": "2700046659", + "Primary somatosensory area, barrel field, C4 barrel": "3404738524", + "Primary somatosensory area, barrel field, C5 barrel layer 1": "1246610280", + "Primary somatosensory area, barrel field, C5 barrel layer 2": "1035739465", + "Primary somatosensory area, barrel field, C5 barrel layer 2/3": "3880590912", + "Primary somatosensory area, barrel field, C5 barrel layer 3": "1105483506", + "Primary somatosensory area, barrel field, C5 barrel layer 4": "1792980078", + "Primary somatosensory area, barrel field, C5 barrel layer 5": "3556494715", + "Primary somatosensory area, barrel field, C5 barrel layer 6a": "1706307657", + "Primary somatosensory area, barrel field, C5 barrel layer 6b": "1869881498", + "Primary somatosensory area, barrel field, C5 barrel": "2062992388", + "Primary somatosensory area, barrel field, C6 barrel layer 1": "2933568634", + "Primary somatosensory area, barrel field, C6 barrel layer 2": "1805611561", + "Primary somatosensory area, barrel field, C6 barrel layer 2/3": "2013207018", + "Primary somatosensory area, barrel field, C6 barrel layer 3": "3719447735", + "Primary somatosensory area, barrel field, C6 barrel layer 4": "2371017187", + "Primary somatosensory area, barrel field, C6 barrel layer 5": "3985188708", + "Primary somatosensory area, barrel field, C6 barrel layer 6a": "3796365620", + "Primary somatosensory area, barrel field, C6 barrel layer 6b": "1714819828", + "Primary somatosensory area, barrel field, C6 barrel": "1261138116", + "Primary somatosensory area, barrel field, D1 barrel layer 1": "3724099631", + "Primary somatosensory area, barrel field, D1 barrel layer 2": "2558258359", + "Primary somatosensory area, barrel field, D1 barrel layer 2/3": "2833279579", + "Primary somatosensory area, barrel field, D1 barrel layer 3": "3859877696", + "Primary somatosensory area, barrel field, D1 barrel layer 4": "2108774369", + "Primary somatosensory area, barrel field, D1 barrel layer 5": "3320050311", + "Primary somatosensory area, barrel field, D1 barrel layer 6a": "3628159968", + "Primary somatosensory area, barrel field, D1 barrel layer 6b": "3638507875", + "Primary somatosensory area, barrel field, D1 barrel": "1171261412", + "Primary somatosensory area, barrel field, D2 barrel layer 1": "1743009264", + "Primary somatosensory area, barrel field, D2 barrel layer 2": "3623254419", + "Primary somatosensory area, barrel field, D2 barrel layer 2/3": "1884779226", + "Primary somatosensory area, barrel field, D2 barrel layer 3": "1926976537", + "Primary somatosensory area, barrel field, D2 barrel layer 4": "2047390011", + "Primary somatosensory area, barrel field, D2 barrel layer 5": "2798287336", + "Primary somatosensory area, barrel field, D2 barrel layer 6a": "2987319910", + "Primary somatosensory area, barrel field, D2 barrel layer 6b": "3872485424", + "Primary somatosensory area, barrel field, D2 barrel": "3329043535", + "Primary somatosensory area, barrel field, D3 barrel layer 1": "1781030954", + "Primary somatosensory area, barrel field, D3 barrel layer 2": "3521164295", + "Primary somatosensory area, barrel field, D3 barrel layer 2/3": "2841658580", + "Primary somatosensory area, barrel field, D3 barrel layer 3": "1876807310", + "Primary somatosensory area, barrel field, D3 barrel layer 4": "1501393228", + "Primary somatosensory area, barrel field, D3 barrel layer 5": "1972094100", + "Primary somatosensory area, barrel field, D3 barrel layer 6a": "3302405705", + "Primary somatosensory area, barrel field, D3 barrel layer 6b": "1099096371", + "Primary somatosensory area, barrel field, D3 barrel": "2036081150", + "Primary somatosensory area, barrel field, D4 barrel layer 1": "1117257996", + "Primary somatosensory area, barrel field, D4 barrel layer 2": "2567067139", + "Primary somatosensory area, barrel field, D4 barrel layer 2/3": "1453537399", + "Primary somatosensory area, barrel field, D4 barrel layer 3": "2427348802", + "Primary somatosensory area, barrel field, D4 barrel layer 4": "3859818063", + "Primary somatosensory area, barrel field, D4 barrel layer 5": "1588504257", + "Primary somatosensory area, barrel field, D4 barrel layer 6a": "3571205574", + "Primary somatosensory area, barrel field, D4 barrel layer 6b": "1096265790", + "Primary somatosensory area, barrel field, D4 barrel": "3202423327", + "Primary somatosensory area, barrel field, D5 barrel layer 1": "1326886999", + "Primary somatosensory area, barrel field, D5 barrel layer 2": "2341450864", + "Primary somatosensory area, barrel field, D5 barrel layer 2/3": "1787178465", + "Primary somatosensory area, barrel field, D5 barrel layer 3": "2551618170", + "Primary somatosensory area, barrel field, D5 barrel layer 4": "1170723867", + "Primary somatosensory area, barrel field, D5 barrel layer 5": "1038004598", + "Primary somatosensory area, barrel field, D5 barrel layer 6a": "1149652689", + "Primary somatosensory area, barrel field, D5 barrel layer 6b": "1582478571", + "Primary somatosensory area, barrel field, D5 barrel": "1412541198", + "Primary somatosensory area, barrel field, D6 barrel layer 1": "1315950883", + "Primary somatosensory area, barrel field, D6 barrel layer 2": "3990698322", + "Primary somatosensory area, barrel field, D6 barrel layer 2/3": "1947266943", + "Primary somatosensory area, barrel field, D6 barrel layer 3": "3301183793", + "Primary somatosensory area, barrel field, D6 barrel layer 4": "1464978040", + "Primary somatosensory area, barrel field, D6 barrel layer 5": "2387503636", + "Primary somatosensory area, barrel field, D6 barrel layer 6a": "2023633893", + "Primary somatosensory area, barrel field, D6 barrel layer 6b": "1913328693", + "Primary somatosensory area, barrel field, D6 barrel": "1588741938", + "Primary somatosensory area, barrel field, D7 barrel layer 1": "1877482733", + "Primary somatosensory area, barrel field, D7 barrel layer 2": "3673895945", + "Primary somatosensory area, barrel field, D7 barrel layer 2/3": "2358987890", + "Primary somatosensory area, barrel field, D7 barrel layer 3": "1393608993", + "Primary somatosensory area, barrel field, D7 barrel layer 4": "2978179471", + "Primary somatosensory area, barrel field, D7 barrel layer 5": "3338653017", + "Primary somatosensory area, barrel field, D7 barrel layer 6a": "2384899589", + "Primary somatosensory area, barrel field, D7 barrel layer 6b": "2710463424", + "Primary somatosensory area, barrel field, D7 barrel": "3920024588", + "Primary somatosensory area, barrel field, D8 barrel layer 1": "1406402073", + "Primary somatosensory area, barrel field, D8 barrel layer 2": "1156116970", + "Primary somatosensory area, barrel field, D8 barrel layer 2/3": "1373744894", + "Primary somatosensory area, barrel field, D8 barrel layer 3": "3453175542", + "Primary somatosensory area, barrel field, D8 barrel layer 4": "3652474151", + "Primary somatosensory area, barrel field, D8 barrel layer 5": "2236457933", + "Primary somatosensory area, barrel field, D8 barrel layer 6a": "3277826222", + "Primary somatosensory area, barrel field, D8 barrel layer 6b": "1005899076", + "Primary somatosensory area, barrel field, D8 barrel": "3055000922", + "Primary somatosensory area, barrel field, Delta barrel layer 1": "1691306271", + "Primary somatosensory area, barrel field, Delta barrel layer 2": "1275601165", + "Primary somatosensory area, barrel field, Delta barrel layer 2/3": "3434166213", + "Primary somatosensory area, barrel field, Delta barrel layer 3": "3946289800", + "Primary somatosensory area, barrel field, Delta barrel layer 4": "2004775342", + "Primary somatosensory area, barrel field, Delta barrel layer 5": "1456398198", + "Primary somatosensory area, barrel field, Delta barrel layer 6a": "3561503481", + "Primary somatosensory area, barrel field, Delta barrel layer 6b": "1901850664", + "Primary somatosensory area, barrel field, Delta barrel": "2438939909", + "Primary somatosensory area, barrel field, E1 barrel layer 1": "3807479791", + "Primary somatosensory area, barrel field, E1 barrel layer 2": "2980820846", + "Primary somatosensory area, barrel field, E1 barrel layer 2/3": "2803418480", + "Primary somatosensory area, barrel field, E1 barrel layer 3": "3188360247", + "Primary somatosensory area, barrel field, E1 barrel layer 4": "1477785742", + "Primary somatosensory area, barrel field, E1 barrel layer 5": "2964598138", + "Primary somatosensory area, barrel field, E1 barrel layer 6a": "3093795446", + "Primary somatosensory area, barrel field, E1 barrel layer 6b": "1507784331", + "Primary somatosensory area, barrel field, E1 barrel": "1071521092", + "Primary somatosensory area, barrel field, E2 barrel layer 1": "3748961581", + "Primary somatosensory area, barrel field, E2 barrel layer 2": "2185403483", + "Primary somatosensory area, barrel field, E2 barrel layer 2/3": "3128223634", + "Primary somatosensory area, barrel field, E2 barrel layer 3": "1433026796", + "Primary somatosensory area, barrel field, E2 barrel layer 4": "1104248884", + "Primary somatosensory area, barrel field, E2 barrel layer 5": "3545403109", + "Primary somatosensory area, barrel field, E2 barrel layer 6a": "1536696383", + "Primary somatosensory area, barrel field, E2 barrel layer 6b": "3527105324", + "Primary somatosensory area, barrel field, E2 barrel": "3054551821", + "Primary somatosensory area, barrel field, E3 barrel layer 1": "1897015494", + "Primary somatosensory area, barrel field, E3 barrel layer 2": "2795738785", + "Primary somatosensory area, barrel field, E3 barrel layer 2/3": "3331790659", + "Primary somatosensory area, barrel field, E3 barrel layer 3": "2768475141", + "Primary somatosensory area, barrel field, E3 barrel layer 4": "2658097375", + "Primary somatosensory area, barrel field, E3 barrel layer 5": "2157528000", + "Primary somatosensory area, barrel field, E3 barrel layer 6a": "3309772165", + "Primary somatosensory area, barrel field, E3 barrel layer 6b": "1928393658", + "Primary somatosensory area, barrel field, E3 barrel": "2811301625", + "Primary somatosensory area, barrel field, E4 barrel layer 1": "3841505448", + "Primary somatosensory area, barrel field, E4 barrel layer 2": "3325173834", + "Primary somatosensory area, barrel field, E4 barrel layer 2/3": "3999683881", + "Primary somatosensory area, barrel field, E4 barrel layer 3": "1798728430", + "Primary somatosensory area, barrel field, E4 barrel layer 4": "3299719941", + "Primary somatosensory area, barrel field, E4 barrel layer 5": "2360313730", + "Primary somatosensory area, barrel field, E4 barrel layer 6a": "3043750963", + "Primary somatosensory area, barrel field, E4 barrel layer 6b": "2641148319", + "Primary somatosensory area, barrel field, E4 barrel": "3840818183", + "Primary somatosensory area, barrel field, E5 barrel layer 1": "1427961626", + "Primary somatosensory area, barrel field, E5 barrel layer 2": "3092405473", + "Primary somatosensory area, barrel field, E5 barrel layer 2/3": "1643593739", + "Primary somatosensory area, barrel field, E5 barrel layer 3": "1181035221", + "Primary somatosensory area, barrel field, E5 barrel layer 4": "3118601025", + "Primary somatosensory area, barrel field, E5 barrel layer 5": "2374653061", + "Primary somatosensory area, barrel field, E5 barrel layer 6a": "3026302666", + "Primary somatosensory area, barrel field, E5 barrel layer 6b": "2197459620", + "Primary somatosensory area, barrel field, E5 barrel": "1468793762", + "Primary somatosensory area, barrel field, E6 barrel layer 1": "1666373161", + "Primary somatosensory area, barrel field, E6 barrel layer 2": "2815501138", + "Primary somatosensory area, barrel field, E6 barrel layer 2/3": "3620340000", + "Primary somatosensory area, barrel field, E6 barrel layer 3": "2091848107", + "Primary somatosensory area, barrel field, E6 barrel layer 4": "2658756176", + "Primary somatosensory area, barrel field, E6 barrel layer 5": "2097438884", + "Primary somatosensory area, barrel field, E6 barrel layer 6a": "2868822451", + "Primary somatosensory area, barrel field, E6 barrel layer 6b": "3331415743", + "Primary somatosensory area, barrel field, E6 barrel": "1965375801", + "Primary somatosensory area, barrel field, E7 barrel layer 1": "2613674898", + "Primary somatosensory area, barrel field, E7 barrel layer 2": "3413451609", + "Primary somatosensory area, barrel field, E7 barrel layer 2/3": "1951878763", + "Primary somatosensory area, barrel field, E7 barrel layer 3": "2225157452", + "Primary somatosensory area, barrel field, E7 barrel layer 4": "2842134861", + "Primary somatosensory area, barrel field, E7 barrel layer 5": "2064317417", + "Primary somatosensory area, barrel field, E7 barrel layer 6a": "2123772309", + "Primary somatosensory area, barrel field, E7 barrel layer 6b": "1510133109", + "Primary somatosensory area, barrel field, E7 barrel": "3618095278", + "Primary somatosensory area, barrel field, E8 barrel layer 1": "1094902124", + "Primary somatosensory area, barrel field, E8 barrel layer 2": "3312222592", + "Primary somatosensory area, barrel field, E8 barrel layer 2/3": "3134535128", + "Primary somatosensory area, barrel field, E8 barrel layer 3": "1518704958", + "Primary somatosensory area, barrel field, E8 barrel layer 4": "1475527815", + "Primary somatosensory area, barrel field, E8 barrel layer 5": "1612593605", + "Primary somatosensory area, barrel field, E8 barrel layer 6a": "2915675742", + "Primary somatosensory area, barrel field, E8 barrel layer 6b": "2644357350", + "Primary somatosensory area, barrel field, E8 barrel": "1624778115", + "Primary somatosensory area, barrel field, Gamma barrel layer 1": "2810081477", + "Primary somatosensory area, barrel field, Gamma barrel layer 2": "2790136061", + "Primary somatosensory area, barrel field, Gamma barrel layer 2/3": "3513655281", + "Primary somatosensory area, barrel field, Gamma barrel layer 3": "2667261098", + "Primary somatosensory area, barrel field, Gamma barrel layer 4": "2302833148", + "Primary somatosensory area, barrel field, Gamma barrel layer 5": "3278290071", + "Primary somatosensory area, barrel field, Gamma barrel layer 6a": "2688781451", + "Primary somatosensory area, barrel field, Gamma barrel layer 6b": "1848522986", + "Primary somatosensory area, barrel field, Gamma barrel": "1171320182", + "Primary somatosensory area, barrel field, layer 2": "2835688982", + "Primary somatosensory area, barrel field, layer 3": "2598818153", + "Primary somatosensory area, lower limb, layer 2": "1454256797", + "Primary somatosensory area, lower limb, layer 3": "2951747260", + "Primary somatosensory area, mouth, layer 2": "2102386393", + "Primary somatosensory area, mouth, layer 3": "3049552521", + "Primary somatosensory area, nose, layer 2": "3591549811", + "Primary somatosensory area, nose, layer 3": "1624848466", + "Primary somatosensory area, trunk, layer 2": "3562104832", + "Primary somatosensory area, trunk, layer 3": "2260827822", + "Primary somatosensory area, unassigned, layer 2": "3808433473", + "Primary somatosensory area, unassigned, layer 3": "2208057363", + "Primary somatosensory area, upper limb, layer 2": "3693772975", + "Primary somatosensory area, upper limb, layer 3": "1890964946", + "Primary visual area, layer 2": "2683995601", + "Primary visual area, layer 3": "3894563657", + "Prosubiculum: Other": "2449182232", + "Retrosplenial area, dorsal part, layer 2": "2361776473", + "Retrosplenial area, dorsal part, layer 3": "3956191525", + "Retrosplenial area, lateral agranular part, layer 2": "3192952047", + "Retrosplenial area, lateral agranular part, layer 3": "2892558637", + "Retrosplenial area, ventral part, layer 3": "3314370483", + "Rostrolateral visual area, layer 2": "1430875964", + "Rostrolateral visual area, layer 3": "3714509274", + "Secondary motor area, layer 2": 3412423041, + "Secondary motor area, layer 3": "2511156654", + "Spinal nucleus of the trigeminal, oral part: Other": "1593308392", + "Striatum: Other": "3034756217", + "Subiculum: Other": "1792026161", + "Superior central nucleus raphe: Other": "2557684018", + "Superior colliculus, motor related, intermediate gray layer: Other": "3654510924", + "Supplemental somatosensory area, layer 2": "2336071181", + "Supplemental somatosensory area, layer 3": "2542216029", + "Supramammillary nucleus: Other": "3449035628", + "Taenia tecta, dorsal part: Other": "3389528505", + "Taenia tecta, ventral part: Other": "1860102496", + "Temporal association areas, layer 2": "2439179873", + "Temporal association areas, layer 3": "2854337283", + "Thalamus: Other": "2614168502", + "Ventral auditory area, layer 2": "1942628671", + "Ventral auditory area, layer 3": "2167613582", + "Ventral part of the lateral geniculate complex: Other": "1043765183", + "Ventromedial hypothalamic nucleus: Other": "2723065947", + "Visceral area, layer 2": "3964792502", + "Visceral area, layer 3": "2189208794", + "Zona incerta: Other": "1171543751", + "corpus callosum, anterior forceps: Other": "3228324150", + "corticospinal tract: Other": "2718688460", + "facial nerve: Other": "3283016083", + "fiber tracts: Other": "2500193001", + "fourth ventricle: Other": "3774104740", + "inferior cerebellar peduncle: Other": "3140724988", + "lateral ventricle: Other": "1744978404", + "oculomotor nerve: Other": "3944974149", + "optic nerve: Other": "1166850207", + "posteromedial visual area, layer 2": "2544082156", + "posteromedial visual area, layer 3": "3710667749", + "root: Other": "1811993763", + "rubrospinal tract: Other": "1428498274", + "sensory root of the trigeminal nerve: Other": "2176156825", + "stria terminalis: Other": "2923485783", + "superior cerebelar peduncles: Other": "2692485271", + "superior cerebellar peduncle decussation: Other": "2434751741", + "supraoptic commissures: Other": "1060511842", + "trochlear nerve: Other": "3537828992", +} + +# this was created by: +# import numpy as np; import voxcell +# br = voxcell.VoxelData.load_nrrd('path/to/annotation.nrrd') +# {int(r): float(c*br.voxel_volume) for r, c in zip(*np.unique(br.raw, return_counts=True))} +BRAIN_ATLAS_REGION_VOLUMES = { + "1": 108343750.0, + "2": 114625000.0, + "6": 2367218750.0, + "7": 1097656250.0, + "9": 232531250.0, + "12": 87562500.0, + "15": 229531250.0, + "17": 2077968750.0, + "19": 126125000.0, + "20": 1595468750.0, + "23": 493562500.0, + "26": 1188468750.0, + "27": 69406250.0, + "28": 1043625000.0, + "30": 50531250.0, + "33": 1063968750.0, + "35": 32593750.0, + "36": 195062500.0, + "42": 328250000.0, + "50": 171218750.0, + "52": 1309218750.0, + "54": 50000000.0, + "56": 4361156250.0, + "58": 42906250.0, + "59": 182125000.0, + "62": 147875000.0, + "64": 159812500.0, + "66": 18218750.0, + "67": 79843750.0, + "68": 254656250.0, + "72": 98406250.0, + "74": 206187500.0, + "75": 11000000.0, + "78": 1086437500.0, + "83": 510093750.0, + "84": 462375000.0, + "91": 855625000.0, + "93": 58062500.0, + "96": 611718750.0, + "97": 529968750.0, + "98": 136281250.0, + "101": 1014500000.0, + "102": 110406250.0, + "105": 194375000.0, + "106": 7125000.0, + "108": 1445906250.0, + "114": 338312500.0, + "115": 7375000.0, + "117": 313125000.0, + "118": 207531250.0, + "120": 417281250.0, + "121": 38437500.0, + "122": 368593750.0, + "123": 173593750.0, + "125": 694593750.0, + "126": 127531250.0, + "129": 930218750.0, + "131": 833468750.0, + "132": 21718750.0, + "133": 145281250.0, + "136": 2779312500.0, + "139": 1421000000.0, + "140": 418750000.0, + "143": 21812500.0, + "146": 2353656250.0, + "147": 14718750.0, + "148": 146406250.0, + "149": 454156250.0, + "153": 459031250.0, + "155": 1012375000.0, + "156": 183281250.0, + "158": 54031250.0, + "162": 203343750.0, + "164": 937500.0, + "169": 247250000.0, + "171": 529937500.0, + "173": 147781250.0, + "177": 29937500.0, + "181": 425968750.0, + "186": 345687500.0, + "187": 544625000.0, + "188": 153875000.0, + "189": 93093750.0, + "190": 561437500.0, + "194": 2068281250.0, + "195": 139218750.0, + "196": 156656250.0, + "197": 57906250.0, + "198": 70125000.0, + "202": 1815187500.0, + "203": 60625000.0, + "204": 276750000.0, + "206": 131843750.0, + "207": 54031250.0, + "209": 286968750.0, + "210": 77656250.0, + "212": 4649125000.0, + "214": 782875000.0, + "215": 1272375000.0, + "217": 352156250.0, + "218": 1197906250.0, + "220": 5379843750.0, + "222": 43281250.0, + "223": 287093750.0, + "225": 746187500.0, + "226": 555343750.0, + "228": 1145937500.0, + "230": 75343750.0, + "231": 42875000.0, + "233": 203500000.0, + "234": 309718750.0, + "236": 1215906250.0, + "237": 9312500.0, + "238": 96093750.0, + "243": 31187500.0, + "244": 5753343750.0, + "246": 137875000.0, + "249": 78812500.0, + "250": 560906250.0, + "252": 341500000.0, + "255": 416312500.0, + "257": 150375000.0, + "258": 1874906250.0, + "260": 110687500.0, + "262": 1445406250.0, + "263": 92625000.0, + "266": 606031250.0, + "268": 148187500.0, + "271": 96312500.0, + "272": 185500000.0, + "274": 756375000.0, + "279": 34968750.0, + "280": 15656250.0, + "281": 132750000.0, + "286": 65781250.0, + "287": 7593750.0, + "289": 945718750.0, + "292": 24406250.0, + "298": 362406250.0, + "303": 771750000.0, + "305": 166843750.0, + "307": 533781250.0, + "310": 480812500.0, + "311": 711687500.0, + "314": 436875000.0, + "318": 17656250.0, + "320": 1322625000.0, + "321": 26875000.0, + "325": 180156250.0, + "327": 766187500.0, + "330": 32343750.0, + "333": 36750000.0, + "334": 718218750.0, + "335": 53375000.0, + "336": 27812500.0, + "338": 22343750.0, + "342": 3008500000.0, + "344": 748906250.0, + "347": 110843750.0, + "350": 27250000.0, + "355": 21250000.0, + "356": 12562500.0, + "358": 46812500.0, + "363": 974062500.0, + "364": 166187500.0, + "366": 307781250.0, + "368": 12718750.0, + "372": 53687500.0, + "374": 194656250.0, + "377": 108593750.0, + "380": 22968750.0, + "381": 1526468750.0, + "390": 47250000.0, + "391": 1909750000.0, + "393": 9125000.0, + "397": 37500000.0, + "399": 3569562500.0, + "401": 59875000.0, + "407": 931687500.0, + "413": 248218750.0, + "414": 69718750.0, + "415": 3703500000.0, + "421": 184031250.0, + "422": 133937500.0, + "428": 8000000.0, + "429": 1675562500.0, + "431": 120937500.0, + "433": 226187500.0, + "436": 269437500.0, + "437": 1824625000.0, + "438": 131250000.0, + "440": 479468750.0, + "441": 28406250.0, + "442": 821843750.0, + "443": 950156250.0, + "446": 59593750.0, + "448": 373125000.0, + "449": 66781250.0, + "450": 459281250.0, + "451": 420281250.0, + "452": 44687500.0, + "454": 161437500.0, + "456": 18125000.0, + "461": 33250000.0, + "466": 1399937500.0, + "469": 30031250.0, + "470": 191125000.0, + "471": 636812500.0, + "478": 523906250.0, + "479": 663625000.0, + "482": 245687500.0, + "483": 319562500.0, + "484": 432468750.0, + "486": 2104062500.0, + "488": 47000000.0, + "495": 1292781250.0, + "501": 98156250.0, + "504": 1535406250.0, + "506": 12281250.0, + "510": 49687500.0, + "520": 281281250.0, + "523": 555406250.0, + "524": 108234375.0, + "526": 1246000000.0, + "527": 196187500.0, + "530": 38093750.0, + "531": 43906250.0, + "534": 258937500.0, + "538": 127375000.0, + "540": 222093750.0, + "542": 963531250.0, + "543": 1250687500.0, + "544": 307625000.0, + "551": 257625000.0, + "553": 145562500.0, + "558": 404468750.0, + "559": 745937500.0, + "564": 424687500.0, + "565": 284250000.0, + "573": 178468750.0, + "574": 691406250.0, + "575": 359781250.0, + "576": 5750000.0, + "577": 523687500.0, + "579": 1034437500.0, + "580": 86843750.0, + "581": 359625000.0, + "583": 548531250.0, + "587": 91625000.0, + "588": 470062500.0, + "590": 658875000.0, + "591": 84250000.0, + "593": 1255562500.0, + "595": 167312500.0, + "596": 740437500.0, + "598": 47656250.0, + "599": 254468750.0, + "601": 112968750.0, + "603": 1507843750.0, + "604": 107687500.0, + "606": 250812500.0, + "608": 239437500.0, + "609": 134468750.0, + "610": 1203906250.0, + "611": 47093750.0, + "613": 312343750.0, + "614": 524125000.0, + "616": 549906250.0, + "620": 471468750.0, + "621": 351437500.0, + "622": 50156250.0, + "625": 791531250.0, + "628": 204593750.0, + "629": 816500000.0, + "630": 1202750000.0, + "632": 1580906250.0, + "633": 18375000.0, + "634": 289062500.0, + "638": 436437500.0, + "642": 153843750.0, + "648": 3256031250.0, + "649": 22531250.0, + "653": 30156250.0, + "654": 546625000.0, + "656": 2308437500.0, + "658": 829000000.0, + "661": 918312500.0, + "662": 40125000.0, + "664": 981437500.0, + "665": 872937500.0, + "671": 497468750.0, + "672": 25878750000.0, + "673": 32031250.0, + "675": 167406250.0, + "678": 131750000.0, + "680": 9906250.0, + "681": 55156250.0, + "685": 925218750.0, + "687": 1669250000.0, + "689": 67250000.0, + "690": 127062500.0, + "692": 168250000.0, + "696": 112218750.0, + "697": 614093750.0, + "699": 3187500.0, + "702": 564781250.0, + "704": 246843750.0, + "706": 57187500.0, + "707": 155718750.0, + "711": 331187500.0, + "718": 870687500.0, + "721": 1020500000.0, + "725": 98875000.0, + "727": 910187500.0, + "728": 6915093750.0, + "729": 520562500.0, + "732": 80312500.0, + "733": 1635312500.0, + "735": 372500000.0, + "741": 214687500.0, + "743": 618750000.0, + "744": 68187500.0, + "747": 48281250.0, + "749": 423968750.0, + "750": 192250000.0, + "753": 33500000.0, + "757": 38187500.0, + "759": 73531250.0, + "763": 9187500.0, + "765": 56687500.0, + "767": 4497750000.0, + "772": 989937500.0, + "773": 278906250.0, + "774": 732125000.0, + "778": 1544812500.0, + "780": 963218750.0, + "781": 23187500.0, + "783": 778093750.0, + "786": 88000000.0, + "791": 180500000.0, + "794": 1610250000.0, + "800": 718843750.0, + "802": 270500000.0, + "804": 240562500.0, + "805": 185406250.0, + "810": 360968750.0, + "811": 1122218750.0, + "816": 233718750.0, + "819": 61812500.0, + "820": 1321718750.0, + "827": 333500000.0, + "828": 1984562500.0, + "831": 48375000.0, + "834": 360687500.0, + "836": 254781250.0, + "839": 171937500.0, + "841": 346750000.0, + "842": 1150343750.0, + "844": 2853718750.0, + "846": 335000000.0, + "847": 710875000.0, + "849": 51781250.0, + "850": 84875000.0, + "851": 642031250.0, + "852": 2208906250.0, + "857": 535125000.0, + "859": 27625000.0, + "862": 2070218750.0, + "866": 284156250.0, + "869": 35937500.0, + "872": 162000000.0, + "873": 1237031250.0, + "874": 45375000.0, + "878": 774968750.0, + "880": 103281250.0, + "882": 182750000.0, + "884": 160687500.0, + "889": 798531250.0, + "893": 212062500.0, + "897": 336093750.0, + "898": 545750000.0, + "900": 733250000.0, + "902": 241500000.0, + "903": 205812500.0, + "906": 411937500.0, + "907": 238750000.0, + "908": 211750000.0, + "910": 186281250.0, + "914": 11468750.0, + "916": 196875000.0, + "919": 696125000.0, + "924": 874343750.0, + "927": 24937500.0, + "929": 54125000.0, + "930": 490218750.0, + "931": 956343750.0, + "935": 612125000.0, + "939": 21750000.0, + "940": 1252093750.0, + "945": 936875000.0, + "946": 707687500.0, + "949": 13281250.0, + "950": 941156250.0, + "952": 1799562500.0, + "954": 296250000.0, + "955": 511968750.0, + "959": 289468750.0, + "963": 56031250.0, + "964": 92781250.0, + "966": 972000000.0, + "969": 385625000.0, + "970": 235718750.0, + "971": 1607687500.0, + "974": 1209218750.0, + "975": 30218750.0, + "977": 385375000.0, + "978": 708406250.0, + "980": 131625000.0, + "981": 306437500.0, + "982": 61468750.0, + "986": 946343750.0, + "988": 529437500.0, + "989": 500437500.0, + "990": 213500000.0, + "996": 458937500.0, + "998": 432375000.0, + "1004": 195343750.0, + "1005": 56437500.0, + "1006": 201468750.0, + "1010": 181750000.0, + "1015": 1193281250.0, + "1016": 4129750000.0, + "1020": 1250687500.0, + "1021": 2360031250.0, + "1022": 1554781250.0, + "1023": 603062500.0, + "1026": 73656250.0, + "1029": 203875000.0, + "1030": 294968750.0, + "1031": 417031250.0, + "1035": 1163750000.0, + "1038": 477062500.0, + "1039": 82000000.0, + "1043": 506718750.0, + "1044": 61625000.0, + "1045": 60218750.0, + "1046": 137406250.0, + "1047": 461687500.0, + "1048": 2621781250.0, + "1052": 891562500.0, + "1054": 205187500.0, + "1058": 706968750.0, + "1060": 5687500.0, + "1061": 142687500.0, + "1062": 76562500.0, + "1070": 459500000.0, + "1072": 171437500.0, + "1074": 117468750.0, + "1077": 148187500.0, + "1079": 276562500.0, + "1081": 11000000.0, + "1085": 73218750.0, + "1086": 152250000.0, + "1088": 248406250.0, + "1090": 2182125000.0, + "1092": 118562500.0, + "1093": 2344031250.0, + "1094": 270031250.0, + "1096": 244906250.0, + "1098": 1124625000.0, + "1101": 1505500000.0, + "1102": 1642062500.0, + "1104": 165968750.0, + "1105": 182968750.0, + "1107": 940312500.0, + "1108": 822406250.0, + "1109": 96500000.0, + "1111": 351531250.0, + "1113": 113031250.0, + "1114": 102843750.0, + "1116": 29031250.0, + "1120": 43187500.0, + "1121": 973562500.0, + "1125": 618531250.0, + "1126": 35625000.0, + "1128": 550250000.0, + "1139": 58875000.0, + "10671": 84750000.0, + "10672": 2714500000.0, + "10674": 2952625000.0, + "10675": 2677281250.0, + "10677": 2996062500.0, + "10678": 2521125000.0, + "10680": 2616281250.0, + "10681": 2582531250.0, + "10683": 2574312500.0, + "10684": 1498906250.0, + "10686": 1318812500.0, + "10687": 2655625000.0, + "10689": 3061312500.0, + "10690": 707781250.0, + "10692": 626281250.0, + "10703": 4276375000.0, + "10704": 680937500.0, + "10705": 58375000.0, + "10707": 65468750.0, + "10708": 622187500.0, + "10710": 719062500.0, + "10711": 1444031250.0, + "10713": 1297312500.0, + "10720": 3198531250.0, + "10722": 3516781250.0, + "10723": 1909656250.0, + "10725": 1430437500.0, + "10726": 627687500.0, + "10728": 521625000.0, + "10729": 991031250.0, + "10731": 1056906250.0, + "10732": 1897375000.0, + "10734": 1564187500.0, + "10735": 755625000.0, + "10737": 768125000.0, + "182305693": 165718750.0, + "182305701": 187812500.0, + "182305705": 258281250.0, + "182305709": 294218750.0, + "182305713": 24562500.0, + "312782550": 233250000.0, + "312782558": 153906250.0, + "312782562": 354531250.0, + "312782566": 221968750.0, + "312782570": 41187500.0, + "312782578": 73218750.0, + "312782586": 57000000.0, + "312782590": 147531250.0, + "312782594": 78406250.0, + "312782598": 15968750.0, + "312782604": 168281250.0, + "312782612": 145843750.0, + "312782616": 244500000.0, + "312782620": 151562500.0, + "312782624": 29000000.0, + "312782632": 248218750.0, + "312782640": 59750000.0, + "312782644": 382125000.0, + "312782648": 179656250.0, + "312782652": 32187500.0, + "484682508": 316281250.0, + "484682512": 1929750000.0, + "484682516": 3094156250.0, + "484682520": 213312500.0, + "484682524": 114812500.0, + "484682528": 34875000.0, + "496345664": 207312500.0, + "496345668": 419281250.0, + "496345672": 95750000.0, + "526157192": 368343750.0, + "526157196": 112125000.0, + "526322264": 875000.0, + "527696977": 3750000.0, + "549009203": 62156250.0, + "549009211": 15906250.0, + "549009215": 318437500.0, + "549009219": 13625000.0, + "549009223": 68906250.0, + "549009227": 42312500.0, + "560581551": 237156250.0, + "560581559": 90468750.0, + "560581563": 173906250.0, + "563807435": 277437500.0, + "563807439": 22500000.0, + "576073699": 50031250.0, + "576073704": 214718750.0, + "589508447": 418875000.0, + "589508451": 101187500.0, + "589508455": 84906250.0, + "599626923": 14843750.0, + "599626927": 47812500.0, + "606826647": 213281250.0, + "606826651": 135968750.0, + "606826655": 38062500.0, + "606826659": 77593750.0, + "606826663": 15937500.0, + "607344830": 21781250.0, + "607344834": 80812500.0, + "607344838": 69250000.0, + "607344842": 26562500.0, + "607344846": 61593750.0, + "607344850": 31812500.0, + "607344854": 18406250.0, + "607344858": 36562500.0, + "607344862": 18531250.0, + "614454277": 42093750.0, + "1005899076": 1312500.0, + "1024543562": 3560406250.0, + "1035739465": 8390625.0, + "1037481934": 441453125.0, + "1038004598": 27000000.0, + "1040222935": 5118562500.0, + "1043765183": 404531250.0, + "1054221329": 20328125.0, + "1060511842": 24531250.0, + "1082141991": 19812500.0, + "1093211310": 2687500.0, + "1094902124": 10031250.0, + "1096265790": 2687500.0, + "1099096371": 2812500.0, + "1104248884": 27093750.0, + "1105483506": 14828125.0, + "1117257996": 20687500.0, + "1126601402": 21656250.0, + "1140764290": 3607343750.0, + "1149652689": 34656250.0, + "1156116970": 5984375.0, + "1160721590": 276625000.0, + "1165809076": 308265625.0, + "1166850207": 71500000.0, + "1170723867": 29812500.0, + "1171543751": 1544437500.0, + "1181035221": 20843750.0, + "1203939479": 1189593750.0, + "1209357605": 1398750000.0, + "1210837267": 11781250.0, + "1246610280": 14062500.0, + "1258169895": 1312500.0, + "1275601165": 11093750.0, + "1307372013": 48046875.0, + "1310126712": 10031250.0, + "1311366798": 13062500.0, + "1315119484": 14218750.0, + "1315950883": 14781250.0, + "1326886999": 18343750.0, + "1337935688": 22468750.0, + "1344105173": 9281250.0, + "1375046773": 1292812500.0, + "1393608993": 10609375.0, + "1406402073": 9125000.0, + "1420546517": 28656250.0, + "1427961626": 16500000.0, + "1428498274": 564406250.0, + "1430875964": 107968750.0, + "1431942459": 152906250.0, + "1433026796": 25562500.0, + "1454256797": 234203125.0, + "1456398198": 21718750.0, + "1456682260": 4671875.0, + "1463157755": 67328125.0, + "1463730273": 380062500.0, + "1464978040": 25875000.0, + "1466095084": 768406250.0, + "1475527815": 17468750.0, + "1477785742": 26937500.0, + "1496257237": 24281250.0, + "1501393228": 33218750.0, + "1507784331": 2437500.0, + "1510133109": 1656250.0, + "1516851569": 16500000.0, + "1518704958": 10703125.0, + "1536696383": 33250000.0, + "1547817274": 26406250.0, + "1549069626": 27218750.0, + "1557651847": 9173843750.0, + "1558550786": 15406250.0, + "1580329576": 923812500.0, + "1582478571": 2406250.0, + "1588504257": 29843750.0, + "1593308392": 991687500.0, + "1598869030": 98109375.0, + "1612593605": 16312500.0, + "1624848466": 408484375.0, + "1639524986": 16468750.0, + "1641347046": 25000000.0, + "1644849336": 22656250.0, + "1645194511": 74218750.0, + "1666373161": 15531250.0, + "1667278413": 28000000.0, + "1668688439": 11540406250.0, + "1672280517": 234781250.0, + "1677451927": 13656250.0, + "1690235425": 710437500.0, + "1691306271": 17375000.0, + "1695203883": 148312500.0, + "1706307657": 26093750.0, + "1714311201": 22687500.0, + "1714819828": 1468750.0, + "1743009264": 23281250.0, + "1744978404": 2134343750.0, + "1758306548": 2432375000.0, + "1781030954": 22031250.0, + "1792026161": 2087437500.0, + "1792980078": 24312500.0, + "1798728430": 22250000.0, + "1805611561": 6515625.0, + "1811993763": 3555625000.0, + "1842735199": 2755218750.0, + "1843338795": 23937500.0, + "1848522986": 2531250.0, + "1860102496": 718437500.0, + "1869881498": 1937500.0, + "1876807310": 27296875.0, + "1877482733": 10500000.0, + "1881029055": 9718750.0, + "1890964946": 632578125.0, + "1897015494": 17531250.0, + "1901850664": 2093750.0, + "1913328693": 2156250.0, + "1926976537": 26984375.0, + "1928393658": 2312500.0, + "1942628671": 124656250.0, + "1945434117": 25281250.0, + "1953921139": 504187500.0, + "1970686062": 12187500.0, + "1972094100": 30812500.0, + "1992072790": 1201937500.0, + "1994494334": 9937500.0, + "2004775342": 23125000.0, + "2006047173": 7250000.0, + "2012716980": 205609375.0, + "2023633893": 29500000.0, + "2047390011": 33781250.0, + "2063775638": 1072562500.0, + "2064317417": 21125000.0, + "2078623765": 94593750.0, + "2091848107": 16671875.0, + "2097438884": 23781250.0, + "2102386393": 538000000.0, + "2108774369": 36593750.0, + "2114704803": 94625000.0, + "2123772309": 27562500.0, + "2127067043": 717937500.0, + "2151167540": 16312500.0, + "2152572352": 19281250.0, + "2153924985": 52687500.0, + "2157528000": 26406250.0, + "2165415682": 1124062500.0, + "2167613582": 262093750.0, + "2168807353": 16062500.0, + "2176156825": 694750000.0, + "2183090366": 10312500.0, + "2185403483": 12562500.0, + "2186168811": 214984375.0, + "2189208794": 374234375.0, + "2194674250": 2375000.0, + "2196657368": 11468750.0, + "2197459620": 1843750.0, + "2208057363": 215796875.0, + "2218254883": 126343750.0, + "2218808594": 6375000.0, + "2224619882": 171609375.0, + "2225157452": 13828125.0, + "2236457933": 15562500.0, + "2254557934": 406468750.0, + "2260827822": 266718750.0, + "2292194787": 131656250.0, + "2302833148": 26187500.0, + "2316153360": 839187500.0, + "2336071181": 704437500.0, + "2341450864": 10984375.0, + "2358040414": 416906250.0, + "2360313730": 26812500.0, + "2361776473": 343968750.0, + "2369238059": 21125000.0, + "2371017187": 17312500.0, + "2374653061": 25156250.0, + "2384899589": 21281250.0, + "2387503636": 22437500.0, + "2406188897": 11406250.0, + "2413172686": 358843750.0, + "2414821463": 561843750.0, + "2416897036": 370062500.0, + "2427348802": 25000000.0, + "2434751741": 48625000.0, + "2436888515": 12531250.0, + "2439179873": 211656250.0, + "2445320853": 2015125000.0, + "2449182232": 1342343750.0, + "2478012832": 23656250.0, + "2500193001": 1543312500.0, + "2511156654": 2362062500.0, + "2525505631": 12812500.0, + "2536061413": 137937500.0, + "2542216029": 1439281250.0, + "2544082156": 104937500.0, + "2551618170": 19265625.0, + "2557684018": 603843750.0, + "2558258359": 15421875.0, + "2561915647": 4845406250.0, + "2563782304": 25875000.0, + "2567067139": 12531250.0, + "2590882612": 6718750.0, + "2593521448": 12250000.0, + "2598818153": 368718750.0, + "2613674898": 13625000.0, + "2614168502": 917687500.0, + "2629778705": 12562500.0, + "2641148319": 2250000.0, + "2644357350": 1125000.0, + "2646114338": 91750000.0, + "2658097375": 23968750.0, + "2658756176": 24000000.0, + "2659044087": 26281250.0, + "2667261098": 23343750.0, + "2668242174": 229578125.0, + "2683995601": 687718750.0, + "2688781451": 20218750.0, + "2692485271": 453906250.0, + "2692580507": 15406250.0, + "2700046659": 2281250.0, + "2710463424": 1468750.0, + "2718688460": 84468750.0, + "2723065947": 550500000.0, + "2739084189": 2218750.0, + "2743616995": 28843750.0, + "2768475141": 22937500.0, + "2782023316": 117328125.0, + "2790124484": 280625000.0, + "2790136061": 12437500.0, + "2791423253": 1336468750.0, + "2795738785": 11718750.0, + "2798287336": 29562500.0, + "2810081477": 18843750.0, + "2812530569": 26718750.0, + "2815501138": 9203125.0, + "2835342929": 11000000.0, + "2835688982": 196281250.0, + "2842134861": 23343750.0, + "2845253318": 132046875.0, + "2854337283": 484750000.0, + "2862362532": 419125000.0, + "2866280389": 3156250.0, + "2868822451": 29531250.0, + "2869757686": 191593750.0, + "2892558637": 431984375.0, + "2897348183": 142609375.0, + "2915675742": 22437500.0, + "2923485783": 331812500.0, + "2927119608": 161921875.0, + "2930307508": 30437500.0, + "2933568634": 10187500.0, + "2936441103": 12343750.0, + "2951747260": 408015625.0, + "2952544119": 933937500.0, + "2956165934": 4293875000.0, + "2964598138": 26718750.0, + "2978179471": 17843750.0, + "2980820846": 12625000.0, + "2985091592": 77906250.0, + "2987319910": 31468750.0, + "3009745967": 1378562500.0, + "3026302666": 33000000.0, + "3034756217": 2684062500.0, + "3043750963": 35375000.0, + "3048883337": 2593750.0, + "3049552521": 949593750.0, + "3080022137": 17156250.0, + "3085221154": 22718750.0, + "3088876178": 617687500.0, + "3092369320": 821187500.0, + "3092405473": 10937500.0, + "3093795446": 29187500.0, + "3095364455": 193718750.0, + "3101970431": 6731906250.0, + "3116469840": 6484375.0, + "3118601025": 24375000.0, + "3132124329": 102421875.0, + "3137025327": 15375000.0, + "3139552203": 16687500.0, + "3140724988": 719343750.0, + "3167765177": 9593750.0, + "3173729836": 7593750.0, + "3188360247": 25187500.0, + "3188993656": 26312500.0, + "3192952047": 237421875.0, + "3215542274": 1218750.0, + "3219108088": 35531250.0, + "3228324150": 855593750.0, + "3250982806": 304937500.0, + "3263488087": 419031250.0, + "3277826222": 19875000.0, + "3278290071": 24000000.0, + "3283016083": 79000000.0, + "3289019263": 18656250.0, + "3291535006": 2625000.0, + "3299719941": 24031250.0, + "3301183793": 15421875.0, + "3302405705": 34468750.0, + "3309772165": 32468750.0, + "3312222592": 6171875.0, + "3314370483": 765187500.0, + "3320050311": 30406250.0, + "3324056088": 6437500.0, + "3325173834": 11375000.0, + "3331415743": 1968750.0, + "3338653017": 16468750.0, + "3376791707": 418078125.0, + "3379356047": 10421875.0, + "3379749055": 1656250.0, + "3389528505": 724125000.0, + "3409505442": 942593750.0, + "3412423041": 1426781250.0, + "3413451609": 8046875.0, + "3416776496": 2750000.0, + "3449035628": 256562500.0, + "3453175542": 10671875.0, + "3467149620": 131156250.0, + "3486673188": 18781250.0, + "3495145594": 26687500.0, + "3516629919": 352343750.0, + "3521164295": 13328125.0, + "3527105324": 2593750.0, + "3537828992": 6906250.0, + "3545403109": 28562500.0, + "3556494715": 20281250.0, + "3561503481": 19593750.0, + "3562104832": 155093750.0, + "3562601313": 8296875.0, + "3565367498": 16093750.0, + "3571205574": 35843750.0, + "3575805529": 14281250.0, + "3577346235": 10093750.0, + "3581771805": 21375000.0, + "3582239403": 378828125.0, + "3591549811": 228703125.0, + "3623254419": 13859375.0, + "3628159968": 29812500.0, + "3638507875": 3093750.0, + "3652474151": 15250000.0, + "3653590473": 165281250.0, + "3654510924": 2026125000.0, + "3670777223": 1593750.0, + "3672106733": 3802656250.0, + "3673895945": 6671875.0, + "3683796018": 130250000.0, + "3685934448": 17000000.0, + "3693772975": 347421875.0, + "3710667749": 184468750.0, + "3714509274": 168562500.0, + "3718675619": 1237312500.0, + "3719447735": 11265625.0, + "3724099631": 24375000.0, + "3748961581": 19718750.0, + "3761146439": 13062500.0, + "3774104740": 509500000.0, + "3781663036": 111296875.0, + "3796365620": 20687500.0, + "3803368771": 177515625.0, + "3807479791": 19437500.0, + "3808183566": 39312500.0, + "3808433473": 114734375.0, + "3835740469": 20593750.0, + "3841505448": 17000000.0, + "3853526235": 19843750.0, + "3859818063": 31750000.0, + "3859877696": 29234375.0, + "3872485424": 3062500.0, + "3877358805": 33000000.0, + "3890169311": 10593750.0, + "3893800328": 270718750.0, + "3894563657": 1300875000.0, + "3895794866": 25718750.0, + "3902978127": 1375000.0, + "3920533696": 254171875.0, + "3926962776": 12000000.0, + "3927629261": 96406250.0, + "3944974149": 7968750.0, + "3946289800": 20406250.0, + "3956191525": 627218750.0, + "3962734174": 203281250.0, + "3964792502": 168203125.0, + "3966633210": 33125000.0, + "3970522306": 13140625.0, + "3985188708": 15718750.0, + "3986345576": 19062500.0, + "3990698322": 8890625.0, +} diff --git a/app/cli/curate.py b/app/cli/curate.py index 0733a57b..e01970ff 100644 --- a/app/cli/curate.py +++ b/app/cli/curate.py @@ -1,457 +1,8 @@ import datetime +from app.cli.brain_region_data import BRAIN_REGION_REPLACEMENTS from app.logger import L -BRAIN_REGION_REPLACEMENTS = { - "Accessory supraoptic group: Other": "2218808594", - "Agranular insular area, dorsal part, layer 2": "3250982806", - "Agranular insular area, dorsal part, layer 3": "3088876178", - "Agranular insular area, posterior part, layer 2": "1672280517", - "Agranular insular area, posterior part, layer 3": "2414821463", - "Agranular insular area, ventral part, layer 2": "2224619882", - "Agranular insular area, ventral part, layer 3": "3376791707", - "Anterior area, layer 2": "1695203883", - "Anterior area, layer 3": "1160721590", - "Anterior cingulate area, dorsal part, layer 2": "3095364455", - "Anterior cingulate area, dorsal part, layer 3": "2862362532", - "Anterior cingulate area, ventral part, layer 2": "2949903222", - "Anterior cingulate area, ventral part, layer 3": "3582239403", - "Anterior hypothalamic nucleus: Other": "1690235425", - "Anterior olfactory nucleus: Other": "2561915647", - "Anterolateral visual area, layer 2": "1463157755", - "Anterolateral visual area, layer 3": "2845253318", - "Anteromedial visual area, layer 2": "1645194511", - "Anteromedial visual area, layer 3": "2292194787", - "Bed nuclei of the stria terminalis: Other": "2791423253", - "Cerebellum: Other": "3092369320", - "Cortical amygdalar area, anterior part: Other": "1466095084", - "Cortical amygdalar area, posterior part, lateral zone: Other": "1992072790", - "Cortical amygdalar area, posterior part, medial zone: Other": "1375046773", - "Cortical subplate: Other": "2416897036", - "Dorsal auditory area, layer 2": "3781663036", - "Dorsal auditory area, layer 3": "2186168811", - "Dorsal peduncular area: Other": "1953921139", - "Dorsomedial nucleus of the hypothalamus: Other": "1463730273", - "Ectorhinal area, layer 2": "2218254883", - "Ectorhinal area, layer 3": "3516629919", - "Frontal pole, layer 2": "2646114338", - "Frontal pole, layer 3": "2536061413", - "Gustatory areas, layer 2": "3683796018", - "Gustatory areas, layer 3": "3893800328", - "Hippocampal formation: Other": "3263488087", - "Hypothalamus: Other": "1842735199", - "Infralimbic area, layer 3": "2078623765", - "Interpeduncular nucleus: Other": "2183090366", - "Lateral visual area, layer 2": "3927629261", - "Lateral visual area, layer 3": "3962734174", - "Laterointermediate area, layer 2": "3808183566", - "Laterointermediate area, layer 3": "2985091592", - "Main olfactory bulb: Other": "2358040414", - "Medial amygdalar nucleus: Other": "2445320853", - "Medial preoptic nucleus: Other": "2254557934", - "Mediodorsal nucleus of thalamus: Other": "3009745967", - "Medulla: Other": "1557651847", - "Midbrain reticular nucleus: Other": "1040222935", - "Midbrain: Other": "3101970431", - "Nucleus of the lateral lemniscus: Other": "2127067043", - "Nucleus of the solitary tract: Other": "2316153360", - "Olfactory areas: Other": "1024543562", - "Olfactory tubercle: Other": "3672106733", - "Orbital area, lateral part, layer 2": "3803368771", - "Orbital area, lateral part, layer 3": "1037481934", - "Orbital area, medial part, layer 3": "2012716980", - "Orbital area, ventrolateral part, layer 2": "3653590473", - "Orbital area, ventrolateral part, layer 3": "2413172686", - "Pallidum: Other": "2165415682", - "Parabrachial nucleus: Other": "3409505442", - "Parapyramidal nucleus: Other": "2114704803", - "Parasubiculum: Other": "2952544119", - "Paraventricular hypothalamic nucleus, descending division: Other": "3467149620", - "Paraventricular hypothalamic nucleus: Other": "2869757686", - "Periaqueductal gray: Other": "2956165934", - "Perirhinal area, layer 2": "3132124329", - "Perirhinal area, layer 3": "2668242174", - "Piriform area: Other": "1668688439", - "Piriform-amygdalar area: Other": "1203939479", - "Pons: Other": "1140764290", - "Posterior auditory area, layer 2": "1307372013", - "Posterior auditory area, layer 3": "1598869030", - "Posterolateral visual area, layer 2": "2153924985", - "Posterolateral visual area, layer 3": "1431942459", - "Postpiriform transition area: Other": "1209357605", - "Postrhinal area, layer 2": "2782023316", - "Postrhinal area, layer 3": "3920533696", - "Postsubiculum: Other": "2063775638", - "Prelimbic area, layer 3": "2790124484", - "Presubiculum: Other": "1580329576", - "Primary auditory area, layer 2": "2927119608", - "Primary auditory area, layer 3": "1165809076", - "Primary motor area, layer 2": "3718675619", - "Primary motor area, layer 3": "1758306548", - "Primary somatosensory area, barrel field, A1 barrel layer 1": "1344105173", - "Primary somatosensory area, barrel field, A1 barrel layer 2": "3116469840", - "Primary somatosensory area, barrel field, A1 barrel layer 2/3": "2615618683", - "Primary somatosensory area, barrel field, A1 barrel layer 3": "3379356047", - "Primary somatosensory area, barrel field, A1 barrel layer 4": "1315119484", - "Primary somatosensory area, barrel field, A1 barrel layer 5": "2436888515", - "Primary somatosensory area, barrel field, A1 barrel layer 6a": "3577346235", - "Primary somatosensory area, barrel field, A1 barrel layer 6b": "3902978127", - "Primary somatosensory area, barrel field, A1 barrel": "1370229894", - "Primary somatosensory area, barrel field, A2 barrel layer 1": "1310126712", - "Primary somatosensory area, barrel field, A2 barrel layer 2": "3324056088", - "Primary somatosensory area, barrel field, A2 barrel layer 2/3": "1446874462", - "Primary somatosensory area, barrel field, A2 barrel layer 3": "2593521448", - "Primary somatosensory area, barrel field, A2 barrel layer 4": "3685934448", - "Primary somatosensory area, barrel field, A2 barrel layer 5": "3575805529", - "Primary somatosensory area, barrel field, A2 barrel layer 6a": "1210837267", - "Primary somatosensory area, barrel field, A2 barrel layer 6b": "1258169895", - "Primary somatosensory area, barrel field, A2 barrel": "3651721123", - "Primary somatosensory area, barrel field, A3 barrel layer 1": "1994494334", - "Primary somatosensory area, barrel field, A3 barrel layer 2": "2590882612", - "Primary somatosensory area, barrel field, A3 barrel layer 2/3": "1447791371", - "Primary somatosensory area, barrel field, A3 barrel layer 3": "3761146439", - "Primary somatosensory area, barrel field, A3 barrel layer 4": "3139552203", - "Primary somatosensory area, barrel field, A3 barrel layer 5": "2692580507", - "Primary somatosensory area, barrel field, A3 barrel layer 6a": "1677451927", - "Primary somatosensory area, barrel field, A3 barrel layer 6b": "3379749055", - "Primary somatosensory area, barrel field, A3 barrel": "2732283703", - "Primary somatosensory area, barrel field, Alpha barrel layer 1": "2835342929", - "Primary somatosensory area, barrel field, Alpha barrel layer 2": "3173729836", - "Primary somatosensory area, barrel field, Alpha barrel layer 2/3": "1897248316", - "Primary somatosensory area, barrel field, Alpha barrel layer 3": "3926962776", - "Primary somatosensory area, barrel field, Alpha barrel layer 4": "2168807353", - "Primary somatosensory area, barrel field, Alpha barrel layer 5": "3137025327", - "Primary somatosensory area, barrel field, Alpha barrel layer 6a": "2406188897", - "Primary somatosensory area, barrel field, Alpha barrel layer 6b": "3670777223", - "Primary somatosensory area, barrel field, Alpha barrel": "3896406483", - "Primary somatosensory area, barrel field, B1 barrel layer 1": "1516851569", - "Primary somatosensory area, barrel field, B1 barrel layer 2": "2196657368", - "Primary somatosensory area, barrel field, B1 barrel layer 2/3": "3913053667", - "Primary somatosensory area, barrel field, B1 barrel layer 3": "3986345576", - "Primary somatosensory area, barrel field, B1 barrel layer 4": "3495145594", - "Primary somatosensory area, barrel field, B1 barrel layer 5": "1644849336", - "Primary somatosensory area, barrel field, B1 barrel layer 6a": "3289019263", - "Primary somatosensory area, barrel field, B1 barrel layer 6b": "2194674250", - "Primary somatosensory area, barrel field, B1 barrel": "2525641171", - "Primary somatosensory area, barrel field, B2 barrel layer 1": "3853526235", - "Primary somatosensory area, barrel field, B2 barrel layer 2": "1311366798", - "Primary somatosensory area, barrel field, B2 barrel layer 2/3": "3456985752", - "Primary somatosensory area, barrel field, B2 barrel layer 3": "1126601402", - "Primary somatosensory area, barrel field, B2 barrel layer 4": "3966633210", - "Primary somatosensory area, barrel field, B2 barrel layer 5": "2812530569", - "Primary somatosensory area, barrel field, B2 barrel layer 6a": "1641347046", - "Primary somatosensory area, barrel field, B2 barrel layer 6b": "3416776496", - "Primary somatosensory area, barrel field, B2 barrel": "1673450198", - "Primary somatosensory area, barrel field, B3 barrel layer 1": "3565367498", - "Primary somatosensory area, barrel field, B3 barrel layer 2": "1881029055", - "Primary somatosensory area, barrel field, B3 barrel layer 2/3": "2657138906", - "Primary somatosensory area, barrel field, B3 barrel layer 3": "3080022137", - "Primary somatosensory area, barrel field, B3 barrel layer 4": "1547817274", - "Primary somatosensory area, barrel field, B3 barrel layer 5": "2369238059", - "Primary somatosensory area, barrel field, B3 barrel layer 6a": "2478012832", - "Primary somatosensory area, barrel field, B3 barrel layer 6b": "2739084189", - "Primary somatosensory area, barrel field, B3 barrel": "1626685236", - "Primary somatosensory area, barrel field, B4 barrel layer 1": "2006047173", - "Primary somatosensory area, barrel field, B4 barrel layer 2": "1456682260", - "Primary somatosensory area, barrel field, B4 barrel layer 2/3": "2180527067", - "Primary somatosensory area, barrel field, B4 barrel layer 3": "3562601313", - "Primary somatosensory area, barrel field, B4 barrel layer 4": "1970686062", - "Primary somatosensory area, barrel field, B4 barrel layer 5": "3890169311", - "Primary somatosensory area, barrel field, B4 barrel layer 6a": "2936441103", - "Primary somatosensory area, barrel field, B4 barrel layer 6b": "3215542274", - "Primary somatosensory area, barrel field, B4 barrel": "3347675430", - "Primary somatosensory area, barrel field, Beta barrel layer 1": "3486673188", - "Primary somatosensory area, barrel field, Beta barrel layer 2": "3970522306", - "Primary somatosensory area, barrel field, Beta barrel layer 2/3": "3783583602", - "Primary somatosensory area, barrel field, Beta barrel layer 3": "1054221329", - "Primary somatosensory area, barrel field, Beta barrel layer 4": "3895794866", - "Primary somatosensory area, barrel field, Beta barrel layer 5": "1496257237", - "Primary somatosensory area, barrel field, Beta barrel layer 6a": "2152572352", - "Primary somatosensory area, barrel field, Beta barrel layer 6b": "3048883337", - "Primary somatosensory area, barrel field, Beta barrel": "1521759875", - "Primary somatosensory area, barrel field, C1 barrel layer 1": "1337935688", - "Primary somatosensory area, barrel field, C1 barrel layer 2": "1558550786", - "Primary somatosensory area, barrel field, C1 barrel layer 2/3": "1667660763", - "Primary somatosensory area, barrel field, C1 barrel layer 3": "2563782304", - "Primary somatosensory area, barrel field, C1 barrel layer 4": "3219108088", - "Primary somatosensory area, barrel field, C1 barrel layer 5": "1420546517", - "Primary somatosensory area, barrel field, C1 barrel layer 6a": "1945434117", - "Primary somatosensory area, barrel field, C1 barrel layer 6b": "2866280389", - "Primary somatosensory area, barrel field, C1 barrel": "1013068637", - "Primary somatosensory area, barrel field, C2 barrel layer 1": "1082141991", - "Primary somatosensory area, barrel field, C2 barrel layer 2": "2525505631", - "Primary somatosensory area, barrel field, C2 barrel layer 2/3": "2157537321", - "Primary somatosensory area, barrel field, C2 barrel layer 3": "1714311201", - "Primary somatosensory area, barrel field, C2 barrel layer 4": "2930307508", - "Primary somatosensory area, barrel field, C2 barrel layer 5": "3188993656", - "Primary somatosensory area, barrel field, C2 barrel layer 6a": "1843338795", - "Primary somatosensory area, barrel field, C2 barrel layer 6b": "3291535006", - "Primary somatosensory area, barrel field, C2 barrel": "2072239244", - "Primary somatosensory area, barrel field, C3 barrel layer 1": "3835740469", - "Primary somatosensory area, barrel field, C3 barrel layer 2": "2629778705", - "Primary somatosensory area, barrel field, C3 barrel layer 2/3": "1125438717", - "Primary somatosensory area, barrel field, C3 barrel layer 3": "3581771805", - "Primary somatosensory area, barrel field, C3 barrel layer 4": "3877358805", - "Primary somatosensory area, barrel field, C3 barrel layer 5": "1667278413", - "Primary somatosensory area, barrel field, C3 barrel layer 6a": "2743616995", - "Primary somatosensory area, barrel field, C3 barrel layer 6b": "1093211310", - "Primary somatosensory area, barrel field, C3 barrel": "2937437636", - "Primary somatosensory area, barrel field, C4 barrel layer 1": "2151167540", - "Primary somatosensory area, barrel field, C4 barrel layer 2": "3167765177", - "Primary somatosensory area, barrel field, C4 barrel layer 2/3": "2460702429", - "Primary somatosensory area, barrel field, C4 barrel layer 3": "1639524986", - "Primary somatosensory area, barrel field, C4 barrel layer 4": "1549069626", - "Primary somatosensory area, barrel field, C4 barrel layer 5": "3085221154", - "Primary somatosensory area, barrel field, C4 barrel layer 6a": "2659044087", - "Primary somatosensory area, barrel field, C4 barrel layer 6b": "2700046659", - "Primary somatosensory area, barrel field, C4 barrel": "3404738524", - "Primary somatosensory area, barrel field, C5 barrel layer 1": "1246610280", - "Primary somatosensory area, barrel field, C5 barrel layer 2": "1035739465", - "Primary somatosensory area, barrel field, C5 barrel layer 2/3": "3880590912", - "Primary somatosensory area, barrel field, C5 barrel layer 3": "1105483506", - "Primary somatosensory area, barrel field, C5 barrel layer 4": "1792980078", - "Primary somatosensory area, barrel field, C5 barrel layer 5": "3556494715", - "Primary somatosensory area, barrel field, C5 barrel layer 6a": "1706307657", - "Primary somatosensory area, barrel field, C5 barrel layer 6b": "1869881498", - "Primary somatosensory area, barrel field, C5 barrel": "2062992388", - "Primary somatosensory area, barrel field, C6 barrel layer 1": "2933568634", - "Primary somatosensory area, barrel field, C6 barrel layer 2": "1805611561", - "Primary somatosensory area, barrel field, C6 barrel layer 2/3": "2013207018", - "Primary somatosensory area, barrel field, C6 barrel layer 3": "3719447735", - "Primary somatosensory area, barrel field, C6 barrel layer 4": "2371017187", - "Primary somatosensory area, barrel field, C6 barrel layer 5": "3985188708", - "Primary somatosensory area, barrel field, C6 barrel layer 6a": "3796365620", - "Primary somatosensory area, barrel field, C6 barrel layer 6b": "1714819828", - "Primary somatosensory area, barrel field, C6 barrel": "1261138116", - "Primary somatosensory area, barrel field, D1 barrel layer 1": "3724099631", - "Primary somatosensory area, barrel field, D1 barrel layer 2": "2558258359", - "Primary somatosensory area, barrel field, D1 barrel layer 2/3": "2833279579", - "Primary somatosensory area, barrel field, D1 barrel layer 3": "3859877696", - "Primary somatosensory area, barrel field, D1 barrel layer 4": "2108774369", - "Primary somatosensory area, barrel field, D1 barrel layer 5": "3320050311", - "Primary somatosensory area, barrel field, D1 barrel layer 6a": "3628159968", - "Primary somatosensory area, barrel field, D1 barrel layer 6b": "3638507875", - "Primary somatosensory area, barrel field, D1 barrel": "1171261412", - "Primary somatosensory area, barrel field, D2 barrel layer 1": "1743009264", - "Primary somatosensory area, barrel field, D2 barrel layer 2": "3623254419", - "Primary somatosensory area, barrel field, D2 barrel layer 2/3": "1884779226", - "Primary somatosensory area, barrel field, D2 barrel layer 3": "1926976537", - "Primary somatosensory area, barrel field, D2 barrel layer 4": "2047390011", - "Primary somatosensory area, barrel field, D2 barrel layer 5": "2798287336", - "Primary somatosensory area, barrel field, D2 barrel layer 6a": "2987319910", - "Primary somatosensory area, barrel field, D2 barrel layer 6b": "3872485424", - "Primary somatosensory area, barrel field, D2 barrel": "3329043535", - "Primary somatosensory area, barrel field, D3 barrel layer 1": "1781030954", - "Primary somatosensory area, barrel field, D3 barrel layer 2": "3521164295", - "Primary somatosensory area, barrel field, D3 barrel layer 2/3": "2841658580", - "Primary somatosensory area, barrel field, D3 barrel layer 3": "1876807310", - "Primary somatosensory area, barrel field, D3 barrel layer 4": "1501393228", - "Primary somatosensory area, barrel field, D3 barrel layer 5": "1972094100", - "Primary somatosensory area, barrel field, D3 barrel layer 6a": "3302405705", - "Primary somatosensory area, barrel field, D3 barrel layer 6b": "1099096371", - "Primary somatosensory area, barrel field, D3 barrel": "2036081150", - "Primary somatosensory area, barrel field, D4 barrel layer 1": "1117257996", - "Primary somatosensory area, barrel field, D4 barrel layer 2": "2567067139", - "Primary somatosensory area, barrel field, D4 barrel layer 2/3": "1453537399", - "Primary somatosensory area, barrel field, D4 barrel layer 3": "2427348802", - "Primary somatosensory area, barrel field, D4 barrel layer 4": "3859818063", - "Primary somatosensory area, barrel field, D4 barrel layer 5": "1588504257", - "Primary somatosensory area, barrel field, D4 barrel layer 6a": "3571205574", - "Primary somatosensory area, barrel field, D4 barrel layer 6b": "1096265790", - "Primary somatosensory area, barrel field, D4 barrel": "3202423327", - "Primary somatosensory area, barrel field, D5 barrel layer 1": "1326886999", - "Primary somatosensory area, barrel field, D5 barrel layer 2": "2341450864", - "Primary somatosensory area, barrel field, D5 barrel layer 2/3": "1787178465", - "Primary somatosensory area, barrel field, D5 barrel layer 3": "2551618170", - "Primary somatosensory area, barrel field, D5 barrel layer 4": "1170723867", - "Primary somatosensory area, barrel field, D5 barrel layer 5": "1038004598", - "Primary somatosensory area, barrel field, D5 barrel layer 6a": "1149652689", - "Primary somatosensory area, barrel field, D5 barrel layer 6b": "1582478571", - "Primary somatosensory area, barrel field, D5 barrel": "1412541198", - "Primary somatosensory area, barrel field, D6 barrel layer 1": "1315950883", - "Primary somatosensory area, barrel field, D6 barrel layer 2": "3990698322", - "Primary somatosensory area, barrel field, D6 barrel layer 2/3": "1947266943", - "Primary somatosensory area, barrel field, D6 barrel layer 3": "3301183793", - "Primary somatosensory area, barrel field, D6 barrel layer 4": "1464978040", - "Primary somatosensory area, barrel field, D6 barrel layer 5": "2387503636", - "Primary somatosensory area, barrel field, D6 barrel layer 6a": "2023633893", - "Primary somatosensory area, barrel field, D6 barrel layer 6b": "1913328693", - "Primary somatosensory area, barrel field, D6 barrel": "1588741938", - "Primary somatosensory area, barrel field, D7 barrel layer 1": "1877482733", - "Primary somatosensory area, barrel field, D7 barrel layer 2": "3673895945", - "Primary somatosensory area, barrel field, D7 barrel layer 2/3": "2358987890", - "Primary somatosensory area, barrel field, D7 barrel layer 3": "1393608993", - "Primary somatosensory area, barrel field, D7 barrel layer 4": "2978179471", - "Primary somatosensory area, barrel field, D7 barrel layer 5": "3338653017", - "Primary somatosensory area, barrel field, D7 barrel layer 6a": "2384899589", - "Primary somatosensory area, barrel field, D7 barrel layer 6b": "2710463424", - "Primary somatosensory area, barrel field, D7 barrel": "3920024588", - "Primary somatosensory area, barrel field, D8 barrel layer 1": "1406402073", - "Primary somatosensory area, barrel field, D8 barrel layer 2": "1156116970", - "Primary somatosensory area, barrel field, D8 barrel layer 2/3": "1373744894", - "Primary somatosensory area, barrel field, D8 barrel layer 3": "3453175542", - "Primary somatosensory area, barrel field, D8 barrel layer 4": "3652474151", - "Primary somatosensory area, barrel field, D8 barrel layer 5": "2236457933", - "Primary somatosensory area, barrel field, D8 barrel layer 6a": "3277826222", - "Primary somatosensory area, barrel field, D8 barrel layer 6b": "1005899076", - "Primary somatosensory area, barrel field, D8 barrel": "3055000922", - "Primary somatosensory area, barrel field, Delta barrel layer 1": "1691306271", - "Primary somatosensory area, barrel field, Delta barrel layer 2": "1275601165", - "Primary somatosensory area, barrel field, Delta barrel layer 2/3": "3434166213", - "Primary somatosensory area, barrel field, Delta barrel layer 3": "3946289800", - "Primary somatosensory area, barrel field, Delta barrel layer 4": "2004775342", - "Primary somatosensory area, barrel field, Delta barrel layer 5": "1456398198", - "Primary somatosensory area, barrel field, Delta barrel layer 6a": "3561503481", - "Primary somatosensory area, barrel field, Delta barrel layer 6b": "1901850664", - "Primary somatosensory area, barrel field, Delta barrel": "2438939909", - "Primary somatosensory area, barrel field, E1 barrel layer 1": "3807479791", - "Primary somatosensory area, barrel field, E1 barrel layer 2": "2980820846", - "Primary somatosensory area, barrel field, E1 barrel layer 2/3": "2803418480", - "Primary somatosensory area, barrel field, E1 barrel layer 3": "3188360247", - "Primary somatosensory area, barrel field, E1 barrel layer 4": "1477785742", - "Primary somatosensory area, barrel field, E1 barrel layer 5": "2964598138", - "Primary somatosensory area, barrel field, E1 barrel layer 6a": "3093795446", - "Primary somatosensory area, barrel field, E1 barrel layer 6b": "1507784331", - "Primary somatosensory area, barrel field, E1 barrel": "1071521092", - "Primary somatosensory area, barrel field, E2 barrel layer 1": "3748961581", - "Primary somatosensory area, barrel field, E2 barrel layer 2": "2185403483", - "Primary somatosensory area, barrel field, E2 barrel layer 2/3": "3128223634", - "Primary somatosensory area, barrel field, E2 barrel layer 3": "1433026796", - "Primary somatosensory area, barrel field, E2 barrel layer 4": "1104248884", - "Primary somatosensory area, barrel field, E2 barrel layer 5": "3545403109", - "Primary somatosensory area, barrel field, E2 barrel layer 6a": "1536696383", - "Primary somatosensory area, barrel field, E2 barrel layer 6b": "3527105324", - "Primary somatosensory area, barrel field, E2 barrel": "3054551821", - "Primary somatosensory area, barrel field, E3 barrel layer 1": "1897015494", - "Primary somatosensory area, barrel field, E3 barrel layer 2": "2795738785", - "Primary somatosensory area, barrel field, E3 barrel layer 2/3": "3331790659", - "Primary somatosensory area, barrel field, E3 barrel layer 3": "2768475141", - "Primary somatosensory area, barrel field, E3 barrel layer 4": "2658097375", - "Primary somatosensory area, barrel field, E3 barrel layer 5": "2157528000", - "Primary somatosensory area, barrel field, E3 barrel layer 6a": "3309772165", - "Primary somatosensory area, barrel field, E3 barrel layer 6b": "1928393658", - "Primary somatosensory area, barrel field, E3 barrel": "2811301625", - "Primary somatosensory area, barrel field, E4 barrel layer 1": "3841505448", - "Primary somatosensory area, barrel field, E4 barrel layer 2": "3325173834", - "Primary somatosensory area, barrel field, E4 barrel layer 2/3": "3999683881", - "Primary somatosensory area, barrel field, E4 barrel layer 3": "1798728430", - "Primary somatosensory area, barrel field, E4 barrel layer 4": "3299719941", - "Primary somatosensory area, barrel field, E4 barrel layer 5": "2360313730", - "Primary somatosensory area, barrel field, E4 barrel layer 6a": "3043750963", - "Primary somatosensory area, barrel field, E4 barrel layer 6b": "2641148319", - "Primary somatosensory area, barrel field, E4 barrel": "3840818183", - "Primary somatosensory area, barrel field, E5 barrel layer 1": "1427961626", - "Primary somatosensory area, barrel field, E5 barrel layer 2": "3092405473", - "Primary somatosensory area, barrel field, E5 barrel layer 2/3": "1643593739", - "Primary somatosensory area, barrel field, E5 barrel layer 3": "1181035221", - "Primary somatosensory area, barrel field, E5 barrel layer 4": "3118601025", - "Primary somatosensory area, barrel field, E5 barrel layer 5": "2374653061", - "Primary somatosensory area, barrel field, E5 barrel layer 6a": "3026302666", - "Primary somatosensory area, barrel field, E5 barrel layer 6b": "2197459620", - "Primary somatosensory area, barrel field, E5 barrel": "1468793762", - "Primary somatosensory area, barrel field, E6 barrel layer 1": "1666373161", - "Primary somatosensory area, barrel field, E6 barrel layer 2": "2815501138", - "Primary somatosensory area, barrel field, E6 barrel layer 2/3": "3620340000", - "Primary somatosensory area, barrel field, E6 barrel layer 3": "2091848107", - "Primary somatosensory area, barrel field, E6 barrel layer 4": "2658756176", - "Primary somatosensory area, barrel field, E6 barrel layer 5": "2097438884", - "Primary somatosensory area, barrel field, E6 barrel layer 6a": "2868822451", - "Primary somatosensory area, barrel field, E6 barrel layer 6b": "3331415743", - "Primary somatosensory area, barrel field, E6 barrel": "1965375801", - "Primary somatosensory area, barrel field, E7 barrel layer 1": "2613674898", - "Primary somatosensory area, barrel field, E7 barrel layer 2": "3413451609", - "Primary somatosensory area, barrel field, E7 barrel layer 2/3": "1951878763", - "Primary somatosensory area, barrel field, E7 barrel layer 3": "2225157452", - "Primary somatosensory area, barrel field, E7 barrel layer 4": "2842134861", - "Primary somatosensory area, barrel field, E7 barrel layer 5": "2064317417", - "Primary somatosensory area, barrel field, E7 barrel layer 6a": "2123772309", - "Primary somatosensory area, barrel field, E7 barrel layer 6b": "1510133109", - "Primary somatosensory area, barrel field, E7 barrel": "3618095278", - "Primary somatosensory area, barrel field, E8 barrel layer 1": "1094902124", - "Primary somatosensory area, barrel field, E8 barrel layer 2": "3312222592", - "Primary somatosensory area, barrel field, E8 barrel layer 2/3": "3134535128", - "Primary somatosensory area, barrel field, E8 barrel layer 3": "1518704958", - "Primary somatosensory area, barrel field, E8 barrel layer 4": "1475527815", - "Primary somatosensory area, barrel field, E8 barrel layer 5": "1612593605", - "Primary somatosensory area, barrel field, E8 barrel layer 6a": "2915675742", - "Primary somatosensory area, barrel field, E8 barrel layer 6b": "2644357350", - "Primary somatosensory area, barrel field, E8 barrel": "1624778115", - "Primary somatosensory area, barrel field, Gamma barrel layer 1": "2810081477", - "Primary somatosensory area, barrel field, Gamma barrel layer 2": "2790136061", - "Primary somatosensory area, barrel field, Gamma barrel layer 2/3": "3513655281", - "Primary somatosensory area, barrel field, Gamma barrel layer 3": "2667261098", - "Primary somatosensory area, barrel field, Gamma barrel layer 4": "2302833148", - "Primary somatosensory area, barrel field, Gamma barrel layer 5": "3278290071", - "Primary somatosensory area, barrel field, Gamma barrel layer 6a": "2688781451", - "Primary somatosensory area, barrel field, Gamma barrel layer 6b": "1848522986", - "Primary somatosensory area, barrel field, Gamma barrel": "1171320182", - "Primary somatosensory area, barrel field, layer 2": "2835688982", - "Primary somatosensory area, barrel field, layer 3": "2598818153", - "Primary somatosensory area, lower limb, layer 2": "1454256797", - "Primary somatosensory area, lower limb, layer 3": "2951747260", - "Primary somatosensory area, mouth, layer 2": "2102386393", - "Primary somatosensory area, mouth, layer 3": "3049552521", - "Primary somatosensory area, nose, layer 2": "3591549811", - "Primary somatosensory area, nose, layer 3": "1624848466", - "Primary somatosensory area, trunk, layer 2": "3562104832", - "Primary somatosensory area, trunk, layer 3": "2260827822", - "Primary somatosensory area, unassigned, layer 2": "3808433473", - "Primary somatosensory area, unassigned, layer 3": "2208057363", - "Primary somatosensory area, upper limb, layer 2": "3693772975", - "Primary somatosensory area, upper limb, layer 3": "1890964946", - "Primary visual area, layer 2": "2683995601", - "Primary visual area, layer 3": "3894563657", - "Prosubiculum: Other": "2449182232", - "Retrosplenial area, dorsal part, layer 2": "2361776473", - "Retrosplenial area, dorsal part, layer 3": "3956191525", - "Retrosplenial area, lateral agranular part, layer 2": "3192952047", - "Retrosplenial area, lateral agranular part, layer 3": "2892558637", - "Retrosplenial area, ventral part, layer 3": "3314370483", - "Rostrolateral visual area, layer 2": "1430875964", - "Rostrolateral visual area, layer 3": "3714509274", - "Secondary motor area, layer 2": 3412423041, - "Secondary motor area, layer 3": "2511156654", - "Spinal nucleus of the trigeminal, oral part: Other": "1593308392", - "Striatum: Other": "3034756217", - "Subiculum: Other": "1792026161", - "Superior central nucleus raphe: Other": "2557684018", - "Superior colliculus, motor related, intermediate gray layer: Other": "3654510924", - "Supplemental somatosensory area, layer 2": "2336071181", - "Supplemental somatosensory area, layer 3": "2542216029", - "Supramammillary nucleus: Other": "3449035628", - "Taenia tecta, dorsal part: Other": "3389528505", - "Taenia tecta, ventral part: Other": "1860102496", - "Temporal association areas, layer 2": "2439179873", - "Temporal association areas, layer 3": "2854337283", - "Thalamus: Other": "2614168502", - "Ventral auditory area, layer 2": "1942628671", - "Ventral auditory area, layer 3": "2167613582", - "Ventral part of the lateral geniculate complex: Other": "1043765183", - "Ventromedial hypothalamic nucleus: Other": "2723065947", - "Visceral area, layer 2": "3964792502", - "Visceral area, layer 3": "2189208794", - "Zona incerta: Other": "1171543751", - "corpus callosum, anterior forceps: Other": "3228324150", - "corticospinal tract: Other": "2718688460", - "facial nerve: Other": "3283016083", - "fiber tracts: Other": "2500193001", - "fourth ventricle: Other": "3774104740", - "inferior cerebellar peduncle: Other": "3140724988", - "lateral ventricle: Other": "1744978404", - "oculomotor nerve: Other": "3944974149", - "optic nerve: Other": "1166850207", - "posteromedial visual area, layer 2": "2544082156", - "posteromedial visual area, layer 3": "3710667749", - "root: Other": "1811993763", - "rubrospinal tract: Other": "1428498274", - "sensory root of the trigeminal nerve: Other": "2176156825", - "stria terminalis: Other": "2923485783", - "superior cerebelar peduncles: Other": "2692485271", - "superior cerebellar peduncle decussation: Other": "2434751741", - "supraoptic commissures: Other": "1060511842", - "trochlear nerve: Other": "3537828992", -} - def curate_role(role): if not role: @@ -530,6 +81,7 @@ def curate_trace(data): def curate_brain_region(data): + data["@id"] = str(data["@id"]) if data["@id"] == "mba:977" and data["label"] == "root": data["@id"] = "mba:997" diff --git a/app/cli/import_data.py b/app/cli/import_data.py index 9e23b317..8a05000b 100644 --- a/app/cli/import_data.py +++ b/app/cli/import_data.py @@ -1,5 +1,6 @@ import datetime import glob +import hashlib import json import os import random @@ -17,6 +18,7 @@ from tqdm import tqdm from app.cli import curate, utils +from app.cli.brain_region_data import BRAIN_ATLAS_REGION_VOLUMES from app.cli.curation import electrical_cell_recording from app.cli.types import ContentType from app.cli.utils import ( @@ -31,6 +33,7 @@ Annotation, Asset, BrainAtlas, + BrainAtlasRegion, BrainRegion, BrainRegionHierarchy, CellComposition, @@ -47,7 +50,6 @@ Measurement, MeasurementAnnotation, MEModel, - Mesh, METypeDensity, MTypeClass, MTypeClassification, @@ -55,6 +57,7 @@ Person, ReconstructionMorphology, SingleNeuronSimulation, + Species, ) from app.db.session import configure_database_session_manager from app.db.types import ( @@ -71,6 +74,9 @@ from app.cli.curation import electrical_cell_recording, cell_composition from app.cli.types import ContentType + +BRAIN_ATLAS_NAME = "BlueBrain Atlas" + REQUIRED_PATH = click.Path(exists=True, readable=True, dir_okay=False, resolve_path=True) REQUIRED_PATH_DIR = click.Path( exists=True, readable=True, file_okay=False, dir_okay=True, resolve_path=True @@ -555,47 +561,97 @@ def ingest( db.commit() -class ImportBrainRegionMeshes(Import): - name = "BrainRegionMeshes" +class ImportBrainAtlas(Import): + name = "BrainAtlas" @staticmethod def is_correct_type(data): - types = ensurelist(data["@type"]) - return "BrainParcellationMesh" in types + # for reasons unknown, the annotations are tagged as v1.2.0 + # the contents of the annotations is the same as in + # s3://openbluebrain/Model_Data/Brain_atlas/Mouse/resolution_25_um/version_1.1.0/Annotation_volume/annotation_ccfv3_l23split_barrelsplit_validated.nrrd + # but their sha256 hashes differ + return ( + utils.is_type(data, "BrainParcellationMesh") + and "atlasRelease" in data + and data["atlasRelease"].get("tag") == "v1.1.0" + ) or ( + utils.is_type(data, "BrainParcellationDataLayer") + and "atlasRelease" in data + and data["atlasRelease"].get("tag") == "v1.2.0" + ) @staticmethod def ingest(db, project_context, data_list, all_data_by_id, hierarchy_name: str): - for data in tqdm(data_list): - if "atlasRelease" not in data or data["atlasRelease"].get("tag", "") != "v1.1.0": - continue + meshes, annotations = [], [] + for d in data_list: + if utils.is_type(d, "BrainParcellationMesh"): + meshes.append(d) + else: + annotations.append(d) + + assert len(annotations) == 1 + brain_atlas = db.execute( + sa.select(BrainAtlas).filter(BrainAtlas.name == BRAIN_ATLAS_NAME) + ).scalar_one_or_none() + if brain_atlas is None: + hierarchy = db.execute( + sa.select(BrainRegionHierarchy).filter(BrainRegionHierarchy.name == hierarchy_name) + ).scalar_one() + + mouse = db.execute( + sa.select(Species).filter(Species.name == "Mus musculus") + ).scalar_one() + + brain_atlas = BrainAtlas( + name=BRAIN_ATLAS_NAME, + description="version v1.1.0 from NEXUS", + species_id=mouse.id, + hierarchy_id=hierarchy.id, + authorized_project_id=project_context.project_id, + authorized_public=True, + ) + db.add(brain_atlas) + db.commit() - legacy_id = data["@id"] - legacy_self = data["_self"] - rm = utils._find_by_legacy_id(legacy_id, Mesh, db) - if rm: - continue + utils.import_distribution( + annotations[0], brain_atlas.id, EntityType.brain_atlas, db, project_context + ) - try: - brain_region_id = utils.get_brain_region(data, hierarchy_name, db) - except RuntimeError: - L.exception("Cannot import mesh") - continue + for mesh in tqdm(meshes): + brain_region_data = mesh["brainLocation"]["brainRegion"] + brain_region_id = utils.get_brain_region_by_hier_id( + brain_region_data, hierarchy_name, db + ) - createdAt, updatedAt = utils.get_created_and_updated(data) + atlas_region = db.execute( + sa.select(BrainAtlasRegion).filter( + BrainAtlasRegion.brain_region_id == str(brain_region_id) + ) + ).scalar_one_or_none() + + if atlas_region is None: + annotation_id = curate.curate_brain_region(brain_region_data)["@id"] + volume = -1 + + leaf_region = False + if annotation_id in BRAIN_ATLAS_REGION_VOLUMES: + volume = BRAIN_ATLAS_REGION_VOLUMES[annotation_id] + leaf_region = True + + atlas_region = BrainAtlasRegion( + brain_atlas_id=brain_atlas.id, + brain_region_id=brain_region_id, + volume=volume, + leaf_region=leaf_region, + authorized_project_id=project_context.project_id, + authorized_public=True, + ) + db.add(atlas_region) + db.commit() - db_item = Mesh( - name=data["name"], - description=data["description"], - legacy_id=[legacy_id], - legacy_self=[legacy_self], - brain_region_id=brain_region_id, - creation_date=createdAt, - update_date=updatedAt, - authorized_project_id=project_context.project_id, - authorized_public=AUTHORIZED_PUBLIC, + utils.import_distribution( + mesh, atlas_region.id, EntityType.brain_atlas, db, project_context ) - db.add(db_item) - db.commit() class ImportMorphologies(Import): @@ -743,8 +799,6 @@ def ingest(db, project_context, data_list, all_data_by_id, hierarchy_name): brain_region_id = utils.get_brain_region(data, hierarchy_name, db) license_id = utils.get_license_mixin(data, db) - # species_id, strain_id = utils.get_species_mixin(data, db) - subject_id = utils.get_or_create_subject(data, project_context, db) createdAt, updatedAt = utils.get_created_and_updated(data) @@ -1036,50 +1090,6 @@ def ingest( create_annotation(annotation, db_item.id, db) -class ImportBrainAtlas(Import): - name = "Brain Atlas" - - @staticmethod - def is_correct_type(data): - return "BrainAtlasRelease" in ensurelist(data["@type"]) and data["@id"] == BRAIN_ATLAS_ID - - @staticmethod - def ingest( - db: Session, - project_context: ProjectContext, - data_list: list[dict], - all_data_by_id: dict, - hierarchy_name: str, - ): - for data in data_list: - legacy_id, legacy_self = data["@id"], data["_self"] - rm = utils._find_by_legacy_id(legacy_id, BrainAtlas, db) - if rm: - continue - - created_by_id, updated_by_id = utils.get_agent_mixin(data, db) - createdAt, updatedAt = utils.get_created_and_updated(data) - species_id, strain_id = utils.get_species_mixin(data, db) - - brain_region_id = utils.get_brain_region(data, hierarchy_name, db) - - db_item = BrainAtlas( - legacy_id=[legacy_id], - legacy_self=[legacy_self], - name=data["name"], - description=data.get("description", ""), - brain_region_id=brain_region_id, - species_id=species_id, - strain_id=strain_id, - created_by_id=created_by_id, - updated_by_id=updated_by_id, - creation_date=createdAt, - update_date=updatedAt, - authorized_project_id=project_context.project_id, - authorized_public=AUTHORIZED_PUBLIC, - ) - - class ImportDistribution(Import): name = "Distribution" @@ -1098,8 +1108,7 @@ def ingest( ignored: dict[tuple[dict], int] = Counter() for data in tqdm(data_list): legacy_id = data["@id"] - root = utils._find_by_legacy_id(legacy_id, Entity, db) - if root: + if root := utils._find_by_legacy_id(legacy_id, Entity, db): utils.import_distribution(data, root.id, root.type, db, project_context) else: dt = data["@type"] @@ -1339,9 +1348,7 @@ def _do_import(db, input_dir, project_context, hierarchy_name): ImportAgent, ImportMETypeDensity, ImportCellComposition, - ImportBrainAtlas, ImportAnalysisSoftwareSourceCode, - ImportBrainRegionMeshes, ImportMorphologies, ImportEModels, ImportExperimentalNeuronDensities, @@ -1350,6 +1357,7 @@ def _do_import(db, input_dir, project_context, hierarchy_name): ImportMEModel, ImportElectricalCellRecording, ImportSingleNeuronSimulation, + ImportBrainAtlas, ImportDistribution, ImportNeuronMorphologyFeatureAnnotation, ] @@ -1579,7 +1587,7 @@ def curate_files(input_digest_path, output_digest_path, out_dir, dry_run): closing(configure_database_session_manager()) as database_session_manager, database_session_manager.session() as db, ): - # Group assets by ntity_type/entity_id/content_type + # Group assets by entity_type/entity_id/content_type assets_per_entity_type = defaultdict(lambda: defaultdict(lambda: defaultdict(list))) for asset in db.query(Asset).all(): entity_type = asset.full_path.split("/")[4] diff --git a/app/cli/utils.py b/app/cli/utils.py index 5056e17a..4e2b3f8f 100644 --- a/app/cli/utils.py +++ b/app/cli/utils.py @@ -60,13 +60,9 @@ def _find_by_legacy_id(legacy_id, db_type, db, _cache={}): return res -def get_brain_region_by_hier_id(brain_region, hierarchy_name, db, _cache={}): - brain_region = curate.curate_brain_region(brain_region) - - brain_region_id = int(brain_region["@id"]) +def get_brain_region_by_annotation_id(brain_region_id: int, hierarchy_name: str, db, _cache={}): if (hierarchy_name, brain_region_id) in _cache: return _cache[hierarchy_name, brain_region_id] - br = db.execute( sa.select(BrainRegion) .join(BrainRegionHierarchy, BrainRegion.hierarchy_id == BrainRegionHierarchy.id) @@ -77,13 +73,22 @@ def get_brain_region_by_hier_id(brain_region, hierarchy_name, db, _cache={}): ).scalar_one_or_none() if br is None: - msg = f"({hierarchy_name}, {brain_region}) not found in database" + msg = f"({hierarchy_name}, {brain_region_id}) not found in database" raise RuntimeError(msg) _cache[hierarchy_name, brain_region_id] = br.id + return br.id +def get_brain_region_by_hier_id(brain_region, hierarchy_name, db): + brain_region = curate.curate_brain_region(brain_region) + + brain_region_id = int(brain_region["@id"]) + + return get_brain_region_by_annotation_id(brain_region_id, hierarchy_name, db) + + def get_or_create_species(species, db, _cache={}): id_ = species["@id"] if id_ in _cache: diff --git a/app/db/model.py b/app/db/model.py index c0a478b9..c3672723 100644 --- a/app/db/model.py +++ b/app/db/model.py @@ -464,12 +464,6 @@ class EModel( __mapper_args__ = {"polymorphic_identity": __tablename__} # noqa: RUF012 -class Mesh(LocationMixin, NameDescriptionVectorMixin, Entity): - __tablename__ = EntityType.mesh.value - id: Mapped[uuid.UUID] = mapped_column(ForeignKey("entity.id"), primary_key=True) - __mapper_args__ = {"polymorphic_identity": __tablename__} # noqa: RUF012 - - class MEModel( MTypesMixin, ETypesMixin, SpeciesMixin, LocationMixin, NameDescriptionVectorMixin, Entity ): @@ -875,9 +869,30 @@ class METypeDensity( __mapper_args__ = {"polymorphic_identity": __tablename__} # noqa: RUF012 -class BrainAtlas(NameDescriptionVectorMixin, LocationMixin, SpeciesMixin, Entity): +class BrainAtlas(NameDescriptionVectorMixin, SpeciesMixin, Entity): __tablename__ = EntityType.brain_atlas + + id: Mapped[uuid.UUID] = mapped_column(ForeignKey("entity.id"), primary_key=True) + + hierarchy_id: Mapped[uuid.UUID] = mapped_column( + ForeignKey("brain_region_hierarchy.id"), index=True + ) + + __mapper_args__ = {"polymorphic_identity": __tablename__} # noqa: RUF012 + + +class BrainAtlasRegion(Entity, LocationMixin): + __tablename__ = EntityType.brain_atlas_region + id: Mapped[uuid.UUID] = mapped_column(ForeignKey("entity.id"), primary_key=True) + + # only the volume for leaf nodes is saved; the consumer must calculate + # volumes depending on which view of the hierarchy they are using + volume: Mapped[float] = mapped_column(nullable=True) + leaf_region: Mapped[bool] = mapped_column(default=False) + + brain_atlas_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("brain_atlas.id"), index=True) + __mapper_args__ = {"polymorphic_identity": __tablename__} # noqa: RUF012 diff --git a/app/db/types.py b/app/db/types.py index 3b4d2f22..1250b004 100644 --- a/app/db/types.py +++ b/app/db/types.py @@ -50,6 +50,7 @@ class EntityType(StrEnum): analysis_software_source_code = auto() brain_atlas = auto() + brain_atlas_region = auto() emodel = auto() cell_composition = auto() experimental_bouton_density = auto() diff --git a/app/filters/brain_atlas.py b/app/filters/brain_atlas.py new file mode 100644 index 00000000..89d51a98 --- /dev/null +++ b/app/filters/brain_atlas.py @@ -0,0 +1,27 @@ +from typing import Annotated + +from fastapi_filter import FilterDepends + +from app.db.model import BrainAtlas, BrainAtlasRegion +from app.filters.base import CustomFilter +from app.filters.common import IdFilterMixin, NameFilterMixin, SpeciesFilterMixin + + +class BrainAtlasFilter(IdFilterMixin, NameFilterMixin, SpeciesFilterMixin, CustomFilter): + order_by: list[str] = ["name"] # noqa: RUF012 + + class Constants(CustomFilter.Constants): + model = BrainAtlas + ordering_model_fields = ["name"] # noqa: RUF012 + + +class BrainAtlasRegionFilter(IdFilterMixin, CustomFilter): + order_by: list[str] = ["id", "creation_date"] # noqa: RUF012 + + class Constants(CustomFilter.Constants): + model = BrainAtlasRegion + ordering_model_fields = ["creation_date"] # noqa: RUF012 + + +BrainAtlasFilterDep = Annotated[BrainAtlasFilter, FilterDepends(BrainAtlasFilter)] +BrainAtlasRegionFilterDep = Annotated[BrainAtlasRegionFilter, FilterDepends(BrainAtlasRegionFilter)] diff --git a/app/routers/__init__.py b/app/routers/__init__.py index 18740a08..255dd5b0 100644 --- a/app/routers/__init__.py +++ b/app/routers/__init__.py @@ -5,6 +5,7 @@ from app.dependencies.auth import user_verified from app.routers import ( asset, + brain_atlas, brain_region, brain_region_hierarchy, cell_composition, @@ -38,6 +39,7 @@ router.include_router(root.router) authenticated_routers = [ asset.router, + brain_atlas.router, brain_region.router, brain_region_hierarchy.router, cell_composition.router, diff --git a/app/routers/brain_atlas.py b/app/routers/brain_atlas.py new file mode 100644 index 00000000..ee2cdf41 --- /dev/null +++ b/app/routers/brain_atlas.py @@ -0,0 +1,13 @@ +from fastapi import APIRouter + +import app.service.brain_atlas + +router = APIRouter( + prefix="/brain-atlas", + tags=["brain-atlas"], +) + +read_many = router.get("")(app.service.brain_atlas.read_many) +read_one = router.get("/{id_}")(app.service.brain_atlas.read_one) +read_many_region = router.get("/{id_}/regions")(app.service.brain_atlas.read_many_region) +read_one_region = router.get("/{id_}/regions/{region_id}")(app.service.brain_atlas.read_one_region) diff --git a/app/schemas/brain_atlas.py b/app/schemas/brain_atlas.py new file mode 100644 index 00000000..820c6d21 --- /dev/null +++ b/app/schemas/brain_atlas.py @@ -0,0 +1,31 @@ +import uuid + +from pydantic import BaseModel, ConfigDict + +from app.schemas.base import CreationMixin, IdentifiableMixin, SpeciesRead + + +class BrainAtlasBase(BaseModel): + model_config = ConfigDict(from_attributes=True) + + name: str + hierarchy_id: uuid.UUID + species: SpeciesRead + + +class BrainAtlasRead(BrainAtlasBase, CreationMixin, IdentifiableMixin): + pass + + +class BrainAtlasRegionBase(BaseModel): + model_config = ConfigDict(from_attributes=True) + + volume: float + leaf_region: bool + + brain_atlas_id: uuid.UUID + brain_region_id: uuid.UUID + + +class BrainAtlasRegionRead(BrainAtlasRegionBase, CreationMixin, IdentifiableMixin): + pass diff --git a/app/service/brain_atlas.py b/app/service/brain_atlas.py new file mode 100644 index 00000000..4adaa7a1 --- /dev/null +++ b/app/service/brain_atlas.py @@ -0,0 +1,72 @@ +import uuid + +import sqlalchemy as sa + +import app.queries.common +from app.db.model import BrainAtlas, BrainAtlasRegion +from app.dependencies.common import PaginationQuery +from app.dependencies.db import SessionDep +from app.errors import ensure_result +from app.filters.brain_atlas import BrainAtlasFilterDep, BrainAtlasRegionFilterDep +from app.schemas.brain_atlas import BrainAtlasRead, BrainAtlasRegionRead +from app.schemas.types import ListResponse + + +def read_many( + db: SessionDep, + pagination_request: PaginationQuery, + brain_atlas_filter: BrainAtlasFilterDep, +) -> ListResponse[BrainAtlasRead]: + return app.queries.common.router_read_many( + db=db, + db_model_class=BrainAtlas, + authorized_project_id=None, + with_search=None, + with_in_brain_region=None, + facets=None, + aliases=None, + apply_filter_query_operations=None, + apply_data_query_operations=None, + pagination_request=pagination_request, + response_schema_class=BrainAtlasRead, + name_to_facet_query_params=None, + filter_model=brain_atlas_filter, + ) + + +def read_one(id_: uuid.UUID, db: SessionDep) -> BrainAtlasRead: + with ensure_result(error_message="Brain Atlas not found"): + stmt = sa.select(BrainAtlas).filter(BrainAtlas.id == id_) + row = db.execute(stmt).scalar_one() + return BrainAtlasRead.model_validate(row) + + +def read_many_region( + db: SessionDep, + pagination_request: PaginationQuery, + brain_atlas_region_filter: BrainAtlasRegionFilterDep, +) -> ListResponse[BrainAtlasRegionRead]: + return app.queries.common.router_read_many( + db=db, + db_model_class=BrainAtlasRegion, + authorized_project_id=None, + with_search=None, + with_in_brain_region=None, + facets=None, + aliases=None, + apply_filter_query_operations=None, + apply_data_query_operations=None, + pagination_request=pagination_request, + response_schema_class=BrainAtlasRegionRead, + name_to_facet_query_params=None, + filter_model=brain_atlas_region_filter, + ) + + +def read_one_region(id_: uuid.UUID, region_id: uuid.UUID, db: SessionDep) -> BrainAtlasRegionRead: + with ensure_result(error_message="Brain Atlas Region not found"): + stmt = sa.select(BrainAtlasRegion).filter( + sa.and_(BrainAtlasRegion.brain_atlas_id == id_, BrainAtlasRegion.id == region_id) + ) + row = db.execute(stmt).scalar_one() + return BrainAtlasRegionRead.model_validate(row) diff --git a/app/service/brain_region_hierarchy.py b/app/service/brain_region_hierarchy.py index 4b76f8e1..7f5a0d9f 100644 --- a/app/service/brain_region_hierarchy.py +++ b/app/service/brain_region_hierarchy.py @@ -38,7 +38,7 @@ def read_many( def read_one(id_: uuid.UUID, db: SessionDep) -> BrainRegionHierarchyRead: - with ensure_result(error_message="Brain Region Hierarchy Name not found"): + with ensure_result(error_message="Brain Region Hierarchy not found"): stmt = sa.select(BrainRegionHierarchy).filter(BrainRegionHierarchy.id == id_) row = db.execute(stmt).scalar_one() return BrainRegionHierarchyRead.model_validate(row) diff --git a/docs/schema.md b/docs/schema.md index 602de843..3488823d 100644 --- a/docs/schema.md +++ b/docs/schema.md @@ -13,7 +13,6 @@ Objects exist independently and have states that can change over time. - AnalysisSoftwareSourceCode - EModel - - Mesh - MEModel - ReconstructionMorphology - SingleCellExperimentalTrace diff --git a/tests/test_brain_atlas.py b/tests/test_brain_atlas.py new file mode 100644 index 00000000..e4ee4f65 --- /dev/null +++ b/tests/test_brain_atlas.py @@ -0,0 +1,162 @@ +from unittest.mock import ANY + +import pytest + +from app.db.model import BrainAtlas, BrainAtlasRegion + +from . import utils + +ROUTE = "/brain-atlas" + + +HIERARCHY = { + "id": 997, + "acronym": "root", + "name": "root", + "color_hex_triplet": "FFFFFF", + "parent_structure_id": None, + "children": [ + { + "id": 8, + "acronym": "grey", + "name": "Basic cell groups and regions", + "color_hex_triplet": "BFDAE3", + "parent_structure_id": 997, + "children": [], + }, + { + "id": 42, + "acronym": "blue", + "name": "BlueRegion", + "color_hex_triplet": "0000FF", + "parent_structure_id": 997, + "children": [ + { + "id": 64, + "acronym": "red", + "name": "RedRegion", + "color_hex_triplet": "FF0000", + "parent_structure_id": 42, + "children": [], + } + ], + }, + ], +} + + +@pytest.fixture +def asdf(): + pass + + +def test_brain_atlas(db, client, species_id): + hierarchy_name = utils.create_hiearchy_name(db, "test_hierarchy") + regions = utils.add_brain_region_hierarchy(db, HIERARCHY, hierarchy_name.id) + + brain_atlas = utils.add_db( + db, + BrainAtlas( + name="test brain atlas", + description="test brain atlas description", + species_id=species_id, + hierarchy_id=hierarchy_name.id, + authorized_project_id=utils.PROJECT_ID, + authorized_public=True, + ), + ) + expected = { + "creation_date": ANY, + "hierarchy_id": str(hierarchy_name.id), + "id": str(brain_atlas.id), + "name": "test brain atlas", + "species": { + "creation_date": ANY, + "id": species_id, + "name": "Test Species", + "taxonomy_id": "12345", + "update_date": ANY, + }, + "update_date": ANY, + } + + response = client.get(ROUTE) + assert response.status_code == 200 + response = response.json() + assert len(response["data"]) == 1 + assert response["data"] == [ + expected, + ] + + response = client.get(f"{ROUTE}/{brain_atlas.id}") + assert response.status_code == 200 + response = response.json() + assert response == expected + + data = (("root", False, -1), ("blue", False, -1), ("red", True, 15), ("grey", True, 10)) + ids = {} + for name, leaf, volume in data: + row = BrainAtlasRegion( + volume=volume, + leaf_region=leaf, + brain_region_id=regions[name].id, + brain_atlas_id=brain_atlas.id, + authorized_project_id=utils.PROJECT_ID, + authorized_public=True, + ) + ids[name] = utils.add_db(db, row) + + response = client.get( + f"{ROUTE}/{brain_atlas.id}/regions", params={"order_by": "+creation_date"} + ) + assert response.status_code == 200 + assert response.json()["data"] == [ + { + "brain_atlas_id": str(brain_atlas.id), + "brain_region_id": str(regions["root"].id), + "creation_date": ANY, + "id": str(ids["root"].id), + "leaf_region": False, + "update_date": ANY, + "volume": -1.0, + }, + { + "brain_atlas_id": str(brain_atlas.id), + "brain_region_id": str(regions["blue"].id), + "creation_date": ANY, + "id": str(ids["blue"].id), + "leaf_region": False, + "update_date": ANY, + "volume": -1.0, + }, + { + "brain_atlas_id": str(brain_atlas.id), + "brain_region_id": str(regions["red"].id), + "creation_date": ANY, + "id": str(ids["red"].id), + "leaf_region": True, + "update_date": ANY, + "volume": 15.0, + }, + { + "brain_atlas_id": str(brain_atlas.id), + "brain_region_id": str(regions["grey"].id), + "creation_date": ANY, + "id": str(ids["grey"].id), + "leaf_region": True, + "update_date": ANY, + "volume": 10.0, + }, + ] + + response = client.get(f"{ROUTE}/{brain_atlas.id}/regions/{ids['root'].id}") + assert response.status_code == 200 + assert response.json() == { + "brain_atlas_id": str(brain_atlas.id), + "brain_region_id": str(regions["root"].id), + "creation_date": ANY, + "id": str(ids["root"].id), + "leaf_region": False, + "update_date": ANY, + "volume": -1.0, + } diff --git a/tests/test_brain_region.py b/tests/test_brain_region.py index 1e4e690d..6be9efbc 100644 --- a/tests/test_brain_region.py +++ b/tests/test_brain_region.py @@ -1,10 +1,6 @@ import itertools as it from unittest.mock import ANY -import sqlalchemy as sa - -from app.db.model import BrainRegion - from . import utils ROUTE = "/brain-region" @@ -46,40 +42,9 @@ } -def add_brain_region_hierarchy(db, hierarchy, hierarchy_id): - regions = [] - - def recurse(i): - children = [] - item = i | {"children": children} - for child in i["children"]: - children.append(child["id"]) - recurse(child) - regions.append(item) - - recurse(hierarchy) - - ids = {None: None} - for region in reversed(regions): - row = BrainRegion( - annotation_value=region["id"], - acronym=region["acronym"], - name=region["name"], - color_hex_triplet=region["color_hex_triplet"], - parent_structure_id=ids[region["parent_structure_id"]], - hierarchy_id=hierarchy_id, - ) - db_br = utils.add_db(db, row) - db.flush() - ids[region["id"]] = db_br.id - - ret = {row.acronym: row for row in db.execute(sa.select(BrainRegion)).scalars()} - return ret - - def test_brain_region_id(db, client): hierarchy_name = utils.create_hiearchy_name(db, "test_hierarchy") - add_brain_region_hierarchy(db, HIERARCHY, hierarchy_name.id) + utils.add_brain_region_hierarchy(db, HIERARCHY, hierarchy_name.id) response = client.get(ROUTE) assert response.status_code == 200 @@ -146,10 +111,10 @@ def test_brain_region_id(db, client): def test_family_queries(db, client, species_id, strain_id): hierarchy_name0 = utils.create_hiearchy_name(db, "hier0") - brain_regions0 = add_brain_region_hierarchy(db, HIERARCHY, hierarchy_name0.id) + brain_regions0 = utils.add_brain_region_hierarchy(db, HIERARCHY, hierarchy_name0.id) hierarchy_name1 = utils.create_hiearchy_name(db, "hier1") - brain_regions1 = add_brain_region_hierarchy(db, HIERARCHY, hierarchy_name1.id) + brain_regions1 = utils.add_brain_region_hierarchy(db, HIERARCHY, hierarchy_name1.id) for acronym, row in it.chain(brain_regions0.items(), brain_regions1.items()): hier = "hier0" if row.hierarchy_id == hierarchy_name0.id else "hier1" diff --git a/tests/test_brain_region_hierarchy.py b/tests/test_brain_region_hierarchy.py index 569eeaad..7cb2e852 100644 --- a/tests/test_brain_region_hierarchy.py +++ b/tests/test_brain_region_hierarchy.py @@ -1,7 +1,6 @@ import operator -from tests import test_brain_region -from tests.utils import MISSING_ID, MISSING_ID_COMPACT +from tests import test_brain_region, utils ROUTE = "/brain-region-hierarchy" @@ -22,10 +21,10 @@ def test_brain_region_hierarchy(client, brain_region_hierarchy_id): def test_missing(client): - response = client.get(f"{ROUTE}/{MISSING_ID}") + response = client.get(f"{ROUTE}/{utils.MISSING_ID}") assert response.status_code == 404 - response = client.get(f"{ROUTE}/{MISSING_ID_COMPACT}") + response = client.get(f"{ROUTE}/{utils.MISSING_ID_COMPACT}") assert response.status_code == 404 response = client.get(f"{ROUTE}/42424242") @@ -36,9 +35,7 @@ def test_missing(client): def test_hierarchy_tree(db, client, brain_region_hierarchy_id): - test_brain_region.add_brain_region_hierarchy( - db, test_brain_region.HIERARCHY, brain_region_hierarchy_id - ) + utils.add_brain_region_hierarchy(db, test_brain_region.HIERARCHY, brain_region_hierarchy_id) response = client.get(f"{ROUTE}/{brain_region_hierarchy_id}/hierarchy") assert response.status_code == 200 diff --git a/tests/utils.py b/tests/utils.py index 31f66878..f3dfec50 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -3,6 +3,7 @@ from pathlib import Path from unittest.mock import ANY +import sqlalchemy as sa from httpx import Headers from starlette.testclient import TestClient @@ -317,3 +318,34 @@ def with_creation_fields(d): "update_date": ANY, "id": ANY, } + + +def add_brain_region_hierarchy(db, hierarchy, hierarchy_id): + regions = [] + + def recurse(i): + children = [] + item = i | {"children": children} + for child in i["children"]: + children.append(child["id"]) + recurse(child) + regions.append(item) + + recurse(hierarchy) + + ids = {None: None} + for region in reversed(regions): + row = BrainRegion( + annotation_value=region["id"], + acronym=region["acronym"], + name=region["name"], + color_hex_triplet=region["color_hex_triplet"], + parent_structure_id=ids[region["parent_structure_id"]], + hierarchy_id=hierarchy_id, + ) + db_br = add_db(db, row) + db.flush() + ids[region["id"]] = db_br.id + + ret = {row.acronym: row for row in db.execute(sa.select(BrainRegion)).scalars()} + return ret From ce2446e662b78e40caf2cbe6e66bb8ba1e90feaf Mon Sep 17 00:00:00 2001 From: Mike Gevaert Date: Fri, 23 May 2025 14:53:51 +0200 Subject: [PATCH 2/5] EZ comments --- app/cli/import_data.py | 2 +- app/service/brain_atlas.py | 40 +++++++++++++++++++++++++------------- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/app/cli/import_data.py b/app/cli/import_data.py index 8a05000b..11258247 100644 --- a/app/cli/import_data.py +++ b/app/cli/import_data.py @@ -631,7 +631,7 @@ def ingest(db, project_context, data_list, all_data_by_id, hierarchy_name: str): if atlas_region is None: annotation_id = curate.curate_brain_region(brain_region_data)["@id"] - volume = -1 + volume = -1_000_000_000 leaf_region = False if annotation_id in BRAIN_ATLAS_REGION_VOLUMES: diff --git a/app/service/brain_atlas.py b/app/service/brain_atlas.py index 4adaa7a1..348b8cbe 100644 --- a/app/service/brain_atlas.py +++ b/app/service/brain_atlas.py @@ -4,15 +4,16 @@ import app.queries.common from app.db.model import BrainAtlas, BrainAtlasRegion +from app.dependencies.auth import UserContextDep from app.dependencies.common import PaginationQuery from app.dependencies.db import SessionDep -from app.errors import ensure_result from app.filters.brain_atlas import BrainAtlasFilterDep, BrainAtlasRegionFilterDep from app.schemas.brain_atlas import BrainAtlasRead, BrainAtlasRegionRead from app.schemas.types import ListResponse def read_many( + user_context: UserContextDep, db: SessionDep, pagination_request: PaginationQuery, brain_atlas_filter: BrainAtlasFilterDep, @@ -20,7 +21,7 @@ def read_many( return app.queries.common.router_read_many( db=db, db_model_class=BrainAtlas, - authorized_project_id=None, + authorized_project_id=user_context.project_id, with_search=None, with_in_brain_region=None, facets=None, @@ -34,14 +35,19 @@ def read_many( ) -def read_one(id_: uuid.UUID, db: SessionDep) -> BrainAtlasRead: - with ensure_result(error_message="Brain Atlas not found"): - stmt = sa.select(BrainAtlas).filter(BrainAtlas.id == id_) - row = db.execute(stmt).scalar_one() - return BrainAtlasRead.model_validate(row) +def read_one(user_context: UserContextDep, id_: uuid.UUID, db: SessionDep) -> BrainAtlasRead: + return app.queries.common.router_read_one( + id_=id_, + db=db, + db_model_class=BrainAtlas, + authorized_project_id=user_context.project_id, + response_schema_class=BrainAtlasRead, + apply_operations=None, + ) def read_many_region( + user_context: UserContextDep, db: SessionDep, pagination_request: PaginationQuery, brain_atlas_region_filter: BrainAtlasRegionFilterDep, @@ -49,7 +55,7 @@ def read_many_region( return app.queries.common.router_read_many( db=db, db_model_class=BrainAtlasRegion, - authorized_project_id=None, + authorized_project_id=user_context.project_id, with_search=None, with_in_brain_region=None, facets=None, @@ -63,10 +69,16 @@ def read_many_region( ) -def read_one_region(id_: uuid.UUID, region_id: uuid.UUID, db: SessionDep) -> BrainAtlasRegionRead: - with ensure_result(error_message="Brain Atlas Region not found"): - stmt = sa.select(BrainAtlasRegion).filter( +def read_one_region( + user_context: UserContextDep, id_: uuid.UUID, region_id: uuid.UUID, db: SessionDep +) -> BrainAtlasRegionRead: + return app.queries.common.router_read_one( + id_=region_id, + db=db, + db_model_class=BrainAtlasRegion, + authorized_project_id=user_context.project_id, + response_schema_class=BrainAtlasRegionRead, + apply_operations=lambda q: q.filter( sa.and_(BrainAtlasRegion.brain_atlas_id == id_, BrainAtlasRegion.id == region_id) - ) - row = db.execute(stmt).scalar_one() - return BrainAtlasRegionRead.model_validate(row) + ), + ) From ece8bbfeb61cdbf9a4e91481482dd83b296ac9b6 Mon Sep 17 00:00:00 2001 From: Mike Gevaert Date: Mon, 26 May 2025 09:48:46 +0200 Subject: [PATCH 3/5] comments --- app/cli/import_data.py | 1 - app/routers/brain_atlas.py | 8 ++++-- app/service/brain_atlas.py | 19 ++++++------- tests/test_brain_atlas.py | 58 ++++++++++++++++++++++++-------------- 4 files changed, 51 insertions(+), 35 deletions(-) diff --git a/app/cli/import_data.py b/app/cli/import_data.py index 11258247..fb15d8bb 100644 --- a/app/cli/import_data.py +++ b/app/cli/import_data.py @@ -1,6 +1,5 @@ import datetime import glob -import hashlib import json import os import random diff --git a/app/routers/brain_atlas.py b/app/routers/brain_atlas.py index ee2cdf41..ae33deea 100644 --- a/app/routers/brain_atlas.py +++ b/app/routers/brain_atlas.py @@ -8,6 +8,8 @@ ) read_many = router.get("")(app.service.brain_atlas.read_many) -read_one = router.get("/{id_}")(app.service.brain_atlas.read_one) -read_many_region = router.get("/{id_}/regions")(app.service.brain_atlas.read_many_region) -read_one_region = router.get("/{id_}/regions/{region_id}")(app.service.brain_atlas.read_one_region) +read_one = router.get("/{atlas_id}")(app.service.brain_atlas.read_one) +read_many_region = router.get("/{atlas_id}/regions")(app.service.brain_atlas.read_many_region) +read_one_region = router.get("/{atlas_id}/regions/{atlas_region_id}")( + app.service.brain_atlas.read_one_region +) diff --git a/app/service/brain_atlas.py b/app/service/brain_atlas.py index 348b8cbe..d6b6b409 100644 --- a/app/service/brain_atlas.py +++ b/app/service/brain_atlas.py @@ -1,7 +1,5 @@ import uuid -import sqlalchemy as sa - import app.queries.common from app.db.model import BrainAtlas, BrainAtlasRegion from app.dependencies.auth import UserContextDep @@ -35,9 +33,9 @@ def read_many( ) -def read_one(user_context: UserContextDep, id_: uuid.UUID, db: SessionDep) -> BrainAtlasRead: +def read_one(user_context: UserContextDep, atlas_id: uuid.UUID, db: SessionDep) -> BrainAtlasRead: return app.queries.common.router_read_one( - id_=id_, + id_=atlas_id, db=db, db_model_class=BrainAtlas, authorized_project_id=user_context.project_id, @@ -48,6 +46,7 @@ def read_one(user_context: UserContextDep, id_: uuid.UUID, db: SessionDep) -> Br def read_many_region( user_context: UserContextDep, + atlas_id: uuid.UUID, db: SessionDep, pagination_request: PaginationQuery, brain_atlas_region_filter: BrainAtlasRegionFilterDep, @@ -60,7 +59,9 @@ def read_many_region( with_in_brain_region=None, facets=None, aliases=None, - apply_filter_query_operations=None, + apply_filter_query_operations=lambda q: q.filter( + BrainAtlasRegion.brain_atlas_id == atlas_id + ), apply_data_query_operations=None, pagination_request=pagination_request, response_schema_class=BrainAtlasRegionRead, @@ -70,15 +71,13 @@ def read_many_region( def read_one_region( - user_context: UserContextDep, id_: uuid.UUID, region_id: uuid.UUID, db: SessionDep + user_context: UserContextDep, atlas_id: uuid.UUID, atlas_region_id: uuid.UUID, db: SessionDep ) -> BrainAtlasRegionRead: return app.queries.common.router_read_one( - id_=region_id, + id_=atlas_region_id, db=db, db_model_class=BrainAtlasRegion, authorized_project_id=user_context.project_id, response_schema_class=BrainAtlasRegionRead, - apply_operations=lambda q: q.filter( - sa.and_(BrainAtlasRegion.brain_atlas_id == id_, BrainAtlasRegion.id == region_id) - ), + apply_operations=lambda q: q.filter(BrainAtlasRegion.brain_atlas_id == atlas_id), ) diff --git a/tests/test_brain_atlas.py b/tests/test_brain_atlas.py index e4ee4f65..191a66e9 100644 --- a/tests/test_brain_atlas.py +++ b/tests/test_brain_atlas.py @@ -1,3 +1,4 @@ +import itertools as it from unittest.mock import ANY import pytest @@ -54,7 +55,7 @@ def test_brain_atlas(db, client, species_id): hierarchy_name = utils.create_hiearchy_name(db, "test_hierarchy") regions = utils.add_brain_region_hierarchy(db, HIERARCHY, hierarchy_name.id) - brain_atlas = utils.add_db( + brain_atlas0 = utils.add_db( db, BrainAtlas( name="test brain atlas", @@ -65,10 +66,21 @@ def test_brain_atlas(db, client, species_id): authorized_public=True, ), ) + brain_atlas1 = utils.add_db( + db, + BrainAtlas( + name="test brain atlas 1", + description="test brain atlas description 1", + species_id=species_id, + hierarchy_id=hierarchy_name.id, + authorized_project_id=utils.PROJECT_ID, + authorized_public=True, + ), + ) expected = { "creation_date": ANY, "hierarchy_id": str(hierarchy_name.id), - "id": str(brain_atlas.id), + "id": str(brain_atlas0.id), "name": "test brain atlas", "species": { "creation_date": ANY, @@ -83,19 +95,23 @@ def test_brain_atlas(db, client, species_id): response = client.get(ROUTE) assert response.status_code == 200 response = response.json() - assert len(response["data"]) == 1 - assert response["data"] == [ - expected, - ] + assert len(response["data"]) == 2 + assert response["data"][0] == expected - response = client.get(f"{ROUTE}/{brain_atlas.id}") + response = client.get(f"{ROUTE}/{brain_atlas0.id}") assert response.status_code == 200 response = response.json() assert response == expected data = (("root", False, -1), ("blue", False, -1), ("red", True, 15), ("grey", True, 10)) ids = {} - for name, leaf, volume in data: + for brain_atlas, (name, leaf, volume) in it.product( + ( + brain_atlas0, + brain_atlas1, + ), + data, + ): row = BrainAtlasRegion( volume=volume, leaf_region=leaf, @@ -104,58 +120,58 @@ def test_brain_atlas(db, client, species_id): authorized_project_id=utils.PROJECT_ID, authorized_public=True, ) - ids[name] = utils.add_db(db, row) + ids[brain_atlas.name, name] = utils.add_db(db, row) response = client.get( - f"{ROUTE}/{brain_atlas.id}/regions", params={"order_by": "+creation_date"} + f"{ROUTE}/{brain_atlas0.id}/regions", params={"order_by": "+creation_date"} ) assert response.status_code == 200 assert response.json()["data"] == [ { - "brain_atlas_id": str(brain_atlas.id), + "brain_atlas_id": str(brain_atlas0.id), "brain_region_id": str(regions["root"].id), "creation_date": ANY, - "id": str(ids["root"].id), + "id": str(ids[brain_atlas0.name, "root"].id), "leaf_region": False, "update_date": ANY, "volume": -1.0, }, { - "brain_atlas_id": str(brain_atlas.id), + "brain_atlas_id": str(brain_atlas0.id), "brain_region_id": str(regions["blue"].id), "creation_date": ANY, - "id": str(ids["blue"].id), + "id": str(ids[brain_atlas0.name, "blue"].id), "leaf_region": False, "update_date": ANY, "volume": -1.0, }, { - "brain_atlas_id": str(brain_atlas.id), + "brain_atlas_id": str(brain_atlas0.id), "brain_region_id": str(regions["red"].id), "creation_date": ANY, - "id": str(ids["red"].id), + "id": str(ids[brain_atlas0.name, "red"].id), "leaf_region": True, "update_date": ANY, "volume": 15.0, }, { - "brain_atlas_id": str(brain_atlas.id), + "brain_atlas_id": str(brain_atlas0.id), "brain_region_id": str(regions["grey"].id), "creation_date": ANY, - "id": str(ids["grey"].id), + "id": str(ids[brain_atlas0.name, "grey"].id), "leaf_region": True, "update_date": ANY, "volume": 10.0, }, ] - response = client.get(f"{ROUTE}/{brain_atlas.id}/regions/{ids['root'].id}") + response = client.get(f"{ROUTE}/{brain_atlas0.id}/regions/{ids[brain_atlas0.name, 'root'].id}") assert response.status_code == 200 assert response.json() == { - "brain_atlas_id": str(brain_atlas.id), + "brain_atlas_id": str(brain_atlas0.id), "brain_region_id": str(regions["root"].id), "creation_date": ANY, - "id": str(ids["root"].id), + "id": str(ids[brain_atlas0.name, "root"].id), "leaf_region": False, "update_date": ANY, "volume": -1.0, From edf654711e8df0160a525751e52e00e65671ff88 Mon Sep 17 00:00:00 2001 From: Mike Gevaert Date: Mon, 26 May 2025 12:16:10 +0200 Subject: [PATCH 4/5] comments --- ..._7699329e803f_default_migration_message.py | 34 -- ...20250523_111526_4a2e856cf2db_brainatlas.py | 203 ----------- ...408404_electricalrecordingstimulus_use_.py | 82 ----- ..._license_use_namedescriptionvectormixin.py | 62 ---- ...250526_121310_f69bb778caa6_base_models.py} | 131 ++++--- ... 20250526_121330_698536102bc8_triggers.py} | 342 ++++++++++-------- app/cli/import_data.py | 8 +- app/db/model.py | 4 +- app/schemas/brain_atlas.py | 4 +- tests/test_brain_atlas.py | 27 +- 10 files changed, 288 insertions(+), 609 deletions(-) delete mode 100644 alembic/versions/20250523_083807_7699329e803f_default_migration_message.py delete mode 100644 alembic/versions/20250523_111526_4a2e856cf2db_brainatlas.py delete mode 100644 alembic/versions/20250526_095128_062c5a408404_electricalrecordingstimulus_use_.py delete mode 100644 alembic/versions/20250526_100043_c4fa9c327b08_license_use_namedescriptionvectormixin.py rename alembic/versions/{20250521_160544_478cb2e9eb55_models.py => 20250526_121310_f69bb778caa6_base_models.py} (97%) rename alembic/versions/{20250521_160604_719dc38efbd6_trigeers.py => 20250526_121330_698536102bc8_triggers.py} (92%) diff --git a/alembic/versions/20250523_083807_7699329e803f_default_migration_message.py b/alembic/versions/20250523_083807_7699329e803f_default_migration_message.py deleted file mode 100644 index 5698af25..00000000 --- a/alembic/versions/20250523_083807_7699329e803f_default_migration_message.py +++ /dev/null @@ -1,34 +0,0 @@ -"""Default migration message - -Revision ID: 7699329e803f -Revises: 719dc38efbd6 -Create Date: 2025-05-23 08:38:07.307381 - -""" - -from typing import Sequence, Union - -from alembic import op -import sqlalchemy as sa - - -from sqlalchemy import Text -import app.db.types - -# revision identifiers, used by Alembic. -revision: str = "7699329e803f" -down_revision: Union[str, None] = "719dc38efbd6" -branch_labels: Union[str, Sequence[str], None] = None -depends_on: Union[str, Sequence[str], None] = None - - -def upgrade() -> None: - # ### commands auto generated by Alembic - please adjust! ### - op.create_index(op.f("ix_measurement_item_value"), "measurement_item", ["value"], unique=False) - # ### end Alembic commands ### - - -def downgrade() -> None: - # ### commands auto generated by Alembic - please adjust! ### - op.drop_index(op.f("ix_measurement_item_value"), table_name="measurement_item") - # ### end Alembic commands ### diff --git a/alembic/versions/20250523_111526_4a2e856cf2db_brainatlas.py b/alembic/versions/20250523_111526_4a2e856cf2db_brainatlas.py deleted file mode 100644 index 07eb25fe..00000000 --- a/alembic/versions/20250523_111526_4a2e856cf2db_brainatlas.py +++ /dev/null @@ -1,203 +0,0 @@ -"""brainatlas - -Revision ID: 4a2e856cf2db -Revises: 7699329e803f -Create Date: 2025-05-23 11:15:26.847117 - -""" - -from typing import Sequence, Union - -from alembic import op -import sqlalchemy as sa -from alembic_postgresql_enum import TableReference -from alembic_utils.pg_trigger import PGTrigger -from sqlalchemy import text as sql_text -from sqlalchemy.dialects import postgresql - -from sqlalchemy import Text -import app.db.types - -# revision identifiers, used by Alembic. -revision: str = "4a2e856cf2db" -down_revision: Union[str, None] = "7699329e803f" -branch_labels: Union[str, Sequence[str], None] = None -depends_on: Union[str, Sequence[str], None] = None - - -def upgrade() -> None: - # ### commands auto generated by Alembic - please adjust! ### - op.create_table( - "brain_atlas_region", - sa.Column("id", sa.Uuid(), nullable=False), - sa.Column("volume", sa.Float(), nullable=True), - sa.Column("leaf_region", sa.Boolean(), nullable=False), - sa.Column("brain_atlas_id", sa.Uuid(), nullable=False), - sa.Column("brain_region_id", sa.Uuid(), nullable=False), - sa.ForeignKeyConstraint( - ["brain_atlas_id"], - ["brain_atlas.id"], - name=op.f("fk_brain_atlas_region_brain_atlas_id_brain_atlas"), - ), - sa.ForeignKeyConstraint( - ["brain_region_id"], - ["brain_region.id"], - name=op.f("fk_brain_atlas_region_brain_region_id_brain_region"), - ), - sa.ForeignKeyConstraint( - ["id"], ["entity.id"], name=op.f("fk_brain_atlas_region_id_entity") - ), - sa.PrimaryKeyConstraint("id", name=op.f("pk_brain_atlas_region")), - ) - op.create_index( - op.f("ix_brain_atlas_region_brain_atlas_id"), - "brain_atlas_region", - ["brain_atlas_id"], - unique=False, - ) - op.create_index( - op.f("ix_brain_atlas_region_brain_region_id"), - "brain_atlas_region", - ["brain_region_id"], - unique=False, - ) - op.drop_index("ix_mesh_brain_region_id", table_name="mesh") - op.drop_index("ix_mesh_description_vector", table_name="mesh", postgresql_using="gin") - op.drop_index("ix_mesh_name", table_name="mesh") - op.drop_table("mesh") - op.add_column("brain_atlas", sa.Column("hierarchy_id", sa.Uuid(), nullable=False)) - op.drop_index("ix_brain_atlas_brain_region_id", table_name="brain_atlas") - op.create_index( - op.f("ix_brain_atlas_hierarchy_id"), "brain_atlas", ["hierarchy_id"], unique=False - ) - op.drop_constraint( - "fk_brain_atlas_brain_region_id_brain_region", "brain_atlas", type_="foreignkey" - ) - op.create_foreign_key( - op.f("fk_brain_atlas_hierarchy_id_brain_region_hierarchy"), - "brain_atlas", - "brain_region_hierarchy", - ["hierarchy_id"], - ["id"], - ) - op.drop_column("brain_atlas", "brain_region_id") - op.sync_enum_values( - enum_schema="public", - enum_name="entitytype", - new_values=[ - "analysis_software_source_code", - "brain_atlas", - "brain_atlas_region", - "emodel", - "cell_composition", - "experimental_bouton_density", - "experimental_neuron_density", - "experimental_synapses_per_connection", - "memodel", - "mesh", - "me_type_density", - "reconstruction_morphology", - "electrical_cell_recording", - "electrical_recording_stimulus", - "single_neuron_simulation", - "single_neuron_synaptome", - "single_neuron_synaptome_simulation", - "ion_channel_model", - "subject", - "validation_result", - ], - affected_columns=[ - TableReference(table_schema="public", table_name="entity", column_name="type") - ], - enum_values_to_rename=[], - ) - - # ### end Alembic commands ### - - -def downgrade() -> None: - # ### commands auto generated by Alembic - please adjust! ### - public_mesh_mesh_description_vector = PGTrigger( - schema="public", - signature="mesh_description_vector", - on_entity="public.mesh", - is_constraint=False, - definition="BEFORE INSERT OR UPDATE ON public.mesh FOR EACH ROW EXECUTE FUNCTION tsvector_update_trigger('description_vector', 'pg_catalog.english', 'description', 'name')", - ) - op.create_entity(public_mesh_mesh_description_vector) - - op.sync_enum_values( - enum_schema="public", - enum_name="entitytype", - new_values=[ - "analysis_software_source_code", - "brain_atlas", - "emodel", - "cell_composition", - "experimental_bouton_density", - "experimental_neuron_density", - "experimental_synapses_per_connection", - "memodel", - "mesh", - "me_type_density", - "reconstruction_morphology", - "electrical_cell_recording", - "electrical_recording_stimulus", - "single_neuron_simulation", - "single_neuron_synaptome", - "single_neuron_synaptome_simulation", - "ion_channel_model", - "subject", - "validation_result", - ], - affected_columns=[ - TableReference(table_schema="public", table_name="entity", column_name="type") - ], - enum_values_to_rename=[], - ) - op.add_column( - "brain_atlas", sa.Column("brain_region_id", sa.UUID(), autoincrement=False, nullable=False) - ) - op.drop_constraint( - op.f("fk_brain_atlas_hierarchy_id_brain_region_hierarchy"), - "brain_atlas", - type_="foreignkey", - ) - op.create_foreign_key( - "fk_brain_atlas_brain_region_id_brain_region", - "brain_atlas", - "brain_region", - ["brain_region_id"], - ["id"], - ) - op.drop_index(op.f("ix_brain_atlas_hierarchy_id"), table_name="brain_atlas") - op.create_index( - "ix_brain_atlas_brain_region_id", "brain_atlas", ["brain_region_id"], unique=False - ) - op.drop_column("brain_atlas", "hierarchy_id") - op.create_table( - "mesh", - sa.Column("id", sa.UUID(), autoincrement=False, nullable=False), - sa.Column("brain_region_id", sa.UUID(), autoincrement=False, nullable=False), - sa.Column("name", sa.VARCHAR(), autoincrement=False, nullable=False), - sa.Column("description", sa.VARCHAR(), autoincrement=False, nullable=False), - sa.Column("description_vector", postgresql.TSVECTOR(), autoincrement=False, nullable=True), - sa.ForeignKeyConstraint( - ["brain_region_id"], ["brain_region.id"], name="fk_mesh_brain_region_id_brain_region" - ), - sa.ForeignKeyConstraint(["id"], ["entity.id"], name="fk_mesh_id_entity"), - sa.PrimaryKeyConstraint("id", name="pk_mesh"), - ) - op.create_index("ix_mesh_name", "mesh", ["name"], unique=False) - op.create_index( - "ix_mesh_description_vector", - "mesh", - ["description_vector"], - unique=False, - postgresql_using="gin", - ) - op.create_index("ix_mesh_brain_region_id", "mesh", ["brain_region_id"], unique=False) - op.drop_index(op.f("ix_brain_atlas_region_brain_region_id"), table_name="brain_atlas_region") - op.drop_index(op.f("ix_brain_atlas_region_brain_atlas_id"), table_name="brain_atlas_region") - op.drop_table("brain_atlas_region") - # ### end Alembic commands ### diff --git a/alembic/versions/20250526_095128_062c5a408404_electricalrecordingstimulus_use_.py b/alembic/versions/20250526_095128_062c5a408404_electricalrecordingstimulus_use_.py deleted file mode 100644 index a7bf7a13..00000000 --- a/alembic/versions/20250526_095128_062c5a408404_electricalrecordingstimulus_use_.py +++ /dev/null @@ -1,82 +0,0 @@ -"""ElectricalRecordingStimulus -> use NameDescriptionVectorMixin - -Revision ID: 062c5a408404 -Revises: 7699329e803f -Create Date: 2025-05-26 09:51:28.523519 - -""" - -from typing import Sequence, Union - -from alembic import op -import sqlalchemy as sa -from alembic_utils.pg_trigger import PGTrigger -from sqlalchemy import text as sql_text -from sqlalchemy.dialects import postgresql - -from sqlalchemy import Text -import app.db.types - -# revision identifiers, used by Alembic. -revision: str = "062c5a408404" -down_revision: Union[str, None] = "7699329e803f" -branch_labels: Union[str, Sequence[str], None] = None -depends_on: Union[str, Sequence[str], None] = None - - -def upgrade() -> None: - # ### commands auto generated by Alembic - please adjust! ### - op.add_column( - "electrical_recording_stimulus", - sa.Column("description_vector", postgresql.TSVECTOR(), nullable=True), - ) - op.create_index( - "ix_electrical_recording_stimulus_description_vector", - "electrical_recording_stimulus", - ["description_vector"], - unique=False, - postgresql_using="gin", - ) - op.create_index( - op.f("ix_electrical_recording_stimulus_name"), - "electrical_recording_stimulus", - ["name"], - unique=False, - ) - public_electrical_recording_stimulus_electrical_recording_stimulus_description_vector = PGTrigger( - schema="public", - signature="electrical_recording_stimulus_description_vector", - on_entity="public.electrical_recording_stimulus", - is_constraint=False, - definition="BEFORE INSERT OR UPDATE ON electrical_recording_stimulus\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", - ) - op.create_entity( - public_electrical_recording_stimulus_electrical_recording_stimulus_description_vector - ) - - # ### end Alembic commands ### - - -def downgrade() -> None: - # ### commands auto generated by Alembic - please adjust! ### - public_electrical_recording_stimulus_electrical_recording_stimulus_description_vector = PGTrigger( - schema="public", - signature="electrical_recording_stimulus_description_vector", - on_entity="public.electrical_recording_stimulus", - is_constraint=False, - definition="BEFORE INSERT OR UPDATE ON electrical_recording_stimulus\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", - ) - op.drop_entity( - public_electrical_recording_stimulus_electrical_recording_stimulus_description_vector - ) - - op.drop_index( - op.f("ix_electrical_recording_stimulus_name"), table_name="electrical_recording_stimulus" - ) - op.drop_index( - "ix_electrical_recording_stimulus_description_vector", - table_name="electrical_recording_stimulus", - postgresql_using="gin", - ) - op.drop_column("electrical_recording_stimulus", "description_vector") - # ### end Alembic commands ### diff --git a/alembic/versions/20250526_100043_c4fa9c327b08_license_use_namedescriptionvectormixin.py b/alembic/versions/20250526_100043_c4fa9c327b08_license_use_namedescriptionvectormixin.py deleted file mode 100644 index 005ad8e8..00000000 --- a/alembic/versions/20250526_100043_c4fa9c327b08_license_use_namedescriptionvectormixin.py +++ /dev/null @@ -1,62 +0,0 @@ -"""License -> use NameDescriptionVectorMixin - -Revision ID: c4fa9c327b08 -Revises: 062c5a408404 -Create Date: 2025-05-26 10:00:43.087987 - -""" - -from typing import Sequence, Union - -from alembic import op -import sqlalchemy as sa -from alembic_utils.pg_trigger import PGTrigger -from sqlalchemy import text as sql_text -from sqlalchemy.dialects import postgresql - -from sqlalchemy import Text -import app.db.types - -# revision identifiers, used by Alembic. -revision: str = "c4fa9c327b08" -down_revision: Union[str, None] = "062c5a408404" -branch_labels: Union[str, Sequence[str], None] = None -depends_on: Union[str, Sequence[str], None] = None - - -def upgrade() -> None: - # ### commands auto generated by Alembic - please adjust! ### - op.add_column("license", sa.Column("description_vector", postgresql.TSVECTOR(), nullable=True)) - op.create_index( - "ix_license_description_vector", - "license", - ["description_vector"], - unique=False, - postgresql_using="gin", - ) - public_license_license_description_vector = PGTrigger( - schema="public", - signature="license_description_vector", - on_entity="public.license", - is_constraint=False, - definition="BEFORE INSERT OR UPDATE ON license\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", - ) - op.create_entity(public_license_license_description_vector) - - # ### end Alembic commands ### - - -def downgrade() -> None: - # ### commands auto generated by Alembic - please adjust! ### - public_license_license_description_vector = PGTrigger( - schema="public", - signature="license_description_vector", - on_entity="public.license", - is_constraint=False, - definition="BEFORE INSERT OR UPDATE ON license\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", - ) - op.drop_entity(public_license_license_description_vector) - - op.drop_index("ix_license_description_vector", table_name="license", postgresql_using="gin") - op.drop_column("license", "description_vector") - # ### end Alembic commands ### diff --git a/alembic/versions/20250521_160544_478cb2e9eb55_models.py b/alembic/versions/20250526_121310_f69bb778caa6_base_models.py similarity index 97% rename from alembic/versions/20250521_160544_478cb2e9eb55_models.py rename to alembic/versions/20250526_121310_f69bb778caa6_base_models.py index 67c9d067..171c6ee0 100644 --- a/alembic/versions/20250521_160544_478cb2e9eb55_models.py +++ b/alembic/versions/20250526_121310_f69bb778caa6_base_models.py @@ -1,8 +1,8 @@ -"""models +"""base models -Revision ID: 478cb2e9eb55 +Revision ID: f69bb778caa6 Revises: -Create Date: 2025-05-21 16:05:44.426230 +Create Date: 2025-05-26 12:13:10.599423 """ @@ -16,7 +16,7 @@ import app.db.types # revision identifiers, used by Alembic. -revision: str = "478cb2e9eb55" +revision: str = "f69bb778caa6" down_revision: Union[str, None] = None branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None @@ -108,6 +108,7 @@ def upgrade() -> None: sa.Enum( "analysis_software_source_code", "brain_atlas", + "brain_atlas_region", "emodel", "cell_composition", "experimental_bouton_density", @@ -268,7 +269,6 @@ def upgrade() -> None: op.create_table( "license", sa.Column("name", sa.String(), nullable=False), - sa.Column("description", sa.String(), nullable=False), sa.Column("label", sa.String(), nullable=False), sa.Column("legacy_id", sa.ARRAY(sa.VARCHAR()), nullable=True), sa.Column("legacy_self", sa.ARRAY(sa.VARCHAR()), nullable=True), @@ -285,9 +285,18 @@ def upgrade() -> None: server_default=sa.text("now()"), nullable=False, ), + sa.Column("description", sa.String(), nullable=False), + sa.Column("description_vector", postgresql.TSVECTOR(), nullable=True), sa.PrimaryKeyConstraint("id", name=op.f("pk_license")), ) op.create_index(op.f("ix_license_creation_date"), "license", ["creation_date"], unique=False) + op.create_index( + "ix_license_description_vector", + "license", + ["description_vector"], + unique=False, + postgresql_using="gin", + ) op.create_index(op.f("ix_license_legacy_id"), "license", ["legacy_id"], unique=False) op.create_index(op.f("ix_license_name"), "license", ["name"], unique=True) op.create_table( @@ -438,6 +447,7 @@ def upgrade() -> None: postgresql.ENUM( "analysis_software_source_code", "brain_atlas", + "brain_atlas_region", "emodel", "cell_composition", "experimental_bouton_density", @@ -669,16 +679,16 @@ def upgrade() -> None: op.create_table( "brain_atlas", sa.Column("id", sa.Uuid(), nullable=False), + sa.Column("hierarchy_id", sa.Uuid(), nullable=False), sa.Column("name", sa.String(), nullable=False), sa.Column("description", sa.String(), nullable=False), sa.Column("description_vector", postgresql.TSVECTOR(), nullable=True), - sa.Column("brain_region_id", sa.Uuid(), nullable=False), sa.Column("species_id", sa.Uuid(), nullable=False), sa.Column("strain_id", sa.Uuid(), nullable=True), sa.ForeignKeyConstraint( - ["brain_region_id"], - ["brain_region.id"], - name=op.f("fk_brain_atlas_brain_region_id_brain_region"), + ["hierarchy_id"], + ["brain_region_hierarchy.id"], + name=op.f("fk_brain_atlas_hierarchy_id_brain_region_hierarchy"), ), sa.ForeignKeyConstraint(["id"], ["entity.id"], name=op.f("fk_brain_atlas_id_entity")), sa.ForeignKeyConstraint( @@ -691,9 +701,6 @@ def upgrade() -> None: ), sa.PrimaryKeyConstraint("id", name=op.f("pk_brain_atlas")), ) - op.create_index( - op.f("ix_brain_atlas_brain_region_id"), "brain_atlas", ["brain_region_id"], unique=False - ) op.create_index( "ix_brain_atlas_description_vector", "brain_atlas", @@ -701,6 +708,9 @@ def upgrade() -> None: unique=False, postgresql_using="gin", ) + op.create_index( + op.f("ix_brain_atlas_hierarchy_id"), "brain_atlas", ["hierarchy_id"], unique=False + ) op.create_index(op.f("ix_brain_atlas_name"), "brain_atlas", ["name"], unique=False) op.create_index(op.f("ix_brain_atlas_species_id"), "brain_atlas", ["species_id"], unique=False) op.create_index(op.f("ix_brain_atlas_strain_id"), "brain_atlas", ["strain_id"], unique=False) @@ -1039,30 +1049,6 @@ def upgrade() -> None: op.create_index( op.f("ix_measurement_record_entity_id"), "measurement_record", ["entity_id"], unique=False ) - op.create_table( - "mesh", - sa.Column("id", sa.Uuid(), nullable=False), - sa.Column("brain_region_id", sa.Uuid(), nullable=False), - sa.Column("name", sa.String(), nullable=False), - sa.Column("description", sa.String(), nullable=False), - sa.Column("description_vector", postgresql.TSVECTOR(), nullable=True), - sa.ForeignKeyConstraint( - ["brain_region_id"], - ["brain_region.id"], - name=op.f("fk_mesh_brain_region_id_brain_region"), - ), - sa.ForeignKeyConstraint(["id"], ["entity.id"], name=op.f("fk_mesh_id_entity")), - sa.PrimaryKeyConstraint("id", name=op.f("pk_mesh")), - ) - op.create_index(op.f("ix_mesh_brain_region_id"), "mesh", ["brain_region_id"], unique=False) - op.create_index( - "ix_mesh_description_vector", - "mesh", - ["description_vector"], - unique=False, - postgresql_using="gin", - ) - op.create_index(op.f("ix_mesh_name"), "mesh", ["name"], unique=False) op.create_table( "mtype_classification", sa.Column("mtype_class_id", sa.Uuid(), nullable=False), @@ -1271,6 +1257,40 @@ def upgrade() -> None: ["validated_entity_id"], unique=False, ) + op.create_table( + "brain_atlas_region", + sa.Column("id", sa.Uuid(), nullable=False), + sa.Column("volume", sa.Float(), nullable=True), + sa.Column("is_leaf_region", sa.Boolean(), nullable=False), + sa.Column("brain_atlas_id", sa.Uuid(), nullable=False), + sa.Column("brain_region_id", sa.Uuid(), nullable=False), + sa.ForeignKeyConstraint( + ["brain_atlas_id"], + ["brain_atlas.id"], + name=op.f("fk_brain_atlas_region_brain_atlas_id_brain_atlas"), + ), + sa.ForeignKeyConstraint( + ["brain_region_id"], + ["brain_region.id"], + name=op.f("fk_brain_atlas_region_brain_region_id_brain_region"), + ), + sa.ForeignKeyConstraint( + ["id"], ["entity.id"], name=op.f("fk_brain_atlas_region_id_entity") + ), + sa.PrimaryKeyConstraint("id", name=op.f("pk_brain_atlas_region")), + ) + op.create_index( + op.f("ix_brain_atlas_region_brain_atlas_id"), + "brain_atlas_region", + ["brain_atlas_id"], + unique=False, + ) + op.create_index( + op.f("ix_brain_atlas_region_brain_region_id"), + "brain_atlas_region", + ["brain_region_id"], + unique=False, + ) op.create_table( "electrical_cell_recording", sa.Column("id", sa.Uuid(), nullable=False), @@ -1678,8 +1698,6 @@ def upgrade() -> None: op.create_table( "electrical_recording_stimulus", sa.Column("id", sa.Uuid(), nullable=False), - sa.Column("name", sa.String(), nullable=False), - sa.Column("description", sa.String(), nullable=False), sa.Column("dt", sa.Float(), nullable=True), sa.Column( "injection_type", @@ -1716,6 +1734,9 @@ def upgrade() -> None: sa.Column("start_time", sa.Float(), nullable=True), sa.Column("end_time", sa.Float(), nullable=True), sa.Column("recording_id", sa.Uuid(), nullable=False), + sa.Column("name", sa.String(), nullable=False), + sa.Column("description", sa.String(), nullable=False), + sa.Column("description_vector", postgresql.TSVECTOR(), nullable=True), sa.ForeignKeyConstraint( ["id"], ["entity.id"], name=op.f("fk_electrical_recording_stimulus_id_entity") ), @@ -1726,6 +1747,19 @@ def upgrade() -> None: ), sa.PrimaryKeyConstraint("id", name=op.f("pk_electrical_recording_stimulus")), ) + op.create_index( + "ix_electrical_recording_stimulus_description_vector", + "electrical_recording_stimulus", + ["description_vector"], + unique=False, + postgresql_using="gin", + ) + op.create_index( + op.f("ix_electrical_recording_stimulus_name"), + "electrical_recording_stimulus", + ["name"], + unique=False, + ) op.create_index( op.f("ix_electrical_recording_stimulus_recording_id"), "electrical_recording_stimulus", @@ -1812,6 +1846,7 @@ def upgrade() -> None: ["measurement_kind_id"], unique=False, ) + op.create_index(op.f("ix_measurement_item_value"), "measurement_item", ["value"], unique=False) op.create_table( "memodel", sa.Column("id", sa.Uuid(), nullable=False), @@ -2097,6 +2132,7 @@ def downgrade() -> None: op.drop_index("ix_memodel_description_vector", table_name="memodel", postgresql_using="gin") op.drop_index(op.f("ix_memodel_brain_region_id"), table_name="memodel") op.drop_table("memodel") + op.drop_index(op.f("ix_measurement_item_value"), table_name="measurement_item") op.drop_index(op.f("ix_measurement_item_measurement_kind_id"), table_name="measurement_item") op.drop_table("measurement_item") op.drop_table("ion_channel_model__emodel") @@ -2104,6 +2140,14 @@ def downgrade() -> None: op.f("ix_electrical_recording_stimulus_recording_id"), table_name="electrical_recording_stimulus", ) + op.drop_index( + op.f("ix_electrical_recording_stimulus_name"), table_name="electrical_recording_stimulus" + ) + op.drop_index( + "ix_electrical_recording_stimulus_description_vector", + table_name="electrical_recording_stimulus", + postgresql_using="gin", + ) op.drop_table("electrical_recording_stimulus") op.drop_index(op.f("ix_measurement_kind_pref_label"), table_name="measurement_kind") op.drop_index( @@ -2208,6 +2252,9 @@ def downgrade() -> None: op.f("ix_electrical_cell_recording_brain_region_id"), table_name="electrical_cell_recording" ) op.drop_table("electrical_cell_recording") + op.drop_index(op.f("ix_brain_atlas_region_brain_region_id"), table_name="brain_atlas_region") + op.drop_index(op.f("ix_brain_atlas_region_brain_atlas_id"), table_name="brain_atlas_region") + op.drop_table("brain_atlas_region") op.drop_index(op.f("ix_validation_result_validated_entity_id"), table_name="validation_result") op.drop_index(op.f("ix_validation_result_name"), table_name="validation_result") op.drop_table("validation_result") @@ -2241,10 +2288,6 @@ def downgrade() -> None: op.drop_index(op.f("ix_mtype_classification_creation_date"), table_name="mtype_classification") op.drop_index(op.f("ix_mtype_classification_created_by_id"), table_name="mtype_classification") op.drop_table("mtype_classification") - op.drop_index(op.f("ix_mesh_name"), table_name="mesh") - op.drop_index("ix_mesh_description_vector", table_name="mesh", postgresql_using="gin") - op.drop_index(op.f("ix_mesh_brain_region_id"), table_name="mesh") - op.drop_table("mesh") op.drop_index(op.f("ix_measurement_record_entity_id"), table_name="measurement_record") op.drop_table("measurement_record") op.drop_index(op.f("ix_measurement_annotation_legacy_id"), table_name="measurement_annotation") @@ -2297,10 +2340,10 @@ def downgrade() -> None: op.drop_index(op.f("ix_brain_atlas_strain_id"), table_name="brain_atlas") op.drop_index(op.f("ix_brain_atlas_species_id"), table_name="brain_atlas") op.drop_index(op.f("ix_brain_atlas_name"), table_name="brain_atlas") + op.drop_index(op.f("ix_brain_atlas_hierarchy_id"), table_name="brain_atlas") op.drop_index( "ix_brain_atlas_description_vector", table_name="brain_atlas", postgresql_using="gin" ) - op.drop_index(op.f("ix_brain_atlas_brain_region_id"), table_name="brain_atlas") op.drop_table("brain_atlas") op.drop_index( "ix_asset_full_path", table_name="asset", postgresql_where=sa.text("status != 'DELETED'") @@ -2362,6 +2405,7 @@ def downgrade() -> None: op.drop_table("mtype_class") op.drop_index(op.f("ix_license_name"), table_name="license") op.drop_index(op.f("ix_license_legacy_id"), table_name="license") + op.drop_index("ix_license_description_vector", table_name="license", postgresql_using="gin") op.drop_index(op.f("ix_license_creation_date"), table_name="license") op.drop_table("license") op.drop_index(op.f("ix_ion_ontology_id"), table_name="ion") @@ -2389,6 +2433,7 @@ def downgrade() -> None: sa.Enum( "analysis_software_source_code", "brain_atlas", + "brain_atlas_region", "emodel", "cell_composition", "experimental_bouton_density", diff --git a/alembic/versions/20250521_160604_719dc38efbd6_trigeers.py b/alembic/versions/20250526_121330_698536102bc8_triggers.py similarity index 92% rename from alembic/versions/20250521_160604_719dc38efbd6_trigeers.py rename to alembic/versions/20250526_121330_698536102bc8_triggers.py index ec9d1ee2..96d0e021 100644 --- a/alembic/versions/20250521_160604_719dc38efbd6_trigeers.py +++ b/alembic/versions/20250526_121330_698536102bc8_triggers.py @@ -1,8 +1,8 @@ -"""trigeers +"""triggers -Revision ID: 719dc38efbd6 -Revises: 478cb2e9eb55 -Create Date: 2025-05-21 16:06:04.722345 +Revision ID: 698536102bc8 +Revises: f69bb778caa6 +Create Date: 2025-05-26 12:13:30.928701 """ @@ -19,49 +19,62 @@ import app.db.types # revision identifiers, used by Alembic. -revision: str = "719dc38efbd6" -down_revision: Union[str, None] = "478cb2e9eb55" +revision: str = "698536102bc8" +down_revision: Union[str, None] = "f69bb778caa6" branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: # ### commands auto generated by Alembic - please adjust! ### - public_cell_composition_cell_composition_description_vector = PGTrigger( + public_ion_channel_model_ion_channel_model_description_vector = PGTrigger( schema="public", - signature="cell_composition_description_vector", - on_entity="public.cell_composition", + signature="ion_channel_model_description_vector", + on_entity="public.ion_channel_model", is_constraint=False, - definition="BEFORE INSERT OR UPDATE ON cell_composition\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", + definition="BEFORE INSERT OR UPDATE ON ion_channel_model\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", ) - op.create_entity(public_cell_composition_cell_composition_description_vector) + op.create_entity(public_ion_channel_model_ion_channel_model_description_vector) - public_electrical_cell_recording_electrical_cell_recording_description_vector = PGTrigger( + public_electrical_recording_stimulus_electrical_recording_stimulus_description_vector = PGTrigger( schema="public", - signature="electrical_cell_recording_description_vector", - on_entity="public.electrical_cell_recording", + signature="electrical_recording_stimulus_description_vector", + on_entity="public.electrical_recording_stimulus", is_constraint=False, - definition="BEFORE INSERT OR UPDATE ON electrical_cell_recording\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", + definition="BEFORE INSERT OR UPDATE ON electrical_recording_stimulus\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", + ) + op.create_entity( + public_electrical_recording_stimulus_electrical_recording_stimulus_description_vector ) - op.create_entity(public_electrical_cell_recording_electrical_cell_recording_description_vector) - public_memodel_memodel_description_vector = PGTrigger( + public_single_neuron_simulation_single_neuron_simulation_description_vector = PGTrigger( schema="public", - signature="memodel_description_vector", - on_entity="public.memodel", + signature="single_neuron_simulation_description_vector", + on_entity="public.single_neuron_simulation", is_constraint=False, - definition="BEFORE INSERT OR UPDATE ON memodel\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", + definition="BEFORE INSERT OR UPDATE ON single_neuron_simulation\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", ) - op.create_entity(public_memodel_memodel_description_vector) + op.create_entity(public_single_neuron_simulation_single_neuron_simulation_description_vector) - public_single_neuron_synaptome_single_neuron_synaptome_description_vector = PGTrigger( + public_experimental_neuron_density_experimental_neuron_density_description_vector = PGTrigger( schema="public", - signature="single_neuron_synaptome_description_vector", - on_entity="public.single_neuron_synaptome", + signature="experimental_neuron_density_description_vector", + on_entity="public.experimental_neuron_density", is_constraint=False, - definition="BEFORE INSERT OR UPDATE ON single_neuron_synaptome\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", + definition="BEFORE INSERT OR UPDATE ON experimental_neuron_density\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", ) - op.create_entity(public_single_neuron_synaptome_single_neuron_synaptome_description_vector) + op.create_entity( + public_experimental_neuron_density_experimental_neuron_density_description_vector + ) + + public_cell_composition_cell_composition_description_vector = PGTrigger( + schema="public", + signature="cell_composition_description_vector", + on_entity="public.cell_composition", + is_constraint=False, + definition="BEFORE INSERT OR UPDATE ON cell_composition\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", + ) + op.create_entity(public_cell_composition_cell_composition_description_vector) public_reconstruction_morphology_reconstruction_morphology_description_vector = PGTrigger( schema="public", @@ -72,17 +85,6 @@ def upgrade() -> None: ) op.create_entity(public_reconstruction_morphology_reconstruction_morphology_description_vector) - public_single_neuron_synaptome_simulation_single_neuron_synaptome_simulation_description_vector = PGTrigger( - schema="public", - signature="single_neuron_synaptome_simulation_description_vector", - on_entity="public.single_neuron_synaptome_simulation", - is_constraint=False, - definition="BEFORE INSERT OR UPDATE ON single_neuron_synaptome_simulation\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", - ) - op.create_entity( - public_single_neuron_synaptome_simulation_single_neuron_synaptome_simulation_description_vector - ) - public_me_type_density_me_type_density_description_vector = PGTrigger( schema="public", signature="me_type_density_description_vector", @@ -92,14 +94,14 @@ def upgrade() -> None: ) op.create_entity(public_me_type_density_me_type_density_description_vector) - public_brain_atlas_brain_atlas_description_vector = PGTrigger( + public_license_license_description_vector = PGTrigger( schema="public", - signature="brain_atlas_description_vector", - on_entity="public.brain_atlas", + signature="license_description_vector", + on_entity="public.license", is_constraint=False, - definition="BEFORE INSERT OR UPDATE ON brain_atlas\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", + definition="BEFORE INSERT OR UPDATE ON license\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", ) - op.create_entity(public_brain_atlas_brain_atlas_description_vector) + op.create_entity(public_license_license_description_vector) public_subject_subject_description_vector = PGTrigger( schema="public", @@ -110,47 +112,43 @@ def upgrade() -> None: ) op.create_entity(public_subject_subject_description_vector) - public_experimental_bouton_density_experimental_bouton_density_description_vector = PGTrigger( + public_electrical_cell_recording_electrical_cell_recording_description_vector = PGTrigger( schema="public", - signature="experimental_bouton_density_description_vector", - on_entity="public.experimental_bouton_density", + signature="electrical_cell_recording_description_vector", + on_entity="public.electrical_cell_recording", is_constraint=False, - definition="BEFORE INSERT OR UPDATE ON experimental_bouton_density\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", - ) - op.create_entity( - public_experimental_bouton_density_experimental_bouton_density_description_vector + definition="BEFORE INSERT OR UPDATE ON electrical_cell_recording\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", ) + op.create_entity(public_electrical_cell_recording_electrical_cell_recording_description_vector) - public_single_neuron_simulation_single_neuron_simulation_description_vector = PGTrigger( + public_analysis_software_source_code_analysis_software_source_code_description_vector = PGTrigger( schema="public", - signature="single_neuron_simulation_description_vector", - on_entity="public.single_neuron_simulation", + signature="analysis_software_source_code_description_vector", + on_entity="public.analysis_software_source_code", is_constraint=False, - definition="BEFORE INSERT OR UPDATE ON single_neuron_simulation\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", + definition="BEFORE INSERT OR UPDATE ON analysis_software_source_code\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", + ) + op.create_entity( + public_analysis_software_source_code_analysis_software_source_code_description_vector ) - op.create_entity(public_single_neuron_simulation_single_neuron_simulation_description_vector) - public_experimental_synapses_per_connection_experimental_synapses_per_connection_description_vector = PGTrigger( + public_memodel_memodel_description_vector = PGTrigger( schema="public", - signature="experimental_synapses_per_connection_description_vector", - on_entity="public.experimental_synapses_per_connection", + signature="memodel_description_vector", + on_entity="public.memodel", is_constraint=False, - definition="BEFORE INSERT OR UPDATE ON experimental_synapses_per_connection\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", - ) - op.create_entity( - public_experimental_synapses_per_connection_experimental_synapses_per_connection_description_vector + definition="BEFORE INSERT OR UPDATE ON memodel\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", ) + op.create_entity(public_memodel_memodel_description_vector) - public_analysis_software_source_code_analysis_software_source_code_description_vector = PGTrigger( + public_single_neuron_synaptome_single_neuron_synaptome_description_vector = PGTrigger( schema="public", - signature="analysis_software_source_code_description_vector", - on_entity="public.analysis_software_source_code", + signature="single_neuron_synaptome_description_vector", + on_entity="public.single_neuron_synaptome", is_constraint=False, - definition="BEFORE INSERT OR UPDATE ON analysis_software_source_code\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", - ) - op.create_entity( - public_analysis_software_source_code_analysis_software_source_code_description_vector + definition="BEFORE INSERT OR UPDATE ON single_neuron_synaptome\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", ) + op.create_entity(public_single_neuron_synaptome_single_neuron_synaptome_description_vector) public_emodel_emodel_description_vector = PGTrigger( schema="public", @@ -161,33 +159,46 @@ def upgrade() -> None: ) op.create_entity(public_emodel_emodel_description_vector) - public_ion_channel_model_ion_channel_model_description_vector = PGTrigger( + public_brain_atlas_brain_atlas_description_vector = PGTrigger( schema="public", - signature="ion_channel_model_description_vector", - on_entity="public.ion_channel_model", + signature="brain_atlas_description_vector", + on_entity="public.brain_atlas", is_constraint=False, - definition="BEFORE INSERT OR UPDATE ON ion_channel_model\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", + definition="BEFORE INSERT OR UPDATE ON brain_atlas\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", ) - op.create_entity(public_ion_channel_model_ion_channel_model_description_vector) + op.create_entity(public_brain_atlas_brain_atlas_description_vector) - public_mesh_mesh_description_vector = PGTrigger( + public_single_neuron_synaptome_simulation_single_neuron_synaptome_simulation_description_vector = PGTrigger( schema="public", - signature="mesh_description_vector", - on_entity="public.mesh", + signature="single_neuron_synaptome_simulation_description_vector", + on_entity="public.single_neuron_synaptome_simulation", is_constraint=False, - definition="BEFORE INSERT OR UPDATE ON mesh\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", + definition="BEFORE INSERT OR UPDATE ON single_neuron_synaptome_simulation\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", + ) + op.create_entity( + public_single_neuron_synaptome_simulation_single_neuron_synaptome_simulation_description_vector ) - op.create_entity(public_mesh_mesh_description_vector) - public_experimental_neuron_density_experimental_neuron_density_description_vector = PGTrigger( + public_experimental_bouton_density_experimental_bouton_density_description_vector = PGTrigger( schema="public", - signature="experimental_neuron_density_description_vector", - on_entity="public.experimental_neuron_density", + signature="experimental_bouton_density_description_vector", + on_entity="public.experimental_bouton_density", is_constraint=False, - definition="BEFORE INSERT OR UPDATE ON experimental_neuron_density\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", + definition="BEFORE INSERT OR UPDATE ON experimental_bouton_density\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", ) op.create_entity( - public_experimental_neuron_density_experimental_neuron_density_description_vector + public_experimental_bouton_density_experimental_bouton_density_description_vector + ) + + public_experimental_synapses_per_connection_experimental_synapses_per_connection_description_vector = PGTrigger( + schema="public", + signature="experimental_synapses_per_connection_description_vector", + on_entity="public.experimental_synapses_per_connection", + is_constraint=False, + definition="BEFORE INSERT OR UPDATE ON experimental_synapses_per_connection\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", + ) + op.create_entity( + public_experimental_synapses_per_connection_experimental_synapses_per_connection_description_vector ) public_unauthorized_private_reference_function_emodel_exemplar_morphology_id_reconstruction_morphology = PGFunction( @@ -307,34 +318,47 @@ def downgrade() -> None: public_unauthorized_private_reference_function_emodel_exemplar_morphology_id_reconstruction_morphology ) - public_experimental_neuron_density_experimental_neuron_density_description_vector = PGTrigger( + public_experimental_synapses_per_connection_experimental_synapses_per_connection_description_vector = PGTrigger( schema="public", - signature="experimental_neuron_density_description_vector", - on_entity="public.experimental_neuron_density", + signature="experimental_synapses_per_connection_description_vector", + on_entity="public.experimental_synapses_per_connection", is_constraint=False, - definition="BEFORE INSERT OR UPDATE ON experimental_neuron_density\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", + definition="BEFORE INSERT OR UPDATE ON experimental_synapses_per_connection\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", ) op.drop_entity( - public_experimental_neuron_density_experimental_neuron_density_description_vector + public_experimental_synapses_per_connection_experimental_synapses_per_connection_description_vector ) - public_mesh_mesh_description_vector = PGTrigger( + public_experimental_bouton_density_experimental_bouton_density_description_vector = PGTrigger( schema="public", - signature="mesh_description_vector", - on_entity="public.mesh", + signature="experimental_bouton_density_description_vector", + on_entity="public.experimental_bouton_density", is_constraint=False, - definition="BEFORE INSERT OR UPDATE ON mesh\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", + definition="BEFORE INSERT OR UPDATE ON experimental_bouton_density\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", + ) + op.drop_entity( + public_experimental_bouton_density_experimental_bouton_density_description_vector ) - op.drop_entity(public_mesh_mesh_description_vector) - public_ion_channel_model_ion_channel_model_description_vector = PGTrigger( + public_single_neuron_synaptome_simulation_single_neuron_synaptome_simulation_description_vector = PGTrigger( schema="public", - signature="ion_channel_model_description_vector", - on_entity="public.ion_channel_model", + signature="single_neuron_synaptome_simulation_description_vector", + on_entity="public.single_neuron_synaptome_simulation", is_constraint=False, - definition="BEFORE INSERT OR UPDATE ON ion_channel_model\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", + definition="BEFORE INSERT OR UPDATE ON single_neuron_synaptome_simulation\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", ) - op.drop_entity(public_ion_channel_model_ion_channel_model_description_vector) + op.drop_entity( + public_single_neuron_synaptome_simulation_single_neuron_synaptome_simulation_description_vector + ) + + public_brain_atlas_brain_atlas_description_vector = PGTrigger( + schema="public", + signature="brain_atlas_description_vector", + on_entity="public.brain_atlas", + is_constraint=False, + definition="BEFORE INSERT OR UPDATE ON brain_atlas\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", + ) + op.drop_entity(public_brain_atlas_brain_atlas_description_vector) public_emodel_emodel_description_vector = PGTrigger( schema="public", @@ -345,47 +369,43 @@ def downgrade() -> None: ) op.drop_entity(public_emodel_emodel_description_vector) - public_analysis_software_source_code_analysis_software_source_code_description_vector = PGTrigger( + public_single_neuron_synaptome_single_neuron_synaptome_description_vector = PGTrigger( schema="public", - signature="analysis_software_source_code_description_vector", - on_entity="public.analysis_software_source_code", + signature="single_neuron_synaptome_description_vector", + on_entity="public.single_neuron_synaptome", is_constraint=False, - definition="BEFORE INSERT OR UPDATE ON analysis_software_source_code\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", - ) - op.drop_entity( - public_analysis_software_source_code_analysis_software_source_code_description_vector + definition="BEFORE INSERT OR UPDATE ON single_neuron_synaptome\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", ) + op.drop_entity(public_single_neuron_synaptome_single_neuron_synaptome_description_vector) - public_experimental_synapses_per_connection_experimental_synapses_per_connection_description_vector = PGTrigger( + public_memodel_memodel_description_vector = PGTrigger( schema="public", - signature="experimental_synapses_per_connection_description_vector", - on_entity="public.experimental_synapses_per_connection", + signature="memodel_description_vector", + on_entity="public.memodel", is_constraint=False, - definition="BEFORE INSERT OR UPDATE ON experimental_synapses_per_connection\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", - ) - op.drop_entity( - public_experimental_synapses_per_connection_experimental_synapses_per_connection_description_vector + definition="BEFORE INSERT OR UPDATE ON memodel\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", ) + op.drop_entity(public_memodel_memodel_description_vector) - public_single_neuron_simulation_single_neuron_simulation_description_vector = PGTrigger( + public_analysis_software_source_code_analysis_software_source_code_description_vector = PGTrigger( schema="public", - signature="single_neuron_simulation_description_vector", - on_entity="public.single_neuron_simulation", + signature="analysis_software_source_code_description_vector", + on_entity="public.analysis_software_source_code", is_constraint=False, - definition="BEFORE INSERT OR UPDATE ON single_neuron_simulation\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", + definition="BEFORE INSERT OR UPDATE ON analysis_software_source_code\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", + ) + op.drop_entity( + public_analysis_software_source_code_analysis_software_source_code_description_vector ) - op.drop_entity(public_single_neuron_simulation_single_neuron_simulation_description_vector) - public_experimental_bouton_density_experimental_bouton_density_description_vector = PGTrigger( + public_electrical_cell_recording_electrical_cell_recording_description_vector = PGTrigger( schema="public", - signature="experimental_bouton_density_description_vector", - on_entity="public.experimental_bouton_density", + signature="electrical_cell_recording_description_vector", + on_entity="public.electrical_cell_recording", is_constraint=False, - definition="BEFORE INSERT OR UPDATE ON experimental_bouton_density\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", - ) - op.drop_entity( - public_experimental_bouton_density_experimental_bouton_density_description_vector + definition="BEFORE INSERT OR UPDATE ON electrical_cell_recording\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", ) + op.drop_entity(public_electrical_cell_recording_electrical_cell_recording_description_vector) public_subject_subject_description_vector = PGTrigger( schema="public", @@ -396,14 +416,14 @@ def downgrade() -> None: ) op.drop_entity(public_subject_subject_description_vector) - public_brain_atlas_brain_atlas_description_vector = PGTrigger( + public_license_license_description_vector = PGTrigger( schema="public", - signature="brain_atlas_description_vector", - on_entity="public.brain_atlas", + signature="license_description_vector", + on_entity="public.license", is_constraint=False, - definition="BEFORE INSERT OR UPDATE ON brain_atlas\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", + definition="BEFORE INSERT OR UPDATE ON license\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", ) - op.drop_entity(public_brain_atlas_brain_atlas_description_vector) + op.drop_entity(public_license_license_description_vector) public_me_type_density_me_type_density_description_vector = PGTrigger( schema="public", @@ -414,17 +434,6 @@ def downgrade() -> None: ) op.drop_entity(public_me_type_density_me_type_density_description_vector) - public_single_neuron_synaptome_simulation_single_neuron_synaptome_simulation_description_vector = PGTrigger( - schema="public", - signature="single_neuron_synaptome_simulation_description_vector", - on_entity="public.single_neuron_synaptome_simulation", - is_constraint=False, - definition="BEFORE INSERT OR UPDATE ON single_neuron_synaptome_simulation\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", - ) - op.drop_entity( - public_single_neuron_synaptome_simulation_single_neuron_synaptome_simulation_description_vector - ) - public_reconstruction_morphology_reconstruction_morphology_description_vector = PGTrigger( schema="public", signature="reconstruction_morphology_description_vector", @@ -434,40 +443,53 @@ def downgrade() -> None: ) op.drop_entity(public_reconstruction_morphology_reconstruction_morphology_description_vector) - public_single_neuron_synaptome_single_neuron_synaptome_description_vector = PGTrigger( + public_cell_composition_cell_composition_description_vector = PGTrigger( schema="public", - signature="single_neuron_synaptome_description_vector", - on_entity="public.single_neuron_synaptome", + signature="cell_composition_description_vector", + on_entity="public.cell_composition", is_constraint=False, - definition="BEFORE INSERT OR UPDATE ON single_neuron_synaptome\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", + definition="BEFORE INSERT OR UPDATE ON cell_composition\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", ) - op.drop_entity(public_single_neuron_synaptome_single_neuron_synaptome_description_vector) + op.drop_entity(public_cell_composition_cell_composition_description_vector) - public_memodel_memodel_description_vector = PGTrigger( + public_experimental_neuron_density_experimental_neuron_density_description_vector = PGTrigger( schema="public", - signature="memodel_description_vector", - on_entity="public.memodel", + signature="experimental_neuron_density_description_vector", + on_entity="public.experimental_neuron_density", is_constraint=False, - definition="BEFORE INSERT OR UPDATE ON memodel\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", + definition="BEFORE INSERT OR UPDATE ON experimental_neuron_density\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", + ) + op.drop_entity( + public_experimental_neuron_density_experimental_neuron_density_description_vector ) - op.drop_entity(public_memodel_memodel_description_vector) - public_electrical_cell_recording_electrical_cell_recording_description_vector = PGTrigger( + public_single_neuron_simulation_single_neuron_simulation_description_vector = PGTrigger( schema="public", - signature="electrical_cell_recording_description_vector", - on_entity="public.electrical_cell_recording", + signature="single_neuron_simulation_description_vector", + on_entity="public.single_neuron_simulation", is_constraint=False, - definition="BEFORE INSERT OR UPDATE ON electrical_cell_recording\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", + definition="BEFORE INSERT OR UPDATE ON single_neuron_simulation\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", ) - op.drop_entity(public_electrical_cell_recording_electrical_cell_recording_description_vector) + op.drop_entity(public_single_neuron_simulation_single_neuron_simulation_description_vector) - public_cell_composition_cell_composition_description_vector = PGTrigger( + public_electrical_recording_stimulus_electrical_recording_stimulus_description_vector = PGTrigger( schema="public", - signature="cell_composition_description_vector", - on_entity="public.cell_composition", + signature="electrical_recording_stimulus_description_vector", + on_entity="public.electrical_recording_stimulus", is_constraint=False, - definition="BEFORE INSERT OR UPDATE ON cell_composition\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", + definition="BEFORE INSERT OR UPDATE ON electrical_recording_stimulus\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", ) - op.drop_entity(public_cell_composition_cell_composition_description_vector) + op.drop_entity( + public_electrical_recording_stimulus_electrical_recording_stimulus_description_vector + ) + + public_ion_channel_model_ion_channel_model_description_vector = PGTrigger( + schema="public", + signature="ion_channel_model_description_vector", + on_entity="public.ion_channel_model", + is_constraint=False, + definition="BEFORE INSERT OR UPDATE ON ion_channel_model\n FOR EACH ROW EXECUTE FUNCTION\n tsvector_update_trigger(description_vector, 'pg_catalog.english', description, name)", + ) + op.drop_entity(public_ion_channel_model_ion_channel_model_description_vector) # ### end Alembic commands ### diff --git a/app/cli/import_data.py b/app/cli/import_data.py index fb15d8bb..1b8e49ce 100644 --- a/app/cli/import_data.py +++ b/app/cli/import_data.py @@ -630,18 +630,18 @@ def ingest(db, project_context, data_list, all_data_by_id, hierarchy_name: str): if atlas_region is None: annotation_id = curate.curate_brain_region(brain_region_data)["@id"] - volume = -1_000_000_000 + volume = None - leaf_region = False + is_leaf_region = False if annotation_id in BRAIN_ATLAS_REGION_VOLUMES: volume = BRAIN_ATLAS_REGION_VOLUMES[annotation_id] - leaf_region = True + is_leaf_region = True atlas_region = BrainAtlasRegion( brain_atlas_id=brain_atlas.id, brain_region_id=brain_region_id, volume=volume, - leaf_region=leaf_region, + is_leaf_region=is_leaf_region, authorized_project_id=project_context.project_id, authorized_public=True, ) diff --git a/app/db/model.py b/app/db/model.py index 1012ff08..50f427a0 100644 --- a/app/db/model.py +++ b/app/db/model.py @@ -885,8 +885,8 @@ class BrainAtlasRegion(Entity, LocationMixin): # only the volume for leaf nodes is saved; the consumer must calculate # volumes depending on which view of the hierarchy they are using - volume: Mapped[float] = mapped_column(nullable=True) - leaf_region: Mapped[bool] = mapped_column(default=False) + volume: Mapped[float | None] + is_leaf_region: Mapped[bool] = mapped_column(default=False) brain_atlas_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("brain_atlas.id"), index=True) diff --git a/app/schemas/brain_atlas.py b/app/schemas/brain_atlas.py index 820c6d21..236bac8d 100644 --- a/app/schemas/brain_atlas.py +++ b/app/schemas/brain_atlas.py @@ -20,8 +20,8 @@ class BrainAtlasRead(BrainAtlasBase, CreationMixin, IdentifiableMixin): class BrainAtlasRegionBase(BaseModel): model_config = ConfigDict(from_attributes=True) - volume: float - leaf_region: bool + volume: float | None + is_leaf_region: bool brain_atlas_id: uuid.UUID brain_region_id: uuid.UUID diff --git a/tests/test_brain_atlas.py b/tests/test_brain_atlas.py index 191a66e9..e1b4fb67 100644 --- a/tests/test_brain_atlas.py +++ b/tests/test_brain_atlas.py @@ -1,8 +1,6 @@ import itertools as it from unittest.mock import ANY -import pytest - from app.db.model import BrainAtlas, BrainAtlasRegion from . import utils @@ -46,11 +44,6 @@ } -@pytest.fixture -def asdf(): - pass - - def test_brain_atlas(db, client, species_id): hierarchy_name = utils.create_hiearchy_name(db, "test_hierarchy") regions = utils.add_brain_region_hierarchy(db, HIERARCHY, hierarchy_name.id) @@ -103,7 +96,7 @@ def test_brain_atlas(db, client, species_id): response = response.json() assert response == expected - data = (("root", False, -1), ("blue", False, -1), ("red", True, 15), ("grey", True, 10)) + data = (("root", False, None), ("blue", False, None), ("red", True, 15), ("grey", True, 10)) ids = {} for brain_atlas, (name, leaf, volume) in it.product( ( @@ -114,7 +107,7 @@ def test_brain_atlas(db, client, species_id): ): row = BrainAtlasRegion( volume=volume, - leaf_region=leaf, + is_leaf_region=leaf, brain_region_id=regions[name].id, brain_atlas_id=brain_atlas.id, authorized_project_id=utils.PROJECT_ID, @@ -132,25 +125,25 @@ def test_brain_atlas(db, client, species_id): "brain_region_id": str(regions["root"].id), "creation_date": ANY, "id": str(ids[brain_atlas0.name, "root"].id), - "leaf_region": False, + "is_leaf_region": False, "update_date": ANY, - "volume": -1.0, + "volume": None, }, { "brain_atlas_id": str(brain_atlas0.id), "brain_region_id": str(regions["blue"].id), "creation_date": ANY, "id": str(ids[brain_atlas0.name, "blue"].id), - "leaf_region": False, + "is_leaf_region": False, "update_date": ANY, - "volume": -1.0, + "volume": None, }, { "brain_atlas_id": str(brain_atlas0.id), "brain_region_id": str(regions["red"].id), "creation_date": ANY, "id": str(ids[brain_atlas0.name, "red"].id), - "leaf_region": True, + "is_leaf_region": True, "update_date": ANY, "volume": 15.0, }, @@ -159,7 +152,7 @@ def test_brain_atlas(db, client, species_id): "brain_region_id": str(regions["grey"].id), "creation_date": ANY, "id": str(ids[brain_atlas0.name, "grey"].id), - "leaf_region": True, + "is_leaf_region": True, "update_date": ANY, "volume": 10.0, }, @@ -172,7 +165,7 @@ def test_brain_atlas(db, client, species_id): "brain_region_id": str(regions["root"].id), "creation_date": ANY, "id": str(ids[brain_atlas0.name, "root"].id), - "leaf_region": False, + "is_leaf_region": False, "update_date": ANY, - "volume": -1.0, + "volume": None, } From 4a6597cba09ab054d36aaf32852a3846019e4721 Mon Sep 17 00:00:00 2001 From: Mike Gevaert Date: Mon, 26 May 2025 13:19:04 +0200 Subject: [PATCH 5/5] make EZ happy --- app/service/brain_region_hierarchy.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/app/service/brain_region_hierarchy.py b/app/service/brain_region_hierarchy.py index 7f5a0d9f..cfcf25f1 100644 --- a/app/service/brain_region_hierarchy.py +++ b/app/service/brain_region_hierarchy.py @@ -9,7 +9,6 @@ from app.db.model import BrainRegion, BrainRegionHierarchy from app.dependencies.common import PaginationQuery from app.dependencies.db import SessionDep -from app.errors import ensure_result from app.filters.brain_region_hierarchy import BrainRegionHierarchyFilterDep from app.schemas.brain_region_hierarchy import BrainRegionHierarchyRead from app.schemas.types import ListResponse @@ -38,10 +37,14 @@ def read_many( def read_one(id_: uuid.UUID, db: SessionDep) -> BrainRegionHierarchyRead: - with ensure_result(error_message="Brain Region Hierarchy not found"): - stmt = sa.select(BrainRegionHierarchy).filter(BrainRegionHierarchy.id == id_) - row = db.execute(stmt).scalar_one() - return BrainRegionHierarchyRead.model_validate(row) + return app.queries.common.router_read_one( + id_=id_, + db=db, + db_model_class=BrainRegionHierarchy, + authorized_project_id=None, + response_schema_class=BrainRegionHierarchyRead, + apply_operations=None, + ) class _JSONEncoder(json.JSONEncoder):