File: test_IsoSpecPy.py

package info (click to toggle)
isospec 2.3.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 12,476 kB
  • sloc: cpp: 9,530; python: 2,095; makefile: 180; ansic: 100; sh: 88
file content (161 lines) | stat: -rw-r--r-- 6,344 bytes parent folder | download
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
import sys
import IsoSpecPy
from math import exp, log

def sprint(s):
    sys.stdout.write(str(s))
    sys.stdout.flush()


silentish_run = False

if len(sys.argv) < 2:
    try:
        import OldIsoSpecPy
    except ImportError:
        print("This test compares the results of installed IsoSpec with IsoSpec version 1.0.7, installed as OldIsoSpecPy")
        print("You must install it, using:")
        print("pip install OldIsoSpecPy --index-url https://test.pypi.org/simple/")
        print("Or run only the new algo: python " + sys.argv[0] + " True")
        sys.exit(1)
else:
    print("Running only new algo...")
    silentish_run = True

# Correctness tests comparing IsoSpecPy 1.0.7 and HEAD. The trouble here is that due to slightly different way things are calculated
# we get different rounding errors, and therefore slightly different results - and that's OK. The function kinda_like reflects that
# - but is still WAAAY too strict. Often we can justifiably get different configurations, or different counts of configurations...

molecules = "H2O1 C100 P1 P100 C1 H10C10O10N10S5 Se1 Se10 Sn1 Sn4 Sn4C1 C2H6O1 C1000 C520H817N139O147S8 C1H1O2N2Se1Sn1P1 P1C1Sn1 Se5 Sn5 Se50 Sn15 Se2Sn2C2O2N2S2B2He2U2Na2Cl2".split()
import platform
if platform.python_implementation() != "CPython":
    molecules = molecules[:5]  # limit test size on non-CPython implementations

parameters = list(map(float, "0.0 0.1 0.5 0.01 0.9 0.99 0.01 0.0001 0.999 0.362 0.852348".split()))

def kinda_like(o1, o2):
    if type(o1) in (list, tuple) and type(o2) in (list, tuple) :
        assert len(o1) == len(o2)
        assert all(kinda_like(oo1, oo2) for oo1, oo2 in zip(o1, o2))
    if type(o1) == type(o2) == float:
        assert o1*o2 >= 0.0 # same sign check
        assert abs(o1*0.99)-0.000001 <= abs(o2) <= abs(o1*1.01)+0.000001
    return True

def sort_confs(confs):
    if len(confs[0]) == 0:
        return confs
    assert len(set(tuple(x) for x in confs[2])) == len(confs[2])
    l = list(zip(*confs))
    l.sort(key = lambda x: -x[1])

    return ([x[0] for x in l], [x[1] for x in l], [x[2] for x in l])

def confs_from_ordered_generator(formula, target_prob):
    ret = ([], [], [])
    prob = 0.0
    for conf in IsoSpecPy.IsoOrderedGenerator(formula=formula, get_confs=True):
        conf = (conf[0], log(conf[1]), conf[2])
        if prob >= target_prob and target_prob < 1.0:
            return ret
        ret[0].append(conf[0])
        prob += exp(conf[1])
        ret[1].append(conf[1])
        ret[2].append([item for sublist in conf[2] for item in sublist])
    return ret

def confs_from_layered_generator(formula, target_prob):
    ret = ([], [], [])
    for conf in IsoSpecPy.IsoLayered(formula=formula, prob_to_cover = target_prob, get_confs=True, get_minimal_pset=True):
        conf = (conf[0], log(conf[1]), conf[2])
        ret[0].append(conf[0])
        ret[1].append(conf[1])
        ret[2].append([item for sublist in conf[2] for item in sublist])

    return sort_confs(ret)

def confs_from_threshold_generator(formula, target_prob):
    ret = ([], [], [])
    for conf in IsoSpecPy.IsoThresholdGenerator(formula=formula, threshold = target_prob, absolute = True, get_confs=True):
        conf = (conf[0], log(conf[1]), conf[2])
        ret[0].append(conf[0])
        ret[1].append(conf[1])
        ret[2].append([item for sublist in conf[2] for item in sublist])

    return sort_confs(ret)

def confs_from_threshold(formula, target_prob):
    ret = ([], [], [])
    for conf in IsoSpecPy.IsoThreshold(formula=formula, threshold = target_prob, absolute = True, get_confs=True):
        conf = (conf[0], log(conf[1]), conf[2])
        ret[0].append(conf[0])
        ret[1].append(conf[1])
        ret[2].append([item for sublist in conf[2] for item in sublist])

    return sort_confs(ret)



def test_zeroprob_assert():
    is_ok = False
    try:
        i = IsoSpecPy.IsoThreshold(0.1, atomCounts = [100], isotopeMasses = [[1.0, 2.0, 3.0]], isotopeProbabilities = [[0.0, 0.6, 0.4]])
        for x in i:
            print(x)
    except ValueError:
        is_ok = True
    assert is_ok



def check_mol_param(molecule, parameter):
        total_confs = 0
        if not silentish_run:
            sprint("{} {}... ".format(molecule, parameter))
            old_ordered = OldIsoSpecPy.IsoSpecPy.IsoSpec.IsoFromFormula(molecule, parameter, method="ordered").getConfs()
            sprint(len(old_ordered[0]))
        new_ordered = confs_from_ordered_generator(molecule, parameter)
        total_confs += len(new_ordered[0])
        if not silentish_run: assert kinda_like(new_ordered, old_ordered)
        new_layered = confs_from_layered_generator(molecule, parameter)
        total_confs += len(new_layered[0])
        if not silentish_run: assert kinda_like(new_layered, new_ordered)
        if len(new_ordered[1]) > 0:
            new_threshold = exp(new_ordered[1][-1]-0.00000001)
        else:
            new_threshold = 1.1
        new_threshold_res = confs_from_threshold_generator(molecule, new_threshold)
        total_confs += len(new_threshold_res[0])
        if not silentish_run:
            assert kinda_like(new_ordered, new_threshold_res)
            assert kinda_like(new_threshold_res, confs_from_threshold(molecule, new_threshold))

        if parameter > 0:
            if not silentish_run: sprint(" thresholded: ")
            new_thr_r = confs_from_threshold_generator(molecule, parameter)
            if not silentish_run:
                sprint(len(new_thr_r[0]))
                old_thr_r = sort_confs(OldIsoSpecPy.IsoSpecPy.IsoSpec.IsoFromFormula(molecule, parameter, method="threshold_absolute").getConfs())
                assert kinda_like(new_thr_r, old_thr_r)

        if not silentish_run:
            print("... OK!")
        return total_confs

try:
    import pytest
    @pytest.mark.parametrize("molecule", molecules)
    @pytest.mark.parametrize("parameter", parameters)
    def test_mol_param(molecule, parameter):
        check_mol_param(molecule, parameter)
except ImportError:
    test_mol_param = check_mol_param


if __name__ == "__main__":
    test_zeroprob_assert()
    total_confs = 0
    for molecule in molecules:
        for parameter in parameters:
            total_confs += check_mol_param(molecule, parameter)
    sprint("Total confs: " + str(total_confs) + "\n")