cognite-neat 0.121.0__py3-none-any.whl → 0.121.2__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.
Potentially problematic release.
This version of cognite-neat might be problematic. Click here for more details.
- cognite/neat/_version.py +1 -1
- cognite/neat/core/_client/_api/statistics.py +91 -0
- cognite/neat/core/_client/_api_client.py +2 -0
- cognite/neat/core/_client/data_classes/statistics.py +125 -0
- cognite/neat/core/_client/testing.py +4 -0
- cognite/neat/core/_constants.py +6 -7
- cognite/neat/core/{_rules → _data_model}/_constants.py +25 -18
- cognite/neat/core/_data_model/_shared.py +59 -0
- cognite/neat/core/_data_model/analysis/__init__.py +3 -0
- cognite/neat/core/{_rules → _data_model}/analysis/_base.py +202 -195
- cognite/neat/core/{_rules → _data_model}/catalog/__init__.py +1 -1
- cognite/neat/core/{_rules → _data_model}/exporters/__init__.py +5 -5
- cognite/neat/core/{_rules → _data_model}/exporters/_base.py +10 -8
- cognite/neat/core/{_rules/exporters/_rules2dms.py → _data_model/exporters/_data_model2dms.py} +22 -18
- cognite/neat/core/{_rules/exporters/_rules2excel.py → _data_model/exporters/_data_model2excel.py} +61 -56
- cognite/neat/core/{_rules/exporters/_rules2instance_template.py → _data_model/exporters/_data_model2instance_template.py} +11 -9
- cognite/neat/core/{_rules/exporters/_rules2ontology.py → _data_model/exporters/_data_model2ontology.py} +64 -61
- cognite/neat/core/{_rules/exporters/_rules2yaml.py → _data_model/exporters/_data_model2yaml.py} +21 -18
- cognite/neat/core/{_rules → _data_model}/importers/__init__.py +6 -8
- cognite/neat/core/{_rules → _data_model}/importers/_base.py +8 -6
- cognite/neat/core/_data_model/importers/_base_file_reader.py +56 -0
- cognite/neat/core/{_rules/importers/_yaml2rules.py → _data_model/importers/_dict2data_model.py} +41 -21
- cognite/neat/core/{_rules/importers/_dms2rules.py → _data_model/importers/_dms2data_model.py} +79 -66
- cognite/neat/core/{_rules/importers/_dtdl2rules → _data_model/importers/_dtdl2data_model}/dtdl_converter.py +41 -41
- cognite/neat/core/{_rules/importers/_dtdl2rules → _data_model/importers/_dtdl2data_model}/dtdl_importer.py +16 -16
- cognite/neat/core/{_rules/importers/_dtdl2rules → _data_model/importers/_dtdl2data_model}/spec.py +3 -3
- cognite/neat/core/{_rules → _data_model}/importers/_rdf/_base.py +18 -16
- cognite/neat/core/{_rules → _data_model}/importers/_rdf/_imf2rules.py +17 -17
- cognite/neat/core/{_rules → _data_model}/importers/_rdf/_inference2rules.py +50 -50
- cognite/neat/core/{_rules → _data_model}/importers/_rdf/_owl2rules.py +14 -14
- cognite/neat/core/{_rules → _data_model}/importers/_rdf/_shared.py +25 -25
- cognite/neat/core/{_rules/importers/_spreadsheet2rules.py → _data_model/importers/_spreadsheet2data_model.py} +69 -38
- cognite/neat/core/_data_model/models/__init__.py +36 -0
- cognite/neat/core/{_rules/models/_base_input.py → _data_model/models/_base_unverified.py} +12 -12
- cognite/neat/core/{_rules/models/_base_rules.py → _data_model/models/_base_verified.py} +13 -13
- cognite/neat/core/{_rules → _data_model}/models/_types.py +13 -13
- cognite/neat/core/_data_model/models/conceptual/__init__.py +25 -0
- cognite/neat/core/{_rules/models/information/_rules_input.py → _data_model/models/conceptual/_unverified.py} +46 -43
- cognite/neat/core/{_rules/models/information → _data_model/models/conceptual}/_validation.py +93 -79
- cognite/neat/core/{_rules/models/information/_rules.py → _data_model/models/conceptual/_verified.py} +83 -83
- cognite/neat/core/{_rules → _data_model}/models/data_types.py +4 -4
- cognite/neat/core/{_rules → _data_model}/models/entities/__init__.py +8 -8
- cognite/neat/core/{_rules → _data_model}/models/entities/_loaders.py +12 -11
- cognite/neat/core/{_rules → _data_model}/models/entities/_multi_value.py +7 -7
- cognite/neat/core/{_rules → _data_model}/models/entities/_single_value.py +45 -39
- cognite/neat/core/{_rules → _data_model}/models/entities/_types.py +9 -3
- cognite/neat/core/{_rules → _data_model}/models/entities/_wrapped.py +3 -3
- cognite/neat/core/{_rules → _data_model}/models/mapping/_classic2core.py +12 -9
- cognite/neat/core/_data_model/models/physical/__init__.py +40 -0
- cognite/neat/core/{_rules/models/dms → _data_model/models/physical}/_exporter.py +83 -64
- cognite/neat/core/{_rules/models/dms/_rules_input.py → _data_model/models/physical/_unverified.py} +56 -44
- cognite/neat/core/{_rules/models/dms → _data_model/models/physical}/_validation.py +20 -17
- cognite/neat/core/{_rules/models/dms/_rules.py → _data_model/models/physical/_verified.py} +79 -71
- cognite/neat/core/{_rules → _data_model}/transformers/__init__.py +27 -23
- cognite/neat/core/{_rules → _data_model}/transformers/_base.py +29 -19
- cognite/neat/core/{_rules → _data_model}/transformers/_converters.py +758 -659
- cognite/neat/core/{_rules → _data_model}/transformers/_mapping.py +79 -60
- cognite/neat/core/_data_model/transformers/_verification.py +120 -0
- cognite/neat/core/{_graph → _instances}/extractors/_base.py +2 -2
- cognite/neat/core/{_graph → _instances}/extractors/_classic_cdf/_base.py +1 -1
- cognite/neat/core/{_graph → _instances}/extractors/_classic_cdf/_classic.py +17 -11
- cognite/neat/core/{_graph → _instances}/extractors/_dms_graph.py +47 -39
- cognite/neat/core/{_graph → _instances}/extractors/_mock_graph_generator.py +102 -99
- cognite/neat/core/{_graph → _instances}/extractors/_rdf_file.py +2 -2
- cognite/neat/core/{_graph → _instances}/loaders/_base.py +2 -2
- cognite/neat/core/{_graph → _instances}/loaders/_rdf2dms.py +16 -14
- cognite/neat/core/{_graph → _instances}/transformers/_base.py +7 -4
- cognite/neat/core/{_graph → _instances}/transformers/_classic_cdf.py +1 -1
- cognite/neat/core/{_graph → _instances}/transformers/_value_type.py +2 -6
- cognite/neat/core/_issues/_base.py +4 -4
- cognite/neat/core/_issues/errors/__init__.py +2 -2
- cognite/neat/core/_issues/errors/_wrapper.py +2 -2
- cognite/neat/core/_issues/warnings/__init__.py +2 -0
- cognite/neat/core/_issues/warnings/_models.py +4 -4
- cognite/neat/core/_issues/warnings/_properties.py +7 -0
- cognite/neat/core/_store/__init__.py +3 -3
- cognite/neat/core/_store/{_rules_store.py → _data_model.py} +128 -121
- cognite/neat/core/_store/{_graph_store.py → _instance.py} +7 -8
- cognite/neat/core/_store/_provenance.py +2 -2
- cognite/neat/core/_store/exceptions.py +4 -4
- cognite/neat/core/_utils/rdf_.py +14 -0
- cognite/neat/core/_utils/spreadsheet.py +1 -1
- cognite/neat/core/_utils/text.py +2 -2
- cognite/neat/session/_base.py +29 -25
- cognite/neat/session/_drop.py +3 -3
- cognite/neat/session/_fix.py +2 -2
- cognite/neat/session/_inspect.py +5 -5
- cognite/neat/session/_mapping.py +11 -9
- cognite/neat/session/_prepare.py +4 -4
- cognite/neat/session/_read.py +15 -15
- cognite/neat/session/_set.py +5 -5
- cognite/neat/session/_show.py +11 -11
- cognite/neat/session/_state.py +17 -17
- cognite/neat/session/_subset.py +14 -11
- cognite/neat/session/_template.py +19 -19
- cognite/neat/session/_to.py +21 -21
- cognite/neat/session/_wizard.py +1 -1
- {cognite_neat-0.121.0.dist-info → cognite_neat-0.121.2.dist-info}/METADATA +1 -1
- cognite_neat-0.121.2.dist-info/RECORD +189 -0
- cognite/neat/core/_rules/_shared.py +0 -43
- cognite/neat/core/_rules/analysis/__init__.py +0 -3
- cognite/neat/core/_rules/exporters/_validation.py +0 -14
- cognite/neat/core/_rules/models/__init__.py +0 -34
- cognite/neat/core/_rules/models/dms/__init__.py +0 -32
- cognite/neat/core/_rules/models/information/__init__.py +0 -20
- cognite/neat/core/_rules/transformers/_verification.py +0 -111
- cognite_neat-0.121.0.dist-info/RECORD +0 -187
- /cognite/neat/core/{_graph → _data_model}/__init__.py +0 -0
- /cognite/neat/core/{_rules → _data_model}/catalog/classic_model.xlsx +0 -0
- /cognite/neat/core/{_rules/catalog/info-rules-imf.xlsx → _data_model/catalog/conceptual-imf-data-model.xlsx} +0 -0
- /cognite/neat/core/{_rules → _data_model}/catalog/hello_world_pump.xlsx +0 -0
- /cognite/neat/core/{_rules/importers/_dtdl2rules → _data_model/importers/_dtdl2data_model}/__init__.py +0 -0
- /cognite/neat/core/{_rules/importers/_dtdl2rules → _data_model/importers/_dtdl2data_model}/_unit_lookup.py +0 -0
- /cognite/neat/core/{_rules → _data_model}/importers/_rdf/__init__.py +0 -0
- /cognite/neat/core/{_rules → _data_model}/models/entities/_constants.py +0 -0
- /cognite/neat/core/{_rules → _data_model}/models/mapping/__init__.py +0 -0
- /cognite/neat/core/{_rules → _data_model}/models/mapping/_classic2core.yaml +0 -0
- /cognite/neat/core/{_graph/extractors/_classic_cdf → _instances}/__init__.py +0 -0
- /cognite/neat/core/{_graph → _instances}/_shared.py +0 -0
- /cognite/neat/core/{_graph → _instances}/_tracking/__init__.py +0 -0
- /cognite/neat/core/{_graph → _instances}/_tracking/base.py +0 -0
- /cognite/neat/core/{_graph → _instances}/_tracking/log.py +0 -0
- /cognite/neat/core/{_graph → _instances}/examples/Knowledge-Graph-Nordic44-dirty.xml +0 -0
- /cognite/neat/core/{_graph → _instances}/examples/Knowledge-Graph-Nordic44.xml +0 -0
- /cognite/neat/core/{_graph → _instances}/examples/__init__.py +0 -0
- /cognite/neat/core/{_graph → _instances}/examples/skos-capturing-sheet-wind-topics.xlsx +0 -0
- /cognite/neat/core/{_graph → _instances}/extractors/__init__.py +0 -0
- /cognite/neat/core/{_rules → _instances/extractors/_classic_cdf}/__init__.py +0 -0
- /cognite/neat/core/{_graph → _instances}/extractors/_classic_cdf/_assets.py +0 -0
- /cognite/neat/core/{_graph → _instances}/extractors/_classic_cdf/_data_sets.py +0 -0
- /cognite/neat/core/{_graph → _instances}/extractors/_classic_cdf/_events.py +0 -0
- /cognite/neat/core/{_graph → _instances}/extractors/_classic_cdf/_files.py +0 -0
- /cognite/neat/core/{_graph → _instances}/extractors/_classic_cdf/_labels.py +0 -0
- /cognite/neat/core/{_graph → _instances}/extractors/_classic_cdf/_relationships.py +0 -0
- /cognite/neat/core/{_graph → _instances}/extractors/_classic_cdf/_sequences.py +0 -0
- /cognite/neat/core/{_graph → _instances}/extractors/_classic_cdf/_timeseries.py +0 -0
- /cognite/neat/core/{_graph → _instances}/extractors/_dict.py +0 -0
- /cognite/neat/core/{_graph → _instances}/extractors/_dms.py +0 -0
- /cognite/neat/core/{_graph → _instances}/extractors/_raw.py +0 -0
- /cognite/neat/core/{_graph → _instances}/loaders/__init__.py +0 -0
- /cognite/neat/core/{_graph → _instances}/queries/__init__.py +0 -0
- /cognite/neat/core/{_graph → _instances}/queries/_base.py +0 -0
- /cognite/neat/core/{_graph → _instances}/queries/_queries.py +0 -0
- /cognite/neat/core/{_graph → _instances}/queries/_select.py +0 -0
- /cognite/neat/core/{_graph → _instances}/queries/_update.py +0 -0
- /cognite/neat/core/{_graph → _instances}/transformers/__init__.py +0 -0
- /cognite/neat/core/{_graph → _instances}/transformers/_prune_graph.py +0 -0
- /cognite/neat/core/{_graph → _instances}/transformers/_rdfpath.py +0 -0
- {cognite_neat-0.121.0.dist-info → cognite_neat-0.121.2.dist-info}/WHEEL +0 -0
- {cognite_neat-0.121.0.dist-info → cognite_neat-0.121.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
"""This module performs importing of various formats to one of serializations for which
|
|
2
2
|
there are loaders to TransformationRules pydantic class."""
|
|
3
3
|
|
|
4
|
-
from cognite.neat.core.
|
|
5
|
-
from cognite.neat.core.
|
|
6
|
-
|
|
4
|
+
from cognite.neat.core._data_model.importers._rdf._base import BaseRDFImporter
|
|
5
|
+
from cognite.neat.core._data_model.importers._rdf._shared import (
|
|
6
|
+
parse_concepts,
|
|
7
7
|
parse_properties,
|
|
8
8
|
)
|
|
9
9
|
|
|
10
10
|
CLASSES_QUERY = """
|
|
11
|
-
SELECT ?
|
|
11
|
+
SELECT ?concept ?name ?description ?implements
|
|
12
12
|
WHERE {{
|
|
13
13
|
VALUES ?type {{ imf:BlockType imf:TerminalType imf:AttributeType }}
|
|
14
|
-
?
|
|
14
|
+
?concept a ?type .
|
|
15
15
|
|
|
16
|
-
OPTIONAL {{?
|
|
17
|
-
OPTIONAL {{?
|
|
18
|
-
OPTIONAL {{?
|
|
16
|
+
OPTIONAL {{?concept rdfs:subClassOf ?parent }}.
|
|
17
|
+
OPTIONAL {{?concept rdfs:label|skos:prefLabel ?name }}.
|
|
18
|
+
OPTIONAL {{?concept rdfs:comment|skos:definition ?description}}.
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
# Add imf:Attribute as parent class when no parent is found
|
|
22
22
|
BIND(IF(!bound(?parent) && ?type = imf:AttributeType, imf:Attribute, ?parent) AS ?implements)
|
|
23
23
|
|
|
24
24
|
# FILTERS
|
|
25
|
-
FILTER (!isBlank(?
|
|
25
|
+
FILTER (!isBlank(?concept))
|
|
26
26
|
FILTER (!bound(?implements) || !isBlank(?implements))
|
|
27
27
|
|
|
28
28
|
FILTER (!bound(?name) || LANG(?name) = "" || LANGMATCHES(LANG(?name), "{language}"))
|
|
@@ -31,13 +31,13 @@ CLASSES_QUERY = """
|
|
|
31
31
|
"""
|
|
32
32
|
|
|
33
33
|
PROPERTIES_QUERY = """
|
|
34
|
-
SELECT ?
|
|
34
|
+
SELECT ?concept ?property_ ?name ?description ?value_type ?min_count ?max_count ?default
|
|
35
35
|
WHERE
|
|
36
36
|
{{
|
|
37
37
|
# CASE 1: Handling Blocks and Terminals
|
|
38
38
|
{{
|
|
39
39
|
VALUES ?type {{ imf:BlockType imf:TerminalType }}
|
|
40
|
-
?
|
|
40
|
+
?concept a ?type ;
|
|
41
41
|
sh:property ?propertyShape .
|
|
42
42
|
?propertyShape sh:path ?property_ .
|
|
43
43
|
|
|
@@ -55,10 +55,10 @@ PROPERTIES_QUERY = """
|
|
|
55
55
|
|
|
56
56
|
# CASE 2: Handling Attributes
|
|
57
57
|
{{
|
|
58
|
-
?
|
|
58
|
+
?concept a imf:AttributeType .
|
|
59
59
|
BIND(xsd:anyURI AS ?valueShape)
|
|
60
60
|
BIND(imf:predicate AS ?property_)
|
|
61
|
-
?
|
|
61
|
+
?concept ?property_ ?defaultURI .
|
|
62
62
|
BIND(STR(?defaultURI) AS ?default)
|
|
63
63
|
|
|
64
64
|
}}
|
|
@@ -67,7 +67,7 @@ PROPERTIES_QUERY = """
|
|
|
67
67
|
BIND(IF(BOUND(?valueShape), ?valueShape, IF(BOUND(?range) , ?range , ?valueShape)) AS ?value_type)
|
|
68
68
|
|
|
69
69
|
FILTER (!isBlank(?property_))
|
|
70
|
-
FILTER (!bound(?
|
|
70
|
+
FILTER (!bound(?concept) || !isBlank(?concept))
|
|
71
71
|
FILTER (!bound(?name) || LANG(?name) = "" || LANGMATCHES(LANG(?name), "{language}"))
|
|
72
72
|
FILTER (!bound(?description) || LANG(?description) = "" || LANGMATCHES(LANG(?description), "{language}"))
|
|
73
73
|
}}
|
|
@@ -81,17 +81,17 @@ class IMFImporter(BaseRDFImporter):
|
|
|
81
81
|
def description(self) -> str:
|
|
82
82
|
return f"IMF Types {self.source_name} read as unverified data model"
|
|
83
83
|
|
|
84
|
-
def
|
|
84
|
+
def _to_data_model_components(
|
|
85
85
|
self,
|
|
86
86
|
) -> dict:
|
|
87
|
-
classes, issue_list =
|
|
87
|
+
classes, issue_list = parse_concepts(self.graph, CLASSES_QUERY, self.language, self.issue_list)
|
|
88
88
|
self.issue_list = issue_list
|
|
89
89
|
properties, issue_list = parse_properties(self.graph, PROPERTIES_QUERY, self.language, self.issue_list)
|
|
90
90
|
self.issue_list = issue_list
|
|
91
91
|
|
|
92
92
|
components = {
|
|
93
93
|
"Metadata": self._metadata,
|
|
94
|
-
"
|
|
94
|
+
"Concepts": list(classes.values()) if classes else [],
|
|
95
95
|
"Properties": list(properties.values()) if properties else [],
|
|
96
96
|
}
|
|
97
97
|
|
|
@@ -12,19 +12,19 @@ from rdflib import Literal as RdfLiteral
|
|
|
12
12
|
|
|
13
13
|
from cognite.neat.core._config import GLOBAL_CONFIG
|
|
14
14
|
from cognite.neat.core._constants import NEAT, get_default_prefixes_and_namespaces
|
|
15
|
+
from cognite.neat.core._data_model.analysis import DataModelAnalysis
|
|
16
|
+
from cognite.neat.core._data_model.models import ConceptualDataModel, data_types
|
|
17
|
+
from cognite.neat.core._data_model.models.conceptual import (
|
|
18
|
+
Concept,
|
|
19
|
+
ConceptualMetadata,
|
|
20
|
+
UnverifiedConcept,
|
|
21
|
+
UnverifiedConceptualProperty,
|
|
22
|
+
)
|
|
23
|
+
from cognite.neat.core._data_model.models.data_types import AnyURI
|
|
24
|
+
from cognite.neat.core._data_model.models.entities._single_value import UnknownEntity
|
|
15
25
|
from cognite.neat.core._issues import IssueList
|
|
16
26
|
from cognite.neat.core._issues.warnings import PropertyValueTypeUndefinedWarning
|
|
17
|
-
from cognite.neat.core.
|
|
18
|
-
from cognite.neat.core._rules.models import InformationRules, data_types
|
|
19
|
-
from cognite.neat.core._rules.models.data_types import AnyURI
|
|
20
|
-
from cognite.neat.core._rules.models.entities._single_value import UnknownEntity
|
|
21
|
-
from cognite.neat.core._rules.models.information import (
|
|
22
|
-
InformationClass,
|
|
23
|
-
InformationInputClass,
|
|
24
|
-
InformationInputProperty,
|
|
25
|
-
InformationMetadata,
|
|
26
|
-
)
|
|
27
|
-
from cognite.neat.core._store import NeatGraphStore
|
|
27
|
+
from cognite.neat.core._store import NeatInstanceStore
|
|
28
28
|
from cognite.neat.core._store._provenance import INSTANCES_ENTITY
|
|
29
29
|
from cognite.neat.core._utils.collection_ import iterate_progress_bar
|
|
30
30
|
from cognite.neat.core._utils.rdf_ import remove_namespace_from_uri, uri_to_short_form
|
|
@@ -83,8 +83,8 @@ class InferenceImporter(BaseRDFImporter):
|
|
|
83
83
|
@classmethod
|
|
84
84
|
def from_graph_store(
|
|
85
85
|
cls,
|
|
86
|
-
store:
|
|
87
|
-
data_model_id: dm.DataModelId | tuple[str, str, str] = DEFAULT_INFERENCE_DATA_MODEL_ID,
|
|
86
|
+
store: NeatInstanceStore,
|
|
87
|
+
data_model_id: (dm.DataModelId | tuple[str, str, str]) = DEFAULT_INFERENCE_DATA_MODEL_ID,
|
|
88
88
|
max_number_of_instance: int = -1,
|
|
89
89
|
non_existing_node_type: UnknownEntity | AnyURI = DEFAULT_NON_EXISTING_NODE_TYPE,
|
|
90
90
|
language: str = "en",
|
|
@@ -145,7 +145,7 @@ class InferenceImporter(BaseRDFImporter):
|
|
|
145
145
|
) -> "InferenceImporter":
|
|
146
146
|
raise NotImplementedError("JSON file format is not supported yet.")
|
|
147
147
|
|
|
148
|
-
def
|
|
148
|
+
def _to_data_model_components(
|
|
149
149
|
self,
|
|
150
150
|
) -> dict:
|
|
151
151
|
"""Convert RDF graph to dictionary defining data model and prefixes of the graph
|
|
@@ -158,33 +158,33 @@ class InferenceImporter(BaseRDFImporter):
|
|
|
158
158
|
Tuple of data model and prefixes of the graph
|
|
159
159
|
"""
|
|
160
160
|
|
|
161
|
-
|
|
161
|
+
concepts: dict[str, dict] = {}
|
|
162
162
|
properties: dict[str, dict] = {}
|
|
163
163
|
prefixes: dict[str, Namespace] = {}
|
|
164
164
|
count_by_value_type_by_property: dict[str, dict[str, int]] = defaultdict(Counter)
|
|
165
165
|
|
|
166
166
|
# Infers all the classes in the graph
|
|
167
|
-
for
|
|
168
|
-
if (
|
|
167
|
+
for concept_uri, no_instances in self.graph.query(ORDERED_CLASSES_QUERY): # type: ignore[misc]
|
|
168
|
+
if (concept_id := remove_namespace_from_uri(cast(URIRef, concept_uri))) in concepts:
|
|
169
169
|
# handles cases when class id is already present in classes
|
|
170
|
-
|
|
170
|
+
concept_id = f"{concept_id}_{len(concepts) + 1}"
|
|
171
171
|
|
|
172
|
-
|
|
173
|
-
"
|
|
174
|
-
"uri":
|
|
172
|
+
concepts[concept_id] = {
|
|
173
|
+
"concept": concept_id,
|
|
174
|
+
"uri": concept_uri,
|
|
175
175
|
"comment": f"Inferred from knowledge graph, where this class has <{no_instances}> instances",
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
-
self._add_uri_namespace_to_prefixes(cast(URIRef,
|
|
178
|
+
self._add_uri_namespace_to_prefixes(cast(URIRef, concept_uri), prefixes)
|
|
179
179
|
|
|
180
180
|
instances_query = (
|
|
181
181
|
INSTANCES_OF_CLASS_QUERY if self.max_number_of_instance == -1 else INSTANCES_OF_CLASS_RICHNESS_ORDERED_QUERY
|
|
182
182
|
)
|
|
183
183
|
|
|
184
|
-
classes_iterable = iterate_progress_bar(
|
|
184
|
+
classes_iterable = iterate_progress_bar(concepts.items(), len(concepts), "Inferring classes")
|
|
185
185
|
|
|
186
186
|
# Infers all the properties of the class
|
|
187
|
-
for
|
|
187
|
+
for concept_id, class_definition in classes_iterable:
|
|
188
188
|
for ( # type: ignore[misc]
|
|
189
189
|
instance,
|
|
190
190
|
_,
|
|
@@ -216,7 +216,7 @@ class InferenceImporter(BaseRDFImporter):
|
|
|
216
216
|
|
|
217
217
|
issue = PropertyValueTypeUndefinedWarning(
|
|
218
218
|
resource_type="Property",
|
|
219
|
-
identifier=f"{
|
|
219
|
+
identifier=f"{concept_id}:{property_id}",
|
|
220
220
|
property_name=property_id,
|
|
221
221
|
default_action="Remove the property from the rules",
|
|
222
222
|
recommended_action="Make sure that graph is complete",
|
|
@@ -225,10 +225,10 @@ class InferenceImporter(BaseRDFImporter):
|
|
|
225
225
|
if issue not in self.issue_list:
|
|
226
226
|
self.issue_list.append(issue)
|
|
227
227
|
|
|
228
|
-
id_ = f"{
|
|
228
|
+
id_ = f"{concept_id}:{property_id}"
|
|
229
229
|
|
|
230
230
|
definition = {
|
|
231
|
-
"
|
|
231
|
+
"concept": concept_id,
|
|
232
232
|
"property_": property_id,
|
|
233
233
|
"max_count": cast(RdfLiteral, occurrence).value,
|
|
234
234
|
"value_type": value_type_id,
|
|
@@ -265,14 +265,14 @@ class InferenceImporter(BaseRDFImporter):
|
|
|
265
265
|
|
|
266
266
|
return {
|
|
267
267
|
"metadata": self._default_metadata(),
|
|
268
|
-
"
|
|
268
|
+
"concepts": list(concepts.values()),
|
|
269
269
|
"properties": list(properties.values()),
|
|
270
270
|
"prefixes": prefixes,
|
|
271
271
|
}
|
|
272
272
|
|
|
273
273
|
def _default_metadata(self) -> dict[str, Any]:
|
|
274
274
|
now = datetime.now(timezone.utc)
|
|
275
|
-
return
|
|
275
|
+
return ConceptualMetadata(
|
|
276
276
|
space=self.data_model_id.space,
|
|
277
277
|
external_id=self.data_model_id.external_id,
|
|
278
278
|
version=cast(str, self.data_model_id.version),
|
|
@@ -357,7 +357,7 @@ class SubclassInferenceImporter(BaseRDFImporter):
|
|
|
357
357
|
self,
|
|
358
358
|
issue_list: IssueList,
|
|
359
359
|
graph: Graph,
|
|
360
|
-
rules:
|
|
360
|
+
rules: ConceptualDataModel | None = None,
|
|
361
361
|
data_model_id: dm.DataModelId | tuple[str, str, str] | None = None,
|
|
362
362
|
non_existing_node_type: UnknownEntity | AnyURI = DEFAULT_NON_EXISTING_NODE_TYPE,
|
|
363
363
|
) -> None:
|
|
@@ -372,7 +372,7 @@ class SubclassInferenceImporter(BaseRDFImporter):
|
|
|
372
372
|
super().__init__(issue_list, graph, identifier, -1, non_existing_node_type, language="en")
|
|
373
373
|
self._rules = rules
|
|
374
374
|
|
|
375
|
-
def
|
|
375
|
+
def _to_data_model_components(
|
|
376
376
|
self,
|
|
377
377
|
) -> dict:
|
|
378
378
|
if self._rules:
|
|
@@ -392,20 +392,20 @@ class SubclassInferenceImporter(BaseRDFImporter):
|
|
|
392
392
|
default_space = metadata["space"]
|
|
393
393
|
return {
|
|
394
394
|
"metadata": metadata,
|
|
395
|
-
"
|
|
395
|
+
"concepts": [cls.dump(default_space) for cls in classes],
|
|
396
396
|
"properties": [prop.dump(default_space) for prop in properties],
|
|
397
397
|
"prefixes": prefixes,
|
|
398
398
|
}
|
|
399
399
|
|
|
400
400
|
def _create_classes_properties(
|
|
401
401
|
self, read_properties: list[_ReadProperties], prefixes: dict[str, Namespace]
|
|
402
|
-
) -> tuple[list[
|
|
402
|
+
) -> tuple[list[UnverifiedConcept], list[UnverifiedConceptualProperty]]:
|
|
403
403
|
if self._rules:
|
|
404
|
-
existing_classes = {class_.
|
|
404
|
+
existing_classes = {class_.concept.suffix: class_ for class_ in self._rules.concepts}
|
|
405
405
|
else:
|
|
406
406
|
existing_classes = {}
|
|
407
|
-
classes: list[
|
|
408
|
-
properties_by_class_suffix_by_property_id: dict[str, dict[str,
|
|
407
|
+
classes: list[UnverifiedConcept] = []
|
|
408
|
+
properties_by_class_suffix_by_property_id: dict[str, dict[str, UnverifiedConceptualProperty]] = {}
|
|
409
409
|
|
|
410
410
|
# Help for IDE
|
|
411
411
|
type_uri: URIRef
|
|
@@ -429,9 +429,9 @@ class SubclassInferenceImporter(BaseRDFImporter):
|
|
|
429
429
|
parent_suffix = remove_namespace_from_uri(parent_uri)
|
|
430
430
|
self._add_uri_namespace_to_prefixes(parent_uri, prefixes)
|
|
431
431
|
if parent_suffix not in existing_classes:
|
|
432
|
-
classes.append(
|
|
432
|
+
classes.append(UnverifiedConcept(concept=parent_suffix))
|
|
433
433
|
else:
|
|
434
|
-
classes.append(
|
|
434
|
+
classes.append(UnverifiedConcept.load(existing_classes[parent_suffix].model_dump()))
|
|
435
435
|
else:
|
|
436
436
|
shared_property_uris = set()
|
|
437
437
|
shared_properties: dict[URIRef, list[_ReadProperties]] = defaultdict(list)
|
|
@@ -441,16 +441,16 @@ class SubclassInferenceImporter(BaseRDFImporter):
|
|
|
441
441
|
|
|
442
442
|
if class_suffix not in existing_classes:
|
|
443
443
|
classes.append(
|
|
444
|
-
|
|
445
|
-
|
|
444
|
+
UnverifiedConcept(
|
|
445
|
+
concept=class_suffix,
|
|
446
446
|
implements=parent_suffix,
|
|
447
447
|
instance_source=type_uri,
|
|
448
448
|
)
|
|
449
449
|
)
|
|
450
450
|
else:
|
|
451
|
-
classes.append(
|
|
451
|
+
classes.append(UnverifiedConcept.load(existing_classes[class_suffix].model_dump()))
|
|
452
452
|
|
|
453
|
-
properties_by_id: dict[str,
|
|
453
|
+
properties_by_id: dict[str, UnverifiedConceptualProperty] = {}
|
|
454
454
|
for property_uri, read_properties in properties_by_property_uri.items():
|
|
455
455
|
if property_uri in shared_property_uris:
|
|
456
456
|
shared_properties[property_uri].extend(read_properties)
|
|
@@ -510,20 +510,20 @@ class SubclassInferenceImporter(BaseRDFImporter):
|
|
|
510
510
|
type_uri, instance_count_literal = cast(tuple[URIRef, RdfLiteral], result_row)
|
|
511
511
|
count_by_type[type_uri] = instance_count_literal.toPython()
|
|
512
512
|
if self._rules:
|
|
513
|
-
analysis =
|
|
513
|
+
analysis = DataModelAnalysis(self._rules)
|
|
514
514
|
existing_class_properties = {
|
|
515
515
|
(class_entity.suffix, prop.property_): prop
|
|
516
|
-
for class_entity, properties in analysis.
|
|
516
|
+
for class_entity, properties in analysis.properties_by_concepts(
|
|
517
517
|
include_ancestors=True, include_different_space=True
|
|
518
518
|
).items()
|
|
519
519
|
for prop in properties
|
|
520
520
|
}
|
|
521
|
-
existing_classes = {cls_.
|
|
521
|
+
existing_classes = {cls_.concept.suffix: cls_ for cls_ in self._rules.concepts}
|
|
522
522
|
else:
|
|
523
523
|
existing_class_properties = {}
|
|
524
524
|
existing_classes = {}
|
|
525
525
|
properties_by_class_by_subclass: list[_ReadProperties] = []
|
|
526
|
-
existing_class:
|
|
526
|
+
existing_class: Concept | None
|
|
527
527
|
total_instance_count = sum(count_by_type.values())
|
|
528
528
|
iterable = count_by_type.items()
|
|
529
529
|
if GLOBAL_CONFIG.use_iterate_bar_threshold and total_instance_count > GLOBAL_CONFIG.use_iterate_bar_threshold:
|
|
@@ -577,11 +577,11 @@ class SubclassInferenceImporter(BaseRDFImporter):
|
|
|
577
577
|
property_uri: URIRef,
|
|
578
578
|
property_id: str,
|
|
579
579
|
prefixes: dict[str, Namespace],
|
|
580
|
-
) ->
|
|
580
|
+
) -> UnverifiedConceptualProperty:
|
|
581
581
|
first = read_properties[0]
|
|
582
582
|
value_type = self._get_value_type(read_properties, prefixes)
|
|
583
|
-
return
|
|
584
|
-
|
|
583
|
+
return UnverifiedConceptualProperty(
|
|
584
|
+
concept=class_suffix,
|
|
585
585
|
property_=property_id,
|
|
586
586
|
max_count=first.max_occurrence,
|
|
587
587
|
value_type=value_type,
|
|
@@ -606,7 +606,7 @@ class SubclassInferenceImporter(BaseRDFImporter):
|
|
|
606
606
|
|
|
607
607
|
def _default_metadata(self) -> dict[str, Any]:
|
|
608
608
|
now = datetime.now(timezone.utc)
|
|
609
|
-
return
|
|
609
|
+
return ConceptualMetadata(
|
|
610
610
|
space=self.data_model_id.space,
|
|
611
611
|
external_id=self.data_model_id.external_id,
|
|
612
612
|
version=cast(str, self.data_model_id.version),
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
"""This module performs importing of various formats to one of serializations for which
|
|
2
2
|
there are loaders to TransformationRules pydantic class."""
|
|
3
3
|
|
|
4
|
-
from cognite.neat.core.
|
|
5
|
-
from cognite.neat.core.
|
|
6
|
-
|
|
4
|
+
from cognite.neat.core._data_model.importers._rdf._base import BaseRDFImporter
|
|
5
|
+
from cognite.neat.core._data_model.importers._rdf._shared import (
|
|
6
|
+
parse_concepts,
|
|
7
7
|
parse_properties,
|
|
8
8
|
)
|
|
9
9
|
|
|
10
|
-
CLASSES_QUERY = """SELECT ?
|
|
10
|
+
CLASSES_QUERY = """SELECT ?concept ?name ?description ?implements
|
|
11
11
|
WHERE {{
|
|
12
12
|
|
|
13
|
-
?
|
|
14
|
-
OPTIONAL {{?
|
|
15
|
-
OPTIONAL {{?
|
|
16
|
-
OPTIONAL {{?
|
|
13
|
+
?concept a owl:Class .
|
|
14
|
+
OPTIONAL {{?concept rdfs:subClassOf ?implements }}.
|
|
15
|
+
OPTIONAL {{?concept rdfs:label|skos:prefLabel ?name }}.
|
|
16
|
+
OPTIONAL {{?concept rdfs:comment|skos:definition ?description}} .
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
FILTER (!isBlank(?
|
|
19
|
+
FILTER (!isBlank(?concept ))
|
|
20
20
|
FILTER (!bound(?implements) || !isBlank(?implements))
|
|
21
21
|
|
|
22
22
|
FILTER (!bound(?name) || LANG(?name) = "" || LANGMATCHES(LANG(?name), "{language}"))
|
|
@@ -27,11 +27,11 @@ CLASSES_QUERY = """SELECT ?class_ ?name ?description ?implements
|
|
|
27
27
|
|
|
28
28
|
PROPERTIES_QUERY = """
|
|
29
29
|
|
|
30
|
-
SELECT ?
|
|
30
|
+
SELECT ?concept ?property_ ?name ?description ?value_type ?minCount ?maxCount ?default
|
|
31
31
|
WHERE {{
|
|
32
32
|
?property_ a ?property_Type.
|
|
33
33
|
FILTER (?property_Type IN (owl:ObjectProperty, owl:DatatypeProperty ) )
|
|
34
|
-
OPTIONAL {{?property_ rdfs:domain ?
|
|
34
|
+
OPTIONAL {{?property_ rdfs:domain ?concept }}.
|
|
35
35
|
OPTIONAL {{?property_ rdfs:range ?value_type }}.
|
|
36
36
|
OPTIONAL {{?property_ rdfs:label|skos:prefLabel ?name }}.
|
|
37
37
|
OPTIONAL {{?property_ rdfs:comment|skos:definition ?description}}.
|
|
@@ -64,10 +64,10 @@ class OWLImporter(BaseRDFImporter):
|
|
|
64
64
|
|
|
65
65
|
"""
|
|
66
66
|
|
|
67
|
-
def
|
|
67
|
+
def _to_data_model_components(
|
|
68
68
|
self,
|
|
69
69
|
) -> dict:
|
|
70
|
-
|
|
70
|
+
concepts, issue_list = parse_concepts(self.graph, CLASSES_QUERY, self.language, self.issue_list)
|
|
71
71
|
self.issue_list = issue_list
|
|
72
72
|
|
|
73
73
|
# NeatError
|
|
@@ -76,7 +76,7 @@ class OWLImporter(BaseRDFImporter):
|
|
|
76
76
|
|
|
77
77
|
components = {
|
|
78
78
|
"Metadata": self._metadata,
|
|
79
|
-
"
|
|
79
|
+
"Concepts": list(concepts.values()) if concepts else [],
|
|
80
80
|
"Properties": list(properties.values()) if properties else [],
|
|
81
81
|
}
|
|
82
82
|
|
|
@@ -13,18 +13,18 @@ from cognite.neat.core._issues.warnings._resources import (
|
|
|
13
13
|
from cognite.neat.core._utils.rdf_ import convert_rdflib_content
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
def
|
|
17
|
-
"""Parse
|
|
16
|
+
def parse_concepts(graph: Graph, query: str, language: str, issue_list: IssueList) -> tuple[dict, IssueList]:
|
|
17
|
+
"""Parse concepts from graph
|
|
18
18
|
|
|
19
19
|
Args:
|
|
20
|
-
graph: Graph containing
|
|
20
|
+
graph: Graph containing concept definitions
|
|
21
21
|
language: Language to use for parsing, by default "en"
|
|
22
22
|
|
|
23
23
|
Returns:
|
|
24
24
|
Dataframe containing owl classes
|
|
25
25
|
"""
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
concepts: dict[str, dict] = {}
|
|
28
28
|
|
|
29
29
|
query = prepareQuery(query.format(language=language), initNs={k: v for k, v in graph.namespaces()})
|
|
30
30
|
expected_keys = [str(v) for v in query.algebra._vars]
|
|
@@ -33,42 +33,42 @@ def parse_classes(graph: Graph, query: str, language: str, issue_list: IssueList
|
|
|
33
33
|
res: dict = convert_rdflib_content(cast(ResultRow, raw).asdict(), True)
|
|
34
34
|
res = {key: res.get(key, None) for key in expected_keys}
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
concept_id = res["concept"]
|
|
37
37
|
|
|
38
38
|
# Safeguarding against incomplete semantic definitions
|
|
39
39
|
if res["implements"] and isinstance(res["implements"], BNode):
|
|
40
40
|
issue_list.append(
|
|
41
41
|
ResourceRetrievalWarning(
|
|
42
|
-
|
|
42
|
+
concept_id,
|
|
43
43
|
"implements",
|
|
44
|
-
error=("Unable to determine
|
|
44
|
+
error=("Unable to determine concept that is being implemented"),
|
|
45
45
|
)
|
|
46
46
|
)
|
|
47
47
|
continue
|
|
48
48
|
|
|
49
|
-
if
|
|
50
|
-
|
|
49
|
+
if concept_id not in concepts:
|
|
50
|
+
concepts[concept_id] = res
|
|
51
51
|
else:
|
|
52
52
|
# Handling implements
|
|
53
|
-
if
|
|
54
|
-
if res["implements"] not in
|
|
55
|
-
|
|
53
|
+
if concepts[concept_id]["implements"] and isinstance(concepts[concept_id]["implements"], list):
|
|
54
|
+
if res["implements"] not in concepts[concept_id]["implements"]:
|
|
55
|
+
concepts[concept_id]["implements"].append(res["implements"])
|
|
56
56
|
|
|
57
|
-
elif
|
|
58
|
-
|
|
57
|
+
elif concepts[concept_id]["implements"] and isinstance(concepts[concept_id]["implements"], str):
|
|
58
|
+
concepts[concept_id]["implements"] = [concepts[concept_id]["implements"]]
|
|
59
59
|
|
|
60
|
-
if res["implements"] not in
|
|
61
|
-
|
|
60
|
+
if res["implements"] not in concepts[concept_id]["implements"]:
|
|
61
|
+
concepts[concept_id]["implements"].append(res["implements"])
|
|
62
62
|
elif res["implements"]:
|
|
63
|
-
|
|
63
|
+
concepts[concept_id]["implements"] = [res["implements"]]
|
|
64
64
|
|
|
65
|
-
handle_meta("
|
|
66
|
-
handle_meta("
|
|
65
|
+
handle_meta("concept", concepts, concept_id, res, "name", issue_list)
|
|
66
|
+
handle_meta("concept", concepts, concept_id, res, "description", issue_list)
|
|
67
67
|
|
|
68
|
-
if not
|
|
69
|
-
issue_list.append(NeatValueError("Unable to parse
|
|
68
|
+
if not concepts:
|
|
69
|
+
issue_list.append(NeatValueError("Unable to parse concepts"))
|
|
70
70
|
|
|
71
|
-
return
|
|
71
|
+
return concepts, issue_list
|
|
72
72
|
|
|
73
73
|
|
|
74
74
|
def parse_properties(graph: Graph, query: str, language: str, issue_list: IssueList) -> tuple[dict, IssueList]:
|
|
@@ -94,12 +94,12 @@ def parse_properties(graph: Graph, query: str, language: str, issue_list: IssueL
|
|
|
94
94
|
property_id = res["property_"]
|
|
95
95
|
|
|
96
96
|
# Safeguarding against incomplete semantic definitions
|
|
97
|
-
if not res["
|
|
97
|
+
if not res["concept"] or isinstance(res["concept"], BNode):
|
|
98
98
|
issue_list.append(
|
|
99
99
|
ResourceRetrievalWarning(
|
|
100
100
|
property_id,
|
|
101
101
|
"property",
|
|
102
|
-
error=("Unable to determine to what
|
|
102
|
+
error=("Unable to determine to what concept property is being defined"),
|
|
103
103
|
)
|
|
104
104
|
)
|
|
105
105
|
continue
|
|
@@ -115,7 +115,7 @@ def parse_properties(graph: Graph, query: str, language: str, issue_list: IssueL
|
|
|
115
115
|
)
|
|
116
116
|
continue
|
|
117
117
|
|
|
118
|
-
id_ = f"{res['
|
|
118
|
+
id_ = f"{res['concept']}.{res['property_']}"
|
|
119
119
|
|
|
120
120
|
if id_ not in properties:
|
|
121
121
|
properties[id_] = res
|