Beispiel #1
0
def quicklook_wf(wfo, logAmp=True, show=True):

    after_dm = proper.prop_get_amplitude(wfo)
    phase_afterdm = proper.prop_get_phase(wfo)

    fig = plt.figure(figsize=(14, 10))
    ax1 = plt.subplot2grid((3, 2), (0, 0), rowspan=2)
    ax2 = plt.subplot2grid((3, 2), (0, 1), rowspan=2)
    ax3 = plt.subplot2grid((3, 2), (2, 0))
    ax4 = plt.subplot2grid((3, 2), (2, 1))
    if logAmp:
        ax1.imshow(after_dm, origin='lower', cmap="YlGnBu_r", norm=LogNorm())
    else:
        ax1.imshow(after_dm, origin='lower', cmap="YlGnBu_r")
    ax2.imshow(phase_afterdm, origin='lower',
               cmap="YlGnBu_r")  #, vmin=-0.5, vmax=0.5)

    ax3.plot(after_dm[int(tp.grid_size / 2)])
    ax3.plot(np.sum(np.eye(tp.grid_size) * after_dm, axis=1))

    # plt.plot(np.sum(after_dm,axis=1)/after_dm[128,128])

    ax4.plot(phase_afterdm[int(tp.grid_size / 2)])
    # ax4.plot(np.sum(np.eye(tp.grid_size)*phase_afterdm,axis=1))
    plt.xlim([0, proper.prop_get_gridsize(wfo)])
    fig.set_tight_layout(True)
    if show == True:
        plt.show()
Beispiel #2
0
def open_loop_wfs(wfo, plane_name='wfs'):
    """
    saves the unwrapped phase [arctan2(imag/real)] of the wfo.wf_collection at each wavelength

    It is an idealized image (exact copy) of the wavefront phase per wavelength. Only the map for the first object
    (the star) is saved. We have initialized

    Here we hardmask on the WFS map to be a circle around the beam in the pupil plane. This hard masking prevents the
     DM from acting on non-beam signal, since the DM modelled by proper is a nxn square array, but the beam is nominally
     circular for circular apertures.

    #TODO the way this is saved for naming the WFS_map is going to break if you want to do closed loop WFS on a
    #TODO woofer-tweeter system

    :param wfo: wavefront object
    :param plane_name: name of the plane to enable or disable saving the WFS map
    :return: array containing only the unwrapped phase delay of the wavefront; shape=[n_wavelengths], units=radians
    """
    star_wf = wfo.wf_collection[:, 0]
    WFS_map = np.zeros((len(star_wf), sp.grid_size, sp.grid_size))

    for iw in range(len(star_wf)):  # for each wavelength
        hardmask_pupil(star_wf[iw])
        phasemap = proper.prop_get_phase(star_wf[iw])
        WFS_map[iw] = unwrap_phase(phasemap, wrap_around=[False, False])
        WFS_map[iw][phasemap == 0] = 0  #TODO is this still necessary?

    if 'WFS' in sp.save_list or sp.closed_loop:
        wfo.save_plane(location='WFS')

    return WFS_map
Beispiel #3
0
def lyot_stop(wf, mode='RAVC', ravc_r=0.6, ls_dRext=0.03, ls_dRint=0.05, 
        ls_dRspi=0.04, spi_width=0.5, spi_angles=[0,60,120], diam_ext=37, 
        diam_int=11, ls_misalign=None, file_app_phase='', file_app_amp='', 
        ngrid=1024, npupil=285, margin=50, get_amp=False, 
        get_phase=False, verbose=False, **conf):

    """Add a Lyot stop, or an APP."""
    
    # case 1: Lyot stop
    if mode in ['CVC', 'RAVC']:
        # LS parameters
        r_obstr = ravc_r if mode in ['RAVC'] else diam_int/diam_ext
        ls_int = r_obstr + ls_dRint
        ls_ext = 1 - ls_dRext
        ls_spi = spi_width/diam_ext + ls_dRspi
        # LS misalignments
        ls_misalign = [0,0,0,0,0,0] if ls_misalign is None else list(ls_misalign)
        dx_amp, dy_amp, dz_amp = ls_misalign[0:3]
        dx_phase, dy_phase, dz_phase = ls_misalign[3:6]
        # create Lyot stop
        proper.prop_circular_aperture(wf, ls_ext, dx_amp, dy_amp, NORM=True)
        if diam_int > 0:
            proper.prop_circular_obscuration(wf, ls_int, dx_amp, dy_amp, NORM=True)
        if spi_width > 0:
            for angle in spi_angles:
                proper.prop_rectangular_obscuration(wf, ls_spi, 2, \
                        dx_amp, dy_amp, ROTATION=angle, NORM=True)
        if verbose is True:
            print('Create Lyot stop')
            print('   ls_int=%3.4f, ls_ext=%3.4f, ls_spi=%3.4f'\
                %(ls_int, ls_ext, ls_spi))
            print('')

    # case 2: APP
    elif mode in ['APP']:
        if verbose is True:
            print('Load APP from files\n')
        # get amplitude and phase data
        APP_amp = fits.getdata(file_app_amp) if os.path.isfile(file_app_amp) \
                else np.ones((npupil, npupil))
        APP_phase = fits.getdata(file_app_phase) if os.path.isfile(file_app_phase) \
                else np.zeros((npupil, npupil))
        # resize to npupil
        APP_amp = impro.resize_img(APP_amp, npupil)
        APP_phase = impro.resize_img(APP_phase, npupil)
        # pad with zeros to match PROPER ngrid
        APP_amp = impro.pad_img(APP_amp, ngrid, 1)
        APP_phase = impro.pad_img(APP_phase, ngrid, 0)
        # multiply the loaded APP
        proper.prop_multiply(wf, APP_amp*np.exp(1j*APP_phase))
    
    # get the LS amplitude and phase for output
    LS_amp = impro.crop_img(proper.prop_get_amplitude(wf), npupil, margin)\
            if get_amp is True else None
    LS_phase = impro.crop_img(proper.prop_get_phase(wf), npupil, margin)\
            if get_phase is True else None
    
    return wf, LS_amp, LS_phase
Beispiel #4
0
def imshow_phi(wf, npupil=None, margin=0):

    amp = proper.prop_get_phase(wf)
    ngrid = amp.shape[0]
    if npupil is None:
        npupil = ngrid
    start = int((ngrid - npupil + npupil % 2) / 2 - margin)
    start = 0 if start < 0 else start
    end = ngrid - start + npupil % 2
    plt.imshow(amp[start:end, start:end], origin='lower')
Beispiel #5
0
def apodize_pupil(wf):
    phase_map = proper.prop_get_phase(wf)
    amp_map = proper.prop_get_amplitude(wf)
    h, w = wf.wfarr.shape[:2]
    wavelength = wf.lamda
    scale = ap.wvl_range[0] / wavelength
    inds = circular_mask(h, w, radius=scale * 0.95 * h * sp.beam_ratio / 2)  #TO DO remove hardcoded sizing, especially if use is default
    mask = np.zeros_like(phase_map)
    mask[inds] = 1
    smooth_mask = gaussian_filter(mask, 1.5, mode='nearest')  #TO DO remove hardcoded sizing, especially if use is default
    smoothed = phase_map * smooth_mask
    wf.wfarr = proper.prop_shift_center(amp_map * np.cos(smoothed) + 1j * amp_map * np.sin(smoothed))
Beispiel #6
0
    def quicklook(self, wf=None, logZ=True, show=True, title=None):
        """
        Produces a figure with an image of amplitude and one of phase as well as 1D slices through these images

        :param wf: optics.Wavefront
        :param logZ: bool logarithmic Z scaling
        :param show: bool display figure now or leave show() to be called by user later on
        :param title: str
        :return:
        """
        if wf == None:
            wf = self.wf_collection[0,0]

        amp_map = proper.prop_get_amplitude(wf)
        phase_map = proper.prop_get_phase(wf)

        fig = plt.figure(figsize=(12, 10))
        ax1 = plt.subplot2grid((1, 2), (0, 0), rowspan=2)  # ((shape of grid to place axis x,y),(location x,y))
        ax2 = plt.subplot2grid((1, 2), (0, 1), rowspan=2)
        # ax3 = plt.subplot2grid((3, 2), (2, 0))
        # ax4 = plt.subplot2grid((3, 2), (2, 1))
        if logZ:
            im1 = ax1.imshow(amp_map, origin='lower', cmap="YlGnBu_r", norm=LogNorm())
        else:
            im1 = ax1.imshow(amp_map, origin='lower', cmap="YlGnBu_r")
        ax1.set_title('Amplitude Map')
        plt.colorbar(im1, ax=ax1)

        im2 = ax2.imshow(phase_map, origin='lower', cmap=sunlight)  # , vmin=-0.5, vmax=0.5)
        ax2.set_title('Phase Map')
        plt.colorbar(im2, ax=ax2)

        # ax3.plot(after_dm[int(sp.grid_size / 2)])
        # ax3.plot(np.sum(np.eye(sp.grid_size) * after_dm, axis=1), label=f'row {int(sp.grid_size / 2)}')
        # ax3.legend()
        #
        # # plt.plot(np.sum(after_dm,axis=1)/after_dm[128,128])
        #
        # ax4.plot(phase_afterdm[int(sp.grid_size / 2)], label=f'row {int(sp.grid_size / 2)}')
        # ax4.legend()
        # # ax4.plot(np.sum(np.eye(ap.grid_size)*phase_afterdm,axis=1))
        # plt.xlim([0, proper.prop_get_gridsize(wf)])
        if not title:
            title = input(f"Always Add A Title\n "
                          f"Please Enter Plane Name:")
            fig.suptitle(f"plane: {title}, lambda: {wf.lamda} m, body: {wf.name}", fontsize=18)
        else:
            fig.suptitle(f"plane: {title}, lambda: {wf.lamda} m, body: {wf.name}", fontsize=18)

        plt.subplots_adjust(top=0.9)

        if show:
            plt.show(block=True)
