Example #1
0
 def run_timestep(self, t):
     self.kwargs['iter'] = t
     return proper.prop_run(tp.prescription,
                            1,
                            sp.grid_size,
                            PASSVALUE=self.kwargs,
                            QUIET=True)
Example #2
0
def generate_images(zern, opt):
    pix_size = opt.pixel_size
    height = opt.sensor_height()
    beam_ratio = 0.5
    npix = int(height / beam_ratio /
               pix_size)  #number of pixels that the grid should span
    gridsize = 512
    setting = {
        'ZERN': zern.at_wavelength(opt.wavelength),
        'DEFOCUS': opt.defocus,
        'diam': opt.aperature,
        'focal_length': opt.focal_length,
        'beam_ratio': beam_ratio
    }

    #add the prescriptions to the path
    sys.path.append(os.path.dirname(os.path.abspath(__file__)))
    #run the optical simulation
    pre_im, sampling = proper.prop_run('prefocal_image',
                                       opt.wavelength_as_um(),
                                       gridsize,
                                       PASSVALUE=setting,
                                       QUIET=True)
    pos_im, sampling = proper.prop_run('postfocal_image',
                                       opt.wavelength_as_um(),
                                       gridsize,
                                       PASSVALUE=setting,
                                       QUIET=True)

    #invert postfocal image
    pos_im = [[
        pos_im[gridsize - y - 1][gridsize - x - 1] for x in range(gridsize)
    ] for y in range(gridsize)]

    #Discretize according to the distance of the camera
    pre_im = cv2.resize(np.array(pre_im), (npix, npix))
    pos_im = cv2.resize(np.array(pos_im), (npix, npix))

    #Correct weird offset from proper (NOTE: Work in progress, may not be accurate for defocus != 1e-3
    M = np.float32([[1, 0, -0.01513], [0, 1, -0.01513]])
    pos_im = cv2.warpAffine(pos_im, M, pos_im.shape)

    return pre_im, pos_im
Example #3
0
    def gen_timeseries(self):
        """
        Time loop wrapper for prescriptions.

        :param inqueue: time index for parallelization (used by multiprocess)
        :param out_queue: series of intensity images (spectral image cube) in the multiprocessing format

        :return: returns the observation sequence, but through the multiprocessing tools, not through more standard
          return protocols.

        :timestep_field is the complex-valued E-field in the planes specified by sp.save_list.
            has shape [timestep, planes, wavelength, objects, x, y]
        :sampling is the final sampling per wavelength in the focal plane
        """
        start = time.time()

        for it, t in enumerate(iter(self.time_idx.get, sentinel)):
            kwargs = {'iter': t, 'params': [iop, sp, ap, tp, cdip]}
            timestep_field, sampling = proper.prop_run(tp.prescription, 1, sp.grid_size, PASSVALUE=kwargs,
                                                       VERBOSE=False, TABLE=False)  # 1 is dummy wavelength

            chunk_ind = it % self.chunk_steps

            self.fields_chunk[chunk_ind] = timestep_field
            self.seen_substeps[chunk_ind] = 1

            chunk_seen = np.all(self.seen_substeps)
            final_chunk_seen = it == sp.numframes-1 and np.all(self.seen_substeps[:self.final_chunk_size])
            while (chunk_ind == self.chunk_steps-1 and not chunk_seen) or \
                  (chunk_ind == self.final_chunk_size-1 and not final_chunk_seen):
                print(f'Waiting for chunk {it//self.chunk_steps} to finish being poplulated before saving') #if sp.verbose
                time.sleep(1)

            if chunk_seen or final_chunk_seen:  # chunk completed or simulation finished
                self.out_chunk.put((self.fields_chunk, sampling))
                if sp.save_to_disk:
                    self.save(self.fields_chunk, sampling)

                if sp.debug:
                    view_spectra(np.sum(np.abs(self.fields_chunk) ** 2, axis=(0, 1))[:, 0],
                                 title='Chunk Spectral Cube')

                self.init_fields_chunk()


        now = time.time()
        elapsed = float(now - start)
        each_iter = float(elapsed) / (sp.numframes + 1)

        print('***********************************')
        print(f'{elapsed/60.:.2f} minutes elapsed, each time step took {each_iter:.2f} minutes')
Example #4
0
    def generate(self):
        self.telescope = auto_load(Telescope)

        self.cpx_sequence = np.zeros((self.sp.numframes, len(self.sp.save_list), self.ap.n_wvl_init,
                                 1 + len(self.ap.contrast), self.sp.grid_size, self.sp.grid_size), dtype=np.complex)

        for t in range(self.sp.numframes):
            kwargs = {'iter': t,
                      'params': [self.ap, self.tp, self.iop, self.sp],
                      'theta': self.cdip.theta_series[t]}
            self.cpx_sequence[t], self.sampling = proper.prop_run(self.tp.prescription,
                                                                  1, self.sp.grid_size,
                                                                  PASSVALUE=kwargs, VERBOSE=False,
                                                                  TABLE=False)  # 1 is dummy wavelength

        return self.cpx_sequence, self.sampling
Example #5
0
def form_multi_psf(prescription,
                   sources,
                   gridsize,
                   common_sampling,
                   npsf,
                   multi=True):
    source_psfs = []
    for source in sources:
        settings = source['settings']
        wavelengths = source['wavelengths']
        wl_weights = source['weights']

        if multi is True:
            (wavefronts,
             samplings) = proper.prop_run_multi(prescription,
                                                wavelengths,
                                                gridsize=gridsize,
                                                QUIET=True,
                                                PRINT_INTENSITY=False,
                                                PASSVALUE=settings)
            # prop_run_multi returns complex arrays, even when PSFs are intensity, so make real with abs
            psfs = normalise_sampling(np.abs(wavefronts), samplings,
                                      common_sampling, npsf)
        else:
            wavefronts = []
            samplings = []
            for wl in wavelengths:
                (wavefront, sampling) = proper.prop_run(prescription,
                                                        wl,
                                                        gridsize=gridsize,
                                                        QUIET=True,
                                                        PRINT_INTENSITY=False,
                                                        PASSVALUE=settings)
                wavefronts.append(wavefront)
                samplings.append(sampling)
            psfs = normalise_sampling(wavefronts, samplings, common_sampling,
                                      npsf)

        source_psfs.append(combine_psfs(psfs, wl_weights))

    psf_all = combine_psfs(np.stack(source_psfs),
                           [1. for i in range(len(source_psfs))])
    return psf_all
