示例#1
0
    def exact_polar(self, freqs, azimuths=None):
        '''Retrieves the MTF at the specified frequency-azimuth pairs

        Args:
            freqs (`iterable`): radial frequencies to retrieve MTF for.

            azimuths (`iterable`): corresponding azimuths to retrieve MTF for.

        Returns:
            list: MTF at the given points.

        '''
        self._make_interp_function()

        # handle user-unspecified azimuth
        if azimuths is None:
            if type(freqs) in (int, float):
                # single azimuth
                azimuths = 0
            else:
                azimuths = [0] * len(freqs)
        # handle single azimuth, multiple freqs
        elif type(azimuths) in (int, float):
            azimuths = [azimuths] * len(freqs)

        azimuths = np.radians(azimuths)
        # handle single value case
        if type(freqs) in (int, float):
            x, y = polar_to_cart(freqs, azimuths)
            return float(self.interpf((x, y), method='linear'))

        outs = []
        for freq, az in zip(freqs, azimuths):
            x, y = polar_to_cart(freq, az)
            outs.append(float(self.interpf((x, y), method='linear')))
        return outs
示例#2
0
def test_polar_to_cart(rho, phi):
    x, y = coordinates.polar_to_cart(rho, phi)
    assert np.allclose(x, rho * np.cos(phi))
    assert np.allclose(y, rho * np.sin(phi))
示例#3
0
def generate_collimated_ray_fan(nrays,
                                maxr,
                                z=0,
                                minr=None,
                                azimuth=90,
                                yangle=0,
                                xangle=0,
                                distribution='uniform',
                                aim_at=None):
    """Generate a 1D fan of rays.

    Colloquially, an extended field in Y for an object at inf is represented by a ray fan with yangle != 0.

    Parameters
    ----------
    nrays : int
        the number of rays in the fan
    maxr : float
        maximum radial value of the fan
    z : float
        z position for the ray fan
    minr : float, optional
        minimum radial value of the fan, -maxr if None
    azimuth: float
        angle in the XY plane, degrees.  0=X ray fan, 90=Y ray fan
    yangle : float
        propagation angle of the rays with respect to the Y axis, clockwise
    xangle : float
        propagation angle of the rays with respect to the X axis, clockwise
    distribution : str, {'uniform', 'random', 'cheby'}
        The distribution to use when placing the rays
        a uniform distribution has rays which are equally spaced from minr to maxr,
        random has rays randomly distributed in minr and maxr, while cheby has the
        Cheby-Gauss-Lobatto roots as its locations from minr to maxr
    aim_at : numpy.ndarray or float
        position [X,Y,Z] aim the rays such that the gut ray of the fan,
        when propagated in an open medium, hits (aim_at)

        if a float, interpreted as if x=0,y=0, z=aim_at

        This argument mimics ray aiming in commercial optical design software, and
        is used in conjunction with xangle/yangle to form off-axis ray bundles which
        properly go through the center of the stop

    Returns
    -------
    numpy.ndarray, numpy.ndarray
        "P" and "S" variables, positions and direction cosines of the rays

    """
    dtype = config.precision
    distribution = distribution.lower()
    if minr is None:
        minr = -maxr
    S = np.array([0, 0, 1], dtype=dtype)
    R = make_rotation_matrix((0, yangle, -xangle))
    S = np.matmul(R, S)
    # need to see a copy of S for each ray, -> add empty dim and broadcast
    S = S[np.newaxis, :]
    S = np.broadcast_to(S, (nrays, 3))

    # now generate the radial part of P
    if distribution == 'uniform':
        r = np.linspace(minr, maxr, nrays, dtype=dtype)
    elif distribution == 'random':
        r = np.random.uniform(low=minr, high=maxr, size=nrays).astype(dtype)

    t = np.asarray(np.radians(azimuth), dtype=dtype)
    t = np.broadcast_to(t, r.shape)
    x, y = polar_to_cart(r, t)
    z = np.array(z, dtype=x.dtype)
    z = np.broadcast_to(z, x.shape)
    xyz = np.stack([x, y, z], axis=1)
    return xyz, S