def ArrayRotation(self, bound, array, **kwargs): ''' bound: True | False For 1D/2D/3D array array[0,0,0] is the original point ax: axis-0 of array: array.shape[0] ay: axis-1 of array: array.shape[1] az: axis-2 of array: array.shape[2] ''' from jizhipy.Array import Invalid import numpy as np shape0 = array.shape r = max(shape0) * 2**0.5 / 2 + 2 for i in range(len(shape0)): d = int(r - shape0[i] / 2) if (i == 0): halfshape = (d, ) + shape0[1:] elif (i == 1): halfshape = (shape0[0], d, shape0[2]) elif (i == 2): halfshape = shape0[:-1] + (d, ) half = np.nan + np.zeros(halfshape) array = np.concatenate([half, array, half], i) shape = array.shape #---------------------------------------- xyzAfter = [array * 0. for i in range(3)] axis = 0 for xyz in xyzAfter: if (len(shape) >= 1 and axis == 0): for i in range(1, shape[0]): xyz[i] = i elif (len(shape) >= 1 and axis == 1): for i in range(1, shape[1]): xyz[:, i] = i elif (len(shape) >= 1 and axis == 2): for i in range(1, shape[2]): xyz[:, :, i] = i axis += 1 xyzBefore = self.xyzRotationPoint(xyzAfter, **kwargs) #---------------------------------------- xyzBefore = xyzBefore.astype(int) n = xyzBefore[-1] for i in range(-2, -len(shape) - 1, -1): n += xyzBefore[i] * np.prod(shape[:i + 1]) array = array.flatten(n.astype(int)).reshape(shape) #---------------------------------------- mask = Invalid(array, None).mask n = [] for i in range(len(shape)): s = range(len(shape)).remove(i) if (bound): tf = mask.prod(axis=s) else: tf = mask.sum(axis=s) n.append(np.arange(tf.size)[tf > 0]) for i in range(len(n)): if (i == 0): array = array[n[i]] elif (i == 1): array = array[:, n[i]] elif (i == 2): array = array[:, :, n[i]] return array
def Bins(self, array, nbins, weight=None, wmax2a=None, nsigma=None): ''' nbins: (1) ==list/ndarray with .size==3 ** nbins, bmin, bmax = bins nbins: number of bins bmin, bmax: min and max of bins, NOT use the whole bin (2) ==int_number: ** Then use weight and wmax2a Give the total number of the bins, in this case, x.size=bins+1, xc.size=bins nsigma: float | None When generate the bins, won't use the whole range of array, set nsigma, will use |array| <= nsigma*array.std() weight: ** Use this only when bins==int_number 'G?', 'K?' | None | ndarray with size=bins (1) ==None: each bin has the same weight => uniform bins (2) ==ndarray: give weights to each bins (3) =='G?': '?' should be an value, for example, 'G1', 'G2.3', 'G5.4', 'G12', use Gaussian weight, and obtain it from np.linspace(-?, +?, bins) =='K?': '?' should be an value, for example, 'K1', 'K2.3', 'K5.4', 'K12', use modified Bessel functions of the second kind, and obtain it from np.linspace(-?, +?, bins) wmax2a: Use it when weight is not None float | None (1) ==float: weight.max() corresponds to which bin, the bin which value wmax2a is in ''' import numpy as np from jizhipy.Basic import IsType from jizhipy.Array import Invalid, Asarray from jizhipy.Math import Gaussian #--------------------------------------------- array = Asarray(array) if (nsigma is not None): mean, sigma = array.mean(), array.std() array = array[(mean - nsigma * sigma <= array) * (array <= mean + nsigma * sigma)] amin, amax = array.min(), array.max() #--------------------------------------------- if (Asarray(nbins).size == 3): nbins, bmin, bmax = nbins else: bmin, bmax = amin, amax #--------------------------------------------- # First uniform bins bins = np.linspace(bmin, bmax, nbins + 1) bstep = bins[1] - bins[0] #--------------------------------------------- # weight if (weight is not None): if (IsType.isstr(weight)): w, v = str(weight[0]).lower(), abs(float(weight[1:])) if (v == 0): v = 1 x = np.linspace(-v, v, nbins) if (w == 'k'): import scipy.special as spsp weight = spsp.k0(abs(x)) weight = Invalid(weight) weight.data[weight.mask] = 2 * weight.max() else: # Gaussian weight = Gaussian.GaussianValue1(x, 0, 0.4) #-------------------- # wmax2a if (wmax2a is not None): nmax = int(round(np.where(weight == weight.max())[0].mean())) nb = abs(bins - wmax2a) nb = np.where(nb == nb.min())[0][0] for i in range(bins.size - 1): if (bins[i] <= wmax2a < bins[i + 1]): nb = i break d = abs(nmax - nb) if (nmax < nb): weight = np.append(weight[-d:], weight[:-d]) elif (nmax > nb): weight = np.append(weight[d:], weight[:d]) #-------------------- weight = weight[:nbins] if (weight.size < nbins): weight = np.concatenate([weight] + (nbins - weight.size) * [weight[-1:]]) weight = weight.max() - weight + weight.min() weight /= weight.sum() weight = weight.cumsum() #-------------------- c = bins[0] + (bmax - bmin) * weight bins[1:-1] = c[:-1] #-------------------- bins = list(bins) n = 1 while (n < len(bins)): if (bins[n] - bins[n - 1] < bstep / 20.): bins = bins[:n] + bins[n + 1:] else: n += 1 bins = Asarray(bins) #--------------------------------------------- return bins