mandos.model.pubchem_data   F
last analyzed

Complexity

Total Complexity 143

Size/Duplication

Total Lines 1031
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 824
dl 0
loc 1031
rs 1.7759
c 0
b 0
f 0
wmc 143

98 Methods

Rating   Name   Duplication   Size   Complexity  
A PharmacologyAndBiochemistry._whoami() 0 3 1
A NamesAndIdentifiers._whoami() 0 3 1
A ChemicalAndPhysicalProperties.charge() 0 3 1
A ChemicalAndPhysicalProperties.xlogp3() 0 3 1
A PharmacologyAndBiochemistry.moa_summary_drugbank_links() 0 3 1
A BiomolecularInteractionsAndPathways.drug_gene_interactions() 0 18 1
A PharmacologyAndBiochemistry.moa_summary_hsdb_text() 0 3 1
B Literature._get_cooccurrences() 0 41 3
A PharmacologyAndBiochemistry._get_moa_links() 0 16 1
A ChemicalAndPhysicalProperties.mol_weight() 0 6 2
A ChemicalAndPhysicalProperties.complexity_rating() 0 3 1
A BiomolecularInteractionsAndPathways.drugbank_interactions() 0 19 1
A ChemicalAndPhysicalProperties._whoami() 0 3 1
A PubchemDataView._toc() 0 3 1
F ChemicalAndPhysicalProperties._extract_value_and_unit() 0 27 14
A RelatedRecords._whoami() 0 3 1
A Classification.chembl_tree() 0 3 1
A PubchemData.drug_and_medication_information() 0 3 1
A PharmacologyAndBiochemistry._get_moa_text() 0 11 1
A PharmacologyAndBiochemistry.atc() 0 14 1
A BiomolecularInteractionsAndPathways._whoami() 0 3 1
A PubchemData.literature() 0 3 1
A Classification.g2p_tree() 0 3 1
A Classification.mesh_tree() 0 3 1
C Literature.depositor_pubmed_articles() 0 75 10
A Classification._whoami() 0 3 1
A Classification.dea() 0 3 1
A PubchemData.safety_and_hazards() 0 3 1
A PubchemData.chemical_and_physical_properties() 0 3 1
A ChemicalAndPhysicalProperties.single_property() 0 3 1
A PharmacologyAndBiochemistry.summary_drugbank_text() 0 12 1
A Literature.gene_cooccurrences() 0 3 1
A PubchemDataView.cid() 0 9 2
A ChemicalAndPhysicalProperties.tpsa() 0 6 2
A PubchemMiniDataView._whoami() 0 3 1
A SafetyAndHazards._whoami() 0 3 1
A PubchemDataView.__init__() 0 2 1
A PharmacologyAndBiochemistry.moa_summary_drugbank_text() 0 3 1
A PharmacologyAndBiochemistry.summary_ncit_links() 0 18 1
A PubchemData.classification() 0 3 1
A DrugAndMedicationInformation.mini() 0 3 1
A PubchemData.title_and_summary() 0 3 1
A Patents.associated_disorders_and_diseases() 0 9 1
A Patents._whoami() 0 3 1
A NamesAndIdentifiers.descriptor() 0 16 1
A Literature._whoami() 0 3 1
A PubchemDataView._tables() 0 3 1
A DrugAndMedicationInformation.indication_summary_livertox() 0 12 1
A DrugAndMedicationInformation.dea_schedule() 0 15 1
A DrugAndMedicationInformation.hsdb_uses() 0 13 2
A PubchemDataView._classifications() 0 3 1
A Classification.cpdat_tree() 0 3 1
A PubchemData.pharmacology_and_biochemistry() 0 3 1
A DrugAndMedicationInformation.indication_summary_drugbank() 0 12 1
A DrugAndMedicationInformation.classes() 0 11 1
A BiologicalTestResults.bioactivity() 0 15 1
A AssociatedDisordersAndDiseases.associated_disorders_and_diseases() 0 9 1
A PubchemData.biomolecular_interactions_and_pathways() 0 3 1
A PharmacologyAndBiochemistry.mesh() 0 9 1
A NamesAndIdentifiers.modify_date() 0 13 1
A BiomolecularInteractionsAndPathways.drugbank_legal_groups() 0 9 1
A PubchemData.parent_or_self() 0 4 2
A ChemicalAndPhysicalProperties._extract_kvr() 0 6 3
A PubchemDataView._nav() 0 3 1
A NamesAndIdentifiers.molecular_formula() 0 14 1
A PubchemData.toxicity() 0 3 1
A PubchemData.related_records() 0 3 1
A Toxicity._whoami() 0 3 1
A AssociatedDisordersAndDiseases._whoami() 0 3 1
B ChemicalAndPhysicalProperties.computed() 0 21 6
A Literature.chemical_cooccurrences() 0 3 1
A TitleAndSummary.safety() 0 12 1
A Classification.chebi_tree() 0 3 1
A BiologicalTestResults._whoami() 0 3 1
A Classification.chemid() 0 3 1
A PubchemData.associated_disorders_and_diseases() 0 3 1
A RelatedRecords.parent() 0 13 2
A NamesAndIdentifiers.inchikey() 0 3 1
A PubchemDataView._refs() 0 3 1
A DrugAndMedicationInformation.dea_class() 0 11 1
A PubchemData.name() 0 3 1
A PubchemMiniDataView._mini() 0 3 1
A DrugAndMedicationInformation.clinical_trials() 0 17 2
A SafetyAndHazards.ghs_codes() 0 19 1
A PubchemDataView._has_ref() 0 2 2
A Classification.atc_tree() 0 3 1
A PharmacologyAndBiochemistry.summary_ncit_text() 0 13 1
A NamesAndIdentifiers.create_date() 0 13 1
A PharmacologyAndBiochemistry.moa_summary_hsdb_links() 0 3 1
A BiomolecularInteractionsAndPathways.compound_gene_interactions() 0 17 1
B Literature._guess_neighbor() 0 11 6
A NamesAndIdentifiers.inchi() 0 3 1
A Toxicity.acute_effects() 0 14 1
A PharmacologyAndBiochemistry.biochem_reactions() 0 4 1
A PubchemDataView._links() 0 3 1
A Literature.disease_cooccurrences() 0 3 1
A PubchemDataView.to_json() 0 12 2
A BiomolecularInteractionsAndPathways.drugbank_ddis() 0 15 1

