Example #1
0
def make_square_stop_origins(side_length: float,
                             num_rays: int,
                             x_axis: int = -2,
                             y_axis: int = -1):
    ox = mathx.reshape_vec(np.linspace(-0.5, 0.5, num_rays),
                           x_axis) * side_length
    oy = mathx.reshape_vec(np.linspace(-0.5, 0.5, num_rays),
                           y_axis) * side_length
    return ox, oy
Example #2
0
    def transform_to_arb(self, E, R, k, axis=None, deriv=0):
        """

        Args:
            E (array): input vector, with r running along axis
            R (scalar): input aperture
            k (array): transverse k to which to transform
            axis (int): axis along which r runs in E.
            deriv (int): derivative order to calculate

        Returns:

        """
        if axis == None:
            axis = last_axis(E)
        k = np.asarray(k)
        E = expand_dims(E, axis)
        # Now E.shape[axis]=1 and r runs along axis-1.
        if axis > -k.ndim:
            # If k spans axis, then to keep all dimensions aligned need to shift leading axes of k too. New axis in k
            # should be new r axis.
            k = expand_dims(k, axis - 1)
        K = self.conj_R(R)
        j = mathx.reshape_vec(self.j, axis - 1)
        J1sqd = mathx.reshape_vec(self.J1sqd, axis - 1)

        def calc_Et(E, k):
            T = 2 * jvp(0, k * j / K, deriv) * ((j / K)**deriv / J1sqd) / K**2
            Et = (T * E).sum(axis - 1)
            return (Et, )

        # shape returns 32 bit int, need 64 bit to avoid overflow
        working_size = np.prod(
            np.array(mathx.broadcasted_shape(E.shape, k.shape),
                     dtype=np.int64))
        # TODO better available memory test
        size_threshold = 1e7
        if working_size > size_threshold and k.ndim > 0:
            chunk_axis = -k.ndim + np.argmax(k.shape)
            num_chunks = working_size / size_threshold
            chunk_length = int(math.ceil(k.shape[chunk_axis] / num_chunks))
            str = 'QDHT working size %g exceeds %g. Making %d chunks of length %d along axis %d ...'
            logger.info(3, str, working_size, size_threshold, num_chunks,
                        chunk_length, chunk_axis)
            # BUG! If E runs along chunk_axis too, then this fails.
            # Et=mathx.eval_array_fun_chunked(calc_Et_from_k,k,chunk_axis,chunk_length)
            # Et=mathx.iterate_broadcast_op(calc_Et,(E,k),chunk_axis,chunk_length)
            Et = mathx.eval_iterated(calc_Et, (E, k),
                                     iter_dims=(chunk_axis, ),
                                     keep_iter_dims=True,
                                     iter_chunk_size=chunk_length,
                                     print_progress=logger.level < 3)[0]
            logger.info(3, '... QDHT done')
            return Et
        else:
            return calc_Et(E, k)[0]
Example #3
0
def make_square_field_vectors(side_length: float,
                              num_spots: int,
                              x_axis: int = -2,
                              y_axis: int = -1):
    # Generate square grid of plane wave vectors along -1 and -2 axes.
    thetax = mathx.reshape_vec(np.linspace(-0.5, 0.5, num_spots),
                               x_axis) * side_length
    thetay = mathx.reshape_vec(np.linspace(-0.5, 0.5, num_spots),
                               y_axis) * side_length
    vx = np.sin(thetax)
    vy = np.sin(thetay)
    vz = (1 - vx**2 - vy**2)**0.5
    return (thetax, thetay), (vx, vy, vz)
Example #4
0
def pad(v, b, a, axis=None):
    if axis is None:
        axis = get_axis(v)
    l = np.shape(v)[axis]
    vp = mathx.reshape_vec(np.arange(-b, l + a), axis) * delta(v, axis) + zero(
        v, axis)
    return vp