Beispiel #7
0
def hardmask_pupil(wf):
    """
    hard-edged circular mask of the pupil plane.

    Masks out the WFS map outside of the beam since the DM modeled by proper can only be a square nxn grid of actuators,
    and thus the influence function surrounding each DM actuator could  be affecting on-beam pixels, even if the
    actuator is acting on off-beam signal. In other words, even if a cornerDM actuator doesn't actuate on the beam,
    if there was non-zero signal in the WFS map, it will try to act on it, and it could 'influence' nearby DM actuators
    that are acting on the beam.

    This hard-edged mask is different from prop_circular_aperture in that it does not anti-alias the edges of the mask
    based on the 'fill factor' of the edge pixels. Instead, it has a boolean mask to zero everything > a fixed radius,
    in this case determined by the grid size and beam ratio of each wavefront passed into it.

    :param wf: a single wavefront
    :return: nothing is returned but the wf passed into it has been masked

    """
    phase_map = proper.prop_get_phase(wf)
    amp_map = proper.prop_get_amplitude(wf)

    # Sizing the Mask
    h, w = wf.wfarr.shape[:2]
    center = (int(w / 2), int(h / 2))
    radius = np.floor(
        sp.grid_size * wf.beam_ratio /
        2)  # Should scale with wavelength if sp.focused_system=False,
    # np.ceil used to oversize map so don't clip the beam
    # Making the Circular Boolean Mask
    Y, X = np.mgrid[:h, :w]
    dist_from_center = np.sqrt((X - center[0])**2 + (Y - center[1])**2)
    inds = dist_from_center <= radius

    # Applying the Mask to the Complex Array
    mask = np.zeros_like(phase_map)
    mask[inds] = 1
    masked = phase_map * mask
    wf.wfarr = proper.prop_shift_center(amp_map * np.cos(masked) +
                                        1j * amp_map * np.sin(masked))
Beispiel #8
0
def quick_wfs(wfo, iter, r0):
    # CPA_map = proper.prop_get_phase(wfo)

    import scipy.ndimage
    from skimage.restoration import unwrap_phase
    # quicklook_im(CPA_map, logAmp=False)
    sigma = [1, 1]
    CPA_map = scipy.ndimage.filters.gaussian_filter(unwrap_phase(
        proper.prop_get_phase(wfo)),
                                                    sigma,
                                                    mode='constant')
    # CPA_map = unwrap_phase(CPA_map)
    # quicklook_im(CPA_map, logAmp=False)
    if tp.piston_error:
        # from Utils.misc import debprint
        # var = 0.27*(tp.diam/(r0 * tp.ao_act))*(5/3)
        var = 0.001  #1e-11 #0.1 wavelengths 0.1*1000e-9
        # debprint(var)
        CPA_map = CPA_map + np.random.normal(
            0, var, (CPA_map.shape[0], CPA_map.shape[1]))

    return CPA_map
Beispiel #9
0
def deformable_mirror(wf,
                      WFS_map,
                      iter,
                      previous_output=None,
                      apodize=False,
                      plane_name='',
                      debug=False):
    """
    combine different DM actuator commands into single map to send to prop_dm

    prop_dm needs an input map of n_actuators x n_actuators in units of actuator command height. quick_ao will handle
    the conversion to actuator command height, and the CDI probe must be scaled in cdi.probe_amp in params in
    units of m. Each subroutine is also responsible for creating a map of n_actuators x n_actuators spacing. prop_dm
    handles the resampling of this map onto the wavefront, including the influence function. Its some wizardry that
    happens in c, and presumably it is taken care of so you don't have to worry about it.

    In the call to proper.prop_dm, we apply the flag tp.fit_dm, which switches between two 'modes' of proper's DM
    surface fitting. If FALSE, the DM is driven to the heights specified by dm_map, and the influence function will
    act on these heights to define the final surface shape applied to the DM, which may differ substantially from
    the initial heights specified by dm_map. If TRUE, proper will iterate applying the influence function to the
    input heights, and adjust the heights until the difference between the influenced-map and input map meets some
    proper-defined convergence criterea. Setting tp.fit_dm=TRUE will obviously slow down the code, but will (likely)
    more accurately represent a well-calibrated DM response function.

    much of this code copied over from example from Proper manual on pg 94

    :param wf: single wavefront
    :param WFS_map: wavefront sensor map, should be in units of phase delay
    :param previous_output:
    :param iter: the current index of iteration (which timestep this is)
    :param plane_name: name of plane (should be 'woofer' or 'tweeter' for best functionality)
    :return: nothing is returned, but the probe map has been applied to the DM via proper.prop_dm. DM plane post DM
        application can be saved via the sp.save_list functionality
    """
    assert np.logical_xor(WFS_map is None, previous_output is None)

    # AO Actuator Count from DM Type
    if plane_name == 'tweeter' and hasattr(tp, 'act_tweeter'):
        nact = tp.act_tweeter
    elif plane_name == 'woofer' and hasattr(tp, 'act_woofer'):
        nact = tp.act_woofer
    else:
        nact = tp.ao_act

    # DM Coordinates
    nact_across_pupil = nact - 2  # number of full DM actuators across pupil (oversizing DM extent)
    dm_xc = (
        nact / 2
    )  # The location of the optical axis (center of the wavefront) on the DM in
    dm_yc = (
        nact / 2
    )  # actuator units. First actuator is centered on (0.0, 0.0). The 0.5 is a
    #  parameter introduced/tuned by Rupert to remove weird errors (address this).
    # KD verified this needs to be here or else suffer weird errors 9/19
    # TODO address/remove the 0.5 in DM x,y coordinates

    ############################
    # Creating DM Surface Map
    ############################
    d_beam = 2 * proper.prop_get_beamradius(wf)  # beam diameter
    act_spacing = d_beam / nact_across_pupil  # actuator spacing [m]

    #######
    # AO
    #######
    if previous_output is not None and WFS_map is None:
        dm_map = update_dm(previous_output)
    else:
        dm_map = quick_ao(wf, nact, WFS_map[wf.iw])

    #########
    # Waffle
    #########
    if tp.satelite_speck['apply'] and plane_name is not 'woofer':
        waffle = make_speckle_kxy(tp.satelite_speck['xloc'],
                                  tp.satelite_speck['yloc'],
                                  tp.satelite_speck['amp'],
                                  tp.satelite_speck['phase'])
        waffle += make_speckle_kxy(tp.satelite_speck['xloc'],
                                   -tp.satelite_speck['yloc'],
                                   tp.satelite_speck['amp'],
                                   tp.satelite_speck['phase'])
        dm_map += waffle

    #######
    # CDI
    ######
    if cdi.use_cdi and plane_name == cdi.which_DM:
        theta = cdi.phase_series[iter]
        if not np.isnan(theta):
            # dprint(f"Applying CDI probe, lambda = {wfo.wsamples[iw]*1e9:.2f} nm")
            cdi.save_tseries(iter, datetime.datetime.now())
            probe = config_probe(theta, nact, iw=wf.iw, ib=wf.ib, tstep=iter)
            dm_map = dm_map + probe  # Add Probe to DM map

    #########################
    # Applying Piston Error
    #########################
    if tp.piston_error:
        mean_dm_map = np.mean(np.abs(dm_map))
        var = 1e-4  # 1e-11
        dm_map = dm_map + np.random.normal(0, var,
                                           (dm_map.shape[0], dm_map.shape[1]))

    #########################
    # proper.prop_dm
    #########################
    dmap = proper.prop_dm(wf, dm_map, dm_xc, dm_yc, act_spacing,
                          FIT=tp.fit_dm)  #

    if debug and wf.iw == 0 and wf.ib == 0 and iter == 0:
        dprint(plane_name)
        check_sampling(wf,
                       iter,
                       plane_name + ' DM pupil plane',
                       getframeinfo(stack()[0][0]),
                       units='mm')

        quick2D(WFS_map[wf.iw],
                title=f"WFS map after masking",
                zlabel='unwrapped phase (rad)',
                vlim=[-3 * np.pi, 3 * np.pi])

        fig, ax = plt.subplots(1, 1)
        cax = ax.imshow(dm_map * 1e9, interpolation='none', origin='lower')
        plt.title(f'{plane_name} dm_map (actuator coordinates)')
        cb = plt.colorbar(cax)
        cb.set_label('nm')

        plt.show()

        post_ao = unwrap_phase(
            proper.prop_get_phase(wf)) * wf.lamda / (2 * np.pi)
        # quick2D(pre_ao_dist*1e9, title='unwrapped wavefront before DM', zlabel='nm', show=False)  # , vlim=(-0.5e-7,0.5e-7))
        # quick2D(np.abs(pre_ao_amp)**2, title='Pre-AO Intensity', show=False)#, vlim=(-0.5e-7,0.5e-7))
        # quick2D(dmap, title='the phase map prop_dm is applying', zlabel='distance (m)', show=False)#, vlim=(-0.5e-7,0.5e-7))
        # plt.figure()
        # plt.plot(pre_ao_dist[len(pre_ao_dist)//2], label=f'pre_ao 1D cut, row {len(pre_ao_dist)//2}')
        # plt.plot(2*dmap[len(dmap)//2], label=f'dmap 1D cut (x2), row {len(dmap)//2}')
        # plt.plot((pre_ao_dist + (2*dmap))[len(dmap)//2], label='difference')
        # plt.legend()
        # plt.xlim(sp.grid_size//2*np.array([1-sp.beam_ratio*1.1, 1+sp.beam_ratio*1.1]))
        # quick2D(pre_ao + (2*dmap), title='diff', zlabel='m', show=False, vlim=(-0.5e-7,0.5e-7))
        # quick2D(post_ao, title='unwrapped wavefront after DM', zlabel='m', show=True, vlim=(-0.5e-7,0.5e-7))
        # quick2D(np.abs(proper.prop_get_amplitude(wf))**2, title='wavefront after DM intensity', show=False)
        # quick2D(proper.prop_get_phase(wf), title='wavefront after DM in phase units', zlabel='Phase',
        #          show=True)  # colormap='sunlight',

    if apodize:
        hardmask_pupil(wf)

    return dmap
