obographs 0.0.3__py3-none-any.whl → 0.0.4__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 +453 -48
- obographs/version.py +1 -1
- {obographs-0.0.3.dist-info → obographs-0.0.4.dist-info}/METADATA +6 -22
- obographs-0.0.4.dist-info/RECORD +10 -0
- {obographs-0.0.3.dist-info → obographs-0.0.4.dist-info}/WHEEL +1 -1
- obographs-0.0.3.dist-info/RECORD +0 -10
- {obographs-0.0.3.dist-info → obographs-0.0.4.dist-info}/entry_points.txt +0 -0
- {obographs-0.0.3.dist-info → obographs-0.0.4.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,17 +176,31 @@ 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
206
|
definition: StandardizedDefinition | 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,23 @@ 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
|
+
subsets=[
|
|
266
|
+
_curie_or_uri_to_ref(subset, converter, strict=strict) for subset in meta.subsets
|
|
267
|
+
]
|
|
155
268
|
if meta.subsets
|
|
156
269
|
else None,
|
|
157
270
|
xrefs=xrefs or None,
|
|
@@ -162,31 +275,69 @@ class StandardizedMeta(BaseModel):
|
|
|
162
275
|
properties=props or None,
|
|
163
276
|
)
|
|
164
277
|
|
|
278
|
+
def to_raw(self, converter: Converter) -> Meta:
|
|
279
|
+
"""Create a raw object."""
|
|
280
|
+
return Meta(
|
|
281
|
+
definition=self.definition.to_raw(converter)
|
|
282
|
+
if self.definition and self.definition.value
|
|
283
|
+
else None,
|
|
284
|
+
subsets=_expand_list(self.subsets, converter),
|
|
285
|
+
xrefs=[xref.to_raw(converter) for xref in self.xrefs] if self.xrefs else None,
|
|
286
|
+
synonyms=[s.to_raw(converter) for s in self.synonyms] if self.synonyms else None,
|
|
287
|
+
comments=self.comments,
|
|
288
|
+
version=self.version, # TODO might need some kind of expansion?
|
|
289
|
+
deprecated=self.deprecated,
|
|
290
|
+
basicPropertyValues=[p.to_raw(converter) for p in self.properties]
|
|
291
|
+
if self.properties
|
|
292
|
+
else None,
|
|
293
|
+
)
|
|
294
|
+
|
|
165
295
|
|
|
166
|
-
class StandardizedNode(
|
|
296
|
+
class StandardizedNode(StandardizedBaseModel[Node]):
|
|
167
297
|
"""A standardized node."""
|
|
168
298
|
|
|
169
299
|
reference: Reference
|
|
170
300
|
label: str | None = Field(None)
|
|
171
301
|
meta: StandardizedMeta | None = None
|
|
172
302
|
type: NodeType | None = Field(None, description="Type of node")
|
|
303
|
+
property_type: PropertyType | None = Field(
|
|
304
|
+
None, description="Type of property, if the node type is a property"
|
|
305
|
+
)
|
|
173
306
|
|
|
174
307
|
@classmethod
|
|
175
|
-
def from_obograph_raw(
|
|
308
|
+
def from_obograph_raw(
|
|
309
|
+
cls, node: Node, converter: Converter, *, strict: bool = False
|
|
310
|
+
) -> Self | None:
|
|
176
311
|
"""Instantiate by standardizing a raw OBO Graph object."""
|
|
177
|
-
reference = _curie_or_uri_to_ref(node.id, converter)
|
|
312
|
+
reference = _curie_or_uri_to_ref(node.id, converter, strict=strict)
|
|
178
313
|
if reference is None:
|
|
314
|
+
if strict:
|
|
315
|
+
raise ValueError(f"failed to parse node's ID: {node.id}")
|
|
179
316
|
logger.warning("failed to parse node's ID %s", node.id)
|
|
180
317
|
return None
|
|
318
|
+
|
|
181
319
|
return cls(
|
|
182
320
|
reference=reference,
|
|
183
321
|
label=node.lbl,
|
|
184
|
-
meta=StandardizedMeta.from_obograph_raw(
|
|
322
|
+
meta=StandardizedMeta.from_obograph_raw(
|
|
323
|
+
node.meta, converter, flag=reference.curie, strict=strict
|
|
324
|
+
),
|
|
185
325
|
type=node.type,
|
|
326
|
+
property_type=node.propertyType,
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
def to_raw(self, converter: Converter) -> Node:
|
|
330
|
+
"""Create a raw object."""
|
|
331
|
+
return Node(
|
|
332
|
+
id=converter.expand_reference(self.reference),
|
|
333
|
+
lbl=self.label,
|
|
334
|
+
meta=self.meta.to_raw(converter) if self.meta is not None else None,
|
|
335
|
+
type=self.type,
|
|
336
|
+
propertyType=self.property_type,
|
|
186
337
|
)
|
|
187
338
|
|
|
188
339
|
|
|
189
|
-
class StandardizedEdge(
|
|
340
|
+
class StandardizedEdge(Triple, StandardizedBaseModel[Edge]):
|
|
190
341
|
"""A standardized edge."""
|
|
191
342
|
|
|
192
343
|
subject: Reference
|
|
@@ -195,18 +346,26 @@ class StandardizedEdge(BaseModel):
|
|
|
195
346
|
meta: StandardizedMeta | None = None
|
|
196
347
|
|
|
197
348
|
@classmethod
|
|
198
|
-
def from_obograph_raw(
|
|
349
|
+
def from_obograph_raw(
|
|
350
|
+
cls, edge: Edge, converter: Converter, *, strict: bool = False
|
|
351
|
+
) -> Self | None:
|
|
199
352
|
"""Instantiate by standardizing a raw OBO Graph object."""
|
|
200
|
-
subject = _curie_or_uri_to_ref(edge.sub, converter)
|
|
353
|
+
subject = _curie_or_uri_to_ref(edge.sub, converter, strict=strict)
|
|
201
354
|
if not subject:
|
|
355
|
+
if strict:
|
|
356
|
+
raise ValueError
|
|
202
357
|
logger.warning("failed to parse edge's subject %s", edge.sub)
|
|
203
358
|
return None
|
|
204
|
-
predicate = _curie_or_uri_to_ref(edge.pred, converter)
|
|
359
|
+
predicate = _curie_or_uri_to_ref(edge.pred, converter, strict=strict)
|
|
205
360
|
if not predicate:
|
|
361
|
+
if strict:
|
|
362
|
+
raise ValueError
|
|
206
363
|
logger.warning("failed to parse edge's predicate %s", edge.pred)
|
|
207
364
|
return None
|
|
208
|
-
obj = _curie_or_uri_to_ref(edge.obj, converter)
|
|
365
|
+
obj = _curie_or_uri_to_ref(edge.obj, converter, strict=strict)
|
|
209
366
|
if not obj:
|
|
367
|
+
if strict:
|
|
368
|
+
raise ValueError
|
|
210
369
|
logger.warning("failed to parse edge's object %s", edge.obj)
|
|
211
370
|
return None
|
|
212
371
|
return cls(
|
|
@@ -214,12 +373,178 @@ class StandardizedEdge(BaseModel):
|
|
|
214
373
|
predicate=predicate,
|
|
215
374
|
object=obj,
|
|
216
375
|
meta=StandardizedMeta.from_obograph_raw(
|
|
217
|
-
edge.meta,
|
|
376
|
+
edge.meta,
|
|
377
|
+
converter,
|
|
378
|
+
flag=f"{subject.curie} {predicate.curie} {obj.curie}",
|
|
379
|
+
strict=strict,
|
|
218
380
|
),
|
|
219
381
|
)
|
|
220
382
|
|
|
383
|
+
def to_raw(self, converter: Converter) -> Edge:
|
|
384
|
+
"""Create a raw object."""
|
|
385
|
+
if self.predicate in REVERSE_BUILTINS:
|
|
386
|
+
predicate = REVERSE_BUILTINS[self.predicate]
|
|
387
|
+
else:
|
|
388
|
+
predicate = converter.expand_reference(self.predicate, strict=True)
|
|
389
|
+
|
|
390
|
+
return Edge(
|
|
391
|
+
sub=converter.expand_reference(self.subject),
|
|
392
|
+
pred=predicate,
|
|
393
|
+
obj=converter.expand_reference(self.object),
|
|
394
|
+
meta=self.meta.to_raw(converter) if self.meta is not None else None,
|
|
395
|
+
)
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
class StandardizedDomainRangeAxiom(StandardizedBaseModel[DomainRangeAxiom]):
|
|
399
|
+
"""Represents a domain/range axiom."""
|
|
400
|
+
|
|
401
|
+
predicate: Reference
|
|
402
|
+
domains: list[Reference] = Field(default_factory=list)
|
|
403
|
+
ranges: list[Reference] = Field(default_factory=list)
|
|
404
|
+
all_values_from_edges: list[StandardizedEdge] = Field(default_factory=list)
|
|
405
|
+
meta: StandardizedMeta | None = None
|
|
406
|
+
|
|
407
|
+
@classmethod
|
|
408
|
+
def from_obograph_raw(
|
|
409
|
+
cls, obj: DomainRangeAxiom, converter: Converter, *, strict: bool = False
|
|
410
|
+
) -> Self | None:
|
|
411
|
+
"""Parse a raw object."""
|
|
412
|
+
return cls(
|
|
413
|
+
predicate=_curie_or_uri_to_ref(obj.predicateId, converter, strict=strict),
|
|
414
|
+
domains=_parse_list(obj.domainClassIds, converter, strict=strict) or [],
|
|
415
|
+
ranges=_parse_list(obj.rangeClassIds, converter, strict=strict) or [],
|
|
416
|
+
all_values_from_edges=[
|
|
417
|
+
StandardizedEdge.from_obograph_raw(edge, converter, strict=strict)
|
|
418
|
+
for edge in obj.allValuesFromEdges or []
|
|
419
|
+
],
|
|
420
|
+
meta=StandardizedMeta.from_obograph_raw(obj.meta, converter, strict=strict),
|
|
421
|
+
)
|
|
422
|
+
|
|
423
|
+
def to_raw(self, converter: Converter) -> DomainRangeAxiom:
|
|
424
|
+
"""Create a raw object."""
|
|
425
|
+
return DomainRangeAxiom(
|
|
426
|
+
predicateId=converter.expand_reference(self.predicate),
|
|
427
|
+
domainClassIds=_expand_list(self.domains, converter),
|
|
428
|
+
rangeClassIds=_expand_list(self.ranges, converter),
|
|
429
|
+
allValuesFromEdges=[edge.to_raw(converter) for edge in self.all_values_from_edges]
|
|
430
|
+
if self.all_values_from_edges
|
|
431
|
+
else None,
|
|
432
|
+
meta=self.meta.to_raw(converter) if self.meta is not None else None,
|
|
433
|
+
)
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
class StandardizedPropertyChainAxiom(StandardizedBaseModel[PropertyChainAxiom]):
|
|
437
|
+
"""Represents a property chain axiom."""
|
|
438
|
+
|
|
439
|
+
predicate: Reference
|
|
440
|
+
chain: list[Reference] = Field(default_factory=list)
|
|
441
|
+
meta: StandardizedMeta | None = None
|
|
442
|
+
|
|
443
|
+
@classmethod
|
|
444
|
+
def from_obograph_raw(
|
|
445
|
+
cls, obj: PropertyChainAxiom, converter: Converter, *, strict: bool = False
|
|
446
|
+
) -> Self | None:
|
|
447
|
+
"""Parse a raw object."""
|
|
448
|
+
return cls(
|
|
449
|
+
predicate=_curie_or_uri_to_ref(obj.predicateId, converter, strict=strict),
|
|
450
|
+
chain=_parse_list(obj.chainPredicateIds, converter, strict=strict),
|
|
451
|
+
meta=StandardizedMeta.from_obograph_raw(obj.meta, converter, strict=strict),
|
|
452
|
+
)
|
|
453
|
+
|
|
454
|
+
def to_raw(self, converter: Converter) -> PropertyChainAxiom:
|
|
455
|
+
"""Create a raw object."""
|
|
456
|
+
return PropertyChainAxiom(
|
|
457
|
+
predicateId=converter.expand_reference(self.predicate),
|
|
458
|
+
chainPredicateIds=_expand_list(self.chain, converter),
|
|
459
|
+
meta=self.meta.to_raw(converter) if self.meta is not None else None,
|
|
460
|
+
)
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
class StandardizedEquivalentNodeSet(StandardizedBaseModel[EquivalentNodeSet]):
|
|
464
|
+
"""Represents an equivalence set."""
|
|
465
|
+
|
|
466
|
+
node: Reference
|
|
467
|
+
equivalents: list[Reference] = Field(default_factory=list)
|
|
468
|
+
meta: StandardizedMeta | None = None
|
|
469
|
+
|
|
470
|
+
@classmethod
|
|
471
|
+
def from_obograph_raw(
|
|
472
|
+
cls, obj: EquivalentNodeSet, converter: Converter, *, strict: bool = False
|
|
473
|
+
) -> Self | None:
|
|
474
|
+
"""Parse a raw object."""
|
|
475
|
+
return cls(
|
|
476
|
+
node=_curie_or_uri_to_ref(obj.representativeNodeId, converter, strict=strict),
|
|
477
|
+
equivalents=_parse_list(obj.nodeIds, converter, strict=strict),
|
|
478
|
+
meta=StandardizedMeta.from_obograph_raw(obj.meta, converter, strict=strict),
|
|
479
|
+
)
|
|
480
|
+
|
|
481
|
+
def to_raw(self, converter: Converter) -> EquivalentNodeSet:
|
|
482
|
+
"""Create a raw object."""
|
|
483
|
+
return EquivalentNodeSet(
|
|
484
|
+
representativeNodeId=converter.expand_reference(self.node),
|
|
485
|
+
nodeIds=_expand_list(self.equivalents, converter),
|
|
486
|
+
meta=self.meta.to_raw(converter) if self.meta is not None else None,
|
|
487
|
+
)
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
class StandardizedExistentialRestriction(StandardizedBaseModel[ExistentialRestrictionExpression]):
|
|
491
|
+
"""Represents an existential restriction expression."""
|
|
492
|
+
|
|
493
|
+
predicate: Reference
|
|
494
|
+
target: Reference
|
|
495
|
+
|
|
496
|
+
@classmethod
|
|
497
|
+
def from_obograph_raw(
|
|
498
|
+
cls, obj: ExistentialRestrictionExpression, converter: Converter, *, strict: bool = False
|
|
499
|
+
) -> Self | None:
|
|
500
|
+
"""Parse a raw object."""
|
|
501
|
+
return cls(
|
|
502
|
+
predicate=_curie_or_uri_to_ref(obj.propertyId, converter, strict=strict),
|
|
503
|
+
target=_curie_or_uri_to_ref(obj.fillerId, converter, strict=strict),
|
|
504
|
+
)
|
|
505
|
+
|
|
506
|
+
def to_raw(self, converter: Converter) -> ExistentialRestrictionExpression:
|
|
507
|
+
"""Create a raw object."""
|
|
508
|
+
return ExistentialRestrictionExpression(
|
|
509
|
+
propertyId=converter.expand_reference(self.predicate),
|
|
510
|
+
fillerId=converter.expand_reference(self.target),
|
|
511
|
+
)
|
|
512
|
+
|
|
221
513
|
|
|
222
|
-
class
|
|
514
|
+
class StandardizedLogicalDefinition(StandardizedBaseModel[LogicalDefinition]):
|
|
515
|
+
"""Represents a logical definition axiom."""
|
|
516
|
+
|
|
517
|
+
node: Reference
|
|
518
|
+
geni: list[Reference] = Field(default_factory=list)
|
|
519
|
+
restrictions: list[StandardizedExistentialRestriction] = Field(default_factory=list)
|
|
520
|
+
meta: StandardizedMeta | None = None
|
|
521
|
+
|
|
522
|
+
@classmethod
|
|
523
|
+
def from_obograph_raw(
|
|
524
|
+
cls, obj: LogicalDefinition, converter: Converter, *, strict: bool = False
|
|
525
|
+
) -> Self | None:
|
|
526
|
+
"""Parse a raw object."""
|
|
527
|
+
return cls(
|
|
528
|
+
node=_curie_or_uri_to_ref(obj.definedClassId, converter, strict=strict),
|
|
529
|
+
geni=_parse_list(obj.genusIds, converter, strict=strict),
|
|
530
|
+
restrictions=[
|
|
531
|
+
StandardizedExistentialRestriction.from_obograph_raw(r, converter, strict=strict)
|
|
532
|
+
for r in obj.restrictions or []
|
|
533
|
+
],
|
|
534
|
+
meta=StandardizedMeta.from_obograph_raw(obj.meta, converter, strict=strict),
|
|
535
|
+
)
|
|
536
|
+
|
|
537
|
+
def to_raw(self, converter: Converter) -> LogicalDefinition:
|
|
538
|
+
"""Create a raw object."""
|
|
539
|
+
return LogicalDefinition(
|
|
540
|
+
definedClassId=converter.expand_reference(self.node),
|
|
541
|
+
genusIds=_expand_list(self.geni, converter),
|
|
542
|
+
restrictions=[r.to_raw(converter) for r in self.restrictions],
|
|
543
|
+
meta=self.meta.to_raw(converter) if self.meta is not None else None,
|
|
544
|
+
)
|
|
545
|
+
|
|
546
|
+
|
|
547
|
+
class StandardizedGraph(StandardizedBaseModel[Graph]):
|
|
223
548
|
"""A standardized graph."""
|
|
224
549
|
|
|
225
550
|
id: str | None = None
|
|
@@ -227,26 +552,62 @@ class StandardizedGraph(BaseModel):
|
|
|
227
552
|
nodes: list[StandardizedNode] = Field(default_factory=list)
|
|
228
553
|
edges: list[StandardizedEdge] = Field(default_factory=list)
|
|
229
554
|
|
|
230
|
-
|
|
555
|
+
equivalent_node_sets: list[StandardizedEquivalentNodeSet] = Field(default_factory=list)
|
|
556
|
+
logical_definition_axioms: list[StandardizedLogicalDefinition] = Field(default_factory=list)
|
|
557
|
+
domain_range_axioms: list[StandardizedDomainRangeAxiom] = Field(default_factory=list)
|
|
558
|
+
property_chain_axioms: list[StandardizedPropertyChainAxiom] = Field(default_factory=list)
|
|
231
559
|
|
|
232
560
|
@classmethod
|
|
233
|
-
def from_obograph_raw(cls, graph: Graph, converter: Converter) -> Self:
|
|
561
|
+
def from_obograph_raw(cls, graph: Graph, converter: Converter, *, strict: bool = False) -> Self:
|
|
234
562
|
"""Instantiate by standardizing a raw OBO Graph object."""
|
|
235
563
|
return cls(
|
|
236
564
|
id=graph.id,
|
|
237
|
-
meta=StandardizedMeta.from_obograph_raw(
|
|
565
|
+
meta=StandardizedMeta.from_obograph_raw(
|
|
566
|
+
graph.meta, converter, flag=graph.id or "", strict=strict
|
|
567
|
+
),
|
|
238
568
|
nodes=[
|
|
239
569
|
s_node
|
|
240
570
|
for node in graph.nodes
|
|
241
|
-
if (s_node := StandardizedNode.from_obograph_raw(node, converter))
|
|
571
|
+
if (s_node := StandardizedNode.from_obograph_raw(node, converter, strict=strict))
|
|
242
572
|
],
|
|
243
573
|
edges=[
|
|
244
574
|
s_edge
|
|
245
575
|
for edge in graph.edges
|
|
246
|
-
if (s_edge := StandardizedEdge.from_obograph_raw(edge, converter))
|
|
576
|
+
if (s_edge := StandardizedEdge.from_obograph_raw(edge, converter, strict=strict))
|
|
577
|
+
],
|
|
578
|
+
equivalent_node_sets=[
|
|
579
|
+
StandardizedEquivalentNodeSet.from_obograph_raw(e, converter, strict=strict)
|
|
580
|
+
for e in graph.equivalentNodesSets or []
|
|
581
|
+
],
|
|
582
|
+
logical_definition_axioms=[
|
|
583
|
+
StandardizedLogicalDefinition.from_obograph_raw(e, converter, strict=strict)
|
|
584
|
+
for e in graph.logicalDefinitionAxioms or []
|
|
585
|
+
],
|
|
586
|
+
property_chain_axioms=[
|
|
587
|
+
StandardizedPropertyChainAxiom.from_obograph_raw(e, converter, strict=strict)
|
|
588
|
+
for e in graph.propertyChainAxioms or []
|
|
589
|
+
],
|
|
590
|
+
domain_range_axioms=[
|
|
591
|
+
StandardizedDomainRangeAxiom.from_obograph_raw(e, converter, strict=strict)
|
|
592
|
+
for e in graph.domainRangeAxioms or []
|
|
247
593
|
],
|
|
248
594
|
)
|
|
249
595
|
|
|
596
|
+
def to_raw(self, converter: Converter) -> Graph:
|
|
597
|
+
"""Create a raw object."""
|
|
598
|
+
return Graph(
|
|
599
|
+
id=self.id,
|
|
600
|
+
meta=self.meta.to_raw(converter) if self.meta is not None else None,
|
|
601
|
+
nodes=[node.to_raw(converter) for node in self.nodes],
|
|
602
|
+
edges=[edge.to_raw(converter) for edge in self.edges],
|
|
603
|
+
logicalDefinitionAxioms=[
|
|
604
|
+
axiom.to_raw(converter) for axiom in self.logical_definition_axioms
|
|
605
|
+
],
|
|
606
|
+
propertyChainAxioms=[axiom.to_raw(converter) for axiom in self.property_chain_axioms],
|
|
607
|
+
domainRangeAxioms=[axiom.to_raw(converter) for axiom in self.domain_range_axioms],
|
|
608
|
+
equivalentNodesSets=[axiom.to_raw(converter) for axiom in self.equivalent_node_sets],
|
|
609
|
+
)
|
|
610
|
+
|
|
250
611
|
def _get_property(self, predicate: Reference) -> str | Reference | None:
|
|
251
612
|
if self.meta is None:
|
|
252
613
|
return None
|
|
@@ -266,29 +627,73 @@ class StandardizedGraph(BaseModel):
|
|
|
266
627
|
return r
|
|
267
628
|
|
|
268
629
|
|
|
269
|
-
|
|
630
|
+
class StandardizedGraphDocument(StandardizedBaseModel[GraphDocument]):
|
|
631
|
+
"""A standardized graph document."""
|
|
632
|
+
|
|
633
|
+
graphs: list[StandardizedGraph]
|
|
634
|
+
meta: StandardizedMeta | None = None
|
|
635
|
+
|
|
636
|
+
@classmethod
|
|
637
|
+
def from_obograph_raw(
|
|
638
|
+
cls, graph_document: GraphDocument, converter: Converter, *, strict: bool = False
|
|
639
|
+
) -> Self:
|
|
640
|
+
"""Instantiate by standardizing a raw OBO Graph Document object."""
|
|
641
|
+
return cls(
|
|
642
|
+
graphs=[
|
|
643
|
+
StandardizedGraph.from_obograph_raw(graph, converter, strict=strict)
|
|
644
|
+
for graph in graph_document.graphs
|
|
645
|
+
],
|
|
646
|
+
meta=StandardizedMeta.from_obograph_raw(graph_document.meta, converter, strict=strict),
|
|
647
|
+
)
|
|
648
|
+
|
|
649
|
+
def to_raw(self, converter: Converter) -> GraphDocument:
|
|
650
|
+
"""Create a raw object."""
|
|
651
|
+
return GraphDocument(
|
|
652
|
+
graphs=[graph.to_raw(converter) for graph in self.graphs],
|
|
653
|
+
meta=self.meta.to_raw(converter) if self.meta is not None else None,
|
|
654
|
+
)
|
|
655
|
+
|
|
656
|
+
|
|
657
|
+
def _parse_list(
|
|
658
|
+
curie_or_uris: list[str] | None, converter: Converter, *, strict: bool
|
|
659
|
+
) -> list[Reference] | None:
|
|
270
660
|
if not curie_or_uris:
|
|
271
661
|
return None
|
|
272
662
|
return [
|
|
273
663
|
reference
|
|
274
664
|
for curie_or_uri in curie_or_uris
|
|
275
|
-
if (reference := _curie_or_uri_to_ref(curie_or_uri, converter))
|
|
665
|
+
if (reference := _curie_or_uri_to_ref(curie_or_uri, converter, strict=strict))
|
|
276
666
|
]
|
|
277
667
|
|
|
278
668
|
|
|
279
669
|
#: defined in https://github.com/geneontology/obographs/blob/6676b10a5cce04707d75b9dd46fa08de70322b0b/obographs-owlapi/src/main/java/org/geneontology/obographs/owlapi/FromOwl.java#L36-L39
|
|
280
|
-
|
|
670
|
+
#: this list is complete.
|
|
671
|
+
BUILTINS: dict[str, Reference] = {
|
|
281
672
|
"is_a": vocabulary.is_a,
|
|
282
673
|
"subPropertyOf": vocabulary.subproperty_of,
|
|
283
674
|
"type": vocabulary.rdf_type,
|
|
284
675
|
"inverseOf": Reference(prefix="owl", identifier="inverseOf"),
|
|
285
676
|
}
|
|
286
677
|
|
|
678
|
+
"""maybe add these later?
|
|
679
|
+
# predicates, see https://github.com/geneontology/obographs/blob/6676b10a5cce04707d75b9dd46fa08de70322b0b/obographs-core/src/test/java/org/geneontology/obographs/core/model/axiom/PropertyChainAxiomTest.java#L12-L14
|
|
680
|
+
# "part_of": vocabulary.part_of,
|
|
681
|
+
# "has_part": vocabulary.has_part,
|
|
682
|
+
# "overlaps": Reference(prefix="RO", identifier="0002131"),
|
|
683
|
+
"""
|
|
287
684
|
|
|
288
|
-
|
|
685
|
+
REVERSE_BUILTINS: dict[Reference, str] = {v: k for k, v in BUILTINS.items()}
|
|
686
|
+
|
|
687
|
+
|
|
688
|
+
def _curie_or_uri_to_ref(s: str, converter: Converter, *, strict: bool) -> Reference | None:
|
|
289
689
|
if s in BUILTINS:
|
|
290
690
|
return BUILTINS[s]
|
|
291
|
-
|
|
691
|
+
try:
|
|
692
|
+
reference_tuple = converter.parse(s, strict=False)
|
|
693
|
+
except curies.preprocessing.BlocklistError:
|
|
694
|
+
return None
|
|
292
695
|
if reference_tuple is not None:
|
|
293
696
|
return reference_tuple.to_pydantic()
|
|
697
|
+
if strict:
|
|
698
|
+
raise ValueError(f"could not parse {s}")
|
|
294
699
|
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.4
|
|
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=69d26bbd35b49232b8d4bc2ae462f864f4fffcadf3acb7d541783fc8745dbd5e,25791
|
|
5
|
+
obographs/version.py,sha256=c50bb52fc81eb5b19dedfb8583a0c19b6127aff659301cb2d3d51f4d244fefc3,961
|
|
6
|
+
obographs-0.0.4.dist-info/licenses/LICENSE,sha256=4be0ec343e3bf11fd54321a6b576d5616ebb7d18898f741f63c517209e33bcb2,1076
|
|
7
|
+
obographs-0.0.4.dist-info/WHEEL,sha256=65f6765ba93534713730ff2172cd912ef280aa42867625a73f77c2fef0639dae,78
|
|
8
|
+
obographs-0.0.4.dist-info/entry_points.txt,sha256=9a9819cedd2186e28d5d42ddce5e3de1417b0db2b07392ff35f9adc7c86a8619,50
|
|
9
|
+
obographs-0.0.4.dist-info/METADATA,sha256=ac4daf3fa7f23379788e758debc91663ee15663ee1c9fabbf79bc69ca79c5e5b,12768
|
|
10
|
+
obographs-0.0.4.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
|