pyobo 0.12.2__py3-none-any.whl → 0.12.3__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.
@@ -0,0 +1,242 @@
1
+ """Import of OBO Graph JSON."""
2
+
3
+ import logging
4
+ from pathlib import Path
5
+
6
+ import curies
7
+ import obographs
8
+ from curies import Converter
9
+ from curies.vocabulary import SynonymScope, synonym_scopes
10
+ from obographs import (
11
+ Graph,
12
+ NodeType,
13
+ StandardizedGraph,
14
+ StandardizedMeta,
15
+ StandardizedNode,
16
+ StandardizedSynonym,
17
+ )
18
+
19
+ from pyobo import Obo, Reference, StanzaType, Synonym, Term, TypeDef
20
+ from pyobo.identifier_utils import get_converter
21
+ from pyobo.struct import Annotation, OBOLiteral, make_ad_hoc_ontology
22
+ from pyobo.struct import vocabulary as v
23
+ from pyobo.struct.typedef import has_ontology_root_term
24
+
25
+ __all__ = [
26
+ "from_node",
27
+ "from_obograph",
28
+ "from_standardized_graph",
29
+ "read_obograph",
30
+ ]
31
+
32
+ logger = logging.getLogger(__name__)
33
+
34
+
35
+ def read_obograph(
36
+ prefix: str, path: str | Path, *, converter: Converter | None = None, strict: bool = False
37
+ ) -> Obo:
38
+ """Read an OBO Graph JSON file using :func:`obographs.read` then process into a PyOBO structure."""
39
+ graph = obographs.read(path, squeeze=True)
40
+ return from_obograph(prefix=prefix, graph=graph, converter=converter, strict=strict)
41
+
42
+
43
+ def from_obograph(
44
+ prefix: str, graph: Graph, *, converter: Converter | None = None, strict: bool = False
45
+ ) -> Obo:
46
+ """Parse a raw OBO Graph JSON into a PyOBO structure."""
47
+ if converter is None:
48
+ converter = get_converter()
49
+ standardized_graph = graph.standardize(converter, strict=strict)
50
+ return from_standardized_graph(prefix, standardized_graph)
51
+
52
+
53
+ def from_standardized_graph(prefix: str, graph: StandardizedGraph) -> Obo:
54
+ """Generate an OBO data structure from OBO Graph JSON."""
55
+ terms: dict[Reference, Term] = {}
56
+ typedefs: dict[Reference, TypeDef] = {}
57
+ for node in graph.nodes:
58
+ stanza = from_node(node)
59
+ match stanza:
60
+ case Term():
61
+ terms[stanza.reference] = stanza
62
+ case TypeDef():
63
+ typedefs[stanza.reference] = stanza
64
+
65
+ for edge in graph.edges:
66
+ s, p, o = (Reference.from_reference(r) for r in (edge.subject, edge.predicate, edge.object))
67
+ if s in terms:
68
+ stanza = terms[s]
69
+ stanza.append_relationship(p, o)
70
+ elif s in typedefs:
71
+ stanza = typedefs[s]
72
+ stanza.append_relationship(p, o)
73
+
74
+ root_terms: list[Reference] = []
75
+ property_values = []
76
+ auto_generated_by: str | None = None
77
+ if graph.meta:
78
+ for prop in graph.meta.properties or []:
79
+ predicate = Reference.from_reference(prop.predicate)
80
+ if predicate == has_ontology_root_term:
81
+ if isinstance(prop.value, str):
82
+ raise TypeError
83
+ else:
84
+ root_terms.append(Reference.from_reference(prop.value))
85
+ elif predicate == v.obo_autogenerated_by:
86
+ if not isinstance(prop.value, str):
87
+ raise TypeError
88
+ auto_generated_by = prop.value
89
+ # TODO specific subsetdef, imports
90
+ else:
91
+ property_values.append(
92
+ Annotation(
93
+ predicate=predicate,
94
+ # TODO obographs are limited by ability to specify datatype?
95
+ value=OBOLiteral.string(prop.value)
96
+ if isinstance(prop.value, str)
97
+ else Reference.from_reference(prop.value),
98
+ )
99
+ )
100
+
101
+ for equivalent_node_set in graph.equivalent_node_sets:
102
+ equivalent_reference = Reference.from_reference(equivalent_node_set.node)
103
+ if equivalent_reference in terms:
104
+ for equivalent in equivalent_node_set.equivalents:
105
+ terms[equivalent_reference].append_equivalent_to(
106
+ Reference.from_reference(equivalent)
107
+ )
108
+ elif equivalent_reference in typedefs:
109
+ for equivalent in equivalent_node_set.equivalents:
110
+ typedefs[equivalent_reference].append_equivalent_to(
111
+ Reference.from_reference(equivalent)
112
+ )
113
+ else:
114
+ logger.warning(
115
+ "unknown reference node in equivalent_node_set: %s", equivalent_reference.curie
116
+ )
117
+
118
+ for _domain_range_axiom in graph.domain_range_axioms or []:
119
+ p = Reference.from_reference(_domain_range_axiom.predicate)
120
+ if p not in typedefs:
121
+ continue
122
+ # the OBO Graph model allows for multiple ranges
123
+ # or domains, but OBO only one.
124
+ if _domain_range_axiom.ranges:
125
+ typedefs[p].range = Reference.from_reference(_domain_range_axiom.ranges[0])
126
+ if _domain_range_axiom.domains:
127
+ typedefs[p].domain = Reference.from_reference(_domain_range_axiom.domains[0])
128
+
129
+ for _property_chain_axiom in graph.property_chain_axioms:
130
+ p = Reference.from_reference(_property_chain_axiom.predicate)
131
+ if p not in typedefs or not _property_chain_axiom.chain:
132
+ continue
133
+ # TODO check if its also transitive_over and/or equivalent_to_chain
134
+ typedefs[p].holds_over_chain.append(
135
+ [Reference.from_reference(r) for r in _property_chain_axiom.chain]
136
+ )
137
+
138
+ for _logical_definition_axiom in graph.logical_definition_axioms:
139
+ pass # TODO
140
+
141
+ return make_ad_hoc_ontology(
142
+ _ontology=prefix,
143
+ _name=graph.name,
144
+ terms=list(terms.values()),
145
+ _typedefs=list(typedefs.values()),
146
+ _root_terms=root_terms,
147
+ _property_values=property_values,
148
+ _data_version=graph.version or (graph.meta.version_iri if graph.meta is not None else None),
149
+ _auto_generated_by=auto_generated_by,
150
+ )
151
+
152
+
153
+ #: A mapping between OBO Graph JSON node types and OBO stanza types
154
+ MAPPING: dict[NodeType, StanzaType] = {
155
+ "CLASS": "Term",
156
+ "INDIVIDUAL": "Instance",
157
+ "PROPERTY": "TypeDef",
158
+ }
159
+
160
+
161
+ def from_node(node: StandardizedNode) -> Term | TypeDef:
162
+ """Generate a term from a node."""
163
+ if node.type == "PROPERTY":
164
+ return _from_property(node)
165
+ return _from_term(node)
166
+
167
+
168
+ def _from_term(node: StandardizedNode) -> Term:
169
+ term = Term(
170
+ reference=_get_ref(node),
171
+ type=MAPPING[node.type] if node.type else "Term",
172
+ )
173
+ if node.meta is not None:
174
+ _process_term_meta(node.meta, term)
175
+ return term
176
+
177
+
178
+ def _from_property(node: StandardizedNode) -> TypeDef:
179
+ typedef = TypeDef(
180
+ reference=_get_ref(node),
181
+ is_metadata_tag=node.property_type == "ANNOTATION",
182
+ )
183
+ if node.meta is not None:
184
+ _process_typedef_meta(node.meta, typedef)
185
+ return typedef
186
+
187
+
188
+ def _get_ref(node: StandardizedNode) -> Reference:
189
+ return Reference(
190
+ prefix=node.reference.prefix,
191
+ identifier=node.reference.identifier,
192
+ name=node.label,
193
+ )
194
+
195
+
196
+ def _process_term_meta(meta: StandardizedMeta, term: Term) -> None:
197
+ """Process the ``meta`` object associated with a term node."""
198
+ if meta.definition:
199
+ term.definition = meta.definition.value
200
+ for definition_xref in meta.definition.xrefs or []:
201
+ term.append_definition_xref(definition_xref)
202
+
203
+ if meta.subsets:
204
+ term.subsets.extend(Reference.from_reference(r) for r in meta.subsets)
205
+
206
+ for xref in meta.xrefs or []:
207
+ term.append_xref(xref.reference)
208
+
209
+ for synonym in meta.synonyms or []:
210
+ if s := _from_synonym(synonym):
211
+ term.append_synonym(s)
212
+
213
+ for comment in meta.comments or []:
214
+ term.append_comment(comment)
215
+
216
+ if meta.deprecated:
217
+ term.is_obsolete = True
218
+
219
+ for prop in meta.properties or []:
220
+ match prop.value:
221
+ case Reference():
222
+ term.annotate_object(prop.predicate, prop.value)
223
+ case str():
224
+ # note, OBO Graph format does not allow for annotating data type
225
+ term.annotate_literal(prop.predicate, OBOLiteral.string(prop.value))
226
+
227
+
228
+ REV_SYNONYM_SCOPE: dict[curies.Reference, SynonymScope] = {v: k for k, v in synonym_scopes.items()}
229
+
230
+
231
+ def _from_synonym(syn: StandardizedSynonym) -> Synonym | None:
232
+ return Synonym(
233
+ name=syn.text,
234
+ specificity=REV_SYNONYM_SCOPE[syn.predicate],
235
+ type=Reference.from_reference(syn.type) if syn.type is not None else None,
236
+ provenance=[Reference.from_reference(r) for r in syn.xrefs or []],
237
+ )
238
+
239
+
240
+ def _process_typedef_meta(meta: StandardizedMeta, typedef: TypeDef) -> None:
241
+ """Process the ``meta`` object associated with a property node."""
242
+ # TODO everything else is in here
@@ -0,0 +1,47 @@
1
+ """Testing utilities."""
2
+
3
+ import unittest
4
+ from typing import cast
5
+
6
+ from curies import Reference
7
+ from obographs import StandardizedGraph, StandardizedMeta
8
+
9
+ __all__ = [
10
+ "assert_graph_equal",
11
+ ]
12
+
13
+
14
+ def assert_graph_equal(
15
+ test_case: unittest.TestCase, expected: StandardizedGraph, actual: StandardizedGraph
16
+ ) -> None:
17
+ """Assert two graphs are equal."""
18
+ if expected.meta is not None:
19
+ test_case.assertIsNotNone(actual.meta)
20
+ test_case.assertEqual(
21
+ expected.meta.model_dump(exclude_unset=True, exclude_none=True, exclude_defaults=True),
22
+ cast(StandardizedMeta, actual.meta).model_dump(
23
+ exclude_unset=True, exclude_none=True, exclude_defaults=True
24
+ ),
25
+ )
26
+
27
+ # strip out extra info
28
+ for node in actual.nodes:
29
+ node.reference = Reference.from_reference(node.reference)
30
+
31
+ test_case.assertEqual(
32
+ {node.reference.curie: node for node in expected.nodes},
33
+ {node.reference.curie: node for node in actual.nodes},
34
+ )
35
+ test_case.assertEqual(
36
+ {node.as_str_triple(): node for node in expected.edges},
37
+ {node.as_str_triple(): node for node in actual.edges},
38
+ )
39
+ excludes = {"nodes", "edges", "meta"}
40
+ test_case.assertEqual(
41
+ expected.model_dump(
42
+ exclude_none=True, exclude_unset=True, exclude_defaults=True, exclude=excludes
43
+ ),
44
+ actual.model_dump(
45
+ exclude_none=True, exclude_unset=True, exclude_defaults=True, exclude=excludes
46
+ ),
47
+ )
pyobo/struct/struct.py CHANGED
@@ -22,7 +22,7 @@ import curies
22
22
  import networkx as nx