Beispiel #10
0
    def lyotstop(self, wf, RAVC=None, APP=None, get_pupil='no', dnpup=50):
        """Add a Lyot stop, or an APP."""

        # load parameters
        npupil = 1  #conf['NPUPIL']
        pad = int((210 - npupil) / 2)

        # get LS misalignments
        LS_misalignment = (np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0]) *
                           npupil).astype(int)
        dx_amp, dy_amp, dz_amp = LS_misalignment[0:3]
        dx_phase, dy_phase, dz_phase = LS_misalignment[3:6]

        # case 1: Lyot stop (no APP)
        if APP is not True:

            # Lyot stop parameters: R_out, dR_in, spi_width
            # outer radius (absolute %), inner radius (relative %), spider width (m)
            (R_out, dR_in, spi_width) = [0.98, 0.03, 0]

            # Lyot stop inner radius at least as large as obstruction radius
            R_in = 0.15

            # case of a ring apodizer
            if RAVC is True:
                # define the apodizer transmission and apodizer radius [Mawet2013]
                # apodizer radius at least as large as obstruction radius
                T_ravc = 1 - (R_in**2 + R_in * np.sqrt(R_in**2 + 8)) / 4
                R_in /= np.sqrt(1 - T_ravc)

            # oversize Lyot stop inner radius
            R_in += dR_in

            # create Lyot stop
            proper.prop_circular_aperture(wf, R_out, dx_amp, dy_amp, NORM=True)
            if R_in > 0:
                proper.prop_circular_obscuration(wf,
                                                 R_in,
                                                 dx_amp,
                                                 dy_amp,
                                                 NORM=True)
            if spi_width > 0:
                for angle in [10]:
                    proper.prop_rectangular_obscuration(wf,
                                                        0.05 * 8,
                                                        8 * 1.3,
                                                        ROTATION=20)
                    proper.prop_rectangular_obscuration(wf,
                                                        8 * 1.3,
                                                        0.05 * 8,
                                                        ROTATION=20)
                    # proper.prop_rectangular_obscuration(wf, spi_width, 2 * 8, \
                    #                                     dx_amp, dy_amp, ROTATION=angle)

        # case 2: APP (no Lyot stop)
        else:
            # get amplitude and phase files
            APP_amp_file = os.path.join(conf['INPUT_DIR'],
                                        conf['APP_AMP_FILE'])
            APP_phase_file = os.path.join(conf['INPUT_DIR'],
                                          conf['APP_PHASE_FILE'])
            # get amplitude and phase data
            APP_amp = getdata(APP_amp_file) if os.path.isfile(APP_amp_file) \
                else np.ones((npupil, npupil))
            APP_phase = getdata(APP_phase_file) if os.path.isfile(APP_phase_file) \
                else np.zeros((npupil, npupil))
            # resize to npupil
            APP_amp = resize(APP_amp, (npupil, npupil),
                             preserve_range=True,
                             mode='reflect')
            APP_phase = resize(APP_phase, (npupil, npupil),
                               preserve_range=True,
                               mode='reflect')
            # pad with zeros to match PROPER gridsize
            APP_amp = np.pad(APP_amp, [(pad + 1 + dx_amp, pad - dx_amp), \
                                       (pad + 1 + dy_amp, pad - dy_amp)], mode='constant')
            APP_phase = np.pad(APP_phase, [(pad + 1 + dx_phase, pad - dx_phase), \
                                           (pad + 1 + dy_phase, pad - dy_phase)], mode='constant')
            # multiply the loaded APP
            proper.prop_multiply(wf, APP_amp * np.exp(1j * APP_phase))

        # get the pupil amplitude or phase for output
        if get_pupil.lower() in 'amplitude':
            return wf, proper.prop_get_amplitude(wf)[pad + 1 - dnpup:-pad +
                                                     dnpup, pad + 1 -
                                                     dnpup:-pad + dnpup]
        elif get_pupil.lower() in 'phase':
            return wf, proper.prop_get_phase(wf)[pad + 1 - dnpup:-pad + dnpup,
                                                 pad + 1 - dnpup:-pad + dnpup]
        else:
            return wf
Beispiel #11
0
def get_intensity(wf_array,
                  sp,
                  logAmp=True,
                  show=False,
                  save=True,
                  phase=False):

    if show == True:
        wfo = wf_array[0, 0]
        after_dm = proper.prop_get_amplitude(wfo)
        phase_afterdm = proper.prop_get_phase(wfo)

        fig = plt.figure(figsize=(14, 10))
        ax1 = plt.subplot2grid((3, 2), (0, 0), rowspan=2)
        ax2 = plt.subplot2grid((3, 2), (0, 1), rowspan=2)
        ax3 = plt.subplot2grid((3, 2), (2, 0))
        ax4 = plt.subplot2grid((3, 2), (2, 1))
        if logAmp:
            ax1.imshow(after_dm,
                       origin='lower',
                       cmap="YlGnBu_r",
                       norm=LogNorm())
        else:
            ax1.imshow(after_dm, origin='lower', cmap="YlGnBu_r")
        ax2.imshow(phase_afterdm, origin='lower',
                   cmap="YlGnBu_r")  #, vmin=-0.5, vmax=0.5)

        ax3.plot(after_dm[int(tp.grid_size / 2)])
        ax3.plot(np.sum(np.eye(tp.grid_size) * after_dm, axis=1))

        # plt.plot(np.sum(after_dm,axis=1)/after_dm[128,128])

        ax4.plot(phase_afterdm[int(tp.grid_size / 2)])
        # ax4.plot(np.sum(np.eye(tp.grid_size)*phase_afterdm,axis=1))
        plt.xlim([0, proper.prop_get_gridsize(wfo)])
        fig.set_tight_layout(True)

        plt.show()

    if save:
        shape = wf_array.shape
        ws = sp.get_ints['w']
        cs = sp.get_ints['c']

        int_maps = np.empty((0, tp.grid_size, tp.grid_size))
        for iw in ws:
            for iwf in cs:
                # int_maps.append(proper.prop_shift_center(np.abs(wf_array[iw, iwf].wfarr) ** 2))
                if phase:
                    int_map = proper.prop_get_phase(wf_array[iw, iwf])

                # int_map = proper.prop_shift_center(np.abs(wf_array[iw, iwf].wfarr) ** 2)
                else:
                    int_map = proper.prop_shift_center(
                        np.abs(wf_array[iw, iwf].wfarr)**2)
                int_maps = np.vstack((int_maps, [int_map]))
                # quicklook_im(int_map)#, logAmp=True)

        # int_maps = np.array(int_maps)
        # view_datacube(int_maps)
        import pickle, os
        if os.path.exists(iop.int_maps):
            # "with" statements are very handy for opening files.
            with open(iop.int_maps, 'rb') as rfp:
                # dprint(np.array(pickle.load(rfp)).shape)
                int_maps = np.vstack((int_maps, pickle.load(rfp)))

        with open(iop.int_maps, 'wb') as wfp:
            pickle.dump(int_maps, wfp, protocol=pickle.HIGHEST_PROTOCOL)