Example #5
0
def interp1d_to_uniform(x, y, axis=None):
    """Resample array to uniformly sampled axis.

    Has some limitations due to use of scipy interp1d.

    Args:
        x (vector): independent variable
        y (array): dependent variable, must broadcast with x
        axis (int): axis along which to resample

    Returns:
        xu: uniformly spaced independent variable
        yu: dependent resampled at xu
    """
    x = np.asarray(x)
    y = np.asarray(y)
    if axis is None:
        axis = mathx.vector_dim(x)
    num = x.shape[axis]
    mn = x.min(axis, keepdims=True)
    mx = x.max(axis, keepdims=True)
    # Limitation of scipy interp1d
    x = x.squeeze()
    mn = mn.squeeze()
    mx = mx.squeeze()
    assert x.ndim == 1
    xu = np.arange(num) / (num - 1) * (mx - mn) + mn
    yu = scipy.interpolate.interp1d(x.squeeze(),
                                    y,
                                    axis=axis,
                                    bounds_error=False)(xu)
    return mathx.reshape_vec(xu, axis), yu
Example #6
0
    def scale_fac(self, R=1, dim=-1):
        """Parseval's theorem scaling vector.

        The scaling vector s_n such that
        sum_{n=0}^{N-1} abs(f(r_n))**2 s_n
        equals the norm-squared of the signal f(r_n), where r_n is given by QDHT.points.
        """
        return 4 * pi * R**2 / reshape_vec(self.j_Np1**2 * self.J1sqd, dim)
Example #7
0
def array(**kwargs):
    """
    Args:
        axis: dimension
        zero: first element
        last: last element
        delta: spacing
        N: number of samples
    
    Returns:
        numpy.ndarray
    """
    axis = kwargs.pop('axis', -1)
    if 'vector' in kwargs:
        a = mathx.reshape_vec(kwargs.pop('vector'), axis)
    elif 'array' in kwargs:
        a = kwargs.pop('array')
    else:
        if all(k in kwargs for k in ('zero', 'N', 'delta')):
            zero = np.array(kwargs.pop('zero'))
            N = kwargs.pop('N')
            delta = np.array(kwargs.pop('delta'))
        elif all(k in kwargs for k in ('zero', 'last', 'delta')):
            zero = np.array(kwargs.pop('zero'))
            last = np.array(kwargs.pop('last'))
            delta = kwargs.pop('delta')
            N = set(round((last - zero) / delta).flatten().tolist())
            if len(N) != 1:
                raise ValueError('N must be same for all sub-vectors')
            N = N.pop()
        elif all(k in kwargs for k in ('zero', 'N', 'last')):
            zero = np.array(kwargs.pop('zero', 0))
            last = np.array(kwargs.pop('last'))
            N = kwargs.pop('N')
            delta = (last - zero) / (N - 1)
        else:
            raise ValueError('Unknown argument combination ' +
                             str(list(kwargs.keys())))
        a = zero + mathx.reshape_vec(np.arange(N), axis) * delta
    if len(kwargs) > 0:
        raise ValueError('Unused arguments ' + str(list(kwargs.keys())))
    return a
Example #8
0
def pad_sampled(v, f, b, a, axis=None, value=0):
    f = np.asarray(f)
    if axis is None:
        axis = get_axis(v)
    shape_a = list(f.shape)
    shape_a[axis] = a
    shape_b = list(f.shape)
    shape_b[axis] = b
    fp = np.concatenate(
        (value * np.ones(shape_b), f, value * np.ones(shape_a)), axis)
    vp = mathx.reshape_vec(np.arange(-b, f.shape[axis] + a), axis) * delta(
        v, axis) + zero(v, axis)
    return vp, fp
