blob: 01b0cec9c790c316a663bdda8102e455f7b76b10 [file] [log] [blame]
koder aka kdanilov6c491062015-04-09 22:33:13 +03001import math
2import itertools
Ved-vampir03166442015-04-10 17:28:23 +03003from numpy import array, linalg
koder aka kdanilov6c491062015-04-09 22:33:13 +03004from numpy.polynomial.chebyshev import chebfit, chebval
Ved-vampir03166442015-04-10 17:28:23 +03005from scipy.optimize import leastsq
koder aka kdanilov6c491062015-04-09 22:33:13 +03006
7
8def med_dev(vals):
9 med = sum(vals) / len(vals)
10 dev = ((sum(abs(med - i) ** 2.0 for i in vals) / len(vals)) ** 0.5)
11 return med, dev
12
13
14def round_deviation(med_dev):
15 med, dev = med_dev
16
17 if dev < 1E-7:
18 return med_dev
19
20 dev_div = 10.0 ** (math.floor(math.log10(dev)) - 1)
21 dev = int(dev / dev_div) * dev_div
22 med = int(med / dev_div) * dev_div
23 return (type(med_dev[0])(med),
24 type(med_dev[1])(dev))
25
26
27def groupby_globally(data, key_func):
28 grouped = {}
29 grouped_iter = itertools.groupby(data, key_func)
30
31 for (bs, cache_tp, act, conc), curr_data_it in grouped_iter:
32 key = (bs, cache_tp, act, conc)
33 grouped.setdefault(key, []).extend(curr_data_it)
34
35 return grouped
36
37
38def approximate_curve(x, y, xnew, curved_coef):
39 """returns ynew - y values of some curve approximation"""
40 return chebval(xnew, chebfit(x, y, curved_coef))
41
42
43def approximate_line(x, y, xnew, relative_dist=False):
Ved-vampir03166442015-04-10 17:28:23 +030044 """ x, y - test data, xnew - dots, where we want find approximation
45 if not relative_dist distance = y - newy
46 returns ynew - y values of linear approximation"""
koder aka kdanilov66839a92015-04-11 13:22:31 +030047
Ved-vampir03166442015-04-10 17:28:23 +030048 # convert to numpy.array (don't work without it)
49 ox = array(x)
50 oy = array(y)
koder aka kdanilov66839a92015-04-11 13:22:31 +030051
Ved-vampir03166442015-04-10 17:28:23 +030052 # set approximation function
koder aka kdanilov66839a92015-04-11 13:22:31 +030053 def func_line(tpl, x):
54 return tpl[0] * x + tpl[1]
55
56 def error_func_rel(tpl, x, y):
57 return 1.0 - y / func_line(tpl, x)
58
59 def error_func_abs(tpl, x, y):
60 return y - func_line(tpl, x)
61
Ved-vampir03166442015-04-10 17:28:23 +030062 # choose distance mode
koder aka kdanilov66839a92015-04-11 13:22:31 +030063 error_func = error_func_rel if relative_dist else error_func_abs
64
65 tpl_initial = tuple(linalg.solve([[ox[0], 1.0], [ox[1], 1.0]],
66 oy[:2]))
67
Ved-vampir03166442015-04-10 17:28:23 +030068 # find line
koder aka kdanilov66839a92015-04-11 13:22:31 +030069 tpl_final, success = leastsq(error_func,
70 tpl_initial[:],
71 args=(ox, oy))
72
Ved-vampir03166442015-04-10 17:28:23 +030073 # if error
74 if success not in range(1, 5):
75 raise ValueError("No line for this dots")
koder aka kdanilov66839a92015-04-11 13:22:31 +030076
Ved-vampir03166442015-04-10 17:28:23 +030077 # return new dots
koder aka kdanilov66839a92015-04-11 13:22:31 +030078 return func_line(tpl_final, array(xnew))
koder aka kdanilov6c491062015-04-09 22:33:13 +030079
80
81def difference(y, ynew):
82 """returns average and maximum relative and
Ved-vampir03166442015-04-10 17:28:23 +030083 absolute differences between y and ynew
84 result may contain None values for y = 0
85 return value - tuple:
86 [(abs dif, rel dif) * len(y)],
87 (abs average, abs max),
88 (rel average, rel max)"""
koder aka kdanilov66839a92015-04-11 13:22:31 +030089
90 abs_dlist = []
91 rel_dlist = []
92
Ved-vampir03166442015-04-10 17:28:23 +030093 for y1, y2 in zip(y, ynew):
94 # absolute
koder aka kdanilov66839a92015-04-11 13:22:31 +030095 abs_dlist.append(y1 - y2)
Ved-vampir03166442015-04-10 17:28:23 +030096
koder aka kdanilov66839a92015-04-11 13:22:31 +030097 if y1 > 1E-6:
98 rel_dlist.append(abs(abs_dlist[-1] / y1))
99 else:
100 raise ZeroDivisionError("{0!r} is too small".format(y1))
101
102 da_avg = sum(abs_dlist) / len(abs_dlist)
103 dr_avg = sum(rel_dlist) / len(rel_dlist)
104
105 return (zip(abs_dlist, rel_dlist),
106 (da_avg, max(abs_dlist)), (dr_avg, max(rel_dlist))
107 )
koder aka kdanilov6c491062015-04-09 22:33:13 +0300108
109
110def calculate_distribution_properties(data):
111 """chi, etc"""
112
113
114def minimal_measurement_amount(data, max_diff, req_probability):
115 """
116 should returns amount of measurements to get results (avg and deviation)
117 with error less, that max_diff in at least req_probability% cases
118 """