Source code for streng.common.math.numerical

"""
    .. uml::

        class lists_and_dicts_and_pandas_etc <<(M,#FF7700)>> {
        .. functions ..
        + area_under_curve(x, y, x_start, x_end)
        + xy_with_endpoints(x, y, x_start, x_end)
        + intersection(x1, y1, x2, y2)
        - _rect_inter_inner(x1, x2)
        - _rectangle_intersection_(x1,y1,x2,y2)
        }
"""

import numpy as np


[docs]def distribute_integers(oranges, plates): base, extra = divmod(oranges, plates) return [base + (i < extra) for i in range(plates)]
[docs]def area_under_curve(x, y, x_start, x_end): x_new, y_new = xy_with_endpoints(x, y, x_start, x_end) res = np.trapz(y=y_new, x=x_new) return res
[docs]def xy_with_endpoints(x, y, x_start, x_end): if x_start < x[0]: x_start = x[0] if x_end > x[-1]: x_end = x[-1] # Για την αρχή y_start = float(np.interp(x_start, x, y)) # Κρατώ μόνο τις τιμές μετά από το x_start _x = x[(x > x_start)] _y = y[len(y) - len(_x):len(y)] # Προσθέτω τα x, y της παρεμβολής _x = np.append(x_start, _x) _y = np.append(y_start, _y) # Για το τέλος y_end = float(np.interp(x_end, x, y)) # Κρατώ μόνο τις τιμές μέχρι μία πρίν από το x_end _x = _x[(_x < x_end)] _y = _y[0:len(_x)] # Προσθέτω τα x, y της παρεμβολής _x = np.append(_x, x_end) _y = np.append(_y, y_end) # Εναλλακτικά με παρεμβολή σε όλες τις τιμές των y...μάλλον όχι για καμπύλες με δοντάκια # ....μικρές διαφορές όμως # _x = x[(x >= x_start)] # print(_x) # print(y) # _x = _x[(_x <= x_end)] # _x = np.append(_x, x_end) # print(_x) # _y = np.interp(_x, x, y) return _x, _y
def _rect_inter_inner(x1, x2): n1 = x1.shape[0] - 1 n2 = x2.shape[0] - 1 X1 = np.c_[x1[:-1], x1[1:]] X2 = np.c_[x2[:-1], x2[1:]] S1 = np.tile(X1.min(axis=1), (n2, 1)).T S2 = np.tile(X2.max(axis=1), (n1, 1)) S3 = np.tile(X1.max(axis=1), (n2, 1)).T S4 = np.tile(X2.min(axis=1), (n1, 1)) return S1, S2, S3, S4 def _rectangle_intersection_(x1, y1, x2, y2): S1, S2, S3, S4 = _rect_inter_inner(x1, x2) S5, S6, S7, S8 = _rect_inter_inner(y1, y2) C1 = np.less_equal(S1, S2) C2 = np.greater_equal(S3, S4) C3 = np.less_equal(S5, S6) C4 = np.greater_equal(S7, S8) ii, jj = np.nonzero(C1 & C2 & C3 & C4) return ii, jj
[docs]def intersection(x1, y1, x2, y2): """Copied from https://github.com/sukhbinder/intersection INTERSECTIONS Intersections of curves. Computes the (x,y) locations where two curves intersect. The curves can be broken with NaNs or have vertical segments. .. usage: x,y=intersection(x1,y1,x2,y2) Example: a, b = 1, 2 phi = np.linspace(3, 10, 100) x1 = a*phi - b*np.sin(phi) y1 = a - b*np.cos(phi) x2=phi y2=np.sin(phi)+2 x,y=intersection(x1,y1,x2,y2) plt.plot(x1,y1,c='r') plt.plot(x2,y2,c='g') plt.plot(x,y,'*k') plt.show() """ ii, jj = _rectangle_intersection_(x1, y1, x2, y2) n = len(ii) dxy1 = np.diff(np.c_[x1, y1], axis=0) dxy2 = np.diff(np.c_[x2, y2], axis=0) T = np.zeros((4, n)) AA = np.zeros((4, 4, n)) AA[0:2, 2, :] = -1 AA[2:4, 3, :] = -1 AA[0::2, 0, :] = dxy1[ii, :].T AA[1::2, 1, :] = dxy2[jj, :].T BB = np.zeros((4, n)) BB[0, :] = -x1[ii].ravel() BB[1, :] = -x2[jj].ravel() BB[2, :] = -y1[ii].ravel() BB[3, :] = -y2[jj].ravel() for i in range(n): try: T[:, i] = np.linalg.solve(AA[:, :, i], BB[:, i]) except: T[:, i] = np.NaN in_range = (T[0, :] >= 0) & (T[1, :] >= 0) & (T[0, :] <= 1) & (T[1, :] <= 1) xy0 = T[2:, in_range] xy0 = xy0.T return xy0[:, 0], xy0[:, 1]