Beispiel #12
0
def apodizer(wf,
             mode='RAVC',
             ravc_t=0.8,
             ravc_r=0.6,
             ravc_misalign=None,
             ngrid=1024,
             npupil=285,
             file_ravc_amp='',
             file_ravc_phase='',
             margin=50,
             get_amp=False,
             get_phase=False,
             verbose=False,
             **conf):
    ''' Create a wavefront object at the entrance pupil plane. 
    The pupil is either loaded from a fits file, or created using 
    pupil parameters.
    Can also select only one petal and mask the others.

    wf: WaveFront
        PROPER wavefront object
    mode: str
        HCI mode
    ravc_t: float
        RA transmittance
    ravc_r: float
        RA radius
    ravc_misalign: list of float
        RA misalignment
    ngrid: int
        number of pixels of the wavefront array
    npupil: int
        number of pixels of the pupil
    file_ravc_amp: str
    file_ravc_phase: str 
        ring apodizer files (optional)
    
    '''

    if mode in ['RAVC']:

        # load apodizer from files if provided
        if os.path.isfile(file_ravc_amp) and os.path.isfile(file_ravc_phase):
            if verbose is True:
                print('Load ring apodizer from files\n')
            # get amplitude and phase data
            RAVC_amp = fits.getdata(file_ravc_amp)
            RAVC_phase = fits.getdata(file_ravc_phase)
            # resize to npupil
            RAVC_amp = impro.resize_img(RAVC_amp, npupil)
            RAVC_phase = impro.resize_img(RAVC_phase, npupil)
            # pad with zeros to match PROPER gridsize
            RAVC_amp = impro.pad_img(RAVC_amp, ngrid)
            RAVC_phase = impro.pad_img(RAVC_phase, ngrid)
            # build complex apodizer
            apo = RAVC_amp * np.exp(1j * RAVC_phase)

        # or else, define the apodizer as a ring (with % misalignments)
        else:
            # RAVC misalignments
            ravc_misalign = [
                0, 0, 0, 0, 0, 0
            ] if ravc_misalign is None else list(ravc_misalign)
            dx_amp, dy_amp, dz_amp = ravc_misalign[0:3]
            dx_phase, dy_phase, dz_phase = ravc_misalign[3:6]
            # create apodizer
            apo = circular_apodization(wf, ravc_r, 1., ravc_t, xc=dx_amp, \
                yc=dy_amp, NORM=True)
            apo = proper.prop_shift_center(apo)
            if verbose is True:
                print('Create ring apodizer')
                print('   ravc_t=%3.4f, ravc_r=%3.4f'\
                    %(ravc_t, ravc_r))
                print('   ravc_misalign=%s' % ravc_misalign)
                print('')

        # multiply the loaded apodizer
        proper.prop_multiply(wf, apo)

        # get the apodizer amplitude and phase for output
        apo_amp = impro.crop_img(proper.prop_get_amplitude(wf), npupil,\
                margin) if get_amp is True else None
        apo_phase = impro.crop_img(proper.prop_get_phase(wf), npupil,\
                margin) if get_phase is True else None

        return wf, apo_amp, apo_phase

    else:  # no ring apodizer
        return wf, None, None
Beispiel #13
0
def simple_telescope(wavelength, gridsize):

    # Define entrance aperture diameter and other quantities
    d_objective = 5.0  # objective diameter in meters
    fl_objective = 20.0 * d_objective  # objective focal length in meters
    fl_eyepiece = 0.021  # eyepiece focal length
    fl_eye = 0.022  # human eye focal length
    beam_ratio = 0.3  # initial beam width/grid width

    # Define the wavefront
    wfo = proper.prop_begin(d_objective, wavelength, gridsize, beam_ratio)

    # print d_objective, wavelength, gridsize, beam_ratio
    # Define a circular aperture
    proper.prop_circular_aperture(wfo, d_objective / 2)

    # proper.prop_propagate(wfo, fl_objective)
    # proper.prop_propagate(wfo, fl_objective)
    # proper.prop_propagate(wfo, fl_objective)

    # plt.imshow(proper.prop_get_amplitude(wfo))
    # plt.show()

    # Define entrance
    proper.prop_define_entrance(wfo)
    # plt.imshow(proper.prop_get_amplitude(wfo))
    # plt.show()

    # proper.prop_propagate(wfo, fl_objective+fl_eyepiece, "eyepiece")
    # # plt.imshow(proper.prop_get_amplitude(wfo))
    # # plt.show()
    #
    # proper.prop_propagate(wfo, fl_objective+fl_eyepiece, "eyepiece")
    # plt.imshow(proper.prop_get_amplitude(wfo))
    # plt.show()
    #
    # proper.prop_propagate(wfo, fl_objective+fl_eyepiece, "eyepiece")
    # plt.imshow(proper.prop_get_amplitude(wfo))
    # plt.show()

    # Define a lens
    proper.prop_lens(wfo, fl_objective, "objective")
    # plt.imshow(proper.prop_get_amplitude(wfo))
    # plt.show()
    # Propagate the wavefront
    proper.prop_propagate(wfo, fl_objective + fl_eyepiece, "eyepiece")
    # plt.imshow(proper.prop_get_amplitude(wfo))
    # plt.show()
    # Define another lens
    proper.prop_lens(wfo, fl_eyepiece, "eyepiece")
    # plt.imshow(proper.prop_get_amplitude(wfo))
    # plt.show()
    exit_pupil_distance = fl_eyepiece / (1 - fl_eyepiece /
                                         (fl_objective + fl_eyepiece))
    proper.prop_propagate(wfo, exit_pupil_distance, "exit pupil at eye lens")
    # quicklook_wf(wfo)
    # plt.imshow(proper.prop_get_amplitude(wfo))
    # plt.show()
    proper.prop_lens(wfo, fl_eye, "eye")
    proper.prop_propagate(wfo, fl_eye, "retina")
    # plt.imshow(proper.prop_get_amplitude(wfo))
    # plt.show()
    quicklook_wf(wfo)
    phase_map = proper.prop_get_phase(wfo)
    amp_map = proper.prop_get_amplitude(wfo)
    # quicklook_im(phase_map)

    amp_map[80:100, 80:100] = 0
    quicklook_im(amp_map, logAmp=True)

    import numpy as np
    wfo.wfarr = proper.prop_shift_center(amp_map * np.cos(phase_map) +
                                         1j * amp_map * np.sin(phase_map))
    # quicklook_wf(wf_array[iw,0])
    proper.prop_propagate(wfo, fl_eye, "retina")
    proper.prop_lens(wfo, fl_eye, "eye")
    quicklook_wf(wfo)

    # End
    (wfo, sampling) = proper.prop_end(wfo)

    return (wfo, sampling)
Beispiel #14
0
def wfs_measurement(wfo, iter, iw, r0):  #, obj_map, wfs_sample):
    # print 'Including WFS Error'
    # quicklook_wf(wfo)
    # quicklook_im(obj_map, show=False, logAmp=False)

    with open(iop.CPA_meas, 'rb') as handle:
        CPA_maps, iters = pickle.load(handle)
    # quicklook_im(proper.prop_get_phase(wfo), logAmp=False)

    # quicklook_im(CPA_maps[0,iw], logAmp=False)
    # if iter < 20 or iter > 35:
    import scipy.ndimage
    sigma = [1, 1]
    # dmap = scipy.ndimage.filters.gaussian_filter(dmap, sigma, mode='constant')
    from skimage.restoration import unwrap_phase
    CPA_maps[0, iw] += scipy.ndimage.filters.gaussian_filter(unwrap_phase(
        proper.prop_get_phase(wfo)),
                                                             sigma,
                                                             mode='constant')
    # CPA_maps[0, iw] += proper.prop_get_phase(wfo)
    # quicklook_im(CPA_maps[0,iw], logAmp=False)
    # for d in [1]:#range(0,2,1):

    # quicklook_im(CPA_maps[0], logAmp=False)
    # CPA_maps[0,iw] = unwrap_phase(CPA_maps[0,iw])

    # quicklook_im(CPA_maps[0], logAmp=False)

    # CPA_maps[0] += proper.prop_get_phase(wfo)
    # loop_frames(CPA_maps, logAmp=False)
    # # print tp.servo_error
    if tp.servo_error:
        # print 'This might produce garbage if several processes are run in parrallel'
        # loop_frames(tp.obj_maps, logAmp=False)
        CPA_maps[:, iw] = np.roll(CPA_maps[:, iw], 1, 0)
        # tp.obj_maps[0] = CPA_maps[0]
        # if tp.servo_lag:
        required_servo = int(tp.servo_error[0])  # delay
        # obj_map = tp.obj_maps[required_servo]
        required_band = int(tp.servo_error[1])  # averaging
        # if tp.wfs_bandwidth_error:
        CPA_maps[0, iw] = np.sum(CPA_maps[required_servo:-1, iw],
                                 axis=0) / required_band

        # loop_frames(tp.obj_maps, logAmp=False)
        # print obj_map
    # quicklook_im(obj_map, logAmp=False)

    # if tp.piston_error:
    #     # from Utils.misc import debprint
    #     # var = 0.27*(tp.diam/(r0 * tp.ao_act))*(5/3)
    #     var = 0.001#1e-11 #0.1 wavelengths 0.1*1000e-9
    #     # debprint(var)
    #     CPA_maps[0,iw] = CPA_maps[0,iw] + np.random.normal(0,var,(CPA_maps[0,iw].shape[0],CPA_maps[0,iw].shape[1]))

    # if tp.wfs_measurement_error:
    #     '''Downsample subarrays and then convert back to original size (interpolation might
    #         be better than repeats'''
    #
    #     print '*** not used in a while! ***'
    #     def sub_sums_ophion(arr, nrows, ncols):
    #         h, w = arr.shape
    #         h = (h // nrows)*nrows
    #         w = (w // ncols)*ncols
    #         arr = arr[:h,:w]
    #         return np.einsum('ijkl->ik', arr.reshape(h // nrows, nrows, -1, ncols))
    #
    #     down_sample = sub_sums_ophion(obj_map, tp.wfs_sample, tp.wfs_sample) / tp.wfs_sample**2
    #     obj_map = np.repeat(np.repeat(down_sample,tp.wfs_sample, axis=0), tp.wfs_sample, axis=1)
    # return obj_map

    # if tp.active_null:
    #     with open(iop.NCPA_meas, 'rb') as handle:
    #         _, NCPA_map, _ = pickle.load(handle)
    #     # quicklook_im(CPA_map, logAmp=False)
    #     # dprint('CPA_map')
    #     # quicklook_im(NCPA_map, logAmp=False)
    #     # dprint('NCPA_map')
    #     CPA_maps[0] += NCPA_map
    #     # quicklook_im(CPA_map, logAmp=False)

    with open(iop.CPA_meas, 'wb') as handle:
        pickle.dump((CPA_maps, iters + 1),
                    handle,
                    protocol=pickle.HIGHEST_PROTOCOL)