Example #9
0
def conj_axis(t, offset=0, offset_type='middle', axis=None):
    if axis is None:
        axis = mx.last_axis(t)
    Dt = np.diff(np.take(t, [0, 1], axis), axis=axis)
    N = t.shape[axis]
    Dw = 2 * pi / (N * Dt)
    if offset_type == 'middle':
        n_o = N / 2
    elif offset_type == 'middle_index':
        n_o = int(N / 2)
    elif offset_type == 'start':
        n_o = 0
    elif offset_type == 'end':
        n_o = N - 1
    else:
        raise ValueError('Unknown offset_type ', offset_type)
    n = mx.reshape_vec(np.arange(N), axis) - n_o
    return offset + n * Dw
Example #10
0
    def test_arb_trans():
        ##
        ht = QDHT(64)
        R = 5
        r = ht.points(R)
        k = ht.conj_points(R)
        Er = exp(-r**2 / 2)
        Ek = ht.transform(Er, R)
        Eka = ht.transform_to_arb(Er, R, k)
        assert np.allclose(Ek, Eka)
        Eka = ht.transform_to_arb(Er, R, mathx.reshape_vec(k, -3))
        assert np.allclose(Ek, Eka.squeeze()) and Eka.shape == (64, 1, 1)

        R = ht.j_Np1**0.5
        r = ht.points(R)
        k = ht.conj_points(R)
        Er = exp(-r**2 / 2)
        Erp = -r * exp(-r**2 / 2)
        plt = pg.plot(r, Erp, pen=pg.mkPen('b', width=10))
        plt.plot(k, ht.transform_to_arb(Er, R, k, deriv=1), pen='r')
Example #11
0
def test_arb_trans():
    ##
    ht=QDHT(64)
    R=5
    r=ht.points(R)
    k=ht.conj_points(R)
    Er=np.exp(-r**2/2)
    Ek=ht.transform(Er,R)
    Eka=ht.transform_to_arb(Er,R,k)
    assert np.allclose(Ek,Eka)
    Eka=ht.transform_to_arb(Er,R,mathx.reshape_vec(k,-3))
    assert np.allclose(Ek,Eka.squeeze()) and Eka.shape==(64,1,1)
    Era=ht.inv_transform_to_arb(Ek,R,r)
    assert np.allclose(Er,Era)
    
    R=ht.j_Np1**0.5 # for same r & k axes
    r=ht.points(R)
    k=ht.conj_points(R)
    Er=np.exp(-r**2/2)
    Erp=-r*np.exp(-r**2/2)
    Ekp=ht.transform_to_arb(Er,R,k,deriv=1)
    assert np.allclose(Erp,Ekp)  
