Пример #1
0
    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
Пример #2
0
    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