Beispiel #15
0
def speck_killing_loop(wfo):
    #configfilename = 'speckle_null_config.ini'
    #config = ConfigObj(configfilename)
    configfilename = tp.FPWFSdir + 'speckle_null_config_Rupe.ini'
    hardwareconfigfile = tp.FPWFSdir + 'speckle_instruments.ini'
    configspecfile = tp.FPWFSdir + 'speckle_null_config.spec'
    print(configfilename)
    config = ConfigObj(configfilename, configspec=configspecfile)
    val = Validator()
    check = config.validate(val)

    #pharo = hardware.PHARO_COM('PHARO',
    #            configfile = hardwareconfigfile)
    #p3k = hardware.P3K_COM('P3K_COM', configfile = hardwareconfigfile)
    camera = hardware.camera()
    ao = hardware.ao()
    apmask = False
    if not apmask:
        aperturemask = np.ones((66, 66))
    if apmask:
        aperturemask = dm.annularmask(66, 12, 33)

    # nulled_field = None
    im_params = config['IM_PARAMS']
    null_params = config['NULLING']
    abc = config['INTENSITY_CAL']['abc']

    use_centoffs = config['NULLING']['cent_off']

    #bgds = flh.setup_bgd_dict(config)
    fake_bgds = {
        'bkgd': np.zeros((tp.grid_size, tp.grid_size)),
        'masterflat': np.ones((tp.grid_size, tp.grid_size)),
        'badpix': np.zeros((tp.grid_size, tp.grid_size))
    }
    print("WARNING: USING FAKE BGDS")
    bgds = fake_bgds.copy()
    # controlregion = pf.open(tp.FPWFSdir+config['CONTROLREGION']['filename'])[0].data
    # controlregion = controlregion[512-int(tp.grid_size/2):512+int(tp.grid_size/2), 512-int(tp.grid_size/2):512+int(tp.grid_size/2)]
    # controlregion = np.roll(controlregion, 15)
    # controlregion[:,0:70] = 0
    # controlregion[:80] = 0
    # controlregion[-80:] = 0
    controlregion = np.zeros((tp.grid_size, tp.grid_size))
    controlregion[50:80, 35:50] = 1
    boarder = get_ctrlrgnBoarder(controlregion)

    quicklook_im(controlregion, logAmp=False)
    # plt.show(block=True)

    #Notes==>scale exptime in snr
    exp = config['INTENSITY_CAL']['exptime']
    #Setup
    # initial_flatmap = ao.grab_current_flatmap()
    # initial_centoffs= ao.grab_current_centoffs()

    defaultim = np.ones((tp.grid_size, tp.grid_size))

    vertsx = config['CONTROLREGION']['verticesx']
    vertsy = config['CONTROLREGION']['verticesy']

    # plt.ion()
    fig = plt.figure(figsize=(12, 12))
    ax1 = plt.subplot2grid((4, 4), (0, 0), rowspan=2, colspan=2)
    ax2 = plt.subplot2grid((4, 4), (0, 2), rowspan=2, colspan=2)
    ax3 = plt.subplot2grid((4, 4), (3, 0))
    ax4 = plt.subplot2grid((4, 4), (2, 2), rowspan=2, colspan=2)
    #ax5 = plt.subplot2grid((4,4),(3,2))
    # ax1b =plt.subplot2grid((4,4),(0, 0), rowspan =2, colspan = 2)

    title = fig.suptitle('Speckle destruction')
    ax1.set_title('Image')
    ax2.set_title('Control region')
    ax3.set_title('RMS in region')
    ax4.set_title('Image')
    #ax5.set_title('Intensity')

    w1 = ax1.imshow(np.log10(np.abs(defaultim)) + boarder,
                    origin='lower',
                    interpolation='nearest')
    current_cmap = cm.get_cmap()
    current_cmap.set_bad(color='white')
    # w1b = ax1b.imshow(boarder*10, origin='lower', interpolation = 'none')
    # ax1.set_xlim(min(vertsx), max(vertsx))
    # ax1.set_ylim(min(vertsy), max(vertsy))
    #ax1.set_ylim(int(im_params['centery'])-25, int(im_params['centery']+50))

    w2 = ax2.imshow(np.log(np.abs(controlregion * defaultim)),
                    origin='lower',
                    interpolation='nearest')
    # ax2.set_xlim(min(vertsx), max(vertsx))
    # ax2.set_ylim(min(vertsy), max(vertsy))

    w3 = ax3.plot([], [])
    ax3.set_xlim(0, 10)

    w4, = ax4.plot(np.abs(defaultim[64]))
    # w4 = ax4.imshow(np.log10(np.abs(defaultim))+boarder, origin='lower', interpolation = 'nearest')
    current_cmap = cm.get_cmap()
    current_cmap.set_bad(color='white')

    N_iterations = 10
    itcounter = []
    maxfluxes = []
    meanfluxes = []
    totalfluxes = []
    rmsfluxes = []
    #w5 = ax5.plot(np.arange(10)*0, np.arange(10)*0)
    # w4 = ax4.imshow(np.log(camera.take_src_return_imagedata(exptime =exp)[242:758, 242:758]), origin='lower', interpolation = 'nearest')

    plt.show()
    tstamp = time.strftime("%Y%m%d-%H%M%S").replace(' ', '_')

    cubeoutputdir = os.path.join(null_params['outputdir'], tstamp)
    if not os.path.exists(cubeoutputdir):
        os.makedirs(cubeoutputdir)

    print(configfilename)
    result_imagecube = output_imagecube(N_iterations,
                                        tp.grid_size,
                                        filepath=os.path.join(
                                            cubeoutputdir,
                                            'test_' + tstamp + '.fits'),
                                        comment='fun',
                                        configfile=configfilename)

    clean_imagecube = output_imagecube(N_iterations,
                                       tp.grid_size,
                                       filepath=os.path.join(
                                           cubeoutputdir,
                                           'test_clean_' + tstamp + '.fits'),
                                       comment='fun',
                                       configfile=configfilename)

    cal_imagecube = output_imagecube(4,
                                     tp.grid_size,
                                     filepath=os.path.join(
                                         cubeoutputdir,
                                         'test_cals_' + tstamp + '.fits'),
                                     comment='fun',
                                     configfile=configfilename)
    cal_imagecube.update(controlregion)
    cal_imagecube.update(bgds['bkgd'])
    cal_imagecube.update(bgds['masterflat'])
    cal_imagecube.update(bgds['badpix'])

    ####MAIN LOOP STARTS HERE#####
    print("BEGINNING NULLING LOOP")

    for iteration in range(N_iterations):
        # quicklook_wf(wfo)
        itcounter.append(iteration)

        if use_centoffs == False:
            current_flatmap = ao.grab_current_flatmap()
        if use_centoffs == True:
            current_centoffs = ao.grab_current_centoffs()
        # quicklook_im(current_flatmap, logAmp=False, show=True)
        print("Taking image of speckle field")
        # if nulled_field != None:
        #     raw_im = nulled_field
        # else:
        raw_im = camera.take_src_return_imagedata(wfo, exptime=exp)

        result_imagecube.update(raw_im)
        field_im = pre.equalize_image(raw_im, **bgds)
        clean_imagecube.update(field_im)

        field_ctrl = field_im * controlregion
        # print np.shape(field_im), np.shape(controlregion), np.shape(field_ctrl)
        # plt.figure()
        # plt.imshow(field_im)
        # plt.figure()
        # plt.imshow(controlregion)
        # plt.figure()
        # plt.imshow(field_ctrl)
        # plt.show(block=True)

        meanfluxes.append(np.mean(field_ctrl[field_ctrl > 0]))
        maxfluxes.append(np.max(field_ctrl[field_ctrl > 0]))
        totalfluxes.append(np.sum(field_ctrl))
        rmsfluxes.append(
            np.std(field_ctrl[field_ctrl > 0]) /
            config['NULLING']['referenceval'])

        ax3.plot(itcounter, rmsfluxes)
        #w5 = plt.plot(itcounter, maxfluxes)
        #w5 = plt.plot(itcounter, totalfluxes)
        ax1.set_title('Iteration: ' + str(iteration) + ',  Mean: ' +
                      str(meanfluxes[iteration]) + ',  Max: ' +
                      str(maxfluxes[iteration]))
        w1.set_data(np.log(np.abs(field_ctrl)) + boarder)

        w1.autoscale()
        plt.draw()
        plt.pause(0.02)

        if iteration > 0:
            try:
                printstats(field_im, speckleslist)
            except:
                pass
            flh.writeout(current_flatmap, 'latestiteration.fits')

        # ans = raw_input('Do you want to run a speckle nulling iteration[Y/N]?')
        ans = 'Y'
        if ans == 'N':
            flatmapans = eval(
                input('Do you want to reload the' +
                      'flatmap/centoffs you started with[Y/N]?'))
            if flatmapans == 'Y':
                print("Reloading initial flatmap/centoffs")

                if use_centoffs == False:
                    status = ao.load_new_flatmap((initial_flatmap))
                if use_centoffs == True:
                    status = ao.load_new_centoffs((initial_centoffs))
                #ao.load_new_flatmap(initial_flatmap)
            break

        print(('Iteration ' + str(iteration) + ' total_intensity: ' +
               str(np.sum(field_ctrl))))
        #return a list of points
        print("computing interesting bright spots")

        #note indices and coordinates are reversed
        ijofinterest = identify_bright_points(field_ctrl, controlregion)
        xyofinterest = [p[::-1] for p in ijofinterest]

        print(("computed ", str(len(xyofinterest)), " bright spots"))
        max_specks = config['DETECTION']['max_speckles']

        #if len(xyofinterest)>50:
        #    xyofinterest = xyofinterest[0:49]

        if len(xyofinterest) < max_specks:
            max_specks = len(xyofinterest)

        fps = filterpoints(xyofinterest,
                           max=max_specks,
                           rad=config['NULLING']['exclusionzone'])
        print(fps)
        print("creating speckle objects")
        speckleslist = [speckle(field_im, xy[0], xy[1], config) for xy in fps]
        speckleslist = [x for x in speckleslist if (x.intensity) > 0]
        #old way--filter the speckles
        #speckleslist =[speckle(field_im, xy[0], xy[1], config) for xy in xyofinterest]
        #speckleslist = filterspeckles(speckleslist, max = max_specks)
        phases = null_params['phases']
        # phases = [-np.pi/2.,0,np.pi/2.,np.pi]
        for idx, phase in enumerate(phases):
            print(("Phase ", phase))
            phaseflat = 0
            allspeck_aps = 0
            #put in sine waves at speckle locations
            for speck in speckleslist:
                #XXX
                # phaseflat= phaseflat+speck.generate_flatmap(phase)
                phaseflat = speck.generate_flatmap(phase)
                # quicklook_im(speck.generate_flatmap(phase), logAmp=False)
                allspeck_aps = allspeck_aps + speck.aperture
            print('here')
            ax2.set_title('Phase: ' + str(phase))
            if idx == 0:
                # w1.set_data( (allspeck_aps*field_ctrl)-0.95*field_ctrl)
                w1.set_data(
                    np.log(np.abs((allspeck_aps * field_im) -
                                  0.95 * field_im)) + boarder)
                w1.autoscale()
                plt.draw()
            #w1.set_data(field_ctrl); w1.autoscale(); plt.draw()

            phaseflat = phaseflat * aperturemask
            # plt.figure()
            # plt.imshow(allspeck_aps)
            # plt.show()
            # ans = raw_input('press enter')
            wf_temp = copy.copy(wfo)
            if use_centoffs == False:
                status = ao.load_new_flatmap(current_flatmap + phaseflat,
                                             wf_temp)
            # if use_centoffs == True:
            #     status = ao.load_new_centoffs(current_centoffs+
            #                  fmf.convert_flatmap_centoffs(phaseflat))
            tp.variable = proper.prop_get_phase(wf_temp)[20, 20]
            print(('speck phase', tp.variable, 'intensity',
                   proper.prop_get_amplitude(wf_temp)[20, 20]))
            # plt.show(block=True)
            # quicklook_wf(wf_temp, show=True)

            phaseim = camera.take_src_return_imagedata(wf_temp, exptime=exp)
            # quicklook_im(phaseim, show=True)
            phaseim = pre.equalize_image(phaseim, **bgds)
            # quicklook_im(phaseim, show=True)
            w2.set_data(np.log(np.abs(phaseim * controlregion)))
            w2.autoscale()
            plt.draw()
            plt.pause(0.02)

            # w4.set_data(range(128), np.sum(np.eye(tp.grid_size)*proper.prop_get_amplitude(wf_temp),axis=1))#ax4.plot(range(128),  proper.prop_get_amplitude(wf_temp)[20])#np.abs(field_im[20]))#+boarder)
            w4.set_data(
                list(range(128)),
                proper.prop_get_amplitude(wf_temp)[64]
            )  # ax4.plot(range(128),  proper.prop_get_amplitude(wf_temp)[20])#np.abs(field_im[20]))#+boarder)
            ax4.set_xlim([0, 128])
            ax4.set_ylim([0, 0.2])

            print("recomputing intensities")
            for speck in speckleslist:
                phase_int = speck.recompute_intensity(phaseim)
                speck.phase_intensities[idx] = phase_int

            print((speck.phase_intensities))
            time.sleep(3)
        # if use_centoffs == False:
        #     ao.load_new_flatmap(current_flatmap, wf_temp)
        # # if use_centoffs == True:
        # #     ao.load_new_centoffs(current_centoffs)

        if config['NULLING']['null_gain'] == False:
            defaultgain = config['NULLING']['default_flatmap_gain']

            nullmap = generate_phase_nullmap(speckleslist, defaultgain, phases)
            nullmap = nullmap * aperturemask
            if use_centoffs == False:
                # ao.load_new_flatmap(current_flatmap + nullmap, wfo)
                ao.load_new_flatmap(nullmap, wfo)
            # FPWFS.quicklook_wf(wfo)
            # camera.take_src_return_imagedata(wfo, exptime=exp)
            # if use_centoffs == True:
            #     ao.load_new_centoffs(current_centoffs+ fmf.convert_flatmap_centoffs(nullmap))

        # ans = raw_input('press enter')
        if config['NULLING']['null_gain'] == True:
            ##NOW CALCULATE GAIN NULLS

            print("DETERMINING NULL GAINS")
            gains = config['NULLING']['amplitudegains']
            for idx, gain in enumerate(gains):
                print("Checking optimal gains")
                nullmap = generate_phase_nullmap(speckleslist, gain, phases)
                nullmap = nullmap * aperturemask

                wf_temp = copy.copy(wfo)
                if use_centoffs == False:
                    ao.load_new_flatmap(current_flatmap + nullmap, wf_temp)
                # if use_centoffs == True:
                #     ao.load_new_centoffs(current_centoffs+ fmf.convert_flatmap_centoffs(nullmap))

                ampim = camera.take_src_return_imagedata(wf_temp, exptime=exp)
                # quicklook_wf(wf_temp)
                ampim = pre.equalize_image(ampim, **bgds)
                w2.set_data(np.log(np.abs(ampim * controlregion)))
                ax2.set_title('Gain: ' + str(gain))
                w2.autoscale()
                plt.draw()
                plt.pause(0.02)
                for speck in speckleslist:
                    amp_int = speck.recompute_intensity(ampim)
                    speck.gain_intensities[idx] = amp_int
                print((speck.gain_intensities))
                w4.set_data(
                    list(range(128)),
                    proper.prop_get_amplitude(wf_temp)[64]
                )  #ax4.plot(range(128),  proper.prop_get_amplitude(wf_temp)[20])#np.abs(field_im[20]))#+boarder)
                ax4.set_xlim([0, 128])
                ax4.set_ylim([0, 0.2])
            for speck in speckleslist:
                speck.compute_null_gain()
            supernullmap = generate_super_nullmap(speckleslist, phases)
            print(
                "Loading supernullmap now that optimal gains have been found!")
            supernullmap = supernullmap * aperturemask
            if use_centoffs == False:
                # ao.load_new_flatmap(current_flatmap + supernullmap, wfo)
                ao.load_new_flatmap(supernullmap, wfo)
            # FPWFS.quicklook_wf(wfo)
            # quicklook_im(supernullmap,logAmp=False, show=True)

            # camera.take_src_return_imagedata(wfo, exptime=exp)
            # if use_centoffs == True:
            #     ao.load_new_centoffs(current_centoffs+ fmf.convert_flatmap_centoffs(supernullmap))
            #ao.load_new_flatmap(supernullmap)
            # w3.set_data(nullmap)

            # plt.draw()
        # w4.set_data(np.log(np.abs(field_im))+boarder)
        # plt.draw()
        # w4.autoscale();
        # quicklook_im(field_im, logAmp=False)
        quicklook_wf(wfo)
        plt.show(block=True)

        # ans = raw_input('press enter')
        # try:
        #     check = raw_input("would you like to continue?: ")
        # except EOFError:
        #     print ("Error: EOF or empty input!")
        #     check = ""
        # print check
        plt.show(block=False)