How to fix   Complexity   

Complexity

Complex classes like mandos.model.pubchem_data often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
"""
0 ignored issues
show
coding-style introduced by
Too many lines in module (1031/1000)
Loading history...
2
PubChem data views and processors.
3
"""
4
from __future__ import annotations
5
6
import abc
7
import logging
8
import re
9
from datetime import date, datetime
10
from typing import Mapping, Optional, Sequence, Union, FrozenSet, Any, Dict
11
from typing import Tuple as Tup
12
from urllib.parse import unquote as url_unescape
13
14
import orjson
0 ignored issues
show
introduced by
Unable to import 'orjson'
Loading history...
15
from pocketutils.core.exceptions import MultipleMatchesError
0 ignored issues
show
introduced by
Unable to import 'pocketutils.core.exceptions'
Loading history...
16
from pocketutils.core.dot_dict import NestedDotDict
0 ignored issues
show
introduced by
Unable to import 'pocketutils.core.dot_dict'
Loading history...
17
from pocketutils.tools.common_tools import CommonTools
0 ignored issues
show
introduced by
Unable to import 'pocketutils.tools.common_tools'
Loading history...
18
from pocketutils.tools.string_tools import StringTools
0 ignored issues
show
introduced by
Unable to import 'pocketutils.tools.string_tools'
Loading history...
19
20
from mandos.model.query_utils import JsonNavigator, Fns, FilterFn
21
from mandos.model.pubchem_support import (
22
    ComputedProperty,
23
    Codes,
24
    CoOccurrenceType,
25
    ClinicalTrial,
26
    GhsCode,
27
    AssociatedDisorder,
28
    AtcCode,
29
    DrugbankInteraction,
30
    DrugbankDdi,
31
    PubmedEntry,
32
    Publication,
33
    CoOccurrence,
34
    DrugGeneInteraction,
35
    CompoundGeneInteraction,
36
    Bioactivity,
37
)
38
39
logger = logging.getLogger("mandos")
40
41
42
class Misc:
0 ignored issues
show
introduced by
Missing class docstring
Loading history...
43
    empty_frozenset = frozenset([])
44
45
46
class Patterns:
0 ignored issues
show
introduced by
Missing class docstring
Loading history...
47
    ghs_code = re.compile(r"((?:H\d+)(?:\+H\d+)*)")
48
    ghs_code_singles = re.compile(r"(H\d+)")
49
    pubchem_compound_url = re.compile(r"^https:\/\/pubchem\.ncbi\.nlm\.nih\.gov\/compound\/(.+)$")
50
    atc_codes = re.compile(r"([A-Z])([0-9]{2})?([A-Z])?([A-Z])?([A-Z])?")
51
    mesh_codes = re.compile(r"[A-Z]")
52
53
54
class PubchemDataView(metaclass=abc.ABCMeta):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
55
    """"""
56
57
    def __init__(self, data: NestedDotDict):
58
        self._data = data
59
60
    def to_json(self) -> str:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
61
        def default(obj: Any) -> Any:
0 ignored issues
show
Unused Code introduced by
Either all return statements in a function should return an expression, or none of them should.
Loading history...
62
            if isinstance(obj, NestedDotDict):
63
                # noinspection PyProtectedMember
64
                return dict(obj._x)
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like _x was declared protected and should not be accessed from this context.

Prefixing a member variable _ is usually regarded as the equivalent of declaring it with protected visibility that exists in other languages. Consequentially, such a member should only be accessed from the same class or a child class:

class MyParent:
    def __init__(self):
        self._x = 1;
        self.y = 2;

class MyChild(MyParent):
    def some_method(self):
        return self._x    # Ok, since accessed from a child class

class AnotherClass:
    def some_method(self, instance_of_my_child):
        return instance_of_my_child._x   # Would be flagged as AnotherClass is not
                                         # a child class of MyParent
Loading history...
65
66
        # noinspection PyProtectedMember
67
        data = dict(self._data._x)
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like _x was declared protected and should not be accessed from this context.

Prefixing a member variable _ is usually regarded as the equivalent of declaring it with protected visibility that exists in other languages. Consequentially, such a member should only be accessed from the same class or a child class:

class MyParent:
    def __init__(self):
        self._x = 1;
        self.y = 2;

class MyChild(MyParent):
    def some_method(self):
        return self._x    # Ok, since accessed from a child class

class AnotherClass:
    def some_method(self, instance_of_my_child):
        return instance_of_my_child._x   # Would be flagged as AnotherClass is not
                                         # a child class of MyParent
Loading history...
68
        encoded = orjson.dumps(data, default=default, option=orjson.OPT_INDENT_2)
69
        encoded = encoded.decode(encoding="utf8")
70
        encoded = StringTools.retab(encoded, 2)
71
        return encoded
72
73
    @property
74
    def cid(self) -> int:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
75
        if self._data["record.RecordType"] != "CID":
76
            raise ValueError(
77
                "RecordType for {} is {}".format(
78
                    self._data["record.RecordNumber"], self._data["record.RecordType"]
79
                )
80
            )
