Esempio n. 1
0
def zernikeResidualSurfaceError(x, y, z_coef, r=50, eps=230e-6, lmbd=2.6e-3, verbose=False):
    """
    Computes the effect of the residual Zernike on the surface error.


    """

    # Simulate thermal deformation.
    # The Zernike polynomials is at the center of the map.
    x_mid = midPoint(x)
    y_mid = midPoint(y)
    z_sim = zernikePoly(x, y, x_mid, y_mid, coefficients=z_coef)
    z_sim[~radialMask(x,y,r)] = np.nan
    eps_z = np.nanstd(z_sim)
    if verbose:
        print("Residual surface error: {} microns".format(eps_z*1e6))

    # Compute surface error.
    eps_tot = np.sqrt(eps_z**2. + eps**2.)
    if verbose:
        print("Total surface error: {} microns".format(eps_tot*1e6))

    # Compute aperture efficiency.
    eta = lambda lmbd, eps: 0.71*np.exp(-np.power(4.*np.pi*eps/lmbd, 2.))
    eta_tot = eta(lmbd, eps_tot)
    if verbose:
        print("Aperture efficiency: {}".format(eta_tot))
        print("Change in aperture efficiency: {} %".format((eta(lmbd, eps) - eta_tot)/eta(lmbd, eps)*100.))

    return eps_tot, eta_tot, eta
Esempio n. 2
0
def zernikeCost(coeffs, x, y, z, w):
    """
    Cost funtion for the least squares problem.
    """

    zpoly = zernikePoly(x, y, midPoint(x), midPoint(y), coeffs)

    return w*(z.flatten() - zpoly.flatten())
Esempio n. 3
0
def zernikeJac(coeffs, x, y, z):
    """
    Jacobian of the cost function for the least squares problem.
    This does not work at the moment.
    """

    coeffs = np.ones_like(coeffs)
    coeffs[:2] = 0

    jac = np.zeros((len(z),len(coeffs)))

    for i in range(2,len(coeffs)):
        cis = np.zeros(36)
        cis[i] = 1.
        jac[i] = zernikePoly(x, y, midPoint(x), midPoint(y), cis)

    return jac
Esempio n. 4
0
def getZernikeCoeffsCycle(x, y, diff, nZern=36, fill=0):
    """
    """

    fl_fs = getZernikeCoeffs(diff.filled(fill)[::-1].T, 36, norm='active-surface')

    diff_sub = np.ma.copy(diff)
    fl_fs_sub = np.copy(fl_fs)
    it = 0
    while np.any(abs(fl_fs_sub[2:4]) > 50e-6):
        fl_fs_sub[2] *= -1.
        zpoly_ = zernikePoly(x, y, midPoint(x), midPoint(y), fl_fs_sub[0:4])
        diff_sub = diff_sub - zpoly_
        fl_fs_sub = getZernikeCoeffs(diff_sub.filled(fill)[::-1].T, 36, norm='active-surface')
        it += 1

    return fl_fs_sub, diff_sub
Esempio n. 5
0
def zernikeWLS(x, y, z, nZern, weights=None):
    """
    Use weighted least-squares to compute Zernike coefficients.
    """

    # Use WLS to determine the Zernike coefficients.
    if weights is None:
        weights = np.ones(z.shape)

    weights = np.ma.masked_invalid(weights)
    
    x_ = np.ma.masked_invalid(x)
    x_ -= midPoint(x)
    y_ = np.ma.masked_invalid(y)
    y_ -= midPoint(y)
    
    fl_wls = getZernikeCoeffsOLS(x_, y_, z, nZern, weights=weights)
    
    return fl_wls
