Passed
Push — main ( bfa577...eb6882 )
by Douglas
04:37
created

PubchemData.chemical_and_physical_properties()   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 (1057/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 livertox_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
                Codes.ClinicaltrialId.of(trial["ctid"]),
438
                trial["title"],
439
                frozenset([Codes.GenericDiseaseCode.of(z) for z in trial["diseaseids"].split("|")]),
440
                frozenset(trial["conditions"].split("|")),
441
                trial["phase"],
442
                trial["status"],
443
                frozenset(trial["interventions"].split("|")),
444
                frozenset([Codes.PubchemCompoundId.of(z) for z in trial["cids"].split("|")]),
445
                source,
446
            )
447
            objs.append(obj)
448
        return frozenset(objs)
449
450
451
class PharmacologyAndBiochemistry(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
452
    """"""
453
454
    @property
455
    def _whoami(self) -> str:
456
        return "Pharmacology and Biochemistry"
457
458
    @property
459
    def summary_drugbank_text(self) -> Optional[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
460
        return (
461
            self._mini
462
            / "Pharmacology"
463
            / "Information"
464
            / self._has_ref("DrugBank")
465
            / "Value"
466
            / "StringWithMarkup"
467
            >> "String"
468
            >> Flatmap.join_nonnulls()
469
        ).get
470
471
    @property
472
    def summary_ncit_text(self) -> Optional[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
473
        return (
474
            self._mini
475
            / "Pharmacology"
476
            / "Information"
477
            / self._has_ref("NCI Thesaurus (NCIt)")
478
            / Filter.key_equals("Name", "Pharmacology")
479
            / "Value"
480
            / "StringWithMarkup"
481
            >> "String"
482
            >> Flatmap.join_nonnulls()
483
        ).get
484
485
    @property
486
    def summary_ncit_links(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
487
        return (
488
            self._mini
489
            / "Pharmacology"
490
            / "Information"
491
            / self._has_ref("NCI Thesaurus (NCIt)")
492
            / Filter.key_equals("Name", "Pharmacology")
493
            / "Value"
494
            / "StringWithMarkup"
495
            / "Markup"
496
            / Filter.key_equals("Type", "PubChem Internal Link")
497
            // ["URL"]
498
            // Flatmap.require_only()
499
            / Mapx.extract_group_1(Patterns.pubchem_compound_url)
500
            / url_unescape
501
            / Mapx.lowercase_unless_acronym()  # TODO necessary but unfortunate -- cocaine and Cocaine
0 ignored issues
show
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...
Coding Style introduced by
TODO and FIXME comments should generally be avoided.
Loading history...
502
        ).to_set
503
504
    @property
505
    def mesh(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
506
        return (
507
            self._mini
508
            / "MeSH Pharmacological Classification"
509
            / "Information"
510
            / self._has_ref("MeSH")
511
            >> "Name"
512
        ).to_set
513
514
    @property
515
    def atc(self) -> FrozenSet[AtcCode]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
516
        strs = (
517
            self._mini
518
            / "ATC Code"
519
            / "Information"
520
            / self._has_ref("WHO Anatomical Therapeutic Chemical (ATC) Classification")
521
            / Filter.key_equals("Name", "ATC Code")
522
            / "Value"
523
            / "StringWithMarkup"
524
            >> "String"
525
        ).to_set
526
        return frozenset(
527
            [AtcCode(s.split(" - ")[0].strip(), s.split(" - ")[1].strip()) for s in strs]
528
        )
529
530
    @property
531
    def moa_summary_drugbank_links(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
532
        return self._get_moa_links("DrugBank")
533
534
    @property
535
    def moa_summary_drugbank_text(self) -> Optional[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
536
        return self._get_moa_text("DrugBank")
537
538
    @property
539
    def moa_summary_hsdb_links(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
540
        return self._get_moa_links("Hazardous Substances Data Bank (HSDB)")
541
542
    @property
543
    def moa_summary_hsdb_text(self) -> Optional[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
544
        return self._get_moa_text("Hazardous Substances Data Bank (HSDB)")
545
546
    def _get_moa_text(self, ref: str) -> Optional[str]:
547
        return (
548
            self._mini
549
            / "Mechanism of Action"
550
            / "Information"
551
            / self._has_ref(ref)
552
            / "Value"
553
            / "StringWithMarkup"
554
            >> "String"
555
            >> Flatmap.join_nonnulls(sep=" /// ")
556
        ).get
557
558
    def _get_moa_links(self, ref: str) -> FrozenSet[str]:
559
        return (
560
            self._mini
561
            / "Mechanism of Action"
562
            / "Information"
563
            / self._has_ref(ref)
564
            / "Value"
565
            / "StringWithMarkup"
566
            / "Markup"
567
            / Filter.key_equals("Type", "PubChem Internal Link")
568
            // ["URL"]
569
            // Flatmap.require_only()
570
            / Mapx.extract_group_1(Patterns.pubchem_compound_url)
571
            / url_unescape
572
            / 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...
573
        ).to_set
574
575
    @property
576
    def biochem_reactions(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
577
        # TODO from multiple sources
0 ignored issues
show
Coding Style introduced by
TODO and FIXME comments should generally be avoided.
Loading history...
578
        return frozenset({s.strip() for s in (self._tables / "pathwayreaction" >> "name").to_set})
579
580
581
class SafetyAndHazards(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
582
    """"""
583
584
    @property
585
    def _whoami(self) -> str:
586
        return "Safety and Hazards"
587
588
    @property
589
    def ghs_codes(self) -> FrozenSet[GhsCode]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
590
        codes = (
591
            self._mini
592
            / "Hazards Identification"
593
            / "Section"
594
            % "TOCHeading"
595
            / "GHS Classification"
596
            / "Information"
597
            / self._has_ref("European Chemicals Agency (ECHA)")
598
            / Filter.key_equals("Name", "GHS Hazard Statements")
599
            / "Value"
600
            / "StringWithMarkup"
601
            // ["String"]
602
            // Flatmap.require_only()
603
            / Mapx.extract_group_1(r"^(H\d+)[ :].*$")
604
            // 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...
605
        ).get
606
        return frozenset([GhsCode.find(code) for code in codes])
607
608
609
class Toxicity(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
610
    """"""
611
612
    @property
613
    def _whoami(self) -> str:
614
        return "Toxicity"
615
616
    @property
617
    def acute_effects(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
618
        values = (
619
            self._tables
620
            / "chemidplus"
621
            // ["effect"]
622
            // Flatmap.request_only()
623
            // Mapx.split_and_flatten_nonnulls(";", skip_nulls=True)
624
        ).contents
625
        vals = {
626
            v.strip().lower().replace("\n", " ").replace("\r", " ").replace("\t", " ")
627
            for v in values
628
        }
629
        return frozenset({v for v in vals if v != "nan"})
630
631
632
class AssociatedDisordersAndDiseases(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
633
    """"""
634
635
    @property
636
    def _whoami(self) -> str:
637
        return "Associated Disorders and Diseases"
638
639
    @property
640
    def associated_disorders_and_diseases(self) -> FrozenSet[AssociatedDisorder]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
641
        return (
642
            self._tables
643
            / "ctd_chemical_disease"
644
            // ["gid", "diseaseextid", "diseasename", "directevidence", "dois"]
645
            / [str, Codes.MeshCode.of, Mapx.req_is(str), Mapx.req_is(str), Mapx.n_bar_items()]
646
            // Flatmap.construct(AssociatedDisorder)
647
        ).to_set
648
649
650
class Literature(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
651
    """"""
652
653
    @property
654
    def _whoami(self) -> str:
655
        return "Literature"
656
657
    @property
658
    def depositor_pubmed_articles(self) -> FrozenSet[PubmedEntry]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
659
        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...
660
            # this is a nightmare
661
            # these fields are comma-delimited strings, but there are commas within each
662
            # all of the examples I've seen with this are for chem name cis/trans
663
            # we can fix those
664
            # however, there may be some left incorrectly split
665
            # and it's possible that we join some when we shouldn't
666
            # ex: 6-Cyano-7-nitroquinoxaline-2,3-dione,Animals,Anticonvulsants,Cocaine,Death, [...]
667
            # 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...
668
            if s is None:
669
                return Misc.empty_frozenset
670
            bits = []
671
            current_bit = " "
672
            for bit in s.split(","):
673
                if current_bit[-1].isdigit() and bit[0].isdigit():
674
                    current_bit += bit
675
                else:
676
                    bits.append(current_bit.strip())
677
                    current_bit = bit
678
            # get the one at the end
679
            bits.append(current_bit)
680
            return frozenset({b.strip() for b in bits if b.strip() != ""})
681
682
        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...
683
            if s is None:
684
                return Misc.empty_frozenset
685
            return frozenset({k.strip() for k in s.split(",") if k.strip() != ""})
686
687
        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...
688
            if s is None:
689
                return Misc.empty_frozenset
690
            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...
691
            return frozenset({b.strip() for b in z if b.strip() != ""})
692
693
        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...
694
            return frozenset(s.split(","))
695
696
        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...
697
            if s is None:
698
                return Misc.empty_frozenset
699
            return frozenset([int(q) for q in s.split(",")])
700
701
        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...
702
            if s is None:
703
                return None
704
            return StringTools.strip_brackets_and_quotes(s.strip()).strip()
705
706
        keys = {
707
            "pmid": Codes.PubmedId.of,
708
            "articletype": Mapx.req_is(str),
709
            "pmidsrcs": split_sources,
710
            "meshheadings": split_mesh_headings,
711
            "meshsubheadings": split_mesh_subheadings,
712
            "meshcodes": split_mesh_codes,
713
            "cids": split_cids,
714
            "articletitle": get_text,
715
            "articleabstract": get_text,
716
            "articlejourname": get_text,
717
            "articlepubdate": Mapx.int_date(),
718
        }
719
        entries = (
720
            self._tables
721
            / "pubmed"
722
            // list(keys.keys())
723
            / list(keys.values())
724
            // Flatmap.construct(PubmedEntry)
725
        ).to_set
726
        return entries
727
728
    @property
729
    def chemical_cooccurrences(self) -> FrozenSet[CoOccurrence]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
730
        return self._get_cooccurrences(CoOccurrenceType.chemical)
731
732
    @property
733
    def gene_cooccurrences(self) -> FrozenSet[CoOccurrence]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
734
        return self._get_cooccurrences(CoOccurrenceType.gene)
735
736
    @property
737
    def disease_cooccurrences(self) -> FrozenSet[CoOccurrence]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
738
        return self._get_cooccurrences(CoOccurrenceType.disease)
739
740
    def _get_cooccurrences(self, kind: CoOccurrenceType) -> FrozenSet[CoOccurrence]:
741
        links = (self._links / kind.x_name / "LinkDataSet" / "LinkData").get
742
        results = set()
743
        for link in links:
744
            link = NestedDotDict(link)
745
            try:
746
                neighbor_id = str(link["ID_2"][kind.id_name])
747
            except KeyError:
748
                raise KeyError(f"Could not find ${kind.id_name} in ${link['ID_2']}")
749
            neighbor_id = self._guess_neighbor(kind, neighbor_id)
750
            evidence = link["Evidence"][kind.x_name]
751
            neighbor_name = evidence["NeighborName"]
752
            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...
753
            nac = evidence["NeighborArticleCount"]
754
            qac = evidence["QueryArticleCount"]
755
            score = evidence["CooccurrenceScore"]
756
            articles = [NestedDotDict(k) for k in evidence["Article"]]
757
            pubs = {
758
                Publication(
759
                    pmid=Codes.PubmedId.of(pub["PMID"]),
760
                    pub_date=datetime.strptime(pub["PublicationDate"].strip(), "%Y-%m-%d").date(),
761
                    is_review=bool(pub["IsReview"]),
762
                    title=pub["Title"].strip(),
763
                    journal=pub["Journal"].strip(),
764
                    relevance_score=pub.req_as("RelevanceScore", int),
765
                )
766
                for pub in articles
767
            }
768
            results.add(
769
                CoOccurrence(
770
                    neighbor_id=neighbor_id,
771
                    neighbor_name=neighbor_name,
772
                    kind=kind,
773
                    article_count=ac,
774
                    query_article_count=qac,
775
                    neighbor_article_count=nac,
776
                    score=score,
777
                    publications=frozenset(pubs),
778
                )
779
            )
780
        return frozenset(results)
781
782
    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...
783
        if kind is CoOccurrenceType.chemical:
0 ignored issues
show
unused-code introduced by
Unnecessary "elif" after "return"
Loading history...
784
            return Codes.PubchemCompoundId(neighbor_id)
785
        elif kind is CoOccurrenceType.gene and neighbor_id.startswith("EC:"):
786
            return Codes.EcNumber(neighbor_id)
787
        elif kind is CoOccurrenceType.gene:
788
            return Codes.GeneId(neighbor_id)
789
        elif kind is CoOccurrenceType.disease:
790
            return Codes.MeshCode(neighbor_id)
791
        else:
792
            raise ValueError(f"Could not find ID type for {kind} ID {neighbor_id}")
793
794
795
class Patents(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
796
    """"""
797
798
    @property
799
    def _whoami(self) -> str:
800
        return "Patents"
801
802
    @property
803
    def associated_disorders_and_diseases(self) -> FrozenSet[AssociatedDisorder]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
804
        return (
805
            self._tables
806
            / "patent"
807
            // ["diseasename", "directevidence", "dois"]
808
            / [Mapx.req_is(str), Mapx.req_is(str), Mapx.n_bar_items()]
809
            // Flatmap.construct(AssociatedDisorder)
810
        ).to_set
811
812
813
class BiomolecularInteractionsAndPathways(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
814
    """"""
815
816
    @property
817
    def _whoami(self) -> str:
818
        return "Biomolecular Interactions and Pathways"
819
820
    @property
821
    def drug_gene_interactions(self) -> FrozenSet[DrugGeneInteraction]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
822
        # the order of this dict is crucial
823
        keys = {
824
            "genename": Mapx.req_is(str, nullable=True),
825
            "geneclaimname": Mapx.req_is(str, nullable=True),
826
            "interactionclaimsource": Mapx.req_is(str, nullable=True),
827
            "interactiontypes": Mapx.split("|", nullable=True),
828
            "pmids": Mapx.split(",", nullable=True),
829
            "dois": Mapx.split("|", nullable=True),
830
        }
831
        return (
832
            self._tables
833
            / "dgidb"
834
            // list(keys.keys())
835
            / list(keys.values())
836
            // Flatmap.construct(DrugGeneInteraction)
837
        ).to_set
838
839
    @property
840
    def compound_gene_interactions(self) -> FrozenSet[CompoundGeneInteraction]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
841
        # the order of this dict is crucial
842
        # YES, the | used in pmids really is different from the , used in DrugGeneInteraction
843
        keys = {
844
            "genesymbol": Codes.GenecardSymbol,
845
            "interaction": Mapx.split("|", nullable=True),
846
            "taxname": Mapx.req_is(str, True),
847
            "pmids": Mapx.split("|", nullable=True),
848
        }
849
        return (
850
            self._tables
851
            / "ctdchemicalgene"
852
            // list(keys.keys())
853
            / list(keys.values())
854
            // Flatmap.construct(CompoundGeneInteraction)
855
        ).to_set
856
857
    @property
858
    def drugbank_interactions(self) -> FrozenSet[DrugbankInteraction]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
859
        keys = {
860
            "genesymbol": Codes.GenecardSymbol,
861
            "drugaction": Mapx.req_is(str),
862
            "targetid": Mapx.req_is(str),
863
            "targetname": Mapx.req_is(str),
864
            "generalfunc": Mapx.req_is(str),
865
            "specificfunc": Mapx.req_is(str),
866
            "pmids": Mapx.split(","),
867
            "dois": Mapx.split("|"),
868
        }
869
        return (
870
            self._tables
871
            / "drugbank"
872
            // list(keys.keys())
873
            / list(keys.values())
874
            // Flatmap.construct(DrugbankInteraction)
875
        ).to_set
876
877
    @property
878
    def drugbank_legal_groups(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
879
        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...
880
        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...
881
            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...
882
                q.add(y.strip())
883
        return frozenset(q)
884
885
    @property
886
    def drugbank_ddis(self) -> FrozenSet[DrugbankDdi]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
887
        keys = {
888
            "dbid2": Codes.DrugbankCompoundId,
889
            "cid2": Codes.PubchemCompoundId,
890
            "name": Mapx.req_is(str),
891
            "descr": Mapx.req_is(str),
892
        }
893
        return (
894
            self._tables
895
            / "drugbankddi"
896
            // list(keys.keys())
897
            / list(keys.values())
898
            // Flatmap.construct(DrugbankDdi)
899
        ).to_set
900
901
902
class BiologicalTestResults(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
903
    """"""
904
905
    @property
906
    def _whoami(self) -> str:
907
        return "Biological Test Results"
908
909
    @property
910
    def bioactivity(self) -> FrozenSet[Bioactivity]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
911
        keys = {
912
            "aid": Mapx.req_is(int),
913
            "aidtype": (lambda s: AssayType[s.lower().strip()]),
914
            "aidsrcname": Mapx.req_is(str),
915
            "aidname": Mapx.req_is(str),
916
            "aidmdate": Mapx.int_date(),
917
            "geneid": Mapx.str_to(Codes.GeneId, nullable=True, flex_type=True),
918
            "taxid": Mapx.str_to(str, flex_type=True, nullable=True),
919
            "pmid": lambda s: None
920
            if s is None
0 ignored issues
show
Coding Style introduced by
Wrong continued indentation (add 8 spaces).
Loading history...
921
            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...
922
            "activity": (lambda s: None if s is None else Activity[s.lower()]),
923
            "acname": Mapx.str_to(str, nullable=True),
924
            "acvalue": (lambda x: None if x is None else float(x)),
925
            "targetname": Mapx.req_is(str, nullable=True),
926
        }
927
        return (
928
            self._tables
929
            / "bioactivity"
930
            // list(keys.keys())
931
            / list(keys.values())
932
            // Flatmap.construct(Bioactivity)
933
        ).to_set
934
935
936
class Classification(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
937
    """"""
938
939
    @property
940
    def _whoami(self) -> str:
941
        return "Classification"
942
943
    @property
944
    def mesh_tree(self) -> Sequence[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
945
        raise NotImplementedError()
946
947
    @property
948
    def chebi_tree(self) -> Sequence[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
949
        raise NotImplementedError()
950
951
    @property
952
    def atc_tree(self) -> FrozenSet[Sequence[str]]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
953
        raise NotImplementedError()
954
955
    @property
956
    def chemid(self) -> FrozenSet[Sequence[str]]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
957
        raise NotImplementedError()
958
959
    @property
960
    def g2p_tree(self) -> FrozenSet[Sequence[str]]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
961
        raise NotImplementedError()
962
963
    @property
964
    def chembl_tree(self) -> FrozenSet[Sequence[str]]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
965
        raise NotImplementedError()
966
967
    @property
968
    def cpdat_tree(self) -> FrozenSet[Sequence[str]]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
969
        raise NotImplementedError()
970
971
    @property
972
    def dea(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
973
        raise NotImplementedError()
974
975
976
class PubchemData(PubchemDataView):
0 ignored issues
show
introduced by
Missing class docstring
Loading history...
977
    @property
978
    def name(self) -> Optional[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
979
        return self._data.get("Record.RecordTitle")
980
981
    @property
982
    def title_and_summary(self) -> TitleAndSummary:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
983
        return TitleAndSummary(self._data)
984
985
    @property
986
    def names_and_identifiers(self) -> NamesAndIdentifiers:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
987
        return NamesAndIdentifiers(self._data)
988
989
    @property
990
    def chemical_and_physical_properties(self) -> ChemicalAndPhysicalProperties:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
991
        return ChemicalAndPhysicalProperties(self._data)
992
993
    @property
994
    def related_records(self) -> RelatedRecords:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
995
        return RelatedRecords(self._data)
996
997
    @property
998
    def drug_and_medication_information(self) -> DrugAndMedicationInformation:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
999
        return DrugAndMedicationInformation(self._data)
1000
1001
    @property
1002
    def pharmacology_and_biochemistry(self) -> PharmacologyAndBiochemistry:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1003
        return PharmacologyAndBiochemistry(self._data)
1004
1005
    @property
1006
    def safety_and_hazards(self) -> SafetyAndHazards:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1007
        return SafetyAndHazards(self._data)
1008
1009
    @property
1010
    def toxicity(self) -> Toxicity:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1011
        return Toxicity(self._data)
1012
1013
    @property
1014
    def literature(self) -> Literature:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1015
        return Literature(self._data)
1016
1017
    @property
1018
    def associated_disorders_and_diseases(self) -> AssociatedDisordersAndDiseases:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1019
        return AssociatedDisordersAndDiseases(self._data)
1020
1021
    @property
1022
    def biomolecular_interactions_and_pathways(self) -> BiomolecularInteractionsAndPathways:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1023
        return BiomolecularInteractionsAndPathways(self._data)
1024
1025
    @property
1026
    def biological_test_results(self) -> BiologicalTestResults:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1027
        return BiologicalTestResults(self._data)
1028
1029
    @property
1030
    def classification(self) -> Classification:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1031
        return Classification(self._data)
1032
1033
    @property
1034
    def parent_or_none(self) -> Optional[int]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1035
        return self.related_records.parent
1036
1037
    @property
1038
    def parent_or_self(self) -> int:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1039
        parent = self.related_records.parent
1040
        return self.cid if parent is None else parent
1041
1042
1043
__all__ = [
1044
    "PubchemData",
1045
    "TitleAndSummary",
1046
    "RelatedRecords",
1047
    "ChemicalAndPhysicalProperties",
1048
    "DrugAndMedicationInformation",
1049
    "PharmacologyAndBiochemistry",
1050
    "SafetyAndHazards",
1051
    "Toxicity",
1052
    "AssociatedDisordersAndDiseases",
1053
    "Literature",
1054
    "NamesAndIdentifiers",
1055
    "BiomolecularInteractionsAndPathways",
1056
    "Classification",
1057
]
1058