81
        return self._data["record.RecordNumber"]
82
83
    @property
84
    def _toc(self) -> JsonNavigator:
85
        return self._nav / "Section" % "TOCHeading"
86
87
    @property
88
    def _tables(self) -> JsonNavigator:
89
        return JsonNavigator.create(self._data) / "external_tables"
90
91
    @property
92
    def _links(self) -> JsonNavigator:
93
        return JsonNavigator.create(self._data) / "link_sets"
94
95
    @property
96
    def _classifications(self) -> JsonNavigator:
97
        return self._nav / "classifications"
98
99
    @property
100
    def _nav(self) -> JsonNavigator:
101
        return JsonNavigator.create(self._data) / "record"
102
103
    @property
104
    def _refs(self) -> Mapping[int, str]:
105
        return {z["ReferenceNumber"]: z["SourceName"] for z in (self._nav / "Reference").contents}
106
107
    def _has_ref(self, name: str) -> FilterFn:
108
        return FilterFn(lambda dot: self._refs.get(dot.get_as("ReferenceNumber", int)) == name)
109
110
111
class PubchemMiniDataView(PubchemDataView, metaclass=abc.ABCMeta):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
112
    """"""
113
114
    @property
115
    def _whoami(self) -> str:
116
        raise NotImplementedError()
117
118
    @property
119
    def _mini(self) -> JsonNavigator:
120
        return self._toc / self._whoami / "Section" % "TOCHeading"
