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/kgproxy.py
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module provides the KGProxy class, which represents a
|
|
3
|
+
KGObject whose type and identifier are known but whose other metadata
|
|
4
|
+
have not been retrieved from the KG.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
# Copyright 2018-2024 CNRS
|
|
8
|
+
|
|
9
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
10
|
+
# you may not use this file except in compliance with the License.
|
|
11
|
+
# You may obtain a copy of the License at
|
|
12
|
+
|
|
13
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
14
|
+
|
|
15
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
16
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
17
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
18
|
+
# See the License for the specific language governing permissions and
|
|
19
|
+
# limitations under the License.
|
|
20
|
+
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
import logging
|
|
23
|
+
from typing import List, Optional, Tuple, Union, Dict, Any, TYPE_CHECKING
|
|
24
|
+
|
|
25
|
+
from openminds.base import Link
|
|
26
|
+
from openminds.registry import lookup
|
|
27
|
+
|
|
28
|
+
from .errors import ResolutionFailure
|
|
29
|
+
from .caching import object_cache
|
|
30
|
+
from .base import RepresentsSingleObject
|
|
31
|
+
|
|
32
|
+
if TYPE_CHECKING:
|
|
33
|
+
from .client import KGClient
|
|
34
|
+
from .kgobject import KGObject
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
logger = logging.getLogger("fairgraph")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class KGProxy(RepresentsSingleObject, Link):
|
|
41
|
+
"""
|
|
42
|
+
Representation of an KGObject whose identifier, and possibly type, are known but whose
|
|
43
|
+
other metadata have not been retrieved from the KG.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
cls (str, KGObject, List[KGObject]): the possible types of the associated KG object, defined by a KGObject subclass
|
|
47
|
+
or by the name of the subclass.
|
|
48
|
+
uri (URI): The global identifier of the KG object.
|
|
49
|
+
preferred_release_status (str, optional): The preferred scope used to resolve the proxy.
|
|
50
|
+
Valid values are "released", "in progress", or "any".
|
|
51
|
+
|
|
52
|
+
Example:
|
|
53
|
+
>>> import fairgraph.openminds
|
|
54
|
+
>>> proxy = KGProxy("openminds.core.Person", "https://kg.ebrains.eu/api/instances/bd554312-9829-4148-8803-cb873d0b32f9")
|
|
55
|
+
>>> person = proxy.resolve(kg_client)
|
|
56
|
+
>>> type(person)
|
|
57
|
+
<class 'fairgraph.openminds.core.actors.person.Person'>
|
|
58
|
+
>>> person.given_name
|
|
59
|
+
Andrew P.
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
# todo: rename uri to id, for consistency?
|
|
63
|
+
|
|
64
|
+
def __init__(
|
|
65
|
+
self,
|
|
66
|
+
classes: Union[str, KGObject, List[KGObject], Tuple[KGObject]],
|
|
67
|
+
uri: str,
|
|
68
|
+
preferred_release_status: str = "released",
|
|
69
|
+
):
|
|
70
|
+
self.classes: List[KGObject] # todo: make this a set?
|
|
71
|
+
if isinstance(classes, str):
|
|
72
|
+
resolved_cls = lookup(classes)
|
|
73
|
+
if TYPE_CHECKING:
|
|
74
|
+
assert isinstance(resolved_cls, KGObject)
|
|
75
|
+
self.classes = [resolved_cls]
|
|
76
|
+
elif isinstance(classes, (list, tuple)):
|
|
77
|
+
self.classes = list(classes)
|
|
78
|
+
else:
|
|
79
|
+
self.classes = [classes]
|
|
80
|
+
if TYPE_CHECKING:
|
|
81
|
+
assert all(isinstance(cls, KGObject) for cls in self.classes)
|
|
82
|
+
self.id = uri
|
|
83
|
+
self.preferred_release_status = preferred_release_status
|
|
84
|
+
self.remote_data = None
|
|
85
|
+
Link.__init__(self, self.id, allowed_types=self.classes)
|
|
86
|
+
|
|
87
|
+
@property
|
|
88
|
+
def type(self) -> List[str]:
|
|
89
|
+
"""
|
|
90
|
+
Provide the global identifiers of the object type (as a list of URIs).
|
|
91
|
+
"""
|
|
92
|
+
try:
|
|
93
|
+
return [cls.type_ for cls in self.classes]
|
|
94
|
+
except AttributeError as err:
|
|
95
|
+
raise AttributeError(f"{err} self.classes={self.classes}")
|
|
96
|
+
|
|
97
|
+
@property
|
|
98
|
+
def cls(self):
|
|
99
|
+
"""
|
|
100
|
+
For backwards compatibility
|
|
101
|
+
"""
|
|
102
|
+
if len(self.classes) == 1:
|
|
103
|
+
return self.classes[0]
|
|
104
|
+
else:
|
|
105
|
+
raise AttributeError("This KGProxy has multiple possible types, use the 'classes' attribute instead")
|
|
106
|
+
|
|
107
|
+
def to_jsonld(self, **kwargs):
|
|
108
|
+
return {"@id": self.id}
|
|
109
|
+
|
|
110
|
+
def resolve(
|
|
111
|
+
self,
|
|
112
|
+
client: KGClient,
|
|
113
|
+
release_status: Optional[str] = None,
|
|
114
|
+
use_cache: bool = True,
|
|
115
|
+
follow_links: Optional[Dict[str, Any]] = None,
|
|
116
|
+
):
|
|
117
|
+
"""
|
|
118
|
+
Retrieve the full metadata for the KGObject represented by this proxy.
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
client: a KGClient
|
|
122
|
+
release_status (str, optional): The scope of the lookup. Valid values are "released", "in progress", or "any".
|
|
123
|
+
If not provided, the "preferred_release_status" provided when creating the proxy object will be used.
|
|
124
|
+
use_cache (bool): Whether to use cached data if they exist. Defaults to True.
|
|
125
|
+
follow_links (dict): The links in the graph to follow. Defaults to None.
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
a KGObject instance, of the appropriate subclass.
|
|
129
|
+
"""
|
|
130
|
+
if use_cache and self.id in object_cache:
|
|
131
|
+
obj = object_cache[self.id]
|
|
132
|
+
else:
|
|
133
|
+
release_status = release_status or self.preferred_release_status
|
|
134
|
+
obj = None
|
|
135
|
+
for cls in self.classes:
|
|
136
|
+
# this is inefficient, we should just get the data from the id, then get the correct type from the data
|
|
137
|
+
try:
|
|
138
|
+
obj = cls.from_uri(self.id, client, release_status=release_status)
|
|
139
|
+
except TypeError:
|
|
140
|
+
pass
|
|
141
|
+
else:
|
|
142
|
+
break
|
|
143
|
+
if obj is None:
|
|
144
|
+
raise ResolutionFailure(f"Cannot resolve proxy object of type {self.classes} with id {self.uuid}")
|
|
145
|
+
object_cache[self.id] = obj
|
|
146
|
+
if follow_links:
|
|
147
|
+
return obj.resolve(client, release_status=release_status, use_cache=use_cache, follow_links=follow_links)
|
|
148
|
+
else:
|
|
149
|
+
return obj
|
|
150
|
+
|
|
151
|
+
def __repr__(self):
|
|
152
|
+
return f"""{self.__class__.__name__}([{", ".join(cls.__name__ for cls in self.classes)}], id="{self.id.split('/')[-1]}")"""
|
|
153
|
+
|
|
154
|
+
def __eq__(self, other):
|
|
155
|
+
return (
|
|
156
|
+
isinstance(other, self.__class__) and set(self.classes).intersection(other.classes) and self.id == other.id
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
def __ne__(self, other):
|
|
160
|
+
return (
|
|
161
|
+
not isinstance(other, self.__class__) or set(self.classes).isdisjoint(other.classes) or self.id != other.id
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
@property
|
|
165
|
+
def uuid(self) -> str:
|
|
166
|
+
return self.id.split("/")[-1]
|
|
167
|
+
|
|
168
|
+
def delete(self, client: KGClient, ignore_not_found: bool = True):
|
|
169
|
+
"""Delete the instance which this proxy represents"""
|
|
170
|
+
try:
|
|
171
|
+
obj = self.resolve(client, release_status="in progress")
|
|
172
|
+
except ResolutionFailure as err:
|
|
173
|
+
logger.warning(str(err))
|
|
174
|
+
obj = None
|
|
175
|
+
if obj:
|
|
176
|
+
obj.delete(client, ignore_not_found=ignore_not_found)
|
|
177
|
+
elif not ignore_not_found:
|
|
178
|
+
raise ResolutionFailure("Couldn't resolve object to delete")
|
fairgraph/kgquery.py
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module provides the KGQuery class, which represents one or more
|
|
3
|
+
KGObjects identified by a range of possible types and by some of their
|
|
4
|
+
metadata, but whose specific identifier(s) is/are not known.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
# Copyright 2018-2024 CNRS
|
|
8
|
+
|
|
9
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
10
|
+
# you may not use this file except in compliance with the License.
|
|
11
|
+
# You may obtain a copy of the License at
|
|
12
|
+
|
|
13
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
14
|
+
|
|
15
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
16
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
17
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
18
|
+
# See the License for the specific language governing permissions and
|
|
19
|
+
# limitations under the License.
|
|
20
|
+
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
import logging
|
|
23
|
+
from typing import Dict, List, Optional, Union, Any, TYPE_CHECKING
|
|
24
|
+
|
|
25
|
+
from openminds.registry import lookup
|
|
26
|
+
|
|
27
|
+
from .utility import as_list, expand_filter
|
|
28
|
+
from .caching import object_cache
|
|
29
|
+
from .base import Resolvable, SupportsQuerying
|
|
30
|
+
|
|
31
|
+
if TYPE_CHECKING:
|
|
32
|
+
from .client import KGClient
|
|
33
|
+
from .kgobject import KGObject
|
|
34
|
+
|
|
35
|
+
logger = logging.getLogger("fairgraph")
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class KGQuery(Resolvable, SupportsQuerying):
|
|
39
|
+
"""
|
|
40
|
+
Representation of one or more KGObjects identified by a range of possible types
|
|
41
|
+
and by some of their metadata, but whose specific identifier(s) is/are not known.
|
|
42
|
+
|
|
43
|
+
It is possible that no KGObjects match the types/metadata.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
classes (list of KGObject subclasses): a list of types to query.
|
|
47
|
+
filter (dict): key:value pairs that should be matched. All pairs must match.
|
|
48
|
+
preferred_release_status (str): The preferred scope used to resolve the query.
|
|
49
|
+
Valid values are "released", "in progress", or "any".
|
|
50
|
+
|
|
51
|
+
Example:
|
|
52
|
+
>>> import fairgraph.openminds.core as omcore
|
|
53
|
+
>>> from fairgraph.utility import as_list
|
|
54
|
+
>>> query = KGQuery([omcore.Person], {"family_name": "Amunts"})
|
|
55
|
+
>>> people = as_list(query.resolve(kg_client))
|
|
56
|
+
>>> len(people)
|
|
57
|
+
1
|
|
58
|
+
>>> people[0].family_name
|
|
59
|
+
Amunts
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
def __init__(
|
|
63
|
+
self,
|
|
64
|
+
classes: Union[str, KGObject, List[Union[str, KGObject]]],
|
|
65
|
+
filter: Dict[str, str],
|
|
66
|
+
preferred_release_status: str = "released",
|
|
67
|
+
):
|
|
68
|
+
self.classes: List[KGObject] = []
|
|
69
|
+
for cls in as_list(classes):
|
|
70
|
+
if isinstance(cls, str):
|
|
71
|
+
resolved_cls = lookup(cls)
|
|
72
|
+
assert isinstance(resolved_cls, KGObject)
|
|
73
|
+
self.classes.append(resolved_cls)
|
|
74
|
+
else:
|
|
75
|
+
self.classes.append(cls)
|
|
76
|
+
self.filter = filter
|
|
77
|
+
self.preferred_release_status = preferred_release_status
|
|
78
|
+
|
|
79
|
+
def __repr__(self):
|
|
80
|
+
return f"""{self.__class__.__name__}([{", ".join(cls.__name__ for cls in self.classes)}], filter="{self.filter!r}")""".replace(
|
|
81
|
+
"https://kg.ebrains.eu/api/instances/", ""
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
def resolve(
|
|
85
|
+
self,
|
|
86
|
+
client: KGClient,
|
|
87
|
+
size: int = 10000,
|
|
88
|
+
from_index: int = 0,
|
|
89
|
+
space: Optional[str] = None,
|
|
90
|
+
release_status: Optional[str] = None,
|
|
91
|
+
use_cache: bool = True,
|
|
92
|
+
follow_links: Optional[Dict[str, Any]] = None,
|
|
93
|
+
with_reverse_properties: Optional[bool] = False,
|
|
94
|
+
):
|
|
95
|
+
"""
|
|
96
|
+
Retrieve the full metadata for the KGObject(s) represented by this query object.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
client: a KGClient
|
|
100
|
+
from_index: The index of the first result to include in the response.
|
|
101
|
+
size: The maximum number of results to include in the response.
|
|
102
|
+
space: If specified, queries only in the given space.
|
|
103
|
+
release_status (str, optional): The scope of the query. Valid values are "released", "in progress", or "any".
|
|
104
|
+
If not provided, the "preferred_release_status" provided when creating the proxy object will be used.
|
|
105
|
+
use_cache (bool): Whether to use cached data if they exist. Defaults to True.
|
|
106
|
+
follow_links (dict): The links in the graph to follow. Defaults to None.
|
|
107
|
+
with_reverse_properties (dict): Whether to include reverse properties. Defaults to False.
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
a KGObject instance, of the appropriate subclass.
|
|
111
|
+
"""
|
|
112
|
+
release_status = release_status or self.preferred_release_status
|
|
113
|
+
objects: List[KGObject] = []
|
|
114
|
+
for cls in self.classes:
|
|
115
|
+
if hasattr(cls, "generate_query"):
|
|
116
|
+
# if cls is EmbeddedMetadata we cannot query it
|
|
117
|
+
query = cls.generate_query(
|
|
118
|
+
client=client,
|
|
119
|
+
filters=self.filter,
|
|
120
|
+
space=space,
|
|
121
|
+
follow_links=follow_links,
|
|
122
|
+
with_reverse_properties=with_reverse_properties,
|
|
123
|
+
)
|
|
124
|
+
instances = client.query(
|
|
125
|
+
query=query,
|
|
126
|
+
size=size,
|
|
127
|
+
from_index=from_index,
|
|
128
|
+
release_status=release_status,
|
|
129
|
+
).data
|
|
130
|
+
objects.extend(cls.from_jsonld(instance_data, client) for instance_data in instances)
|
|
131
|
+
for obj in objects:
|
|
132
|
+
object_cache[obj.id] = obj
|
|
133
|
+
|
|
134
|
+
if follow_links:
|
|
135
|
+
for obj in objects:
|
|
136
|
+
obj.resolve(client, release_status=release_status, use_cache=use_cache, follow_links=follow_links)
|
|
137
|
+
|
|
138
|
+
if len(objects) == 1:
|
|
139
|
+
return objects[0]
|
|
140
|
+
else:
|
|
141
|
+
return objects
|
|
142
|
+
|
|
143
|
+
def count(self, client: KGClient, space: Optional[str] = None, release_status: Optional[str] = None):
|
|
144
|
+
"""
|
|
145
|
+
Return the number of objects that would be returned by resolving this query.
|
|
146
|
+
"""
|
|
147
|
+
release_status = release_status or self.preferred_release_status
|
|
148
|
+
n = 0
|
|
149
|
+
for cls in self.classes:
|
|
150
|
+
n += cls.count(client, api="query", release_status=release_status, space=space, **self.filter)
|
|
151
|
+
return n
|