Example #12
0
 def __init__(self, sign=-1, axis=None, **kwargs):
     """N is number of samples, x_0 is first x sample, Dx is x spacing, i.e. x_n=x_0+n*Dx,
     X is N*Dx. x_m is the middle = x_0+(N-1)*Dx/2. All of these are defined
      similarly for k. Can specify any combination of them with sufficient information
      to define the sampling axes. If unspecified, x_0 and k_0 default to 0."""
     for key in kwargs.keys():
         if key not in ('N', 'x', 'x_0', 'Dx', 'x_m', 'x_middle_ind', 'X',
                        'k', 'k_0', 'Dk', 'k_m', 'k_middle_ind', 'K'):
             raise ValueError('Unknown argument %s' % key)
     self.sign = sign
     if axis is not None:
         if axis >= 0:
             raise TypeError(
                 'axis must be negative (because numpy broadcasts starting from trailing dimensions)'
             )
         self.axis = axis
     elif 'x' in kwargs:
         self.axis = mx.last_axis(kwargs['x'])
     elif 'k' in kwargs:
         self.axis = mx.last_axis(kwargs['k'])
     else:
         self.axis = -1
     # Determine N
     if 'N' in kwargs:
         self.N = kwargs['N']
     elif 'x' in kwargs:
         self.N = kwargs['x'].shape[self.axis]
     elif 'k' in kwargs:
         self.N = kwargs['k'].shape[self.axis]
     elif 'Dx' in kwargs and 'X' in kwargs:
         self.N = math.ceil(kwargs['X'] / kwargs['Dx'])
     elif 'Dk' in kwargs and 'K' in kwargs:
         self.N = math.ceil(kwargs['K'] / kwargs['Dk'])
     elif 'Dx' in kwargs and 'Dk' in kwargs:
         self.N = math.ceil(2 * pi / (kwargs['Dx'] * kwargs['Dk']))
     elif 'X' in kwargs and 'K' in kwargs:
         self.N = math.ceil(kwargs['X'] * kwargs['K'] / (2 * pi))
     else:
         raise ValueError('N undetermined by arguments')
     self.N = np.unique(self.N)
     if len(self.N) > 1:
         raise ValueError('Only one N allowed')
     self.N = self.N[0]
     # Determine Dx
     Dx = None
     if 'x' in kwargs:
         Dx = np.diff(np.take(kwargs['x'], [0, 1], self.axis),
                      axis=self.axis)
     elif 'Dx' in kwargs:
         Dx = kwargs['Dx']
     elif 'X' in kwargs:
         Dx = kwargs['X'] / self.N
     if Dx is not None:
         self.Dx = np.array(Dx)
         self.Dk = 2 * pi / (self.N * self.Dx)
     else:
         if 'k' in kwargs:
             Dk = np.diff(np.take(kwargs['k'], [0, 1], axis=self.axis),
                          axis=self.axis)
         elif 'Dk' in kwargs:
             Dk = kwargs['Dk']
         elif 'K' in kwargs:
             Dk = kwargs['K'] / self.N
         else:
             raise ValueError('Dx and Dk undetermined by arguments')
         self.Dk = np.asarray(Dk)
         self.Dx = 2 * pi / (self.N * self.Dk)
     # Determine x_0
     if 'x' in kwargs:
         x_0 = np.take(kwargs['x'], [0], axis=self.axis)
     elif 'x_0' in kwargs:
         x_0 = kwargs['x_0']
     elif 'x_m' in kwargs:
         x_0 = kwargs['x_m'] - (self.N - 1) * self.Dx / 2
     elif 'x_middle_ind' in kwargs:
         x_0 = kwargs['x_middle_ind'] - round(self.N / 2) * self.Dx
     else:
         x_0 = 0
     self.x_0 = np.asarray(x_0)
     # Determine k_0
     if 'k' in kwargs:
         k_0 = np.take(kwargs['k'], [0], axis=self.axis)
     elif 'k_0' in kwargs:
         k_0 = kwargs['k_0']
     elif 'k_m' in kwargs:
         k_0 = kwargs['k_m'] - (self.N - 1) * self.Dk / 2
     elif 'k_middle_ind' in kwargs:
         k_0 = kwargs['k_middle_ind'] - round(self.N / 2) * self.Dk
     else:
         k_0 = 0
     self.k_0 = np.asarray(k_0)
     # Setup arrays
     n = mx.reshape_vec(np.arange(self.N), self.axis)
     self.x = self.x_0 + self.Dx * n
     self.k = self.k_0 + self.Dk * n
     self.X = self.Dx * self.N
     self.K = self.Dk * self.N
     self.x_fac = np.exp(1j * self.sign * self.k_0 * self.Dx * n)
     self.k_fac = np.exp(1j * self.sign * self.x_0 * self.Dk * n)
     self.fac = np.exp(1j * self.sign * self.x_0 * self.k_0) * sqrt(
         self.N / (2 * pi))
Example #13
0
def polar_grid(Ntheta, Nphi, dim_theta=-2, dim_phi=-1):
    theta = np.pi*(mathx.reshape_vec(np.arange(Ntheta), dim_theta) + 1)/(Ntheta + 1)
    phi = np.pi*2*mathx.reshape_vec(np.arange(Nphi), dim_phi)/Nphi
    return theta, phi
Example #14
0
 def points(self, R=1, dim=-1):
     """Compute r sampling points."""
     return reshape_vec(self.j, dim) / self.j_Np1 * R