Beispiel #16
0
def lyotstop(wf, conf, RAVC):
    input_dir = conf['INPUT_DIR']
    diam = conf['DIAM']
    npupil = conf['NPUPIL']
    spiders_angle = conf['SPIDERS_ANGLE']
    r_obstr = conf['R_OBSTR']
    Debug = conf['DEBUG']
    Debug_print = conf['DEBUG_PRINT']
    LS_amplitude_apodizer_file = conf['AMP_APODIZER']
    LS_misalignment = np.array(conf['LS_MIS_ALIGN'])
    if conf['PHASE_APODIZER_FILE'] == 0:
        LS_phase_apodizer_file = 0
    else:
        LS_phase_apodizer_file = fits.getdata(input_dir + '/' +
                                              conf['PHASE_APODIZER_FILE'])
    LS = conf['LYOT_STOP']
    LS_parameters = np.array(conf['LS_PARA'])
    n = proper.prop_get_gridsize(wf)
    if (RAVC == True):  # define the inner radius of the Lyot Stop
        t1_opt = 1. - 1. / 4 * (
            r_obstr**2 + r_obstr * (math.sqrt(r_obstr**2 + 8.))
        )  # define the apodizer transmission [Mawet2013]
        R1_opt = (r_obstr / math.sqrt(1. - t1_opt)
                  )  # define teh apodizer radius [Mawet2013]
        r_LS = R1_opt + LS_parameters[
            1]  # when a Ring apodizer is present, the inner LS has to have at least the value of the apodizer radius
    else:
        r_LS = r_obstr + LS_parameters[
            1]  # when no apodizer, the LS has to have at least the radius of the pupil central obstruction
    if LS == True:  # apply the LS
        if (Debug_print == True):
            print("LS parameters: ", LS_parameters)
        proper.prop_circular_aperture(wf,
                                      LS_parameters[0],
                                      LS_misalignment[0],
                                      LS_misalignment[1],
                                      NORM=True)
        proper.prop_circular_obscuration(wf,
                                         r_LS,
                                         LS_misalignment[0],
                                         LS_misalignment[1],
                                         NORM=True)
        if (LS_parameters[2] != 0):
            for iter in range(0, len(spiders_angle)):
                if (Debug_print == True):
                    print("LS_misalignment: ", LS_misalignment)
                proper.prop_rectangular_obscuration(
                    wf,
                    LS_parameters[2],
                    2 * diam,
                    LS_misalignment[0],
                    LS_misalignment[1],
                    ROTATION=spiders_angle[iter])  # define the spiders
        if (Debug == True):
            out_dir = str('./output_files/')
            fits.writeto(
                out_dir + '_Lyot_stop.fits',
                proper.prop_get_amplitude(wf)[int(n / 2) -
                                              int(npupil / 2 + 50):int(n / 2) +
                                              int(npupil / 2 + 50),
                                              int(n / 2) -
                                              int(npupil / 2 + 50):int(n / 2) +
                                              int(npupil / 2 + 50)],
                overwrite=True)

    if (isinstance(LS_phase_apodizer_file, (list, tuple, np.ndarray)) == True):
        xc_pixels = int(LS_misalignment[3] * npupil)
        yc_pixels = int(LS_misalignment[4] * npupil)
        apodizer_pixels = (LS_phase_apodizer_file.shape)[0]  ## fits file size
        scaling_factor = float(npupil) / float(
            apodizer_pixels
        )  ## scaling factor between the fits file size and the pupil size of the simulation

        #        scaling_factor = float(npupil)/float(pupil_pixels) ## scaling factor between the fits file size and the pupil size of the simulation
        if (Debug_print == True):
            print("scaling_factor: ", scaling_factor)
        apodizer_scale = cv2.resize(
            LS_phase_apodizer_file.astype(np.float32), (0, 0),
            fx=scaling_factor,
            fy=scaling_factor,
            interpolation=cv2.INTER_LINEAR
        )  # scale the pupil to the pupil size of the simualtions
        if (Debug_print == True):
            print("apodizer_resample", apodizer_scale.shape)
        apodizer_large = np.zeros(
            (n, n))  # define an array of n-0s, where to insert the pupuil
        if (Debug_print == True):
            print("npupil: ", npupil)
        apodizer_large[
            int(n / 2) + 1 - int(npupil / 2) - 1 + xc_pixels:int(n / 2) + 1 +
            int(npupil / 2) + xc_pixels,
            int(n / 2) + 1 - int(npupil / 2) - 1 + yc_pixels:int(n / 2) + 1 +
            int(npupil / 2) +
            yc_pixels] = apodizer_scale  # insert the scaled pupil into the 0s grid
        phase_multiply = np.array(np.zeros((n, n)),
                                  dtype=complex)  # create a complex array
        phase_multiply.imag = apodizer_large  # define the imaginary part of the complex array as the atm screen
        apodizer = np.exp(phase_multiply)
        proper.prop_multiply(wf, apodizer)
        if (Debug == True):
            fits.writeto('LS_apodizer.fits',
                         proper.prop_get_phase(wf),
                         overwrite=True)

    if (isinstance(LS_amplitude_apodizer_file,
                   (list, tuple, np.ndarray)) == True):
        print('4th')
        xc_pixels = int(LS_misalignment[0] * npupil)
        yc_pixels = int(LS_misalignment[1] * npupil)
        apodizer_pixels = (
            LS_amplitude_apodizer_file.shape)[0]  ## fits file size
        scaling_factor = float(npupil) / float(
            pupil_pixels
        )  ## scaling factor between the fits file size and the pupil size of the simulation
        if (Debug_print == True):
            print("scaling_factor: ", scaling_factor)
            apodizer_scale = cv2.resize(
                amplitude_apodizer_file.astype(np.float32), (0, 0),
                fx=scaling_factor,
                fy=scaling_factor,
                interpolation=cv2.INTER_LINEAR
            )  # scale the pupil to the pupil size of the simualtions
        if (Debug_print == True):
            print("apodizer_resample", apodizer_scale.shape)
        apodizer_large = np.zeros(
            (n, n))  # define an array of n-0s, where to insert the pupuil
        if (Debug_print == True):
            print("grid_size: ", n)
            print("npupil: ", npupil)
        apodizer_large[
            int(n / 2) + 1 - int(npupil / 2) - 1 + xc_pixels:int(n / 2) + 1 +
            int(npupil / 2) + xc_pixels,
            int(n / 2) + 1 - int(npupil / 2) - 1 + yc_pixels:int(n / 2) + 1 +
            int(npupil / 2) +
            yc_pixels] = apodizer_scale  # insert the scaled pupil into the 0s grid
        apodizer = apodizer_large
        proper.prop_multiply(wf, apodizer)
        if (Debug == True):
            fits.writeto('LS_apodizer.fits',
                         proper.prop_get_amplitude(wf),
                         overwrite=True)

    return wf
