Passed
Push — dependabot/pip/sphinx-autoapi-... ( 48fb62 )
by
unknown
04:13 queued 01:53
created

PubchemData.biological_test_results()   A

Complexity

Conditions 1

Size

Total Lines 3
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
"""
0 ignored issues
show
coding-style introduced by
Too many lines in module (1047/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
# noinspection PyProtectedMember
21
from mandos.model.pubchem_support._nav_fns import Filter, Mapx, Flatmap
22
23
# noinspection PyProtectedMember
24
from mandos.model.pubchem_support._nav_model import FilterFn
25
26
# noinspection PyProtectedMember
27
from mandos.model.pubchem_support._nav import JsonNavigator
28
from mandos.model.pubchem_support.pubchem_models import (
29
    ComputedProperty,
30
    Codes,
31
    CoOccurrenceType,
32
    ClinicalTrial,
33
    GhsCode,
34
    AssociatedDisorder,
35
    AtcCode,
36
    DrugbankInteraction,
37
    DrugbankDdi,
38
    PubmedEntry,
39
    Publication,
40
    AssayType,
41
    Activity,
42
    CoOccurrence,
43
    DrugGeneInteraction,
44
    CompoundGeneInteraction,
45
    Bioactivity,
46
)
47
48
logger = logging.getLogger("mandos")
49
50
51
class Misc:
0 ignored issues
show
introduced by
Missing class docstring
Loading history...
52
    empty_frozenset = frozenset([])
53
54
55
class Patterns:
0 ignored issues
show
introduced by
Missing class docstring
Loading history...
56
    ghs_code = re.compile(r"((?:H\d+)(?:\+H\d+)*)")
57
    ghs_code_singles = re.compile(r"(H\d+)")
58
    pubchem_compound_url = re.compile(r"^https:\/\/pubchem\.ncbi\.nlm\.nih\.gov\/compound\/(.+)$")
59
    atc_codes = re.compile(r"([A-Z])([0-9]{2})?([A-Z])?([A-Z])?([A-Z])?")
60
    mesh_codes = re.compile(r"[A-Z]")
61
62
63
class PubchemDataView(metaclass=abc.ABCMeta):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
64
    """"""
65
66
    def __init__(self, data: NestedDotDict):
67
        self._data = data
68
69
    def to_json(self) -> str:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
70
        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...
71
            if isinstance(obj, NestedDotDict):
72
                # noinspection PyProtectedMember
73
                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...
74
75
        # noinspection PyProtectedMember
76
        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...
77
        encoded = orjson.dumps(data, default=default, option=orjson.OPT_INDENT_2)
78
        encoded = encoded.decode(encoding="utf8")
79
        encoded = StringTools.retab(encoded, 2)
80
        return encoded
81
82
    @property
83
    def cid(self) -> int:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
84
        if self._data["record.RecordType"] != "CID":
85
            raise ValueError(
86
                "RecordType for {} is {}".format(
87
                    self._data["record.RecordNumber"], self._data["record.RecordType"]
88
                )
89
            )
90
        return self._data["record.RecordNumber"]
91
92
    @property
93
    def _toc(self) -> JsonNavigator:
94
        return self._nav / "Section" % "TOCHeading"
95
96
    @property
97
    def _tables(self) -> JsonNavigator:
98
        return JsonNavigator.create(self._data) / "external_tables"
99
100
    @property
101
    def _links(self) -> JsonNavigator:
102
        return JsonNavigator.create(self._data) / "link_sets"
103
104
    @property
105
    def _classifications(self) -> JsonNavigator:
106
        return self._nav / "classifications"
107
108
    @property
109
    def _nav(self) -> JsonNavigator:
110
        return JsonNavigator.create(self._data) / "record"
111
112
    @property
113
    def _refs(self) -> Mapping[int, str]:
114
        return {z["ReferenceNumber"]: z["SourceName"] for z in (self._nav / "Reference").contents}
115
116
    def _has_ref(self, name: str) -> FilterFn:
117
        return FilterFn(lambda dot: self._refs.get(dot.get_as("ReferenceNumber", int)) == name)
118
119
120
class PubchemMiniDataView(PubchemDataView, metaclass=abc.ABCMeta):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
121
    """"""
122
123
    @property
124
    def _whoami(self) -> str:
125
        raise NotImplementedError()
126
127
    @property
128
    def _mini(self) -> JsonNavigator:
129
        return self._toc / self._whoami / "Section" % "TOCHeading"
130
131
132
class TitleAndSummary(PubchemDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
133
    """"""
134
135
    @property
136
    def safety(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
137
        return (
138
            self._toc
139
            / "Chemical Safety"
140
            / "Information"
141
            / self._has_ref("PubChem")
142
            / "Value"
143
            / "StringWithMarkup"
144
            / "Markup"
145
            >> "Extra"
146
        ).to_set
147
148
149
class RelatedRecords(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
150
    """"""
151
152
    @property
153
    def _whoami(self) -> str:
154
        return "Related Records"
155
156
    @property
157
    def parent(self) -> Optional[int]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
158
        parent = (
159
            self._mini
160
            / "Parent Compound"
161
            / "Information"
162
            / "Value"
163
            / "StringWithMarkup"
164
            // ["String"]
165
            // Flatmap.require_only()
166
        )
167
        parent = parent / Mapx.extract_group_1(r"CID (\d+) +.*") // Flatmap.request_only()
168
        return self.cid if parent.get is None else int(parent.get)
169
170
171
class NamesAndIdentifiers(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
172
    """"""
173
174
    @property
175
    def _whoami(self) -> str:
176
        return "Names and Identifiers"
177
178
    @property
179
    def inchikey(self) -> str:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
180
        return self.descriptor("InChI Key")
181
182
    @property
183
    def inchi(self) -> str:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
184
        return self.descriptor("InChI")
185
186
    @property
187
    def molecular_formula(self) -> str:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
188
        return (
189
            self._toc
190
            / "Molecular Formula"
191
            / "Information"
192
            / self._has_ref("PubChem")
193
            / "Value"
194
            / "StringWithMarkup"
195
            / "Markup"
196
            // ["String"]
197
            // Flatmap.require_only()
198
            // Flatmap.require_only()
199
        ).get
200
201
    def descriptor(self, key: str) -> str:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
202
        return (
203
            self._toc
204
            / "Computed Descriptors"
205
            / "Section"
206
            % "TOCHeading"
207
            / key
208
            / "Information"
209
            / self._has_ref("PubChem")
210
            / "Value"
211
            / "StringWithMarkup"
212
            / "Markup"
213
            // ["String"]
214
            // Flatmap.require_only()
215
            // Flatmap.require_only()
216
        ).get
217
218
    @property
219
    def create_date(self) -> date:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
220
        return (
221
            self._toc
222
            / "Create Date"
223
            / "Information"
224
            / self._has_ref("PubChem")
225
            / "Value"
226
            // ["DateISO8601"]
227
            // Flatmap.require_only()
228
            / date.fromisoformat
229
            // Flatmap.require_only()
230
        ).get
231
232
    @property
233
    def modify_date(self) -> date:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
234
        return (
235
            self._toc
236
            / "Modify Date"
237
            / "Information"
238
            / self._has_ref("PubChem")
239
            / "Value"
240
            // ["DateISO8601"]
241
            // Flatmap.require_only()
242
            / date.fromisoformat
243
            // Flatmap.require_only()
244
        ).get
245
246
247
class ChemicalAndPhysicalProperties(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
248
    """"""
249
250
    @property
251
    def _whoami(self) -> str:
252
        return "Chemical and Physical Properties"
253
254
    @property
255
    def xlogp3(self) -> str:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
256
        return self.single_property("XLogP3").req_is(float)
257
258
    @property
259
    def mol_weight(self) -> str:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
260
        weight = self.single_property("Molecular Weight")
261
        if weight.unit != "g/mol":
262
            raise ValueError(f"Expected g/mol for weight; got {weight.unit}")
263
        return weight.req_is(float)
264
265
    @property
266
    def tpsa(self) -> str:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
267
        weight = self.single_property("Topological Polar Surface Area")
268
        if weight.unit != "Ų":
269
            raise ValueError(f"Expected Ų for weight; got {weight.unit}")
270
        return weight.req_is(float)
271
272
    @property
273
    def charge(self) -> int:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
274
        return self.single_property("Formal Charge", "PubChem").value
275
276
    @property
277
    def complexity_rating(self) -> int:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
278
        return self.single_property("Complexity", "PubChem").value
279
280
    def single_property(self, key: str, ref: Optional[str] = "PubChem") -> ComputedProperty:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
281
        return CommonTools.only(
282
            [kvr for kvr in self.computed if kvr.key == key and (ref is None or kvr.ref == ref)]
283
        )
284
285
    @property
286
    def computed(self) -> FrozenSet[ComputedProperty]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
287
        cid = self.cid
288
        props = {
289
            dot["TOCHeading"]: dot["Information"]
290
            for dot in (self._mini / "Computed Properties" / "Section").get
291
        }
292
        results: Dict[Tup[str, str], ComputedProperty] = {}
293
        for heading, info in props.items():
294
            for dot in info:
295
                try:
296
                    dot = NestedDotDict(dot)
297
                    kvr = self._extract_kvr(heading, dot)
298
                    if kvr is not None:
299
                        if (kvr.key, kvr.ref) in results:
300
                            raise MultipleMatchesError(f"Multiple matches for {kvr} on {cid}")
301
                        results[(kvr.key, kvr.ref)] = kvr
302
                except (KeyError, ValueError):
303
                    logger.debug(f"Failed on {dot} for cid {cid}")
0 ignored issues
show
introduced by
Use lazy % formatting in logging functions
Loading history...
304
                    raise
305
        return frozenset(results.values())
306
307
    def _extract_kvr(self, heading: str, dot: NestedDotDict) -> Optional[ComputedProperty]:
308
        if "Value" not in dot or "Reference" not in dot:
309
            return None
310
        ref = ", ".join(dot["Reference"])
311
        value, unit = self._extract_value_and_unit(dot["Value"])
312
        return ComputedProperty(heading, value, unit, ref)
313
314
    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...
315
        self, dot: NestedDotDict
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
316
    ) -> Tup[Union[None, int, str, float, bool], str]:
317
        value, unit = None, None
318
        if "Number" in dot and len(["Number"]) == 1:
319
            value = dot["Number"][0]
320
        elif "Number" in dot and len(["Number"]) > 1:
321
            value = ", ".join([str(s) for s in dot["Number"]])
322
        elif (
323
            "StringWithMarkup" in dot
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
324
            and len(dot["StringWithMarkup"]) == 1
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
325
            and "String" in dot["StringWithMarkup"][0]
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
326
        ):
327
            value = dot["StringWithMarkup"][0]["String"]
328
        elif (
329
            "StringWithMarkup" in dot
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
330
            and len(dot["StringWithMarkup"]) > 1
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
331
            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...
332
        ):
333
            value = ", ".join([str(s) for s in dot["StringWithMarkup"]])
334
        else:
335
            value = None
336
        if "Unit" in dot and value is not None:
337
            unit = dot["Unit"]
338
        if isinstance(value, str):
339
            value = value.strip().replace("\n", "").replace("\r", "").strip()
340
        return value, unit
341
342
343
class DrugAndMedicationInformation(PubchemDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
344
    """"""
345
346
    @property
347
    def mini(self) -> JsonNavigator:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
348
        return self._toc / "Drug and Medication Information" / "Section" % "TOCHeading"
349
350
    @property
351
    def indication_summary_drugbank(self) -> Optional[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
352
        return (
353
            self.mini
354
            / "Drug Indication"
355
            / "Information"
356
            / self._has_ref("DrugBank")
357
            / "Value"
358
            / "StringWithMarkup"
359
            >> "String"
360
            >> Flatmap.join_nonnulls()
361
        ).get
362
363
    @property
364
    def indication_summary_livertox(self) -> Optional[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
365
        return (
366
            self.mini
367
            / "LiverTox Summary"
368
            / "Information"
369
            / self._has_ref("LiverTox")
370
            / "Value"
371
            / "StringWithMarkup"
372
            >> "String"
373
            >> Flatmap.join_nonnulls()
374
        ).get
375
376
    @property
377
    def classes(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
378
        return (
379
            self.mini
380
            / "Drug Classes"
381
            / "Information"
382
            / self._has_ref("LiverTox")
383
            / "Value"
384
            / "StringWithMarkup"
385
            >> "String"
386
        ).to_set
387
388
    @property
389
    def dea_class(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
390
        return (
391
            self.mini
392
            / "DEA Drug Facts"
393
            / "Information"
394
            / self._has_ref("Drug Enforcement Administration (DEA)")
395
            / "Value"
396
            / "StringWithMarkup"
397
            >> "String"
398
        ).to_set
399
400
    @property
401
    def dea_schedule(self) -> Optional[Codes.DeaSchedule]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
402
        return (
403
            self.mini
404
            / "DEA Controlled Substances"
405
            / "Information"
406
            / self._has_ref("Drug Enforcement Administration (DEA)")
407
            / "Value"
408
            / "StringWithMarkup"
409
            // ["String"]
410
            // Flatmap.require_only()
411
            / Mapx.extract_group_1(r" *Schedule ([IV]+).*")
412
            / Codes.DeaSchedule
413
            // Flatmap.request_only()
414
        ).get
415
416
    @property
417
    def hsdb_uses(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
418
        mesh = "National Library of Medicine's Medical Subject Headings"
419
        return (
420
            self.mini
421
            / "Therapeutic Uses"
422
            / "Information"
423
            / self._has_ref("Hazardous Substances Data Bank (HSDB)")
424
            / FilterFn(lambda dot: dot.req_as("Reference", str).startswith(mesh))
425
            / "Value"
426
            / "StringWithMarkup"
427
            >> "String"
428
        ).to_set
429
430
    @property
431
    def clinical_trials(self) -> FrozenSet[ClinicalTrial]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
432
        trials = (self._tables / "clinicaltrials").get
433
        objs = []
434
        for trial in trials:
435
            source = self._refs[int(trial["srcid"])]
436
            obj = ClinicalTrial(
437
                trial["title"],
438
                frozenset(trial["conditions"].split("|")),
439
                trial["phase"],
440
                trial["status"],
441
                frozenset(trial["interventions"].split("|")),
442
                frozenset([Codes.PubchemCompoundId.of(z) for z in trial["cids"].split("|")]),
443
                source,
444
            )
445
            objs.append(obj)
446
        return frozenset(objs)
447
448
449
class PharmacologyAndBiochemistry(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
450
    """"""
451
452
    @property
453
    def _whoami(self) -> str:
454
        return "Pharmacology and Biochemistry"
455
456
    @property
457
    def summary_drugbank_text(self) -> Optional[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
458
        return (
459
            self._mini
460
            / "Pharmacology"
461
            / "Information"
462
            / self._has_ref("DrugBank")
463
            / "Value"
464
            / "StringWithMarkup"
465
            >> "String"
466
            >> Flatmap.join_nonnulls()
467
        ).get
468
469
    @property
470
    def summary_ncit_text(self) -> Optional[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
471
        return (
472
            self._mini
473
            / "Pharmacology"
474
            / "Information"
475
            / self._has_ref("NCI Thesaurus (NCIt)")
476
            / Filter.key_equals("Name", "Pharmacology")
477
            / "Value"
478
            / "StringWithMarkup"
479
            >> "String"
480
            >> Flatmap.join_nonnulls()
481
        ).get
482
483
    @property
484
    def summary_ncit_links(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
485
        return (
486
            self._mini
487
            / "Pharmacology"
488
            / "Information"
489
            / self._has_ref("NCI Thesaurus (NCIt)")
490
            / Filter.key_equals("Name", "Pharmacology")
491
            / "Value"
492
            / "StringWithMarkup"
493
            / "Markup"
494
            / Filter.key_equals("Type", "PubChem Internal Link")
495
            // ["URL"]
496
            // Flatmap.require_only()
497
            / Mapx.extract_group_1(Patterns.pubchem_compound_url)
498
            / url_unescape
499
            / Mapx.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 (102/100).

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

Loading history...
500
        ).to_set
501
502
    @property
503
    def mesh(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
504
        return (
505
            self._mini
506
            / "MeSH Pharmacological Classification"
507
            / "Information"
508
            / self._has_ref("MeSH")
509
            >> "Name"
510
        ).to_set
511
512
    @property
513
    def atc(self) -> FrozenSet[AtcCode]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
514
        strs = (
515
            self._mini
516
            / "ATC Code"
517
            / "Information"
518
            / self._has_ref("WHO Anatomical Therapeutic Chemical (ATC) Classification")
519
            / Filter.key_equals("Name", "ATC Code")
520
            / "Value"
521
            / "StringWithMarkup"
522
            >> "String"
523
        ).to_set
524
        return frozenset(
525
            [AtcCode(s.split(" - ")[0].strip(), s.split(" - ")[1].strip()) for s in strs]
526
        )
527
528
    @property
529
    def moa_summary_drugbank_links(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
530
        return self._get_moa_links("DrugBank")
531
532
    @property
533
    def moa_summary_drugbank_text(self) -> Optional[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
534
        return self._get_moa_text("DrugBank")
535
536
    @property
537
    def moa_summary_hsdb_links(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
538
        return self._get_moa_links("Hazardous Substances Data Bank (HSDB)")
539
540
    @property
541
    def moa_summary_hsdb_text(self) -> Optional[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
542
        return self._get_moa_text("Hazardous Substances Data Bank (HSDB)")
543
544
    def _get_moa_text(self, ref: str) -> Optional[str]:
545
        return (
546
            self._mini
547
            / "Mechanism of Action"
548
            / "Information"
549
            / self._has_ref(ref)
550
            / "Value"
551
            / "StringWithMarkup"
552
            >> "String"
553
            >> Flatmap.join_nonnulls(sep=" /// ")
554
        ).get
555
556
    def _get_moa_links(self, ref: str) -> FrozenSet[str]:
557
        return (
558
            self._mini
559
            / "Mechanism of Action"
560
            / "Information"
561
            / self._has_ref(ref)
562
            / "Value"
563
            / "StringWithMarkup"
564
            / "Markup"
565
            / Filter.key_equals("Type", "PubChem Internal Link")
566
            // ["URL"]
567
            // Flatmap.require_only()
568
            / Mapx.extract_group_1(Patterns.pubchem_compound_url)
569
            / url_unescape
570
            / Mapx.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 (102/100).

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

Loading history...
571
        ).to_set
572
573
    @property
574
    def biochem_reactions(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
575
        # TODO from multiple sources
0 ignored issues
show
Coding Style introduced by
TODO and FIXME comments should generally be avoided.
Loading history...
576
        return frozenset({s.strip() for s in (self._tables / "pathwayreaction" >> "name").to_set})
577
578
579
class SafetyAndHazards(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
580
    """"""
581
582
    @property
583
    def _whoami(self) -> str:
584
        return "Safety and Hazards"
585
586
    @property
587
    def ghs_codes(self) -> FrozenSet[GhsCode]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
588
        codes = (
589
            self._mini
590
            / "Hazards Identification"
591
            / "Section"
592
            % "TOCHeading"
593
            / "GHS Classification"
594
            / "Information"
595
            / self._has_ref("European Chemicals Agency (ECHA)")
596
            / Filter.key_equals("Name", "GHS Hazard Statements")
597
            / "Value"
598
            / "StringWithMarkup"
599
            // ["String"]
600
            // Flatmap.require_only()
601
            / Mapx.extract_group_1(r"^(H\d+)[ :].*$")
602
            // Mapx.split_and_flatten_nonnulls("+")  # TODO: how is this being used to flatten?
0 ignored issues
show
Coding Style introduced by
TODO and FIXME comments should generally be avoided.
Loading history...
603
        ).get
604
        return frozenset([GhsCode.find(code) for code in codes])
605
606
607
class Toxicity(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
608
    """"""
609
610
    @property
611
    def _whoami(self) -> str:
612
        return "Toxicity"
613
614
    @property
615
    def acute_effects(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
616
        values = (
617
            self._tables
618
            / "chemidplus"
619
            // ["effect"]
620
            // Flatmap.request_only()
621
            // Mapx.split_and_flatten_nonnulls(";", skip_nulls=True)
622
        ).contents
623
        vals = {
624
            v.strip().lower().replace("\n", " ").replace("\r", " ").replace("\t", " ")
625
            for v in values
626
        }
627
        return frozenset({v for v in vals if v != "nan"})
628
629
630
class AssociatedDisordersAndDiseases(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
631
    """"""
632
633
    @property
634
    def _whoami(self) -> str:
635
        return "Associated Disorders and Diseases"
636
637
    @property
638
    def associated_disorders_and_diseases(self) -> FrozenSet[AssociatedDisorder]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
639
        return (
640
            self._tables
641
            / "ctd_chemical_disease"
642
            // ["diseasename", "directevidence", "dois"]
643
            / [Mapx.req_is(str), Mapx.req_is(str), Mapx.n_bar_items()]
644
            // Flatmap.construct(AssociatedDisorder)
645
        ).to_set
646
647
648
class Literature(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
649
    """"""
650
651
    @property
652
    def _whoami(self) -> str:
653
        return "Literature"
654
655
    @property
656
    def depositor_pubmed_articles(self) -> FrozenSet[PubmedEntry]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
657
        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...
658
            # this is a nightmare
659
            # these fields are comma-delimited strings, but there are commas within each
660
            # all of the examples I've seen with this are for chem name cis/trans
661
            # we can fix those
662
            # however, there may be some left incorrectly split
663
            # and it's possible that we join some when we shouldn't
664
            # ex: 6-Cyano-7-nitroquinoxaline-2,3-dione,Animals,Anticonvulsants,Cocaine,Death, [...]
665
            # 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...
666
            if s is None:
667
                return Misc.empty_frozenset
668
            bits = []
669
            current_bit = " "
670
            for bit in s.split(","):
671
                if current_bit[-1].isdigit() and bit[0].isdigit():
672
                    current_bit += bit
673
                else:
674
                    bits.append(current_bit.strip())
675
                    current_bit = bit
676
            # get the one at the end
677
            bits.append(current_bit)
678
            return frozenset({b.strip() for b in bits if b.strip() != ""})
679
680
        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...
681
            if s is None:
682
                return Misc.empty_frozenset
683
            return frozenset({k.strip() for k in s.split(",") if k.strip() != ""})
684
685
        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...
686
            if s is None:
687
                return Misc.empty_frozenset
688
            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...
689
            return frozenset({b.strip() for b in z if b.strip() != ""})
690
691
        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...
692
            return frozenset(s.split(","))
693
694
        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...
695
            if s is None:
696
                return Misc.empty_frozenset
697
            return frozenset([int(q) for q in s.split(",")])
698
699
        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...
700
            if s is None:
701
                return None
702
            return StringTools.strip_brackets_and_quotes(s.strip()).strip()
703
704
        keys = {
705
            "pmid": Codes.PubmedId.of,
706
            "articletype": Mapx.req_is(str),
707
            "pmidsrcs": split_sources,
708
            "meshheadings": split_mesh_headings,
709
            "meshsubheadings": split_mesh_subheadings,
710
            "meshcodes": split_mesh_codes,
711
            "cids": split_cids,
712
            "articletitle": get_text,
713
            "articleabstract": get_text,
714
            "articlejourname": get_text,
715
            "articlepubdate": Mapx.int_date(),
716
        }
717
        entries = (
718
            self._tables
719
            / "pubmed"
720
            // list(keys.keys())
721
            / list(keys.values())
722
            // Flatmap.construct(PubmedEntry)
723
        ).to_set
724
        return entries
725
726
    @property
727
    def chemical_cooccurrences(self) -> FrozenSet[CoOccurrence]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
728
        return self._get_cooccurrences(CoOccurrenceType.chemical)
729
730
    @property
731
    def gene_cooccurrences(self) -> FrozenSet[CoOccurrence]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
732
        return self._get_cooccurrences(CoOccurrenceType.gene)
733
734
    @property
735
    def disease_cooccurrences(self) -> FrozenSet[CoOccurrence]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
736
        return self._get_cooccurrences(CoOccurrenceType.disease)
737
738
    def _get_cooccurrences(self, kind: CoOccurrenceType) -> FrozenSet[CoOccurrence]:
739
        links = (self._links / kind.x_name / "LinkDataSet" / "LinkData").get
740
        results = set()
741
        for link in links:
742
            link = NestedDotDict(link)
743
            try:
744
                neighbor_id = str(link["ID_2"][kind.id_name])
745
            except KeyError:
746
                raise KeyError(f"Could not find ${kind.id_name} in ${link['ID_2']}")
747
            neighbor_id = self._guess_neighbor(kind, neighbor_id)
748
            evidence = link["Evidence"][kind.x_name]
749
            neighbor_name = evidence["NeighborName"]
750
            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...
751
            nac = evidence["NeighborArticleCount"]
752
            qac = evidence["QueryArticleCount"]
753
            score = evidence["CooccurrenceScore"]
754
            articles = [NestedDotDict(k) for k in evidence["Article"]]
755
            pubs = {
756
                Publication(
757
                    pmid=Codes.PubmedId.of(pub["PMID"]),
758
                    pub_date=datetime.strptime(pub["PublicationDate"].strip(), "%Y-%m-%d").date(),
759
                    is_review=bool(pub["IsReview"]),
760
                    title=pub["Title"].strip(),
761
                    journal=pub["Journal"].strip(),
762
                    relevance_score=pub.req_as("RelevanceScore", int),
763
                )
764
                for pub in articles
765
            }
766
            results.add(
767
                CoOccurrence(
768
                    neighbor_id=neighbor_id,
769
                    neighbor_name=neighbor_name,
770
                    kind=kind,
771
                    article_count=ac,
772
                    query_article_count=qac,
773
                    neighbor_article_count=nac,
774
                    score=score,
775
                    publications=frozenset(pubs),
776
                )
777
            )
778
        return frozenset(results)
779
780
    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...
781
        if kind is CoOccurrenceType.chemical:
0 ignored issues
show
unused-code introduced by
Unnecessary "elif" after "return"
Loading history...
782
            return Codes.PubchemCompoundId(neighbor_id)
783
        elif kind is CoOccurrenceType.gene and neighbor_id.startswith("EC:"):
784
            return Codes.EcNumber(neighbor_id)
785
        elif kind is CoOccurrenceType.gene:
786
            return Codes.GeneId(neighbor_id)
787
        elif kind is CoOccurrenceType.disease:
788
            return Codes.MeshCode(neighbor_id)
789
        else:
790
            raise ValueError(f"Could not find ID type for {kind} ID {neighbor_id}")
791
792
793
class Patents(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
794
    """"""
795
796
    @property
797
    def _whoami(self) -> str:
798
        return "Patents"
799
800
    @property
801
    def associated_disorders_and_diseases(self) -> FrozenSet[AssociatedDisorder]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
802
        return (
803
            self._tables
804
            / "patent"
805
            // ["diseasename", "directevidence", "dois"]
806
            / [Mapx.req_is(str), Mapx.req_is(str), Mapx.n_bar_items()]
807
            // Flatmap.construct(AssociatedDisorder)
808
        ).to_set
809
810
811
class BiomolecularInteractionsAndPathways(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
812
    """"""
813
814
    @property
815
    def _whoami(self) -> str:
816
        return "Biomolecular Interactions and Pathways"
817
818
    @property
819
    def drug_gene_interactions(self) -> FrozenSet[DrugGeneInteraction]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
820
        # the order of this dict is crucial
821
        keys = {
822
            "genename": Mapx.req_is(str, nullable=True),
823
            "geneclaimname": Mapx.req_is(str, nullable=True),
824
            "interactionclaimsource": Mapx.req_is(str, nullable=True),
825
            "interactiontypes": Mapx.split("|", nullable=True),
826
            "pmids": Mapx.split(",", nullable=True),
827
            "dois": Mapx.split("|", nullable=True),
828
        }
829
        return (
830
            self._tables
831
            / "dgidb"
832
            // list(keys.keys())
833
            / list(keys.values())
834
            // Flatmap.construct(DrugGeneInteraction)
835
        ).to_set
836
837
    @property
838
    def compound_gene_interactions(self) -> FrozenSet[CompoundGeneInteraction]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
839
        # the order of this dict is crucial
840
        # YES, the | used in pmids really is different from the , used in DrugGeneInteraction
841
        keys = {
842
            "genesymbol": Codes.GenecardSymbol,
843
            "interaction": Mapx.split("|", nullable=True),
844
            "taxname": Mapx.req_is(str, True),
845
            "pmids": Mapx.split("|", nullable=True),
846
        }
847
        return (
848
            self._tables
849
            / "ctdchemicalgene"
850
            // list(keys.keys())
851
            / list(keys.values())
852
            // Flatmap.construct(CompoundGeneInteraction)
853
        ).to_set
854
855
    @property
856
    def drugbank_interactions(self) -> FrozenSet[DrugbankInteraction]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
857
        keys = {
858
            "genesymbol": Codes.GenecardSymbol,
859
            "drugaction": Mapx.req_is(str),
860
            "targetid": Mapx.req_is(str),
861
            "targetname": Mapx.req_is(str),
862
            "generalfunc": Mapx.req_is(str),
863
            "specificfunc": Mapx.req_is(str),
864
            "pmids": Mapx.split(","),
865
            "dois": Mapx.split("|"),
866
        }
867
        return (
868
            self._tables
869
            / "drugbank"
870
            // list(keys.keys())
871
            / list(keys.values())
872
            // Flatmap.construct(DrugbankInteraction)
873
        ).to_set
874
875
    @property
876
    def drugbank_legal_groups(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
877
        q = set()
0 ignored issues
show
Coding Style Naming introduced by
Variable name "q" 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...
878
        for x in (self._tables / "drugbank" // ["druggroup"] // Flatmap.require_only()).to_set:
0 ignored issues
show
Coding Style Naming introduced by
Variable name "x" 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...
879
            for y in x.split(";"):
0 ignored issues
show
Coding Style Naming introduced by
Variable name "y" 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...
880
                q.add(y.strip())
881
        return frozenset(q)
882
883
    @property
884
    def drugbank_ddis(self) -> FrozenSet[DrugbankDdi]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
885
        keys = {
886
            "dbid2": Codes.DrugbankCompoundId,
887
            "cid2": Codes.PubchemCompoundId,
888
            "name": Mapx.req_is(str),
889
            "descr": Mapx.req_is(str),
890
        }
891
        return (
892
            self._tables
893
            / "drugbankddi"
894
            // list(keys.keys())
895
            / list(keys.values())
896
            // Flatmap.construct(DrugbankDdi)
897
        ).to_set
898
899
900
class BiologicalTestResults(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
901
    """"""
902
903
    @property
904
    def _whoami(self) -> str:
905
        return "Biological Test Results"
906
907
    @property
908
    def bioactivity(self) -> FrozenSet[Bioactivity]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
909
        keys = {
910
            "aid": Mapx.req_is(int),
911
            "aidtype": (lambda s: AssayType[s.lower().strip()]),
912
            "aidsrcname": Mapx.req_is(str),
913
            "aidname": Mapx.req_is(str),
914
            "aidmdate": Mapx.int_date(),
915
            "geneid": Mapx.str_to(Codes.GeneId, nullable=True, flex_type=True),
916
            "taxid": Mapx.str_to(str, flex_type=True, nullable=True),
917
            "pmid": lambda s: None
918
            if s is None
0 ignored issues
show
Coding Style introduced by
Wrong continued indentation (add 8 spaces).
Loading history...
919
            else Codes.PubmedId(StringTools.strip_off_end(str(s), ".0")),
0 ignored issues
show
Coding Style introduced by
Wrong continued indentation (add 8 spaces).
Loading history...
920
            "activity": (lambda s: None if s is None else Activity[s.lower()]),
921
            "acname": Mapx.str_to(str, nullable=True),
922
            "acvalue": (lambda x: None if x is None else float(x)),
923
            "targetname": Mapx.req_is(str, nullable=True),
924
        }
925
        return (
926
            self._tables
927
            / "bioactivity"
928
            // list(keys.keys())
929
            / list(keys.values())
930
            // Flatmap.construct(Bioactivity)
931
        ).to_set
932
933
934
class Classification(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
935
    """"""
936
937
    @property
938
    def _whoami(self) -> str:
939
        return "Classification"
940
941
    @property
942
    def mesh_tree(self) -> Sequence[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
943
        raise NotImplementedError()
944
945
    @property
946
    def chebi_tree(self) -> Sequence[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
947
        raise NotImplementedError()
948
949
    @property
950
    def atc_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 chemid(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 g2p_tree(self) -> FrozenSet[Sequence[str]]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
959
        raise NotImplementedError()
960
961
    @property
962
    def chembl_tree(self) -> FrozenSet[Sequence[str]]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
963
        raise NotImplementedError()
964
965
    @property
966
    def cpdat_tree(self) -> FrozenSet[Sequence[str]]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
967
        raise NotImplementedError()
968
969
    @property
970
    def dea(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
971
        raise NotImplementedError()
972
973
974
class PubchemData(PubchemDataView):
0 ignored issues
show
introduced by
Missing class docstring
Loading history...
975
    @property
976
    def name(self) -> Optional[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
977
        return self._data.get("Record.RecordTitle")
978
979
    @property
980
    def title_and_summary(self) -> TitleAndSummary:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
981
        return TitleAndSummary(self._data)
982
983
    @property
984
    def chemical_and_physical_properties(self) -> ChemicalAndPhysicalProperties:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
985
        return ChemicalAndPhysicalProperties(self._data)
986
987
    @property
988
    def related_records(self) -> RelatedRecords:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
989
        return RelatedRecords(self._data)
990
991
    @property
992
    def drug_and_medication_information(self) -> DrugAndMedicationInformation:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
993
        return DrugAndMedicationInformation(self._data)
994
995
    @property
996
    def pharmacology_and_biochemistry(self) -> PharmacologyAndBiochemistry:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
997
        return PharmacologyAndBiochemistry(self._data)
998
999
    @property
1000
    def safety_and_hazards(self) -> SafetyAndHazards:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1001
        return SafetyAndHazards(self._data)
1002
1003
    @property
1004
    def toxicity(self) -> Toxicity:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1005
        return Toxicity(self._data)
1006
1007
    @property
1008
    def literature(self) -> Literature:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1009
        return Literature(self._data)
1010
1011
    @property
1012
    def associated_disorders_and_diseases(self) -> AssociatedDisordersAndDiseases:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1013
        return AssociatedDisordersAndDiseases(self._data)
1014
1015
    @property
1016
    def biomolecular_interactions_and_pathways(self) -> BiomolecularInteractionsAndPathways:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1017
        return BiomolecularInteractionsAndPathways(self._data)
1018
1019
    @property
1020
    def biological_test_results(self) -> BiologicalTestResults:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1021
        return BiologicalTestResults(self._data)
1022
1023
    @property
1024
    def classification(self) -> Classification:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1025
        return Classification(self._data)
1026
1027
    @property
1028
    def parent_or_self(self) -> int:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1029
        parent = self.related_records.parent
1030
        return self.cid if parent is None else parent
1031
1032
1033
__all__ = [
1034
    "PubchemData",
1035
    "TitleAndSummary",
1036
    "RelatedRecords",
1037
    "ChemicalAndPhysicalProperties",
1038
    "DrugAndMedicationInformation",
1039
    "PharmacologyAndBiochemistry",
1040
    "SafetyAndHazards",
1041
    "Toxicity",
1042
    "AssociatedDisordersAndDiseases",
1043
    "Literature",
1044
    "NamesAndIdentifiers",
1045
    "BiomolecularInteractionsAndPathways",
1046
    "Classification",
1047
]
1048