File size: 2,469 Bytes
83db774
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
from __future__ import annotations

import sys
from pathlib import Path


sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "scripts"))
import build_goodscents_odor_source_v11 as source  # noqa: E402


def test_build_rows_requires_valid_unique_exact_cas():
    opl = [
        {"TGSC ID": "one", "CAS Number": "100-52-7"},
        {"TGSC ID": "ambiguous", "CAS Number": "100-52-7"},
        {"TGSC ID": "ambiguous", "CAS Number": "100-51-6"},
        {"TGSC ID": "bad", "CAS Number": "100-52-8"},
        {"TGSC ID": "structure", "CAS Number": "71-43-2", "CID": "241"},
    ]
    odor = [
        {"TGSC ID": "one", "Description": "sweet almond", "Source": "TGSC"},
        {"TGSC ID": "ambiguous", "Description": "woody"},
        {"TGSC ID": "bad", "Description": "fruity"},
        {"TGSC ID": "structure", "Description": "aromatic"},
    ]
    molecules = [{"CID": "241", "IsomericSMILES": "c1ccccc1"}]
    profiles = [
        {"cas": "100-52-7", "smiles": "O=Cc1ccccc1"},
        {"cas": "100-51-6", "smiles": "OCc1ccccc1"},
        {"cas": "100-52-8", "smiles": ""},
        {"cas": "SMILES:c1ccccc1", "smiles": "c1ccccc1"},
    ]
    rows, report = source.build_rows(opl, odor, molecules, profiles)
    assert [(row["cas"], row["text"]) for row in rows] == [
        ("100-52-7", "sweet almond"),
        ("SMILES:c1ccccc1", "aromatic"),
    ]
    assert report == {
        "profiles_with_rows": 2,
        "description_rows": 2,
        "ambiguous_tgsc_ids_rejected": 1,
        "exact_structure_profiles": 1,
        "ambiguous_structure_profiles_rejected": 0,
        "identity_policy": (
            "exact CAS first; otherwise exact full InChIKey with one profile and one source CAS; "
            "ambiguous structures rejected"
        ),
    }


def test_build_rows_rejects_structure_join_with_multiple_source_cas():
    opl = [
        {"TGSC ID": "a", "CAS Number": "71-43-2", "CID": "241"},
        {"TGSC ID": "b", "CAS Number": "108-88-3", "CID": "999"},
    ]
    odor = [
        {"TGSC ID": "a", "Description": "aromatic"},
        {"TGSC ID": "b", "Description": "sweet"},
    ]
    molecules = [
        {"CID": "241", "IsomericSMILES": "c1ccccc1"},
        {"CID": "999", "IsomericSMILES": "c1ccccc1"},
    ]
    profiles = [{"cas": "SMILES:c1ccccc1", "smiles": "c1ccccc1"}]
    rows, report = source.build_rows(opl, odor, molecules, profiles)
    assert rows == []
    assert report["ambiguous_structure_profiles_rejected"] == 1