11import datetime
22import glob
3+ import hashlib
34import json
45import os
56import random
1718from tqdm import tqdm
1819
1920from app .cli import curate , utils
21+ from app .cli .brain_region_data import BRAIN_ATLAS_REGION_VOLUMES
2022from app .cli .curation import electrical_cell_recording
2123from app .cli .types import ContentType
2224from app .cli .utils import (
3133 Annotation ,
3234 Asset ,
3335 BrainAtlas ,
36+ BrainAtlasRegion ,
3437 BrainRegion ,
3538 BrainRegionHierarchy ,
3639 CellComposition ,
4750 Measurement ,
4851 MeasurementAnnotation ,
4952 MEModel ,
50- Mesh ,
5153 METypeDensity ,
5254 MTypeClass ,
5355 MTypeClassification ,
5456 Organization ,
5557 Person ,
5658 ReconstructionMorphology ,
5759 SingleNeuronSimulation ,
60+ Species ,
5861)
5962from app .db .session import configure_database_session_manager
6063from app .db .types import (
7174from app .cli .curation import electrical_cell_recording , cell_composition
7275from app .cli .types import ContentType
7376
77+
78+ BRAIN_ATLAS_NAME = "BlueBrain Atlas"
79+
7480REQUIRED_PATH = click .Path (exists = True , readable = True , dir_okay = False , resolve_path = True )
7581REQUIRED_PATH_DIR = click .Path (
7682 exists = True , readable = True , file_okay = False , dir_okay = True , resolve_path = True
@@ -555,47 +561,97 @@ def ingest(
555561 db .commit ()
556562
557563
558- class ImportBrainRegionMeshes (Import ):
559- name = "BrainRegionMeshes "
564+ class ImportBrainAtlas (Import ):
565+ name = "BrainAtlas "
560566
561567 @staticmethod
562568 def is_correct_type (data ):
563- types = ensurelist (data ["@type" ])
564- return "BrainParcellationMesh" in types
569+ # for reasons unknown, the annotations are tagged as v1.2.0
570+ # the contents of the annotations is the same as in
571+ # s3://openbluebrain/Model_Data/Brain_atlas/Mouse/resolution_25_um/version_1.1.0/Annotation_volume/annotation_ccfv3_l23split_barrelsplit_validated.nrrd
572+ # but their sha256 hashes differ
573+ return (
574+ utils .is_type (data , "BrainParcellationMesh" )
575+ and "atlasRelease" in data
576+ and data ["atlasRelease" ].get ("tag" ) == "v1.1.0"
577+ ) or (
578+ utils .is_type (data , "BrainParcellationDataLayer" )
579+ and "atlasRelease" in data
580+ and data ["atlasRelease" ].get ("tag" ) == "v1.2.0"
581+ )
565582
566583 @staticmethod
567584 def ingest (db , project_context , data_list , all_data_by_id , hierarchy_name : str ):
568- for data in tqdm (data_list ):
569- if "atlasRelease" not in data or data ["atlasRelease" ].get ("tag" , "" ) != "v1.1.0" :
570- continue
585+ meshes , annotations = [], []
586+ for d in data_list :
587+ if utils .is_type (d , "BrainParcellationMesh" ):
588+ meshes .append (d )
589+ else :
590+ annotations .append (d )
591+
592+ assert len (annotations ) == 1
593+ brain_atlas = db .execute (
594+ sa .select (BrainAtlas ).filter (BrainAtlas .name == BRAIN_ATLAS_NAME )
595+ ).scalar_one_or_none ()
596+ if brain_atlas is None :
597+ hierarchy = db .execute (
598+ sa .select (BrainRegionHierarchy ).filter (BrainRegionHierarchy .name == hierarchy_name )
599+ ).scalar_one ()
600+
601+ mouse = db .execute (
602+ sa .select (Species ).filter (Species .name == "Mus musculus" )
603+ ).scalar_one ()
604+
605+ brain_atlas = BrainAtlas (
606+ name = BRAIN_ATLAS_NAME ,
607+ description = "version v1.1.0 from NEXUS" ,
608+ species_id = mouse .id ,
609+ hierarchy_id = hierarchy .id ,
610+ authorized_project_id = project_context .project_id ,
611+ authorized_public = True ,
612+ )
613+ db .add (brain_atlas )
614+ db .commit ()
571615
572- legacy_id = data ["@id" ]
573- legacy_self = data ["_self" ]
574- rm = utils ._find_by_legacy_id (legacy_id , Mesh , db )
575- if rm :
576- continue
616+ utils .import_distribution (
617+ annotations [0 ], brain_atlas .id , EntityType .brain_atlas , db , project_context
618+ )
577619
578- try :
579- brain_region_id = utils . get_brain_region ( data , hierarchy_name , db )
580- except RuntimeError :
581- L . exception ( "Cannot import mesh" )
582- continue
620+ for mesh in tqdm ( meshes ) :
621+ brain_region_data = mesh [ "brainLocation" ][ "brainRegion" ]
622+ brain_region_id = utils . get_brain_region_by_hier_id (
623+ brain_region_data , hierarchy_name , db
624+ )
583625
584- createdAt , updatedAt = utils .get_created_and_updated (data )
626+ atlas_region = db .execute (
627+ sa .select (BrainAtlasRegion ).filter (
628+ BrainAtlasRegion .brain_region_id == str (brain_region_id )
629+ )
630+ ).scalar_one_or_none ()
631+
632+ if atlas_region is None :
633+ annotation_id = curate .curate_brain_region (brain_region_data )["@id" ]
634+ volume = - 1
635+
636+ leaf_region = False
637+ if annotation_id in BRAIN_ATLAS_REGION_VOLUMES :
638+ volume = BRAIN_ATLAS_REGION_VOLUMES [annotation_id ]
639+ leaf_region = True
640+
641+ atlas_region = BrainAtlasRegion (
642+ brain_atlas_id = brain_atlas .id ,
643+ brain_region_id = brain_region_id ,
644+ volume = volume ,
645+ leaf_region = leaf_region ,
646+ authorized_project_id = project_context .project_id ,
647+ authorized_public = True ,
648+ )
649+ db .add (atlas_region )
650+ db .commit ()
585651
586- db_item = Mesh (
587- name = data ["name" ],
588- description = data ["description" ],
589- legacy_id = [legacy_id ],
590- legacy_self = [legacy_self ],
591- brain_region_id = brain_region_id ,
592- creation_date = createdAt ,
593- update_date = updatedAt ,
594- authorized_project_id = project_context .project_id ,
595- authorized_public = AUTHORIZED_PUBLIC ,
652+ utils .import_distribution (
653+ mesh , atlas_region .id , EntityType .brain_atlas , db , project_context
596654 )
597- db .add (db_item )
598- db .commit ()
599655
600656
601657class ImportMorphologies (Import ):
@@ -743,8 +799,6 @@ def ingest(db, project_context, data_list, all_data_by_id, hierarchy_name):
743799 brain_region_id = utils .get_brain_region (data , hierarchy_name , db )
744800
745801 license_id = utils .get_license_mixin (data , db )
746- # species_id, strain_id = utils.get_species_mixin(data, db)
747-
748802 subject_id = utils .get_or_create_subject (data , project_context , db )
749803 createdAt , updatedAt = utils .get_created_and_updated (data )
750804
@@ -1036,50 +1090,6 @@ def ingest(
10361090 create_annotation (annotation , db_item .id , db )
10371091
10381092
1039- class ImportBrainAtlas (Import ):
1040- name = "Brain Atlas"
1041-
1042- @staticmethod
1043- def is_correct_type (data ):
1044- return "BrainAtlasRelease" in ensurelist (data ["@type" ]) and data ["@id" ] == BRAIN_ATLAS_ID
1045-
1046- @staticmethod
1047- def ingest (
1048- db : Session ,
1049- project_context : ProjectContext ,
1050- data_list : list [dict ],
1051- all_data_by_id : dict ,
1052- hierarchy_name : str ,
1053- ):
1054- for data in data_list :
1055- legacy_id , legacy_self = data ["@id" ], data ["_self" ]
1056- rm = utils ._find_by_legacy_id (legacy_id , BrainAtlas , db )
1057- if rm :
1058- continue
1059-
1060- created_by_id , updated_by_id = utils .get_agent_mixin (data , db )
1061- createdAt , updatedAt = utils .get_created_and_updated (data )
1062- species_id , strain_id = utils .get_species_mixin (data , db )
1063-
1064- brain_region_id = utils .get_brain_region (data , hierarchy_name , db )
1065-
1066- db_item = BrainAtlas (
1067- legacy_id = [legacy_id ],
1068- legacy_self = [legacy_self ],
1069- name = data ["name" ],
1070- description = data .get ("description" , "" ),
1071- brain_region_id = brain_region_id ,
1072- species_id = species_id ,
1073- strain_id = strain_id ,
1074- created_by_id = created_by_id ,
1075- updated_by_id = updated_by_id ,
1076- creation_date = createdAt ,
1077- update_date = updatedAt ,
1078- authorized_project_id = project_context .project_id ,
1079- authorized_public = AUTHORIZED_PUBLIC ,
1080- )
1081-
1082-
10831093class ImportDistribution (Import ):
10841094 name = "Distribution"
10851095
@@ -1098,8 +1108,7 @@ def ingest(
10981108 ignored : dict [tuple [dict ], int ] = Counter ()
10991109 for data in tqdm (data_list ):
11001110 legacy_id = data ["@id" ]
1101- root = utils ._find_by_legacy_id (legacy_id , Entity , db )
1102- if root :
1111+ if root := utils ._find_by_legacy_id (legacy_id , Entity , db ):
11031112 utils .import_distribution (data , root .id , root .type , db , project_context )
11041113 else :
11051114 dt = data ["@type" ]
@@ -1339,9 +1348,7 @@ def _do_import(db, input_dir, project_context, hierarchy_name):
13391348 ImportAgent ,
13401349 ImportMETypeDensity ,
13411350 ImportCellComposition ,
1342- ImportBrainAtlas ,
13431351 ImportAnalysisSoftwareSourceCode ,
1344- ImportBrainRegionMeshes ,
13451352 ImportMorphologies ,
13461353 ImportEModels ,
13471354 ImportExperimentalNeuronDensities ,
@@ -1350,6 +1357,7 @@ def _do_import(db, input_dir, project_context, hierarchy_name):
13501357 ImportMEModel ,
13511358 ImportElectricalCellRecording ,
13521359 ImportSingleNeuronSimulation ,
1360+ ImportBrainAtlas ,
13531361 ImportDistribution ,
13541362 ImportNeuronMorphologyFeatureAnnotation ,
13551363 ]
@@ -1579,7 +1587,7 @@ def curate_files(input_digest_path, output_digest_path, out_dir, dry_run):
15791587 closing (configure_database_session_manager ()) as database_session_manager ,
15801588 database_session_manager .session () as db ,
15811589 ):
1582- # Group assets by ntity_type /entity_id/content_type
1590+ # Group assets by entity_type /entity_id/content_type
15831591 assets_per_entity_type = defaultdict (lambda : defaultdict (lambda : defaultdict (list )))
15841592 for asset in db .query (Asset ).all ():
15851593 entity_type = asset .full_path .split ("/" )[4 ]
0 commit comments