obographs 0.0.3__py3-none-any.whl → 0.0.5__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.
- obographs/__init__.py +41 -1
- obographs/model.py +72 -29
- obographs/standardized.py +456 -49
- obographs/version.py +1 -1
- {obographs-0.0.3.dist-info → obographs-0.0.5.dist-info}/METADATA +6 -22
- obographs-0.0.5.dist-info/RECORD +10 -0
- {obographs-0.0.3.dist-info → obographs-0.0.5.dist-info}/WHEEL +1 -1
- obographs-0.0.3.dist-info/RECORD +0 -10
- {obographs-0.0.3.dist-info → obographs-0.0.5.dist-info}/entry_points.txt +0 -0
- {obographs-0.0.3.dist-info → obographs-0.0.5.dist-info}/licenses/LICENSE +0 -0
obographs/__init__.py
CHANGED
|
@@ -1,30 +1,70 @@
|
|
|
1
1
|
"""A python data model for OBO Graphs."""
|
|
2
2
|
|
|
3
|
-
from .model import
|
|
3
|
+
from .model import (
|
|
4
|
+
Definition,
|
|
5
|
+
DomainRangeAxiom,
|
|
6
|
+
Edge,
|
|
7
|
+
EquivalentNodeSet,
|
|
8
|
+
ExistentialRestrictionExpression,
|
|
9
|
+
Graph,
|
|
10
|
+
GraphDocument,
|
|
11
|
+
LogicalDefinition,
|
|
12
|
+
Meta,
|
|
13
|
+
Node,
|
|
14
|
+
NodeType,
|
|
15
|
+
Property,
|
|
16
|
+
PropertyChainAxiom,
|
|
17
|
+
PropertyType,
|
|
18
|
+
Synonym,
|
|
19
|
+
Xref,
|
|
20
|
+
read,
|
|
21
|
+
)
|
|
4
22
|
from .standardized import (
|
|
23
|
+
StandardizedBaseModel,
|
|
5
24
|
StandardizedDefinition,
|
|
25
|
+
StandardizedDomainRangeAxiom,
|
|
6
26
|
StandardizedEdge,
|
|
27
|
+
StandardizedEquivalentNodeSet,
|
|
28
|
+
StandardizedExistentialRestriction,
|
|
7
29
|
StandardizedGraph,
|
|
30
|
+
StandardizedGraphDocument,
|
|
31
|
+
StandardizedLogicalDefinition,
|
|
8
32
|
StandardizedMeta,
|
|
9
33
|
StandardizedNode,
|
|
10
34
|
StandardizedProperty,
|
|
35
|
+
StandardizedPropertyChainAxiom,
|
|
11
36
|
StandardizedSynonym,
|
|
12
37
|
StandardizedXref,
|
|
13
38
|
)
|
|
14
39
|
|
|
15
40
|
__all__ = [
|
|
41
|
+
"Definition",
|
|
42
|
+
"DomainRangeAxiom",
|
|
43
|
+
"Edge",
|
|
44
|
+
"EquivalentNodeSet",
|
|
45
|
+
"ExistentialRestrictionExpression",
|
|
16
46
|
"Graph",
|
|
17
47
|
"GraphDocument",
|
|
48
|
+
"LogicalDefinition",
|
|
18
49
|
"Meta",
|
|
19
50
|
"Node",
|
|
20
51
|
"NodeType",
|
|
21
52
|
"Property",
|
|
53
|
+
"PropertyChainAxiom",
|
|
54
|
+
"PropertyType",
|
|
55
|
+
"StandardizedBaseModel",
|
|
22
56
|
"StandardizedDefinition",
|
|
57
|
+
"StandardizedDomainRangeAxiom",
|
|
23
58
|
"StandardizedEdge",
|
|
59
|
+
"StandardizedEquivalentNodeSet",
|
|
60
|
+
"StandardizedExistentialRestriction",
|
|
24
61
|
"StandardizedGraph",
|
|
62
|
+
"StandardizedGraphDocument",
|
|
63
|
+
"StandardizedLogicalDefinition",
|
|
25
64
|
"StandardizedMeta",
|
|
26
65
|
"StandardizedNode",
|
|
27
66
|
"StandardizedProperty",
|
|
67
|
+
"StandardizedPropertyChainAxiom",
|
|
28
68
|
"StandardizedSynonym",
|
|
29
69
|
"StandardizedXref",
|
|
30
70
|
"Synonym",
|
obographs/model.py
CHANGED
|
@@ -9,27 +9,35 @@
|
|
|
9
9
|
|
|
10
10
|
from __future__ import annotations
|
|
11
11
|
|
|
12
|
+
import gzip
|
|
12
13
|
import json
|
|
13
14
|
import logging
|
|
14
15
|
from collections import defaultdict
|
|
15
16
|
from pathlib import Path
|
|
16
|
-
from typing import TYPE_CHECKING,
|
|
17
|
+
from typing import TYPE_CHECKING, Literal, TypeAlias, overload
|
|
17
18
|
|
|
19
|
+
import curies
|
|
20
|
+
from curies.vocabulary import SynonymScopeOIO
|
|
18
21
|
from pydantic import BaseModel, Field
|
|
19
22
|
|
|
20
23
|
if TYPE_CHECKING:
|
|
21
|
-
import curies
|
|
22
|
-
|
|
23
24
|
from .standardized import StandardizedGraph
|
|
24
25
|
|
|
25
26
|
__all__ = [
|
|
26
27
|
"Definition",
|
|
28
|
+
"DomainRangeAxiom",
|
|
27
29
|
"Edge",
|
|
30
|
+
"EquivalentNodeSet",
|
|
31
|
+
"ExistentialRestrictionExpression",
|
|
28
32
|
"Graph",
|
|
29
33
|
"GraphDocument",
|
|
34
|
+
"LogicalDefinition",
|
|
30
35
|
"Meta",
|
|
31
36
|
"Node",
|
|
37
|
+
"NodeType",
|
|
32
38
|
"Property",
|
|
39
|
+
"PropertyChainAxiom",
|
|
40
|
+
"PropertyType",
|
|
33
41
|
"Synonym",
|
|
34
42
|
"Xref",
|
|
35
43
|
"read",
|
|
@@ -40,24 +48,12 @@ logger = logging.getLogger(__name__)
|
|
|
40
48
|
OBO_URI_PREFIX = "http://purl.obolibrary.org/obo/"
|
|
41
49
|
OBO_URI_PREFIX_LEN = len(OBO_URI_PREFIX)
|
|
42
50
|
|
|
43
|
-
SynonymPredicate: TypeAlias = Literal[
|
|
44
|
-
"hasExactSynonym",
|
|
45
|
-
"hasBroadSynonym",
|
|
46
|
-
"hasNarrowSynonym",
|
|
47
|
-
"hasRelatedSynonym",
|
|
48
|
-
]
|
|
49
51
|
NodeType: TypeAlias = Literal["CLASS", "PROPERTY", "INDIVIDUAL"]
|
|
50
52
|
|
|
51
|
-
|
|
53
|
+
#: When node type is ``PROPERTY``, this is extra information
|
|
54
|
+
PropertyType: TypeAlias = Literal["ANNOTATION", "OBJECT", "DATA"]
|
|
52
55
|
|
|
53
|
-
|
|
54
|
-
#: identifiers. See https://owlcollab.github.io/oboformat/doc/GO.format.obo-1_4.html
|
|
55
|
-
OBO_SYNONYM_TO_OIO: dict[str, SynonymPredicate] = {
|
|
56
|
-
"EXACT": "hasExactSynonym",
|
|
57
|
-
"BROAD": "hasBroadSynonym",
|
|
58
|
-
"NARROW": "hasNarrowSynonym",
|
|
59
|
-
"RELATED": "hasRelatedSynonym",
|
|
60
|
-
}
|
|
56
|
+
TimeoutHint = int | float | None
|
|
61
57
|
|
|
62
58
|
|
|
63
59
|
class Property(BaseModel):
|
|
@@ -91,7 +87,7 @@ class Synonym(BaseModel):
|
|
|
91
87
|
"""Represents a synonym inside an object meta."""
|
|
92
88
|
|
|
93
89
|
val: str | None = Field(default=None)
|
|
94
|
-
pred:
|
|
90
|
+
pred: SynonymScopeOIO = Field(default="hasExactSynonym")
|
|
95
91
|
synonymType: str | None = Field(None, examples=["OMO:0003000"]) # noqa:N815
|
|
96
92
|
xrefs: list[str] = Field(
|
|
97
93
|
default_factory=list,
|
|
@@ -129,6 +125,51 @@ class Node(BaseModel):
|
|
|
129
125
|
lbl: str | None = Field(None, description="The name of the node")
|
|
130
126
|
meta: Meta | None = None
|
|
131
127
|
type: NodeType | None = Field(None, description="Type of node")
|
|
128
|
+
propertyType: PropertyType | None = Field( # noqa:N815
|
|
129
|
+
None, description="Type of property, if the node type is a property"
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
class DomainRangeAxiom(BaseModel):
|
|
134
|
+
"""Represents a domain/range axiom."""
|
|
135
|
+
|
|
136
|
+
predicateId: str # noqa:N815
|
|
137
|
+
domainClassIds: list[str] | None = None # noqa:N815
|
|
138
|
+
rangeClassIds: list[str] | None = None # noqa:N815
|
|
139
|
+
allValuesFromEdges: list[Edge] | None = None # noqa:N815
|
|
140
|
+
meta: Meta | None = None
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class PropertyChainAxiom(BaseModel):
|
|
144
|
+
"""Represents a property chain axiom."""
|
|
145
|
+
|
|
146
|
+
predicateId: str # noqa:N815
|
|
147
|
+
chainPredicateIds: list[str] # noqa:N815
|
|
148
|
+
meta: Meta | None = None
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
class ExistentialRestrictionExpression(BaseModel):
|
|
152
|
+
"""Represents an existential restriction."""
|
|
153
|
+
|
|
154
|
+
propertyId: str # noqa:N815
|
|
155
|
+
fillerId: str # noqa:N815
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
class LogicalDefinition(BaseModel):
|
|
159
|
+
"""Represents a logical definition chain axiom."""
|
|
160
|
+
|
|
161
|
+
definedClassId: str # noqa:N815
|
|
162
|
+
genusIds: list[str] | None = None # noqa:N815
|
|
163
|
+
restrictions: list[ExistentialRestrictionExpression] | None = None
|
|
164
|
+
meta: Meta | None = None
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
class EquivalentNodeSet(BaseModel):
|
|
168
|
+
"""Represents a set of equivalent nodes."""
|
|
169
|
+
|
|
170
|
+
representativeNodeId: str # noqa:N815
|
|
171
|
+
nodeIds: list[str] # noqa:N815
|
|
172
|
+
meta: Meta | None = None
|
|
132
173
|
|
|
133
174
|
|
|
134
175
|
class Graph(BaseModel):
|
|
@@ -138,10 +179,10 @@ class Graph(BaseModel):
|
|
|
138
179
|
meta: Meta | None = None
|
|
139
180
|
nodes: list[Node] = Field(default_factory=list)
|
|
140
181
|
edges: list[Edge] = Field(default_factory=list)
|
|
141
|
-
equivalentNodesSets: list[
|
|
142
|
-
logicalDefinitionAxioms: list[
|
|
143
|
-
domainRangeAxioms: list[
|
|
144
|
-
propertyChainAxioms: list[
|
|
182
|
+
equivalentNodesSets: list[EquivalentNodeSet] = Field(default_factory=list) # noqa:N815
|
|
183
|
+
logicalDefinitionAxioms: list[LogicalDefinition] = Field(default_factory=list) # noqa:N815
|
|
184
|
+
domainRangeAxioms: list[DomainRangeAxiom] = Field(default_factory=list) # noqa:N815
|
|
185
|
+
propertyChainAxioms: list[PropertyChainAxiom] = Field(default_factory=list) # noqa:N815
|
|
145
186
|
|
|
146
187
|
def standardize(self, converter: curies.Converter) -> StandardizedGraph:
|
|
147
188
|
"""Standardize the graph."""
|
|
@@ -210,12 +251,14 @@ def read(
|
|
|
210
251
|
|
|
211
252
|
elif isinstance(source, str | Path):
|
|
212
253
|
path = Path(source).expanduser().resolve()
|
|
213
|
-
if path.is_file():
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
254
|
+
if not path.is_file():
|
|
255
|
+
raise FileNotFoundError
|
|
256
|
+
if path.suffix.endswith(".gz"):
|
|
257
|
+
with gzip.open(path, mode="rt") as file:
|
|
258
|
+
graph_document = GraphDocument.model_validate(json.load(file))
|
|
259
|
+
else:
|
|
260
|
+
with path.open() as file:
|
|
261
|
+
graph_document = GraphDocument.model_validate(json.load(file))
|
|
219
262
|
else:
|
|
220
263
|
raise TypeError(f"Unhandled source: {source}")
|
|
221
264
|
|
obographs/standardized.py
CHANGED
|
@@ -3,20 +3,48 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import logging
|
|
6
|
+
from abc import ABC, abstractmethod
|
|
7
|
+
from typing import Generic, TypeVar, cast
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
import curies.preprocessing
|
|
10
|
+
from curies import Converter, Reference, Triple, vocabulary
|
|
11
|
+
from curies.vocabulary import SynonymScopeOIO
|
|
8
12
|
from pydantic import BaseModel, Field
|
|
9
13
|
from typing_extensions import Self
|
|
10
14
|
|
|
11
|
-
from obographs.model import
|
|
15
|
+
from obographs.model import (
|
|
16
|
+
Definition,
|
|
17
|
+
DomainRangeAxiom,
|
|
18
|
+
Edge,
|
|
19
|
+
EquivalentNodeSet,
|
|
20
|
+
ExistentialRestrictionExpression,
|
|
21
|
+
Graph,
|
|
22
|
+
GraphDocument,
|
|
23
|
+
LogicalDefinition,
|
|
24
|
+
Meta,
|
|
25
|
+
Node,
|
|
26
|
+
NodeType,
|
|
27
|
+
Property,
|
|
28
|
+
PropertyChainAxiom,
|
|
29
|
+
PropertyType,
|
|
30
|
+
Synonym,
|
|
31
|
+
Xref,
|
|
32
|
+
)
|
|
12
33
|
|
|
13
34
|
__all__ = [
|
|
35
|
+
"StandardizedBaseModel",
|
|
14
36
|
"StandardizedDefinition",
|
|
37
|
+
"StandardizedDomainRangeAxiom",
|
|
15
38
|
"StandardizedEdge",
|
|
39
|
+
"StandardizedEquivalentNodeSet",
|
|
40
|
+
"StandardizedExistentialRestriction",
|
|
16
41
|
"StandardizedGraph",
|
|
42
|
+
"StandardizedGraphDocument",
|
|
43
|
+
"StandardizedLogicalDefinition",
|
|
17
44
|
"StandardizedMeta",
|
|
18
45
|
"StandardizedNode",
|
|
19
46
|
"StandardizedProperty",
|
|
47
|
+
"StandardizedPropertyChainAxiom",
|
|
20
48
|
"StandardizedSynonym",
|
|
21
49
|
"StandardizedXref",
|
|
22
50
|
]
|
|
@@ -24,7 +52,33 @@ __all__ = [
|
|
|
24
52
|
logger = logging.getLogger(__name__)
|
|
25
53
|
|
|
26
54
|
|
|
27
|
-
|
|
55
|
+
def _expand_list(references: list[Reference] | None, converter: Converter) -> list[str] | None:
|
|
56
|
+
if references is None or not references:
|
|
57
|
+
return None
|
|
58
|
+
return [converter.expand_reference(r, strict=True) for r in references]
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
X = TypeVar("X")
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class StandardizedBaseModel(BaseModel, ABC, Generic[X]):
|
|
65
|
+
"""A standardized property."""
|
|
66
|
+
|
|
67
|
+
@classmethod
|
|
68
|
+
@abstractmethod
|
|
69
|
+
def from_obograph_raw(
|
|
70
|
+
cls, obj: X, converter: Converter, *, strict: bool = False
|
|
71
|
+
) -> Self | None:
|
|
72
|
+
"""Instantiate by standardizing a raw OBO Graph object."""
|
|
73
|
+
raise NotImplementedError
|
|
74
|
+
|
|
75
|
+
@abstractmethod
|
|
76
|
+
def to_raw(self, converter: Converter) -> X:
|
|
77
|
+
"""Create a raw object."""
|
|
78
|
+
raise NotImplementedError
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class StandardizedProperty(StandardizedBaseModel[Property]):
|
|
28
82
|
"""A standardized property."""
|
|
29
83
|
|
|
30
84
|
predicate: Reference
|
|
@@ -35,52 +89,85 @@ class StandardizedProperty(BaseModel):
|
|
|
35
89
|
meta: StandardizedMeta | None = None
|
|
36
90
|
|
|
37
91
|
@classmethod
|
|
38
|
-
def from_obograph_raw(
|
|
92
|
+
def from_obograph_raw(
|
|
93
|
+
cls, prop: Property, converter: Converter, *, strict: bool = False
|
|
94
|
+
) -> Self:
|
|
39
95
|
"""Instantiate by standardizing a raw OBO Graph object."""
|
|
40
96
|
if not prop.val or not prop.pred:
|
|
41
97
|
raise ValueError
|
|
42
98
|
value: Reference | str | None
|
|
43
|
-
|
|
44
|
-
|
|
99
|
+
|
|
100
|
+
if (
|
|
101
|
+
prop.val.startswith("http://")
|
|
102
|
+
or prop.val.startswith("https")
|
|
103
|
+
or converter.is_curie(prop.val)
|
|
104
|
+
or prop.val in BUILTINS
|
|
105
|
+
):
|
|
106
|
+
value = _curie_or_uri_to_ref(prop.val, converter, strict=False) or prop.val
|
|
45
107
|
else:
|
|
46
108
|
value = prop.val
|
|
47
|
-
if value is None:
|
|
48
|
-
raise ValueError
|
|
49
109
|
return cls(
|
|
50
|
-
predicate=_curie_or_uri_to_ref(prop.pred, converter),
|
|
110
|
+
predicate=_curie_or_uri_to_ref(prop.pred, converter, strict=strict),
|
|
51
111
|
value=value,
|
|
52
112
|
)
|
|
53
113
|
|
|
114
|
+
def to_raw(self, converter: Converter) -> Property:
|
|
115
|
+
"""Create a raw object."""
|
|
116
|
+
return Property(
|
|
117
|
+
pred=converter.expand_reference(self.predicate),
|
|
118
|
+
val=converter.expand_reference(self.value)
|
|
119
|
+
if isinstance(self.value, Reference)
|
|
120
|
+
else self.value,
|
|
121
|
+
xrefs=_expand_list(self.xrefs, converter),
|
|
122
|
+
meta=self.meta.to_raw(converter) if self.meta is not None else None,
|
|
123
|
+
)
|
|
124
|
+
|
|
54
125
|
|
|
55
|
-
class StandardizedDefinition(
|
|
126
|
+
class StandardizedDefinition(StandardizedBaseModel[Definition]):
|
|
56
127
|
"""A standardized definition."""
|
|
57
128
|
|
|
58
129
|
value: str | None = Field(default=None)
|
|
59
130
|
xrefs: list[Reference] | None = Field(default=None)
|
|
60
131
|
|
|
61
132
|
@classmethod
|
|
62
|
-
def from_obograph_raw(
|
|
63
|
-
|
|
133
|
+
def from_obograph_raw(
|
|
134
|
+
cls, definition: Definition | None, converter: Converter, *, strict: bool = False
|
|
135
|
+
) -> Self | None:
|
|
136
|
+
"""Parse a raw object."""
|
|
64
137
|
if definition is None:
|
|
65
138
|
return None
|
|
66
139
|
return cls(
|
|
67
140
|
value=definition.val,
|
|
68
|
-
xrefs=_parse_list(definition.xrefs, converter),
|
|
141
|
+
xrefs=_parse_list(definition.xrefs, converter, strict=strict),
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
def to_raw(self, converter: Converter) -> Definition:
|
|
145
|
+
"""Create a raw object."""
|
|
146
|
+
return Definition(
|
|
147
|
+
val=self.value,
|
|
148
|
+
xrefs=_expand_list(self.xrefs, converter),
|
|
69
149
|
)
|
|
70
150
|
|
|
71
151
|
|
|
72
|
-
class StandardizedXref(
|
|
152
|
+
class StandardizedXref(StandardizedBaseModel[Xref]):
|
|
73
153
|
"""A standardized database cross-reference."""
|
|
74
154
|
|
|
75
155
|
reference: Reference
|
|
76
156
|
|
|
77
157
|
@classmethod
|
|
78
|
-
def from_obograph_raw(cls, xref: Xref, converter: Converter) -> Self:
|
|
158
|
+
def from_obograph_raw(cls, xref: Xref, converter: Converter, *, strict: bool = False) -> Self:
|
|
79
159
|
"""Instantiate by standardizing a raw OBO Graph object."""
|
|
80
|
-
|
|
160
|
+
reference = _curie_or_uri_to_ref(xref.val, converter, strict=strict)
|
|
161
|
+
if reference is None:
|
|
162
|
+
raise ValueError(f"could not parse xref: {xref.val}")
|
|
163
|
+
return cls(reference=reference)
|
|
81
164
|
|
|
165
|
+
def to_raw(self, converter: Converter) -> Xref:
|
|
166
|
+
"""Create a raw object."""
|
|
167
|
+
return Xref(val=self.reference.curie)
|
|
82
168
|
|
|
83
|
-
|
|
169
|
+
|
|
170
|
+
class StandardizedSynonym(StandardizedBaseModel[Synonym]):
|
|
84
171
|
"""A standardized synonym."""
|
|
85
172
|
|
|
86
173
|
text: str
|
|
@@ -89,20 +176,34 @@ class StandardizedSynonym(BaseModel):
|
|
|
89
176
|
xrefs: list[Reference] | None = None
|
|
90
177
|
|
|
91
178
|
@classmethod
|
|
92
|
-
def from_obograph_raw(
|
|
179
|
+
def from_obograph_raw(
|
|
180
|
+
cls, synonym: Synonym, converter: Converter, *, strict: bool = False
|
|
181
|
+
) -> Self:
|
|
93
182
|
"""Instantiate by standardizing a raw OBO Graph object."""
|
|
94
183
|
return cls(
|
|
95
184
|
text=synonym.val,
|
|
96
185
|
predicate=Reference(prefix="oboInOwl", identifier=synonym.pred),
|
|
97
|
-
type=synonym.synonymType
|
|
98
|
-
|
|
186
|
+
type=synonym.synonymType
|
|
187
|
+
and _curie_or_uri_to_ref(synonym.synonymType, converter, strict=strict),
|
|
188
|
+
xrefs=_parse_list(synonym.xrefs, converter, strict=strict),
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
def to_raw(self, converter: Converter) -> Synonym:
|
|
192
|
+
"""Create a raw object."""
|
|
193
|
+
if self.predicate.prefix.lower() != "oboinowl":
|
|
194
|
+
raise ValueError
|
|
195
|
+
return Synonym(
|
|
196
|
+
val=self.text,
|
|
197
|
+
pred=cast(SynonymScopeOIO, self.predicate.identifier),
|
|
198
|
+
synonymType=converter.expand_reference(self.type) if self.type is not None else None,
|
|
199
|
+
xrefs=_expand_list(self.xrefs, converter) or [],
|
|
99
200
|
)
|
|
100
201
|
|
|
101
202
|
|
|
102
|
-
class StandardizedMeta(
|
|
203
|
+
class StandardizedMeta(StandardizedBaseModel[Meta]):
|
|
103
204
|
"""A standardized meta object."""
|
|
104
205
|
|
|
105
|
-
definition: StandardizedDefinition | None
|
|
206
|
+
definition: StandardizedDefinition | None = None
|
|
106
207
|
subsets: list[Reference] | None = None
|
|
107
208
|
xrefs: list[StandardizedXref] | None = None
|
|
108
209
|
synonyms: list[StandardizedSynonym] | None = None
|
|
@@ -113,7 +214,7 @@ class StandardizedMeta(BaseModel):
|
|
|
113
214
|
|
|
114
215
|
@classmethod
|
|
115
216
|
def from_obograph_raw( # noqa:C901
|
|
116
|
-
cls, meta: Meta | None, converter: Converter, flag: str = ""
|
|
217
|
+
cls, meta: Meta | None, converter: Converter, flag: str = "", strict: bool = False
|
|
117
218
|
) -> Self | None:
|
|
118
219
|
"""Instantiate by standardizing a raw OBO Graph object."""
|
|
119
220
|
if meta is None:
|
|
@@ -123,8 +224,10 @@ class StandardizedMeta(BaseModel):
|
|
|
123
224
|
for raw_xref in meta.xrefs or []:
|
|
124
225
|
if raw_xref.val:
|
|
125
226
|
try:
|
|
126
|
-
st_xref = StandardizedXref.from_obograph_raw(raw_xref, converter)
|
|
227
|
+
st_xref = StandardizedXref.from_obograph_raw(raw_xref, converter, strict=strict)
|
|
127
228
|
except ValueError:
|
|
229
|
+
if strict:
|
|
230
|
+
raise
|
|
128
231
|
logger.debug("[%s] failed to standardize xref: %s", flag, raw_xref)
|
|
129
232
|
else:
|
|
130
233
|
xrefs.append(st_xref)
|
|
@@ -133,8 +236,10 @@ class StandardizedMeta(BaseModel):
|
|
|
133
236
|
for raw_synonym in meta.synonyms or []:
|
|
134
237
|
if raw_synonym.val:
|
|
135
238
|
try:
|
|
136
|
-
s = StandardizedSynonym.from_obograph_raw(raw_synonym, converter)
|
|
239
|
+
s = StandardizedSynonym.from_obograph_raw(raw_synonym, converter, strict=strict)
|
|
137
240
|
except ValueError:
|
|
241
|
+
if strict:
|
|
242
|
+
raise
|
|
138
243
|
logger.debug("[%s] failed to standardize synonym: %s", flag, raw_synonym)
|
|
139
244
|
else:
|
|
140
245
|
synonyms.append(s)
|
|
@@ -143,15 +248,25 @@ class StandardizedMeta(BaseModel):
|
|
|
143
248
|
for raw_prop in meta.basicPropertyValues or []:
|
|
144
249
|
if raw_prop.val and raw_prop.pred:
|
|
145
250
|
try:
|
|
146
|
-
prop = StandardizedProperty.from_obograph_raw(
|
|
251
|
+
prop = StandardizedProperty.from_obograph_raw(
|
|
252
|
+
raw_prop, converter, strict=strict
|
|
253
|
+
)
|
|
147
254
|
except ValueError:
|
|
255
|
+
if strict:
|
|
256
|
+
raise
|
|
148
257
|
logger.debug("[%s] failed to standardize property: %s", flag, raw_prop)
|
|
149
258
|
else:
|
|
150
259
|
props.append(prop)
|
|
151
260
|
|
|
152
261
|
return cls(
|
|
153
|
-
definition=StandardizedDefinition.from_obograph_raw(
|
|
154
|
-
|
|
262
|
+
definition=StandardizedDefinition.from_obograph_raw(
|
|
263
|
+
meta.definition, converter, strict=strict
|
|
264
|
+
)
|
|
265
|
+
if meta.definition is not None
|
|
266
|
+
else None,
|
|
267
|
+
subsets=[
|
|
268
|
+
_curie_or_uri_to_ref(subset, converter, strict=strict) for subset in meta.subsets
|
|
269
|
+
]
|
|
155
270
|
if meta.subsets
|
|
156
271
|
else None,
|
|
157
272
|
xrefs=xrefs or None,
|
|
@@ -162,31 +277,69 @@ class StandardizedMeta(BaseModel):
|
|
|
162
277
|
properties=props or None,
|
|
163
278
|
)
|
|
164
279
|
|
|
280
|
+
def to_raw(self, converter: Converter) -> Meta:
|
|
281
|
+
"""Create a raw object."""
|
|
282
|
+
return Meta(
|
|
283
|
+
definition=self.definition.to_raw(converter)
|
|
284
|
+
if self.definition and self.definition.value
|
|
285
|
+
else None,
|
|
286
|
+
subsets=_expand_list(self.subsets, converter),
|
|
287
|
+
xrefs=[xref.to_raw(converter) for xref in self.xrefs] if self.xrefs else None,
|
|
288
|
+
synonyms=[s.to_raw(converter) for s in self.synonyms] if self.synonyms else None,
|
|
289
|
+
comments=self.comments,
|
|
290
|
+
version=self.version, # TODO might need some kind of expansion?
|
|
291
|
+
deprecated=self.deprecated,
|
|
292
|
+
basicPropertyValues=[p.to_raw(converter) for p in self.properties]
|
|
293
|
+
if self.properties
|
|
294
|
+
else None,
|
|
295
|
+
)
|
|
296
|
+
|
|
165
297
|
|
|
166
|
-
class StandardizedNode(
|
|
298
|
+
class StandardizedNode(StandardizedBaseModel[Node]):
|
|
167
299
|
"""A standardized node."""
|
|
168
300
|
|
|
169
301
|
reference: Reference
|
|
170
302
|
label: str | None = Field(None)
|
|
171
303
|
meta: StandardizedMeta | None = None
|
|
172
304
|
type: NodeType | None = Field(None, description="Type of node")
|
|
305
|
+
property_type: PropertyType | None = Field(
|
|
306
|
+
None, description="Type of property, if the node type is a property"
|
|
307
|
+
)
|
|
173
308
|
|
|
174
309
|
@classmethod
|
|
175
|
-
def from_obograph_raw(
|
|
310
|
+
def from_obograph_raw(
|
|
311
|
+
cls, node: Node, converter: Converter, *, strict: bool = False
|
|
312
|
+
) -> Self | None:
|
|
176
313
|
"""Instantiate by standardizing a raw OBO Graph object."""
|
|
177
|
-
reference = _curie_or_uri_to_ref(node.id, converter)
|
|
314
|
+
reference = _curie_or_uri_to_ref(node.id, converter, strict=strict)
|
|
178
315
|
if reference is None:
|
|
316
|
+
if strict:
|
|
317
|
+
raise ValueError(f"failed to parse node's ID: {node.id}")
|
|
179
318
|
logger.warning("failed to parse node's ID %s", node.id)
|
|
180
319
|
return None
|
|
320
|
+
|
|
181
321
|
return cls(
|
|
182
322
|
reference=reference,
|
|
183
323
|
label=node.lbl,
|
|
184
|
-
meta=StandardizedMeta.from_obograph_raw(
|
|
324
|
+
meta=StandardizedMeta.from_obograph_raw(
|
|
325
|
+
node.meta, converter, flag=reference.curie, strict=strict
|
|
326
|
+
),
|
|
185
327
|
type=node.type,
|
|
328
|
+
property_type=node.propertyType,
|
|
329
|
+
)
|
|
330
|
+
|
|
331
|
+
def to_raw(self, converter: Converter) -> Node:
|
|
332
|
+
"""Create a raw object."""
|
|
333
|
+
return Node(
|
|
334
|
+
id=converter.expand_reference(self.reference),
|
|
335
|
+
lbl=self.label,
|
|
336
|
+
meta=self.meta.to_raw(converter) if self.meta is not None else None,
|
|
337
|
+
type=self.type,
|
|
338
|
+
propertyType=self.property_type,
|
|
186
339
|
)
|
|
187
340
|
|
|
188
341
|
|
|
189
|
-
class StandardizedEdge(
|
|
342
|
+
class StandardizedEdge(Triple, StandardizedBaseModel[Edge]):
|
|
190
343
|
"""A standardized edge."""
|
|
191
344
|
|
|
192
345
|
subject: Reference
|
|
@@ -195,18 +348,26 @@ class StandardizedEdge(BaseModel):
|
|
|
195
348
|
meta: StandardizedMeta | None = None
|
|
196
349
|
|
|
197
350
|
@classmethod
|
|
198
|
-
def from_obograph_raw(
|
|
351
|
+
def from_obograph_raw(
|
|
352
|
+
cls, edge: Edge, converter: Converter, *, strict: bool = False
|
|
353
|
+
) -> Self | None:
|
|
199
354
|
"""Instantiate by standardizing a raw OBO Graph object."""
|
|
200
|
-
subject = _curie_or_uri_to_ref(edge.sub, converter)
|
|
355
|
+
subject = _curie_or_uri_to_ref(edge.sub, converter, strict=strict)
|
|
201
356
|
if not subject:
|
|
357
|
+
if strict:
|
|
358
|
+
raise ValueError
|
|
202
359
|
logger.warning("failed to parse edge's subject %s", edge.sub)
|
|
203
360
|
return None
|
|
204
|
-
predicate = _curie_or_uri_to_ref(edge.pred, converter)
|
|
361
|
+
predicate = _curie_or_uri_to_ref(edge.pred, converter, strict=strict)
|
|
205
362
|
if not predicate:
|
|
363
|
+
if strict:
|
|
364
|
+
raise ValueError
|
|
206
365
|
logger.warning("failed to parse edge's predicate %s", edge.pred)
|
|
207
366
|
return None
|
|
208
|
-
obj = _curie_or_uri_to_ref(edge.obj, converter)
|
|
367
|
+
obj = _curie_or_uri_to_ref(edge.obj, converter, strict=strict)
|
|
209
368
|
if not obj:
|
|
369
|
+
if strict:
|
|
370
|
+
raise ValueError
|
|
210
371
|
logger.warning("failed to parse edge's object %s", edge.obj)
|
|
211
372
|
return None
|
|
212
373
|
return cls(
|
|
@@ -214,12 +375,178 @@ class StandardizedEdge(BaseModel):
|
|
|
214
375
|
predicate=predicate,
|
|
215
376
|
object=obj,
|
|
216
377
|
meta=StandardizedMeta.from_obograph_raw(
|
|
217
|
-
edge.meta,
|
|
378
|
+
edge.meta,
|
|
379
|
+
converter,
|
|
380
|
+
flag=f"{subject.curie} {predicate.curie} {obj.curie}",
|
|
381
|
+
strict=strict,
|
|
218
382
|
),
|
|
219
383
|
)
|
|
220
384
|
|
|
385
|
+
def to_raw(self, converter: Converter) -> Edge:
|
|
386
|
+
"""Create a raw object."""
|
|
387
|
+
if self.predicate in REVERSE_BUILTINS:
|
|
388
|
+
predicate = REVERSE_BUILTINS[self.predicate]
|
|
389
|
+
else:
|
|
390
|
+
predicate = converter.expand_reference(self.predicate, strict=True)
|
|
391
|
+
|
|
392
|
+
return Edge(
|
|
393
|
+
sub=converter.expand_reference(self.subject),
|
|
394
|
+
pred=predicate,
|
|
395
|
+
obj=converter.expand_reference(self.object),
|
|
396
|
+
meta=self.meta.to_raw(converter) if self.meta is not None else None,
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
class StandardizedDomainRangeAxiom(StandardizedBaseModel[DomainRangeAxiom]):
|
|
401
|
+
"""Represents a domain/range axiom."""
|
|
402
|
+
|
|
403
|
+
predicate: Reference
|
|
404
|
+
domains: list[Reference] = Field(default_factory=list)
|
|
405
|
+
ranges: list[Reference] = Field(default_factory=list)
|
|
406
|
+
all_values_from_edges: list[StandardizedEdge] = Field(default_factory=list)
|
|
407
|
+
meta: StandardizedMeta | None = None
|
|
408
|
+
|
|
409
|
+
@classmethod
|
|
410
|
+
def from_obograph_raw(
|
|
411
|
+
cls, obj: DomainRangeAxiom, converter: Converter, *, strict: bool = False
|
|
412
|
+
) -> Self | None:
|
|
413
|
+
"""Parse a raw object."""
|
|
414
|
+
return cls(
|
|
415
|
+
predicate=_curie_or_uri_to_ref(obj.predicateId, converter, strict=strict),
|
|
416
|
+
domains=_parse_list(obj.domainClassIds, converter, strict=strict) or [],
|
|
417
|
+
ranges=_parse_list(obj.rangeClassIds, converter, strict=strict) or [],
|
|
418
|
+
all_values_from_edges=[
|
|
419
|
+
StandardizedEdge.from_obograph_raw(edge, converter, strict=strict)
|
|
420
|
+
for edge in obj.allValuesFromEdges or []
|
|
421
|
+
],
|
|
422
|
+
meta=StandardizedMeta.from_obograph_raw(obj.meta, converter, strict=strict),
|
|
423
|
+
)
|
|
424
|
+
|
|
425
|
+
def to_raw(self, converter: Converter) -> DomainRangeAxiom:
|
|
426
|
+
"""Create a raw object."""
|
|
427
|
+
return DomainRangeAxiom(
|
|
428
|
+
predicateId=converter.expand_reference(self.predicate),
|
|
429
|
+
domainClassIds=_expand_list(self.domains, converter),
|
|
430
|
+
rangeClassIds=_expand_list(self.ranges, converter),
|
|
431
|
+
allValuesFromEdges=[edge.to_raw(converter) for edge in self.all_values_from_edges]
|
|
432
|
+
if self.all_values_from_edges
|
|
433
|
+
else None,
|
|
434
|
+
meta=self.meta.to_raw(converter) if self.meta is not None else None,
|
|
435
|
+
)
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
class StandardizedPropertyChainAxiom(StandardizedBaseModel[PropertyChainAxiom]):
|
|
439
|
+
"""Represents a property chain axiom."""
|
|
440
|
+
|
|
441
|
+
predicate: Reference
|
|
442
|
+
chain: list[Reference] = Field(default_factory=list)
|
|
443
|
+
meta: StandardizedMeta | None = None
|
|
444
|
+
|
|
445
|
+
@classmethod
|
|
446
|
+
def from_obograph_raw(
|
|
447
|
+
cls, obj: PropertyChainAxiom, converter: Converter, *, strict: bool = False
|
|
448
|
+
) -> Self | None:
|
|
449
|
+
"""Parse a raw object."""
|
|
450
|
+
return cls(
|
|
451
|
+
predicate=_curie_or_uri_to_ref(obj.predicateId, converter, strict=strict),
|
|
452
|
+
chain=_parse_list(obj.chainPredicateIds, converter, strict=strict),
|
|
453
|
+
meta=StandardizedMeta.from_obograph_raw(obj.meta, converter, strict=strict),
|
|
454
|
+
)
|
|
455
|
+
|
|
456
|
+
def to_raw(self, converter: Converter) -> PropertyChainAxiom:
|
|
457
|
+
"""Create a raw object."""
|
|
458
|
+
return PropertyChainAxiom(
|
|
459
|
+
predicateId=converter.expand_reference(self.predicate),
|
|
460
|
+
chainPredicateIds=_expand_list(self.chain, converter),
|
|
461
|
+
meta=self.meta.to_raw(converter) if self.meta is not None else None,
|
|
462
|
+
)
|
|
463
|
+
|
|
464
|
+
|
|
465
|
+
class StandardizedEquivalentNodeSet(StandardizedBaseModel[EquivalentNodeSet]):
|
|
466
|
+
"""Represents an equivalence set."""
|
|
467
|
+
|
|
468
|
+
node: Reference
|
|
469
|
+
equivalents: list[Reference] = Field(default_factory=list)
|
|
470
|
+
meta: StandardizedMeta | None = None
|
|
471
|
+
|
|
472
|
+
@classmethod
|
|
473
|
+
def from_obograph_raw(
|
|
474
|
+
cls, obj: EquivalentNodeSet, converter: Converter, *, strict: bool = False
|
|
475
|
+
) -> Self | None:
|
|
476
|
+
"""Parse a raw object."""
|
|
477
|
+
return cls(
|
|
478
|
+
node=_curie_or_uri_to_ref(obj.representativeNodeId, converter, strict=strict),
|
|
479
|
+
equivalents=_parse_list(obj.nodeIds, converter, strict=strict),
|
|
480
|
+
meta=StandardizedMeta.from_obograph_raw(obj.meta, converter, strict=strict),
|
|
481
|
+
)
|
|
482
|
+
|
|
483
|
+
def to_raw(self, converter: Converter) -> EquivalentNodeSet:
|
|
484
|
+
"""Create a raw object."""
|
|
485
|
+
return EquivalentNodeSet(
|
|
486
|
+
representativeNodeId=converter.expand_reference(self.node),
|
|
487
|
+
nodeIds=_expand_list(self.equivalents, converter),
|
|
488
|
+
meta=self.meta.to_raw(converter) if self.meta is not None else None,
|
|
489
|
+
)
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
class StandardizedExistentialRestriction(StandardizedBaseModel[ExistentialRestrictionExpression]):
|
|
493
|
+
"""Represents an existential restriction expression."""
|
|
494
|
+
|
|
495
|
+
predicate: Reference
|
|
496
|
+
target: Reference
|
|
497
|
+
|
|
498
|
+
@classmethod
|
|
499
|
+
def from_obograph_raw(
|
|
500
|
+
cls, obj: ExistentialRestrictionExpression, converter: Converter, *, strict: bool = False
|
|
501
|
+
) -> Self | None:
|
|
502
|
+
"""Parse a raw object."""
|
|
503
|
+
return cls(
|
|
504
|
+
predicate=_curie_or_uri_to_ref(obj.propertyId, converter, strict=strict),
|
|
505
|
+
target=_curie_or_uri_to_ref(obj.fillerId, converter, strict=strict),
|
|
506
|
+
)
|
|
507
|
+
|
|
508
|
+
def to_raw(self, converter: Converter) -> ExistentialRestrictionExpression:
|
|
509
|
+
"""Create a raw object."""
|
|
510
|
+
return ExistentialRestrictionExpression(
|
|
511
|
+
propertyId=converter.expand_reference(self.predicate),
|
|
512
|
+
fillerId=converter.expand_reference(self.target),
|
|
513
|
+
)
|
|
514
|
+
|
|
221
515
|
|
|
222
|
-
class
|
|
516
|
+
class StandardizedLogicalDefinition(StandardizedBaseModel[LogicalDefinition]):
|
|
517
|
+
"""Represents a logical definition axiom."""
|
|
518
|
+
|
|
519
|
+
node: Reference
|
|
520
|
+
geni: list[Reference] = Field(default_factory=list)
|
|
521
|
+
restrictions: list[StandardizedExistentialRestriction] = Field(default_factory=list)
|
|
522
|
+
meta: StandardizedMeta | None = None
|
|
523
|
+
|
|
524
|
+
@classmethod
|
|
525
|
+
def from_obograph_raw(
|
|
526
|
+
cls, obj: LogicalDefinition, converter: Converter, *, strict: bool = False
|
|
527
|
+
) -> Self | None:
|
|
528
|
+
"""Parse a raw object."""
|
|
529
|
+
return cls(
|
|
530
|
+
node=_curie_or_uri_to_ref(obj.definedClassId, converter, strict=strict),
|
|
531
|
+
geni=_parse_list(obj.genusIds, converter, strict=strict),
|
|
532
|
+
restrictions=[
|
|
533
|
+
StandardizedExistentialRestriction.from_obograph_raw(r, converter, strict=strict)
|
|
534
|
+
for r in obj.restrictions or []
|
|
535
|
+
],
|
|
536
|
+
meta=StandardizedMeta.from_obograph_raw(obj.meta, converter, strict=strict),
|
|
537
|
+
)
|
|
538
|
+
|
|
539
|
+
def to_raw(self, converter: Converter) -> LogicalDefinition:
|
|
540
|
+
"""Create a raw object."""
|
|
541
|
+
return LogicalDefinition(
|
|
542
|
+
definedClassId=converter.expand_reference(self.node),
|
|
543
|
+
genusIds=_expand_list(self.geni, converter),
|
|
544
|
+
restrictions=[r.to_raw(converter) for r in self.restrictions],
|
|
545
|
+
meta=self.meta.to_raw(converter) if self.meta is not None else None,
|
|
546
|
+
)
|
|
547
|
+
|
|
548
|
+
|
|
549
|
+
class StandardizedGraph(StandardizedBaseModel[Graph]):
|
|
223
550
|
"""A standardized graph."""
|
|
224
551
|
|
|
225
552
|
id: str | None = None
|
|
@@ -227,26 +554,62 @@ class StandardizedGraph(BaseModel):
|
|
|
227
554
|
nodes: list[StandardizedNode] = Field(default_factory=list)
|
|
228
555
|
edges: list[StandardizedEdge] = Field(default_factory=list)
|
|
229
556
|
|
|
230
|
-
|
|
557
|
+
equivalent_node_sets: list[StandardizedEquivalentNodeSet] = Field(default_factory=list)
|
|
558
|
+
logical_definition_axioms: list[StandardizedLogicalDefinition] = Field(default_factory=list)
|
|
559
|
+
domain_range_axioms: list[StandardizedDomainRangeAxiom] = Field(default_factory=list)
|
|
560
|
+
property_chain_axioms: list[StandardizedPropertyChainAxiom] = Field(default_factory=list)
|
|
231
561
|
|
|
232
562
|
@classmethod
|
|
233
|
-
def from_obograph_raw(cls, graph: Graph, converter: Converter) -> Self:
|
|
563
|
+
def from_obograph_raw(cls, graph: Graph, converter: Converter, *, strict: bool = False) -> Self:
|
|
234
564
|
"""Instantiate by standardizing a raw OBO Graph object."""
|
|
235
565
|
return cls(
|
|
236
566
|
id=graph.id,
|
|
237
|
-
meta=StandardizedMeta.from_obograph_raw(
|
|
567
|
+
meta=StandardizedMeta.from_obograph_raw(
|
|
568
|
+
graph.meta, converter, flag=graph.id or "", strict=strict
|
|
569
|
+
),
|
|
238
570
|
nodes=[
|
|
239
571
|
s_node
|
|
240
572
|
for node in graph.nodes
|
|
241
|
-
if (s_node := StandardizedNode.from_obograph_raw(node, converter))
|
|
573
|
+
if (s_node := StandardizedNode.from_obograph_raw(node, converter, strict=strict))
|
|
242
574
|
],
|
|
243
575
|
edges=[
|
|
244
576
|
s_edge
|
|
245
577
|
for edge in graph.edges
|
|
246
|
-
if (s_edge := StandardizedEdge.from_obograph_raw(edge, converter))
|
|
578
|
+
if (s_edge := StandardizedEdge.from_obograph_raw(edge, converter, strict=strict))
|
|
579
|
+
],
|
|
580
|
+
equivalent_node_sets=[
|
|
581
|
+
StandardizedEquivalentNodeSet.from_obograph_raw(e, converter, strict=strict)
|
|
582
|
+
for e in graph.equivalentNodesSets or []
|
|
583
|
+
],
|
|
584
|
+
logical_definition_axioms=[
|
|
585
|
+
StandardizedLogicalDefinition.from_obograph_raw(e, converter, strict=strict)
|
|
586
|
+
for e in graph.logicalDefinitionAxioms or []
|
|
587
|
+
],
|
|
588
|
+
property_chain_axioms=[
|
|
589
|
+
StandardizedPropertyChainAxiom.from_obograph_raw(e, converter, strict=strict)
|
|
590
|
+
for e in graph.propertyChainAxioms or []
|
|
591
|
+
],
|
|
592
|
+
domain_range_axioms=[
|
|
593
|
+
StandardizedDomainRangeAxiom.from_obograph_raw(e, converter, strict=strict)
|
|
594
|
+
for e in graph.domainRangeAxioms or []
|
|
247
595
|
],
|
|
248
596
|
)
|
|
249
597
|
|
|
598
|
+
def to_raw(self, converter: Converter) -> Graph:
|
|
599
|
+
"""Create a raw object."""
|
|
600
|
+
return Graph(
|
|
601
|
+
id=self.id,
|
|
602
|
+
meta=self.meta.to_raw(converter) if self.meta is not None else None,
|
|
603
|
+
nodes=[node.to_raw(converter) for node in self.nodes],
|
|
604
|
+
edges=[edge.to_raw(converter) for edge in self.edges],
|
|
605
|
+
logicalDefinitionAxioms=[
|
|
606
|
+
axiom.to_raw(converter) for axiom in self.logical_definition_axioms
|
|
607
|
+
],
|
|
608
|
+
propertyChainAxioms=[axiom.to_raw(converter) for axiom in self.property_chain_axioms],
|
|
609
|
+
domainRangeAxioms=[axiom.to_raw(converter) for axiom in self.domain_range_axioms],
|
|
610
|
+
equivalentNodesSets=[axiom.to_raw(converter) for axiom in self.equivalent_node_sets],
|
|
611
|
+
)
|
|
612
|
+
|
|
250
613
|
def _get_property(self, predicate: Reference) -> str | Reference | None:
|
|
251
614
|
if self.meta is None:
|
|
252
615
|
return None
|
|
@@ -266,29 +629,73 @@ class StandardizedGraph(BaseModel):
|
|
|
266
629
|
return r
|
|
267
630
|
|
|
268
631
|
|
|
269
|
-
|
|
632
|
+
class StandardizedGraphDocument(StandardizedBaseModel[GraphDocument]):
|
|
633
|
+
"""A standardized graph document."""
|
|
634
|
+
|
|
635
|
+
graphs: list[StandardizedGraph]
|
|
636
|
+
meta: StandardizedMeta | None = None
|
|
637
|
+
|
|
638
|
+
@classmethod
|
|
639
|
+
def from_obograph_raw(
|
|
640
|
+
cls, graph_document: GraphDocument, converter: Converter, *, strict: bool = False
|
|
641
|
+
) -> Self:
|
|
642
|
+
"""Instantiate by standardizing a raw OBO Graph Document object."""
|
|
643
|
+
return cls(
|
|
644
|
+
graphs=[
|
|
645
|
+
StandardizedGraph.from_obograph_raw(graph, converter, strict=strict)
|
|
646
|
+
for graph in graph_document.graphs
|
|
647
|
+
],
|
|
648
|
+
meta=StandardizedMeta.from_obograph_raw(graph_document.meta, converter, strict=strict),
|
|
649
|
+
)
|
|
650
|
+
|
|
651
|
+
def to_raw(self, converter: Converter) -> GraphDocument:
|
|
652
|
+
"""Create a raw object."""
|
|
653
|
+
return GraphDocument(
|
|
654
|
+
graphs=[graph.to_raw(converter) for graph in self.graphs],
|
|
655
|
+
meta=self.meta.to_raw(converter) if self.meta is not None else None,
|
|
656
|
+
)
|
|
657
|
+
|
|
658
|
+
|
|
659
|
+
def _parse_list(
|
|
660
|
+
curie_or_uris: list[str] | None, converter: Converter, *, strict: bool
|
|
661
|
+
) -> list[Reference] | None:
|
|
270
662
|
if not curie_or_uris:
|
|
271
663
|
return None
|
|
272
664
|
return [
|
|
273
665
|
reference
|
|
274
666
|
for curie_or_uri in curie_or_uris
|
|
275
|
-
if (reference := _curie_or_uri_to_ref(curie_or_uri, converter))
|
|
667
|
+
if (reference := _curie_or_uri_to_ref(curie_or_uri, converter, strict=strict))
|
|
276
668
|
]
|
|
277
669
|
|
|
278
670
|
|
|
279
671
|
#: defined in https://github.com/geneontology/obographs/blob/6676b10a5cce04707d75b9dd46fa08de70322b0b/obographs-owlapi/src/main/java/org/geneontology/obographs/owlapi/FromOwl.java#L36-L39
|
|
280
|
-
|
|
672
|
+
#: this list is complete.
|
|
673
|
+
BUILTINS: dict[str, Reference] = {
|
|
281
674
|
"is_a": vocabulary.is_a,
|
|
282
675
|
"subPropertyOf": vocabulary.subproperty_of,
|
|
283
676
|
"type": vocabulary.rdf_type,
|
|
284
677
|
"inverseOf": Reference(prefix="owl", identifier="inverseOf"),
|
|
285
678
|
}
|
|
286
679
|
|
|
680
|
+
"""maybe add these later?
|
|
681
|
+
# predicates, see https://github.com/geneontology/obographs/blob/6676b10a5cce04707d75b9dd46fa08de70322b0b/obographs-core/src/test/java/org/geneontology/obographs/core/model/axiom/PropertyChainAxiomTest.java#L12-L14
|
|
682
|
+
# "part_of": vocabulary.part_of,
|
|
683
|
+
# "has_part": vocabulary.has_part,
|
|
684
|
+
# "overlaps": Reference(prefix="RO", identifier="0002131"),
|
|
685
|
+
"""
|
|
287
686
|
|
|
288
|
-
|
|
687
|
+
REVERSE_BUILTINS: dict[Reference, str] = {v: k for k, v in BUILTINS.items()}
|
|
688
|
+
|
|
689
|
+
|
|
690
|
+
def _curie_or_uri_to_ref(s: str, converter: Converter, *, strict: bool) -> Reference | None:
|
|
289
691
|
if s in BUILTINS:
|
|
290
692
|
return BUILTINS[s]
|
|
291
|
-
|
|
693
|
+
try:
|
|
694
|
+
reference_tuple = converter.parse(s, strict=False)
|
|
695
|
+
except curies.preprocessing.BlocklistError:
|
|
696
|
+
return None
|
|
292
697
|
if reference_tuple is not None:
|
|
293
698
|
return reference_tuple.to_pydantic()
|
|
699
|
+
if strict:
|
|
700
|
+
raise ValueError(f"could not parse {s}")
|
|
294
701
|
return None
|
obographs/version.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: obographs
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.5
|
|
4
4
|
Summary: A python data model for OBO Graphs
|
|
5
5
|
Keywords: snekpack,cookiecutter
|
|
6
6
|
Author: Charles Tapley Hoyt
|
|
@@ -23,15 +23,8 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
23
23
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
24
24
|
Classifier: Typing :: Typed
|
|
25
25
|
Requires-Dist: pydantic
|
|
26
|
-
Requires-Dist: curies>=0.10.
|
|
26
|
+
Requires-Dist: curies>=0.10.19
|
|
27
27
|
Requires-Dist: typing-extensions
|
|
28
|
-
Requires-Dist: sphinx>=8 ; extra == 'docs'
|
|
29
|
-
Requires-Dist: sphinx-rtd-theme>=3.0 ; extra == 'docs'
|
|
30
|
-
Requires-Dist: sphinx-automodapi ; extra == 'docs'
|
|
31
|
-
Requires-Dist: autodoc-pydantic ; extra == 'docs'
|
|
32
|
-
Requires-Dist: requests ; extra == 'network'
|
|
33
|
-
Requires-Dist: pytest ; extra == 'tests'
|
|
34
|
-
Requires-Dist: coverage[toml] ; extra == 'tests'
|
|
35
28
|
Maintainer: Charles Tapley Hoyt
|
|
36
29
|
Maintainer-email: Charles Tapley Hoyt <cthoyt@gmail.com>
|
|
37
30
|
Requires-Python: >=3.10
|
|
@@ -40,9 +33,6 @@ Project-URL: Documentation, https://obographs.readthedocs.io
|
|
|
40
33
|
Project-URL: Funding, https://github.com/sponsors/cthoyt
|
|
41
34
|
Project-URL: Homepage, https://github.com/cthoyt/obographs
|
|
42
35
|
Project-URL: Repository, https://github.com/cthoyt/obographs.git
|
|
43
|
-
Provides-Extra: docs
|
|
44
|
-
Provides-Extra: network
|
|
45
|
-
Provides-Extra: tests
|
|
46
36
|
Description-Content-Type: text/markdown
|
|
47
37
|
|
|
48
38
|
<!--
|
|
@@ -129,18 +119,15 @@ $ python3 -m pip install obographs
|
|
|
129
119
|
The most recent code and data can be installed directly from GitHub with uv:
|
|
130
120
|
|
|
131
121
|
```console
|
|
132
|
-
$ uv
|
|
122
|
+
$ uv pip install git+https://github.com/cthoyt/obographs.git
|
|
133
123
|
```
|
|
134
124
|
|
|
135
125
|
or with pip:
|
|
136
126
|
|
|
137
127
|
```console
|
|
138
|
-
$
|
|
128
|
+
$ python3 -m pip install git+https://github.com/cthoyt/obographs.git
|
|
139
129
|
```
|
|
140
130
|
|
|
141
|
-
Note that this requires setting `UV_PREVIEW` mode enabled until the uv build
|
|
142
|
-
backend becomes a stable feature.
|
|
143
|
-
|
|
144
131
|
## 👐 Contributing
|
|
145
132
|
|
|
146
133
|
Contributions, whether filing an issue, making a pull request, or forking, are
|
|
@@ -203,18 +190,15 @@ To install in development mode, use the following:
|
|
|
203
190
|
```console
|
|
204
191
|
$ git clone git+https://github.com/cthoyt/obographs.git
|
|
205
192
|
$ cd obographs
|
|
206
|
-
$ uv
|
|
193
|
+
$ uv pip install -e .
|
|
207
194
|
```
|
|
208
195
|
|
|
209
196
|
Alternatively, install using pip:
|
|
210
197
|
|
|
211
198
|
```console
|
|
212
|
-
$
|
|
199
|
+
$ python3 -m pip install -e .
|
|
213
200
|
```
|
|
214
201
|
|
|
215
|
-
Note that this requires setting `UV_PREVIEW` mode enabled until the uv build
|
|
216
|
-
backend becomes a stable feature.
|
|
217
|
-
|
|
218
202
|
### Updating Package Boilerplate
|
|
219
203
|
|
|
220
204
|
This project uses `cruft` to keep boilerplate (i.e., configuration, contribution
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
obographs/__init__.py,sha256=55f4bf18441bd7f6c41afa68d094532933b02b21dbdd20679cf8807c1791d494,1601
|
|
2
|
+
obographs/model.py,sha256=1f1bda132b83d8e08d7301eddb9be8d58b7e61c5b30e9baab9c24fd22348db53,8457
|
|
3
|
+
obographs/py.typed,sha256=01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b,1
|
|
4
|
+
obographs/standardized.py,sha256=43ee42d342f33df38f24151339cdeb6525252af541366149c7719d188901a52f,25863
|
|
5
|
+
obographs/version.py,sha256=03a64be7e09716976ae72d4c1ce70afe06d2bf1772e45dd140a3903675f07332,961
|
|
6
|
+
obographs-0.0.5.dist-info/licenses/LICENSE,sha256=4be0ec343e3bf11fd54321a6b576d5616ebb7d18898f741f63c517209e33bcb2,1076
|
|
7
|
+
obographs-0.0.5.dist-info/WHEEL,sha256=65f6765ba93534713730ff2172cd912ef280aa42867625a73f77c2fef0639dae,78
|
|
8
|
+
obographs-0.0.5.dist-info/entry_points.txt,sha256=9a9819cedd2186e28d5d42ddce5e3de1417b0db2b07392ff35f9adc7c86a8619,50
|
|
9
|
+
obographs-0.0.5.dist-info/METADATA,sha256=5dd83cf5b36da7b18dbb68e37072463e342e189975429e9f3aa3535675e7874d,12768
|
|
10
|
+
obographs-0.0.5.dist-info/RECORD,,
|
obographs-0.0.3.dist-info/RECORD
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
obographs/version.py,sha256=3709d2674acd39467891048cff0ca525f08edfba747910e241f23b6fb168d2dc,961
|
|
2
|
-
obographs/__init__.py,sha256=0c3d73d035bde44a5375cbc4dffcf314fc89994853777e0048f1307b0fdd53a8,706
|
|
3
|
-
obographs/model.py,sha256=445dbea604eb3d732c691afee71291348a6185750121ac41fcfeb8973b6a219b,7120
|
|
4
|
-
obographs/py.typed,sha256=01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b,1
|
|
5
|
-
obographs/standardized.py,sha256=27955c754e0f077aa8a4c36e9941331e5b8a716bb2cc21295b7ede7917bbc18d,9859
|
|
6
|
-
obographs-0.0.3.dist-info/licenses/LICENSE,sha256=4be0ec343e3bf11fd54321a6b576d5616ebb7d18898f741f63c517209e33bcb2,1076
|
|
7
|
-
obographs-0.0.3.dist-info/WHEEL,sha256=e3765529bb0cc791d07188d72ec6a759d7625ff6d3a5e4b710d25409bae03770,79
|
|
8
|
-
obographs-0.0.3.dist-info/entry_points.txt,sha256=9a9819cedd2186e28d5d42ddce5e3de1417b0db2b07392ff35f9adc7c86a8619,50
|
|
9
|
-
obographs-0.0.3.dist-info/METADATA,sha256=ce84eea275fad376b42901cbd5d93982cae494d0595cea5cbd7ee44748f6631c,13438
|
|
10
|
-
obographs-0.0.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|