Beispiel #17
0
def scexao_model(lmda, grid_size, kwargs):
    """
    propagates instantaneous complex E-field thru Subaru from the DM through SCExAO

    uses PyPROPER3 to generate the complex E-field at the pupil plane, then propagates it through SCExAO 50x50 DM,
        then coronagraph, to the focal plane
    :returns spectral cube at instantaneous time in the focal_plane()
    """
    # print("Propagating Broadband Wavefront Through Subaru")

    # Initialize the Wavefront in Proper
    wfo = proper.prop_begin(entrance_d, lmda, grid_size, beam_ratio)

    # Defines aperture (baffle-before primary)
    proper.prop_circular_aperture(wfo, entrance_d / 2)
    proper.prop_define_entrance(wfo)  # normalizes abs intensity

    # Test Sampling
    if kwargs['verbose'] and kwargs['ix'] == 0:
        check1 = proper.prop_get_sampling(wfo)
        print(
            f"\n\tDM Pupil Plane\n"
            f"sampling at aperture is {check1 * 1e3:.4f} mm\n"
            f"Total Sim is {check1 * 1e3 * grid_size:.2f}x{check1 * 1e3 * grid_size:.2f} mm\n"
            f"Diameter of beam is {check1 * 1e3 * grid_size * beam_ratio:.4f} mm over {grid_size * beam_ratio} pix"
        )

    # SCExAO Reimaging 1
    proper.prop_lens(
        wfo, fl_SxOAPG)  # produces f#14 beam (approx exit beam of AO188)
    proper.prop_propagate(wfo, fl_SxOAPG * 2)  # move to second pupil
    if kwargs['verbose'] and kwargs['ix'] == 0:
        print(f"initial f# is {proper.prop_get_fratio(wfo):.2f}\n")

    ########################################
    # Import/Apply Actual DM Map
    # #######################################
    plot_flag = False
    if kwargs['verbose'] and kwargs['ix'] == 0:
        plot_flag = True

    dm_map = kwargs['map']
    errormap(wfo,
             dm_map,
             SAMPLING=dm_pitch,
             MIRROR_SURFACE=True,
             MASKING=True,
             BR=beam_ratio,
             PLOT=plot_flag)  # MICRONS=True

    if kwargs['verbose'] and kwargs['ix'] == 0:
        fig, subplot = plt.subplots(nrows=1, ncols=2, figsize=(12, 5))
        ax1, ax2 = subplot.flatten()
        fig.suptitle('SCExAO Model WFO after errormap',
                     fontweight='bold',
                     fontsize=14)
        ax1.imshow(proper.prop_get_amplitude(wfo), interpolation='none'
                   )  # np.abs(proper.prop_shift_center(wfo.wfarr))**2
        ax1.set_title('Amplitude')
        ax2.imshow(
            proper.prop_get_phase(wfo),
            interpolation=
            'none',  # np.angle(proper.prop_shift_center(wfo.wfarr))
            vmin=-1 * np.pi,
            vmax=1 * np.pi,
            cmap='hsv')  # , cmap='hsv'
        ax2.set_title('Phase')

    # ------------------------------------------------
    # SCExAO Reimaging 2
    proper.prop_lens(wfo, fl_SxOAPG)
    proper.prop_propagate(wfo,
                          fl_SxOAPG)  # focus at exit of DM telescope system
    proper.prop_lens(wfo, fl_SxOAPG)
    proper.prop_propagate(wfo,
                          fl_SxOAPG)  # focus at exit of DM telescope system

    # # Coronagraph
    SubaruPupil(wfo)  # focal plane mask
    # if kwargs['verbose'] and kwargs['ix']==0:
    #     fig, subplot = plt.subplots(nrows=1, ncols=2, figsize=(12, 5))
    #     ax1, ax2 = subplot.flatten()
    #     fig.suptitle('SCExAO Model WFO after FPM', fontweight='bold', fontsize=14)
    #     # ax.imshow(dm_map, interpolation='none')
    #     ax1.imshow(np.abs(proper.prop_shift_center(wfo.wfarr))**2, interpolation='none', norm=LogNorm(vmin=1e-7,vmax=1e-2))
    #     ax1.set_title('Amplitude')
    #     ax2.imshow(np.angle(proper.prop_shift_center(wfo.wfarr)), interpolation='none',
    #                vmin=-2*np.pi, vmax=2*np.pi, cmap='hsv')  # , cmap='hsv'
    #     ax2.set_title('Phase')
    proper.prop_propagate(wfo, fl_SxOAPG)
    proper.prop_lens(wfo, fl_SxOAPG)
    proper.prop_propagate(wfo, fl_SxOAPG)  # middle of 2f system
    proper.prop_circular_aperture(wfo, lyot_size, NORM=True)  # lyot stop
    proper.prop_propagate(wfo, fl_SxOAPG)  #
    proper.prop_lens(wfo, fl_SxOAPG)  # exit lens of gaussian telescope
    proper.prop_propagate(wfo, fl_SxOAPG)  # to focus

    # MEC Pickoff reimager.
    proper.prop_propagate(wfo, mec_parax_fl)  # to another pupil
    proper.prop_lens(
        wfo, mec_parax_fl)  # collimating lens, pupil size should be 8 mm
    proper.prop_propagate(wfo, mec1_fl +
                          .0142557)  # mec1_fl  .054  mec1_fl+.0101057
    # if kwargs['verbose'] and kwargs['ix']==0:
    #     current = proper.prop_get_beamradius(wfo)
    #     print(f'Beam Radius after SCExAO exit (at MEC foreoptics entrance) is {current*1e3:.3f} mm\n'
    #           f'current f# is {proper.prop_get_fratio(wfo):.2f}\n')

    # ##################################
    # MEC Optics Box
    # ###################################
    proper.prop_circular_aperture(wfo,
                                  0.00866)  # reading off the zemax diameter
    proper.prop_lens(wfo, mec1_fl)  # MEC lens 1
    proper.prop_propagate(wfo,
                          mec_l1_l2)  # there is a image plane at z=mec1_fl
    proper.prop_lens(wfo, mec2_fl)  # MEC lens 2 (tiny lens)
    proper.prop_propagate(wfo, mec_l2_l3)
    proper.prop_lens(wfo, mec3_fl)  # MEC lens 3
    proper.prop_propagate(wfo, mec3_fl,
                          TO_PLANE=False)  # , TO_PLANE=True mec_l3_focus

    # #######################################
    # Focal Plane
    # #######################################
    # Check Sampling in focal plane
    # shifts wfo from Fourier Space (origin==lower left corner) to object space (origin==center)
    # wf, samp = proper.prop_end(wfo, NoAbs=True)
    wf = proper.prop_shift_center(wfo.wfarr)
    wf = extract_center(wf, new_size=np.array(kwargs['psf_size']))
    samp = proper.prop_get_sampling(wfo)
    smp_asec = proper.prop_get_sampling_arcsec(wfo)

    if kwargs['verbose'] and kwargs['ix'] == 0:
        fig, subplot = plt.subplots(nrows=1, ncols=2, figsize=(12, 5))
        fig.subplots_adjust(left=0.08, hspace=.4, wspace=0.2)

        ax1, ax2 = subplot.flatten()
        fig.suptitle('SCExAO Model Focal Plane',
                     fontweight='bold',
                     fontsize=14)
        tic_spacing, tic_labels, axlabel = scale_lD(
            wfo, newsize=kwargs['psf_size'][0])
        tic_spacing[0] = tic_spacing[0] + 1  # hack for edge effects
        tic_spacing[-1] = tic_spacing[-1] - 1  # hack for edge effects

        im = ax1.imshow(
            np.abs(wf)**2,
            interpolation='none',
            norm=LogNorm(
                vmin=1e-7,
                vmax=1e-2))  # np.abs(proper.prop_shift_center(wfo.wfarr))**2
        ax1.set_xticks(tic_spacing)
        ax1.set_xticklabels(tic_labels)
        ax1.set_yticks(tic_spacing)
        ax1.set_yticklabels(tic_labels)
        ax1.set_ylabel(axlabel, fontsize=8)
        add_colorbar(im)

        im = ax2.imshow(np.angle(wf),
                        interpolation='none',
                        vmin=-np.pi,
                        vmax=np.pi,
                        cmap='hsv')
        ax2.set_xticks(tic_spacing)
        ax2.set_xticklabels(tic_labels)
        ax2.set_yticks(tic_spacing)
        ax2.set_yticklabels(tic_labels)
        ax2.set_ylabel(axlabel, fontsize=8)
        add_colorbar(im)

    if kwargs['verbose'] and kwargs['ix'] == 0:
        print(
            f"\nFocal Plane\n"
            f"sampling at focal plane is {samp*1e6:.1f} um ~= {smp_asec * 1e3:.4f} mas\n"
            f"\tfull FOV is {samp * kwargs['psf_size'][0] * 1e3:.2f} x {samp * kwargs['psf_size'][1] * 1e3:.2f} mm "
        )
        # s_rad = proper.prop_get_sampling_radians(wfo)
        # print(f"sampling at focal plane is {s_rad * 1e6:.6f} urad")
        print(f'final focal ratio is {proper.prop_get_fratio(wfo)}')

        print(f"Finished simulation")

    return wf, samp