Esempio n. 6
0
def maskXYZ(x,
            y,
            z,
            n=512,
            guess=[60., 0., 0., 0., 0., 0.],
            bounds=None,
            radialMask=True,
            maskRadius=40.,
            poly_order=2,
            **kwargs):
    """
    """

    xf = x[~np.isnan(z)]
    yf = y[~np.isnan(z)]
    zf = z[~np.isnan(z)]

    # Use masked arrays on the input data to avoid warnings.
    x = np.ma.masked_invalid(x)
    y = np.ma.masked_invalid(y)
    z = np.ma.masked_invalid(z)

    # Fit a parabola to the data.
    fitresult = fitLeicaData(xf, yf, zf, guess, bounds=bounds, weights=None)

    # Subtract the fitted parabola from the data.
    # The difference should be flat.
    c = fitresult.x
    zp = paraboloid(x, y, c[0])
    cor = np.hstack((-1 * c[1:4], c[4:6], 0))
    xrr, yrr, zrr = shiftRotateXYZ(x, y, z, cor)
    diff = zrr - zp

    if radialMask:
        xc = midPoint(xrr)
        yc = midPoint(yrr)
        mask = (((xrr - xc)**2. + (yrr - yc)**2.) < maskRadius**2.)
        mdiff = np.ma.masked_where(~mask, diff)
    else:
        mdiff = diff

    # Mask any pixels which deviate from the noise.
    # This should mask out retroreflectors, misaligned panels and sub-scans where the TLS moved due to wind.
    mcdiff = sigma_clip(mdiff)

    # Apply the mask to the original data and repeat once more.
    # In the end also fit a parabola to each row in the data, and mask outliers.
    # This allows to find more subtle features in the data.
    xf = np.ma.masked_where(mcdiff.mask, x)
    yf = np.ma.masked_where(mcdiff.mask, y)
    zf = np.ma.masked_where(mcdiff.mask, z)

    masked_fitresult = fitLeicaData(xf.compressed(),
                                    yf.compressed(),
                                    zf.compressed(),
                                    guess,
                                    bounds=bounds,
                                    weights=None)

    c = masked_fitresult.x
    zp = paraboloid(x, y, c[0])
    cor = np.hstack((-1 * c[1:4], c[4:6], 0))
    xrrm, yrrm, zrrm = shiftRotateXYZ(x, y, z, cor)
    masked_diff = zrrm - zp

    mcdiff2 = masked_diff

    # Final mask.
    map_mask = np.zeros((n, n), dtype=bool)

    xl = np.linspace(0, n, n)

    # Loop over rows fitting a parabola and masking any pixels that deviate from noise.
    for i in range(0, n):

        yl = mcdiff2[i]

        if len(xl[~yl.mask]) > 3:

            poly_c = np.polyfit(xl[~yl.mask], yl[~yl.mask], poly_order)
            poly_f = np.poly1d(poly_c)

            res = np.ma.masked_invalid(yl - poly_f(xl))
            res_sc = sigma_clip(res, **kwargs)

            map_mask[i] = res_sc.mask

        else:

            map_mask[i] = True

    # Prepare output.
    origData = (x, y, z)

    origMaskedData = (np.ma.masked_where(map_mask,
                                         x), np.ma.masked_where(map_mask, y),
                      np.ma.masked_where(map_mask, z))

    rotatedData = (xrrm, yrrm, np.ma.masked_where(map_mask, zrrm))

    fitResidual = np.ma.masked_where(map_mask, zrrm - zp)

    parabolaFit = (xrrm, yrrm, zp)

    outData = {
        'origData': origData,
        'origMasked': origMaskedData,
        'rotated': rotatedData,
        'fitResidual': fitResidual,
        'parabolaFit': parabolaFit,
        'parabolaFitCoeffs': c
    }

    return outData
Esempio n. 7
0
def plotZernikes(x, y, zernCoeffs, n=512, title=None, filename=None):
    """
    Plot Zernike polynomials with coefficients `zernCoeffs` over a square grid.

    Parameters
    ----------
    x : array
        Array with x coordinates.
        Used to evaluate the Zernike polynomials.
    y : array
        Array with y coordinates.
        Used to evaluate the Zernike polynomials.
    zernCoeffs : array
        Array with the coefficients of a Zernike polynomial.
    n : int, optional
        Number of pixels per side of the square grid used to
        display the Zernike polynomial.
    title : string, optional
    filename : string, optional
        Save the plot to this disk location.
    """

    # Create the linear combination of the Zernike polynomials.
    zPoly = zernikePoly(x, y, midPoint(x), midPoint(y), zernCoeffs)

    # Grid it to a regularly sampled cartesian grid.
    xx, yy, zz = regridXYZ(x, y, zPoly, n=n)

    # Make it look like the dish of the GBT by selecting a circular area.
    mask = (((xx - midPoint(xx))**2. + (yy - midPoint(yy))**2.) < 49.**2.)
    zz[~mask] = np.nan

    # To get meaningful plot tick labels.
    extent = [np.nanmin(xx), np.nanmax(xx), np.nanmin(yy), np.nanmax(yy)]

    fig = plt.figure(figsize=(12, 8), dpi=80)
    ax = fig.gca()
    im = ax.imshow(zz.T, cmap=cm.RdYlGn, extent=extent)
    plt.colorbar(im)

    # Add minor ticks and make them point inwards.
    ax.minorticks_on()
    ax.tick_params('both',
                   which='both',
                   direction='in',
                   top=True,
                   right=True,
                   bottom=True,
                   left=True)

    # Set a title.
    if title is not None:
        plt.title(title)

    # Set axis label names.
    ax.set_xlabel('x axis (m)')
    ax.set_ylabel('y axis (m)')

    # Save the figure to disk.
    if filename is not None:
        plt.savefig(filename)
Esempio n. 8
0
    def testMidPoint(self):

        x = np.array([1, 2, 3])
        self.assertEqual(midPoint(x), 2)