Example #6
0
def cdi_postprocess(fp_seq, cdi_zip, map_dir=None, plot=False, debug=False):
    """
    this is the function that accepts the timeseries of intensity images from the simulation and returns the processed
    single image. This function calculates the speckle amplitude phase, and then corrects for it to create the dark
    hole over the specified region of the image.

    :param fp_seq: focal plane sequence (temporal cube) [nx, ny, time]
    :param cdi_zip: cdi_zipdata from .pkl file from DM settings and timestream created at runtime
    :param map_dir: directory where the DM telemetry data (generated by scexaortc) is stored
    :param plot: toggle to display plots or not
    :return: nothing, lots of plots though
    """
    ##
    print(f'\nStarting CDI post-processing')
    st = time.time()

    nx = fp_seq.shape[1]  # size of MEC images
    ny = fp_seq.shape[2]
    dm_act = cdi_zip.probe.DM_cmd_cycle.shape[-1]  # number of DM actuators
    n_pairs = cdi_zip.ts.n_probes // 2  # number of deltas (probe differentials)
    n_nulls = int(cdi_zip.ts.null_time / cdi_zip.ts.phase_integration_time)
    n_cycles = cdi_zip.ts.n_cycles
    n_probes = cdi_zip.ts.n_probes

    # MEC Probe Commands (removes flat (null step) commands )
    msk = np.tile(np.append(np.repeat(True, n_probes), False), n_cycles)  # there is no beginning 'flat' command
    cmds_probe_only = cdi_zip.ts.cmd_tstamps[msk]
    cmds_nulls_only = cdi_zip.ts.cmd_tstamps[~msk]

    # # Sorting fp_seq
    if 'irreg' in datf:
        # Each 'null' step is much longer in time than the probe commands; matches the format of the probe timesteps
        # since the null was sent with a single flat command and lasts the length of a null as determined by mec_cdi.py
        reg_msk = msk
    else:
        # this assumes fp_seq was created with the null steps spaced out over time via photontable.temporal cube
        # regular bins in read_photons.py. Must reformat mask if there is one large null step, as in irreg_bins
        reg_msk = np.tile(np.append(np.repeat(True, n_probes), np.repeat(False, n_nulls)),
                          n_cycles)
        # raise ValueError(f'No longer working for regular binned data, use irreg instead')

    if len(reg_msk) > fp_seq.shape[0]:  # h5 might be cutoff mid-cycle if the dataset was long
        reg_msk = reg_msk[0:fp_seq.shape[0]]
    mec_probed = fp_seq[ reg_msk]
    mec_nulls = fp_seq[~reg_msk]
    intensity_counter(mec_probed, mec_nulls)

    # Define arrays for sorting probe vs null steps
    sim_grid = 256  # phase propagation simulation grid size nxn
    extracted = [nx,ny]
    probe_tstamps = np.zeros((len(cmds_probe_only)))
    probe_maps = np.zeros((len(cmds_probe_only), dm_act, dm_act))
    null_tstamps = np.zeros((len(cmds_nulls_only)))
    null_maps = np.zeros((len(cmds_nulls_only), dm_act, dm_act))

    ## Loading or simulating DM voltage maps
    lst = time.time()
    # # Complex Map
    # fp_mask, edges = get_fp_mask(cdi_zip)
    # cl = LineCollection(edges, colors='r')

    if map_dir:
        # Load DM Telemetry Data => dm voltage maps saved by scexaortc (referred to as map)
        # cpx_dm_sim = np.zeros((len(cmds_probe_only), nx, ny), dtype=complex)
        # cpx_null_sim = np.zeros((len(cmds_nulls_only), nx, ny), dtype=complex)
        cpx_dm = np.zeros((len(cmds_probe_only), nx, ny), dtype=complex)
        cpx_null = np.zeros((len(cmds_nulls_only), nx, ny), dtype=complex)

        # Converting .txt string to Unix to compare with MEC command timestamp
        fn = sorted(os.listdir(map_dir))
        txts = [x for x in fn if ".fits" not in x]
        tt = [x.replace('dm00disp_', '') for x in txts]  # 'dm00disp03_'
        tt = [x.replace('.txt', '') for x in tt]
        ymd = cdi_zip.ts.cmd_tstamps[0].astype('datetime64[D]')
        ymd = ymd.astype('<U18')
        tt = [(ymd + 'T' + x) for x in tt]
        tt = [datetime_to_unix(np.datetime64(x)) for x in tt]
        # #---------------------
        # Saving DM map that matches closest prior probe command
        flat = get_standard_flat(debug=False)
        # Probes
        for ix in range(len(cmds_probe_only)):  # len(cmds_probe_only)
            map_ts, dm_map, ixsync = sync_tstep(ix, cmds_probe_only, txts, tt)
            probe_tstamps[ix] = map_ts[ixsync]
            probe_maps[ix] = dm_map[ixsync, :, :]
            # cpx_dm[ix] = basic_fft(dm_map[ixsync, :, :], nx, ny)
            cpx_dm[ix], smp = proper.prop_run('scexao_model', .9, sim_grid,  # for some reason 0.9 gives 900 nm
                                             PASSVALUE={'map':probe_maps[ix]*1e-6, 'psf_size':extracted,
                                                        'verbose':debug, 'ix':ix}, QUIET=True)
        # Nulls
        for ix in range(len(cmds_nulls_only)):  # len(cmds_nulls_only)
            map_ts, dm_map, ixsync = sync_tstep(ix, cmds_nulls_only, txts, tt)
            null_tstamps[ix] = map_ts[ixsync]
            null_maps[ix] = dm_map[ixsync, :, :]-flat
            # cpx_null[ix] = basic_fft(null_maps[ix], nx, ny)
            cpx_null[ix], smp = proper.prop_run('scexao_model', .9, sim_grid,  # for some reason 0.9 gives 900 nm
                                          PASSVALUE={'map': null_maps[ix]*1e-6, 'psf_size':extracted,
                                                     'verbose':False, 'ix':ix}, QUIET=True)
        # # Rescaling to match MEC focal plane dimensions
        # for ix in range(cpx_dm_sim.shape[0]):
        #     cpx_dm[ix]   = resample_cpx(cpx_dm_sim[ix],   nx, ny)
        # for ix in range(cpx_null_sim.shape[0]):
        #     cpx_null[ix] = resample_cpx(cpx_null_sim[ix], nx, ny)

        elt = time.time()
        print(
            f'Phase propagation finished in {elt - lst:.1f} sec == {(elt - lst) / 60:.2f} min')

    else:
        # Just use the DM probe pattern as the voltage map
        cpx_all_sim = np.zeros((len(cdi_zip.probe.DM_cmd_cycle), extracted[0], extracted[1]), dtype=complex)
        cpx_all_1 = np.zeros((n_pairs*2+n_nulls, nx, ny), dtype=complex)
        cpx_all = np.zeros((len(reg_msk), nx, ny), dtype=complex)

        # flat = get_standard_flat(debug=False)  # standard flat  900e-9/1e6 *
        flat = np.zeros((50,50),dtype=float)  # empty
        # cos function
        # dmx, dmy = np.meshgrid(
        #     np.linspace(-0.5, 0.5, 50),
        #     np.linspace(-0.5, 0.5, 50))
        #
        # xm = dmx * 12 * 2.0 * np.pi
        # ym = dmy * 2.0 * np.pi
        # flat = 1e-8*np.sin(xm)
        # # # Test Probe
        # x = np.linspace(-1/2 - 5/50, 1/2 - 5/50, 50, dtype=np.float32)
        # y = np.linspace(-1/2 - 5/50, 1/2 - 5/50, 50, dtype=np.float32)
        # X,Y = np.meshgrid(x,y)
        # flat =  np.sinc(10 * X) * np.sinc(5 * Y) * np.cos(2 * np.pi * 10 * Y + np.pi/4)

        # complex of all maps from the probe pattern
        # last probe in the command cycle is the null
        for ix in range(len(cdi_zip.probe.DM_cmd_cycle)):
            map = 1e-6 * (flat + cdi_zip.probe.DM_cmd_cycle[ix])   #TODO replace flat + cmd
            # cpx_all_sim[ix] = basic_fft(map, 128, 128)
            cpx_all_sim[ix], smp = proper.prop_run('scexao_model', .9, sim_grid,
                                              PASSVALUE={'map': map, 'psf_size':extracted,
                                                         'verbose': debug, 'ix':ix}, QUIET=True)

        # Copying FP Null image for n_nulls steps
        ix=0
        while ix < n_nulls-1:
            cpx_all_sim = np.concatenate((cpx_all_sim, np.array([cpx_all_sim[-1,:,:]])),axis=0)
            ix+=1

        # repeat cycle of n_probes+n_nulls for n_cycles
        # for ix in range(len(cpx_all_sim)):
        #     cpx_all_1[ix] = resample_cpx(cpx_all_sim[ix], nx, ny)
        # cycle through the probe cycle for length of observation
        cpx_all = np.tile(cpx_all_sim, (cdi_zip.ts.n_cycles, 1, 1))

        # Probes
        cpx_dm = cpx_all[reg_msk]
        probe_maps = (cdi_zip.probe.DM_cmd_cycle[0:cdi_zip.ts.n_probes] + flat)
        probe_tstamps = cdi_zip.ts.cmd_tstamps[msk].astype('float')/1e9
        # Nulls
        cpx_null = cpx_all[~reg_msk]
        null_maps = np.tile(cdi_zip.probe.DM_cmd_cycle[-1] + flat, (cdi_zip.ts.n_cycles, 1, 1))
        null_tstamps = cdi_zip.ts.cmd_tstamps[~msk].astype('float')/1e9

        elt = time.time()
        print(
            f'\nPhase propagation finished in {elt - lst:.1f} sec == {(elt - lst) / 60:.2f} min\n')

    if debug:
        # Plot DM Map Probe Sequence
        fig, subplot = plt.subplots(2, cdi_zip.ts.n_probes//2, figsize=(14, 8))
        fig.suptitle(f'DM Telemetry Data, Probe Commands: '
                     f'target = {target_name}\n'
                     f' N probes={cdi_zip.ts.n_probes}, '
                     f'N null steps={int(cdi_zip.ts.null_time / cdi_zip.ts.phase_integration_time)}, '
                     f'integration time={cdi_zip.ts.phase_integration_time} sec', fontweight='bold', fontsize=14)

        for ax, ix in zip(subplot.flatten(), range(len(cdi_zip.probe.DM_cmd_cycle))):
            im = ax.imshow(probe_maps[ix],   #
                           vmax=np.max(probe_maps[0]), vmin=-np.max(probe_maps[0]) # np.min(probe_maps[0])
                           )
            ax.set_title(f"t={probe_tstamps[ix] - (cdi_zip.ts.cmd_tstamps[0]).astype('float')/1e9:.2f}")

        cax = fig.add_axes([0.91, 0.2, 0.02, 0.6])  # Add axes for colorbar @ position [left,bottom,width,height]
        cb = fig.colorbar(im, orientation='vertical', cax=cax)  #
        cb.set_label('DM voltage (relative scale)')
        plt.savefig(f'{plt_path}/{target_name}_dmMap_probeseq.png')

        # Null DM Map
        fig, subplot = plt.subplots(2, len(cmds_nulls_only) // 2, figsize=(14, 8))
        fig.suptitle(f'DM Telemetry Data, Non-probed Timesteps (nulls): '
                     f'target = {target_name}\n'
                     f' N probes={n_probes}, '
                     f'N null steps={int(n_nulls)}, '
                     f'integration time={cdi_zip.ts.phase_integration_time} sec', fontweight='bold', fontsize=14)

        for ax, ix in zip(subplot.flatten(), range(len(cmds_nulls_only))):
            im = ax.imshow(null_maps[ix],  #
                           vmax=np.max(null_maps[0]), vmin=-np.max(null_maps[0])  # 0
                           )
            ax.set_title(f"t={null_tstamps[ix] - (cdi_zip.ts.cmd_tstamps[0]).astype('float') / 1e9:.2f}")
        cax = fig.add_axes([0.91, 0.2, 0.02, 0.6])  # Add axes for colorbar @ position [left,bottom,width,height]
        cb = fig.colorbar(im, orientation='vertical', cax=cax)  #
        cb.set_label(f'DM actuator height (' + r'$\mu$' + 'm, uncalibrated)')
        plt.savefig(f'{plt_path}/{target_name}_dmMap_nullseq.png')

    # Re-center array to match mec images
    cpx_dm   = np.roll(cpx_dm , (-3, 20),(1,2))
    cpx_null = np.roll(cpx_null,(-3, 20),(1,2))
    if plot:
        # Complex Map
        # fp_mask, edges = get_fp_mask(cdi_zip)
        # cl = LineCollection(edges, colors='r')

        fig, subplot = plt.subplots(2, n_probes // 2, figsize=(14, 8))
        fig.suptitle(f'Propogated Intensity through SCExAO Model (probes): '
                     f'target = {target_name}\n'
                     f' N probes={cdi_zip.ts.n_probes}, '
                     f'N null steps={int(cdi_zip.ts.null_time / cdi_zip.ts.phase_integration_time)}, '
                     f'integration time={cdi_zip.ts.phase_integration_time} sec', fontweight='bold', fontsize=14)

        for ax, ix in zip(subplot.flatten(), range(n_probes)):
            im = ax.imshow(np.abs(cpx_dm[ix])**2, interpolation='none',
                  norm=LogNorm(vmin=1e-5,vmax=1e-2)
                           )
            # ax.add_collection(cl)
            ax.set_title(f"t={probe_tstamps[ix] - (cdi_zip.ts.cmd_tstamps[0]).astype('float')/1e9:.2f}")

        cax = fig.add_axes([0.91, 0.2, 0.02, 0.6])  # Add axes for colorbar @ position [left,bottom,width,height]
        cb = fig.colorbar(im, orientation='vertical', cax=cax)  #
        cb.set_label(f'Intensity')
        plt.savefig(f'{plt_path}/{target_name}_simulated_focalplane.png')

    # plt.show()
    ######################
    # CDI Algorithm
    # ####################
    # Defining Matrices
    delta = np.zeros((n_pairs, nx, ny), dtype=float)
    E_pupil = np.zeros((n_nulls*n_cycles, nx, ny), dtype=complex)
    H = np.zeros((n_pairs, 2), dtype=float)
    b = np.zeros((n_pairs, 1))

    # Masking
    mask2D, imsk, jmsk, irng, jrng, imx, imn, jmx, jmn = get_fp_mask(cdi_zip, thresh=1e-3, shft=[-3, 20])  # , shft=[25,10]

    if debug:
        fig, ax = plt.subplots(1,1)
        fig.suptitle(f'Masked FP in CDI probe Region', fontweight='bold', fontsize=14)
        im = ax.imshow((mec_probed[0,:,:]*mask2D).T)

        cax = fig.add_axes([0.85, 0.2, 0.02, 0.6])  # Add axes for colorbar @ position [left,bottom,width,height]
        cb = fig.colorbar(im, orientation='vertical', cax=cax)  #
        cb.set_label(f'Counts')

    cdit = time.time()
    for cy in range(1):  # range(cdi_zip.ts.n_cycles)
        cycle = cy*n_nulls
        for i in range(140):  #  range(80,85)  irng range(140)
            for j in range(140):  #  range(80,85)  jrng range(140)
                for xn in range(n_nulls):
                    for ip in range(n_pairs):
                        # print(f'writing to [{cycle + xn}, i={i}, j={j}], cycle={cycle}, cy={cy}, xn={xn}')
                        # Differance Images (delta)
                        # (I_ip+ - I_ip-)/2
                        delta[ip,:,:] = (mec_probed[cycle+ip, :, :] - mec_probed[cycle + ip + n_pairs, :, :]) / 2
                            #TODO does this get overwritten each cycle?

                        # Amplitude DeltaP
                        Ip = mec_probed[cycle + ip, i, j]
                        Im = mec_probed[cycle + ip + n_pairs, i, j]
                        Io = mec_nulls[cycle + xn, i, j] #TODO fix this to run over all nulls in series
                        abs = (Ip + Im) / 2 - Io
                        if abs < 0:
                            abs = 0
                        absDeltaP = np.sqrt(abs)
                        # absDeltaP = np.sqrt(np.abs((Ip + Im) / 2 - Io))

                        # Phase DeltaP
                        # The phase of the change in the focal plane of the probe applied to the DM
                        # First subtract Eo vector from each probe phase to make new field vectors dEa, dEb,
                        # then take the angle between the two
                        dEp = cpx_dm[cycle + ip, i, j] - cpx_null[cycle + xn, i, j]
                        dEm = cpx_dm[cycle+ip+n_pairs, i, j] - cpx_null[cycle + xn, i, j]
                        # dEp = fp_seq[i, j, ip] - fp_seq[i, j, cdi_zip.ts.n_probes + xn]
                        # dEm = fp_seq[i, j, ip + n_pairs] - fp_seq[i, j, cdi_zip.ts.n_probes + xn]
                        phsDeltaP = np.arctan2(dEp.imag - dEm.imag, dEp.real - dEm.real)

                        # print(f'dEp={dEp}, dEm={dEm}, xn={xn}\n'
                        #       f'abs={absDeltaP}, phs={phsDeltaP}')

                        cpxDeltaP = absDeltaP * np.exp(1j * phsDeltaP)
                        H[ip, :] = [-cpxDeltaP.imag, cpxDeltaP.real]  # [n_pairs, 2]
                        b[ip] = delta[ip, i, j]  # [n_pairs, 1]

                    a = 2 * H
                    Exy = sl.lstsq(a, b)[0]  # returns tuple, not array
                    # print(f'writing to [{cycle + xn}, i={i}, j={j}], cycle={cycle}, cy={cy}, xn={xn}')
                    E_pupil[cycle + xn, i, j] = Exy[0] + (1j * Exy[1])

    et = time.time()
    print(f'CDI post-processing for {n_nulls*cdi_zip.ts.n_cycles} null-images'
          f' finished in {et-cdit:.1f} sec == {(et-cdit)/60:.2f} min\n')

    # I_processed
    I_processed = np.zeros((len(E_pupil), nx, ny))
    for ix in range(len(E_pupil)):
        I_processed[ix] = np.floor(np.abs(E_pupil[ix]) ** 2 )

    ##
    if plot:
        ####################
        # Difference Images
        fig, subplot = plt.subplots(1, n_pairs, figsize=(14,5))
        fig.subplots_adjust(wspace=0.3, right=0.90, left=0.05)

        fig.suptitle((r'$I_i^+ - I_i^-$' ' for CDI Probes'), fontweight='bold', fontsize=14)

        for ax, ix in zip(subplot.flatten(), range(n_pairs)):
            im = ax.imshow(delta[ix].T, interpolation='none',
                           # norm=SymLogNorm(linthresh=1e-2),
                           vmin=-1, vmax=1) #, norm=SymLogNorm(linthresh=1e-5))
            ax.set_title(f"Diff Probe\n" + r'$\theta$' + f'={cdi_zip.ts.phase_cycle[ix]/np.pi:.3f}' +
                         r'$\pi$ -$\theta$' + f'={cdi_zip.ts.phase_cycle[ix+n_pairs]/np.pi:.3f}' + r'$\pi$')

        # cax = fig.add_axes([0.9, 0.2, 0.03, 0.6])  # Add axes for colorbar @ position [left,bottom,width,height]
        # cb = fig.colorbar(im, orientation='vertical', cax=cax)  #
        # cb.set_label('Intensity')


        ##############################
        # Focal Plane E-field Estimate
        fig, subplt = plt.subplots(2, 4, figsize=(14, 7))
        fig.subplots_adjust(wspace=0.3, right=0.85, left=0.05)

        fig.suptitle('Estimated Focal-Plane E-field', fontweight='bold', fontsize=14)
        for ax, ix in zip(subplt.flatten(), range(8)):
            im = ax.imshow(I_processed[ix].T, interpolation='none',  # ,
                           vmin=-1, vmax=200)  # ,
                           # norm=LogNorm())
            ax.set_title(f'Estimation timestep {ix}')
        cax = fig.add_axes([0.9, 0.2, 0.03, 0.6])  # Add axes for colorbar @ position [left,bottom,width,height]
        cb = fig.colorbar(im, orientation='vertical', cax=cax)  #
        cb.set_label('Intensity')

        ######################
        # Subtracted E-field
        fig, subplot = plt.subplots(1, 3, figsize=(14, 5))
        fig.subplots_adjust(wspace=0.1, right=0.85, left=0.05)
        fig.suptitle(f' Subtracted E-field', fontweight='bold', fontsize=14)

        for ax, ix in zip(subplot, range(3)):
            imsx = ax.imshow(mec_nulls[ix,:,:].T-I_processed[ix].T, interpolation='none',
                             vmin=-1, vmax=2000)
                           # norm=LogNorm())
            ax.set_title(f'Estimation timestep {ix}')

        cax = fig.add_axes([0.9, 0.2, 0.03, 0.6])  # Add axes for colorbar @ position [left,bottom,width,height]
        cb = fig.colorbar(imsx, orientation='vertical', cax=cax)  #
        # cb.set_label('Intensity')
        ######################################################
        # Subtracted E-field
        fig, subplot = plt.subplots(2, 3, figsize=(14, 10))
        fig.subplots_adjust(wspace=0.1, right=0.85)
        fig.suptitle(f'{target_name} Subtracted E-field', fontweight='bold', fontsize=14)
        ax1, ax2, ax3, ax4, ax5, ax6 = subplot.flatten()

        ax1.imshow(fp_seq[0 + n_nulls].T, interpolation='none', vmin=-1, vmax=2000)
        ax1.set_title(f'Null Step 1')
        ax2.imshow(fp_seq[1 + n_nulls].T, interpolation='none', vmin=-1, vmax=2000)
        ax2.set_title(f'Null Step 2')
        ax3.imshow(fp_seq[2 + n_nulls].T, interpolation='none', vmin=-1, vmax=2000)
        ax3.set_title(f'Null Step 3')
        ax4.imshow(fp_seq[0 + n_nulls].T-I_processed[0].T, interpolation='none', vmin=-1, vmax=2000)
        ax4.set_title(f'CDI Subtracted Null 1')
        ax5.imshow(fp_seq[1 + n_nulls].T - I_processed[0].T, interpolation='none', vmin=-1, vmax=2000)
        ax5.set_title(f'CDI Subtracted Null 2')
        ax6.imshow(fp_seq[ 2 + n_nulls].T - I_processed[0].T, interpolation='none', vmin=-1, vmax=2000)
        ax6.set_title(f'CDI Subtracted Null 3')

        # plt.show()
        ##
        # DeltaP
        fig, subplot = plt.subplots(2, n_pairs, figsize=(12, 8))
        fig.subplots_adjust(wspace=0.5, right=0.85)
        fig.suptitle(r'$\frac{I_i^+ + I_i^-}{2} - I_{null}$ for CDI Probes  ' +
                     f'target = {target_name}, \n'
                     f'Probe Amp = {cdi_zip.probe.amp}, N probes={cdi_zip.ts.n_probes}, '
                     f'N null steps={int(cdi_zip.ts.null_time / cdi_zip.ts.phase_integration_time)}, '
                     f'integration time={cdi_zip.ts.phase_integration_time} sec\n', fontweight='bold', fontsize=14)

        cnt = np.tile(range(n_pairs), 2)
        xn = 1
        for ax, ix in zip(subplot.flatten(), range(2 * n_pairs)):
            Ip = fp_seq[cnt[ix] ]
            Im = fp_seq[cnt[ix] + n_pairs]
            Io = fp_seq[cdi_zip.ts.n_probes + (ix // n_pairs + 0)]

            absDP = (Ip + Im) / 2 - Io
            # if absDP.any() < 0:
            #     absDP = 0
            # absDeltaP = np.sqrt(absDP)
            im = ax.imshow(absDP.T, interpolation='none',  #
                           vmin=-1, vmax=1,
                           cmap='plasma',
                           )  # , norm=SymLogNorm(linthresh=1e-5))
            ax.set_title(f"probe phase pair {cnt[ix] + 1},\nnull step {ix // n_pairs + 1 + 0}")
            # cl = LineCollection(edges, colors='r')
            # ax.add_collection(cl)
            if ix + 1 > xn * n_pairs - 1:
                xn += 1

        cax = fig.add_axes([0.9, 0.2, 0.03, 0.6])  # Add axes for colorbar @ position [left,bottom,width,height]
        cb = fig.colorbar(im, orientation='vertical', cax=cax)  #
        cb.set_label('Intensity')
Example #7
0
def coronagraph_demo():

    n = 512  # grid size
    lamda = 0.55  # wavelength (microns)

    (no_errors, no_errors_sampl) = proper.prop_run("run_coronagraph_dm",
                                                   lamda,
                                                   n,
                                                   PASSVALUE={
                                                       'use_errors': False,
                                                       'use_dm': False,
                                                       'occulter_type':
                                                       '8TH_ORDER'
                                                   },
                                                   VERBOSE=False)

    (with_errors, with_errors_sampl) = proper.prop_run("run_coronagraph_dm",
                                                       lamda,
                                                       n,
                                                       PASSVALUE={
                                                           'use_errors':
                                                           True,
                                                           'use_dm':
                                                           False,
                                                           'occulter_type':
                                                           '8TH_ORDER'
                                                       },
                                                       VERBOSE=False)

    (with_dm, with_dm_sampl) = proper.prop_run("run_coronagraph_dm",
                                               lamda,
                                               n,
                                               PASSVALUE={
                                                   'use_errors': True,
                                                   'use_dm': True,
                                                   'occulter_type': '8TH_ORDER'
                                               },
                                               VERBOSE=False)

    nd = 256
    psfs = np.zeros([3, nd, nd], dtype=np.float64)
    psfs[0, :, :] = no_errors[int(n / 2 - nd / 2):int(n / 2 + nd / 2),
                              int(n / 2 - nd / 2):int(n / 2 + nd / 2)]
    psfs[1, :, :] = with_errors[int(n / 2 - nd / 2):int(n / 2 + nd / 2),
                                int(n / 2 - nd / 2):int(n / 2 + nd / 2)]
    psfs[2, :, :] = with_dm[int(n / 2 - nd / 2):int(n / 2 + nd / 2),
                            int(n / 2 - nd / 2):int(n / 2 + nd / 2)]

    plt.figure(figsize=(14, 7))
    plt.suptitle("PSFs", fontsize=18, fontweight='bold')

    plt.subplot(1, 3, 1)
    plt.title('No errors')
    plt.imshow(psfs[0, :, :]**0.25, origin="lower", cmap=plt.cm.gray)
    plt.subplot(1, 3, 2)
    plt.title('With errors')
    plt.imshow(psfs[1, :, :]**0.25, origin="lower", cmap=plt.cm.gray)
    plt.subplot(1, 3, 3)
    plt.title('DM corrected')
    plt.imshow(psfs[2, :, :]**0.25, origin="lower", cmap=plt.cm.gray)
    plt.show()

    print("Maximum speckle flux / stellar flux :")
    print("  No wavefront errors = {0:0.3E}".format(np.max(no_errors),
                                                    np.min(no_errors)))
    print("  With wavefront errors = {0:0.3E}".format(np.max(with_errors)))
    print("  With DM correction = {0:0.3E}".format(np.max(with_dm)))
Example #8
0
if (mp.Nsbp == 1):
    lambdaFacs = np.array([1.])
else:
    lambdaFacs = np.linspace(1 - mp.fracBW / 2., 1 + mp.fracBW / 2., mp.Nsbp)

# Get the Input Pupil's E-field
mp.P1.compact.E = np.ones(
    (mp.P1.compact.Nbeam + 2, mp.P1.compact.Nbeam + 2, mp.Nsbp),
    dtype=complex)  # Initialize
for si in range(mp.Nsbp):
    lambda_um = 1e6 * mp.lambda0 * lambdaFacs[si]

    fldFull, sampling = proper.prop_run('wfirst_phaseb',
                                        lambda_um,
                                        nout,
                                        QUIET=True,
                                        PASSVALUE=optval.__dict__)
    if (mp.flagPlot):
        plt.figure(1)
        plt.imshow(np.angle(fldFull))
        plt.colorbar()
        plt.hsv()
        plt.pause(1e-2)
        plt.figure(2)
        plt.imshow(np.abs(fldFull))
        plt.colorbar()
        plt.magma()
        plt.pause(0.5)
        # figure(605); imagesc(angle(fldFull)); axis xy equal tight; colorbar; colormap hsv; drawnow;
        #         figure(606); imagesc(abs(fldFull)); axis xy equal tight; colorbar; colormap parula; drawnow;
Example #9
0
    def telescope(self):
        """
        main script to organize calls to various aspects of the telescope simulation

        initialize different sub-processes, such as atmosphere and aberration maps, MKID device parameters
        sets up the multiprocessing features
        returns the observation sequence

        :return: obs_sequence [n_timesteps, n_saved_planes, n_wavelengths, n_stars/planets, grid_size, grid_size]
        """
        print('Beginning Telescope Simulation with MEDIS')
        print('***************************************')
        start = time.time()

        # =======================================================================
        # Intialization
        # =======================================================================
        # Check for Existing File
        #todo update this automatic load if exists functionality

        # check = mu.check_exists_obs_sequence(plot=False)
        # if check:
        #     if iop.obs_seq[-3:] == '.h5':
        #         obs_sequence = mu.open_obs_sequence_hdf5(iop.obs_seq)
        #     else:
        #         obs_sequence = mu.open_obs_sequence(iop.obs_seq)
        #
        #     return obs_sequence

        if ap.companion is False:
            ap.contrast = []

        # Initialize CDI probes
        if cdip.use_cdi is True:
            theta_series = cdi.gen_CDI_phase_stream()
        else:
            theta_series = np.zeros(sp.numframes) * np.nan  # string of Nans

        # Initialize Obs Sequence
        self.cpx_sequence = np.zeros((sp.numframes, len(sp.save_list), ap.n_wvl_init, 1 + len(ap.contrast),
                                      sp.grid_size, sp.grid_size), dtype=np.complex)
        self.sampling = np.zeros((len(sp.save_list), ap.n_wvl_init))

        # =======================================================================================================
        # Closed-Loop- No Multiprocessing
        # =======================================================================================================
        if sp.closed_loop:
            ##########################
            # Generating Timeseries
            ##########################
            for t in range(sp.numframes):
                kwargs = {'iter': t, 'params': [ap, tp, iop, sp],
                          'WFS_map':self.cpx_sequence[t-sp.ao_delay]}
                self.cpx_sequence[t], self.sampling = proper.prop_run(tp.prescription, 1, sp.grid_size,
                                                                         PASSVALUE=kwargs,
                                                                         VERBOSE=False,
                                                                         TABLE=False)  # 1 is dummy wavelength

            print('MEDIS Telescope Run Completed')
            print('**************************************')
            finish = time.time()
            print(f'Time elapsed: {(finish - start) / 60:.2f} minutes')
            # print(f"Number of timesteps = {np.shape(cpx_sequence)[0]}")

            return self.cpx_sequence, self.sampling

        # =======================================================================================================
        # Open-Loop- Uses Multiprocessing
        # =======================================================================================================
        else:
            try:
                multiprocessing.set_start_method('spawn')
            except RuntimeError:
                pass

            # Multiprocessing Settings
            time_idx = multiprocessing.Queue()  # time indicies that begin each timestep calculation
            out_chunk = multiprocessing.Queue()  # tuple of planes and sampling after each chunk is calculated
            jobs = []

            # Everything initialised in Timeseries is available to us in this obj. planes etc need to be accessed using a queue
            mt = MutliTime(time_idx, out_chunk)

            # Create the processes
            for i in range(sp.num_processes):
                p = multiprocessing.Process(target=mt.gen_timeseries, args=())
                jobs.append(p)
                p.start()

            # Populate the time indicies and start the simulation
            for t in range(sp.startframe, sp.startframe + sp.numframes):
                time_idx.put(t)

            # Tell the simulation to stop after the final time index is reached
            for i in range(sp.num_processes):
                time_idx.put(sentinel)

            # ========================
            # Read Obs Sequence
            # ========================
            # Getting Returned Variables from gen_timeseries
            for it in range(int(np.ceil(mt.num_chunks))):
                fields_chunk, sampling = out_chunk.get()
                self.cpx_sequence[it*mt.chunk_steps - sp.startframe :
                             (it+1)*mt.chunk_steps - sp.startframe, :, :, :, :, :] = fields_chunk
            self.sampling = sampling

            # # Ending the gen_timeseries loop via multiprocessing protocol
            for i, p in enumerate(jobs):
                p.join()  # Wait for all the jobs to finish and consolidate them here

        print('MEDIS Telescope Run Completed')
        print('**************************************')
        finish = time.time()
        print(f'Time elapsed: {(finish - start) / 60:.2f} minutes')
        # print(f"Number of timesteps = {np.shape(cpx_sequence)[0]}")

        mu.display_sequence_shape(self.cpx_sequence)

        return self.cpx_sequence, self.sampling
Example #10
0
    lambdaFacs = np.array([1.])
else:
    lambdaFacs = np.linspace(1 - mp.fracBW / 2, 1 + mp.fracBW / 2, mp.Nsbp)

# Get the Input Pupil's E-field
nCompact = falco.util.ceil_even(mp.P1.compact.Nbeam + 1)
mp.P1.compact.E = np.ones((nCompact, nCompact, mp.Nsbp), dtype=complex)
for iSubband in range(mp.Nsbp):

    lambda_um = 1e6 * mp.lambda0 * lambdaFacs[iSubband]

    # Get aberrations for the full optical train
    optval.pinhole_diam_m = 0  # 0 means don't use the pinhole at FPAM
    fieldFullAll, sampling = proper.prop_run('roman_phasec',
                                             lambda_um,
                                             nout,
                                             QUIET=True,
                                             PASSVALUE=optval.__dict__)

    # Put pinhole at FPM to get back-end optical aberrations
    optval.pinhole_diam_m = mp.F3.pinhole_diam_m
    fieldFullBackEnd, sampling = proper.prop_run('roman_phasec',
                                                 lambda_um,
                                                 nout,
                                                 QUIET=True,
                                                 PASSVALUE=optval.__dict__)
    optval.pinhole_diam_m = 0  # 0 means don't use the pinhole at FPAM

    # Subtract off back-end phase aberrations from the phase retrieval estimate
    phFrontEnd = np.angle(fieldFullAll) - np.angle(fieldFullBackEnd)
    # swMask = ampthresh(fieldFullAll)
Example #11
0
    # 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)


proper.prop_run('simple_telescope', 1.1, 128, PHASE_OFFSET=1)
Example #12
0
#code to run CAOS
if tp.use_atmos and glob.glob(cp.atmosdir + '*.fits') == []:
    import Atmosphere.caos as caos  #import here since pidly can stay open sometimes and that's annoying
    caos.make_idl_params()
    caos.generate_maps()

# hypercube = []
for t in range(1):
    print 'propagating frame:', t
    kwargs = {
        'iter': t,
        'atmos_map': cp.atmosdir + 'telz%f.fits' % (t * mp.frame_time)
    }
    no_occult = proper.prop_run("run_system",
                                1,
                                tp.grid_size,
                                PASSVALUE=kwargs,
                                VERBOSE=False,
                                PHASE_OFFSET=1)[0][0]

tp.occult_loc = (4, -6)  #opposit sense to normal x y direction
tp.occulter_type = 'GAUSSIAN'  # None#

for t in range(1):
    print 'propagating frame:', t
    kwargs = {
        'iter': t,
        'atmos_map': cp.atmosdir + 'telz%f.fits' % (t * mp.frame_time)
    }
    occult = proper.prop_run("run_system",
                             1,
                             tp.grid_size,
Example #13
0
def full(mp, modvar, isNorm=True):
    """
    Truth model used to generate images in simulation.

    Truth model used to generate images in simulation. Can include
    aberrations/errors that are unknown to the estimator and controller. This
    function is the wrapper for full models of any coronagraph type.

    Parameters
    ----------
    mp : ModelParameters
        Structure containing optical model parameters
    modvar : ModelVariables
        Structure containing temporary optical model variables
    isNorm : bool
        If False, return an unnormalized image. If True, return a
        normalized image with the currently stored norm value.

    Returns
    -------
    Eout : numpy ndarray
        2-D electric field in final focal plane
    """
    if type(mp) is not falco.config.ModelParameters:
        raise TypeError('Input "mp" must be of type ModelParameters')

    if hasattr(modvar, 'sbpIndex'):
        normFac = mp.Fend.full.I00[modvar.sbpIndex, modvar.wpsbpIndex]
        # Value to normalize the PSF. Set to 0 when finding the norm factor

    # Optional Keyword arguments
    if not isNorm:
        normFac = 0

    # Set the wavelength
    if (hasattr(modvar, 'wvl')):  # For FALCO or standalone use of full model
        wvl = modvar.wvl
    elif (hasattr(modvar, 'sbpIndex')):  # For use in FALCO
        wvl = mp.full.lambdasMat[modvar.sbpIndex, modvar.wpsbpIndex]
    else:
        raise ValueError('Need to specify value or indices for wavelength.')
    """ Input E-fields """
    if modvar.whichSource.lower() == 'offaxis':  # Use for thput calculations
        TTphase = (-1.) * (2 * np.pi * (modvar.x_offset * mp.P2.full.XsDL +
                                        modvar.y_offset * mp.P2.full.YsDL))
        Ett = np.exp(1j * TTphase * mp.lambda0 / wvl)
        Ein = Ett * np.squeeze(mp.P1.full.E[:, :, modvar.wpsbpIndex,
                                            modvar.sbpIndex])

    else:  # Default to using the starlight
        Ein = np.squeeze(mp.P1.full.E[:, :, modvar.wpsbpIndex,
                                      modvar.sbpIndex])

    # Shift the source off-axis to compute the intensity normalization value.
    # This replaces the previous way of taking the FPM out in the optical model
    if normFac == 0:
        source_x_offset = mp.source_x_offset_norm  # source offset in lambda0/D
        source_y_offset = mp.source_y_offset_norm  # source offset in lambda0/D
        TTphase = (-1) * (2 * np.pi * (source_x_offset * mp.P2.full.XsDL +
                                       source_y_offset * mp.P2.full.YsDL))
        Ett = np.exp(1j * TTphase * mp.lambda0 / wvl)
        Ein = Ett * np.squeeze(mp.P1.full.E[:, :, modvar.wpsbpIndex,
                                            modvar.sbpIndex])

    # Apply a Zernike (in amplitude) at input pupil if specified
    if not (hasattr(modvar, 'zernIndex')):
        modvar.zernIndex = 1
    if not modvar.zernIndex == 1:
        indsZnoll = modvar.zernIndex  # Just send in 1 Zernike mode
        zernMat = np.squeeze(
            falco.zern.gen_norm_zern_maps(mp.P1.full.Nbeam, mp.centering,
                                          indsZnoll))
        zernMat = pad_crop(zernMat, mp.P1.full.Narr)
        Ein = Ein * zernMat * (
            2 * np.pi / wvl) * mp.jac.Zcoef[mp.jac.zerns == modvar.zernIndex]

    # %% Pre-compute the FPM first for HLC
    if mp.layout.lower() == 'fourier' or mp.layout.lower() == 'proper':
        # ilam = (modvar.sbpIndex-1)*mp.Nwpsbp + modvar.wpsbpIndex
        if mp.coro.upper() == 'HLC':
            mp.F3.full.mask = falco.hlc.gen_fpm_from_LUT(
                mp, modvar.sbpIndex, modvar.wpsbpIndex, 'full')
    elif mp.layout.lower() == 'fpm_scale':
        if mp.coro.upper() == 'HLC':
            if mp.Nsbp > 1 and mp.Nwpsbp > 1:
                # Weird indexing is because interior wavelengths at
                # edges of sub-bands are the same, and the fpmCube
                # contains only the minimal set of masks.
                ilam = (modvar.sbpIndex-2)*mp.Nwpsbp + modvar.wpsbpIndex + \
                    (mp.Nsbp-modvar.sbpIndex+1)
            elif mp.Nsbp == 1 and mp.Nwpsbp > 1:
                ilam = modvar.wpsbpIndex
            elif mp.Nwpsbp == 1:
                ilam = modvar.sbpIndex

            mp.F3.full.mask = mp.full.fpmCube[:, :, ilam]

    # %% Select which optical layout's full model to use.
    if mp.layout.lower() == 'fourier':
        Eout = full_Fourier(mp, wvl, Ein, normFac)

    elif mp.layout.lower() == 'fpm_scale':  # FPM scales with wavelength
        Eout = full_Fourier(mp, wvl, Ein, normFac, flagScaleFPM=True)

    elif mp.layout.lower() == 'proper':

        optval = copy.copy(vars(mp.full))

        if any(mp.dm_ind == 1):
            optval['use_dm1'] = True
            optval['dm1'] = mp.dm1.V * mp.dm1.VtoH + mp.full.dm1FlatMap

        if any(mp.dm_ind == 2):
            optval['use_dm2'] = True
            optval['dm2'] = mp.dm2.V * mp.dm2.VtoH + mp.full.dm2FlatMap

        if normFac == 0:
            optval['xoffset'] = -mp.source_x_offset_norm
            optval['yoffset'] = -mp.source_y_offset_norm
            if mp.coro.upper() in ('VORTEX', 'VC', 'AVC'):
                optval['use_fpm'] = False
                optval['xoffset'] = 0
                optval['yoffset'] = 0
                pass

        # wavelength needs to be in microns instead of meters for PROPER
        [Eout, sampling_m] = proper.prop_run(mp.full.prescription,
                                             wvl * 1e6,
                                             mp.P1.full.Narr,
                                             QUIET=True,
                                             PASSVALUE=optval)
        if not normFac == 0:
            Eout = Eout / np.sqrt(normFac)

        del optval

    elif mp.layout.lower() in ('wfirst_phaseb_proper', 'roman_phasec_proper'):
        optval = copy.copy(vars(mp.full))
        optval['use_dm1'] = True
        optval['use_dm2'] = True
        optval['dm1_m'] = mp.dm1.V * mp.dm1.VtoH + mp.full.dm1.flatmap
        optval['dm2_m'] = mp.dm2.V * mp.dm2.VtoH + mp.full.dm2.flatmap
        if normFac == 0:
            optval['source_x_offset'] = -mp.source_x_offset_norm
            optval['source_y_offset'] = -mp.source_y_offset_norm

        if mp.layout.lower() == 'wfirst_phaseb_proper':
            fn_proper = 'wfirst_phaseb'
        elif mp.layout.lower() == 'roman_phasec_proper':
            fn_proper = 'roman_phasec'

        [Eout,
         sampling] = proper.prop_run(fn_proper,
                                     wvl * 1e6,
                                     int(2**falco.util.nextpow2(mp.Fend.Nxi)),
                                     QUIET=True,
                                     PASSVALUE=optval)
        Eout = pad_crop(Eout, (mp.Fend.Nxi, mp.Fend.Nxi))

        if not normFac == 0:
            Eout = Eout / np.sqrt(normFac)

    return Eout
Example #14
0
def Simulation(inqueue, output, datacubes, xxx_todo_changeme):
    # def Simulation(inqueue, output, (dp, cp)):
    (tp, ap, sp, iop, cp, mp) = xxx_todo_changeme

    # import matplotlib.pylab as plt
    # plt.plot(list(range(10)))
    # plt.show()
    # plt.show(block=True)

    try:

        if tp.detector == 'MKIDs':
            with open(iop.device_params, 'rb') as handle:
                dp = pickle.load(handle)

        # with open(iop.NCPA_meas, 'rb') as handle:
        #     tp.Imaps, tp.phase_map = pickle.load(handle)
        # hypercube = []
        start = time.time()

        for it, t in enumerate(iter(inqueue.get, sentinel)):

            if cp.vary_r0:
                # # print cp.r0s, cp.r0s_idx
                # cp.r0s_idx = caos.random_r0walk(cp.r0s_idx, cp.r0s)
                # # print cp.r0s_idx
                # r0 = cp.r0s[cp.r0s_idx]
                element = int(np.random.random() * len(cp.r0s))
                # cp.r0s_idx = element
                r0 = cp.r0s[element]
            else:
                r0 = cp.r0s  # this is a scalar in this instance
            # dprint((t, r0, 'r0', tp.rot_rate))
            atmos_map = cp.atmosdir + 'telz%f_%1.3f.fits' % (
                t * cp.frame_time, r0)  #t *
            # dprint((atmos_map, cp.atmosdir))
            kwargs = {
                'iter': t,
                'atmos_map': atmos_map,
                'params': [ap, tp, iop, sp]
            }
            # dprint(tp.occulter_type)
            datacube, _ = proper.prop_run("run_system",
                                          1,
                                          tp.grid_size,
                                          PASSVALUE=kwargs,
                                          VERBOSE=False,
                                          PHASE_OFFSET=1)
            # view_datacube(datacube, logAmp=True)
            # print np.sum(datacube,axis=(1,2))

            if tp.detector == 'ideal':
                image = np.sum(datacube, axis=0)
                vmin = np.min(datacube) * 10
                # cube = ideal.assign_calibtime(datacube,PASSVALUE['iter'])
                # cube = rawImageIO.arange_into_cube(packets, value='phase')
                # rawImageIO.make_phase_map(cube, plot=True)
                # return ''
            elif tp.detector == 'H2RG':

                image = np.sum(datacube, axis=0)
                vmin = np.min(datacube) * 10
            elif tp.detector == 'MKIDs':

                # dprint(dp.__dict__)
                # print np.sum(datacube, axis=(1,2)), 'sum'
                packets = read.get_packets(datacube, t, dp, mp)
                # dprint(packets.shape)
                # plt.hist(packets[:,1] - packets[:,0])
                # plt.show()

                if sp.show_wframe or sp.show_cube or sp.return_cube:
                    cube = pipe.arange_into_cube(
                        packets, (mp.array_size[0], mp.array_size[1]))
                    # # if mp.remove_close:
                    # #     timecube = read.remove_close_photons(cube)

                if sp.show_wframe:
                    image = pipe.make_intensity_map(
                        cube, (mp.array_size[0], mp.array_size[1]))

                # # # packets = rawImageIO.arange_into_packets(cube)
                # # # wfo = read.convert_to_wfo(image, wfo)
                if sp.show_cube or sp.return_cube:
                    datacube = pipe.make_datacube(
                        cube, (mp.array_size[0], mp.array_size[1], tp.w_bins))
                    # dprint(datacube.shape)
                    # datacube = datacube[:,:mp.array_size[0],:mp.array_size[0]]
                    # dprint(datacube.shape)
                # print packets.shape
                if sp.save_obs:
                    command = read.get_obs_command(packets, t)
                    output.put(command)

                vmin = 0.9
                # return command
                # else:
                #     return ''
            # hypercube.append(datacube)

            if sp.show_wframe:
                quicklook_im(image,
                             logAmp=True,
                             show=sp.show_wframe,
                             vmin=vmin)
                # dprint(np.sum(image))
            if sp.show_cube:
                # import matplotlib.pyplot as plt
                # plt.plot(np.sum(datacube,axis=(1,2)))
                # plt.show()
                view_datacube(datacube, logAmp=True, vmin=vmin)

            if sp.return_cube:
                datacubes.put((t, datacube))
            # dprint('lol')
            # return datacube
            now = time.time()
            elapsed = float(now - start) / 60.
            each_iter = float(elapsed) / (it + 1)
            # print ap.numframes, each_iter
            dprint('%i elapsed of %i mins' %
                   (elapsed, each_iter * ap.numframes / sp.num_processes))
    except Exception as e:
        # print ' **** Caught Exception ****'
        traceback.print_exc()
        # raise e
        pass
        ('normLyotDiam', 0.95),
        ('vortexCharge', 6),
        ('xoffset', 0),
        ('yoffset', 0)
            ])

# %% No Correction

# Phase Retrieval of Pupil
optval['use_pr'] = True
optval['pr_pupil_diam_pix'] = 248
optval['use_errors'] = 1  # 1 = use optical surface errors, 0 = none
optval['use_fpm'] = 0  # use focal plane mask (0 = no FPM)
optval['use_lyot_stop'] = 1  # use Lyot stop (0 = no stop)
optval['use_field_stop'] = 0  # use field stop (0 = no stop)
[Epup, sampling_m] = proper.prop_run(prescription, lambda_um, gridsize,
                                     PASSVALUE=optval, QUIET=True)

mask = np.zeros(Epup.shape)
mask[np.abs(Epup) > 0.1*np.max(np.abs(Epup))] = 1

plt.figure(1); plt.imshow(np.abs(Epup)); plt.colorbar(); plt.title('abs(Epupil)'); plt.pause(1e-2)
plt.figure(2); plt.imshow(mask*np.angle(Epup)); plt.colorbar(); plt.clim(-1, 1); plt.title('angle(Epupil)'); plt.pause(1e-2)

# PSF for normalization
optval['use_pr'] = False
optval['use_errors'] = 1;		#-- 1 = use optical surface errors, 0 = none
optval['use_fpm'] = 0;		#-- use focal plane mask (0 = no FPM)
optval['use_lyot_stop'] = 1 	#-- use Lyot stop (0 = no stop)
optval['use_field_stop'] = 0 	#-- use field stop (0 = no stop)
[EforNorm, sampling_m] = proper.prop_run(prescription, lambda_um, gridsize, PASSVALUE=optval, QUIET=True )
IforNorm = np.abs(EforNorm)**2
Example #16
0
    lambdaFacs = (1, )
else:
    lambdaFacs = np.linspace(1 - mp.fracBW / 2, 1 + mp.fracBW / 2, mp.Nsbp)

prescription = 'habex'

# Get the Input Pupil's E-field
Nf = nout  #--N full
Nc = falco.util.ceil_even((mp.P1.compact.Nbeam / mp.P1.full.Nbeam) * Nf)
mp.P1.compact.E = np.ones((Nc, Nc, mp.Nsbp), dtype=complex)
# mp.P1.compact.E = ones(mp.P1.compact.Nbeam+2, mp.P1.compact.Nbeam+2, mp.Nsbp); %--Initialize
for si in range(mp.Nsbp):
    lambda_um = 1e6 * mp.lambda0 * lambdaFacs[si]
    [fldFull, sampling_m] = proper.prop_run(prescription,
                                            lambda_um,
                                            nout,
                                            PASSVALUE=optval,
                                            QUIET=True)
    if (mp.flagPlot):
        pass
        plt.figure(605)
        plt.imshow(np.angle(fldFull))
        plt.colorbar
        plt.hsv()
        plt.pause(1e-2)
        plt.figure(606)
        plt.imshow(np.abs(fldFull))
        plt.colorbar
        plt.magma()
        plt.pause(1e-2)
import proper
import matplotlib.pyplot as plt
from matplotlib import cm


def simple_telescope(wavelength, gridsize):
    diam = 1.0
    focal_ratio = 15.0
    focal_length = diam * focal_ratio
    beam_ratio = 0.5

    wfo = proper.prop_begin(diam, wavelength, gridsize, beam_ratio)

    proper.prop_circular_aperture(wfo, diam / 2)
    proper.prop_zernikes(wfo, [5], [1e-6])
    proper.prop_define_entrance(wfo)
    proper.prop_lens(wfo, focal_length * 0.98)

    proper.prop_propagate(wfo, focal_length)

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

    return (wfo, sampling)


if __name__ == "__main__":
    psf, sampling = proper.prop_run('simple_telescope', 0.5, 512)
    plt.imshow(psf, cmap=cm.gray)
    plt.show()
Example #18
0
def metiscoronagraphsimulator(
        n,
        lam,
        pixelsize,
        prefix,
        path,
        diam=37.,
        r_obstr=0.3,
        f_lens=658.6,
        pupil_file=0,
        spiders_width=0.60,
        spiders_angle=[0., 60., 120.],
        charge=0,
        LS_parameters=[0.0, 0.0, 0.0],
        amplitude_apodizer_file=0,
        phase_apodizer_file=0,
        LS_amplitude_apodizer_file=0,
        LS_phase_apodizer_file=0,
        TILT=[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.,
        NoCoro_psf=0,
        Offaxis_psf=0,
        ELT_circ=True,
        Vortex=False,
        Back=False,
        RAVC=False,
        LS=False,
        Debug=True,
        Debug_print=True,
        Norm_max=True,
        Norm_flux1=False):
    """MCS.
        
        Parameters
        ----------
        n : integer
        Grid size
        
        lam : float in microns
        Wavelength
        
        pixelsize : float in mas
        Pixelsize in the detector plane
        
        prefix : string
        Prefix for the fits file writing
        
        path : string
        path where to save the outputs
        
        
        Returns
        -------
        None
        
        
        PASSVALUE
        ---------
        diam: 37. --> float, meters
        when both ELT_circ and other_pupil are False, the diameter has to be defined here
        
        r_obstr: 0.3 -->float, ratio
        when both ELT_circ and other_pupil are False, the central obstruction has to be defined here
        
        f_lens: 658.6 --> float, meters
        focal distance
        
        pupil_file: 0 --> float matrix
        it contains the pupil in case the 'other_pupil' is called
        
        spiders_width: 0.60 --> float, meters
        the spiders width has to be defined here, when the 'ELT_circ' is called (the fits file has no spiders) and when both ELT_circ and other_pupil are False and spiders are present
        
        spiders_angle: [0., 60., 120.] --> float, degrees
        the spiders rotation angle has to be defined here, when the 'ELT_circ' is called (the fits file has no spiders) and when both ELT_circ and other_pupil are False and spiders are present
        
        charge: 0 -->integer
        it indicates the charge of the vortex coronagraph ('Vortex' has to be called)
        
        LS_parameters : [0.0, 0.0, 0.0] --> float [percentage of the outer diamter, percentage of the outer diamter to add to the central obstruction/apodizer diameter, meters for the spiders]
            it indicates the values of the Lyot Stop ('LS' has to be called)
        
        amplitude_apodizer_file:0, float matrix
        it contains the pupil amplitude apodizer file in case the 'amplitude_apodizer' is called
        
        phase_apodizer_file:0, float matrix
        it contains the pupil phase apodizer file in case the 'phase_apodizer' is called
        
        LS_amplitude_apodizer_file:0, float matrix
        it contains the Lyot Stop amplitude apodizer file in case the 'LS_amplitude_apodizer' is called
        
        LS_phase_apodizer_file:0, float matrix
        it contains the yot Stop phase apodizer file in case the 'LS_phase_apodizer' is called
        
        TILT: [0.0, 0.0] --> float, lambda/D
        Tilt values : [xtilt, ytilt] !!! PROPER CHANGE THE DIRECTION BETWEEN XTILT AND YTILT !!!!
        
        atm_screen: 0 --> float matrix, microns
        it contains the atm phase screen
        
        missing_segments_number: 0 --> integer
        it contains the number of missing segments ('missing_segments' has to be called)
        
        apodizer_misalignment: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0] --> float, percentage
        it indicated the pupil apodizer misalignment: the first 3 are for an amplitude apodizer misalignment ('pupil_amplitude_apodizer_misalignment' has to be called) and the last 3 are for a phase apodizer misalignment ('pupil_phase_apodizer_misalignment' has to be called)
        
        LS_misalignment: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0] --> float, percentage
        it indicated the LS apodizer misalignment: the first 3 are for an amplitude apodizer misalignment ('LS_amplitude_apodizer_misalignment' has to be called) and the last 3 are for a phase apodizer misalignment ('LS_phase_apodizer_misalignment' has to be called)
        
        Island_Piston: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0] --> float, microns
        it indicated the values for the petals differential pistons. Since only 'ELT_circ' is supported for now, it needs 6 values for the 6 petals
        
        NCPA: 0 --> float matrix, microns
        it contains the NCPA matrix in microns
        
        NoCoro_psf: 0 --> float matrix, non coronagraphic psf
        
        Offaxis_psf: 0 --> float matrix, off-axis psf
        
        
        
        kwargs
        ----------------
        ELT_circ : bool
        If the pupil is the circularised ELT pupil in the file "ELT_2048_37m_11m_5mas_nospiders_cut.fits"

        Vortex : bool
        If the coronagraph is a vortex coronagraph, it needs the passvalue 'charge', which contains the charge of the vortex
        
        Back : bool
        If the back-propagation for the vortex coronagraph is needed: the back rpopagation depends on the grid and the pupil size (only the external diamater).
        
        RAVC: bool
        If the coronagraph is a RAVC (to work properly, also the vortex parameter has to be True)
        
        LS: bool
        If the Lyot Stop is present, it needs the passvalue 'LS_parameters' to be completed with the proper values
        
        Debug: bool
        it writes all the fits file, with the prefix
        
        Debug_print: bool
        it print several values
        
        Norm_max: bool
        it normalizes the psfs with respect to the max of the non-coronagraphic psf
        
        Norm_flux1: bool
        it normalizes the psfs with respect to the max of the non-coronagraphic psf, where the total flux has been put to 1

        """

    if (ELT_circ == True):
        PACKAGE_PATH = os.path.abspath(os.path.join(__file__, os.pardir))
        pupil_file = fits.getdata(PACKAGE_PATH +
                                  '/ELT_2048_37m_11m_5mas_nospiders_cut.fits')
        diam = 37.

    beam_ratio = pixelsize * 4.85e-9 / (lam * 1e-6 / diam)
    npupil = math.ceil(
        n * 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 ("Debug_print" in kwargs and kwargs["Debug_print"]):
    if (Debug_print == True):
        print("npupil: ", npupil)

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

    if (isinstance(NoCoro_psf, (list, tuple, np.ndarray)) != True):
        ## Non coronagraphic PSF --> simulate a non-coronagraphic psf
        (wfo_noCoro, sampling) = proper.prop_run(
            'telescope',
            lam,
            n,
            PASSVALUE={
                'prefix': prefix,
                'path': path,
                'charge': 0,
                'CAL': 0,
                'diam': diam,
                'spiders_width': spiders_width,
                'spiders_angle': spiders_angle,
                'beam_ratio': beam_ratio,
                'f_lens': f_lens,
                'npupil': npupil,
                'r_obstr': r_obstr,
                'pupil_file': pupil_file,
                '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.],
                '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': Debug_print,
                'Debug': Debug
            },
            QUIET=True)
        NoCoro_psf = (abs(wfo_noCoro))**2
        fits.writeto(
            path + prefix + '_psf_noCoro_nonorm.fits',
            NoCoro_psf[int(n / 2) - math.ceil(50. / beam_ratio):int(n / 2) +
                       math.ceil(50. / beam_ratio),
                       int(n / 2) - math.ceil(50. / beam_ratio):int(n / 2) +
                       math.ceil(50. / beam_ratio)],
            overwrite=True)
        #if ("Norm_max" in kwargs and kwargs["Norm_max"]):
        if (Norm_max == True):
            psf_noCoro_maxnorm = NoCoro_psf / np.max(NoCoro_psf)
            fits.writeto(
                path + prefix + '_psf_noCoro_maxnorm.fits',
                psf_noCoro_maxnorm[int(n / 2) -
                                   math.ceil(50. / beam_ratio):int(n / 2) +
                                   math.ceil(50. / beam_ratio),
                                   int(n / 2) -
                                   math.ceil(50. / beam_ratio):int(n / 2) +
                                   math.ceil(50. / beam_ratio)],
                overwrite=True)
        #if ("Norm_flux1" in kwargs and kwargs["Norm_flux1"]):
        if (Norm_flux1 == True):
            psf_noCoro_flux1norm = NoCoro_psf / sum(sum(NoCoro_psf))
            fits.writeto(
                path + prefix + '_psf_noCoro_flux1norm.fits',
                psf_noCoro_flux1norm[int(n / 2) -
                                     math.ceil(50. / beam_ratio):int(n / 2) +
                                     math.ceil(50. / beam_ratio),
                                     int(n / 2) -
                                     math.ceil(50. / beam_ratio):int(n / 2) +
                                     math.ceil(50. / beam_ratio)],
                overwrite=True)

    ## Coronagraphic PSF
    if (Vortex == True):

        if (Back == True):
            ## A/R --> simulate a perfect vortex by propagating a perfectly circular pupil through the vortex to the Lyot Stop, null the amplitude inside (as theory requires), then propagating back to the vortex level and save a "modified" vortex, to use in the future simulations
            (wfo_AR, sampling) = proper.prop_run(
                'telescope',
                lam,
                n,
                PASSVALUE={
                    'prefix': prefix,
                    'path': path,
                    'charge': charge,
                    'CAL': 1,
                    'diam': diam,
                    'spiders_width': 0,
                    'spiders_angle': [0., 0., 0.],
                    'beam_ratio': beam_ratio,
                    'f_lens': f_lens,
                    'npupil': npupil,
                    'r_obstr': 0.,
                    '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.],
                    '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': Debug_print,
                    'Debug': Debug
                },
                QUIET=True)

        if (isinstance(Offaxis_psf, (list, tuple, np.ndarray)) != True):
            ## No Vortex Si Mask --> simulate a non-coronagraphic-apodized psf: apodizer and Lyot Stop are present, but not the vortex --> as an off-axis psf
            (wfo_offaxis, sampling) = proper.prop_run(
                'telescope',
                lam,
                n,
                PASSVALUE={
                    'prefix': prefix,
                    'path': path,
                    'charge': 0,
                    'CAL': 0,
                    'diam': diam,
                    'spiders_width': spiders_width,
                    'spiders_angle': spiders_angle,
                    'beam_ratio': beam_ratio,
                    'f_lens': f_lens,
                    'npupil': npupil,
                    'r_obstr': r_obstr,
                    'pupil_file': pupil_file,
                    'phase_apodizer_file': phase_apodizer_file,
                    'amplitude_apodizer_file': amplitude_apodizer_file,
                    'TILT': [0., 0.],
                    'LS': LS,
                    'RAVC': RAVC,
                    'LS_phase_apodizer_file': LS_phase_apodizer_file,
                    'LS_amplitude_apodizer_file': LS_amplitude_apodizer_file,
                    'LS_parameters': LS_parameters,
                    'atm_screen': 0,
                    'missing_segments_number': missing_segments_number,
                    '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': Debug_print,
                    'Debug': Debug
                },
                QUIET=True)
            Offaxis_psf = (abs(wfo_offaxis))**2
            fits.writeto(path + prefix + '_psf_offaxis_nonorm.fits',
                         Offaxis_psf[int(n / 2) -
                                     math.ceil(50. / beam_ratio):int(n / 2) +
                                     math.ceil(50. / beam_ratio),
                                     int(n / 2) -
                                     math.ceil(50. / beam_ratio):int(n / 2) +
                                     math.ceil(50. / beam_ratio)],
                         overwrite=True)
            if (Norm_max == True):
                #if ("Norm_max" in kwargs and kwargs["Norm_max"]):
                psf_noVortex_Mask_maxnorm = Offaxis_psf / np.max(NoCoro_psf)
                fits.writeto(
                    path + prefix + '_psf_offaxis_maxnorm.fits',
                    psf_noVortex_Mask_maxnorm[
                        int(n / 2) - math.ceil(50. / beam_ratio):int(n / 2) +
                        math.ceil(50. / beam_ratio),
                        int(n / 2) - math.ceil(50. / beam_ratio):int(n / 2) +
                        math.ceil(50. / beam_ratio)],
                    overwrite=True)
            if (Norm_flux1 == True):
                #if ("Norm_flux1" in kwargs and kwargs["Norm_flux1"]):
                psf_noVortex_Mask_flux1norm = Offaxis_psf / sum(
                    sum(NoCoro_psf))
                fits.writeto(
                    path + prefix + '_psf_offaxis_flux1norm.fits',
                    psf_noVortex_Mask_flux1norm[
                        int(n / 2) - math.ceil(50. / beam_ratio):int(n / 2) +
                        math.ceil(50. / beam_ratio),
                        int(n / 2) - math.ceil(50. / beam_ratio):int(n / 2) +
                        math.ceil(50. / beam_ratio)],
                    overwrite=True)

    atm_screen = np.array(atm_screen)
    NCPA = np.array(NCPA)

    if (atm_screen.ndim == 3) or (TILT.ndim == 2) or (
            LS_misalignment.ndim == 2) or (apodizer_misalignment.ndim
                                           == 2) or (Island_Piston.ndim
                                                     == 2) or (NCPA.ndim == 3):
        print('Cube')

        if (atm_screen.ndim == 3):
            length_cube = atm_screen.shape[0]
        if (TILT.ndim == 2):
            length_cube = TILT.shape[0]
        if (LS_misalignment.ndim == 2):
            length_cube = LS_misalignment.shape[0]
        if (apodizer_misalignment.ndim == 2):
            length_cube = apodizer_misalignment.shape[0]
        if (Island_Piston.ndim == 2):
            length_cube = Island_Piston.shape[0]
        if (NCPA.ndim == 3):
            length_cube = NCPA.shape[0]

        psf_Coro = np.zeros((length_cube, n, n))

        for iter in range(0, length_cube):
            print('iter: ', iter)

            if ((isinstance(atm_screen, (list, tuple, np.ndarray)) == True)):
                if (atm_screen.ndim == 3):
                    atm_screen_iter = atm_screen[iter, :, :]
                else:
                    atm_screen_iter = atm_screen
            if (TILT.ndim == 2):
                TILT_iter = TILT[iter, :]
                print('TILT: ', TILT_iter)
            else:
                TILT_iter = TILT
            if (LS_misalignment.ndim == 2):
                LS_misalignment_iter = LS_misalignment[iter, :]
            else:
                LS_misalignment_iter = LS_misalignment
            if (apodizer_misalignment.ndim == 2):
                apodizer_misalignment_iter = apodizer_misalignment[iter, :]
            else:
                apodizer_misalignment_iter = apodizer_misalignment
            if (Island_Piston.ndim == 2):
                Island_Piston_iter = Island_Piston[iter, :]
            else:
                Island_Piston_iter = Island_Piston
            if (isinstance(NCPA, (list, tuple, np.ndarray)) == True):
                if (NCPA.ndim == 3):
                    NCPA_iter = NCPA[iter, :, :]
                else:
                    NCPA_iter = NCPA

            if (Vortex == True):
                ## Si Vortex Si Mask --> simulate the coronagraphic-apodized psf
                (wfo_Coro, sampling) = proper.prop_run(
                    'telescope',
                    lam,
                    n,
                    PASSVALUE={
                        'prefix': prefix,
                        'path': path,
                        'charge': charge,
                        'CAL': 0,
                        'diam': diam,
                        'spiders_width': spiders_width,
                        'spiders_angle': spiders_angle,
                        'beam_ratio': beam_ratio,
                        'f_lens': f_lens,
                        'npupil': npupil,
                        'r_obstr': r_obstr,
                        'pupil_file': pupil_file,
                        'phase_apodizer_file': phase_apodizer_file,
                        'amplitude_apodizer_file': amplitude_apodizer_file,
                        'TILT': TILT_iter,
                        'LS': LS,
                        'RAVC': RAVC,
                        'LS_phase_apodizer_file': LS_phase_apodizer_file,
                        'LS_amplitude_apodizer_file':
                        LS_amplitude_apodizer_file,
                        'LS_parameters': LS_parameters,
                        'atm_screen': atm_screen_iter,
                        'missing_segments_number': missing_segments_number,
                        'apodizer_misalignment': apodizer_misalignment_iter,
                        'LS_misalignment': LS_misalignment_iter,
                        'Island_Piston': Island_Piston_iter,
                        'NCPA': NCPA_iter,
                        'Debug_print': Debug_print,
                        'Debug': Debug
                    },
                    QUIET=True)
                psf_Coro[iter, :, :] = (abs(wfo_Coro))**2
            else:

                ## Apodizer --> simulate a coronagraphic psf with an apodizer (no Vortex)
                (wfo_apodizer, sampling) = proper.prop_run(
                    'telescope',
                    lam,
                    n,
                    PASSVALUE={
                        'prefix': prefix,
                        'path': path,
                        'charge': 0,
                        'CAL': 0,
                        'diam': diam,
                        'spiders_width': spiders_width,
                        'spiders_angle': spiders_angle,
                        'beam_ratio': beam_ratio,
                        'f_lens': f_lens,
                        'npupil': npupil,
                        'r_obstr': r_obstr,
                        'pupil_file': pupil_file,
                        'phase_apodizer_file': phase_apodizer_file,
                        'amplitude_apodizer_file': amplitude_apodizer_file,
                        'TILT': TILT_iter,
                        'LS': LS,
                        'RAVC': False,
                        'LS_phase_apodizer_file': LS_phase_apodizer_file,
                        'LS_amplitude_apodizer_file':
                        LS_amplitude_apodizer_file,
                        'LS_parameters': LS_parameters,
                        'atm_screen': atm_screen_iter,
                        'missing_segments_number': missing_segments_number,
                        'apodizer_misalignment': apodizer_misalignment_iter,
                        'LS_misalignment': LS_misalignment_iter,
                        'Island_Piston': Island_Piston_iter,
                        'NCPA': NCPA_iter,
                        'Debug_print': Debug_print,
                        'Debug': Debug
                    },
                    QUIET=True)
                psf_Coro[iter, :, :] = (abs(wfo_apodizer))**2

        fits.writeto(
            path + prefix + '_psf_cube_Coro_nonorm.fits',
            psf_Coro[:,
                     int(n / 2) - math.ceil(50. / beam_ratio):int(n / 2) +
                     math.ceil(50. / beam_ratio),
                     int(n / 2) - math.ceil(50. / beam_ratio):int(n / 2) +
                     math.ceil(50. / beam_ratio)],
            overwrite=True)
        if (Norm_max == True):
            if (Vortex == True):
                psf_Coro_maxnorm = psf_Coro / np.max(Offaxis_psf)
            else:
                psf_Coro_maxnorm = psf_Coro / np.max(NoCoro_psf)
        fits.writeto(path + prefix + '_psf_cube_Coro_maxnorm.fits',
                     psf_Coro_maxnorm[:,
                                      int(n / 2) -
                                      math.ceil(50. / beam_ratio):int(n / 2) +
                                      math.ceil(50. / beam_ratio),
                                      int(n / 2) -
                                      math.ceil(50. / beam_ratio):int(n / 2) +
                                      math.ceil(50. / beam_ratio)],
                     overwrite=True)
        if (Norm_flux1 == True):
            psf_Coro_flux1norm = psf_Coro / sum(sum(NoCoro_psf))
            fits.writeto(
                path + prefix + '_psf_cube_Coro_flux1norm.fits',
                psf_Coro_flux1norm[:,
                                   int(n / 2) -
                                   math.ceil(50. / beam_ratio):int(n / 2) +
                                   math.ceil(50. / beam_ratio),
                                   int(n / 2) -
                                   math.ceil(50. / beam_ratio):int(n / 2) +
                                   math.ceil(50. / beam_ratio)],
                overwrite=True)

    else:
        print('No Cube')
        if (Vortex == True):
            print('VC')
            print(
                'ATM: ',
                int(isinstance(atm_screen, (list, tuple, np.ndarray)) == True))
            print('atm screen: ', atm_screen.shape)
            ## Si Vortex Si Mask --> simulate the coronagraphic-apodized psf
            (wfo_Coro, sampling) = proper.prop_run(
                'telescope',
                lam,
                n,
                PASSVALUE={
                    'prefix': prefix,
                    'path': path,
                    'charge': charge,
                    'CAL': 0,
                    'diam': diam,
                    'spiders_width': spiders_width,
                    'spiders_angle': spiders_angle,
                    'beam_ratio': beam_ratio,
                    'f_lens': f_lens,
                    'npupil': npupil,
                    'r_obstr': r_obstr,
                    'pupil_file': pupil_file,
                    'phase_apodizer_file': phase_apodizer_file,
                    'amplitude_apodizer_file': amplitude_apodizer_file,
                    'TILT': TILT,
                    'LS': LS,
                    'RAVC': RAVC,
                    'LS_phase_apodizer_file': LS_phase_apodizer_file,
                    'LS_amplitude_apodizer_file': LS_amplitude_apodizer_file,
                    'LS_parameters': LS_parameters,
                    'atm_screen': atm_screen,
                    'missing_segments_number': missing_segments_number,
                    'apodizer_misalignment': apodizer_misalignment,
                    'LS_misalignment': LS_misalignment,
                    'Island_Piston': Island_Piston,
                    'NCPA': NCPA,
                    'Debug_print': Debug_print,
                    'Debug': Debug
                },
                QUIET=True)
            psf_Coro = (abs(wfo_Coro))**2

        else:
            print('Apodizer')
            print(
                'ATM: ',
                int(isinstance(atm_screen, (list, tuple, np.ndarray)) == True))
            print('atm screen: ', atm_screen.shape)
            ## Apodizer --> simulate a coronagraphic psf with an apodizer (no Vortex)
            (wfo_apodizer, sampling) = proper.prop_run(
                'telescope',
                lam,
                n,
                PASSVALUE={
                    'prefix': prefix,
                    'path': path,
                    'charge': 0,
                    'CAL': 0,
                    'diam': diam,
                    'spiders_width': spiders_width,
                    'spiders_angle': spiders_angle,
                    'beam_ratio': beam_ratio,
                    'f_lens': f_lens,
                    'npupil': npupil,
                    'r_obstr': r_obstr,
                    'pupil_file': pupil_file,
                    'phase_apodizer_file': phase_apodizer_file,
                    'amplitude_apodizer_file': amplitude_apodizer_file,
                    'TILT': TILT,
                    'LS': LS,
                    'RAVC': False,
                    'LS_phase_apodizer_file': LS_phase_apodizer_file,
                    'LS_amplitude_apodizer_file': LS_amplitude_apodizer_file,
                    'LS_parameters': LS_parameters,
                    'atm_screen': atm_screen,
                    'missing_segments_number': missing_segments_number,
                    'apodizer_misalignment': apodizer_misalignment,
                    'LS_misalignment': LS_misalignment,
                    'Island_Piston': Island_Piston,
                    'NCPA': NCPA,
                    'Debug_print': Debug_print,
                    'Debug': Debug
                },
                QUIET=True)
            psf_Coro = (abs(wfo_apodizer))**2

        fits.writeto(
            path + prefix + '_psf_Coro_nonorm.fits',
            psf_Coro[int(n / 2) - math.ceil(50. / beam_ratio):int(n / 2) +
                     math.ceil(50. / beam_ratio),
                     int(n / 2) - math.ceil(50. / beam_ratio):int(n / 2) +
                     math.ceil(50. / beam_ratio)],
            overwrite=True)
        if (Norm_max == True):
            if (Vortex == True):
                psf_Coro_maxnorm = psf_Coro / np.max(Offaxis_psf)
            else:
                psf_Coro_maxnorm = psf_Coro / np.max(NoCoro_psf)
            fits.writeto(
                path + prefix + '_psf_Coro_maxnorm.fits',
                psf_Coro_maxnorm[int(n / 2) -
                                 math.ceil(50. / beam_ratio):int(n / 2) +
                                 math.ceil(50. / beam_ratio),
                                 int(n / 2) -
                                 math.ceil(50. / beam_ratio):int(n / 2) +
                                 math.ceil(50. / beam_ratio)],
                overwrite=True)
        if (Norm_flux1 == True):
            psf_Coro_flux1norm = psf_Coro / sum(sum(NoCoro_psf))
            fits.writeto(
                path + prefix + '_psf_Coro_flux1norm.fits',
                psf_Coro_flux1norm[int(n / 2) -
                                   math.ceil(50. / beam_ratio):int(n / 2) +
                                   math.ceil(50. / beam_ratio),
                                   int(n / 2) -
                                   math.ceil(50. / beam_ratio):int(n / 2) +
                                   math.ceil(50. / beam_ratio)],
                overwrite=True)

    return