def dimensionality_decorator(func): def decorated(self, *args): if hasattr(self[0], "__len__"): return Array([func(s_, *args) for s_ in self]) else: return Array(func(self, *args)) return decorated def indexing_decorator(func): def decorated(self, v, *args): nn = len(shape(v)) if (nn ==1): if (type(v[0]) is bool): return Array([s_ for s_, v_ in zip(self,v) if v_]) else: return Array([self[v_] for v_ in v]) elif nn ==2: if type(v[0]) is bool: return Array([[s_ for s_, v_ in zip(self[n],v[n]) if v_ ] for n in range(nn)]) else: ret = func(self, v, *args) if hasattr(ret, "__len__"): return Array(ret) else: return ret return decorated class Array(list): def __init__(self, data): super(Array, self).__init__(data) self.getint = super(Array, self).__getitem__ @dimensionality_decorator def __add__(self, v): return add(self, v) @dimensionality_decorator def __sub__(self, v): return sub(self, v) @dimensionality_decorator def __mul__(self, v): return mul(self, v) @dimensionality_decorator def __div__(self, v): return div(self, v) @dimensionality_decorator def interpolate(self, num): return interpolate(self, num) @dimensionality_decorator def __lt__(self, v): return lower_than(self, v) @dimensionality_decorator def __le__(self, v): return lower_equal(self, v) @dimensionality_decorator def __gt__(self, v): return greater_than(self, v) @dimensionality_decorator def __ge__(self, v): return greater_equal(self, v) @indexing_decorator def __getitem__(self, v): return super(Array, self).__getitem__(v) @property def shape(self): return shape(self) @property def abs(self): return arr_abs(self) @property def T(self): return Array(transpose(self)) ### math helper functions def shape(self): o = self s = [] while hasattr(o, "__len__"): s = s+[len(o)] o = o[0] return s def transpose(a): mm = len(a[0]) a_t = [[v[m] for v in a] for m in range(mm)] return a_t def arr_abs(a): n = a.shape if len(n)==1: a_abs = [abs(e) for e in a] elif len(n)==2: a_abs = [[abs(e) for e in v] for v in a] return Array(a_abs) def interpolate(v,points_per_interval, round_to=2): v_i=[[round(v[m]+1.*n/points_per_interval*(v[m+1]-v[m]), round_to) for n in range(points_per_interval)] for m in range(len(v)-1)] ret = [] for i in v_i: ret=ret+i ret=ret+[v[-1]] return ret def add(list1, v): if hasattr(v, "__len__"): return [l+v_ for l, v_ in zip(list1, v)] else: return [l+v for l in list1] def sub(list1, v): if hasattr(v, "__len__"): return [l-v_ for l, v_ in zip(list1, v)] else: return [l-v for l in list1] def mul(list1, v): if hasattr(v, "__len__"): return [l*v_ for l, v_ in zip(list1, v)] else: return [l*v for l in list1] def div(list1, v): if hasattr(v, "__len__"): return [1.*l/v_ for l, v_ in zip(list1, v)] else: return [1.*l/v for l in list1] def lower_than(self, v): if hasattr(v, "__len__"): return [v_>s_ for v_, s_ in zip(v, self)] else: return [v>s_ for s_ in self] def lower_equal(self, v): if hasattr(v, "__len__"): return [v_>=s_ for v_, s_ in zip(v, self)] else: return [v>=s_ for s_ in self] def greater_than(self, v): if hasattr(v, "__len__"): return [s_>v_ for v_, s_ in zip(v, self)] else: return [s_>v for s_ in self] def greater_equal(self, v): if hasattr(v, "__len__"): return [s_>=v_ for v_, s_ in zip(v, self)] else: return [s_>=v for s_ in self]