23
23
  import pandas as pd
24
24
  import ssslm
25
- from curies import ReferenceTuple
25
+ from curies import Converter, ReferenceTuple
26
26
  from curies import vocabulary as _cv
27
27
  from more_click import force_option, verbose_option
28
28
  from tqdm.auto import tqdm
@@ -84,6 +84,7 @@ __all__ = [
84
84
  "Synonym",
85
85
  "SynonymTypeDef",
86
86
  "Term",
87
+ "TypeDef",
87
88
  "abbreviation",
88
89
  "acronym",
89
90
  "make_ad_hoc_ontology",
@@ -91,9 +92,6 @@ __all__ = [
91
92
 
92
93
  logger = logging.getLogger(__name__)
93
94
 
94
- #: This is what happens if no specificity is given
95
- DEFAULT_SPECIFICITY: _cv.SynonymScope = "RELATED"
96
-
97
95
  #: Columns in the SSSOM dataframe
98
96
  SSSOM_DF_COLUMNS = [
99
97
  "subject_id",
@@ -104,7 +102,6 @@ SSSOM_DF_COLUMNS = [
104
102
  "confidence",
105
103
  "contributor",
106
104
  ]
107
- UNSPECIFIED_MATCHING_CURIE = "sempav:UnspecifiedMatching"
108
105
  FORMAT_VERSION = "1.4"
109
106
 
110
107
 
@@ -153,14 +150,14 @@ class Synonym(HasReferencesMixin):
153
150
  def _sort_key(self) -> tuple[str, _cv.SynonymScope, str]:
154
151
  return (
155
152
  self.name,
156
- self.specificity or DEFAULT_SPECIFICITY,
153
+ self.specificity or _cv.DEFAULT_SYNONYM_SCOPE,
157
154
  self.type.curie if self.type else "",
158
155
  )
159
156
 
160
157
  @property
161
158
  def predicate(self) -> curies.NamedReference:
162
159
  """Get the specificity reference."""
163
- return _cv.synonym_scopes[self.specificity or DEFAULT_SPECIFICITY]
160
+ return _cv.synonym_scopes[self.specificity or _cv.DEFAULT_SYNONYM_SCOPE]
164
161
 
165
162
  def to_obo(
166
163
  self,
@@ -189,7 +186,7 @@ class Synonym(HasReferencesMixin):
189
186
  elif self.type is not None:
190
187
  # it's not valid to have a synonym type without a specificity,
191
188
  # so automatically assign one if we'll need it
192
- x = f"{x} {DEFAULT_SPECIFICITY}"
189
+ x = f"{x} {_cv.DEFAULT_SYNONYM_SCOPE}"
193
190
 
194
191
  # Add on the synonym type, if exists
195
192
  if self.type is not None:
@@ -429,9 +426,8 @@ class Term(Stanza):
429
426
  if self.definition:
430
427
  yield f"def: {self._definition_fp()}"
431
428
  # 7
432
- for x in self.get_property_values(v.comment):
433
- if isinstance(x, OBOLiteral):
434
- yield f'comment: "{x.value}"'
429
+ for comment in self.get_comments():
430
+ yield f'comment: "{comment}"'
435
431
  # 8
436
432
  yield from _reference_list_tag("subset", self.subsets, ontology_prefix)
437
433
  # 9
@@ -723,17 +719,11 @@ class Obo:
723
719
  """Iterate over terms in this ontology."""
724
720
  raise NotImplementedError
725
721
 
726
- def get_graph(self):
727
- """Get an OBO Graph object."""
728
- from ..obographs import graph_from_obo
729
-
730
- return graph_from_obo(self)
731
-
732
- def write_obograph(self, path: str | Path) -> None:
722
+ def write_obograph(self, path: str | Path, *, converter: Converter | None = None) -> None:
733
723
  """Write OBO Graph json."""
734
- graph = self.get_graph()
735
- with safe_open(path, read=False) as file:
736
- file.write(graph.model_dump_json(indent=2, exclude_none=True, exclude_unset=True))
724
+ from . import obograph
725
+
726
+ obograph.write_obograph(self, path, converter=converter)
737
727
 
738
728
  @classmethod
739
729
  def cli(cls, *args, default_rewrite: bool = False) -> Any:
@@ -1642,13 +1632,13 @@ class Obo:
1642
1632
  #############
1643
1633
 
1644
1634
  def iterate_edges(
1645
- self, *, use_tqdm: bool = False
1635
+ self, *, use_tqdm: bool = False, include_xrefs: bool = True
1646
1636
  ) -> Iterable[tuple[Stanza, TypeDef, Reference]]:
1647
1637
  """Iterate over triples of terms, relations, and their targets."""
1648
1638
  _warned: set[ReferenceTuple] = set()
1649
1639
  typedefs = self._index_typedefs()
1650
1640
  for stanza in self._iter_stanzas(use_tqdm=use_tqdm, desc=f"[{self.ontology}] edge"):
1651
- for predicate, reference in stanza._iter_edges():
1641
+ for predicate, reference in stanza._iter_edges(include_xrefs=include_xrefs):
1652
1642
  if td := self._get_typedef(stanza, predicate, _warned, typedefs):
1653
1643
  yield stanza, td, reference
1654
1644
 
@@ -231,6 +231,8 @@ class Stanza(Referenced, HasReferencesMixin):
231
231
  ) -> None:
232
232
  self._axioms[_property_resolve(p, o)].append(annotation)
233
233
 
234
+ # TODO check different usages of this
235
+
234
236
  def append_equivalent(
235
237
  self,
236
238
  reference: ReferenceHint,
@@ -242,6 +244,15 @@ class Stanza(Referenced, HasReferencesMixin):
242
244
  stanza_type_to_eq_prop[self.type], reference, annotations=annotations
243
245
  )
244
246
 
247
+ def append_equivalent_to(
248
+ self, reference: ReferenceHint, *, annotations: Iterable[Annotation] | None = None
249
+ ) -> Self:
250
+ """Append to the "equivalent to" list."""
251
+ reference = _ensure_ref(reference)
252
+ self.equivalent_to.append(reference)
253
+ self._extend_annotations(stanza_type_to_eq_prop[self.type], reference, annotations)
254
+ return self
255
+
245
256
  def append_xref(
246
257
  self,
247
258
  reference: ReferenceHint,
@@ -317,15 +328,6 @@ class Stanza(Referenced, HasReferencesMixin):
317
328
  self.union_of.append(_ensure_ref(reference))
318
329
  return self
319
330
 
320
- def append_equivalent_to(
321
- self, reference: ReferenceHint, *, annotations: Iterable[Annotation] | None = None
322
- ) -> Self:
323
- """Append to the "equivalent to" list."""
324
- reference = _ensure_ref(reference)
325
- self.equivalent_to.append(reference)
326
- self._extend_annotations(stanza_type_to_eq_prop[self.type], reference, annotations)
327
- return self
328
-
329
331
  def _iterate_intersection_of_obo(self, *, ontology_prefix: str) -> Iterable[str]:
330
332
  for element in sorted(self.intersection_of, key=self._intersection_of_key):
331
333
  match element:
@@ -679,14 +681,18 @@ class Stanza(Referenced, HasReferencesMixin):
679
681
  """Add a comment property."""
680
682
  return self.annotate_string(v.comment, value, annotations=annotations, language=language)
681
683
 
684
+ def get_comments(self) -> list[str]:
685
+ """Get all comment strings."""
686
+ return [x.value for x in self.get_property_values(v.comment) if isinstance(x, OBOLiteral)]
687
+
682
688
  @property
683
689
  def alt_ids(self) -> Sequence[Reference]:
684
690
  """Get alternative terms."""
685
691
  return tuple(self.get_property_objects(v.alternative_term))
686
692
 
687
- def get_edges(self) -> list[tuple[Reference, Reference]]:
693
+ def get_edges(self, *, include_xrefs: bool = True) -> list[tuple[Reference, Reference]]:
688
694
  """Get edges."""
689
- return list(self._iter_edges())
695
+ return list(self._iter_edges(include_xrefs=include_xrefs))
690
696
 
691
697
  def _iter_parents(self) -> Iterable[tuple[Reference, Reference]]:
692
698
  parent_prop = stanza_type_to_prop[self.type]
@@ -702,7 +708,7 @@ class Stanza(Referenced, HasReferencesMixin):
702
708
  case (predicate, target):
703
709
  yield predicate, target
704
710
 
705
- def _iter_edges(self) -> Iterable[tuple[Reference, Reference]]:
711
+ def _iter_edges(self, *, include_xrefs: bool = True) -> Iterable[tuple[Reference, Reference]]:
706
712
  # The following are "object" properties, meaning
707
713
  # they're part of the definition of the object
708
714
  yield from self.iterate_relations()
@@ -715,8 +721,10 @@ class Stanza(Referenced, HasReferencesMixin):
715
721
  for subset in self.subsets:
716
722
  yield v.in_subset, subset
717
723
  yield from self.iterate_object_properties()
718
- for xref_reference in self.xrefs:
719
- yield v.has_dbxref, xref_reference
724
+
725
+ if include_xrefs:
726
+ for xref_reference in self.xrefs:
727
+ yield v.has_dbxref, xref_reference
720
728
 
721
729
  # TODO disjoint_from
722
730
 
pyobo/struct/typedef.py CHANGED
@@ -294,6 +294,10 @@ has_end_date = TypeDef(
294
294
  has_title = TypeDef(reference=v.has_title, is_metadata_tag=True)
295
295
  has_license = TypeDef(reference=v.has_license, is_metadata_tag=True)
296
296
  has_description = TypeDef(reference=v.has_description, is_metadata_tag=True)
297
+ obo_autogenerated_by = TypeDef(reference=v.obo_autogenerated_by, is_metadata_tag=True)
298
+ obo_has_format_version = TypeDef(reference=v.obo_has_format_version, is_metadata_tag=True)
299
+ obo_is_metadata_tag = TypeDef(reference=v.obo_is_metadata_tag, is_metadata_tag=True)
300
+ obo_has_id = TypeDef(reference=v.obo_has_id, is_metadata_tag=True)
297
301
 
298
302
  in_subset = TypeDef(reference=v.in_subset, is_metadata_tag=True)
299
303
  has_term_editor = TypeDef(reference=v.has_term_editor, is_metadata_tag=True)
@@ -47,6 +47,13 @@ has_dbxref = _c(_v.has_dbxref)
47
47
 
48
48
  in_subset = _c(_v.obo_in_subset)
49
49
  has_obo_namespace = _c(_v.obo_has_namespace)
50
+ obo_is_metadata_tag = Reference(
51
+ prefix="oboinowl", identifier="is_metadata_tag", name="is metadata tag"
52
+ )
53
+ obo_has_id = Reference(prefix="oboinowl", identifier="id", name="has ID")
54
+ obo_has_format_version = Reference(
55
+ prefix="oboinowl", identifier="hasOBOFormatVersion", name="has OBO format version"
56
+ )
50
57
  obo_autogenerated_by = _c(_v.obo_autogenerated_by)
51
58
  obo_creation_date = _c(_v.obo_creation_date)
52
59
 
pyobo/version.py CHANGED
@@ -12,7 +12,7 @@ __all__ = [
12
12
  "get_version",
13
13
  ]
14
14
 
15
- VERSION = "0.12.2"
15
+ VERSION = "0.12.3"
16
16
 
17
17
 
18
18
  def get_git_hash() -> str:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyobo
3
- Version: 0.12.2
3
+ Version: 0.12.3
4
4
  Summary: A python package for handling and generating OBO
5
5
  Keywords: snekpack,cookiecutter,ontologies,biomedical ontologies,life sciences,natural sciences,bioinformatics,cheminformatics,Open Biomedical Ontologies,OBO
6
6
  Author: Charles Tapley Hoyt
@@ -45,7 +45,7 @@ Requires-Dist: zenodo-client>=0.3.6
45
45
  Requires-Dist: class-resolver>=0.6.0
46
46
  Requires-Dist: psycopg2-binary
47
47
  Requires-Dist: pydantic>=2.0
48
- Requires-Dist: curies>=0.10.13
48
+ Requires-Dist: curies>=0.10.17
49
49
  Requires-Dist: curies-processing>=0.1.0
50
50
  Requires-Dist: python-dateutil
51
51
  Requires-Dist: networkx>=3.4
@@ -56,6 +56,7 @@ Requires-Dist: clinicaltrials-downloader>=0.0.2
56
56
  Requires-Dist: nih-reporter-downloader>=0.0.1
57
57
  Requires-Dist: typing-extensions
58
58
  Requires-Dist: rdflib
59
+ Requires-Dist: obographs>=0.0.8
59
60
  Requires-Dist: ssslm[gilda] ; extra == 'gilda'
60
61
  Requires-Dist: ssslm[gilda-slim] ; extra == 'gilda-slim'
61
62
  Maintainer: Charles Tapley Hoyt
@@ -1,5 +1,5 @@
1
1
  pyobo/.DS_Store,sha256=00b8c741cd5b001c03c1a582f55bfbcda0ad16f0e55019d64f93241b74991980,8196
2
- pyobo/__init__.py,sha256=0d90185e6e3aa041ccc27c68226c45e456e39369328e3db17706d65b52015819,3439
2
+ pyobo/__init__.py,sha256=ae0b55a37ac88a8423fd32252683d3447102bcce078fe4c2a418f78196e9d648,3434
3
3
  pyobo/__main__.py,sha256=70e610d8e10bc45fbd4fa9ee67dc672d2bbd6cb1e4e9e8a7aec4a8cfb11c0fd3,83
4
4
  pyobo/api/__init__.py,sha256=259870a4519a6baa5df1180378837e67c688e8ecbe46e9a3d4a90e6435c79e1d,2955
5
5
  pyobo/api/alts.py,sha256=478b3162574616f2827bd73107f80f5dfdaf5971eaf6c6813109109dba89e522,3032
@@ -21,10 +21,10 @@ pyobo/cli/database_utils.py,sha256=8d0eea4a0fa8664f90f910b5db536451ba9778d8342bc
21
21
  pyobo/cli/lookup.py,sha256=1b11bbe771979c345ff8df494562919900b95e237c7c437997595ee42de31c76,9163
22
22
  pyobo/cli/utils.py,sha256=9e6b57b311b44d61088e321efa387f6aacebd3d6d337bf8d1c589fb871b3304d,1738
23
23
  pyobo/constants.py,sha256=c1ffa4f12c1ddee556adf728ef4ac51da44f228fe6fca9b58b9ab8f263acc87b,5112
24
- pyobo/getters.py,sha256=0d9a129a46213f3657cb80d7a70a73aa24567644a1d9090c57f09c67cb86921a,17375
24
+ pyobo/getters.py,sha256=0bbd39aeba8b4511230ebadd209b2c9c64b117f81d80e1a1327230a068a13eeb,17618
25
25
  pyobo/gilda_utils.py,sha256=b9384002b00b48dcc98be86b47d954bed41c8b9548c380aaab62fa9ad929d0aa,1990
26
- pyobo/identifier_utils/__init__.py,sha256=ef7bbb0ffb088daa04ee79446bafc8a5ee1d404e347e637361b835879755dea2,753
27
- pyobo/identifier_utils/api.py,sha256=c308dc9f48753d14084d19362f08003f822c2e495fe0badd9b9d3bc176fbaba1,9215
26
+ pyobo/identifier_utils/__init__.py,sha256=8921c06613b0a9666662939fa5734bb8aa2e4988fb652562697ec1179b93f2ca,793
27
+ pyobo/identifier_utils/api.py,sha256=b65d99d4b8d223341d7d3bd4b7bc2e41ce7b52e218b0779b90bacde6a9beaa61,9247
28
28
  pyobo/identifier_utils/relations/__init__.py,sha256=2961f492b8530a678a9e010887b5530c3de1cc2df8f294e210a18dbb748d01db,159
29
29
  pyobo/identifier_utils/relations/api.py,sha256=c625bca0f09379ba7ef544d05aaf4b998ee9798945a90f3b98b6d763ef9d36df,5764
30
30
  pyobo/identifier_utils/relations/data.json,sha256=88b6ce5fb632faa389b512b68f1b73acdd54b552a1aaa8043430eb5e0020a0bc,113169
@@ -35,11 +35,8 @@ pyobo/mocks.py,sha256=8f9e392bd3ff0cfb0306e6070eb8724cb8e694fa0d951744b5c4652e15
35
35
  pyobo/ner/__init__.py,sha256=0199b704f1235184d521069034823c3d9960ff6756205c299649b87a4bbd4041,153
36
36
  pyobo/ner/api.py,sha256=b34309833eac8f5dea881d531323bf682f35d377e09d807066ba1183282964dc,2167
37
37
  pyobo/ner/normalizer.py,sha256=4e90d93801877f72f2fab8069db986e79cc749533a068a8b07a9d7c9e37cb9c2,954
38
- pyobo/obographs.py,sha256=8b4258792727430b6c4f15833116313905abb83511f1fee565091c400323f49d,4345
39
38
  pyobo/plugins.py,sha256=c04afe369c99ed9eae12bd2e18334e7972ce199a2419b166a377becf63cd2893,1232
40
39
  pyobo/py.typed,sha256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855,0
41
- pyobo/reader.py,sha256=6fc2522a89772b718eaa6278e2abc7d5ca536378b537992b34bfe12bcfd10d72,52246
42
- pyobo/reader_utils.py,sha256=5324154d08576e167d7c28b3660dbaa394e67878acf7ea9930abd0170201460a,4423
43
40
  pyobo/resource_utils.py,sha256=6e5a1229b1df30bcf4841f009213247cb386ab0e85c8ef02114e8b360d0f54c9,4406
44
41
  pyobo/resources/__init__.py,sha256=43d9e293b1e0a4808238dec610aa5bc37cfd64833b345270a063697a9927da70,38
45
42
  pyobo/resources/ncbitaxon.py,sha256=92484774b0f45247cb4090b34e3851a5c175dde2da03e472d891c9953968116b,1979
@@ -49,7 +46,7 @@ pyobo/resources/ro.tsv,sha256=62f9412cf00acb6c38221798ccef68c75620e9690774c57331
49
46
  pyobo/resources/so.py,sha256=4bebe643b2fc009134f057c6543209a8d40d68b3d49ae27a1c2e45e2158732b0,1466
50
47
  pyobo/resources/so.tsv,sha256=50964a153100bff5eccd861bba7e167fa6f88e8bc38d229cd51591411713cc3c,82068
51
48
  pyobo/sources/README.md,sha256=0296f0a48da16d8422c3837a284fd5000a5f3a64d01e47936eb34413121b5f82,901
52
- pyobo/sources/__init__.py,sha256=94db6754ef36ea969a347c2ae38ff9eddb44dbe177ce06d9f93e5432592bc404,4630
49
+ pyobo/sources/__init__.py,sha256=fb9f5ba3c87a3ea2f2d28144659897c99de0ad824e4ed2382035a8814184313c,4683
53
50
  pyobo/sources/agrovoc.py,sha256=489b1b27b2adc5d2541bd4629a66f609f2dfce92bd78eccfd30c79f608feeace,787
54
51
  pyobo/sources/antibodyregistry.py,sha256=3726d4ccf1286e7e73aebd6252f0bc67d72ea83103335bb4eec8d5d540037664,3353
55
52
  pyobo/sources/bigg/__init__.py,sha256=e292beef5071d08bfddcfaa665e714297f4b71aa5b5bdc26ef304df6f85ba582,349
@@ -74,7 +71,7 @@ pyobo/sources/cvx.py,sha256=97d0acbae76bf54ca8d0f35c8c94db346eb610e51cac05688a3d
74
71
  pyobo/sources/depmap.py,sha256=7f05bfd54901e49b6c797c137dbd017e32ef626fb17feb17c1feb368f2a4960f,3585
75
72
  pyobo/sources/dictybase_gene.py,sha256=78bbde62732e26cd92c2d287ca3e34b678e9f058f2d72157a0f0e8b9bd5d6164,2672
76
73
  pyobo/sources/drugbank/__init__.py,sha256=880b2dbd9419d3525c25e0089b606727ddb7501be2f1a490e2d1158440e8540a,178
77
- pyobo/sources/drugbank/drugbank.py,sha256=eb2fc65b2d43ac54c0c81fefb0701b1326411027cf3cfb5eac7534df925cb33c,10899
74
+ pyobo/sources/drugbank/drugbank.py,sha256=5a216ccbfe883599207ad99b518904d6f3e983974bc2305fcf7715263228d705,10914
78
75
  pyobo/sources/drugbank/drugbank_salt.py,sha256=69b565fe280b7a698cc3850b8b7fc8b5381f09aab7bb26e3aa7b13f5187b0b59,1646
79
76
  pyobo/sources/drugcentral.py,sha256=9fb9bbcbaf0b3c494163dde2e627a6695366ca1c74cb7293efd2419871a610a1,4047
80
77
  pyobo/sources/expasy.py,sha256=25f116d229b5c25858db82add7a037e8c5b405e40dbfd76d3ff67a1f581c8755,11053
@@ -90,7 +87,7 @@ pyobo/sources/go.py,sha256=cd72c37dca9b894eb43371540adab37cfcd8a07952be4533000f1
90
87
  pyobo/sources/gtdb.py,sha256=ab420486568c8ad1d6a39200cb6979f2e5cc2d67a40addeb2303a60ecb031138,5221
91
88
  pyobo/sources/gwascentral/__init__.py,sha256=55d1c8801551fb7e81ee02ee851e175795179ff120359d3e8b583d36384e8d8d,231
92
89
  pyobo/sources/gwascentral/gwascentral_phenotype.py,sha256=4af302177b18a9cdc5e6735709fefa033221353ebdf191c79d3a4ed0819fb7ca,1788
93
- pyobo/sources/gwascentral/gwascentral_study.py,sha256=bddb3b20e2374cc3ff14601aba36c17466897d46f1d086bf75ecf62992263bd9,2657
90
+ pyobo/sources/gwascentral/gwascentral_study.py,sha256=7f30e246e594f38d3ce60725cee58d2dbc4312c21d572b2a5d270c53405d5e73,2672
94
91
  pyobo/sources/hgnc/__init__.py,sha256=d5084cec674febf03108ccda073da4dd244b9034ce912da15213cc2c44d21963,157
95
92
  pyobo/sources/hgnc/hgnc.py,sha256=f05121570f4e4b06f4d70bbf6950363349a726de22c6f2ed5e3e43411591bf95,16377
96
93
  pyobo/sources/hgnc/hgncgenefamily.py,sha256=e3e8d0b750d59a7da3d0ac2b100e248e8dad51af54c045405a12704e36db20cd,3710
@@ -98,6 +95,7 @@ pyobo/sources/icd/__init__.py,sha256=0eb65597be8ff1eb2c278b6564f71ab8556b5d59082
98
95
  pyobo/sources/icd/icd10.py,sha256=61ab55ce0af6dbd27f59e25c6b8150007a96af1edcecde1f1db85bd5c4354de5,2587
99
96
  pyobo/sources/icd/icd11.py,sha256=5b6e59f8028cfbd41f860151d1164514be2653a50078c0fc8748c20b815ee11b,4867
100
97
  pyobo/sources/icd/icd_utils.py,sha256=8fbc63228bd61b4f86c47eee5d6ad76433b52d7132a3fe0275680f4874c85c96,4525
98
+ pyobo/sources/intact.py,sha256=7e78d9e164acadf67b6df963a4c58116d4861a4e959aef0fb1d7d1f6c6f15cfe,2497
101
99
  pyobo/sources/interpro.py,sha256=d6d99771293946b8228fbd35183aa845b77f7c46af1e5f3f03a6887f92ba10b1,4809
102
100
  pyobo/sources/itis.py,sha256=6b1d54c40ece2a97176c497aaa3113fbf78ea32845e918fc76de4a1bf254dbbf,2876
103
101
  pyobo/sources/kegg/__init__.py,sha256=8553f4b6ec15a6234c8a416ffdb34faf3b98bfe1c0d7f6cf742bcdc7e7e6e458,219
@@ -169,19 +167,26 @@ pyobo/ssg/base.html,sha256=fef95d5026be80bd984cd63a1a002ec4d4f74e06840f9f39bc5fe
169
167
  pyobo/ssg/index.html,sha256=da62c16a198f7ad2468599c5d7e4da4d7b81e02a18a25a59da741a579746e676,4346
170
168
  pyobo/ssg/term.html,sha256=b522c82774980d37ad2bd8361280cacaee1a1dc855a351145e4fda62119e38aa,3869
171
169
  pyobo/ssg/typedef.html,sha256=2ab76acc1eb18edebcf5b1b7dc3dba00bfb5d49aef36e124a3134d23e106f938,2038
172
- pyobo/struct/__init__.py,sha256=fb813dfa7de27f195c07cd5311de78403b03dfbf0a183995c8fb448033ace311,1444
170
+ pyobo/struct/__init__.py,sha256=653697fa0c263df189df3550d1e79772c8c4f20e6886a8fffaccc676fbbb94d2,1474
173
171
  pyobo/struct/functional/__init__.py,sha256=d536edb7fe86a1aad19607df3dea62b49dd0b4bb2b30f31b8431a842700a499e,32
174
172
  pyobo/struct/functional/dsl.py,sha256=780b4e5616b8dc823cee610945a95ffa109aa43287992dd4dd51511c461f96fb,101183
175
173
  pyobo/struct/functional/macros.py,sha256=cc654f131fa685d4afc87d8c7b5e8565da1b789dd5d73045a77b3e033a8ced52,13785
176
174
  pyobo/struct/functional/obo_to_functional.py,sha256=785c46fdb00dc45f3903f67ad24ae4fcb6d187ce48208373fc9d42833a85f6b8,13273
177
- pyobo/struct/functional/ontology.py,sha256=bc610a206c5f502cc658cbf7dcaa9caeb112a596ab1cb07fcbd571c8a6da2894,9331
175
+ pyobo/struct/functional/ontology.py,sha256=c261c91ed950d3a6564ffcbda379fb228ffd28f0d873cb5f9c1a237a4e744328,9338
178
176
  pyobo/struct/functional/utils.py,sha256=73e5c6d9227b0a162dcfb294dcad05f93ea870c8d87af7a2d16c6591f9249ad1,3487
177
+ pyobo/struct/obo/__init__.py,sha256=c49005278cae796050bf706bb53b871c9ec0ccea8280eb8780a638450a1cb16d,157
178
+ pyobo/struct/obo/reader.py,sha256=6dd8c153e8210c8da1cceed08a4c4bf4addaa3355529b2d34d03960d7c446916,52261
179
+ pyobo/struct/obo/reader_utils.py,sha256=5324154d08576e167d7c28b3660dbaa394e67878acf7ea9930abd0170201460a,4423
180
+ pyobo/struct/obograph/__init__.py,sha256=078acd3fd3824e73179bc629434adaaf5b309f8188c3d6f88100fe215baa1f2c,452
181
+ pyobo/struct/obograph/export.py,sha256=a4630989db4171855683d76a169ef6a554dad3c3944401fdb0b4ea37cdef93da,9747
182
+ pyobo/struct/obograph/reader.py,sha256=dbae3255e0fc6b78c6c7d11a194655c456d243fa7043fe9c915c3d4bcc2225f3,8525
183
+ pyobo/struct/obograph/utils.py,sha256=8ded244a40b6e0c53da56447ab5fcaf89e635a18d611263a348dd3a59aaf67f4,1516
179
184
  pyobo/struct/reference.py,sha256=4fc7d3b665cd18c8dfbbb2b8b49de4bc30a8e101d14ff26bf5f88e9c562bc2d3,11735
180
- pyobo/struct/struct.py,sha256=29b77204d903a948aff74f93aa043e5421cc932c22a893e70dbfd3f27b911fb7,89480
181
- pyobo/struct/struct_utils.py,sha256=7b8bfd7a322f34cf1436b83c8eab983944651ba467923045bf61ecc245800d2c,39164
182
- pyobo/struct/typedef.py,sha256=fd94429e28efcdf7bbeba4b1729fa66af5f64c34e49437d82e4b3e5a457d064d,12099
185
+ pyobo/struct/struct.py,sha256=fd60053e55c16c3ca2222852ad0f8bd6de20ac8151e096340d271086d6fa9099,89172
186
+ pyobo/struct/struct_utils.py,sha256=a4fa0ee672bc626095fbc0df66f0b948ad35ff39b55971b0145cd6bd80e640fb,39511
187
+ pyobo/struct/typedef.py,sha256=8817a49f6426a9adc9ed8462d5db3d3324780b2ad3874d8781a1648e64fe9ce5,12429
183
188
  pyobo/struct/utils.py,sha256=ce4a4e138d894087e4374adce6a34434ad375482a691fff9eed1e88cc24aef56,906
184
- pyobo/struct/vocabulary.py,sha256=56e0f6770cf7da2d6f1221e3fc8261f1c07dc8358a1f3dfb487894a25b1ed133,4335
189
+ pyobo/struct/vocabulary.py,sha256=1d853a86c2d0e34dd6bd64e68d1323b8ac51d3a4b2932a6bde4fc8c4b52104e9,4645
185
190
  pyobo/utils/__init__.py,sha256=08035263cbc6abfeaff2b5a159121d9e4f96a392c0d91f568e0d67a9b5aa2cec,17
186
191
  pyobo/utils/cache.py,sha256=136ccd03b82afd534699a36bad129e5f3e73aba5c3184fb93d5a24af30d99227,3098
187
192
  pyobo/utils/io.py,sha256=fa0cb5a8633a6c9fb95eb2f74e08fbf69acc4fc229b89c18dd233921b80378a9,5100
@@ -189,9 +194,9 @@ pyobo/utils/iter.py,sha256=ad845b6da1491f131a134c94fab419a026a0608aed7afd3db98d2
189
194
  pyobo/utils/misc.py,sha256=99d1f6e88b48d3f0cdbd7fff8a908556bf949278fcf0ef639e5cc8a421d0f4db,2684
190
195
  pyobo/utils/ndex_utils.py,sha256=128902592d345ab93fe32f2575e42e53269a0bac8dcc18370da81497e2767336,2326
191
196
  pyobo/utils/path.py,sha256=cc37f10de8e0ef90a6063cc2b1c5d1b0993e41649536f04bfddc892d61a3bc4f,3398
192
- pyobo/version.py,sha256=d76710b61a3b9c38c2f582b5788dc0c462786829754363c869633e386dccebd6,926
193
- pyobo-0.12.2.dist-info/licenses/LICENSE,sha256=41c80964a1b1956e41c013670812fc5592d5b51bd7b3cd4287d949450488a498,1076
194
- pyobo-0.12.2.dist-info/WHEEL,sha256=ec89e25a684ec3ad8fb2a9be806e47666a27f7dcdcf9b55bff3f1d3ed5e60e0a,78
195
- pyobo-0.12.2.dist-info/entry_points.txt,sha256=00d833beec05ffdff58a90a8c49b5b04ce80e22d8c92ddfd80c3f340eea1bc6b,42
196
- pyobo-0.12.2.dist-info/METADATA,sha256=37f00c716dd218308afda6c1d5543267fae9c0dab78c5e17879388a6491b9a36,21626
197
- pyobo-0.12.2.dist-info/RECORD,,
197
+ pyobo/version.py,sha256=058efa6160d82b428d446de28699dffcaf1ff92245abfe4d7849ad166827adae,926
198
+ pyobo-0.12.3.dist-info/licenses/LICENSE,sha256=41c80964a1b1956e41c013670812fc5592d5b51bd7b3cd4287d949450488a498,1076
199
+ pyobo-0.12.3.dist-info/WHEEL,sha256=ec89e25a684ec3ad8fb2a9be806e47666a27f7dcdcf9b55bff3f1d3ed5e60e0a,78
200
+ pyobo-0.12.3.dist-info/entry_points.txt,sha256=00d833beec05ffdff58a90a8c49b5b04ce80e22d8c92ddfd80c3f340eea1bc6b,42
201
+ pyobo-0.12.3.dist-info/METADATA,sha256=42859807092f3325348ae45ae2592887162b287a77d360b0d7220527e0ff4a51,21658
202
+ pyobo-0.12.3.dist-info/RECORD,,