diff --git a/bluepyemodel/access_point/forge_access_point.py b/bluepyemodel/access_point/forge_access_point.py index 25ce714..64d82fc 100644 --- a/bluepyemodel/access_point/forge_access_point.py +++ b/bluepyemodel/access_point/forge_access_point.py @@ -351,7 +351,6 @@ def add_images_to_resource(self, images, resource, filters_existence=None): can be used to search for existence of resource on nexus. Used to get image type if cannot be extracted from image path. """ - resource = Dataset.from_resource(self.forge, resource, store_metadata=True) if filters_existence is None: filters_existence = {} for path in images: @@ -426,8 +425,12 @@ def register( resource = self.forge.from_json(resource_description, na="None") resource = self.add_contribution(resource) - if distributions: + if distributions or images: + # do this before adding lazy actions. + # if we do it after, it turns the lazy actions into a str resource = Dataset.from_resource(self.forge, resource) + + if distributions: for path in distributions: resource.add_distribution(path, content_type=f"application/{path.split('.')[-1]}") diff --git a/bluepyemodel/access_point/nexus.py b/bluepyemodel/access_point/nexus.py index daf32f0..65c00d9 100755 --- a/bluepyemodel/access_point/nexus.py +++ b/bluepyemodel/access_point/nexus.py @@ -286,12 +286,19 @@ def get_nexus_subject(self, species): return subject def store_object( - self, object_, seed=None, description=None, currents=None, is_analysis_suitable=False + self, + object_, + seed=None, + description=None, + currents=None, + is_analysis_suitable=False, + is_curated=False, ): """Store a BPEM object on Nexus""" metadata_dict = self.emodel_metadata_ontology.for_resource( - is_analysis_suitable=is_analysis_suitable + is_analysis_suitable=is_analysis_suitable, + is_curated=is_curated, ) if seed is not None: metadata_dict["seed"] = seed @@ -622,11 +629,15 @@ def create_emodel_workflow(self, state="not launched"): except AccessPointException: targets_configuration_id = None - pipeline_settings_id = self.access_point.get_nexus_id( - type_="EModelPipelineSettings", - metadata=self.emodel_metadata_ontology.filters_for_resource(), - legacy_metadata=self.emodel_metadata_ontology.filters_for_resource_legacy(), - ) + try: + pipeline_settings_id = self.access_point.get_nexus_id( + type_="EModelPipelineSettings", + metadata=self.emodel_metadata_ontology.filters_for_resource(), + legacy_metadata=self.emodel_metadata_ontology.filters_for_resource_legacy(), + ) + except AccessPointException: + pipeline_settings_id = None + emodel_configuration_id = self.access_point.get_nexus_id( type_="EModelConfiguration", metadata=self.emodel_metadata_ontology.filters_for_resource(), @@ -803,6 +814,7 @@ def store_emodel(self, emodel, description=None): ) emodel.workflow_id = nexus_id + # make it analysis suitable AND curated if this is True is_analysis_suitable = ( self.has_fitness_calculator_configuration and self.has_model_configuration @@ -814,6 +826,7 @@ def store_emodel(self, emodel, description=None): seed=emodel.seed, description=description, is_analysis_suitable=is_analysis_suitable, + is_curated=is_analysis_suitable, ) # wait for the object to be uploaded and fetchable time.sleep(self.sleep_time) diff --git a/bluepyemodel/emodel_pipeline/emodel_metadata.py b/bluepyemodel/emodel_pipeline/emodel_metadata.py index 8a89a02..c354c80 100644 --- a/bluepyemodel/emodel_pipeline/emodel_metadata.py +++ b/bluepyemodel/emodel_pipeline/emodel_metadata.py @@ -126,7 +126,7 @@ def ttype_annotation_dict(self): "name": "T-type annotation", } - def annotation_list(self, is_analysis_suitable=False): + def annotation_list(self, is_analysis_suitable=False, is_curated=False): """Returns an annotation list containing mtype, etype and ttype annotations. Args: @@ -148,6 +148,19 @@ def annotation_list(self, is_analysis_suitable=False): "note": "Analysis can be run on this model.", } ) + if is_curated: + annotation_list.append( + { + "@type": ["QualityAnnotation", "Annotation"], + "hasBody": { + "@id": "https://neuroshapes.org/Curated", + "@type": ["AnnotationBody", "DataMaturity"], + "label": "Curated", + }, + "motivatedBy": {"@id": "quality:Assessment", "@type": "Motivation"}, + "name": "Data maturity annotation", + } + ) if self.etype: annotation_list.append(self.etype_annotation_dict()) if self.mtype: @@ -201,7 +214,7 @@ def filters_for_resource_legacy(self): """Legacy metadata used for filtering, without the annotation list""" return self.as_dict_for_resource_legacy() - def for_resource(self, is_analysis_suitable=False): + def for_resource(self, is_analysis_suitable=False, is_curated=False): """Metadata to add to a resource to register. DO NOT use for filtering. For filtering, use self.filters_for_resource() instead. @@ -213,7 +226,9 @@ def for_resource(self, is_analysis_suitable=False): metadata = self.as_dict_for_resource() - metadata["annotation"] = self.annotation_list(is_analysis_suitable=is_analysis_suitable) + metadata["annotation"] = self.annotation_list( + is_analysis_suitable=is_analysis_suitable, is_curated=is_curated + ) return metadata