Example #1
0
def wavefront_abberations(wfo,
                          npupil,
                          atm_screen,
                          NCPA,
                          Island_Piston,
                          TILT=[0, 0],
                          Debug='False',
                          Debug_print='False',
                          prefix='test'):

    lamda = proper.prop_get_wavelength(wfo)

    if (isinstance(atm_screen, (list, tuple, np.ndarray)) == True) and (
            atm_screen.ndim >= 2):  # when the atmosphere is present
        atmosphere(wfo, npupil, atm_screen, Debug_print, Debug)

    if (isinstance(NCPA, (list, tuple, np.ndarray))
            == True) and (NCPA.ndim >= 2):  # when the atmosphere is present
        NCPA_application(wfo, npupil, NCPA, Debug_print, Debug)

    if (all(v == 0
            for v in Island_Piston) == False):  # when the piston is present
        island_effect_piston(wfo, npupil, Island_Piston, Debug_print, Debug)

    if (TILT.any != 0.):  # when tip/tilt
        if (Debug_print == True):
            print("TILT: ", TILT)
            print("lamda: ", lamda)
        tiptilt = (np.multiply(
            TILT, lamda
        )) / 4  # translate the tip/tilt from lambda/D into RMS phase errors
        proper.prop_zernikes(wfo, [2, 3], tiptilt)  # 2-->xtilt, 3-->ytilt

    return wfo
Example #2
0
def atmosphere(wf, npupil, atm_screen, Debug_print, Debug):
    
    n = int(proper.prop_get_gridsize(wf))
    lamda=proper.prop_get_wavelength(wf) #save the wavelength value [m] into lamda

    screen = atm_screen # read the phase screen
    if (Debug_print == True):
        print ("screen", screen.shape)
    screen_pixels = (screen.shape)[0] # size of the phase screen
    scaling_factor_screen = float(npupil)/float(screen_pixels) # scaling factor the phase screen to the simulation pupil size
    if (Debug_print == True):
        print ("scaling_factor_screen: ", scaling_factor_screen)
    screen_scale = cv2.resize(screen.astype(np.float32), (0,0), fx=scaling_factor_screen, fy=scaling_factor_screen, interpolation=cv2.INTER_LINEAR) # scale the the phase screen to the simulation pupil size
    if (Debug_print == True):
        print ("screen_resample", screen_scale.shape)
    screen_large = np.zeros((n,n)) # define an array of n-0s, where to insert the screen
    if (Debug_print == True):
        print("n: ", n)
        print("npupil: ", npupil)
    screen_large[int(n/2)+1-int(npupil/2)-1:int(n/2)+1+int(npupil/2),int(n/2)+1-int(npupil/2)-1:int(n/2)+1+int(npupil/2)] =screen_scale # insert the scaled screen into the 0s grid


    lambda2=lamda/(1e-6) # need to use lambda in microns
    screen_atm = np.exp(1j*screen_large/lambda2*2*math.pi)
    proper.prop_multiply(wf, screen_atm) # multiply the atm screen to teh wavefront


    return wf
Example #3
0
def NCPA_application(wf, npupil, NCPA, path, Debug_print, Debug):
    
    n = int(proper.prop_get_gridsize(wf))
    lamda=proper.prop_get_wavelength(wf) #save the wavelength value [m] into lamda
    
    if (Debug_print == True):
        print ("NCPA", NCPA.shape)
    NCPA_pixels = (NCPA.shape)[0] # size of the phase screen
    scaling_factor_NCPA = float(npupil)/float(NCPA_pixels) # scaling factor the phase screen to the simulation pupil size
    if (Debug_print == True):
        print ("scaling_factor_NCPA: ", scaling_factor_NCPA)
    NCPA_scale = cv2.resize(NCPA.astype(np.float32), (0,0), fx=scaling_factor_NCPA, fy=scaling_factor_NCPA, interpolation=cv2.INTER_LINEAR) # scale the the phase screen to the simulation pupil size
    if (Debug_print == True):
        print ("NCPA_resample", NCPA_scale.shape)
    NCPA_large = np.zeros((n,n)) # define an array of n-0s, where to insert the screen
    if (Debug_print == True):
        print("n: ", n)
        print("npupil: ", npupil)
    NCPA_large[int(n/2)+1-int(npupil/2)-1:int(n/2)+1+int(npupil/2),int(n/2)+1-int(npupil/2)-1:int(n/2)+1+int(npupil/2)] =NCPA_scale # insert the scaled screen into the 0s grid
    if (Debug == 1):
        fits.writeto(path + 'NCPA_large.fits', NCPA_large, overwrite=True) # fits file for the screen
    
    
    lambda2=lamda/(1e-6) # need to use lambda in microns
    screen_atm = np.exp(1j*NCPA_large/lambda2*2*math.pi)
    proper.prop_multiply(wf, screen_atm) # multiply the atm screen to teh wavefront

#rms_error = NCPA[0]#30nm-- RMS wavefront error in meters
#c_freq = NCPA[1]# 5  ;-- correlation frequency (cycles/meter)
#high_power = NCPA[2]#3.0  ;-- high frequency falloff (r^-high_power)
#RANDOM_MAP = readfits('RANDOM_MAP.fits')
#proper.prop_psd_errormap_mod( wf, rms_error, c_freq, high_power, RMS=True)
    
    
    return
Example #4
0
def coronagraph(wfo, f_lens, occulter_type, diam):
    
    proper.prop_lens(wfo, f_lens, "coronagraph imaging lens")
    proper.prop_propagate(wfo, f_lens, "occulter")
    
    # occulter sizes are specified here in units of lambda/diameter;
    # convert lambda/diam to radians then to meters
    lamda = proper.prop_get_wavelength(wfo)
    occrad = 4.                           # occulter radius in lam/D
    occrad_rad = occrad * lamda / diam    # occulter radius in radians
    dx_m = proper.prop_get_sampling(wfo)
    dx_rad = proper.prop_get_sampling_radians(wfo)    
    occrad_m = occrad_rad * dx_m / dx_rad  # occulter radius in meters

    plt.figure(figsize=(12,8))
        
    if occulter_type == "GAUSSIAN":
        r = proper.prop_radius(wfo)
        h = np.sqrt(-0.5 * occrad_m**2 / np.log(1 - np.sqrt(0.5)))
        gauss_spot = 1 - np.exp(-0.5 * (r/h)**2)
        proper.prop_multiply(wfo, gauss_spot)
        plt.suptitle("Gaussian spot", fontsize = 18)
    elif occulter_type == "SOLID":
        proper.prop_circular_obscuration(wfo, occrad_m)
        plt.suptitle("Solid spot", fontsize = 18)
    elif occulter_type == "8TH_ORDER":
        proper.prop_8th_order_mask(wfo, occrad, CIRCULAR = True)
        plt.suptitle("8th order band limited spot", fontsize = 18)
        
    # After occulter
    plt.subplot(1,2,1)
    plt.imshow(np.sqrt(proper.prop_get_amplitude(wfo)), origin = "lower", cmap = plt.cm.gray)
    plt.text(200, 10, "After Occulter", color = "w")
        
    proper.prop_propagate(wfo, f_lens, "pupil reimaging lens")  
    proper.prop_lens(wfo, f_lens, "pupil reimaging lens")
    
    proper.prop_propagate(wfo, 2*f_lens, "lyot stop")

    plt.subplot(1,2,2)        
    plt.imshow(proper.prop_get_amplitude(wfo)**0.2, origin = "lower", cmap = plt.cm.gray)
    plt.text(200, 10, "Before Lyot Stop", color = "w")
    plt.show()   
    
    if occulter_type == "GAUSSIAN":
        proper.prop_circular_aperture(wfo, 0.25, NORM = True)
    elif occulter_type == "SOLID":
        proper.prop_circular_aperture(wfo, 0.84, NORM = True)
    elif occulter_type == "8TH_ORDER":
        proper.prop_circular_aperture(wfo, 0.50, NORM = True)
    
    proper.prop_propagate(wfo, f_lens, "reimaging lens")
    proper.prop_lens(wfo, f_lens, "reimaging lens")
    
    proper.prop_propagate(wfo, f_lens, "final focus")
    
    return
