Passed
Push — main ( 82dd22...9813db )
by Douglas
01:58
created

NamesAndIdentifiers.isomeric_smiles()   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 (1075/1000)
Loading history...
2
PubChem data views and processors.
3
"""
4
from __future__ import annotations
5
6
import abc
7
import re
8
from datetime import date, datetime
9
from typing import Any, Dict, FrozenSet, Mapping, Optional, Sequence
10
from typing import Tuple as Tup
11
from typing import Union
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.dot_dict import NestedDotDict
0 ignored issues
show
introduced by
Unable to import 'pocketutils.core.dot_dict'
Loading history...
16
from pocketutils.tools.common_tools import CommonTools
0 ignored issues
show
introduced by
Unable to import 'pocketutils.tools.common_tools'
Loading history...
17
from pocketutils.tools.string_tools import StringTools
0 ignored issues
show
introduced by
Unable to import 'pocketutils.tools.string_tools'
Loading history...
18
19
from mandos import logger
20
21
# noinspection PyProtectedMember
22
from mandos.model import MultipleMatchesError
23
24
# noinspection PyProtectedMember
25
from mandos.model.apis.pubchem_support._nav import JsonNavigator
26
from mandos.model.apis.pubchem_support._nav_fns import Filter, Flatmap, Mapx
27
28
# noinspection PyProtectedMember
29
from mandos.model.apis.pubchem_support._nav_model import FilterFn
30
from mandos.model.apis.pubchem_support.pubchem_models import (
31
    Activity,
32
    AcuteEffectEntry,
33
    AssociatedDisorder,
34
    AtcCode,
35
    Bioactivity,
36
    ChemicalGeneInteraction,
37
    ClinicalTrial,
38
    Codes,
39
    ComputedProperty,
40
    CoOccurrence,
41
    CoOccurrenceType,
42
    DrugbankDdi,
43
    DrugbankInteraction,
44
    DrugbankTargetType,
45
    DrugGeneInteraction,
46
    GhsCode,
47
    Publication,
48
    PubmedEntry,
49
)
50
51
52
class Misc:
0 ignored issues
show
introduced by
Missing class docstring
Loading history...
53
    empty_frozenset = frozenset([])
54
55
56
class Patterns:
0 ignored issues
show
introduced by
Missing class docstring
Loading history...
57
    ghs_code = re.compile(r"((?:H\d+)(?:\+H\d+)*)")
58
    ghs_code_singles = re.compile(r"(H\d+)")
59
    pubchem_compound_url = re.compile(r"^https:\/\/pubchem\.ncbi\.nlm\.nih\.gov\/compound\/(.+)$")
60
    atc_codes = re.compile(r"([A-Z])([0-9]{2})?([A-Z])?([A-Z])?([A-Z])?")
61
    mesh_codes = re.compile(r"[A-Z]")
62
63
64
class PubchemDataView(metaclass=abc.ABCMeta):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
65
    """ """
66
67
    def __init__(self, data: NestedDotDict):
68
        self._data = data
69
70
    def to_json(self) -> str:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
71
        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...
72
            if isinstance(obj, NestedDotDict):
73
                # noinspection PyProtectedMember
74
                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...
75
76
        # noinspection PyProtectedMember
77
        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...
78
        encoded = orjson.dumps(data, default=default, option=orjson.OPT_INDENT_2)
79
        encoded = encoded.decode(encoding="utf8")
80
        encoded = StringTools.retab(encoded, 2)
81
        return encoded
82
83
    @property
84
    def cid(self) -> int:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
85
        if self._data["record.RecordType"] != "CID":
86
            raise ValueError(
87
                "RecordType for {} is {}".format(
88
                    self._data["record.RecordNumber"], self._data["record.RecordType"]
89
                )
90
            )
91
        return self._data["record.RecordNumber"]
92
93
    @property
94
    def _toc(self) -> JsonNavigator:
95
        return self._nav / "Section" % "TOCHeading"
96
97
    @property
98
    def _tables(self) -> JsonNavigator:
99
        return JsonNavigator.create(self._data) / "external_tables"
100
101
    @property
102
    def _links(self) -> JsonNavigator:
103
        return JsonNavigator.create(self._data) / "link_sets"
104
105
    @property
106
    def _classifications(self) -> JsonNavigator:
107
        return self._nav / "classifications"
108
109
    @property
110
    def _nav(self) -> JsonNavigator:
111
        return JsonNavigator.create(self._data) / "record"
112
113
    @property
114
    def _refs(self) -> Mapping[int, str]:
115
        return {z["ReferenceNumber"]: z["SourceName"] for z in (self._nav / "Reference").contents}
116
117
    def _has_ref(self, name: str) -> FilterFn:
118
        return FilterFn(lambda dot: self._refs.get(dot.get_as("ReferenceNumber", int)) == name)
119
120
121
class PubchemMiniDataView(PubchemDataView, metaclass=abc.ABCMeta):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
122
    """ """
123
124
    @property
125
    def _whoami(self) -> str:
126
        raise NotImplementedError()
127
128
    @property
129
    def _mini(self) -> JsonNavigator:
130
        return self._toc / self._whoami / "Section" % "TOCHeading"
131
132
133
class TitleAndSummary(PubchemDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
134
    """ """
135
136
    @property
137
    def safety(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
138
        return (
139
            self._toc
140
            / "Chemical Safety"
141
            / "Information"
142
            / self._has_ref("PubChem")
143
            / "Value"
144
            / "StringWithMarkup"
145
            / "Markup"
146
            >> "Extra"
147
        ).to_set
148
149
150
class RelatedRecords(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
151
    """ """
152
153
    @property
154
    def _whoami(self) -> str:
155
        return "Related Records"
156
157
    @property
158
    def parent(self) -> Optional[int]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
159
        parent = (
160
            self._mini
161
            / "Parent Compound"
162
            / "Information"
163
            / "Value"
164
            / "StringWithMarkup"
165
            // ["String"]
166
            // Flatmap.require_only()
167
        )
168
        parent = parent / Mapx.extract_group_1(r"CID (\d+) +.*") // Flatmap.request_only()
169
        return self.cid if parent.get is None else int(parent.get)
170
171
172
class NamesAndIdentifiers(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
173
    """ """
174
175
    @property
176
    def _whoami(self) -> str:
177
        return "Names and Identifiers"
178
179
    @property
180
    def inchikey(self) -> str:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
181
        return self.descriptor("InChI Key")
182
183
    @property
184
    def inchi(self) -> str:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
185
        return self.descriptor("InChI")
186
187
    @property
188
    def isomeric_smiles(self) -> str:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
189
        return ""  # self.descriptor("Isomeric SMILES")
190
191
    @property
192
    def iupac(self) -> str:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
193
        return self.descriptor("IUPAC Name")
194
195
    @property
196
    def molecular_formula(self) -> str:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
197
        return (
198
            self._mini
199
            / "Molecular Formula"
200
            / "Information"
201
            / self._has_ref("PubChem")
202
            / "Value"
203
            / "StringWithMarkup"
204
            // ["String"]
205
            // Flatmap.require_only()
206
            // Flatmap.require_only()
207
        ).get
208
209
    def descriptor(self, key: str) -> str:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
210
        return (
211
            self._mini
212
            / "Computed Descriptors"
213
            / "Section"
214
            % "TOCHeading"
215
            / key
216
            / "Information"
217
            / self._has_ref("PubChem")
218
            / "Value"
219
            / "StringWithMarkup"
220
            // ["String"]
221
            // Flatmap.require_only()
222
            // Flatmap.require_only()
223
        ).get
224
225
    @property
226
    def create_date(self) -> date:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
227
        return (
228
            self._toc
229
            / "Create Date"
230
            / "Information"
231
            / self._has_ref("PubChem")
232
            / "Value"
233
            // ["DateISO8601"]
234
            // Flatmap.require_only()
235
            / date.fromisoformat
236
            // Flatmap.require_only()
237
        ).get
238
239
    @property
240
    def modify_date(self) -> date:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
241
        return (
242
            self._toc
243
            / "Modify Date"
244
            / "Information"
245
            / self._has_ref("PubChem")
246
            / "Value"
247
            // ["DateISO8601"]
248
            // Flatmap.require_only()
249
            / date.fromisoformat
250
            // Flatmap.require_only()
251
        ).get
252
253
254
class ChemicalAndPhysicalProperties(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
255
    """ """
256
257
    @property
258
    def _whoami(self) -> str:
259
        return "Chemical and Physical Properties"
260
261
    @property
262
    def xlogp3(self) -> str:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
263
        return self.single_property("XLogP3").req_is(float)
264
265
    @property
266
    def mol_weight(self) -> str:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
267
        weight = self.single_property("Molecular Weight")
268
        if weight.unit != "g/mol":
269
            raise ValueError(f"Expected g/mol for weight; got {weight.unit}")
270
        return weight.req_is(float)
271
272
    @property
273
    def tpsa(self) -> str:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
274
        weight = self.single_property("Topological Polar Surface Area")
275
        if weight.unit != "Ų":
276
            raise ValueError(f"Expected Ų for weight; got {weight.unit}")
277
        return weight.req_is(float)
278
279
    @property
280
    def charge(self) -> int:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
281
        return self.single_property("Formal Charge", "PubChem").value
282
283
    @property
284
    def complexity_rating(self) -> int:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
285
        return self.single_property("Complexity", "PubChem").value
286
287
    def single_property(self, key: str, ref: Optional[str] = "PubChem") -> ComputedProperty:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
288
        return CommonTools.only(
289
            [kvr for kvr in self.computed if kvr.key == key and (ref is None or kvr.ref == ref)]
290
        )
291
292
    @property
293
    def computed(self) -> FrozenSet[ComputedProperty]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
294
        cid = self.cid
295
        props = {
296
            dot["TOCHeading"]: dot["Information"]
297
            for dot in (self._mini / "Computed Properties" / "Section").get
298
        }
299
        results: Dict[Tup[str, str], ComputedProperty] = {}
300
        for heading, info in props.items():
301
            for dot in info:
302
                try:
303
                    dot = NestedDotDict(dot)
304
                    kvr = self._extract_kvr(heading, dot)
305
                    if kvr is not None:
306
                        if (kvr.key, kvr.ref) in results:
307
                            raise MultipleMatchesError(f"Multiple matches for {kvr} on {cid}")
308
                        results[(kvr.key, kvr.ref)] = kvr
309
                except (KeyError, ValueError):
310
                    logger.debug(f"Failed on {dot} for cid {cid}")
311
                    raise
312
        return frozenset(results.values())
313
314
    def _extract_kvr(self, heading: str, dot: NestedDotDict) -> Optional[ComputedProperty]:
315
        if "Value" not in dot or "Reference" not in dot:
316
            return None
317
        ref = ", ".join(dot["Reference"])
318
        value, unit = self._extract_value_and_unit(dot["Value"])
319
        return ComputedProperty(heading, value, unit, ref)
320
321
    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...
322
        self, dot: NestedDotDict
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
323
    ) -> Tup[Union[None, int, str, float, bool], str]:
324
        value, unit = None, None
325
        if "Number" in dot and len(["Number"]) == 1:
326
            value = dot["Number"][0]
327
        elif "Number" in dot and len(["Number"]) > 1:
328
            value = ", ".join([str(s) for s in dot["Number"]])
329
        elif (
330
            "StringWithMarkup" in dot
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
331
            and len(dot["StringWithMarkup"]) == 1
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
332
            and "String" in dot["StringWithMarkup"][0]
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
333
        ):
334
            value = dot["StringWithMarkup"][0]["String"]
335
        elif (
336
            "StringWithMarkup" in dot
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
337
            and len(dot["StringWithMarkup"]) > 1
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
338
            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...
339
        ):
340
            value = ", ".join([str(s) for s in dot["StringWithMarkup"]])
341
        else:
342
            value = None
343
        if "Unit" in dot and value is not None:
344
            unit = dot["Unit"]
345
        if isinstance(value, str):
346
            value = value.strip().replace("\n", "").replace("\r", "").strip()
347
        return value, unit
348
349
350
class DrugAndMedicationInformation(PubchemDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
351
    """ """
352
353
    @property
354
    def mini(self) -> JsonNavigator:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
355
        return self._toc / "Drug and Medication Information" / "Section" % "TOCHeading"
356
357
    @property
358
    def indication_summary_drugbank(self) -> Optional[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
359
        return (
360
            self.mini
361
            / "Drug Indication"
362
            / "Information"
363
            / self._has_ref("DrugBank")
364
            / "Value"
365
            / "StringWithMarkup"
366
            >> "String"
367
            >> Flatmap.join_nonnulls()
368
        ).get
369
370
    @property
371
    def indication_summary_livertox(self) -> Optional[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
372
        return (
373
            self.mini
374
            / "LiverTox Summary"
375
            / "Information"
376
            / self._has_ref("LiverTox")
377
            / "Value"
378
            / "StringWithMarkup"
379
            >> "String"
380
            >> Flatmap.join_nonnulls()
381
        ).get
382
383
    @property
384
    def livertox_classes(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
385
        return (
386
            self.mini
387
            / "Drug Classes"
388
            / "Information"
389
            / self._has_ref("LiverTox")
390
            / "Value"
391
            / "StringWithMarkup"
392
            >> "String"
393
        ).to_set
394
395
    @property
396
    def dea_class(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
397
        return (
398
            self.mini
399
            / "DEA Drug Facts"
400
            / "Information"
401
            / self._has_ref("Drug Enforcement Administration (DEA)")
402
            / "Value"
403
            / "StringWithMarkup"
404
            >> "String"
405
        ).to_set
406
407
    @property
408
    def dea_schedule(self) -> Optional[Codes.DeaSchedule]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
409
        return (
410
            self.mini
411
            / "DEA Controlled Substances"
412
            / "Information"
413
            / self._has_ref("Drug Enforcement Administration (DEA)")
414
            / "Value"
415
            / "StringWithMarkup"
416
            // ["String"]
417
            // Flatmap.require_only()
418
            / Mapx.extract_group_1(r" *Schedule ([IV]+).*")
419
            / Codes.DeaSchedule
420
            // Flatmap.request_only()
421
        ).get
422
423
    @property
424
    def hsdb_uses(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
425
        mesh = "National Library of Medicine's Medical Subject Headings"
426
        return (
427
            self.mini
428
            / "Therapeutic Uses"
429
            / "Information"
430
            / self._has_ref("Hazardous Substances Data Bank (HSDB)")
431
            / FilterFn(lambda dot: dot.req_as("Reference", str).startswith(mesh))
432
            / "Value"
433
            / "StringWithMarkup"
434
            >> "String"
435
        ).to_set
436
437
    @property
438
    def clinical_trials(self) -> FrozenSet[ClinicalTrial]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
439
        trials = (self._tables / "clinicaltrials").get
440
        objs = []
441
        for trial in trials:
442
            source = self._refs[int(trial["srcid"])]
443
            obj = ClinicalTrial(
444
                Codes.ClinicaltrialId.of(trial["ctid"]),
445
                trial["title"],
446
                frozenset([Codes.GenericDiseaseCode.of(z) for z in trial["diseaseids"].split("|")]),
447
                frozenset(trial["conditions"].split("|")),
448
                trial["phase"],
449
                trial["status"],
450
                frozenset(trial["interventions"].split("|")),
451
                frozenset([Codes.PubchemCompoundId.of(z) for z in trial["cids"].split("|")]),
452
                source,
453
            )
454
            objs.append(obj)
455
        return frozenset(objs)
456
457
458
class PharmacologyAndBiochemistry(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
459
    """ """
460
461
    @property
462
    def _whoami(self) -> str:
463
        return "Pharmacology and Biochemistry"
464
465
    @property
466
    def summary_drugbank_text(self) -> Optional[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
467
        return (
468
            self._mini
469
            / "Pharmacology"
470
            / "Information"
471
            / self._has_ref("DrugBank")
472
            / "Value"
473
            / "StringWithMarkup"
474
            >> "String"
475
            >> Flatmap.join_nonnulls()
476
        ).get
477
478
    @property
479
    def summary_ncit_text(self) -> Optional[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
480
        return (
481
            self._mini
482
            / "Pharmacology"
483
            / "Information"
484
            / self._has_ref("NCI Thesaurus (NCIt)")
485
            / Filter.key_equals("Name", "Pharmacology")
486
            / "Value"
487
            / "StringWithMarkup"
488
            >> "String"
489
            >> Flatmap.join_nonnulls()
490
        ).get
491
492
    @property
493
    def summary_ncit_links(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
494
        return (
495
            self._mini
496
            / "Pharmacology"
497
            / "Information"
498
            / self._has_ref("NCI Thesaurus (NCIt)")
499
            / Filter.key_equals("Name", "Pharmacology")
500
            / "Value"
501
            / "StringWithMarkup"
502
            / "Markup"
503
            / Filter.key_equals("Type", "PubChem Internal Link")
504
            // ["URL"]
505
            // Flatmap.require_only()
506
            / Mapx.extract_group_1(Patterns.pubchem_compound_url)
507
            / url_unescape
508
            / 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...
509
        ).to_set
510
511
    @property
512
    def mesh(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
513
        return (
514
            self._mini
515
            / "MeSH Pharmacological Classification"
516
            / "Information"
517
            / self._has_ref("MeSH")
518
            >> "Name"
519
        ).to_set
520
521
    @property
522
    def atc(self) -> FrozenSet[AtcCode]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
523
        strs = (
524
            self._mini
525
            / "ATC Code"
526
            / "Information"
527
            / self._has_ref("WHO Anatomical Therapeutic Chemical (ATC) Classification")
528
            / Filter.key_equals("Name", "ATC Code")
529
            / "Value"
530
            / "StringWithMarkup"
531
            >> "String"
532
        ).to_set
533
        return frozenset(
534
            [AtcCode(s.split(" - ")[0].strip(), s.split(" - ")[1].strip()) for s in strs]
535
        )
536
537
    @property
538
    def moa_summary_drugbank_links(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
539
        return self._get_moa_links("DrugBank")
540
541
    @property
542
    def moa_summary_drugbank_text(self) -> Optional[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
543
        return self._get_moa_text("DrugBank")
544
545
    @property
546
    def moa_summary_hsdb_links(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
547
        return self._get_moa_links("Hazardous Substances Data Bank (HSDB)")
548
549
    @property
550
    def moa_summary_hsdb_text(self) -> Optional[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
551
        return self._get_moa_text("Hazardous Substances Data Bank (HSDB)")
552
553
    def _get_moa_text(self, ref: str) -> Optional[str]:
554
        return (
555
            self._mini
556
            / "Mechanism of Action"
557
            / "Information"
558
            / self._has_ref(ref)
559
            / "Value"
560
            / "StringWithMarkup"
561
            >> "String"
562
            >> Flatmap.join_nonnulls(sep=" /// ")
563
        ).get
564
565
    def _get_moa_links(self, ref: str) -> FrozenSet[str]:
566
        return (
567
            self._mini
568
            / "Mechanism of Action"
569
            / "Information"
570
            / self._has_ref(ref)
571
            / "Value"
572
            / "StringWithMarkup"
573
            / "Markup"
574
            / Filter.key_equals("Type", "PubChem Internal Link")
575
            // ["URL"]
576
            // Flatmap.require_only()
577
            / Mapx.extract_group_1(Patterns.pubchem_compound_url)
578
            / url_unescape
579
            / 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...
580
        ).to_set
581
582
    @property
583
    def biochem_reactions(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
584
        # TODO from multiple sources
0 ignored issues
show
Coding Style introduced by
TODO and FIXME comments should generally be avoided.
Loading history...
585
        return frozenset({s.strip() for s in (self._tables / "pathwayreaction" >> "name").to_set})
586
587
588
class SafetyAndHazards(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
589
    """ """
590
591
    @property
592
    def _whoami(self) -> str:
593
        return "Safety and Hazards"
594
595
    @property
596
    def ghs_codes(self) -> FrozenSet[GhsCode]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
597
        codes = (
598
            self._mini
599
            / "Hazards Identification"
600
            / "Section"
601
            % "TOCHeading"
602
            / "GHS Classification"
603
            / "Information"
604
            / self._has_ref("European Chemicals Agency (ECHA)")
605
            / Filter.key_equals("Name", "GHS Hazard Statements")
606
            / "Value"
607
            / "StringWithMarkup"
608
            // ["String"]
609
            // Flatmap.require_only()
610
            / Mapx.extract_group_1(r"^(H\d+)[ :].*$")
611
            // 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...
612
        ).get
613
        return frozenset([GhsCode.find(code) for code in codes])
614
615
616
class Toxicity(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
617
    """ """
618
619
    @property
620
    def _whoami(self) -> str:
621
        return "Toxicity"
622
623
    @property
624
    def acute_effects(self) -> FrozenSet[AcuteEffectEntry]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
625
        return (
626
            self._tables
627
            / "chemidplus"
628
            // ["gid", "effect", "organism", "testtype", "route", "dose"]
629
            / [
630
                Mapx.get_int(nullable=True),
631
                Mapx.split_to(Codes.ChemIdPlusEffect.of, ";", nullable=True),
632
                Codes.ChemIdPlusOrganism.of,
633
                str,
634
                str,
635
                str,
636
            ]
637
            // Flatmap.construct(AcuteEffectEntry)
638
        ).to_set
639
640
641
class AssociatedDisordersAndDiseases(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
642
    """ """
643
644
    @property
645
    def _whoami(self) -> str:
646
        return "Associated Disorders and Diseases"
647
648
    @property
649
    def associated_disorders_and_diseases(self) -> FrozenSet[AssociatedDisorder]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
650
        return (
651
            self._tables
652
            / "ctd_chemical_disease"
653
            // ["gid", "diseaseextid", "diseasename", "directevidence", "dois"]
654
            / [
655
                str,
656
                Codes.MeshCode.of,
657
                Mapx.req_is(str),
658
                Mapx.req_is(str),
659
                Mapx.n_bar_items(null_is_zero=True),
660
            ]
661
            // Flatmap.construct(AssociatedDisorder)
662
        ).to_set
663
664
665
class Literature(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
666
    """ """
667
668
    @property
669
    def _whoami(self) -> str:
670
        return "Literature"
671
672
    @property
673
    def depositor_pubmed_articles(self) -> FrozenSet[PubmedEntry]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
674
        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...
675
            # this is a nightmare
676
            # these fields are comma-delimited strings, but there are commas within each
677
            # all of the examples I've seen with this are for chem name cis/trans
678
            # we can fix those
679
            # however, there may be some left incorrectly split
680
            # and it's possible that we join some when we shouldn't
681
            # ex: 6-Cyano-7-nitroquinoxaline-2,3-dione,Animals,Anticonvulsants,Cocaine,Death, [...]
682
            # 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...
683
            if s is None:
684
                return Misc.empty_frozenset
685
            bits = []
686
            current_bit = " "
687
            for bit in s.split(","):
688
                if current_bit[-1].isdigit() and bit[0].isdigit():
689
                    current_bit += bit
690
                else:
691
                    bits.append(current_bit.strip())
692
                    current_bit = bit
693
            # get the one at the end
694
            bits.append(current_bit)
695
            return frozenset({b.strip() for b in bits if b.strip() != ""})
696
697
        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...
698
            if s is None:
699
                return Misc.empty_frozenset
700
            return frozenset({k.strip() for k in s.split(",") if k.strip() != ""})
701
702
        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...
703
            if s is None:
704
                return Misc.empty_frozenset
705
            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...
706
            return frozenset({b.strip() for b in z if b.strip() != ""})
707
708
        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...
709
            return frozenset(s.split(","))
710
711
        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...
712
            if s is None:
713
                return Misc.empty_frozenset
714
            return frozenset([int(q) for q in s.split(",")])
715
716
        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...
717
            if s is None:
718
                return None
719
            return StringTools.strip_brackets_and_quotes(s.strip()).strip()
720
721
        keys = {
722
            "pmid": Codes.PubmedId.of,
723
            "articletype": Mapx.req_is(str),
724
            "pmidsrcs": split_sources,
725
            "meshheadings": split_mesh_headings,
726
            "meshsubheadings": split_mesh_subheadings,
727
            "meshcodes": split_mesh_codes,
728
            "cids": split_cids,
729
            "articletitle": get_text,
730
            "articleabstract": get_text,
731
            "articlejourname": get_text,
732
            "articlepubdate": Mapx.int_date(),
733
        }
734
        entries = (
735
            self._tables
736
            / "pubmed"
737
            // list(keys.keys())
738
            / list(keys.values())
739
            // Flatmap.construct(PubmedEntry)
740
        ).to_set
741
        return entries
742
743
    @property
744
    def chemical_cooccurrences(self) -> FrozenSet[CoOccurrence]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
745
        return self._get_cooccurrences(CoOccurrenceType.chemical)
746
747
    @property
748
    def gene_cooccurrences(self) -> FrozenSet[CoOccurrence]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
749
        return self._get_cooccurrences(CoOccurrenceType.gene)
750
751
    @property
752
    def disease_cooccurrences(self) -> FrozenSet[CoOccurrence]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
753
        return self._get_cooccurrences(CoOccurrenceType.disease)
754
755
    def _get_cooccurrences(self, kind: CoOccurrenceType) -> FrozenSet[CoOccurrence]:
756
        links = (self._links / kind.x_name / "LinkDataSet" / "LinkData").get
757
        results = set()
758
        for link in links:
759
            link = NestedDotDict(link)
760
            try:
761
                neighbor_id = str(link["ID_2"][kind.id_name])
762
            except KeyError:
763
                raise KeyError(f"Could not find ${kind.id_name} in ${link['ID_2']}")
764
            neighbor_id = self._guess_neighbor(kind, neighbor_id)
765
            evidence = link["Evidence"][kind.x_name]
766
            neighbor_name = evidence["NeighborName"]
767
            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...
768
            nac = evidence["NeighborArticleCount"]
769
            qac = evidence["QueryArticleCount"]
770
            score = evidence["CooccurrenceScore"]
771
            articles = [NestedDotDict(k) for k in evidence["Article"]]
772
            pubs = {
773
                Publication(
774
                    pmid=Codes.PubmedId.of(pub["PMID"]),
775
                    pub_date=datetime.strptime(pub["PublicationDate"].strip(), "%Y-%m-%d").date(),
776
                    is_review=bool(pub["IsReview"]),
777
                    title=pub["Title"].strip(),
778
                    journal=pub["Journal"].strip(),
779
                    relevance_score=pub.req_as("RelevanceScore", int),
780
                )
781
                for pub in articles
782
            }
783
            results.add(
784
                CoOccurrence(
785
                    neighbor_id=neighbor_id,
786
                    neighbor_name=neighbor_name,
787
                    kind=kind,
788
                    article_count=ac,
789
                    query_article_count=qac,
790
                    neighbor_article_count=nac,
791
                    score=score,
792
                    publications=frozenset(pubs),
793
                )
794
            )
795
        return frozenset(results)
796
797
    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...
798
        if kind is CoOccurrenceType.chemical:
0 ignored issues
show
unused-code introduced by
Unnecessary "elif" after "return"
Loading history...
799
            return Codes.PubchemCompoundId(neighbor_id)
800
        elif kind is CoOccurrenceType.gene and neighbor_id.startswith("EC:"):
801
            return Codes.EcNumber(neighbor_id)
802
        elif kind is CoOccurrenceType.gene:
803
            return Codes.GeneId(neighbor_id)
804
        elif kind is CoOccurrenceType.disease:
805
            return Codes.MeshCode(neighbor_id)
806
        else:
807
            raise ValueError(f"Could not find ID type for {kind} ID {neighbor_id}")
808
809
810
class Patents(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
811
    """ """
812
813
    @property
814
    def _whoami(self) -> str:
815
        return "Patents"
816
817
    @property
818
    def associated_disorders_and_diseases(self) -> FrozenSet[AssociatedDisorder]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
819
        return (
820
            self._tables
821
            / "patent"
822
            // ["diseasename", "directevidence", "dois"]
823
            / [Mapx.req_is(str), Mapx.req_is(str), Mapx.n_bar_items()]
824
            // Flatmap.construct(AssociatedDisorder)
825
        ).to_set
826
827
828
class BiomolecularInteractionsAndPathways(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
829
    """ """
830
831
    @property
832
    def _whoami(self) -> str:
833
        return "Biomolecular Interactions and Pathways"
834
835
    @property
836
    def drug_gene_interactions(self) -> FrozenSet[DrugGeneInteraction]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
837
        # the order of this dict is crucial
838
        keys = {
839
            "genename": Mapx.req_is(str, nullable=True),
840
            "geneclaimname": Mapx.get_str(nullable=True),
841
            "interactionclaimsource": Mapx.req_is(str, nullable=True),
842
            "interactiontypes": Mapx.split("|", nullable=True),
843
            "pmids": Mapx.split(",", nullable=True),
844
            "dois": Mapx.split("|", nullable=True),
845
        }
846
        return (
847
            self._tables
848
            / "dgidb"
849
            // list(keys.keys())
850
            / list(keys.values())
851
            // Flatmap.construct(DrugGeneInteraction)
852
        ).to_set
853
854
    @property
855
    def chemical_gene_interactions(self) -> FrozenSet[ChemicalGeneInteraction]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
856
        # the order of this dict is crucial
857
        # YES, the | used in pmids really is different from the , used in DrugGeneInteraction
858
        keys = {
859
            "genesymbol": Codes.GenecardSymbol.of_nullable,
860
            "interaction": Mapx.split("|", nullable=True),
861
            "taxid": Mapx.get_int(nullable=True),
862
            "taxname": Mapx.req_is(str, True),
863
            "pmids": Mapx.split("|", nullable=True),
864
        }
865
        return (
866
            self._tables
867
            / "ctdchemicalgene"
868
            // list(keys.keys())
869
            / list(keys.values())
870
            // Flatmap.construct(ChemicalGeneInteraction)
871
        ).to_set
872
873
    @property
874
    def drugbank_interactions(self) -> FrozenSet[DrugbankInteraction]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
875
        keys = {
876
            "gid": (lambda f: None if f is None else str(int(f))),
877
            "genesymbol": Codes.GenecardSymbol.of,
878
            "drugaction": Mapx.req_is(str, nullable=True),
879
            "targetcomponentname": Mapx.req_is(str),
880
            "targettype": (lambda s: DrugbankTargetType[s.lower()]),
881
            "targetname": Mapx.req_is(str),
882
            "generalfunc": Mapx.req_is(str, nullable=True),
883
            "specificfunc": Mapx.req_is(str, nullable=True),
884
            "pmids": Mapx.split(",", nullable=True),
885
            "dois": Mapx.split("|", nullable=True),
886
        }
887
        return (
888
            self._tables
889
            / "drugbank"
890
            // list(keys.keys())
891
            / list(keys.values())
892
            // Flatmap.construct(DrugbankInteraction)
893
        ).to_set
894
895
    @property
896
    def drugbank_legal_groups(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
897
        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...
898
        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...
899
            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...
900
                q.add(y.strip())
901
        return frozenset(q)
902
903
    @property
904
    def drugbank_ddis(self) -> FrozenSet[DrugbankDdi]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
905
        keys = {
906
            "dbid2": Codes.DrugbankCompoundId,
907
            "cid2": Codes.PubchemCompoundId,
908
            "name": Mapx.req_is(str),
909
            "descr": Mapx.req_is(str),
910
        }
911
        return (
912
            self._tables
913
            / "drugbankddi"
914
            // list(keys.keys())
915
            / list(keys.values())
916
            // Flatmap.construct(DrugbankDdi)
917
        ).to_set
918
919
920
class BiologicalTestResults(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
921
    """ """
922
923
    @property
924
    def _whoami(self) -> str:
925
        return "Biological Test Results"
926
927
    @property
928
    def bioactivity(self) -> FrozenSet[Bioactivity]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
929
        keys = {
930
            "aid": Mapx.get_int,
931
            "aidtype": Mapx.req_is(str, nullable=False),
932
            "aidsrcname": Mapx.req_is(str, nullable=True),
933
            "aidname": Mapx.req_is(str, nullable=True),
934
            "aidmdate": Mapx.int_date(nullable=True),
935
            "geneid": Codes.GeneId.of_nullable,
936
            "taxid": Mapx.str_to(str, flex_type=True, nullable=True),
937
            "pmid": Codes.PubmedId.of_nullable,
938
            "activity": (lambda s: None if s is None else Activity[s.lower()]),
939
            "acname": Mapx.str_to(str, nullable=True),
940
            "acvalue": (lambda x: None if x is None else float(x)),
941
            "targetname": Mapx.req_is(str, nullable=True),
942
            "cmpdname": Mapx.req_is(str, nullable=False),
943
        }
944
        return (
945
            self._tables
946
            / "bioactivity"
947
            // list(keys.keys())
948
            / FilterFn(lambda lst: lst[11] is not None)
949
            / list(keys.values())
950
            // Flatmap.construct(Bioactivity)
951
        ).to_set
952
953
954
class Classification(PubchemMiniDataView):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
955
    """ """
956
957
    @property
958
    def _whoami(self) -> str:
959
        return "Classification"
960
961
    @property
962
    def mesh_tree(self) -> Sequence[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
963
        raise NotImplementedError()
964
965
    @property
966
    def chebi_tree(self) -> Sequence[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
967
        raise NotImplementedError()
968
969
    @property
970
    def atc_tree(self) -> FrozenSet[Sequence[str]]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
971
        raise NotImplementedError()
972
973
    @property
974
    def chemid(self) -> FrozenSet[Sequence[str]]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
975
        raise NotImplementedError()
976
977
    @property
978
    def g2p_tree(self) -> FrozenSet[Sequence[str]]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
979
        raise NotImplementedError()
980
981
    @property
982
    def chembl_tree(self) -> FrozenSet[Sequence[str]]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
983
        raise NotImplementedError()
984
985
    @property
986
    def cpdat_tree(self) -> FrozenSet[Sequence[str]]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
987
        raise NotImplementedError()
988
989
    @property
990
    def dea(self) -> FrozenSet[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
991
        raise NotImplementedError()
992
993
994
class PubchemData(PubchemDataView):
0 ignored issues
show
introduced by
Missing class docstring
Loading history...
995
    @property
996
    def name(self) -> Optional[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
997
        return self._data.get("record.RecordTitle")
998
999
    @property
1000
    def title_and_summary(self) -> TitleAndSummary:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1001
        return TitleAndSummary(self._data)
1002
1003
    @property
1004
    def names_and_identifiers(self) -> NamesAndIdentifiers:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1005
        return NamesAndIdentifiers(self._data)
1006
1007
    @property
1008
    def chemical_and_physical_properties(self) -> ChemicalAndPhysicalProperties:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1009
        return ChemicalAndPhysicalProperties(self._data)
1010
1011
    @property
1012
    def related_records(self) -> RelatedRecords:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1013
        return RelatedRecords(self._data)
1014
1015
    @property
1016
    def drug_and_medication_information(self) -> DrugAndMedicationInformation:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1017
        return DrugAndMedicationInformation(self._data)
1018
1019
    @property
1020
    def pharmacology_and_biochemistry(self) -> PharmacologyAndBiochemistry:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1021
        return PharmacologyAndBiochemistry(self._data)
1022
1023
    @property
1024
    def safety_and_hazards(self) -> SafetyAndHazards:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1025
        return SafetyAndHazards(self._data)
1026
1027
    @property
1028
    def toxicity(self) -> Toxicity:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1029
        return Toxicity(self._data)
1030
1031
    @property
1032
    def literature(self) -> Literature:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1033
        return Literature(self._data)
1034
1035
    @property
1036
    def associated_disorders_and_diseases(self) -> AssociatedDisordersAndDiseases:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1037
        return AssociatedDisordersAndDiseases(self._data)
1038
1039
    @property
1040
    def biomolecular_interactions_and_pathways(self) -> BiomolecularInteractionsAndPathways:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1041
        return BiomolecularInteractionsAndPathways(self._data)
1042
1043
    @property
1044
    def biological_test_results(self) -> BiologicalTestResults:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1045
        return BiologicalTestResults(self._data)
1046
1047
    @property
1048
    def classification(self) -> Classification:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1049
        return Classification(self._data)
1050
1051
    @property
1052
    def parent_or_none(self) -> Optional[int]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1053
        return self.related_records.parent
1054
1055
    @property
1056
    def parent_or_self(self) -> int:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
1057
        parent = self.related_records.parent
1058
        return self.cid if parent is None else parent
1059
1060
1061
__all__ = [
1062
    "PubchemData",
1063
    "TitleAndSummary",
1064
    "RelatedRecords",
1065
    "ChemicalAndPhysicalProperties",
1066
    "DrugAndMedicationInformation",
1067
    "PharmacologyAndBiochemistry",
1068
    "SafetyAndHazards",
1069
    "Toxicity",
1070
    "AssociatedDisordersAndDiseases",
1071
    "Literature",
1072
    "NamesAndIdentifiers",
1073
    "BiomolecularInteractionsAndPathways",
1074
    "Classification",
1075
]
1076