fairgraph 0.13.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fairgraph/__init__.py +61 -0
- fairgraph/base.py +104 -0
- fairgraph/caching.py +52 -0
- fairgraph/client.py +867 -0
- fairgraph/collection.py +104 -0
- fairgraph/embedded.py +122 -0
- fairgraph/errors.py +47 -0
- fairgraph/fields.py +11 -0
- fairgraph/kgobject.py +1087 -0
- fairgraph/kgproxy.py +178 -0
- fairgraph/kgquery.py +151 -0
- fairgraph/node.py +488 -0
- fairgraph/openminds/__init__.py +1 -0
- fairgraph/openminds/chemicals/__init__.py +40 -0
- fairgraph/openminds/chemicals/amount_of_chemical.py +23 -0
- fairgraph/openminds/chemicals/chemical_mixture.py +72 -0
- fairgraph/openminds/chemicals/chemical_substance.py +67 -0
- fairgraph/openminds/chemicals/product_source.py +57 -0
- fairgraph/openminds/computation/__init__.py +53 -0
- fairgraph/openminds/computation/data_analysis.py +104 -0
- fairgraph/openminds/computation/data_copy.py +104 -0
- fairgraph/openminds/computation/environment.py +66 -0
- fairgraph/openminds/computation/generic_computation.py +104 -0
- fairgraph/openminds/computation/hardware_system.py +53 -0
- fairgraph/openminds/computation/launch_configuration.py +68 -0
- fairgraph/openminds/computation/local_file.py +83 -0
- fairgraph/openminds/computation/model_validation.py +107 -0
- fairgraph/openminds/computation/optimization.py +104 -0
- fairgraph/openminds/computation/simulation.py +104 -0
- fairgraph/openminds/computation/software_agent.py +81 -0
- fairgraph/openminds/computation/validation_test.py +105 -0
- fairgraph/openminds/computation/validation_test_version.py +180 -0
- fairgraph/openminds/computation/visualization.py +104 -0
- fairgraph/openminds/computation/workflow_execution.py +44 -0
- fairgraph/openminds/computation/workflow_recipe.py +95 -0
- fairgraph/openminds/computation/workflow_recipe_version.py +185 -0
- fairgraph/openminds/controlled_terms/__init__.py +116 -0
- fairgraph/openminds/controlled_terms/action_status_type.py +97 -0
- fairgraph/openminds/controlled_terms/age_category.py +89 -0
- fairgraph/openminds/controlled_terms/analysis_technique.py +108 -0
- fairgraph/openminds/controlled_terms/anatomical_axes_orientation.py +89 -0
- fairgraph/openminds/controlled_terms/anatomical_identification_type.py +89 -0
- fairgraph/openminds/controlled_terms/anatomical_plane.py +89 -0
- fairgraph/openminds/controlled_terms/annotation_criteria_type.py +89 -0
- fairgraph/openminds/controlled_terms/annotation_type.py +89 -0
- fairgraph/openminds/controlled_terms/atlas_type.py +88 -0
- fairgraph/openminds/controlled_terms/auditory_stimulus_type.py +127 -0
- fairgraph/openminds/controlled_terms/biological_order.py +117 -0
- fairgraph/openminds/controlled_terms/biological_process.py +79 -0
- fairgraph/openminds/controlled_terms/biological_sex.py +132 -0
- fairgraph/openminds/controlled_terms/breeding_type.py +127 -0
- fairgraph/openminds/controlled_terms/cell_culture_type.py +117 -0
- fairgraph/openminds/controlled_terms/cell_type.py +151 -0
- fairgraph/openminds/controlled_terms/chemical_mixture_type.py +89 -0
- fairgraph/openminds/controlled_terms/colormap.py +79 -0
- fairgraph/openminds/controlled_terms/contribution_type.py +79 -0
- fairgraph/openminds/controlled_terms/cranial_window_construction_type.py +89 -0
- fairgraph/openminds/controlled_terms/cranial_window_reinforcement_type.py +89 -0
- fairgraph/openminds/controlled_terms/criteria_quality_type.py +89 -0
- fairgraph/openminds/controlled_terms/data_type.py +89 -0
- fairgraph/openminds/controlled_terms/device_type.py +94 -0
- fairgraph/openminds/controlled_terms/difference_measure.py +89 -0
- fairgraph/openminds/controlled_terms/disease.py +142 -0
- fairgraph/openminds/controlled_terms/disease_model.py +142 -0
- fairgraph/openminds/controlled_terms/educational_level.py +79 -0
- fairgraph/openminds/controlled_terms/electrical_stimulus_type.py +137 -0
- fairgraph/openminds/controlled_terms/ethics_assessment.py +79 -0
- fairgraph/openminds/controlled_terms/experimental_approach.py +79 -0
- fairgraph/openminds/controlled_terms/file_bundle_grouping.py +99 -0
- fairgraph/openminds/controlled_terms/file_repository_type.py +89 -0
- fairgraph/openminds/controlled_terms/file_usage_role.py +89 -0
- fairgraph/openminds/controlled_terms/genetic_strain_type.py +127 -0
- fairgraph/openminds/controlled_terms/gustatory_stimulus_type.py +127 -0
- fairgraph/openminds/controlled_terms/handedness.py +127 -0
- fairgraph/openminds/controlled_terms/language.py +88 -0
- fairgraph/openminds/controlled_terms/laterality.py +94 -0
- fairgraph/openminds/controlled_terms/learning_resource_type.py +88 -0
- fairgraph/openminds/controlled_terms/measured_quantity.py +89 -0
- fairgraph/openminds/controlled_terms/measured_signal_type.py +79 -0
- fairgraph/openminds/controlled_terms/meta_data_model_type.py +88 -0
- fairgraph/openminds/controlled_terms/model_abstraction_level.py +89 -0
- fairgraph/openminds/controlled_terms/model_scope.py +89 -0
- fairgraph/openminds/controlled_terms/molecular_entity.py +142 -0
- fairgraph/openminds/controlled_terms/mri_pulse_sequence.py +98 -0
- fairgraph/openminds/controlled_terms/mri_weighting.py +98 -0
- fairgraph/openminds/controlled_terms/olfactory_stimulus_type.py +127 -0
- fairgraph/openminds/controlled_terms/operating_device.py +79 -0
- fairgraph/openminds/controlled_terms/operating_system.py +88 -0
- fairgraph/openminds/controlled_terms/optical_stimulus_type.py +127 -0
- fairgraph/openminds/controlled_terms/organ.py +161 -0
- fairgraph/openminds/controlled_terms/organism_substance.py +151 -0
- fairgraph/openminds/controlled_terms/organism_system.py +117 -0
- fairgraph/openminds/controlled_terms/patch_clamp_variation.py +89 -0
- fairgraph/openminds/controlled_terms/preparation_type.py +98 -0
- fairgraph/openminds/controlled_terms/product_accessibility.py +79 -0
- fairgraph/openminds/controlled_terms/programming_language.py +88 -0
- fairgraph/openminds/controlled_terms/qualitative_overlap.py +79 -0
- fairgraph/openminds/controlled_terms/semantic_data_type.py +79 -0
- fairgraph/openminds/controlled_terms/service.py +89 -0
- fairgraph/openminds/controlled_terms/setup_type.py +89 -0
- fairgraph/openminds/controlled_terms/software_application_category.py +79 -0
- fairgraph/openminds/controlled_terms/software_feature.py +79 -0
- fairgraph/openminds/controlled_terms/species.py +143 -0
- fairgraph/openminds/controlled_terms/stimulation_approach.py +98 -0
- fairgraph/openminds/controlled_terms/stimulation_technique.py +98 -0
- fairgraph/openminds/controlled_terms/subcellular_entity.py +143 -0
- fairgraph/openminds/controlled_terms/subject_attribute.py +89 -0
- fairgraph/openminds/controlled_terms/tactile_stimulus_type.py +127 -0
- fairgraph/openminds/controlled_terms/technique.py +108 -0
- fairgraph/openminds/controlled_terms/term_suggestion.py +121 -0
- fairgraph/openminds/controlled_terms/terminology.py +89 -0
- fairgraph/openminds/controlled_terms/tissue_sample_attribute.py +89 -0
- fairgraph/openminds/controlled_terms/tissue_sample_type.py +127 -0
- fairgraph/openminds/controlled_terms/type_of_uncertainty.py +89 -0
- fairgraph/openminds/controlled_terms/uberon_parcellation.py +153 -0
- fairgraph/openminds/controlled_terms/unit_of_measurement.py +108 -0
- fairgraph/openminds/controlled_terms/visual_stimulus_type.py +127 -0
- fairgraph/openminds/controlledterms.py +6 -0
- fairgraph/openminds/core/__init__.py +107 -0
- fairgraph/openminds/core/actors/__init__.py +7 -0
- fairgraph/openminds/core/actors/account_information.py +44 -0
- fairgraph/openminds/core/actors/affiliation.py +30 -0
- fairgraph/openminds/core/actors/consortium.py +175 -0
- fairgraph/openminds/core/actors/contact_information.py +43 -0
- fairgraph/openminds/core/actors/contribution.py +23 -0
- fairgraph/openminds/core/actors/organization.py +199 -0
- fairgraph/openminds/core/actors/person.py +236 -0
- fairgraph/openminds/core/data/__init__.py +13 -0
- fairgraph/openminds/core/data/content_type.py +107 -0
- fairgraph/openminds/core/data/content_type_pattern.py +53 -0
- fairgraph/openminds/core/data/copyright.py +23 -0
- fairgraph/openminds/core/data/file.py +275 -0
- fairgraph/openminds/core/data/file_archive.py +71 -0
- fairgraph/openminds/core/data/file_bundle.py +150 -0
- fairgraph/openminds/core/data/file_path_pattern.py +23 -0
- fairgraph/openminds/core/data/file_repository.py +99 -0
- fairgraph/openminds/core/data/file_repository_structure.py +51 -0
- fairgraph/openminds/core/data/hash.py +23 -0
- fairgraph/openminds/core/data/license.py +77 -0
- fairgraph/openminds/core/data/measurement.py +45 -0
- fairgraph/openminds/core/data/service_link.py +49 -0
- fairgraph/openminds/core/digital_identifier/__init__.py +11 -0
- fairgraph/openminds/core/digital_identifier/doi.py +98 -0
- fairgraph/openminds/core/digital_identifier/gridid.py +41 -0
- fairgraph/openminds/core/digital_identifier/handle.py +52 -0
- fairgraph/openminds/core/digital_identifier/identifiers_dot_org_id.py +41 -0
- fairgraph/openminds/core/digital_identifier/isbn.py +88 -0
- fairgraph/openminds/core/digital_identifier/issn.py +63 -0
- fairgraph/openminds/core/digital_identifier/orcid.py +41 -0
- fairgraph/openminds/core/digital_identifier/rorid.py +41 -0
- fairgraph/openminds/core/digital_identifier/rrid.py +55 -0
- fairgraph/openminds/core/digital_identifier/stock_number.py +23 -0
- fairgraph/openminds/core/digital_identifier/swhid.py +48 -0
- fairgraph/openminds/core/miscellaneous/__init__.py +7 -0
- fairgraph/openminds/core/miscellaneous/comment.py +47 -0
- fairgraph/openminds/core/miscellaneous/funding.py +70 -0
- fairgraph/openminds/core/miscellaneous/quantitative_value.py +43 -0
- fairgraph/openminds/core/miscellaneous/quantitative_value_array.py +49 -0
- fairgraph/openminds/core/miscellaneous/quantitative_value_range.py +43 -0
- fairgraph/openminds/core/miscellaneous/research_product_group.py +26 -0
- fairgraph/openminds/core/miscellaneous/web_resource.py +104 -0
- fairgraph/openminds/core/products/__init__.py +12 -0
- fairgraph/openminds/core/products/dataset.py +95 -0
- fairgraph/openminds/core/products/dataset_version.py +240 -0
- fairgraph/openminds/core/products/meta_data_model.py +95 -0
- fairgraph/openminds/core/products/meta_data_model_version.py +168 -0
- fairgraph/openminds/core/products/model.py +103 -0
- fairgraph/openminds/core/products/model_version.py +235 -0
- fairgraph/openminds/core/products/project.py +56 -0
- fairgraph/openminds/core/products/setup.py +69 -0
- fairgraph/openminds/core/products/software.py +95 -0
- fairgraph/openminds/core/products/software_version.py +226 -0
- fairgraph/openminds/core/products/web_service.py +103 -0
- fairgraph/openminds/core/products/web_service_version.py +182 -0
- fairgraph/openminds/core/research/__init__.py +17 -0
- fairgraph/openminds/core/research/behavioral_protocol.py +69 -0
- fairgraph/openminds/core/research/configuration.py +67 -0
- fairgraph/openminds/core/research/custom_property_set.py +27 -0
- fairgraph/openminds/core/research/numerical_property.py +23 -0
- fairgraph/openminds/core/research/property_value_list.py +71 -0
- fairgraph/openminds/core/research/protocol.py +67 -0
- fairgraph/openminds/core/research/protocol_execution.py +76 -0
- fairgraph/openminds/core/research/strain.py +90 -0
- fairgraph/openminds/core/research/string_property.py +23 -0
- fairgraph/openminds/core/research/subject.py +79 -0
- fairgraph/openminds/core/research/subject_group.py +91 -0
- fairgraph/openminds/core/research/subject_group_state.py +113 -0
- fairgraph/openminds/core/research/subject_state.py +138 -0
- fairgraph/openminds/core/research/tissue_sample.py +87 -0
- fairgraph/openminds/core/research/tissue_sample_collection.py +99 -0
- fairgraph/openminds/core/research/tissue_sample_collection_state.py +109 -0
- fairgraph/openminds/core/research/tissue_sample_state.py +127 -0
- fairgraph/openminds/ephys/__init__.py +39 -0
- fairgraph/openminds/ephys/activity/__init__.py +3 -0
- fairgraph/openminds/ephys/activity/cell_patching.py +73 -0
- fairgraph/openminds/ephys/activity/electrode_placement.py +67 -0
- fairgraph/openminds/ephys/activity/recording_activity.py +67 -0
- fairgraph/openminds/ephys/device/__init__.py +6 -0
- fairgraph/openminds/ephys/device/electrode.py +81 -0
- fairgraph/openminds/ephys/device/electrode_array.py +85 -0
- fairgraph/openminds/ephys/device/electrode_array_usage.py +105 -0
- fairgraph/openminds/ephys/device/electrode_usage.py +101 -0
- fairgraph/openminds/ephys/device/pipette.py +81 -0
- fairgraph/openminds/ephys/device/pipette_usage.py +123 -0
- fairgraph/openminds/ephys/entity/__init__.py +2 -0
- fairgraph/openminds/ephys/entity/channel.py +23 -0
- fairgraph/openminds/ephys/entity/recording.py +63 -0
- fairgraph/openminds/publications/__init__.py +47 -0
- fairgraph/openminds/publications/book.py +106 -0
- fairgraph/openminds/publications/chapter.py +100 -0
- fairgraph/openminds/publications/learning_resource.py +90 -0
- fairgraph/openminds/publications/live_paper.py +95 -0
- fairgraph/openminds/publications/live_paper_resource_item.py +58 -0
- fairgraph/openminds/publications/live_paper_section.py +57 -0
- fairgraph/openminds/publications/live_paper_version.py +177 -0
- fairgraph/openminds/publications/periodical.py +53 -0
- fairgraph/openminds/publications/publication_issue.py +44 -0
- fairgraph/openminds/publications/publication_volume.py +44 -0
- fairgraph/openminds/publications/scholarly_article.py +146 -0
- fairgraph/openminds/sands/__init__.py +57 -0
- fairgraph/openminds/sands/atlas/__init__.py +9 -0
- fairgraph/openminds/sands/atlas/atlas_annotation.py +52 -0
- fairgraph/openminds/sands/atlas/brain_atlas.py +113 -0
- fairgraph/openminds/sands/atlas/brain_atlas_version.py +213 -0
- fairgraph/openminds/sands/atlas/common_coordinate_space.py +121 -0
- fairgraph/openminds/sands/atlas/common_coordinate_space_version.py +243 -0
- fairgraph/openminds/sands/atlas/parcellation_entity.py +133 -0
- fairgraph/openminds/sands/atlas/parcellation_entity_version.py +162 -0
- fairgraph/openminds/sands/atlas/parcellation_terminology.py +38 -0
- fairgraph/openminds/sands/atlas/parcellation_terminology_version.py +38 -0
- fairgraph/openminds/sands/mathematical_shapes/__init__.py +3 -0
- fairgraph/openminds/sands/mathematical_shapes/circle.py +23 -0
- fairgraph/openminds/sands/mathematical_shapes/ellipse.py +27 -0
- fairgraph/openminds/sands/mathematical_shapes/rectangle.py +23 -0
- fairgraph/openminds/sands/miscellaneous/__init__.py +6 -0
- fairgraph/openminds/sands/miscellaneous/anatomical_target_position.py +40 -0
- fairgraph/openminds/sands/miscellaneous/coordinate_point.py +23 -0
- fairgraph/openminds/sands/miscellaneous/qualitative_relation_assessment.py +34 -0
- fairgraph/openminds/sands/miscellaneous/quantitative_relation_assessment.py +38 -0
- fairgraph/openminds/sands/miscellaneous/single_color.py +24 -0
- fairgraph/openminds/sands/miscellaneous/viewer_specification.py +40 -0
- fairgraph/openminds/sands/non_atlas/__init__.py +3 -0
- fairgraph/openminds/sands/non_atlas/custom_anatomical_entity.py +110 -0
- fairgraph/openminds/sands/non_atlas/custom_annotation.py +54 -0
- fairgraph/openminds/sands/non_atlas/custom_coordinate_space.py +67 -0
- fairgraph/openminds/specimen_prep/__init__.py +38 -0
- fairgraph/openminds/specimen_prep/activity/__init__.py +3 -0
- fairgraph/openminds/specimen_prep/activity/cranial_window_preparation.py +69 -0
- fairgraph/openminds/specimen_prep/activity/tissue_culture_preparation.py +67 -0
- fairgraph/openminds/specimen_prep/activity/tissue_sample_slicing.py +69 -0
- fairgraph/openminds/specimen_prep/device/__init__.py +2 -0
- fairgraph/openminds/specimen_prep/device/slicing_device.py +73 -0
- fairgraph/openminds/specimen_prep/device/slicing_device_usage.py +117 -0
- fairgraph/openminds/specimenprep.py +4 -0
- fairgraph/openminds/stimulation/__init__.py +38 -0
- fairgraph/openminds/stimulation/activity/__init__.py +1 -0
- fairgraph/openminds/stimulation/activity/stimulation_activity.py +67 -0
- fairgraph/openminds/stimulation/stimulus/__init__.py +1 -0
- fairgraph/openminds/stimulation/stimulus/ephys_stimulus.py +63 -0
- fairgraph/queries.py +499 -0
- fairgraph/registry.py +123 -0
- fairgraph/utility.py +607 -0
- fairgraph-0.13.0.dist-info/METADATA +222 -0
- fairgraph-0.13.0.dist-info/RECORD +267 -0
- fairgraph-0.13.0.dist-info/WHEEL +5 -0
- fairgraph-0.13.0.dist-info/licenses/LICENSE.txt +177 -0
- fairgraph-0.13.0.dist-info/top_level.txt +1 -0
fairgraph/utility.py
ADDED
|
@@ -0,0 +1,607 @@
|
|
|
1
|
+
"""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
# Copyright 2019-2020 CNRS
|
|
7
|
+
|
|
8
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
9
|
+
# you may not use this file except in compliance with the License.
|
|
10
|
+
# You may obtain a copy of the License at
|
|
11
|
+
|
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
13
|
+
|
|
14
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
15
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
16
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
17
|
+
# See the License for the specific language governing permissions and
|
|
18
|
+
# limitations under the License.
|
|
19
|
+
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
from copy import deepcopy
|
|
22
|
+
import hashlib
|
|
23
|
+
import logging
|
|
24
|
+
from typing import Any, Dict, Iterable, List, Optional, Tuple, Union, TYPE_CHECKING
|
|
25
|
+
import warnings
|
|
26
|
+
|
|
27
|
+
from openminds.registry import lookup_type
|
|
28
|
+
|
|
29
|
+
from .base import OPENMINDS_VERSION
|
|
30
|
+
|
|
31
|
+
if TYPE_CHECKING:
|
|
32
|
+
from .client import KGClient
|
|
33
|
+
from .kgobject import KGObject
|
|
34
|
+
|
|
35
|
+
logger = logging.getLogger("fairgraph")
|
|
36
|
+
|
|
37
|
+
JSONdict = Dict[str, Any] # see https://github.com/python/typing/issues/182 for some possible improvements
|
|
38
|
+
ATTACHMENT_SIZE_LIMIT = 1024 * 1024 # 1 MB
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def as_list(obj: Union[None, KGObject, dict, str, list, tuple]) -> list:
|
|
42
|
+
"""
|
|
43
|
+
Converts the input obj into a list.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
obj: The input object to be converted to a list.
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
list: A list - see Notes below.
|
|
50
|
+
|
|
51
|
+
Raises:
|
|
52
|
+
TypeError: If the input obj cannot be converted to a list.
|
|
53
|
+
|
|
54
|
+
Notes:
|
|
55
|
+
- If obj is None, it returns an empty list.
|
|
56
|
+
- If obj is a dict or a str, it returns a list containing obj.
|
|
57
|
+
- If obj is a list or a tuple, it returns a list with the same elements as obj.
|
|
58
|
+
- If obj is not any of the above, it tries to convert obj into a list. If it fails due to a TypeError, it raises a TypeError with an appropriate error message.
|
|
59
|
+
"""
|
|
60
|
+
if obj is None:
|
|
61
|
+
return []
|
|
62
|
+
elif isinstance(obj, (dict, str)):
|
|
63
|
+
return [obj]
|
|
64
|
+
try:
|
|
65
|
+
L = list(obj)
|
|
66
|
+
except TypeError:
|
|
67
|
+
L = [obj]
|
|
68
|
+
return L
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def invert_dict(D):
|
|
72
|
+
newD = {}
|
|
73
|
+
for key, value in D.items():
|
|
74
|
+
newD[value] = key
|
|
75
|
+
return newD
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def expand_uri(uri_list: Union[str, List[str]], context: Dict[str, Any]) -> Union[str, Tuple[str, ...]]:
|
|
79
|
+
"""
|
|
80
|
+
Expands a URI or a list of URIs using a given context.
|
|
81
|
+
|
|
82
|
+
Args:
|
|
83
|
+
uri_list (Union[str, List[str]]): A URI or a list of URIs to be expanded.
|
|
84
|
+
context (Dict[str, Any]): A dictionary containing a mapping of prefixes to base URLs.
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
Union[str, Tuple[str, ...]]: An expanded URI or a tuple of expanded URIs.
|
|
88
|
+
|
|
89
|
+
Raises:
|
|
90
|
+
ValueError: If a prefix in the URI is not found in the context.
|
|
91
|
+
|
|
92
|
+
Examples:
|
|
93
|
+
>>> context = {'foaf': 'http://xmlns.com/foaf/0.1/'}
|
|
94
|
+
>>> uri_list = 'foaf:Person'
|
|
95
|
+
>>> expand_uri(uri_list, context)
|
|
96
|
+
'http://xmlns.com/foaf/0.1/Person'
|
|
97
|
+
|
|
98
|
+
"""
|
|
99
|
+
expanded_uris = []
|
|
100
|
+
for uri in as_list(uri_list):
|
|
101
|
+
if uri.startswith("http") or uri.startswith("@"):
|
|
102
|
+
expanded_uris.append(uri)
|
|
103
|
+
else:
|
|
104
|
+
parts = uri.split(":")
|
|
105
|
+
if len(parts) == 1:
|
|
106
|
+
prefix = "@vocab"
|
|
107
|
+
identifier = uri
|
|
108
|
+
else:
|
|
109
|
+
prefix, identifier = parts
|
|
110
|
+
if prefix not in context:
|
|
111
|
+
raise ValueError(f"prefix {prefix} not found in context")
|
|
112
|
+
base_url = context[prefix]
|
|
113
|
+
if not base_url.endswith("/"):
|
|
114
|
+
base_url += "/"
|
|
115
|
+
expanded_uris.append(f"{base_url}{identifier}")
|
|
116
|
+
if isinstance(uri_list, str):
|
|
117
|
+
return expanded_uris[0]
|
|
118
|
+
else:
|
|
119
|
+
return tuple(expanded_uris)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def compact_uri(
|
|
123
|
+
uri_list: Union[str, List[str]], context: Dict[str, Any], strict: bool = False
|
|
124
|
+
) -> Union[str, Tuple[str, ...]]:
|
|
125
|
+
"""
|
|
126
|
+
Compacts a URI or a list of URIs using a given context.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
uri_list (Union[str, List[str]]): A URI or a list of URIs to be compacted.
|
|
130
|
+
context (Dict[str, Any]): A dictionary containing a mapping of prefixes to base URLs.
|
|
131
|
+
strict (bool, optional): Whether to raise an error if a URI cannot be compacted. Defaults to False.
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
Union[str, Tuple[str, ...]]: A compacted URI or a tuple of compacted URIs.
|
|
135
|
+
|
|
136
|
+
Raises:
|
|
137
|
+
ValueError: If strict is True and a URI cannot be compacted.
|
|
138
|
+
|
|
139
|
+
Examples:
|
|
140
|
+
>>> context = {'foaf': 'http://xmlns.com/foaf/0.1/'}
|
|
141
|
+
>>> uri_list = 'http://xmlns.com/foaf/0.1/Person'
|
|
142
|
+
>>> compact_uri(uri_list, context)
|
|
143
|
+
'foaf:Person'
|
|
144
|
+
"""
|
|
145
|
+
compacted_uris = []
|
|
146
|
+
for uri in as_list(uri_list):
|
|
147
|
+
if uri.startswith("http"):
|
|
148
|
+
found = False
|
|
149
|
+
for prefix, base_url in context.items():
|
|
150
|
+
if uri.startswith(base_url):
|
|
151
|
+
start = len(base_url)
|
|
152
|
+
identifier = uri[start:].strip("/")
|
|
153
|
+
if prefix == "@vocab":
|
|
154
|
+
compacted_uris.append(identifier)
|
|
155
|
+
else:
|
|
156
|
+
compacted_uris.append(f"{prefix}:{identifier}")
|
|
157
|
+
found = True
|
|
158
|
+
break
|
|
159
|
+
if not found:
|
|
160
|
+
if strict:
|
|
161
|
+
raise ValueError(f"Unable to compact {uri} with the provided context")
|
|
162
|
+
else:
|
|
163
|
+
compacted_uris.append(uri)
|
|
164
|
+
else:
|
|
165
|
+
compacted_uris.append(uri)
|
|
166
|
+
if isinstance(uri_list, str):
|
|
167
|
+
return compacted_uris[0]
|
|
168
|
+
else:
|
|
169
|
+
return tuple(compacted_uris)
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def normalize_data(data: Union[None, JSONdict], context: Dict[str, Any]) -> Union[None, JSONdict]:
|
|
173
|
+
"""
|
|
174
|
+
Normalizes JSON-LD data using a given context.
|
|
175
|
+
|
|
176
|
+
Args:
|
|
177
|
+
data (Union[None, JSONdict]): A JSON-LD data dict to be normalized.
|
|
178
|
+
context (Dict[str, Any]): A dictionary containing a mapping of prefixes to base URLs.
|
|
179
|
+
|
|
180
|
+
Returns:
|
|
181
|
+
Union[None, JSONdict]: A normalized JSON-LD data dict.
|
|
182
|
+
|
|
183
|
+
Examples:
|
|
184
|
+
>>> context = {'foaf': 'http://xmlns.com/foaf/0.1/'}
|
|
185
|
+
>>> data = {
|
|
186
|
+
... "foaf:name": "John Smith",
|
|
187
|
+
... "foaf:age": 35,
|
|
188
|
+
... "foaf:knows": {
|
|
189
|
+
... "foaf:name": "Jane Doe",
|
|
190
|
+
... "foaf:age": 25
|
|
191
|
+
... }
|
|
192
|
+
... }
|
|
193
|
+
>>> normalize_data(data, context)
|
|
194
|
+
{
|
|
195
|
+
"http://xmlns.com/foaf/0.1/name": "John Smith",
|
|
196
|
+
"http://xmlns.com/foaf/0.1/age": 35,
|
|
197
|
+
"http://xmlns.com/foaf/0.1/knows": {
|
|
198
|
+
"http://xmlns.com/foaf/0.1/name": "Jane Doe",
|
|
199
|
+
"http://xmlns.com/foaf/0.1/age": 25
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
"""
|
|
204
|
+
if data is None:
|
|
205
|
+
return data
|
|
206
|
+
normalized: JSONdict = {}
|
|
207
|
+
for key, value in data.items():
|
|
208
|
+
assert isinstance(key, str)
|
|
209
|
+
if key == "@context":
|
|
210
|
+
continue
|
|
211
|
+
elif key.startswith("Q"):
|
|
212
|
+
expanded_key = key
|
|
213
|
+
else:
|
|
214
|
+
result = expand_uri(key, context)
|
|
215
|
+
assert isinstance(result, str) # for type checking
|
|
216
|
+
expanded_key = result
|
|
217
|
+
assert expanded_key.startswith("http") or expanded_key.startswith("@") or expanded_key.startswith("Q")
|
|
218
|
+
|
|
219
|
+
if hasattr(value, "__len__") and len(value) == 0:
|
|
220
|
+
pass
|
|
221
|
+
elif expanded_key == "@id":
|
|
222
|
+
if value.startswith("http"):
|
|
223
|
+
# do not take local ids, e.g., those starting with "_"
|
|
224
|
+
normalized[expanded_key] = value
|
|
225
|
+
elif expanded_key == "@type":
|
|
226
|
+
normalized[expanded_key] = value
|
|
227
|
+
elif isinstance(value, (list, tuple)):
|
|
228
|
+
normalized[expanded_key] = []
|
|
229
|
+
for item in value:
|
|
230
|
+
if isinstance(item, dict):
|
|
231
|
+
normalized[expanded_key].append(normalize_data(item, context))
|
|
232
|
+
else:
|
|
233
|
+
normalized[expanded_key].append(item)
|
|
234
|
+
elif isinstance(value, dict):
|
|
235
|
+
normalized[expanded_key] = normalize_data(value, context)
|
|
236
|
+
else:
|
|
237
|
+
normalized[expanded_key] = value
|
|
238
|
+
return normalized
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def in_notebook() -> bool:
|
|
242
|
+
try:
|
|
243
|
+
shell = get_ipython().__class__.__name__ # type: ignore
|
|
244
|
+
if shell == "ZMQInteractiveShell":
|
|
245
|
+
return True
|
|
246
|
+
elif shell == "TerminalInteractiveShell":
|
|
247
|
+
return False
|
|
248
|
+
else:
|
|
249
|
+
return False
|
|
250
|
+
except NameError:
|
|
251
|
+
return False
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def expand_filter(filter_dict: Dict[str, Any]):
|
|
255
|
+
"""
|
|
256
|
+
Expand single-level filter specification (provided by user) into
|
|
257
|
+
a multi-level dict as required by the query-generation machinery.
|
|
258
|
+
|
|
259
|
+
Example:
|
|
260
|
+
>>> filter = {
|
|
261
|
+
... "developers__affiliations__member_of__alias": "CNRS",
|
|
262
|
+
... "digital_identifier__identifier": "https://doi.org/some-doi"
|
|
263
|
+
... }
|
|
264
|
+
>>> expand_filter(filter)
|
|
265
|
+
{
|
|
266
|
+
"developers": {
|
|
267
|
+
"affiliations": {
|
|
268
|
+
"member_of": {
|
|
269
|
+
"alias": "CNRS
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
},
|
|
273
|
+
"digital_identifier": {
|
|
274
|
+
"identifier": "https://doi.org/some-doi"
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
"""
|
|
278
|
+
expanded = {}
|
|
279
|
+
for key, value in filter_dict.items():
|
|
280
|
+
if hasattr(value, "items"):
|
|
281
|
+
raise TypeError("Filter specifications should be a single-level dict, without nesting")
|
|
282
|
+
local_path = expanded
|
|
283
|
+
parts = key.split("__")
|
|
284
|
+
for part in parts[:-1]:
|
|
285
|
+
local_path[part] = {}
|
|
286
|
+
local_path = local_path[part]
|
|
287
|
+
local_path[parts[-1]] = value
|
|
288
|
+
return expanded
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
def sha1sum(filename):
|
|
292
|
+
BUFFER_SIZE = 128 * 1024
|
|
293
|
+
h = hashlib.sha1()
|
|
294
|
+
with open(filename, "rb") as fp:
|
|
295
|
+
while True:
|
|
296
|
+
data = fp.read(BUFFER_SIZE)
|
|
297
|
+
if not data:
|
|
298
|
+
break
|
|
299
|
+
h.update(data)
|
|
300
|
+
return h.hexdigest()
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
class LogEntry:
|
|
304
|
+
"""
|
|
305
|
+
Represents an entry in an activity log.
|
|
306
|
+
|
|
307
|
+
Attributes:
|
|
308
|
+
cls (str): The name of the class of the Knowledge Grapg object.
|
|
309
|
+
id (Optional[str]): The identifer of the object being logged.
|
|
310
|
+
delta (Optional[JSONdict]): A dictionary containing the changes made to the object.
|
|
311
|
+
space (Optional[str]): The Knowledge Graph space containing the object.
|
|
312
|
+
type_ (str): The type of the log entry.
|
|
313
|
+
"""
|
|
314
|
+
|
|
315
|
+
def __init__(
|
|
316
|
+
self,
|
|
317
|
+
cls: str,
|
|
318
|
+
id: Optional[str],
|
|
319
|
+
delta: Optional[JSONdict],
|
|
320
|
+
space: Optional[str],
|
|
321
|
+
type_: str,
|
|
322
|
+
):
|
|
323
|
+
self.cls = cls
|
|
324
|
+
self.id = id
|
|
325
|
+
self.delta = delta
|
|
326
|
+
self.space = space
|
|
327
|
+
self.type = type_
|
|
328
|
+
|
|
329
|
+
def __repr__(self):
|
|
330
|
+
return f"{self.type}: {self.cls}({self.id}) in '{self.space}'"
|
|
331
|
+
|
|
332
|
+
def as_dict(self):
|
|
333
|
+
return {
|
|
334
|
+
"cls": self.cls,
|
|
335
|
+
"id": self.id,
|
|
336
|
+
"delta": self.delta,
|
|
337
|
+
"space": self.space,
|
|
338
|
+
"type_": self.type
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
class ActivityLog:
|
|
343
|
+
"""
|
|
344
|
+
Represents a log of activities performed on Knowledge Graph objects.
|
|
345
|
+
|
|
346
|
+
Attributes:
|
|
347
|
+
entries (List[LogEntry]): A list of LogEntry objects representing the activities performed.
|
|
348
|
+
"""
|
|
349
|
+
|
|
350
|
+
def __init__(self):
|
|
351
|
+
self.entries = []
|
|
352
|
+
|
|
353
|
+
def update(self, item: KGObject, delta: Optional[JSONdict], space: Optional[str], entry_type: str):
|
|
354
|
+
"""
|
|
355
|
+
Adds a new log entry to the activity log.
|
|
356
|
+
|
|
357
|
+
Args:
|
|
358
|
+
item (KGObject): The object being logged.
|
|
359
|
+
delta (Optional[JSONdict]): A dictionary containing the changes made to the object.
|
|
360
|
+
space (Optional[str]): The Knowledge Graph space containing the object.
|
|
361
|
+
entry_type (str): The type of the log entry.
|
|
362
|
+
"""
|
|
363
|
+
self.entries.append(LogEntry(item.__class__.__name__, item.uuid, delta, space, entry_type))
|
|
364
|
+
|
|
365
|
+
def __repr__(self):
|
|
366
|
+
return "\n".join((str(entry) for entry in self.entries))
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
TERMS_OF_USE = """
|
|
370
|
+
# EBRAINS Knowledge Graph Data Platform Citation Requirements
|
|
371
|
+
|
|
372
|
+
This text is provided to describe the requirements for citing datasets,
|
|
373
|
+
models and software found via EBRAINS Knowledge Graph Data Platform (KG):
|
|
374
|
+
https://kg.ebrains.eu/search.
|
|
375
|
+
It is meant to provide a more human-readable form of key parts of the
|
|
376
|
+
KG Terms of Service, but in the event of disagreement between the KG Terms of
|
|
377
|
+
Service and these Citation Requirements, the former is to be taken as authoritative.
|
|
378
|
+
|
|
379
|
+
## Dataset, model and software licensing
|
|
380
|
+
|
|
381
|
+
Datasets, models and software in the KG have explicit licensing conditions attached.
|
|
382
|
+
The license is typically one of the Creative Commons licenses.
|
|
383
|
+
You must follow the licensing conditions attached to the dataset, model or software,
|
|
384
|
+
including all restrictions on commercial use, requirements for attribution or
|
|
385
|
+
requirements to share-alike.
|
|
386
|
+
|
|
387
|
+
## EBRAINS Knowledge Graph citation policy
|
|
388
|
+
|
|
389
|
+
If you use content or services from the EBRAINS Knowledge Graph (Search or API)
|
|
390
|
+
to advance a scientific publication you must follow the following citation policy:
|
|
391
|
+
|
|
392
|
+
1. For a dataset or model which is released under a Creative Commons license
|
|
393
|
+
which includes "Attribution":
|
|
394
|
+
|
|
395
|
+
1. Cite the dataset / model as defined in the provided citation instructions
|
|
396
|
+
("Cite dataset / model") and - if available - also cite the primary publication listed
|
|
397
|
+
|
|
398
|
+
or
|
|
399
|
+
|
|
400
|
+
2. in cases where neither citation instructions nor a primary publication are provided,
|
|
401
|
+
and only in such cases, the names of the contributors should be cited
|
|
402
|
+
(Data / model provided by Contributor 1, Contributor 2, …, and Contributor N) .
|
|
403
|
+
|
|
404
|
+
2. For software, please cite as defined in the software's respective citation policy.
|
|
405
|
+
If you can't identify a clear citation policy for the software in question,
|
|
406
|
+
use the open source repository as the citation link.
|
|
407
|
+
|
|
408
|
+
3. For EBRAINS services which were key in attaining your results, please consider
|
|
409
|
+
citing the corresponding software which the service relies on,
|
|
410
|
+
including but not limited to:
|
|
411
|
+
|
|
412
|
+
EBRAINS Knowledge Graph, "https://kg.ebrains.eu"
|
|
413
|
+
|
|
414
|
+
Failure to cite datasets, models, or software used in another publication or
|
|
415
|
+
presentation would constitute scientific misconduct.
|
|
416
|
+
Failure to cite datasets, models, or software used in a scientific publication
|
|
417
|
+
must be corrected by an Erratum and correction of the given article if it was
|
|
418
|
+
discovered post-publication.
|
|
419
|
+
|
|
420
|
+
## Final thoughts
|
|
421
|
+
|
|
422
|
+
Citations are essential for encouraging researchers to release their datasets,
|
|
423
|
+
models and software through the KG or other scientific sharing platforms.
|
|
424
|
+
Your citation may help them to get their next job or next grant and will
|
|
425
|
+
ultimately encourage researchers to produce and release more useful open data
|
|
426
|
+
and open source. Make science more reproducible and more efficient.
|
|
427
|
+
"""
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
def accepted_terms_of_use(client: KGClient, accept_terms_of_use: bool = False) -> bool:
|
|
431
|
+
if accept_terms_of_use or client.accepted_terms_of_use:
|
|
432
|
+
return True
|
|
433
|
+
else:
|
|
434
|
+
if in_notebook():
|
|
435
|
+
from IPython.display import display, Markdown # type: ignore
|
|
436
|
+
|
|
437
|
+
display(Markdown(TERMS_OF_USE))
|
|
438
|
+
else:
|
|
439
|
+
print(TERMS_OF_USE)
|
|
440
|
+
user_response = input("Do you accept the EBRAINS KG Terms of Service? ")
|
|
441
|
+
if user_response in ("y", "Y", "yes", "YES"):
|
|
442
|
+
client.accepted_terms_of_use = True
|
|
443
|
+
return True
|
|
444
|
+
else:
|
|
445
|
+
warnings.warn("Please accept the terms of use before downloading the dataset")
|
|
446
|
+
return False
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
def types_match(a, b):
|
|
450
|
+
# temporarily, during the openMINDS transition v3-v4, we allow different namespaces for the types
|
|
451
|
+
assert isinstance(a, str), a
|
|
452
|
+
assert isinstance(b, str), b
|
|
453
|
+
if a == b:
|
|
454
|
+
return True
|
|
455
|
+
elif a.split("/")[-1] == b.split("/")[-1]:
|
|
456
|
+
logger.warning(f"Assuming {a} matches {b} in types_match()")
|
|
457
|
+
return True
|
|
458
|
+
else:
|
|
459
|
+
return False
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
def _adapt_namespaces(data, adapt_keys, adapt_type, adapt_instance_uri):
|
|
463
|
+
if isinstance(data, list):
|
|
464
|
+
for item in data:
|
|
465
|
+
_adapt_namespaces(item, adapt_keys, adapt_type, adapt_instance_uri)
|
|
466
|
+
elif isinstance(data, dict):
|
|
467
|
+
# adapt property URIs
|
|
468
|
+
old_keys = tuple(data.keys())
|
|
469
|
+
new_keys = adapt_keys(old_keys)
|
|
470
|
+
for old_key, new_key in zip(old_keys, new_keys):
|
|
471
|
+
data[new_key] = data.pop(old_key)
|
|
472
|
+
for key, value in data.items():
|
|
473
|
+
if key == "@id":
|
|
474
|
+
data[key] = adapt_instance_uri(value)
|
|
475
|
+
elif isinstance(value, (list, dict)):
|
|
476
|
+
_adapt_namespaces(value, adapt_keys, adapt_type, adapt_instance_uri)
|
|
477
|
+
# adapt @type URIs
|
|
478
|
+
if "@type" in data:
|
|
479
|
+
data["@type"] = adapt_type(data["@type"])
|
|
480
|
+
else:
|
|
481
|
+
pass
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
def adapt_namespaces_3to4(data):
|
|
485
|
+
|
|
486
|
+
def adapt_keys_3to4(uri_list):
|
|
487
|
+
replacement = ("openminds.ebrains.eu/vocab", "openminds.om-i.org/props")
|
|
488
|
+
return (uri.replace(*replacement) for uri in uri_list)
|
|
489
|
+
|
|
490
|
+
def adapt_type_3to4(uri):
|
|
491
|
+
if isinstance(uri, list):
|
|
492
|
+
assert len(uri) == 1
|
|
493
|
+
uri = uri[0]
|
|
494
|
+
return f"https://openminds.om-i.org/types/{uri.split('/')[-1]}"
|
|
495
|
+
|
|
496
|
+
def adapt_instance_uri_3to4(uri):
|
|
497
|
+
if uri.startswith("https://openminds"):
|
|
498
|
+
return uri.replace("ebrains.eu", "om-i.org")
|
|
499
|
+
else:
|
|
500
|
+
return uri
|
|
501
|
+
|
|
502
|
+
return _adapt_namespaces(data, adapt_keys_3to4, adapt_type_3to4, adapt_instance_uri_3to4)
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
def adapt_type_4to3(uri):
|
|
506
|
+
if isinstance(uri, list):
|
|
507
|
+
assert len(uri) == 1
|
|
508
|
+
uri = uri[0]
|
|
509
|
+
cls = lookup_type(uri, OPENMINDS_VERSION)
|
|
510
|
+
|
|
511
|
+
if cls.__module__ == "test.test_client":
|
|
512
|
+
return cls.type_
|
|
513
|
+
|
|
514
|
+
module_name = cls.__module__.split(".")[2] # e.g., 'fairgraph.openminds.core.actors.person' -> "core"
|
|
515
|
+
module_name = {"controlled_terms": "controlledTerms", "specimen_prep": "specimenPrep"}.get(
|
|
516
|
+
module_name, module_name
|
|
517
|
+
)
|
|
518
|
+
return f"https://openminds.ebrains.eu/{module_name}/{cls.__name__}"
|
|
519
|
+
|
|
520
|
+
|
|
521
|
+
def adapt_namespaces_4to3(data):
|
|
522
|
+
|
|
523
|
+
def adapt_keys_4to3(uri_list):
|
|
524
|
+
replacement = ("openminds.om-i.org/props", "openminds.ebrains.eu/vocab")
|
|
525
|
+
return (uri.replace(*replacement) for uri in uri_list)
|
|
526
|
+
|
|
527
|
+
def adapt_instance_uri_4to3(uri):
|
|
528
|
+
if uri.startswith("https://openminds"):
|
|
529
|
+
return uri.replace("om-i.org", "ebrains.eu")
|
|
530
|
+
else:
|
|
531
|
+
return uri
|
|
532
|
+
|
|
533
|
+
return _adapt_namespaces(data, adapt_keys_4to3, adapt_type_4to3, adapt_instance_uri_4to3)
|
|
534
|
+
|
|
535
|
+
|
|
536
|
+
def adapt_namespaces_for_query(query):
|
|
537
|
+
"""Map from v4+ to v3 openMINDS namespace"""
|
|
538
|
+
|
|
539
|
+
def adapt_path(item_path, replacement):
|
|
540
|
+
if isinstance(item_path, str):
|
|
541
|
+
return item_path.replace(*replacement)
|
|
542
|
+
elif isinstance(item_path, list):
|
|
543
|
+
return [adapt_path(part, replacement) for part in item_path]
|
|
544
|
+
else:
|
|
545
|
+
assert isinstance(item_path, dict)
|
|
546
|
+
new_item_path = item_path.copy()
|
|
547
|
+
new_item_path["@id"] = item_path["@id"].replace(*replacement)
|
|
548
|
+
if "typeFilter" in item_path:
|
|
549
|
+
if isinstance(item_path["typeFilter"], list):
|
|
550
|
+
new_item_path["typeFilter"] = [
|
|
551
|
+
{"@id": adapt_type_4to3(subitem["@id"])} for subitem in item_path["typeFilter"]
|
|
552
|
+
]
|
|
553
|
+
else:
|
|
554
|
+
new_item_path["typeFilter"]["@id"] = adapt_type_4to3(item_path["typeFilter"]["@id"])
|
|
555
|
+
return new_item_path
|
|
556
|
+
|
|
557
|
+
def adapt_structure(structure, replacement):
|
|
558
|
+
for item in structure:
|
|
559
|
+
item["path"] = adapt_path(item["path"], replacement)
|
|
560
|
+
if "structure" in item:
|
|
561
|
+
adapt_structure(item["structure"], replacement)
|
|
562
|
+
|
|
563
|
+
def adapt_filters(structure, replacement):
|
|
564
|
+
for item in structure:
|
|
565
|
+
if "filter" in item and "value" in item["filter"]:
|
|
566
|
+
item["filter"]["value"] = item["filter"]["value"].replace(*replacement)
|
|
567
|
+
if "structure" in item:
|
|
568
|
+
adapt_filters(item["structure"], replacement)
|
|
569
|
+
|
|
570
|
+
migrated_query = deepcopy(query)
|
|
571
|
+
migrated_query["meta"]["type"] = adapt_type_4to3(migrated_query["meta"]["type"])
|
|
572
|
+
adapt_structure(migrated_query["structure"], ("openminds.om-i.org/props", "openminds.ebrains.eu/vocab"))
|
|
573
|
+
adapt_filters(migrated_query["structure"], ("openminds.om-i.org/instances", "openminds.ebrains.eu/instances"))
|
|
574
|
+
return migrated_query
|
|
575
|
+
|
|
576
|
+
|
|
577
|
+
def initialise_instances(class_list):
|
|
578
|
+
"""Cast openMINDS instances to their fairgraph subclass"""
|
|
579
|
+
for cls in class_list:
|
|
580
|
+
cls.set_error_handling(None)
|
|
581
|
+
# find parent openMINDS class
|
|
582
|
+
for parent_cls in cls.__mro__[1:]:
|
|
583
|
+
if parent_cls.__name__ == cls.__name__:
|
|
584
|
+
# could also do this by looking for issubclass(parent_cls, openminds.Node)
|
|
585
|
+
break
|
|
586
|
+
for key, value in parent_cls.__dict__.items():
|
|
587
|
+
if isinstance(value, parent_cls):
|
|
588
|
+
fg_instance = cls.from_jsonld(value.to_jsonld())
|
|
589
|
+
fg_instance._space = cls.default_space
|
|
590
|
+
setattr(cls, key, fg_instance)
|
|
591
|
+
cls.set_error_handling("log")
|
|
592
|
+
|
|
593
|
+
|
|
594
|
+
def handle_scope_keyword(scope, release_status):
|
|
595
|
+
"""
|
|
596
|
+
The keyword 'scope' has been renamed 'release_status',
|
|
597
|
+
use of 'scope' is deprecated but still accepted.
|
|
598
|
+
"""
|
|
599
|
+
if scope in ("released", "in progress", "any"):
|
|
600
|
+
warnings.warn(
|
|
601
|
+
"The keyword 'scope' is deprecated, and will be removed in version 1.0; it has been renamed to 'release_status'",
|
|
602
|
+
DeprecationWarning,
|
|
603
|
+
stacklevel=2,
|
|
604
|
+
)
|
|
605
|
+
return scope
|
|
606
|
+
else:
|
|
607
|
+
return release_status
|