Example #5
0
def quick_ao(wfo, iwf, f_lens, beam_ratio, iter, CPA_map):
    nact = tp.ao_act  # 49                       # number of DM actuators along one axis
    nact_across_pupil = nact - 2  # 47          # number of DM actuators across pupil
    dm_xc = (nact / 2) - 0.5
    dm_yc = (nact / 2) - 0.5
    d_beam = 2 * proper.prop_get_beamradius(wfo)  # beam diameter
    act_spacing = d_beam / nact_across_pupil  # actuator spacing
    # map_spacing = proper.prop_get_sampling(wfo)  # map sampling

    # dm_map = np.zeros((65, 65))
    # quicklook_im(CPA_map, logAmp=False, vmin=-3.14, vmax=3.14)
    dm_map = CPA_map[tp.grid_size / 2 -
                     (beam_ratio * tp.grid_size / 2):tp.grid_size / 2 +
                     (beam_ratio * tp.grid_size / 2) + 1, tp.grid_size / 2 -
                     (beam_ratio * tp.grid_size / 2):tp.grid_size / 2 +
                     (beam_ratio * tp.grid_size / 2) + 1]
    # quicklook_im(dm_map, logAmp=False)
    f = interpolate.interp2d(range(dm_map.shape[0]), range(dm_map.shape[0]),
                             dm_map)
    dm_map = f(np.linspace(0, dm_map.shape[0], nact),
               np.linspace(0, dm_map.shape[0], nact))
    # dm_map = proper.prop_magnify(CPA_map, map_spacing / act_spacing, nact)
    # quicklook_im(CPA_map, logAmp=False)
    # quicklook_im(dm_map, logAmp=False)
    # quicklook_wf(wfo)
    if tp.piston_error:
        # dprint('doing this')
        mean_dm_map = np.mean(np.abs(dm_map))
        # var = mean_dm_map/50.
        var = 0.001  # 1e-11
        dm_map = dm_map + np.random.normal(0, var,
                                           (dm_map.shape[0], dm_map.shape[1]))

    dm_map = -dm_map * proper.prop_get_wavelength(wfo) / (4 * np.pi
                                                          )  # <--- here
    # dmap = proper.prop_dm(wfo, dm_map, dm_xc, dm_yc, N_ACT_ACROSS_PUPIL=nact, FIT=True)  # <-- here
    dmap = proper.prop_dm(wfo, dm_map, dm_xc, dm_yc, act_spacing,
                          FIT=True)  # <-- here
    # quicklook_wf(wfo)
    # I = np.real(wfo.wfarr)
    # Q = np.imag(wfo.wfarr)
    # I = proper.prop_shift_center(I)
    # Q = proper.prop_shift_center(Q)
    #
    # anomaly = int(np.round(beam_ratio*tp.grid_size/2 + tp.grid_size/2))
    # # dprint((anomaly))
    # Q[anomaly] = 0 # 89
    # Q[:, anomaly] = 0
    # I[anomaly] = 0
    # I[:, anomaly] = 0
    # I = proper.prop_shift_center(I)
    # Q = proper.prop_shift_center(Q)
    # wfo.wfarr = I + 1j * Q

    return
Example #6
0
def island_effect_piston(wf, npupil, Island_Piston, path, Debug_print, Debug):

    n = int(proper.prop_get_gridsize(wf))
    lamda=proper.prop_get_wavelength(wf) #save the wavelength value [m] into lamda

    PACKAGE_PATH = os.path.abspath(os.path.join(__file__, os.pardir))
    petal1 = fits.getdata(PACKAGE_PATH+'/1024_pixelsize5mas_petal1_243px.fits')
    petal2 = fits.getdata(PACKAGE_PATH+'/1024_pixelsize5mas_petal2_243px.fits')
    petal3 = fits.getdata(PACKAGE_PATH+'/1024_pixelsize5mas_petal3_243px.fits')
    petal4 = fits.getdata(PACKAGE_PATH+'/1024_pixelsize5mas_petal4_243px.fits')
    petal5 = fits.getdata(PACKAGE_PATH+'/1024_pixelsize5mas_petal5_243px.fits')
    petal6 = fits.getdata(PACKAGE_PATH+'/1024_pixelsize5mas_petal6_243px.fits')

    piston_petal1 = Island_Piston[0]*petal1
    piston_petal2 = Island_Piston[1]*petal2
    piston_petal3 = Island_Piston[2]*petal3
    piston_petal4 = Island_Piston[3]*petal4
    piston_petal5 = Island_Piston[4]*petal5
    piston_petal6 = Island_Piston[5]*petal6

    piston = piston_petal1 + piston_petal2 + piston_petal3 + piston_petal4 + piston_petal5 + piston_petal6

    piston_pixels = (piston.shape)[0]## fits file size
    scaling_factor = float(npupil)/float(piston_pixels) ## scaling factor between the fits file size and the pupil size of the simulation
    if (Debug_print==True):
        print ("scaling_factor: ", scaling_factor)
    piston_scale = cv2.resize(piston.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 ("piston_resample", piston_scale.shape)
    piston_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)
    piston_large[int(n/2)+1-int(npupil/2)-1:int(n/2)+1+int(npupil/2),int(n/2)+1-int(npupil/2)-1:int(n/2)+1+int(npupil/2)] =piston_scale # insert the scaled pupil into the 0s grid
    if (Debug == 1):
        fits.writeto(path+'piston_phase.fits', piston_large, overwrite=True) # fits file for the screen


    lambda2=lamda/(1e-6) # need to use lambda in microns
    piston_phase = np.exp(1j*piston_large/lambda2*2*math.pi)
    proper.prop_multiply(wf, piston_phase) # multiply the atm screen to teh wavefront

    return
Example #7
0
    def set_size(self, wf, size_in_lambda_d=0, size_in_m=0):
        """
        sets size of occulter in m, depending on if input is in units of lambda/D or in m

        :param wf: 2D wavefront
        :param size_in_lambda_d: desired occulter size in units of lambda/D
        :param size_in_m: desired occulter size in m
        :return: occulter size in m
        """
        lamda = proper.prop_get_wavelength(wf)
        dx_m = proper.prop_get_sampling(wf)
        dx_rad = proper.prop_get_sampling_radians(wf)

        if size_in_lambda_d is not 0:
            occrad_rad = size_in_lambda_d * lamda / tp.entrance_d  # occulter radius in radians
            self.size = occrad_rad * dx_m / dx_rad  # occulter radius in meters
        elif size_in_m is not 0:
            self.size = size_in_m
        else:
            raise ValueError('must set occulter size in either m or lambda/D units')
