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/node.py
ADDED
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
from typing import TYPE_CHECKING, Optional, Dict, List, Union, Any
|
|
3
|
+
from copy import copy
|
|
4
|
+
from itertools import chain
|
|
5
|
+
import logging
|
|
6
|
+
from warnings import warn
|
|
7
|
+
|
|
8
|
+
from openminds.base import value_to_jsonld, Link
|
|
9
|
+
from openminds.properties import Property
|
|
10
|
+
|
|
11
|
+
from .registry import Node
|
|
12
|
+
from .base import Resolvable, ErrorHandling, RepresentsSingleObject
|
|
13
|
+
from .kgproxy import KGProxy
|
|
14
|
+
from .kgquery import KGQuery
|
|
15
|
+
from .queries import QueryProperty, get_query_properties, get_query_filter_property, get_filter_value
|
|
16
|
+
from .errors import ResolutionFailure, CannotBuildExistenceQuery
|
|
17
|
+
from .utility import (
|
|
18
|
+
as_list, # temporary for backwards compatibility (a lot of code imports it from here)
|
|
19
|
+
expand_uri,
|
|
20
|
+
invert_dict,
|
|
21
|
+
normalize_data,
|
|
22
|
+
types_match,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
if TYPE_CHECKING:
|
|
26
|
+
from .client import KGClient
|
|
27
|
+
from .utility import ActivityLog
|
|
28
|
+
|
|
29
|
+
logger = logging.getLogger("fairgraph")
|
|
30
|
+
|
|
31
|
+
JSONdict = Dict[str, Any] # see https://github.com/python/typing/issues/182 for some possible improvements
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class ContainsMetadata(Resolvable, metaclass=Node): # KGObject and EmbeddedMetadata
|
|
35
|
+
properties: List[Property]
|
|
36
|
+
reverse_properties: List[Property] = []
|
|
37
|
+
context: Dict[str, str]
|
|
38
|
+
type_: str
|
|
39
|
+
release_status: Optional[str]
|
|
40
|
+
space: Union[str, None]
|
|
41
|
+
default_space: Union[str, None]
|
|
42
|
+
remote_data: Optional[JSONdict]
|
|
43
|
+
aliases: Dict[str, str] = {}
|
|
44
|
+
error_handling: ErrorHandling = ErrorHandling.log
|
|
45
|
+
|
|
46
|
+
def __init__(self, data: Optional[Dict] = None, **properties):
|
|
47
|
+
properties_copy = copy(properties)
|
|
48
|
+
for prop in self.__class__.all_properties:
|
|
49
|
+
try:
|
|
50
|
+
val = properties[prop.name]
|
|
51
|
+
except KeyError:
|
|
52
|
+
if prop.required:
|
|
53
|
+
msg = "Property '{}' is required.".format(prop.name)
|
|
54
|
+
ErrorHandling.handle_violation(self.error_handling, msg)
|
|
55
|
+
val = None
|
|
56
|
+
else:
|
|
57
|
+
properties_copy.pop(prop.name)
|
|
58
|
+
if isinstance(val, (list, tuple)) and len(val) == 0: # empty list
|
|
59
|
+
val = None
|
|
60
|
+
setattr(self, prop.name, val)
|
|
61
|
+
for name_, alias_ in self.aliases.items():
|
|
62
|
+
# the trailing underscores are because 'name' and 'alias' can be keys in 'properties'
|
|
63
|
+
if name_ in properties_copy:
|
|
64
|
+
val = properties_copy.pop(name_)
|
|
65
|
+
if val is not None:
|
|
66
|
+
if properties.get(alias_, None):
|
|
67
|
+
raise ValueError(f"'{name_}' is an alias for '{alias_}', you cannot specify both")
|
|
68
|
+
setattr(self, alias_, val)
|
|
69
|
+
if len(properties_copy) > 0:
|
|
70
|
+
if len(properties_copy) == 1:
|
|
71
|
+
raise NameError(
|
|
72
|
+
f'{self.__class__.__name__} does not have a property named "{list(properties_copy)[0]}".'
|
|
73
|
+
)
|
|
74
|
+
else:
|
|
75
|
+
raise NameError(
|
|
76
|
+
f"""{self.__class__.__name__} does not have properties named "{'", "'.join(properties_copy)}"."""
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
def __getattribute__(self, name):
|
|
80
|
+
try:
|
|
81
|
+
return object.__getattribute__(self, name)
|
|
82
|
+
except AttributeError:
|
|
83
|
+
if name in self.aliases:
|
|
84
|
+
return object.__getattribute__(self, self.aliases[name])
|
|
85
|
+
else:
|
|
86
|
+
raise
|
|
87
|
+
|
|
88
|
+
def __setattr__(self, name, value):
|
|
89
|
+
try:
|
|
90
|
+
prop = self._property_lookup[name]
|
|
91
|
+
except KeyError:
|
|
92
|
+
if name in self.aliases:
|
|
93
|
+
setattr(self, self.aliases[name], value)
|
|
94
|
+
else:
|
|
95
|
+
super().__setattr__(name, value)
|
|
96
|
+
else:
|
|
97
|
+
if not isinstance(value, KGQuery):
|
|
98
|
+
failures = prop.validate(value)
|
|
99
|
+
if failures:
|
|
100
|
+
errmsg = str(failures) # todo: create a nicer error message
|
|
101
|
+
ErrorHandling.handle_violation(self.error_handling, errmsg)
|
|
102
|
+
super().__setattr__(name, value)
|
|
103
|
+
|
|
104
|
+
@classmethod
|
|
105
|
+
def get_property(cls, name):
|
|
106
|
+
return cls._property_lookup[name]
|
|
107
|
+
|
|
108
|
+
@classmethod
|
|
109
|
+
def from_jsonld(cls, data: JSONdict, release_status: Optional[str] = None) -> ContainsMetadata:
|
|
110
|
+
"""
|
|
111
|
+
Create an instance of the class from a JSON-LD document.
|
|
112
|
+
"""
|
|
113
|
+
raise NotImplementedError("This should be implemented by subclasses")
|
|
114
|
+
|
|
115
|
+
def save(
|
|
116
|
+
self,
|
|
117
|
+
client: KGClient,
|
|
118
|
+
space: Optional[str] = None,
|
|
119
|
+
recursive: bool = True,
|
|
120
|
+
activity_log: Optional[ActivityLog] = None,
|
|
121
|
+
replace: bool = False,
|
|
122
|
+
ignore_auth_errors: bool = False,
|
|
123
|
+
ignore_duplicates: bool = False,
|
|
124
|
+
):
|
|
125
|
+
raise NotImplementedError("This should be implemented by subclasses")
|
|
126
|
+
|
|
127
|
+
@classmethod
|
|
128
|
+
def set_error_handling(cls, value: Union[ErrorHandling, None]):
|
|
129
|
+
"""
|
|
130
|
+
Control validation for this class.
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
value (str): action to follow when there is a validation failure.
|
|
134
|
+
(e.g. if a required property is not provided).
|
|
135
|
+
Possible values: "error", "warning", "log", None
|
|
136
|
+
"""
|
|
137
|
+
if value is None:
|
|
138
|
+
value = ErrorHandling.none
|
|
139
|
+
else:
|
|
140
|
+
value = ErrorHandling(value)
|
|
141
|
+
cls.error_handling = value
|
|
142
|
+
# set the same action for all embedded types
|
|
143
|
+
for prop in cls.properties:
|
|
144
|
+
for type_ in prop.types:
|
|
145
|
+
if issubclass(type_, ContainsMetadata) and not issubclass(type_, RepresentsSingleObject):
|
|
146
|
+
# i.e., is EmbeddedMetadata
|
|
147
|
+
type_.set_error_handling(value)
|
|
148
|
+
|
|
149
|
+
@classmethod
|
|
150
|
+
def normalize_filter(cls, filter_dict: Dict[str, Any], check_validity: bool = True) -> Dict[str, Any]:
|
|
151
|
+
"""
|
|
152
|
+
Normalize a dict containing filter key:value pairs so that it can be used
|
|
153
|
+
in a call to the KG query API.
|
|
154
|
+
|
|
155
|
+
Example:
|
|
156
|
+
>>> import fairgraph.openminds.core as omcore
|
|
157
|
+
>>> person = omcore.Person.from_uuid("045f846f-f010-4db8-97b9-b95b20970bf2", kg_client)
|
|
158
|
+
>>> filter_dict = {"custodians": person, "name": "Virtual"}
|
|
159
|
+
>>> omcore.Dataset.normalize_filter(filter_dict)
|
|
160
|
+
{'name': 'Virtual',
|
|
161
|
+
'custodians': 'https://kg.ebrains.eu/api/instances/045f846f-f010-4db8-97b9-b95b20970bf2'}
|
|
162
|
+
"""
|
|
163
|
+
normalized = {}
|
|
164
|
+
filter_dict_copy = filter_dict.copy()
|
|
165
|
+
|
|
166
|
+
# handle aliases
|
|
167
|
+
for name_, alias_ in cls.aliases.items():
|
|
168
|
+
if name_ in filter_dict_copy:
|
|
169
|
+
filter_dict_copy[alias_] = filter_dict_copy.pop(name_)
|
|
170
|
+
|
|
171
|
+
def _check_validity(filters, property_names):
|
|
172
|
+
invalid_filters = set(filters).difference(property_names)
|
|
173
|
+
if invalid_filters:
|
|
174
|
+
if len(invalid_filters) == 1:
|
|
175
|
+
msg = f"Invalid filter: "
|
|
176
|
+
else:
|
|
177
|
+
msg = f"Invalid filters: "
|
|
178
|
+
raise ValueError(msg + ", ".join(sorted(invalid_filters)))
|
|
179
|
+
|
|
180
|
+
if check_validity:
|
|
181
|
+
_check_validity(filter_dict_copy, cls.all_property_names + list(cls.aliases.keys()))
|
|
182
|
+
|
|
183
|
+
for prop in cls.all_properties:
|
|
184
|
+
if prop.name in filter_dict_copy:
|
|
185
|
+
value = filter_dict_copy[prop.name]
|
|
186
|
+
if isinstance(value, dict):
|
|
187
|
+
_check_validity(
|
|
188
|
+
value,
|
|
189
|
+
set(
|
|
190
|
+
chain(
|
|
191
|
+
*(
|
|
192
|
+
child_cls.all_property_names + list(child_cls.aliases.keys())
|
|
193
|
+
for child_cls in prop.types
|
|
194
|
+
)
|
|
195
|
+
)
|
|
196
|
+
),
|
|
197
|
+
)
|
|
198
|
+
normalized[prop.name] = {}
|
|
199
|
+
for child_cls in prop.types:
|
|
200
|
+
normalized[prop.name].update(child_cls.normalize_filter(value, check_validity=False))
|
|
201
|
+
else:
|
|
202
|
+
normalized[prop.name] = get_filter_value(prop, value)
|
|
203
|
+
|
|
204
|
+
return normalized
|
|
205
|
+
|
|
206
|
+
@classmethod
|
|
207
|
+
def generate_query_properties(
|
|
208
|
+
cls, follow_links: Optional[Dict[str, Any]] = None, with_reverse_properties: Optional[bool] = False
|
|
209
|
+
):
|
|
210
|
+
"""
|
|
211
|
+
Generate a list of QueryProperty instances for this class
|
|
212
|
+
for use in constructing a KG query definition.
|
|
213
|
+
|
|
214
|
+
Args:
|
|
215
|
+
follow_links (dict): The links in the graph to follow when constructing the query.
|
|
216
|
+
Defaults to None.
|
|
217
|
+
with_reverse_properties (bool): Whether to include reverse properties.
|
|
218
|
+
Defaults to False.`
|
|
219
|
+
"""
|
|
220
|
+
if issubclass(cls, RepresentsSingleObject): # KGObject
|
|
221
|
+
query_properties = [
|
|
222
|
+
QueryProperty("https://core.kg.ebrains.eu/vocab/meta/space", name="query:space"),
|
|
223
|
+
QueryProperty("@type"),
|
|
224
|
+
]
|
|
225
|
+
else: # EmbeddedMetadata
|
|
226
|
+
query_properties = [QueryProperty("@type")]
|
|
227
|
+
reverse_aliases = invert_dict(cls.aliases)
|
|
228
|
+
|
|
229
|
+
if with_reverse_properties:
|
|
230
|
+
included_properties = cls.all_properties
|
|
231
|
+
else:
|
|
232
|
+
included_properties = cls.properties[:] # need to make a copy because we may be appending to it
|
|
233
|
+
if follow_links:
|
|
234
|
+
for prop_name in follow_links:
|
|
235
|
+
try:
|
|
236
|
+
prop = cls.get_property(prop_name)
|
|
237
|
+
# where a property can be of multiple types,
|
|
238
|
+
# not all types may be relevant to follow_links
|
|
239
|
+
except KeyError:
|
|
240
|
+
pass
|
|
241
|
+
else:
|
|
242
|
+
if prop.reverse:
|
|
243
|
+
included_properties.append(prop)
|
|
244
|
+
|
|
245
|
+
for prop in included_properties:
|
|
246
|
+
if prop.is_link and follow_links:
|
|
247
|
+
if prop.name in follow_links:
|
|
248
|
+
query_properties.extend(
|
|
249
|
+
get_query_properties(prop, cls.context, follow_links[prop.name], with_reverse_properties)
|
|
250
|
+
)
|
|
251
|
+
elif reverse_aliases.get(prop.name, None) in follow_links:
|
|
252
|
+
query_properties.extend(
|
|
253
|
+
get_query_properties(
|
|
254
|
+
prop, cls.context, follow_links[reverse_aliases[prop.name]], with_reverse_properties
|
|
255
|
+
)
|
|
256
|
+
)
|
|
257
|
+
else:
|
|
258
|
+
query_properties.extend(
|
|
259
|
+
get_query_properties(prop, cls.context, with_reverse_properties=with_reverse_properties)
|
|
260
|
+
)
|
|
261
|
+
else:
|
|
262
|
+
query_properties.extend(
|
|
263
|
+
get_query_properties(prop, cls.context, with_reverse_properties=with_reverse_properties)
|
|
264
|
+
)
|
|
265
|
+
return query_properties
|
|
266
|
+
|
|
267
|
+
@classmethod
|
|
268
|
+
def generate_query_filter_properties(
|
|
269
|
+
cls,
|
|
270
|
+
filters: Optional[Dict[str, Any]] = None,
|
|
271
|
+
):
|
|
272
|
+
"""
|
|
273
|
+
|
|
274
|
+
Args:
|
|
275
|
+
filters (dict, optional): A dict containing search parameters for the query.
|
|
276
|
+
"""
|
|
277
|
+
if filters is None:
|
|
278
|
+
filters = {}
|
|
279
|
+
properties = []
|
|
280
|
+
for prop in cls.all_properties:
|
|
281
|
+
if prop.name in filters:
|
|
282
|
+
properties.append(get_query_filter_property(prop, cls.context, filters[prop.name]))
|
|
283
|
+
return properties
|
|
284
|
+
|
|
285
|
+
@classmethod
|
|
286
|
+
def _deserialize_data(cls, data: JSONdict, include_id: bool = False):
|
|
287
|
+
|
|
288
|
+
def _get_type_from_data(data_item):
|
|
289
|
+
# KG returns a list of types, openMINDS expects only a single string
|
|
290
|
+
if isinstance(data_item, dict) and "@type" in data_item:
|
|
291
|
+
if isinstance(data_item["@type"], (list, tuple)):
|
|
292
|
+
assert len(data_item["@type"]) == 1
|
|
293
|
+
return data_item["@type"][0]
|
|
294
|
+
else:
|
|
295
|
+
return data_item["@type"]
|
|
296
|
+
else:
|
|
297
|
+
return None
|
|
298
|
+
|
|
299
|
+
def _normalize_type(data_item):
|
|
300
|
+
# replace @type as list with @type as string
|
|
301
|
+
if isinstance(data_item, (list, tuple)):
|
|
302
|
+
data_item = [_normalize_type(part) for part in data_item]
|
|
303
|
+
else:
|
|
304
|
+
type_from_data_item = _get_type_from_data(data_item)
|
|
305
|
+
if type_from_data_item:
|
|
306
|
+
data_item = data_item.copy()
|
|
307
|
+
data_item["@type"] = type_from_data_item
|
|
308
|
+
return data_item
|
|
309
|
+
|
|
310
|
+
type_from_data = _get_type_from_data(data)
|
|
311
|
+
# check types match
|
|
312
|
+
if not types_match(cls.type_, type_from_data):
|
|
313
|
+
raise TypeError("type mismatch {} - {}".format(cls.type_, type_from_data))
|
|
314
|
+
|
|
315
|
+
# normalize data by expanding keys
|
|
316
|
+
D = {"@type": type_from_data}
|
|
317
|
+
if "@context" in data:
|
|
318
|
+
context = data["@context"]
|
|
319
|
+
else:
|
|
320
|
+
context = cls.context
|
|
321
|
+
if include_id and "@id" in data:
|
|
322
|
+
D["@id"] = data["@id"]
|
|
323
|
+
for key, value in data.items():
|
|
324
|
+
if "__" in key:
|
|
325
|
+
key, type_filter = key.split("__")
|
|
326
|
+
normalised_key = expand_uri(key, context)
|
|
327
|
+
value = [item for item in as_list(value) if _get_type_from_data(item).endswith(type_filter)]
|
|
328
|
+
if normalised_key in D:
|
|
329
|
+
if isinstance(D[normalised_key], list):
|
|
330
|
+
D[normalised_key].extend(value)
|
|
331
|
+
else:
|
|
332
|
+
D[normalised_key] = [D[normalised_key]] + value
|
|
333
|
+
else:
|
|
334
|
+
D[normalised_key] = value
|
|
335
|
+
elif key.startswith("Q"): # for 'Q' properties in data from queries
|
|
336
|
+
D[key] = value
|
|
337
|
+
elif key[0] != "@":
|
|
338
|
+
normalised_key = expand_uri(key, context)
|
|
339
|
+
D[normalised_key] = value
|
|
340
|
+
|
|
341
|
+
deserialized_data = {}
|
|
342
|
+
for prop in cls.all_properties:
|
|
343
|
+
expanded_path = expand_uri(prop.path, cls.context)
|
|
344
|
+
data_item = _normalize_type(D.get(expanded_path))
|
|
345
|
+
|
|
346
|
+
if data_item is not None and prop.reverse:
|
|
347
|
+
# for reverse properties, more than one property can have the same path
|
|
348
|
+
# so we extract only those sub-items whose types match
|
|
349
|
+
try:
|
|
350
|
+
data_item = [
|
|
351
|
+
part
|
|
352
|
+
for part in as_list(data_item)
|
|
353
|
+
if _get_type_from_data(part) in [t.type_ for t in prop.types]
|
|
354
|
+
]
|
|
355
|
+
except AttributeError:
|
|
356
|
+
# problem when a forward and reverse path both given the same expanded path
|
|
357
|
+
# e.g. for Configuration
|
|
358
|
+
data_item = None
|
|
359
|
+
|
|
360
|
+
# sometimes queries put single items in a list, this removes the enclosing list
|
|
361
|
+
if (not prop.multiple) and isinstance(data_item, (list, tuple)) and len(data_item) == 1:
|
|
362
|
+
data_item = data_item[0]
|
|
363
|
+
|
|
364
|
+
if data_item is None:
|
|
365
|
+
if prop.reverse and "@id" in data:
|
|
366
|
+
if isinstance(prop.reverse, list):
|
|
367
|
+
# todo: handle all possible reverses
|
|
368
|
+
# for now, we just take the first
|
|
369
|
+
deserialized_data[prop.name] = KGQuery(prop.types, {prop.reverse[0]: data["@id"]})
|
|
370
|
+
else:
|
|
371
|
+
deserialized_data[prop.name] = KGQuery(prop.types, {prop.reverse: data["@id"]})
|
|
372
|
+
else:
|
|
373
|
+
deserialized_data[prop.name] = None
|
|
374
|
+
else:
|
|
375
|
+
try:
|
|
376
|
+
value = prop.deserialize(data_item)
|
|
377
|
+
except ValueError as err:
|
|
378
|
+
ErrorHandling.handle_violation(cls.error_handling, str(err))
|
|
379
|
+
else:
|
|
380
|
+
if isinstance(value, Link) and value.allowed_types is not None:
|
|
381
|
+
value = KGProxy(value.allowed_types, value.identifier)
|
|
382
|
+
elif isinstance(value, list) and len(value) > 0 and isinstance(value[0], Link):
|
|
383
|
+
# here we assume that if the first item is a Link, they all are
|
|
384
|
+
value = [KGProxy(item.allowed_types, item.identifier) for item in value]
|
|
385
|
+
deserialized_data[prop.name] = value
|
|
386
|
+
|
|
387
|
+
return deserialized_data
|
|
388
|
+
|
|
389
|
+
def resolve(
|
|
390
|
+
self,
|
|
391
|
+
client: KGClient,
|
|
392
|
+
release_status: Optional[str] = None,
|
|
393
|
+
use_cache: bool = True,
|
|
394
|
+
follow_links: Optional[Dict[str, Any]] = None,
|
|
395
|
+
):
|
|
396
|
+
"""
|
|
397
|
+
Resolve properties that are represented by KGProxy objects.
|
|
398
|
+
|
|
399
|
+
Args:
|
|
400
|
+
client: KGClient object that handles the communication with the KG.
|
|
401
|
+
release_status (str): The scope of instances to include in the response.
|
|
402
|
+
Valid values are 'released', 'in progress', 'any'.
|
|
403
|
+
use_cache (bool): whether to use cached data if they exist. Defaults to True.
|
|
404
|
+
follow_links (dict): The links in the graph to follow. Defaults to None.
|
|
405
|
+
|
|
406
|
+
Note: a real (non-proxy) object resolves to itself.
|
|
407
|
+
"""
|
|
408
|
+
use_release_status = release_status or self.release_status or "released"
|
|
409
|
+
if follow_links:
|
|
410
|
+
reverse_aliases = invert_dict(self.__class__.aliases)
|
|
411
|
+
for prop in self.__class__.all_properties:
|
|
412
|
+
if prop.is_link:
|
|
413
|
+
follow_name = None
|
|
414
|
+
if prop.name in follow_links:
|
|
415
|
+
follow_name = prop.name
|
|
416
|
+
elif reverse_aliases.get(prop.name, None) in follow_links:
|
|
417
|
+
follow_name = reverse_aliases[prop.name]
|
|
418
|
+
|
|
419
|
+
if follow_name:
|
|
420
|
+
if issubclass(prop.types[0], ContainsMetadata):
|
|
421
|
+
values = getattr(self, prop.name)
|
|
422
|
+
resolved_values: List[Any] = []
|
|
423
|
+
for value in as_list(values):
|
|
424
|
+
if isinstance(value, Resolvable):
|
|
425
|
+
if isinstance(value, ContainsMetadata) and isinstance(
|
|
426
|
+
value, RepresentsSingleObject
|
|
427
|
+
):
|
|
428
|
+
# i.e. isinstance(value, KGObject) - already resolved
|
|
429
|
+
resolved_values.append(value)
|
|
430
|
+
else:
|
|
431
|
+
try:
|
|
432
|
+
resolved_value = value.resolve(
|
|
433
|
+
client,
|
|
434
|
+
release_status=use_release_status,
|
|
435
|
+
use_cache=use_cache,
|
|
436
|
+
follow_links=follow_links[follow_name],
|
|
437
|
+
)
|
|
438
|
+
except ResolutionFailure as err:
|
|
439
|
+
warn(str(err))
|
|
440
|
+
resolved_values.append(value)
|
|
441
|
+
else:
|
|
442
|
+
resolved_values.append(resolved_value)
|
|
443
|
+
if isinstance(values, RepresentsSingleObject):
|
|
444
|
+
assert len(resolved_values) == 1
|
|
445
|
+
setattr(self, prop.name, resolved_values[0])
|
|
446
|
+
elif values is None:
|
|
447
|
+
assert len(resolved_values) == 0
|
|
448
|
+
setattr(self, prop.name, None)
|
|
449
|
+
else:
|
|
450
|
+
setattr(self, prop.name, resolved_values)
|
|
451
|
+
return self
|
|
452
|
+
|
|
453
|
+
def _build_existence_query(self) -> Union[None, Dict[str, Any]]:
|
|
454
|
+
"""
|
|
455
|
+
Generate a KG query definition (as a JSON-LD document) that can be used to
|
|
456
|
+
check whether a locally-defined object (with no ID) already exists in the KG.
|
|
457
|
+
"""
|
|
458
|
+
if self.existence_query_properties is None:
|
|
459
|
+
return None
|
|
460
|
+
|
|
461
|
+
query_properties = []
|
|
462
|
+
for property_name in self.existence_query_properties:
|
|
463
|
+
for property in self.__class__.all_properties:
|
|
464
|
+
if property.name == property_name:
|
|
465
|
+
query_properties.append(property)
|
|
466
|
+
break
|
|
467
|
+
if len(query_properties) < 1:
|
|
468
|
+
raise CannotBuildExistenceQuery("Empty existence query for class {}".format(self.__class__.__name__))
|
|
469
|
+
query = {}
|
|
470
|
+
for property in query_properties:
|
|
471
|
+
query_property_name = property.name
|
|
472
|
+
value = getattr(self, property.name)
|
|
473
|
+
if isinstance(value, ContainsMetadata):
|
|
474
|
+
if hasattr(value, "id") and value.id:
|
|
475
|
+
query[query_property_name] = value.id
|
|
476
|
+
else:
|
|
477
|
+
sub_query = value._build_existence_query()
|
|
478
|
+
query.update({f"{query_property_name}__{key}": val for key, val in sub_query.items()})
|
|
479
|
+
elif isinstance(value, (list, tuple)):
|
|
480
|
+
raise CannotBuildExistenceQuery("not implemented yet")
|
|
481
|
+
elif value is None:
|
|
482
|
+
raise CannotBuildExistenceQuery(f"Required value for '{query_property_name}' is missing")
|
|
483
|
+
else:
|
|
484
|
+
query_val = value_to_jsonld(value, include_empty_properties=False, embed_linked_nodes=False)
|
|
485
|
+
if query_val is None:
|
|
486
|
+
raise CannotBuildExistenceQuery(f"Required value for '{query_property_name}' is missing")
|
|
487
|
+
query[query_property_name] = query_val
|
|
488
|
+
return query
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from . import chemicals, computation, controlled_terms, core, ephys, publications, sands, specimen_prep, stimulation
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import inspect
|
|
3
|
+
from fairgraph.kgobject import KGObject
|
|
4
|
+
from fairgraph.embedded import EmbeddedMetadata
|
|
5
|
+
|
|
6
|
+
from .amount_of_chemical import AmountOfChemical
|
|
7
|
+
from .chemical_mixture import ChemicalMixture
|
|
8
|
+
from .chemical_substance import ChemicalSubstance
|
|
9
|
+
from .product_source import ProductSource
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def list_kg_classes():
|
|
13
|
+
"""List all KG classes defined in this module"""
|
|
14
|
+
return [
|
|
15
|
+
obj
|
|
16
|
+
for name, obj in inspect.getmembers(sys.modules[__name__])
|
|
17
|
+
if inspect.isclass(obj) and issubclass(obj, KGObject) and obj.__module__.startswith(__name__)
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def list_embedded_metadata_classes():
|
|
22
|
+
"""List all embedded metadata classes defined in this module"""
|
|
23
|
+
return [
|
|
24
|
+
obj
|
|
25
|
+
for name, obj in inspect.getmembers(sys.modules[__name__])
|
|
26
|
+
if inspect.isclass(obj) and issubclass(obj, EmbeddedMetadata) and obj.__module__.startswith(__name__)
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def set_error_handling(value):
|
|
31
|
+
"""
|
|
32
|
+
Control validation for all classes in this module.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
value (str): action to follow when there is a validation failure.
|
|
36
|
+
(e.g. if a required property is not provided).
|
|
37
|
+
Possible values: "error", "warning", "log", None
|
|
38
|
+
"""
|
|
39
|
+
for cls in list_kg_classes() + list_embedded_metadata_classes():
|
|
40
|
+
cls.set_error_handling(value)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Structured information about the amount of a given chemical that was used.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
# this file was auto-generated
|
|
6
|
+
|
|
7
|
+
from openminds.properties import Property
|
|
8
|
+
from openminds.v4.chemicals import AmountOfChemical as OMAmountOfChemical
|
|
9
|
+
from fairgraph import EmbeddedMetadata
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class AmountOfChemical(EmbeddedMetadata, OMAmountOfChemical):
|
|
13
|
+
"""
|
|
14
|
+
Structured information about the amount of a given chemical that was used.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
type_ = "https://openminds.om-i.org/types/AmountOfChemical"
|
|
18
|
+
# forward properties are defined in the parent class (in openMINDS-Python)
|
|
19
|
+
reverse_properties = []
|
|
20
|
+
existence_query_properties = ("chemical_product", "amount")
|
|
21
|
+
|
|
22
|
+
def __init__(self, amount=None, chemical_product=None, id=None, data=None, space=None, release_status=None):
|
|
23
|
+
return EmbeddedMetadata.__init__(self, data=data, amount=amount, chemical_product=chemical_product)
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Structured information about a mixture of chemical substances.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
# this file was auto-generated
|
|
6
|
+
|
|
7
|
+
from openminds.properties import Property
|
|
8
|
+
from openminds.v4.chemicals import ChemicalMixture as OMChemicalMixture
|
|
9
|
+
from fairgraph import KGObject
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ChemicalMixture(KGObject, OMChemicalMixture):
|
|
13
|
+
"""
|
|
14
|
+
Structured information about a mixture of chemical substances.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
type_ = "https://openminds.om-i.org/types/ChemicalMixture"
|
|
18
|
+
default_space = "in-depth"
|
|
19
|
+
# forward properties are defined in the parent class (in openMINDS-Python)
|
|
20
|
+
reverse_properties = [
|
|
21
|
+
Property(
|
|
22
|
+
"composes",
|
|
23
|
+
["openminds.v4.ephys.Electrode", "openminds.v4.ephys.ElectrodeArray", "openminds.v4.ephys.Pipette"],
|
|
24
|
+
["insulatorMaterial", "material"],
|
|
25
|
+
reverse=["insulator_material", "material"],
|
|
26
|
+
multiple=True,
|
|
27
|
+
description="reverse of insulator_material, material",
|
|
28
|
+
),
|
|
29
|
+
Property(
|
|
30
|
+
"used_in",
|
|
31
|
+
[
|
|
32
|
+
"openminds.v4.ephys.CellPatching",
|
|
33
|
+
"openminds.v4.ephys.PipetteUsage",
|
|
34
|
+
"openminds.v4.specimen_prep.TissueCulturePreparation",
|
|
35
|
+
"openminds.v4.specimen_prep.TissueSampleSlicing",
|
|
36
|
+
],
|
|
37
|
+
["cultureMedium", "pipetteSolution", "tissueBathSolution"],
|
|
38
|
+
reverse=["culture_medium", "pipette_solution", "tissue_bath_solution"],
|
|
39
|
+
multiple=True,
|
|
40
|
+
description="reverse of culture_medium, pipette_solution, tissue_bath_solution",
|
|
41
|
+
),
|
|
42
|
+
]
|
|
43
|
+
existence_query_properties = ("has_parts", "type")
|
|
44
|
+
|
|
45
|
+
def __init__(
|
|
46
|
+
self,
|
|
47
|
+
name=None,
|
|
48
|
+
additional_remarks=None,
|
|
49
|
+
composes=None,
|
|
50
|
+
has_parts=None,
|
|
51
|
+
product_source=None,
|
|
52
|
+
type=None,
|
|
53
|
+
used_in=None,
|
|
54
|
+
id=None,
|
|
55
|
+
data=None,
|
|
56
|
+
space=None,
|
|
57
|
+
release_status=None,
|
|
58
|
+
):
|
|
59
|
+
return KGObject.__init__(
|
|
60
|
+
self,
|
|
61
|
+
id=id,
|
|
62
|
+
space=space,
|
|
63
|
+
release_status=release_status,
|
|
64
|
+
data=data,
|
|
65
|
+
name=name,
|
|
66
|
+
additional_remarks=additional_remarks,
|
|
67
|
+
composes=composes,
|
|
68
|
+
has_parts=has_parts,
|
|
69
|
+
product_source=product_source,
|
|
70
|
+
type=type,
|
|
71
|
+
used_in=used_in,
|
|
72
|
+
)
|