Beispiel #18
0
def lyotstop(wf, diam, r_obstr, npupil, RAVC, LS, LS_parameters, spiders_angle, LS_phase_apodizer_file, LS_amplitude_apodizer_file, LS_misalignment, path, Debug_print, Debug):

    if (RAVC==True): # define the inner radius of the Lyot Stop
        t1_opt = 1. - 1./4*(r_obstr**2 + r_obstr*(math.sqrt(r_obstr**2 + 8.))) # define the apodizer transmission [Mawet2013]
        R1_opt = (r_obstr/math.sqrt(1. - t1_opt)) # define teh apodizer radius [Mawet2013]
        r_LS = R1_opt + LS_parameters[1] # when a Ring apodizer is present, the inner LS has to have at least the value of the apodizer radius
    else:
        r_LS = r_obstr + LS_parameters[1] # when no apodizer, the LS has to have at least the radius of the pupil central obstruction
    if LS==True: # apply the LS
        if (Debug_print==True):
            print("LS parameters: ", LS_parameters)
        proper.prop_circular_aperture(wf, LS_parameters[0], LS_misalignment[0], LS_misalignment[1], NORM=True)
        proper.prop_circular_obscuration(wf, r_LS, LS_misalignment[0], LS_misalignment[1], NORM=True)
        if (LS_parameters[2]!=0):
            for iter in range(0,len(spiders_angle)):
                if (Debug_print==True):
                    print("LS_misalignment: ", LS_misalignment)
                proper.prop_rectangular_obscuration(wf, LS_parameters[2], 2*diam,LS_misalignment[0], LS_misalignment[1], ROTATION=spiders_angle[iter]) # define the spiders

    
    if (isinstance(LS_phase_apodizer_file, (list, tuple, np.ndarray)) == True):
        xc_pixels = int(LS_misalignment[3]*npupil)
        yc_pixels = int(LS_misalignment[4]*npupil)
        apodizer_pixels = (LS_phase_apodizer_file.shape)[0]## fits file size
        scaling_factor = float(npupil)/float(pupil_pixels) ## scaling factor between the fits file size and the pupil size of the simulation
        if (Debug_print==True):
            print ("scaling_factor: ", scaling_factor)
        apodizer_scale = cv2.resize(phase_apodizer_file.astype(np.float32), (0,0), fx=scaling_factor, fy=scaling_factor, interpolation=cv2.INTER_LINEAR) # scale the pupil to the pupil size of the simualtions
        if (Debug_print==True):
            print ("apodizer_resample", apodizer_scale.shape)
        apodizer_large = np.zeros((n,n)) # define an array of n-0s, where to insert the pupuil
        if (Debug_print==True):
            print("n: ", n)
            print("npupil: ", npupil)
        apodizer_large[int(n/2)+1-int(npupil/2)-1 + xc_pixels:int(n/2)+1+int(npupil/2)+ xc_pixels,int(n/2)+1-int(npupil/2)-1+ yc_pixels:int(n/2)+1+int(npupil/2)+ yc_pixels] =apodizer_scale # insert the scaled pupil into the 0s grid
        phase_multiply = np.array(np.zeros((n,n)), dtype=complex) # create a complex array
        phase_multiply.imag = apodizer_large # define the imaginary part of the complex array as the atm screen
        apodizer = np.exp(phase_multiply)
        proper.prop_multiply(wf, apodizer)
        if (Debug == True):
            fits.writeto(path + 'LS_apodizer.fits', proper.prop_get_phase(wf), overwrite=True)

    
    
    if (isinstance(LS_amplitude_apodizer_file, (list, tuple, np.ndarray)) == True):
        xc_pixels = int(LS_misalignment[0]*npupil)
        yc_pixels = int(LS_misalignment[1]*npupil)
        apodizer_pixels = (LS_amplitude_apodizer_file.shape)[0]## fits file size
        scaling_factor = float(npupil)/float(pupil_pixels) ## scaling factor between the fits file size and the pupil size of the simulation
        if (Debug_print==True):
            print ("scaling_factor: ", scaling_factor)
            apodizer_scale = cv2.resize(amplitude_apodizer_file.astype(np.float32), (0,0), fx=scaling_factor, fy=scaling_factor, interpolation=cv2.INTER_LINEAR) # scale the pupil to the pupil size of the simualtions
        if (Debug_print==True):
            print ("apodizer_resample", apodizer_scale.shape)
        apodizer_large = np.zeros((n,n)) # define an array of n-0s, where to insert the pupuil
        if (Debug_print==True):
            print("n: ", n)
            print("npupil: ", npupil)
        apodizer_large[int(n/2)+1-int(npupil/2)-1 + xc_pixels:int(n/2)+1+int(npupil/2)+ xc_pixels,int(n/2)+1-int(npupil/2)-1+ yc_pixels:int(n/2)+1+int(npupil/2)+ yc_pixels] =apodizer_scale # insert the scaled pupil into the 0s grid
        apodizer = apodizer_large
        proper.prop_multiply(wf, apodizer)
        if (Debug == True):
            fits.writeto(path + 'LS_apodizer.fits', proper.prop_get_amplitude(wf), overwrite=True)





    return