Example #8
0
def polmap( wavefront, polfile, pupil_diam_pix, condition, MUF=1.0 ):
    n = proper.prop_get_gridsize( wavefront )
    lambda_m = proper.prop_get_wavelength(wavefront)

    if condition <= 2:
        (amp, pha) = polab( polfile, lambda_m, pupil_diam_pix, condition )
    elif condition == 5:
        (amp_m45_x, pha_m45_x) = polab( polfile, lambda_m, pupil_diam_pix, -1 )
        (amp_p45_x, pha_p45_x) = polab( polfile, lambda_m, pupil_diam_pix, +1 )
        amp = (amp_m45_x + amp_p45_x) / 2
        pha = (pha_m45_x + pha_p45_x) / 2
    elif condition == 6:
        (amp_m45_y, pha_m45_y) = polab( polfile, lambda_m, pupil_diam_pix, -2 )
        (amp_p45_y, pha_p45_y) = polab( polfile, lambda_m, pupil_diam_pix, +2 )
        amp = (amp_m45_y + amp_p45_y) / 2
        pha = (pha_m45_y + pha_p45_y) / 2
    elif condition == 10:
        (amp_m45_x, pha_m45_x) = polab( polfile, lambda_m, pupil_diam_pix, -1 )
        (amp_p45_x, pha_p45_x) = polab( polfile, lambda_m, pupil_diam_pix, +1 )
        (amp_m45_y, pha_m45_y) = polab( polfile, lambda_m, pupil_diam_pix, -2 )
        (amp_p45_y, pha_p45_y) = polab( polfile, lambda_m, pupil_diam_pix, +2 )
        amp = (amp_m45_x + amp_p45_x + amp_m45_y + amp_p45_y) / 4
        pha = (pha_m45_x + pha_p45_x + pha_m45_y + pha_p45_y) / 4
    else:
        raise Exception( 'POLMAP: unmatched condition' )

    proper.prop_multiply( wavefront, trim(amp,n) ) 
    proper.prop_add_phase( wavefront, trim(MUF*pha,n) )

    amp = 0
    phase = 0
    amp_p45x = 0
    amp_m45x = 0
    amp_p45y = 0
    amp_m45y = 0
    pha_p45x = 0
    pha_m45x = 0
    pha_p45y = 0
    pha_m45y = 0

    return 
Example #9
0
def wavefront_abberations(wfo, conf,atm_screen, TILT):

    diam = conf['DIAM']
    gridsize = conf['GRIDSIZE']
    pixelsize = conf['PIXEL_SCALE'] 
    wavelength = conf['WAVELENGTH']
    lamda = proper.prop_get_wavelength(wfo)
    Debug = conf['DEBUG']
    Debug_print = conf['DEBUG_PRINT'] 

    Island_Piston = np.array(conf['ISLAND_PISTON'])
#    atm_screen = fits.getdata(input_dir + '/' + atm_screen)
    beam_ratio = pixelsize*4.85e-9/(wavelength/diam)
    npupil = np.ceil(gridsize*beam_ratio) # compute the pupil size --> has to be ODD (proper puts the center in the up right pixel next to the grid center)

    if npupil % 2 == 0:
        npupil = npupil + 1

    if (isinstance(atm_screen, (list, tuple, np.ndarray)) == True) and (atm_screen.ndim >= 2): # when the atmosphere is present
        atmosphere(wfo, npupil, atm_screen, Debug_print, Debug)
    
    if (all(v == 0 for v in Island_Piston) == False): # when the piston is present
        island_effect_piston(wfo, npupil, Island_Piston, Debug_print, Debug)

    if conf['STATIC_NCPA'] == True:
        filename = conf['IMG_LM_SCAO']
        phase_screen = fits.getdata(conf['INPUT_DIR'] + filename)
        phase_screen = np.nan_to_num(phase_screen)
        phase_screen *= 10**-9          # scale the wavelenth to nm
        static_ncpa(wfo, npupil, phase_screen)
    
    if (TILT.any != 0.): # when tip/tilt
        if (Debug_print==True):
            print("TILT: ", TILT)
            print("lamda: ", lamda)
        tiptilt = (np.multiply(TILT, lamda))/4 # translate the tip/tilt from lambda/D into RMS phase errors
        proper.prop_zernikes(wfo, [2,3], tiptilt) # 2-->xtilt, 3-->ytilt
    
    return wfo
