From accbefa6ff4c8f1712e8e30a7e2b93b924dae8a2 Mon Sep 17 00:00:00 2001
From: Yannick Ulrich <yannick.ulrich@psi.ch>
Date: Sun, 9 Feb 2020 11:31:05 +0100
Subject: [PATCH] 5: basic error tools in re #17

---
 pymule/__init__.py   |  2 ++
 pymule/errortools.py | 86 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 88 insertions(+)
 create mode 100644 pymule/errortools.py

diff --git a/pymule/__init__.py b/pymule/__init__.py
index 051ce74..2bbb715 100644
--- a/pymule/__init__.py
+++ b/pymule/__init__.py
@@ -2,3 +2,5 @@ import numpy as np
 import matplotlib.pyplot as plt
 
 from vegas import importvegas
+from errortools import mergenumbers, plusnumbers, dividenumbers, timesnumbers,\
+                       mergeplots, addplots, combineNplots, scaleplot
diff --git a/pymule/errortools.py b/pymule/errortools.py
new file mode 100644
index 0000000..528731b
--- /dev/null
+++ b/pymule/errortools.py
@@ -0,0 +1,86 @@
+import numpy as np
+
+
+def mergenumbers(values, quiet=False):
+    if type(values) == list:
+        values = np.array(values)
+
+    weight = sum(1 / values[:,1]**2)
+    value = sum(values[:,0] / values[:,1]**2 / weight)
+    chi = 1./len(values) * sum(
+        ((values[:,0]-value) / values[:,1])**2
+    )
+    ans = np.array([value, np.sqrt(1/weight)])
+
+    if not quiet:
+        print chi
+        return ans
+    else:
+        return chi, ans
+
+
+def plusnumbers(*args):
+    if len(args) == 1:
+        lst = np.array(args[0])
+    else:
+        lst = np.array(args)
+    return np.array([
+        sum(lst[:,0]),
+        np.sqrt(sum(lst[:,1]**2))
+    ])
+
+
+def dividenumbers(a, b):
+    return np.array([
+        a[0]/b[0],
+        np.sqrt((b[1]**2*a[0]**2)/b[0]**4 + a[1]**2/b[0]**2)
+    ])
+
+
+def timesnumbers(a, b):
+    return np.array([
+        a[0]*b[0],
+        np.sqrt(b[0]**2*a[1]**2 + a[0]**2*b[1]**2)
+    ])
+
+
+def mergeplots(ps, returnchi=False):
+    if type(ps) == list:
+        ps = np.array(ps)
+
+    with np.errstate(divide='ignore', invalid='ignore'):
+        w = sum(1/ps[:,:,2]**2)
+        out = np.zeros(ps[0].shape)
+        out[:,0] = ps[0,:,0]
+
+        out[:,1] = sum(ps[:,:,1]/ps[:,:,2]**2 / w)
+        out[:,2] = np.sqrt(1/w)
+
+        # if one bin is empty, the zero causes trouble
+        out[~np.isfinite(out)] = 0
+
+        chi = 1./(len(ps)-1)*sum((ps[:,:,1]-out[:,1])**2/ps[:,:,2]**2)
+        chi = np.column_stack((out[:,0], chi))
+        chi[~np.isfinite(chi)] = 0
+
+    if returnchi:
+        return out, chi
+    else:
+        return out
+
+
+def addplots(a, b, sa=1., sb=1.):
+    # There must be a better way of doing this
+    maskA = [False]*len(a)
+    maskB = [False]*len(b)
+    for ia in range(len(a)):
+        for ib in range(len(b)):
+            if abs(1-a[ia, 0] / b[ib, 0]) < 1e-15:
+                maskA[ia] = True
+                maskB[ib] = True
+
+    x = a[maskA, 0]
+    y = sa*a[maskA, 1] + sb*b[maskB, 1]
+    e = np.sqrt(sa**2 * a[maskA, 2]**2 + sb**2 * b[maskB, 2]**2)
+
+    return np.column_stack((x, y, e))
-- 
GitLab