121
122
123
class TitleAndSummary(PubchemDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
124
    """"""
125
126
    @property
127
    def safety(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
128
        return (
129
            self._toc
130
            / "Chemical Safety"
131
            / "Information"
132
            / self._has_ref("PubChem")
133
            / "Value"
134
            / "StringWithMarkup"
135
            / "Markup"
136
            >> "Extra"
137
        ).to_set
138
139
140
class RelatedRecords(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
141
    """"""
142
143
    @property
144
    def _whoami(self) -> str:
145
        return "Related Records"
146
147
    @property
148
    def parent(self) -> Optional[int]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
149
        parent = (
150
            self._mini
151
            / "Parent Compound"
152
            / "Information"
153
            / "Value"
154
            / "StringWithMarkup"
155
            // ["String"]
156
            // Fns.require_only()
157
        )
158
        parent = parent / Fns.extract_group_1(r"CID (\d+) +.*") // Fns.request_only()
159
        return self.cid if parent.get is None else int(parent.get)
160
161
162
class NamesAndIdentifiers(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
163
    """"""
164
165
    @property
166
    def _whoami(self) -> str:
167
        return "Names and Identifiers"
168
169
    @property
170
    def inchikey(self) -> str:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
171
        return self.descriptor("InChI Key")
172
173
    @property
174
    def inchi(self) -> str:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
175
        return self.descriptor("InChI")
176
177
    @property
178
    def molecular_formula(self) -> str:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
179
        return (
180
            self._toc
181
            / "Molecular Formula"
182
            / "Information"
183
            / self._has_ref("PubChem")
184
            / "Value"
185
            / "StringWithMarkup"
186
            / "Markup"
187
            // ["String"]
188
            // Fns.require_only()
189
            // Fns.require_only()
190
        ).get
191
192
    def descriptor(self, key: str) -> str:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
193
        return (
194
            self._toc
195
            / "Computed Descriptors"
196
            / "Section"
197
            % "TOCHeading"
198
            / key
199
            / "Information"
200
            / self._has_ref("PubChem")
201
            / "Value"
202
            / "StringWithMarkup"
203
            / "Markup"
204
            // ["String"]
205
            // Fns.require_only()
206
            // Fns.require_only()
207
        ).get
208
209
    @property
210
    def create_date(self) -> date:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
211
        return (
212
            self._toc
213
            / "Create Date"
214
            / "Information"
215
            / self._has_ref("PubChem")
216
            / "Value"
217
            // ["DateISO8601"]
218
            // Fns.require_only()
219
            / date.fromisoformat
220
            // Fns.require_only()
221
        ).get
222
223
    @property
224
    def modify_date(self) -> date:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
225
        return (
226
            self._toc
227
            / "Modify Date"
228
            / "Information"
229
            / self._has_ref("PubChem")
230
            / "Value"
231
            // ["DateISO8601"]
232
            // Fns.require_only()
233
            / date.fromisoformat
234
            // Fns.require_only()
235
        ).get
236
237
238
class ChemicalAndPhysicalProperties(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
239
    """"""
240
241
    @property
242
    def _whoami(self) -> str:
243
        return "Chemical and Physical Properties"
244
245
    @property
246
    def xlogp3(self) -> str:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
247
        return self.single_property("XLogP3").req_is(float)
248
249
    @property
250
    def mol_weight(self) -> str:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
251
        weight = self.single_property("Molecular Weight")
252
        if weight.unit != "g/mol":
253
            raise ValueError(f"Expected g/mol for weight; got {weight.unit}")
254
        return weight.req_is(float)
255
256
    @property
257
    def tpsa(self) -> str:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
258
        weight = self.single_property("Topological Polar Surface Area")
259
        if weight.unit != "Ų":
260
            raise ValueError(f"Expected Ų for weight; got {weight.unit}")
261
        return weight.req_is(float)
262
263
    @property
264
    def charge(self) -> int:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
265
        return self.single_property("Formal Charge", "PubChem").value
266
267
    @property
268
    def complexity_rating(self) -> int:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
269
        return self.single_property("Complexity", "PubChem").value
270
271
    def single_property(self, key: str, ref: Optional[str] = "PubChem") -> ComputedProperty:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
272
        return CommonTools.only(
273
            [kvr for kvr in self.computed if kvr.key == key and (ref is None or kvr.ref == ref)]
274
        )
275
276
    @property
277
    def computed(self) -> FrozenSet[ComputedProperty]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
278
        cid = self.cid
279
        props = {
280
            dot["TOCHeading"]: dot["Information"]
281
            for dot in (self._mini / "Computed Properties" / "Section").get
282
        }
283
        results: Dict[Tup[str, str], ComputedProperty] = {}
284
        for heading, info in props.items():
285
            for dot in info:
286
                try:
287
                    dot = NestedDotDict(dot)
288
                    kvr = self._extract_kvr(heading, dot)
289
                    if kvr is not None:
290
                        if (kvr.key, kvr.ref) in results:
291
                            raise MultipleMatchesError(f"Multiple matches for {kvr} on {cid}")
292
                        results[(kvr.key, kvr.ref)] = kvr
293
                except (KeyError, ValueError):
294
                    logger.debug(f"Failed on {dot} for cid {cid}")
0 ignored issues
show
introduced by
Use lazy % formatting in logging functions
Loading history...
295
                    raise
296
        return frozenset(results.values())
297
298
    def _extract_kvr(self, heading: str, dot: NestedDotDict) -> Optional[ComputedProperty]:
299
        if "Value" not in dot or "Reference" not in dot:
300
            return None
301
        ref = ", ".join(dot["Reference"])
302
        value, unit = self._extract_value_and_unit(dot["Value"])
303
        return ComputedProperty(heading, value, unit, ref)
304
305
    def _extract_value_and_unit(
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
306
        self, dot: NestedDotDict
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
307
    ) -> Tup[Union[None, int, str, float, bool], str]:
308
        value, unit = None, None
309
        if "Number" in dot and len(["Number"]) == 1:
310
            value = dot["Number"][0]
311
        elif "Number" in dot and len(["Number"]) > 1:
312
            value = ", ".join([str(s) for s in dot["Number"]])
313
        elif (
314
            "StringWithMarkup" in dot
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
315
            and len(dot["StringWithMarkup"]) == 1
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
316
            and "String" in dot["StringWithMarkup"][0]
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
317
        ):
318
            value = dot["StringWithMarkup"][0]["String"]
319
        elif (
320
            "StringWithMarkup" in dot
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
321
            and len(dot["StringWithMarkup"]) > 1
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
322
            and all(["String" in swump for swump in dot["StringWithMarkup"]])
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
323
        ):
324
            value = ", ".join([str(s) for s in dot["StringWithMarkup"]])
325
        else:
326
            value = None
327
        if "Unit" in dot and value is not None:
328
            unit = dot["Unit"]
329
        if isinstance(value, str):
330
            value = value.strip().replace("\n", "").replace("\r", "").strip()
331
        return value, unit
332
333
334
class DrugAndMedicationInformation(PubchemDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
335
    """"""
336
337
    @property
338
    def mini(self) -> JsonNavigator:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
339
        return self._toc / "Drug and Medication Information" / "Section" % "TOCHeading"
340
341
    @property
342
    def indication_summary_drugbank(self) -> Optional[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
343
        return (
344
            self.mini
345
            / "Drug Indication"
346
            / "Information"
347
            / self._has_ref("DrugBank")
348
            / "Value"
349
            / "StringWithMarkup"
350
            >> "String"
351
            >> Fns.join_nonnulls()
352
        ).get
353
354
    @property
355
    def indication_summary_livertox(self) -> Optional[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
356
        return (
357
            self.mini
358
            / "LiverTox Summary"
359
            / "Information"
360
            / self._has_ref("LiverTox")
361
            / "Value"
362
            / "StringWithMarkup"
363
            >> "String"
364
            >> Fns.join_nonnulls()
365
        ).get
366
367
    @property
368
    def classes(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
369
        return (
370
            self.mini
371
            / "Drug Classes"
372
            / "Information"
373
            / self._has_ref("LiverTox")
374
            / "Value"
375
            / "StringWithMarkup"
376
            >> "String"
377
        ).to_set
378
379
    @property
380
    def dea_class(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
381
        return (
382
            self.mini
383
            / "DEA Drug Facts"
384
            / "Information"
385
            / self._has_ref("Drug Enforcement Administration (DEA)")
386
            / "Value"
387
            / "StringWithMarkup"
388
            >> "String"
389
        ).to_set
390
391
    @property
392
    def dea_schedule(self) -> Optional[Codes.DeaSchedule]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
393
        return (
394
            self.mini
395
            / "DEA Controlled Substances"
396
            / "Information"
397
            / self._has_ref("Drug Enforcement Administration (DEA)")
398
            / "Value"
399
            / "StringWithMarkup"
400
            // ["String"]
401
            // Fns.require_only()
402
            / Fns.extract_group_1(r" *Schedule ([IV]+).*")
403
            / Codes.DeaSchedule
404
            // Fns.request_only()
405
        ).get
406
407
    @property
408
    def hsdb_uses(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
409
        mesh = "National Library of Medicine's Medical Subject Headings"
410
        return (
411
            self.mini
412
            / "Therapeutic Uses"
413
            / "Information"
414
            / self._has_ref("Hazardous Substances Data Bank (HSDB)")
415
            / FilterFn(lambda dot: dot.req_as("Reference", str).startswith(mesh))
416
            / "Value"
417
            / "StringWithMarkup"
418
            >> "String"
419
        ).to_set
420
421
    @property
422
    def clinical_trials(self) -> FrozenSet[ClinicalTrial]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
423
        trials = (self._tables / "clinicaltrials").get
424
        objs = []
425
        for trial in trials:
426
            source = self._refs[int(trial["srcid"])]
427
            obj = ClinicalTrial(
428
                trial["title"],
429
                frozenset(trial["conditions"].split("|")),
430
                trial["phase"],
431
                trial["status"],
432
                frozenset(trial["interventions"].split("|")),
433
                frozenset([Codes.PubchemCompoundId.of(z) for z in trial["cids"].split("|")]),
434
                source,
435
            )
436
            objs.append(obj)
437
        return frozenset(objs)
438
439
440
class PharmacologyAndBiochemistry(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
441
    """"""
442
443
    @property
444
    def _whoami(self) -> str:
445
        return "Pharmacology and Biochemistry"
446
447
    @property
448
    def summary_drugbank_text(self) -> Optional[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
449
        return (
450
            self._mini
451
            / "Pharmacology"
452
            / "Information"
453
            / self._has_ref("DrugBank")
454
            / "Value"
455
            / "StringWithMarkup"
456
            >> "String"
457
            >> Fns.join_nonnulls()
458
        ).get
459
460
    @property
461
    def summary_ncit_text(self) -> Optional[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
462
        return (
463
            self._mini
464
            / "Pharmacology"
465
            / "Information"
466
            / self._has_ref("NCI Thesaurus (NCIt)")
467
            / Fns.key_equals("Name", "Pharmacology")
468
            / "Value"
469
            / "StringWithMarkup"
470
            >> "String"
471
            >> Fns.join_nonnulls()
472
        ).get
473
474
    @property
475
    def summary_ncit_links(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
476
        return (
477
            self._mini
478
            / "Pharmacology"
479
            / "Information"
480
            / self._has_ref("NCI Thesaurus (NCIt)")
481
            / Fns.key_equals("Name", "Pharmacology")
482
            / "Value"
483
            / "StringWithMarkup"
484
            / "Markup"
485
            / Fns.key_equals("Type", "PubChem Internal Link")
486
            // ["URL"]
487
            // Fns.require_only()
488
            / Fns.extract_group_1(Patterns.pubchem_compound_url)
489
            / url_unescape
490
            / Fns.lowercase_unless_acronym()  # TODO necessary but unfortunate -- cocaine and Cocaine
0 ignored issues
show
Coding Style introduced by
TODO and FIXME comments should generally be avoided.
Loading history...
Coding Style introduced by
This line is too long as per the coding-style (101/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
491
        ).to_set
492
493
    @property
494
    def mesh(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
495
        return (
496
            self._mini
497
            / "MeSH Pharmacological Classification"
498
            / "Information"
499
            / self._has_ref("MeSH")
500
            >> "Name"
501
        ).to_set
502
503
    @property
504
    def atc(self) -> FrozenSet[AtcCode]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
505
        strs = (
506
            self._mini
507
            / "ATC Code"
508
            / "Information"
509
            / self._has_ref("WHO Anatomical Therapeutic Chemical (ATC) Classification")
510
            / Fns.key_equals("Name", "ATC Code")
511
            / "Value"
512
            / "StringWithMarkup"
513
            >> "String"
514
        ).to_set
515
        return frozenset(
516
            [AtcCode(s.split(" - ")[0].strip(), s.split(" - ")[1].strip()) for s in strs]
517
        )
518
519
    @property
520
    def moa_summary_drugbank_links(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
521
        return self._get_moa_links("DrugBank")
522
523
    @property
524
    def moa_summary_drugbank_text(self) -> Optional[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
525
        return self._get_moa_text("DrugBank")
526
527
    @property
528
    def moa_summary_hsdb_links(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
529
        return self._get_moa_links("Hazardous Substances Data Bank (HSDB)")
530
531
    @property
532
    def moa_summary_hsdb_text(self) -> Optional[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
533
        return self._get_moa_text("Hazardous Substances Data Bank (HSDB)")
534
535
    def _get_moa_text(self, ref: str) -> Optional[str]:
536
        return (
537
            self._mini
538
            / "Mechanism of Action"
539
            / "Information"
540
            / self._has_ref(ref)
541
            / "Value"
542
            / "StringWithMarkup"
543
            >> "String"
544
            >> Fns.join_nonnulls()
545
        ).get
546
547
    def _get_moa_links(self, ref: str) -> FrozenSet[str]:
548
        return (
549
            self._mini
550
            / "Mechanism of Action"
551
            / "Information"
552
            / self._has_ref(ref)
553
            / "Value"
554
            / "StringWithMarkup"
555
            / "Markup"
556
            / Fns.key_equals("Type", "PubChem Internal Link")
557
            // ["URL"]
558
            // Fns.require_only()
559
            / Fns.extract_group_1(Patterns.pubchem_compound_url)
560
            / url_unescape
561
            / Fns.lowercase_unless_acronym()  # TODO necessary but unfortunate -- cocaine and Cocaine
0 ignored issues
show
Coding Style introduced by
TODO and FIXME comments should generally be avoided.
Loading history...
Coding Style introduced by
This line is too long as per the coding-style (101/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
562
        ).to_set
563
564
    @property
565
    def biochem_reactions(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
566
        # TODO from multiple sources
0 ignored issues
show
Coding Style introduced by
TODO and FIXME comments should generally be avoided.
Loading history...
567
        return (self._tables / "pathwayreaction" >> "name").to_set
568
569
570
class SafetyAndHazards(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
571
    """"""
572
573
    @property
574
    def _whoami(self) -> str:
575
        return "Safety and Hazards"
576
577
    @property
578
    def ghs_codes(self) -> FrozenSet[GhsCode]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
579
        codes = (
580
            self._mini
581
            / "Hazards Identification"
582
            / "Section"
583
            % "TOCHeading"
584
            / "GHS Classification"
585
            / "Information"
586
            / self._has_ref("European Chemicals Agency (ECHA)")
587
            / Fns.key_equals("Name", "GHS Hazard Statements")
588
            / "Value"
589
            / "StringWithMarkup"
590
            // ["String"]
591
            // Fns.require_only()
592
            / Fns.extract_group_1(r"^(H\d+)[ :].*$")
593
            // Fns.split_and_flatten_nonnulls("+")
594
        ).get
595
        return frozenset([GhsCode.find(code) for code in codes])
596
597
598
class Toxicity(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
599
    """"""
600
601
    @property
602
    def _whoami(self) -> str:
603
        return "Toxicity"
604
605
    @property
606
    def acute_effects(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
607
        values = (
608
            self._tables
609
            / "chemidplus"
610
            // ["effect"]
611
            // Fns.request_only()
612
            // Fns.split_and_flatten_nonnulls(";", skip_nulls=True)
613
        ).contents
614
        vals = {
615
            v.strip().lower().replace("\n", " ").replace("\r", " ").replace("\t", " ")
616
            for v in values
617
        }
618
        return frozenset({v for v in vals if v != "nan"})
619
620
621
class AssociatedDisordersAndDiseases(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
622
    """"""
623
624
    @property
625
    def _whoami(self) -> str:
626
        return "Associated Disorders and Diseases"
627
628
    @property
629
    def associated_disorders_and_diseases(self) -> FrozenSet[AssociatedDisorder]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
630
        return (
631
            self._tables
632
            / "ctd_chemical_disease"
633
            // ["diseasename", "directevidence", "dois"]
634
            / [Fns.identity, Fns.identity, Fns.n_bar_items()]
635
            // Fns.construct(AssociatedDisorder)
636
        ).to_set
637
638
639
class Literature(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
640
    """"""
641
642
    @property
643
    def _whoami(self) -> str:
644
        return "Literature"
645
646
    @property
647
    def depositor_pubmed_articles(self) -> FrozenSet[PubmedEntry]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
648
        def split_mesh_headings(s: str) -> FrozenSet[Codes.MeshHeading]:
0 ignored issues
show
Coding Style Naming introduced by
Argument name "s" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
649
            # this is a nightmare
650
            # these fields are comma-delimited strings, but there are commas within each
651
            # all of the examples I've seen with this are for chem name cis/trans
652
            # we can fix those
653
            # however, there may be some left incorrectly split
654
            # and it's possible that we join some when we shouldn't
655
            # ex: 6-Cyano-7-nitroquinoxaline-2,3-dione,Animals,Anticonvulsants,Cocaine,Death, [...]
656
            # ex: 2,3,4,5-Tetrahydro-7,8-dihydroxy-1-phenyl-1H-3-benzazepine,Animals,Benzazepines, [...]
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (104/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
657
            if s is None:
658
                return Misc.empty_frozenset
659
            bits = []
660
            current_bit = " "
661
            for bit in s.split(","):
662
                if current_bit[-1].isdigit() and bit[0].isdigit():
663
                    current_bit += bit
664
                else:
665
                    bits.append(current_bit.strip())
666
                    current_bit = bit
667
            # get the one at the end
668
            bits.append(current_bit)
669
            return frozenset({b.strip() for b in bits if b.strip() != ""})
670
671
        def split_mesh_subheadings(s: Optional[str]) -> FrozenSet[Codes.MeshSubheading]:
0 ignored issues
show
Coding Style Naming introduced by
Argument name "s" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
672
            if s is None:
673
                return Misc.empty_frozenset
674
            return frozenset({k.strip() for k in s.split(",") if k.strip() != ""})
675
676
        def split_mesh_codes(s: Optional[str]) -> FrozenSet[Codes.MeshCode]:
0 ignored issues
show
Coding Style Naming introduced by
Argument name "s" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
677
            if s is None:
678
                return Misc.empty_frozenset
679
            z = [bit.split(" ")[0] for bit in s.split(",")]
0 ignored issues
show
Coding Style Naming introduced by
Variable name "z" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
680
            return frozenset({b.strip() for b in z if b.strip() != ""})
681
682
        def split_sources(s: Optional[str]) -> FrozenSet[str]:
0 ignored issues
show
Coding Style Naming introduced by
Argument name "s" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
683
            return frozenset(s.split(","))
684
685
        def split_cids(s: Optional[str]) -> FrozenSet[int]:
0 ignored issues
show
Coding Style Naming introduced by
Argument name "s" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
686
            if s is None:
687
                return Misc.empty_frozenset
688
            return frozenset([int(q) for q in s.split(",")])
689
690
        def get_text(s: Optional[str]) -> Optional[str]:
0 ignored issues
show
Coding Style Naming introduced by
Argument name "s" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
691
            if s is None:
692
                return None
693
            return StringTools.strip_brackets_and_quotes(s.strip()).strip()
694
695
        def get_date(s: Optional[str]) -> Optional[date]:
0 ignored issues
show
Coding Style Naming introduced by
Argument name "s" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
696
            if s is None:
697
                return None
698
            return datetime.strptime(str(s).strip(), "%Y%m%d").date()
699
700
        keys = {
701
            "pmid": Codes.PubmedId.of,
702
            "articletype": Fns.req_is(str),
703
            "pmidsrcs": split_sources,
704
            "meshheadings": split_mesh_headings,
705
            "meshsubheadings": split_mesh_subheadings,
706
            "meshcodes": split_mesh_codes,
707
            "cids": split_cids,
708
            "articletitle": get_text,
709
            "articleabstract": get_text,
710
            "articlejourname": get_text,
711
            "articlepubdate": get_date,
712
        }
713
        entries = (
714
            self._tables
715
            / "pubmed"
716
            // list(keys.keys())
717
            / list(keys.values())
718
            // Fns.construct(PubmedEntry)
719
        ).to_set
720
        return entries
721
722
    @property
723
    def chemical_cooccurrences(self) -> FrozenSet[CoOccurrence]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
724
        return self._get_cooccurrences(CoOccurrenceType.chemical)
725
726
    @property
727
    def gene_cooccurrences(self) -> FrozenSet[CoOccurrence]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
728
        return self._get_cooccurrences(CoOccurrenceType.gene)
729
730
    @property
731
    def disease_cooccurrences(self) -> FrozenSet[CoOccurrence]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
732
        return self._get_cooccurrences(CoOccurrenceType.disease)
733
734
    def _get_cooccurrences(self, kind: CoOccurrenceType) -> FrozenSet[CoOccurrence]:
735
        links = (self._links / kind.x_name / "LinkDataSet" / "LinkData").get
736
        results = set()
737
        for link in links:
738
            link = NestedDotDict(link)
739
            try:
740
                neighbor_id = str(link["ID_2"][kind.id_name])
741
            except KeyError:
742
                raise KeyError(f"Could not find ${kind.id_name} in ${link['ID_2']}")
743
            neighbor_id = self._guess_neighbor(kind, neighbor_id)
744
            evidence = link["Evidence"][kind.x_name]
745
            neighbor_name = evidence["NeighborName"]
746
            ac = evidence["ArticleCount"]
0 ignored issues
show
Coding Style Naming introduced by
Variable name "ac" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
747
            nac = evidence["NeighborArticleCount"]
748
            qac = evidence["QueryArticleCount"]
749
            score = evidence["CooccurrenceScore"]
750
            articles = [NestedDotDict(k) for k in evidence["Article"]]
751
            pubs = {
752
                Publication(
753
                    pmid=Codes.PubmedId.of(pub["PMID"]),
754
                    pub_date=datetime.strptime(pub["PublicationDate"].strip(), "%Y-%m-%d").date(),
755
                    is_review=bool(pub["IsReview"]),
756
                    title=pub["Title"].strip(),
757
                    journal=pub["Journal"].strip(),
758
                    relevance_score=pub.req_as("RelevanceScore", int),
759
                )
760
                for pub in articles
761
            }
762
            results.add(
763
                CoOccurrence(
764
                    neighbor_id=neighbor_id,
765
                    neighbor_name=neighbor_name,
766
                    kind=kind,
767
                    article_count=ac,
768
                    query_article_count=qac,
769
                    neighbor_article_count=nac,
770
                    score=score,
771
                    publications=frozenset(pubs),
772
                )
773
            )
774
        return frozenset(results)
775
776
    def _guess_neighbor(self, kind: CoOccurrenceType, neighbor_id: str) -> str:
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
777
        if kind is CoOccurrenceType.chemical:
0 ignored issues
show
unused-code introduced by
Unnecessary "elif" after "return"
Loading history...
778
            return Codes.PubchemCompoundId(neighbor_id)
779
        elif kind is CoOccurrenceType.gene and neighbor_id.startswith("EC:"):
780
            return Codes.EcNumber(neighbor_id)
781
        elif kind is CoOccurrenceType.gene:
782
            return Codes.GeneId(neighbor_id)
783
        elif kind is CoOccurrenceType.disease:
784
            return Codes.MeshCode(neighbor_id)
785
        else:
786
            raise ValueError(f"Could not find ID type for {kind} ID {neighbor_id}")
787
788
789
class Patents(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
790
    """"""
791
792
    @property
793
    def _whoami(self) -> str:
794
        return "Patents"
795
796
    @property
797
    def associated_disorders_and_diseases(self) -> FrozenSet[AssociatedDisorder]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
798
        return (
799
            self._tables
800
            / "patent"
801
            // ["diseasename", "directevidence", "dois"]
802
            / [Fns.identity, Fns.identity, Fns.n_bar_items()]
803
            // Fns.construct(AssociatedDisorder)
804
        ).to_set
805
806
807
class BiomolecularInteractionsAndPathways(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
808
    """"""
809
810
    @property
811
    def _whoami(self) -> str:
812
        return "Biomolecular Interactions and Pathways"
813
814
    @property
815
    def drug_gene_interactions(self) -> FrozenSet[DrugGeneInteraction]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
816
        # the order of this dict is crucial
817
        keys = {
818
            "genename": Fns.identity(),
819
            "geneclaimname": Fns.req_is(str, True),
820
            "interactionclaimsource": Fns.req_is(str, True),
821
            "interactiontypes": Fns.split("|"),
822
            "pmids": Fns.split(","),
823
            "dois": Fns.split("|"),
824
        }
825
        return (
826
            self._tables
827
            / "dgidb"
828
            // list(keys.keys())
829
            / list(keys.values())
830
            // Fns.construct(DrugGeneInteraction)
831
        ).to_set
832
833
    @property
834
    def compound_gene_interactions(self) -> FrozenSet[CompoundGeneInteraction]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
835
        # the order of this dict is crucial
836
        # YES, the | used in pmids really is different from the , used in DrugGeneInteraction
837
        keys = {
838
            "genesymbol": Codes.GenecardSymbol,
839
            "interaction": Fns.split("|"),
840
            "taxname": Fns.req_is(str, True),
841
            "pmids": Fns.split("|"),
842
        }
843
        return (
844
            self._tables
845
            / "ctdchemicalgene"
846
            // list(keys.keys())
847
            / list(keys.values())
848
            // Fns.construct(CompoundGeneInteraction)
849
        ).to_set
850
851
    @property
852
    def drugbank_interactions(self) -> FrozenSet[DrugbankInteraction]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
853
        keys = {
854
            "genesymbol": Codes.GenecardSymbol,
855
            "drugaction": Fns.req_is(str),
856
            "targetid": Fns.req_is(str),
857
            "targetname": Fns.req_is(str),
858
            "generalfunc": Fns.req_is(str),
859
            "specificfunc": Fns.req_is(str),
860
            "pmids": Fns.split(","),
861
            "dois": Fns.split("|"),
862
        }
863
        return (
864
            self._tables
865
            / "drugbank"
866
            // list(keys.keys())
867
            / list(keys.values())
868
            // Fns.construct(DrugbankInteraction)
869
        ).to_set
870
871
    @property
872
    def drugbank_legal_groups(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
873
        return (
874
            self._tables
875
            / "drugbank"
876
            // ["druggroup"]
877
            // Fns.require_only()
878
            / Fns.split_and_flatten_nonnulls(";")
879
        ).to_set
880
881
    @property
882
    def drugbank_ddis(self) -> FrozenSet[DrugbankDdi]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
883
        keys = {
884
            "dbid2": Codes.DrugbankCompoundId,
885
            "cid2": Codes.PubchemCompoundId,
886
            "name": Fns.req_is(str),
887
            "descr": Fns.req_is(str),
888
        }
889
        return (
890
            self._tables
891
            / "drugbankddi"
892
            // list(keys.keys())
893
            / list(keys.values())
894
            // Fns.construct(DrugbankDdi)
895
        ).to_set
896
897
898
class BiologicalTestResults(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
899
    """"""
900
901
    @property
902
    def _whoami(self) -> str:
903
        return "Biological Test Results"
904
905
    @property
906
    def bioactivity(self) -> FrozenSet[Bioactivity]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
907
        keys = {
908
            "dbid2": Codes.DrugbankCompoundId.of,
909
            "cid2": Codes.PubchemCompoundId.of,
910
            "name": Fns.req_is(str),
911
            "descr": Fns.req_is(str),
912
        }
913
        return (
914
            self._tables
915
            / "bioactivity"
916
            // list(keys.keys())
917
            / list(keys.values())
918
            // Fns.construct(DrugbankDdi)
919
        ).to_set
920
921
922
class Classification(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
923
    """"""
924
925
    @property
926
    def _whoami(self) -> str:
927
        return "Classification"
928
929
    @property
930
    def mesh_tree(self) -> Sequence[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
931
        raise NotImplementedError()
932
933
    @property
934
    def chebi_tree(self) -> Sequence[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
935
        raise NotImplementedError()
936
937
    @property
938
    def atc_tree(self) -> FrozenSet[Sequence[str]]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
939
        raise NotImplementedError()
940
941
    @property
942
    def chemid(self) -> FrozenSet[Sequence[str]]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
943
        raise NotImplementedError()
944
945
    @property
946
    def g2p_tree(self) -> FrozenSet[Sequence[str]]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
947
        raise NotImplementedError()
948
949
    @property
950
    def chembl_tree(self) -> FrozenSet[Sequence[str]]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
951
        raise NotImplementedError()
952
953
    @property
954
    def cpdat_tree(self) -> FrozenSet[Sequence[str]]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
955
        raise NotImplementedError()
956
957
    @property
958
    def dea(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
959
        raise NotImplementedError()
960
961
962
class PubchemData(PubchemDataView):
0 ignored issues
show
introduced by
Missing class docstring
Loading history...
963
    @property
964
    def name(self) -> Optional[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
965
        return self._data.get("Record.RecordTitle")
966
967
    @property
968
    def title_and_summary(self) -> TitleAndSummary:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
969
        return TitleAndSummary(self._data)
970
971
    @property
972
    def chemical_and_physical_properties(self) -> ChemicalAndPhysicalProperties:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
973
        return ChemicalAndPhysicalProperties(self._data)
974
975
    @property
976
    def related_records(self) -> RelatedRecords:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
977
        return RelatedRecords(self._data)
978
979
    @property
980
    def drug_and_medication_information(self) -> DrugAndMedicationInformation:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
981
        return DrugAndMedicationInformation(self._data)
982
983
    @property
984
    def pharmacology_and_biochemistry(self) -> PharmacologyAndBiochemistry:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
985
        return PharmacologyAndBiochemistry(self._data)
986
987
    @property
988
    def safety_and_hazards(self) -> SafetyAndHazards:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
989
        return SafetyAndHazards(self._data)
990
991
    @property
992
    def toxicity(self) -> Toxicity:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
993
        return Toxicity(self._data)
994
995
    @property
996
    def literature(self) -> Literature:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
997
        return Literature(self._data)
998
999
    @property
1000
    def associated_disorders_and_diseases(self) -> AssociatedDisordersAndDiseases:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1001
        return AssociatedDisordersAndDiseases(self._data)
1002
1003
    @property
1004
    def biomolecular_interactions_and_pathways(self) -> BiomolecularInteractionsAndPathways:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1005
        return BiomolecularInteractionsAndPathways(self._data)
1006
1007
    @property
1008
    def classification(self) -> Classification:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1009
        return Classification(self._data)
1010
1011
    @property
1012
    def parent_or_self(self) -> int:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1013
        parent = self.related_records.parent
1014
        return self.cid if parent is None else parent
1015
1016
1017
__all__ = [
1018
    "PubchemData",
1019
    "TitleAndSummary",
1020
    "RelatedRecords",
1021
    "ChemicalAndPhysicalProperties",
1022
    "DrugAndMedicationInformation",
1023
    "PharmacologyAndBiochemistry",
1024
    "SafetyAndHazards",
1025
    "Toxicity",
1026
    "AssociatedDisordersAndDiseases",
1027
    "Literature",
1028
    "NamesAndIdentifiers",
1029
    "BiomolecularInteractionsAndPathways",
1030
    "Classification",
1031
]
1032