Example #10
0
def telescope(
    wavelength,
    gridsize,
    PASSVALUE={
        'prefix': 'prova',
        'path': os.path.abspath(os.path.join(__file__, os.pardir)),
        'charge': 0,
        'CAL': 0,
        'diam': 37.,
        'spiders_width': 0.60,
        'spiders_angle': [0., 60., 120.],
        'beam_ratio': 0.25,
        'f_lens': 658.6,
        'npupil': 243,
        'r_obstr': 0.3,
        'pupil_file': 0,
        'phase_apodizer_file': 0,
        'amplitude_apodizer_file': 0,
        'TILT': [0., 0.],
        'LS': False,
        'RAVC': False,
        'LS_phase_apodizer_file': 0,
        'LS_amplitude_apodizer_file': 0,
        'LS_parameters': [0.0, 0.0, 0.0],
        'atm_screen': 0,
        'missing_segments_number': 0,
        'apodizer_misalignment': [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
        'LS_misalignment': [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
        'Island_Piston': [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
        'NCPA': 0,
        'Debug_print': False,
        'Debug': False
    }):

    ## call all the vues passed via passvalue
    prefix = PASSVALUE['prefix']
    path = PASSVALUE['path']
    charge = PASSVALUE['charge']
    CAL = PASSVALUE['CAL']
    diam = PASSVALUE['diam']
    spiders_width = PASSVALUE['spiders_width']
    spiders_angle = PASSVALUE['spiders_angle']
    beam_ratio = PASSVALUE['beam_ratio']
    f_lens = PASSVALUE['f_lens']
    npupil = PASSVALUE['npupil']
    r_obstr = PASSVALUE['r_obstr']
    pupil_file = PASSVALUE['pupil_file']
    phase_apodizer_file = PASSVALUE['phase_apodizer_file']
    amplitude_apodizer_file = PASSVALUE['amplitude_apodizer_file']
    TILT = PASSVALUE['TILT']
    LS = PASSVALUE['LS']
    RAVC = PASSVALUE['RAVC']
    LS_phase_apodizer_file = PASSVALUE['LS_phase_apodizer_file']
    LS_amplitude_apodizer_file = PASSVALUE['LS_amplitude_apodizer_file']
    LS_parameters = PASSVALUE['LS_parameters']
    atm_screen = PASSVALUE['atm_screen']
    missing_segments_number = PASSVALUE['missing_segments_number']
    apodizer_misalignment = PASSVALUE['apodizer_misalignment']
    LS_misalignment = PASSVALUE['LS_misalignment']
    Island_Piston = PASSVALUE['Island_Piston']
    NCPA = PASSVALUE['NCPA']
    Debug_print = PASSVALUE['Debug_print']
    Debug = PASSVALUE['Debug']

    TILT = np.array(TILT)
    apodizer_misalignment = np.array(apodizer_misalignment)
    LS_misalignment = np.array(LS_misalignment)
    Island_Piston = np.array(Island_Piston)

    ## call the size of the grid
    n = int(gridsize)

    wfo = proper.prop_begin(diam, wavelength, gridsize,
                            beam_ratio)  # define the simualtion pupil
    lamda = proper.prop_get_wavelength(
        wfo)  #save the wavelength value [m] into lamda

    if (Debug_print == True):
        print("lambda: ", lamda)

    pupil(wfo, CAL, npupil, diam, r_obstr, spiders_width, spiders_angle,
          pupil_file, missing_segments_number, Debug, Debug_print)

    if (Debug == True):
        fits.writeto(
            path + prefix + '_pupil_pre_define.fits',
            proper.prop_get_amplitude(wfo)[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)

    proper.prop_define_entrance(wfo)  #define the entrance wavefront

    #wfo.wfarr *= 1./np.amax(wfo._wfarr) # max(amplitude)=1

    if (isinstance(atm_screen, (list, tuple, np.ndarray)) == True) and (
            atm_screen.ndim >= 2):  # when the atmosphere is present
        print('atmosphere')
        atmosphere(wfo, npupil, atm_screen, Debug_print, Debug)

    if (isinstance(NCPA, (list, tuple, np.ndarray))
            == True) and (NCPA.ndim >= 2):  # when the atmosphere is present
        NCPA_application(wfo, npupil, NCPA, path, Debug_print, Debug)

    if (RAVC
            == True) or (isinstance(phase_apodizer_file,
                                    (list, tuple, np.ndarray))
                         == True) or (isinstance(amplitude_apodizer_file,
                                                 (list, tuple, np.ndarray))
                                      == True):  # when tha apodizer is present
        apodization(wfo, r_obstr, npupil, RAVC, phase_apodizer_file,
                    amplitude_apodizer_file, apodizer_misalignment,
                    Debug_print, Debug)

    if (all(v == 0
            for v in Island_Piston) == False):  # when the piston is present
        island_effect_piston(wfo, npupil, Island_Piston, path, Debug_print,
                             Debug)

    if (TILT.any != 0.):  # when tip/tilt
        if (Debug_print == True):
            print("TILT: ", TILT)
            print("lamda: ", lamda)
        tiptilt = (np.multiply(
            TILT, lamda
        )) / 4  # translate the tip/tilt from lambda/D into RMS phase errors
        proper.prop_zernikes(wfo, [2, 3], tiptilt)  # 2-->xtilt, 3-->ytilt

    if (Debug == True):
        if CAL == 1:
            fits.writeto(path + prefix + '_pupil_amplitude_CAL1.fits',
                         proper.prop_get_amplitude(wfo)
                         [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)
            fits.writeto(
                path + prefix + '_pupil_phase_CAL1.fits',
                proper.prop_get_phase(wfo)[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)
        else:
            fits.writeto(
                path + prefix + '_pupil_amplitude_CAL0_RA' + str(int(RAVC)) +
                '_charge' + str(charge) + '_ATM' + str(
                    int(
                        isinstance(atm_screen, (list, tuple,
                                                np.ndarray)) == True)) +
                '.fits',
                proper.prop_get_amplitude(
                    wfo)[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)
            fits.writeto(
                path + prefix + '_pupil_phase_CAL0_RA' + str(int(RAVC)) +
                '_charge' + str(charge) + '_ATM' + str(
                    int(
                        isinstance(atm_screen, (list, tuple,
                                                np.ndarray)) == True)) +
                '.fits',
                proper.prop_get_phase(wfo)[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)

    proper.prop_propagate(wfo, f_lens, 'inizio')  # propagate wavefront

    proper.prop_lens(wfo, f_lens,
                     'focusing lens vortex')  # propagate through a lens
    proper.prop_propagate(wfo, f_lens, 'VC')  # propagate wavefront

    vortex(wfo, CAL, charge, f_lens, path, Debug_print)

    if (Debug == True):
        if CAL == 1:
            fits.writeto(path + prefix + '_afterVortex_CAL1.fits',
                         proper.prop_get_amplitude(wfo)
                         [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)
            fits.writeto(
                path + prefix + '_afterVortex_CAL1_phase.fits',
                proper.prop_get_phase(wfo)[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)
        else:
            print(
                'ATM: ',
                str(
                    int(
                        isinstance(atm_screen, (list, tuple,
                                                np.ndarray)) == True)))
            if ((((int(
                    isinstance(atm_screen, (list, tuple,
                                            np.ndarray)) == True)))) == 1):
                print('atm_screen: ', atm_screen.shape)
                print(
                    'ATM: ',
                    int(
                        isinstance(atm_screen, (list, tuple,
                                                np.ndarray)) == True))
            fits.writeto(
                path + prefix + '_afterVortex_CAL0_RA' + str(int(RAVC)) +
                '_charge' + str(charge) + '_ATM' + str(
                    int(
                        isinstance(atm_screen, (list, tuple,
                                                np.ndarray)) == True)) +
                '.fits',
                proper.prop_get_amplitude(
                    wfo)[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)
            fits.writeto(
                path + prefix + '_afterVortex_phase_CAL0_RA' + str(int(RAVC)) +
                '_charge' + str(charge) + '_ATM' + str(
                    int(
                        isinstance(atm_screen, (list, tuple,
                                                np.ndarray)) == True)) +
                '.fits',
                proper.prop_get_phase(wfo)[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)

    proper.prop_propagate(wfo, f_lens,
                          'Lyot Collimetor')  # propagate wavefront

    proper.prop_lens(wfo, f_lens,
                     'Lyot Collimetor')  # propagate wavefront through  a lens
    proper.prop_propagate(wfo, f_lens, 'Lyot Stop')  # propagate wavefront

    if (Debug == True):
        if CAL == 1:
            fits.writeto(path + prefix + '_beforeLS_CAL1.fits',
                         proper.prop_get_amplitude(wfo)
                         [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)
        else:
            fits.writeto(
                path + prefix + '_beforeLS_CAL0_charge' + str(charge) +
                '_ATM' + str(
                    int(
                        isinstance(atm_screen, (list, tuple,
                                                np.ndarray)) == True)) +
                '.fits',
                proper.prop_get_amplitude(
                    wfo)[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)

    lyotstop(wfo, 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 (Debug == True):
        if CAL == 1:
            fits.writeto(path + prefix + '_afterLS_CAL1.fits',
                         proper.prop_get_amplitude(wfo)
                         [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)
        else:
            fits.writeto(
                path + prefix + '_afterLS_CAL0_charge' + str(charge) + '_LS' +
                str(int(LS)) + '_RA' + str(int(RAVC)) + '_ATM' + str(
                    int(
                        isinstance(atm_screen, (list, tuple,
                                                np.ndarray)) == True)) +
                '.fits',
                proper.prop_get_amplitude(
                    wfo)[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)

    proper.prop_propagate(wfo, f_lens)  # propagate wavefront

    proper.prop_lens(wfo, f_lens)  # propagate wavefront through a lens
    proper.prop_propagate(wfo, f_lens)  # propagate wavefront

    (wfo, sampling) = proper.prop_end(
        wfo, NOABS=True
    )  # conclude the simulation --> noabs= the wavefront array will be complex

    return (wfo, sampling)  # return the wavefront
Example #11
0
def quick_ao(wf, nact, WFS_map):
    """
    calculate the offset map to send to the DM from the WFS map

    The main idea is to apply the DM only to the region of the wavefront that contains the beam. The phase map from
    the wfs saved the whole wavefront, so that must be cropped. During the wavefront initialization in
    wavefront.initialize_proper, the beam ratio set in sp.beam_ratio is scaled per wavelength (to achieve constant
    sampling sto create white light images), so the cropped value must also be scaled by wavelength. Note, beam ratio
    is scaled differently depending on if sp.focused_sys is True or not. See params-->sp.focused_sys and Proper
    manual pg 36 for more info.

    Then, we interpolate the cropped beam onto a grid of (n_actuators,n_actuators), such that the DM can apply a
    actuator height to each represented actuator, not a over or sub-sampled form. If the number of actuators is low
    compared to the number of samples on the beam, you should anti-alias the WFS map via a lowpass filter before
    interpolating. There is a discrepancy between the sampling of the wavefront at this location (the size you cropped)
    vs the size of the DM. proper.prop_dm handles this, so just plug in the n_actuator sized DM map with specified
    parameters, and assume that prop_dm handles the resampling correctly via the spacing or n_act_across_pupil flag.
    FYI the resampling is done via a c library you installed/compiled when installing proper.

    The WFS map is a map of real values in units of phase delay in radians. However, the AO map that gets passed to
    proper.prop_dm wants input in nm height of each actuator. Therefore, you need to convert the phase delay to
    a DM height. For the ideal AO, you would do this individually for each wavelength. However, for a 'real' AO system
    you do this for the median wavelength. You also need to account for a factor of 2, since the DM is modeled as
    a mirror so it travels the length of the phase delay twice.

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

    :param wfo: wavefront object created by optics.Wavefronts() [n_wavelengths, n_objects] of tp.gridsize x tp.gridsize
    :param WFS_map: returned from quick_wfs (as of Aug 2019, its an idealized image)
    :return: ao_map: map of DM actuator command heights in units of m
    """

    nact_across_pupil = nact - 2  # number of full DM actuators across pupil (oversizing DM extent)
    # Note: oversample by 2 actuators hardcoded here, check if this is appropriate

    ############################
    # Creating AO Surface Map
    ############################
    d_beam = 2 * proper.prop_get_beamradius(wf)  # beam diameter
    act_spacing = d_beam / nact_across_pupil  # actuator spacing [m]
    # map_spacing = proper.prop_get_sampling(wfo.wf_collection[iw,0])

    ###################################
    # Cropping the Beam from WFS map
    ###################################
    # cropping here by beam_ratio rather than d_beam is valid since the beam size was initialized
    #  using the scaled beam_ratios when the wfo was created
    # dprint(f"{WFS_map[0,0,0]}")
    ao_map = WFS_map[
        sp.grid_size // 2 -
        np.int_(wf.beam_ratio * sp.grid_size // 2):sp.grid_size // 2 +
        np.int_(wf.beam_ratio * sp.grid_size // 2) + 1, sp.grid_size // 2 -
        np.int_(wf.beam_ratio * sp.grid_size // 2):sp.grid_size // 2 +
        np.int_(wf.beam_ratio * sp.grid_size // 2) + 1]

    ########################################################
    # Interpolating the WFS map onto the actuator spacing
    # (tp.nact,tp.nact)
    ########################################################
    # Lowpass Filter- prevents aliasing; uses Gaussian filter
    nyquist_dm = tp.ao_act / 2 * act_spacing  # [m]
    sigma = [nyquist_dm / 2.355,
             nyquist_dm / 2.355]  # assume we want sigma to be twice the HWHM
    ao_map = ndimage.gaussian_filter(ao_map, sigma=sigma, mode='nearest')

    f = interpolate.interp2d(range(ao_map.shape[0]),
                             range(ao_map.shape[0]),
                             ao_map,
                             kind='cubic')
    ao_map = f(np.linspace(0, ao_map.shape[0], nact),
               np.linspace(0, ao_map.shape[0], nact))
    # dm_map = proper.prop_magnify(dm_map, map_spacing / act_spacing, nact)

    ################################################
    # Converting phase delay to DM actuator height
    ################################################
    # Apply the inverse of the WFS image to the DM, so use -dm_map (dm_map is in phase units, divide by k=2pi/lambda)
    surf_height = proper.prop_get_wavelength(wf) / (4 * np.pi)  # [m/rad]
    ao_map = -ao_map * surf_height  # Converts DM map to units of [m] of actuator heights

    return ao_map
Example #12
0
    def occulter(self, wf):

        n = int(proper.prop_get_gridsize(wf))
        ofst = 0  # no offset
        ramp_sign = 1  # sign of charge is positive
        ramp_oversamp = 11.  # vortex is oversampled for a better discretization

        # f_lens = tp.f_lens #conf['F_LENS']
        # diam = tp.diam#conf['DIAM']
        charge = 2  #conf['CHARGE']
        pixelsize = 5  #conf['PIXEL_SCALE']
        Debug_print = False  #conf['DEBUG_PRINT']

        coron_temp = os.path.join(iop.testdir, 'coron_maps/')
        if not os.path.exists(coron_temp):
            os.mkdir(coron_temp)

        if charge != 0:
            wavelength = proper.prop_get_wavelength(wf)
            gridsize = proper.prop_get_gridsize(wf)
            beam_ratio = pixelsize * 4.85e-9 / (wavelength / tp.entrance_d)
            # dprint((wavelength,gridsize,beam_ratio))
            calib = str(charge) + str('_') + str(int(
                beam_ratio * 100)) + str('_') + str(gridsize)
            my_file = str(coron_temp + 'zz_perf_' + calib + '_r.fits')

            if (os.path.isfile(my_file) == True):
                if (Debug_print == True):
                    print("Charge ", charge)
                vvc = self.readfield(
                    coron_temp,
                    'zz_vvc_' + calib)  # read the theoretical vortex field
                vvc = proper.prop_shift_center(vvc)
                scale_psf = wf._wfarr[0, 0]
                psf_num = self.readfield(coron_temp, 'zz_psf_' +
                                         calib)  # read the pre-vortex field
                psf0 = psf_num[0, 0]
                psf_num = psf_num / psf0 * scale_psf
                perf_num = self.readfield(
                    coron_temp,
                    'zz_perf_' + calib)  # read the perfect-result vortex field
                perf_num = perf_num / psf0 * scale_psf
                wf._wfarr = (
                    wf._wfarr - psf_num
                ) * vvc + perf_num  # the wavefront takes into account the real pupil with the perfect-result vortex field

            else:  # CAL==1: # create the vortex for a perfectly circular pupil
                if (Debug_print == True):
                    dprint(f"Vortex Charge= {charge}")

                f_lens = 200.0 * tp.entrance_d
                wf1 = proper.prop_begin(tp.entrance_d, wavelength, gridsize,
                                        beam_ratio)
                proper.prop_circular_aperture(wf1, tp.entrance_d / 2)
                proper.prop_define_entrance(wf1)
                proper.prop_propagate(wf1, f_lens,
                                      'inizio')  # propagate wavefront
                proper.prop_lens(
                    wf1, f_lens,
                    'focusing lens vortex')  # propagate through a lens
                proper.prop_propagate(wf1, f_lens, 'VC')  # propagate wavefront

                self.writefield(coron_temp, 'zz_psf_' + calib,
                                wf1.wfarr)  # write the pre-vortex field
                nramp = int(n * ramp_oversamp)  # oversamp
                # create the vortex by creating a matrix (theta) representing the ramp (created by atan 2 gradually varying matrix, x and y)
                y1 = np.ones((nramp, ), dtype=np.int)
                y2 = np.arange(0, nramp,
                               1.) - (nramp / 2) - int(ramp_oversamp) / 2
                y = np.outer(y2, y1)
                x = np.transpose(y)
                theta = np.arctan2(y, x)
                x = 0
                y = 0
                vvc_tmp = np.exp(1j * (ofst + ramp_sign * charge * theta))
                theta = 0
                vvc_real_resampled = cv2.resize(
                    vvc_tmp.real, (0, 0),
                    fx=1 / ramp_oversamp,
                    fy=1 / ramp_oversamp,
                    interpolation=cv2.INTER_LINEAR
                )  # scale the pupil to the pupil size of the simualtions
                vvc_imag_resampled = cv2.resize(
                    vvc_tmp.imag, (0, 0),
                    fx=1 / ramp_oversamp,
                    fy=1 / ramp_oversamp,
                    interpolation=cv2.INTER_LINEAR
                )  # scale the pupil to the pupil size of the simualtions
                vvc = np.array(vvc_real_resampled, dtype=complex)
                vvc.imag = vvc_imag_resampled
                vvcphase = np.arctan2(vvc.imag,
                                      vvc.real)  # create the vortex phase
                vvc_complex = np.array(np.zeros((n, n)), dtype=complex)
                vvc_complex.imag = vvcphase
                vvc = np.exp(vvc_complex)
                vvc_tmp = 0.
                self.writefield(coron_temp, 'zz_vvc_' + calib,
                                vvc)  # write the theoretical vortex field

                proper.prop_multiply(wf1, vvc)
                proper.prop_propagate(wf1, f_lens, 'OAP2')
                proper.prop_lens(wf1, f_lens)
                proper.prop_propagate(wf1, f_lens, 'forward to Lyot Stop')
                proper.prop_circular_obscuration(
                    wf1, 1.,
                    NORM=True)  # null the amplitude iside the Lyot Stop
                proper.prop_propagate(wf1, -f_lens)  # back-propagation
                proper.prop_lens(wf1, -f_lens)
                proper.prop_propagate(wf1, -f_lens)
                self.writefield(
                    coron_temp, 'zz_perf_' + calib,
                    wf1.wfarr)  # write the perfect-result vortex field

                vvc = self.readfield(coron_temp, 'zz_vvc_' + calib)
                vvc = proper.prop_shift_center(vvc)
                scale_psf = wf._wfarr[0, 0]
                psf_num = self.readfield(coron_temp, 'zz_psf_' +
                                         calib)  # read the pre-vortex field
                psf0 = psf_num[0, 0]
                psf_num = psf_num / psf0 * scale_psf
                perf_num = self.readfield(
                    coron_temp,
                    'zz_perf_' + calib)  # read the perfect-result vortex field
                perf_num = perf_num / psf0 * scale_psf
                wf._wfarr = (
                    wf._wfarr - psf_num
                ) * vvc + perf_num  # the wavefront takes into account the real pupil with the perfect-result vortex field

        return wf
Example #13
0
def vortex(wfo, charge, f_lens, diam, pixelsize, Debug_print=False):

    n = int(proper.prop_get_gridsize(wfo))
    ofst = 0  # no offset
    ramp_sign = 1  #sign of charge is positive
    ramp_oversamp = 11.  # vortex is oversampled for a better discretization

    if charge != 0:
        wavelength = proper.prop_get_wavelength(wfo)
        gridsize = proper.prop_get_gridsize(wfo)
        beam_ratio = pixelsize * 4.85e-9 / (wavelength / diam)
        calib = str(charge) + str('_') + str(int(
            beam_ratio * 100)) + str('_') + str(gridsize)
        my_file = str(tmp_dir + 'zz_perf_' + calib + '_r.fits')

        proper.prop_propagate(wfo, f_lens, 'inizio')  # propagate wavefront
        proper.prop_lens(wfo, f_lens,
                         'focusing lens vortex')  # propagate through a lens
        proper.prop_propagate(wfo, f_lens, 'VC')  # propagate wavefront

        if (os.path.isfile(my_file) == True):
            if (Debug_print == True):
                print("Charge ", charge)
            vvc = readfield(tmp_dir, 'zz_vvc_' +
                            calib)  # read the theoretical vortex field
            vvc = proper.prop_shift_center(vvc)
            scale_psf = wfo._wfarr[0, 0]
            psf_num = readfield(tmp_dir,
                                'zz_psf_' + calib)  # read the pre-vortex field
            psf0 = psf_num[0, 0]
            psf_num = psf_num / psf0 * scale_psf
            perf_num = readfield(tmp_dir, 'zz_perf_' +
                                 calib)  # read the perfect-result vortex field
            perf_num = perf_num / psf0 * scale_psf
            wfo._wfarr = (
                wfo._wfarr - psf_num
            ) * vvc + perf_num  # the wavefront takes into account the real pupil with the perfect-result vortex field

        else:  # CAL==1: # create the vortex for a perfectly circular pupil
            if (Debug_print == True):
                print("Charge ", charge)

            wfo1 = proper.prop_begin(diam, wavelength, gridsize, beam_ratio)
            proper.prop_circular_aperture(wfo1, diam / 2)
            proper.prop_define_entrance(wfo1)
            proper.prop_propagate(wfo1, f_lens,
                                  'inizio')  # propagate wavefront
            proper.prop_lens(
                wfo1, f_lens,
                'focusing lens vortex')  # propagate through a lens
            proper.prop_propagate(wfo1, f_lens, 'VC')  # propagate wavefront

            writefield(tmp_dir, 'zz_psf_' + calib,
                       wfo1.wfarr)  # write the pre-vortex field
            nramp = int(n * ramp_oversamp)  #oversamp
            # create the vortex by creating a matrix (theta) representing the ramp (created by atan 2 gradually varying matrix, x and y)
            y1 = np.ones((nramp, ), dtype=np.int)
            y2 = np.arange(0, nramp, 1.) - (nramp / 2) - int(ramp_oversamp) / 2
            y = np.outer(y2, y1)
            x = np.transpose(y)
            theta = np.arctan2(y, x)
            x = 0
            y = 0
            vvc_tmp = np.exp(1j * (ofst + ramp_sign * charge * theta))
            theta = 0
            vvc_real_resampled = cv2.resize(
                vvc_tmp.real, (0, 0),
                fx=1 / ramp_oversamp,
                fy=1 / ramp_oversamp,
                interpolation=cv2.INTER_LINEAR
            )  # scale the pupil to the pupil size of the simualtions
            vvc_imag_resampled = cv2.resize(
                vvc_tmp.imag, (0, 0),
                fx=1 / ramp_oversamp,
                fy=1 / ramp_oversamp,
                interpolation=cv2.INTER_LINEAR
            )  # scale the pupil to the pupil size of the simualtions
            vvc = np.array(vvc_real_resampled, dtype=complex)
            vvc.imag = vvc_imag_resampled
            vvcphase = np.arctan2(vvc.imag,
                                  vvc.real)  # create the vortex phase
            vvc_complex = np.array(np.zeros((n, n)), dtype=complex)
            vvc_complex.imag = vvcphase
            vvc = np.exp(vvc_complex)
            vvc_tmp = 0.
            writefield(tmp_dir, 'zz_vvc_' + calib,
                       vvc)  # write the theoretical vortex field

            proper.prop_multiply(wfo1, vvc)
            proper.prop_propagate(wfo1, f_lens, 'OAP2')
            proper.prop_lens(wfo1, f_lens)
            proper.prop_propagate(wfo1, f_lens, 'forward to Lyot Stop')
            proper.prop_circular_obscuration(
                wfo1, 1., NORM=True)  # null the amplitude iside the Lyot Stop
            proper.prop_propagate(wfo1, -f_lens)  # back-propagation
            proper.prop_lens(wfo1, -f_lens)
            proper.prop_propagate(wfo1, -f_lens)
            writefield(tmp_dir, 'zz_perf_' + calib,
                       wfo1.wfarr)  # write the perfect-result vortex field

            vvc = readfield(tmp_dir, 'zz_vvc_' + calib)
            vvc = proper.prop_shift_center(vvc)
            scale_psf = wfo._wfarr[0, 0]
            psf_num = readfield(tmp_dir,
                                'zz_psf_' + calib)  # read the pre-vortex field
            psf0 = psf_num[0, 0]
            psf_num = psf_num / psf0 * scale_psf
            perf_num = readfield(tmp_dir, 'zz_perf_' +
                                 calib)  # read the perfect-result vortex field
            perf_num = perf_num / psf0 * scale_psf
            wfo._wfarr = (
                wfo._wfarr - psf_num
            ) * vvc + perf_num  # the wavefront takes into account the real pupil with the perfect-result vortex field

        proper.prop_propagate(wfo, f_lens, "propagate to pupil reimaging lens")
        proper.prop_lens(wfo, f_lens, "apply pupil reimaging lens")
        proper.prop_propagate(wfo, f_lens, "lyot stop")

    return wfo
Example #14
0
def adaptive_optics(wfo, iwf, iw, f_lens, beam_ratio, iter):
    # print 'Including Adaptive Optics'
    # PSF = proper.prop_shift_center(np.abs(wfo.wfarr)**2)

    # quicklook_im(obj_map, logAmp=False)

    # code to distort measured phase map goes here....
    # print 'add code to distort phase measurment'
    nact = tp.ao_act  #49                       # number of DM actuators along one axis
    nact_across_pupil = nact - 2  #/1.075#nact #47          # number of DM actuators across pupil
    dm_xc = (nact / 2) - 0.5  #-1#0.5#- 0.5
    dm_yc = (nact / 2) - 0.5  #-1#0.5#- 0.5
    d_beam = 2 * proper.prop_get_beamradius(wfo)  # beam diameter
    # dprint((d_beam, d_beam/nact_across_pupil))
    act_spacing = d_beam / (nact_across_pupil)  # actuator spacing
    map_spacing = proper.prop_get_sampling(wfo)  # map sampling

    # have passed through focus, so pupil has rotated 180 deg;
    # need to rotate error map (also need to shift due to the way
    # the rotate() function operates to recenter map)
    # obj_map = np.roll(np.roll(np.rot90(obj_map, 2), 1, 0), 1, 1)
    # obj_map = np.roll(obj_map, 1, -1)
    # quicklook_im(obj_map[45:83,45:83], logAmp=False, show=False)
    # plt.figure()
    # plt.plot(range(44, 84), obj_map[64, 44:84])

    # print map_spacing
    # interpolate map to match number of DM actuators
    # print map_spacing/act_spacing

    # print 'Interpolation boundary uncertainty is likely because of beam ratio causing a non-integer'
    # print '128*0.3 ~ 38 so thats what is being used for now. Needs some T.L.C.'

    # true_width = tp.grid_size*beam_ratio
    # width = int(np.ceil(true_width))
    # # width = int(np.ceil(tp.grid_size*beam_ratio))
    # if width%2 != 0:
    #     width += 1
    # exten = width/true_width
    # print exten
    # mid = int(tp.grid_size/2.)
    # lower = int(mid-width/2.)
    # upper = int(mid+width/2.)
    # print width, mid, lower, upper
    # #
    # # f= interpolate.interp2d(range(width+1), range(width+1), obj_map[lower:upper, lower:upper])
    # # dm_map = f(np.linspace(0,width+1,nact),np.linspace(0,width+1,nact))
    #
    # import skimage.transform
    # dm_map = skimage.transform.resize(obj_map[lower:upper, lower:upper], (nact,nact))
    # print map_spacing, act_spacing, map_spacing/act_spacing

    try:
        with open(iop.CPA_meas, 'rb') as handle:
            CPA_maps, iters = pickle.load(handle)
    except EOFError:
        print 'CPA file not ready?'
        import time
        time.sleep(10)
        with open(iop.CPA_meas, 'rb') as handle:
            CPA_maps, iters = pickle.load(handle)

    # loop_frames(CPA_maps, logAmp=False)
    if iwf[:9] == 'companion':
        CPA_map = CPA_maps[1, iw]
    else:
        CPA_map = CPA_maps[0, iw]

    # loop_frames(CPA_maps, logAmp=False)

    # quicklook_im(CPA_map, logAmp=False)

    # dprint((map_spacing, act_spacing, map_spacing/act_spacing))
    # dm_map = proper.prop_magnify(CPA_map, map_spacing/act_spacing, nact)

    dm_map = CPA_map[tp.grid_size / 2 -
                     (beam_ratio * tp.grid_size / 2):tp.grid_size / 2 +
                     (beam_ratio * tp.grid_size / 2) + 1, tp.grid_size / 2 -
                     (beam_ratio * tp.grid_size / 2):tp.grid_size / 2 +
                     (beam_ratio * tp.grid_size / 2) + 1]
    f = interpolate.interp2d(range(dm_map.shape[0]), range(dm_map.shape[0]),
                             dm_map)
    dm_map = f(np.linspace(0, dm_map.shape[0], nact),
               np.linspace(0, dm_map.shape[0], nact))
    # quicklook_im(dm_map, logAmp=False, show=True)
    dm_map = -dm_map * proper.prop_get_wavelength(wfo) / (4 * np.pi
                                                          )  #<--- here
    # dm_map = -dm_map * proper.prop_get_wavelength(wfo) / (2 * np.pi)
    # dm_map = np.zeros((65,65))
    # quicklook_im(dm_map, logAmp=False, show=True, colormap='jet')
    # if tp.piston_error:
    #     mean_dm_map = np.mean(np.abs(dm_map))
    #     var = mean_dm_map/200.#40.
    #     print var
    #     # var = 0.001#1e-11
    #     if var != 0.0:
    #         dm_map = dm_map + np.random.normal(0, var, (dm_map.shape[0], dm_map.shape[1]))
    # quicklook_im(dm_map, logAmp=False, show=True, colormap='jet')
    # plt.figure()
    # quicklook_wf(wfo)
    # plt.plot(np.linspace(44, 84, nact),dm_map[16])
    # plt.figure()
    # quicklook_im( obj_map[lower:upper, lower:upper], logAmp=False, show=True)
    # act_spacing /= 0.625
    # print act_spacing, proper.prop_get_beamradius(wfo)
    # Need to put on opposite pattern; convert wavefront error to surface height
    # plt.plot(range(44,84), proper.prop_get_phase(wfo)[64, 44:84])
    # proper.prop_add_phase(wfo, waffle)

    # quicklook_im(dm_map)
    if tp.active_null:
        with open(iop.NCPA_meas, 'rb') as handle:
            _, null_map, _ = pickle.load(handle)
        # dprint('null_map')
        # quicklook_im(null_map, logAmp=False)
        # dm_NCPA = -proper.prop_magnify(NCPA_map, map_spacing / act_spacing, nact)
        dm_NCPA = null_map * proper.prop_get_wavelength(wfo) / (4 * np.pi)

        # quicklook_im(dm_map, logAmp=False)
        dm_map += dm_NCPA
        # quicklook_im(dm_map, logAmp=False, show=True, colormap ='jet')
        # dm_map /= 2

    # if tp.speckle_kill:
    #     with open(iop.NCPA_meas, 'rb') as handle:
    #         Imaps, NCPA_map,_ = pickle.load(handle)
    # quicklook_im(NCPA_map, logAmp=False)
    # loop_frames(Imaps+1e-9, logAmp=True)
    # with open(iop.NCPA_meas, 'rb') as handle:
    #     _, NCPA_map,_ = pickle.load(handle)
    # quicklook_im(NCPA_map, logAmp=False)
    #
    # dm_NCPA = -proper.prop_magnify(NCPA_map, map_spacing / act_spacing, nact)
    # dm_NCPA = dm_NCPA*proper.prop_get_wavelength(wfo)/(4*np.pi)
    #
    # # quicklook_im(dm_map, logAmp=False)
    # dm_map = dm_NCPA

    if tp.active_modulate and iter >= 8:
        # import dm_functions as DM
        # # speck.generate_flatmap(phase)
        # s_amp = DM.amplitudemodel(0.05, 30, c=1.6)
        # tp.null_ao_act = tp.ao_act
        # xloc, yloc = 4, 0
        # # rotate_angle = iter%30 * 360/30
        # # rotate_angle = np.pi * rotate_angle / 180.
        # # rot_matrix = [[np.cos(rotate_angle), -np.sin(rotate_angle)], [np.sin(rotate_angle), np.cos(rotate_angle)]]
        # # xloc, yloc = np.matmul(rot_matrix, [xloc, yloc])
        #
        # phase = iter % 10 * 2 * np.pi / 10.
        # s_amp = iter % 5 * s_amp/ 5.
        # print xloc, yloc, phase
        # waffle = DM.make_speckle_kxy(xloc, yloc, s_amp, phase) / 1e6
        # waffle += DM.make_speckle_kxy(yloc, xloc, s_amp, -phase) / 1e6
        # waffle += DM.make_speckle_kxy(0.71 * xloc, 0.71 * xloc, s_amp, -phase) / 1e6
        # waffle += DM.make_speckle_kxy(0.71 * xloc, -0.71 * xloc, s_amp, -phase) / 1e6
        # waffle /= 4
        # # quicklook_im(waffle, logAmp=False)
        # # print dm_map.shape
        # # print waffle.shape
        #
        # dmap =proper.prop_dm(wfo, waffle, dm_xc, dm_yc, N_ACT_ACROSS_PUPIL=nact, FIT = True)
        # dm_map = -dm_map * proper.prop_get_wavelength(wfo) / (4 * np.pi * 5) * (iter % 10 - 5)
        print 1 / 5. * (iter % 10 - 5)
        dm_map = dm_map / 5. * (iter % 10 - 5)
        # dmap = proper.prop_dm(wfo, pattern, dm_xc, dm_yc,
        #                       N_ACT_ACROSS_PUPIL=nact, FIT=True)
    # quicklook_wf(wfo)

    # quicklook_wf(wfo)
    # dmap =proper.prop_dm(wfo, dm_map, dm_xc, dm_yc, N_ACT_ACROSS_PUPIL=nact, FIT = True) #<-- here

    dmap = proper.prop_dm(wfo, dm_map, dm_xc, dm_yc, act_spacing,
                          FIT=True)  #<-- here

    # quicklook_im(dmap, logAmp=False, show=True)
    # quicklook_im(CPA_map*proper.prop_get_wavelength(wfo)/(4*np.pi), logAmp=False)
    # quicklook_im(CPA_map*proper.prop_get_wavelength(wfo)/(4*np.pi) + dmap, logAmp=False, show=True)

    # # # There's a boundary effect that needs to be mitigated
    # phase_map = proper.prop_get_phase(wfo)
    # artefacts = np.abs(phase_map) > 1
    # # print np.shape(artefacts), np.shape(phase_map)
    # # quicklook_im(phase_map, logAmp=False)
    #
    # width = round(tp.grid_size*beam_ratio)
    # mid = int(tp.grid_size/2.)
    # lower = int(mid-width/2.)
    # upper = int(mid+width/2.)
    # mask = np.zeros((tp.grid_size, tp.grid_size))
    # mask[upper,:] = 1
    # mask[:, upper] = 1
    # mask[lower,:] = 1
    # mask[:,lower] = 1
    # mask = mask*artefacts
    #
    # # print width, upper
    #
    # # wfo.wfarr[upper] = phase_map[tp.grid_size/2,tp.grid_size/2]
    # # quicklook_im( phase_map*mask, logAmp=False)
    #
    # proper.prop_add_phase(wfo,-phase_map*mask*proper.prop_get_wavelength(wfo)/(2*np.pi))
    # quicklook_IQ(wfo)

    # I = np.real(wfo.wfarr)
    # Q = np.imag(wfo.wfarr)
    # I = proper.prop_shift_center(I)
    # Q = proper.prop_shift_center(Q)
    # Q[89] = 0
    # Q[:,89] = 0
    # # Q[39] = 0
    # # Q[:,39] = 0
    # I = proper.prop_shift_center(I)
    # Q = proper.prop_shift_center(Q)
    # wfo.wfarr = I+1j*Q
    # quicklook_wf(wfo)

    # quicklook_IQ(wfo)
    # print phase_map[artefacts]
    # plt.imshow(phase_map)
    # # plt.figure()
    # # plt.imshow(dmap)
    # #
    # plt.show()
    # #
    # proper.prop_propagate(wfo, f_lens, "coronagraph lens")
    # quicklook_wf(wfo)
    return
Example #15
0
def coronagraph(wfo, f_lens, occulter_type, occult_loc, diam):
    # proper.prop_lens(wfo, f_lens, "coronagraph imaging lens")
    # proper.prop_propagate(wfo, f_lens, "occulter")
    # quicklook_wf(wfo)
    # occulter sizes are specified here in units of lambda/diameter;
    # convert lambda/diam to radians then to meters

    lamda = proper.prop_get_wavelength(wfo)
    # print lamda
    occrad = 3  # occulter radius in lam/D
    occrad_rad = occrad * lamda / diam  # occulter radius in radians
    dx_m = proper.prop_get_sampling(wfo)
    dx_rad = proper.prop_get_sampling_radians(wfo)
    occrad_m = occrad_rad * dx_m / dx_rad  # occulter radius in meters
    # print occrad_m, occulter_type
    # print 'line 22.', occulter_type
    #plt.figure(figsize=(12,8))
    # quicklook_wf(wfo)
    if occulter_type == "Gaussian":
        r = proper.prop_radius(wfo)
        h = np.sqrt(-0.5 * occrad_m**2 / np.log(1 - np.sqrt(0.5)))  #*0.8
        gauss_spot = 1 - np.exp(-0.5 * (r / h)**2)
        # print occult_loc
        # gauss_spot = np.roll(gauss_spot,occult_loc,(0,1))
        gauss_spot = shift(gauss_spot, shift=occult_loc, mode='wrap')
        proper.prop_multiply(wfo, gauss_spot)
        # quicklook_wf(wfo)
        #plt.suptitle("Gaussian spot", fontsize = 18)
    elif occulter_type == "Solid":
        proper.prop_circular_obscuration(wfo, occrad_m * 4. / 3)
        #plt.suptitle("Solid spot", fontsize = 18)
        # quicklook_wf(wfo)
    elif occulter_type == "8th_Order":
        proper.prop_8th_order_mask(wfo, occrad * 3. / 4., CIRCULAR=True)
        # quicklook_wf(wfo)
    elif occulter_type == 'Vortex':
        # print('lol')
        # apodization(wfo, True)
        vortex(wfo)
        # lyotstop(wfo, True)

        #plt.suptitle("8th order band limited spot", fontsize = 18)
    # quicklook_wf(wfo, logAmp=False, show=True)
    # After occulter
    # plt.subplot(1,2,1)
    # plt.imshow(np.sqrt(proper.prop_get_amplitude(wfo)), origin = "lower", cmap = plt.cm.gray)
    # plt.text(200, 10, "After Occulter", color = "w")
    # plt.show()
    # quicklook_wf(wfo)

    proper.prop_propagate(wfo, f_lens, "pupil reimaging lens")
    # quicklook_wf(wfo)
    proper.prop_lens(wfo, f_lens, "pupil reimaging lens")
    # quicklook_wf(wfo)
    proper.prop_propagate(wfo, 2 * f_lens, "lyot stop")
    # quicklook_wf(wfo)

    # from numpy.fft import fft2, ifft2
    # wfo.wfarr = fft2(wfo.wfarr) #/ np.size(wfo.wfarr)
    # quicklook_wf(wfo)

    # plt.subplot(1,2,2)
    # plt.imshow(proper.prop_get_amplitude(wfo)**0.2, origin = "lower", cmap = plt.cm.gray)
    # plt.text(200, 10, "Before Lyot Stop", color = "w")
    # plt.show()
    # quicklook_wf(wfo,logAmp=False, show=True)

    if occulter_type == "Gaussian":
        # quicklook_wf(wfo)
        proper.prop_circular_aperture(wfo, 0.75, NORM=True)
    elif occulter_type == "Solid":
        # quicklook_wf(wfo)
        proper.prop_circular_aperture(wfo, 0.84, NORM=True)
    elif occulter_type == "8th_Order":
        # quicklook_wf(wfo)
        proper.prop_circular_aperture(wfo, 0.75, NORM=True)  #0.5
    elif occulter_type == "Vortex":
        # proper.prop_circular_aperture(wfo, 0.98, NORM = True) #0.5
        lyotstop(wfo, True)
        # quicklook_wf(wfo)
    elif occulter_type == "None (Lyot Stop)":
        proper.prop_circular_aperture(wfo, 0.8, NORM=True)

    proper.prop_propagate(wfo, f_lens, "reimaging lens")
    # errs = np.sqrt(proper.prop_get_amplitude(wfo))
    # # plt.figure()
    # # plt.imshow(errs)
    # # plt.show()
    # quicklook_wf(wfo)
    proper.prop_lens(wfo, f_lens, "reimaging lens")
    # quicklook_wf(wfo)
    proper.prop_propagate(wfo, f_lens, "final focus")
    # from numpy.fft import fft2, ifft2
    # wfo.wfarr = fft2(wfo.wfarr) / np.size(wfo.wfarr)
    # quicklook_wf(wfo)
    return