Example #1
0
def _luvoir_matrix_one_pair(design, norm, wfe_aber, zern_mode, resDir, savepsfs, saveopds, segment_pair):
    """
    Function to calculate LVUOIR-A mean contrast of one aberrated segment pair; for num_matrix_luvoir_multiprocess().
    :param design: str, what coronagraph design to use - 'small', 'medium' or 'large'
    :param norm: float, direct PSF normalization factor (peak pixel of direct PSF)
    :param wfe_aber: float, calibration aberration per segment in m
    :param zern_mode: Zernike mode object, local Zernike aberration
    :param resDir: str, directory for matrix calculations
    :param savepsfs: bool, if True, all PSFs will be saved to disk individually, as fits files
    :param saveopds: bool, if True, all pupil surface maps of aberrated segment pairs will be saved to disk as PDF
    :param segment_pair: tuple, pair of segments to aberrate, 0-indexed. If same segment gets passed in both tuple
                         entries, the segment will be aberrated only once.
                         Note how LUVOIR segments start numbering at 1, with 0 being the center segment that doesn't exist.
    :return: contrast as float, and segment pair as tuple
    """

    # Instantiate LUVOIR object
    sampling = CONFIG_PASTIS.getfloat('LUVOIR', 'sampling')
    optics_input = CONFIG_PASTIS.get('LUVOIR', 'optics_path')
    luv = LuvoirAPLC(optics_input, design, sampling)

    log.info(f'PAIR: {segment_pair[0]+1}-{segment_pair[1]+1}')

    # Put aberration on correct segments. If i=j, apply only once!
    luv.flatten()
    luv.set_segment(segment_pair[0]+1, wfe_aber / 2, 0, 0)
    if segment_pair[0] != segment_pair[1]:
        luv.set_segment(segment_pair[1]+1, wfe_aber / 2, 0, 0)

    log.info('Calculating coro image...')
    image, inter = luv.calc_psf(ref=False, display_intermediate=False, return_intermediate='intensity')
    # Normalize PSF by reference image
    psf = image / norm

    # Save PSF image to disk
    if savepsfs:
        filename_psf = f'psf_{zern_mode.name}_{zern_mode.convention + str(zern_mode.index)}_segs_{segment_pair[0]+1}-{segment_pair[1]+1}'
        hcipy.write_fits(psf, os.path.join(resDir, 'psfs', filename_psf + '.fits'))

    # Plot segmented mirror WFE and save to disk
    if saveopds:
        opd_name = f'opd_{zern_mode.name}_{zern_mode.convention + str(zern_mode.index)}_segs_{segment_pair[0]+1}-{segment_pair[1]+1}'
        plt.clf()
        hcipy.imshow_field(inter['seg_mirror'], grid=luv.aperture.grid, mask=luv.aperture, cmap='RdBu')
        plt.savefig(os.path.join(resDir, 'OTE_images', opd_name + '.pdf'))

    log.info('Calculating mean contrast in dark hole')
    dh_intensity = psf * luv.dh_mask
    contrast = np.mean(dh_intensity[np.where(luv.dh_mask != 0)])
    log.info(f'contrast: {float(contrast)}')    # contrast is a Field, here casting to normal float

    return float(contrast), segment_pair
Example #2
0
def plot_single_mode(mode_nr,
                     pastis_modes,
                     out_dir,
                     design,
                     figsize=(8.5, 8.5),
                     vmin=None,
                     vmax=None,
                     fname_suffix='',
                     save=False):
    """
    Plot a single PASTIS mode.
    :param mode_nr: int, mode index
    :param pastis_modes: array, PASTIS modes [seg, mode] in nm
    :param out_dir: str, output path to save the figure to if save=True
    :param design: str, "small", "medium", or "large" LUVOIR-A APLC design
    :param figsize: tuple, size of figure, default=(8.5,8.5)
    :param vmin: matplotlib min extent of image, default is None
    :param vmax: matplotlib max extent of image, default is None
    :param fname_suffix: str, optional, suffix to add to the saved file name
    :param save: bool, whether to save to disk or not, default is False
    :return:
    """
    fname = f'mode_{mode_nr}'
    if fname_suffix != '':
        fname += f'_{fname_suffix}'

    # Create luvoir instance
    sampling = CONFIG_PASTIS.getfloat('LUVOIR', 'sampling')
    optics_input = CONFIG_PASTIS.get('LUVOIR', 'optics_path')
    luvoir = LuvoirAPLC(optics_input, design, sampling)

    plt.figure(figsize=figsize, constrained_layout=False)
    one_mode = apply_mode_to_luvoir(pastis_modes[:, mode_nr - 1], luvoir)[0]
    hcipy.imshow_field(one_mode.phase, cmap='RdBu', vmin=vmin, vmax=vmax)
    plt.axis('off')
    plt.annotate(f'{mode_nr}',
                 xy=(-7.1, -6.9),
                 fontweight='roman',
                 fontsize=43)
    cbar = plt.colorbar(
        fraction=0.046, pad=0.04
    )  # no clue what these numbers mean but it did the job of adjusting the colorbar size to the actual plot size
    cbar.ax.tick_params(
        labelsize=40)  # this changes the numbers on the colorbar
    plt.tight_layout()

    if save:
        plt.savefig(os.path.join(out_dir, '.'.join([fname, 'pdf'])))
Example #3
0
def plot_all_modes(pastis_modes, out_dir, design, fname_suffix='', save=False):
    """
    Plot all PATIS modes onto a grid.
    :param pastis_modes: array, PASTIS modes [seg, mode] in nm
    :param out_dir: str, output path to save the figure to if save=True
    :param design: str, "small", "medium", or "large" LUVOIR-A APLC design
    :param fname_suffix: str, optional, suffix to add to the saved file name
    :param save: bool, whether to save to disk or not, default is False
    :return:
    """
    fname = f'all_modes'
    if fname_suffix != '':
        fname += f'_{fname_suffix}'

    # Calculate phases of all modes
    all_modes = calculate_mode_phases(pastis_modes, design)

    # Plot them
    fig, axs = plt.subplots(12, 10, figsize=(20, 24))
    for i, ax in enumerate(axs.flat):
        im = hcipy.imshow_field(all_modes[i],
                                cmap='RdBu',
                                ax=ax,
                                vmin=-0.0045,
                                vmax=0.0045)
        ax.axis('off')
        ax.annotate(f'{i + 1}',
                    xy=(-6.8, -6.8),
                    fontweight='roman',
                    fontsize=13)
    fig.tight_layout()

    if save:
        plt.savefig(os.path.join(out_dir, '.'.join([fname, 'pdf'])))
def run_loyt():
    from hcipy import make_pupil_grid, make_focal_grid, FraunhoferPropagator, circular_aperture, evaluate_supersampled, imshow_field, imsave_field, Field, LyotCoronagraph, Wavefront
    import numpy as np
    import matplotlib.pyplot as plt

    pupil_grid = make_pupil_grid(256)
    focal_grid = make_focal_grid(pupil_grid, 8, 32)
    prop = FraunhoferPropagator(pupil_grid, focal_grid)

    aperture = circular_aperture(1)
    aperture = evaluate_supersampled(aperture, pupil_grid, 8)

    mask = 1 - circular_aperture(3)(focal_grid)
    stop = circular_aperture(0.7)(pupil_grid)
    coro = LyotCoronagraph(pupil_grid, mask, stop)

    wf = Wavefront(aperture)
    lyot = coro(wf)

    img = prop(lyot)
    img_ref = prop(wf)

    output_path = get_output_path("miscellaneous")

    fig = plt.figure()
    imshow_field(np.log10(img.power / img_ref.power.max()), vmin=-6, vmax=0)
    plt.xlim(-25, 25)
    plt.ylim(-25, 25)
    cbar = plt.colorbar()
    cbar.set_label(r"$^{10}\log(contrast)$")
    plt.ylabel(r"$\lambda/D$")
    plt.xlabel(r"$\lambda/D$")
    fig.savefig(output_path + "lyot_psf")

    fig = plt.figure()
    imshow_field(np.log10(img_ref.power / img_ref.power.max()),
                 vmin=-6,
                 vmax=0)
    plt.xlim(-25, 25)
    plt.ylim(-25, 25)
    cbar = plt.colorbar()
    cbar.set_label(r"$^{10}\log(contrast)$")
    plt.ylabel(r"$\lambda/D$")
    plt.xlabel(r"$\lambda/D$")
    fig.savefig(output_path + "normal_psf")
def run_loyt():
    from hcipy import make_pupil_grid, make_focal_grid, FraunhoferPropagator, circular_aperture, evaluate_supersampled, imshow_field, imsave_field, Field, LyotCoronagraph, Wavefront
    import numpy as np
    import matplotlib.pyplot as plt

    pupil_grid = make_pupil_grid(256)
    focal_grid = make_focal_grid(pupil_grid, 8, 32)
    prop = FraunhoferPropagator(pupil_grid, focal_grid)

    aperture = circular_aperture(1)
    aperture = evaluate_supersampled(aperture, pupil_grid, 8)

    mask = 1 - circular_aperture(3)(focal_grid)
    stop = circular_aperture(0.7)(pupil_grid)
    coro = LyotCoronagraph(pupil_grid, mask, stop)

    wf = Wavefront(aperture)
    lyot = coro(wf)

    img = prop(lyot)
    img_ref = prop(wf)

    output_path = get_output_path("miscellaneous")

    fig = plt.figure()
    imshow_field(np.log10(img.power / img_ref.power.max()), vmin=-6, vmax=0)
    plt.xlim(-25,25)
    plt.ylim(-25,25)
    cbar = plt.colorbar()
    cbar.set_label(r"$^{10}\log(contrast)$")
    plt.ylabel(r"$\lambda/D$")
    plt.xlabel(r"$\lambda/D$")
    fig.savefig(output_path+"lyot_psf")

    fig = plt.figure()
    imshow_field(np.log10(img_ref.power / img_ref.power.max()), vmin=-6, vmax=0)
    plt.xlim(-25,25)
    plt.ylim(-25,25)
    cbar = plt.colorbar()
    cbar.set_label(r"$^{10}\log(contrast)$")
    plt.ylabel(r"$\lambda/D$")
    plt.xlabel(r"$\lambda/D$")
    fig.savefig(output_path+"normal_psf")
Example #6
0
def score_matrix3(aberrations, show=False):
    
    # Make segmented mirror
    aper, segments = hcipy.make_hexagonal_segmented_aperture(num_rings,
                                                         segment_flat_to_flat,
                                                         gap_size,
                                                         starting_ring=1,
                                                         return_segments=True)

    aper = hcipy.evaluate_supersampled(aper, pupil_grid, 1)
    segments = hcipy.evaluate_supersampled(segments, pupil_grid, 1)
    
    # Instantiate the segmented mirror
    hsm = hcipy.SegmentedDeformableMirror(segments)

    # Make a pupil plane wavefront from aperture
    wf = hcipy.Wavefront(aper, wavelength)
    
    hsm.flatten()
    
    # Get poke segments
    for i in range(0,len(aberrations)):
        if float(aberrations[i]) != 0:
            hsm.set_segment_actuators(i, aber_to_opd(aber_rad, wavelength) / (1/float(aberrations[i])), 0, 0)
    
    if show:
        plt.figure(figsize=(8,8))
        plt.title('OPD for HCIPy SM')
        hcipy.imshow_field(hsm.surface * 2, mask=aper, cmap='RdBu_r', vmin=-5e-7, vmax=5e-7)
        plt.colorbar()
        plt.show()
    
    ### PROPAGATE AND SCORE ###
    wf_fp_pistoned = hsm(wf)

    # Propagate from SM to image plane
    im_pistoned_hc = prop(wf_fp_pistoned)
    norm_hc = np.max(im_pistoned_hc.intensity)
    
    if show:
        # Display intensity in image plane

        hcipy.imshow_field(np.log10(im_pistoned_hc.intensity / norm_hc), cmap='inferno', vmin=-9)
        plt.title('Image plane after SM')
        plt.colorbar()
        plt.show()
        
        hcipy.imshow_field(np.log10((im_pistoned_hc.intensity / norm_hc)*(annulus)), cmap='inferno', vmin=-9)
        plt.title('Annular image plane region')
        plt.colorbar()
        plt.show()
        
    interested_field = (im_pistoned_hc.intensity / norm_hc)*(1-annulus)
    score = float(hcipy.Field.sum(interested_field)/hcipy.Field.sum(im_pistoned_hc.intensity / norm_hc))*100
    
    return score
Example #7
0
def full_modes_from_themselves(pmodes, datadir, sm, wf_aper, saving=False):
    """
    Put all modes onto the pupuil SM and get full 2D modes.

    Take the pmodes array of all modes (shape [segnum, modenum] = [nseg, nseg]) and apply them onto a segmenter mirror
    in the pupil. This phase gets returned both as an array of hcipy.Fields, as well as a standard array of 2D arrays.
    Optionally, save a PDF displaying all modes, a fits cube and individual PDF images.
    :param pmodes: array of PASTIS modes [segnum, modenum]
    :param datadir: string, path to overall data directory containing matrix and results folder
    :param saving: bool, whether to save figure to disk or not
    :return: all_modes as array of Fields, mode_cube as array of 2D arrays (hcipy vs matplotlib)
    """

    nseg = 120

    ### Put all modes on the SM and get their phase
    all_modes = []
    for thismode in range(nseg):
        print('Working on mode {}/{}.'.format(thismode + 1, nseg))

        wf_sm = apply_mode_to_sm(pmodes[:, thismode], sm, wf_aper)
        all_modes.append(wf_sm.phase / wf_sm.wavenumber
                         )  # wf.phase is in rad, so this converts it to meters

    ### Check for results directory structure and create if it doesn't exist
    if saving:
        subdirs = [
            os.path.join(datadir, 'results'),
            os.path.join(datadir, 'results', 'modes'),
            os.path.join(datadir, 'results', 'modes', 'fits'),
            os.path.join(datadir, 'results', 'modes', 'pdf')
        ]
        for place in subdirs:
            if not os.path.isdir(place):
                os.mkdir(place)

    ### Plot all modes together and save
    if saving:
        print('Saving all PASTIS modes...')
        plt.figure(figsize=(36, 30))
        for thismode in range(nseg):
            plt.subplot(12, 10, thismode + 1)
            hc.imshow_field(all_modes[thismode], cmap='RdBu')
            plt.axis('off')
            plt.title('Mode ' + str(thismode + 1))
        plt.savefig(
            os.path.join(datadir, 'results', 'modes', 'modes_piston.pdf'))

    ### Plot them individually and save as fits and pdf
    mode_cube = []  # to save as a fits cube
    for thismode in range(nseg):

        # pdf
        plt.clf()
        hc.imshow_field(all_modes[thismode], cmap='RdBu')
        plt.axis('off')
        plt.title('Mode ' + str(thismode + 1), size=30)
        if saving:
            plt.savefig(
                os.path.join(datadir, 'results', 'modes', 'pdf',
                             'mode' + str(thismode + 1) + '.pdf'))

        # for the fits cube
        mode_cube.append(all_modes[thismode].shaped)

    # fits cube
    mode_cube = np.array(mode_cube)
    if saving:
        hc.write_fits(
            mode_cube,
            os.path.join(datadir, 'results', 'modes', 'fits',
                         'cube_modes.fits'))

    return all_modes, mode_cube
Example #8
0
    ### Calculate segment-based static constraints
    if calculate_mus:
        print('Calculating static segment-based constraints')
        mus = np.zeros_like(sigmas)
        for segnum in range(nseg):
            mus[segnum] = calculate_segment_constraints(pmodes, sigmas, segnum)

        np.savetxt(
            os.path.join(workdir, 'results',
                         'mus_' + str(c_stat) + '_test.txt'), mus)

        # Put mus on SM and plot
        wf_constraints = apply_mode_to_sm(mus, sm, wf_aper)

        plt.figure()
        hc.imshow_field(wf_constraints.phase / wf_constraints.wavenumber,
                        cmap='Blues')  # in meters
        plt.title('Static segment constraints $\mu_p$ for C = ' + str(c_stat),
                  size=20)
        plt.colorbar()
        plt.savefig(
            os.path.join(workdir, 'results',
                         'static_constraints_' + str(c_stat) + '_test.pdf'))

    else:
        print('Reading mus from {}'.format(workdir))
        mus = np.loadtxt(
            os.path.join(workdir, 'results',
                         'mus_' + str(c_stat) + '_test.txt'))

    ### Calculate Monte Carlo confirmation with E2E
    if run_monte_carlo:
def clean_vapp():
    import numpy as np
    import matplotlib.pyplot as plt 

    from hcipy import read_fits, make_pupil_grid, make_focal_grid, FraunhoferPropagator, circular_aperture, evaluate_supersampled, imshow_field, imsave_field, Field, LyotCoronagraph, Wavefront

    script_path = os.path.realpath(__file__).split("vApp_reduction",1)[0]
    full_path = script_path+"vApp_reduction/data/"
    amplitude_file = full_path+'SCExAO_vAPP_amplitude_resampled.fits'
    phase_file     = full_path+'SCExAO_vAPP_phase_resampled.fits'

    # loading the files required for generating the vAPP. 
    amplitude_temp = read_fits(amplitude_file)
    phase_temp     = read_fits(phase_file)

    # number of pixels along one axis in the pupil
    Npix = amplitude_temp.shape[0]

    # generating the grids 
    pupil_grid = make_pupil_grid(Npix)
    focal_grid = make_focal_grid(pupil_grid, 4, 25)

    # Mapping from pupil plane to focal plane
    propagator = FraunhoferPropagator(pupil_grid, focal_grid)

    # converting the amplitude and phase to fields 
    amplitude = Field(amplitude_temp.ravel(), pupil_grid)
    phase     = Field(phase_temp.ravel(), pupil_grid)

    # the wavefront for the three PSFs 
    pupil_wf_PSF_1 = Wavefront(amplitude * np.exp(1j * phase)) # coronagraphic PSF 1
    pupil_wf_PSF_2 = Wavefront(amplitude * np.exp(-1j * phase)) # coronagraphic PSF 2
    pupil_wf_PSF_3 = Wavefront(amplitude) # leakage

    # Propagating them to the focal plane 
    focal_wf_PSF_1 = propagator(pupil_wf_PSF_1)
    focal_wf_PSF_2 = propagator(pupil_wf_PSF_2)
    focal_wf_PSF_3 = propagator(pupil_wf_PSF_3)

    # setting the total power in the images 
    focal_wf_PSF_1.total_power = 1
    focal_wf_PSF_2.total_power = 1
    focal_wf_PSF_3.total_power = 1

    # the strenght of the leakage term
    leakage = 0.02

    # getting the power and scaling with leakage 
    PSF_1_pwr = focal_wf_PSF_1.power * (1 - leakage / 2)
    PSF_2_pwr = focal_wf_PSF_2.power * (1 - leakage / 2)
    PSF_3_pwr = focal_wf_PSF_3.power * leakage

    # generating the total PSF of the vAPP
    total_PSF = PSF_1_pwr + PSF_2_pwr + PSF_3_pwr

    # normalizing to sum = 1
    total_PSF /= np.sum(total_PSF)

    fig = plt.figure()
    imshow_field(np.log10(total_PSF / total_PSF.max()), vmin=-5, vmax=0)
    cbar = plt.colorbar()
    cbar.set_label(r"$^{10}\log(contrast)$")
    plt.ylabel(r"$\lambda/D$")
    plt.xlabel(r"$\lambda/D$")

    plt.show()
    output_path = get_output_path("miscellaneous")
    fig.savefig(output_path+"clean_vapp")
Example #10
0
def gen_atmos(plot=False):
    """
    generates atmospheric phase distortions using hcipy (updated from original using CAOS)

    read more on HCIpy here: https://hcipy.readthedocs.io/en/latest/index.html
    In hcipy, the atmosphere evolves as a function of time, specified by the user. User can thus specify the
    timescale of evolution through both velocity of layer and time per step in the obs_sequence, in loop for
    medis_main.gen_timeseries().

    :param plot: turn plotting on or off
    :return:
    """
    dprint("Making New Atmosphere Model")
    # Saving Parameters
    # np.savetxt(iop.atmosconfig, ['Grid Size', 'Wvl Range', 'Number of Frames', 'Layer Strength', 'Outer Scale', 'Velocity', 'Scale Height', cp.model])
    # np.savetxt(iop.atmosconfig, ['ap.grid_size', 'ap.wvl_range', 'ap.numframes', 'atmp.cn_sq', 'atmp.L0', 'atmp.vel', 'atmp.h', 'cp.model'])
    # np.savetxt(iop.atmosconfig, [ap.grid_size, ap.wvl_range, ap.numframes, atmp.cn_sq, atmp.L0, atmp.vel, atmp.h, cp.model], fmt='%s')

    wsamples = np.linspace(ap.wvl_range[0], ap.wvl_range[1], ap.n_wvl_init)
    wavefronts = []

    ##################################
    # Initiate HCIpy Atmosphere Type
    ##################################
    pupil_grid = hcipy.make_pupil_grid(sp.grid_size, tp.entrance_d)
    if atmp.model == 'single':
        layers = [
            hcipy.InfiniteAtmosphericLayer(pupil_grid, atmp.cn_sq, atmp.L0,
                                           atmp.vel, atmp.h, 2)
        ]
    elif atmp.model == 'hcipy_standard':
        # Make multi-layer atmosphere
        layers = hcipy.make_standard_atmospheric_layers(
            pupil_grid, atmp.outer_scale)
    elif atmp.model == 'evolving':
        raise NotImplementedError
    atmos = hcipy.MultiLayerAtmosphere(layers, scintilation=False)

    for wavelength in wsamples:
        wavefronts.append(
            hcipy.Wavefront(hcipy.Field(np.ones(pupil_grid.size), pupil_grid),
                            wavelength))

    ###########################################
    # Evolving Wavefront using HCIpy tools
    ###########################################
    for it, t in enumerate(
            np.arange(0, sp.numframes * sp.sample_time, sp.sample_time)):
        atmos.evolve_until(t)
        for iw, wf in enumerate(wavefronts):
            wf2 = atmos.forward(wf)

            filename = get_filename(it, wsamples[iw])
            dprint(f"atmos file = {filename}")
            hdu = fits.ImageHDU(wf2.phase.reshape(sp.grid_size, sp.grid_size))
            hdu.header['PIXSIZE'] = tp.entrance_d / sp.grid_size
            hdu.writeto(filename, overwrite=True)

            if plot and iw == 0:
                import matplotlib.pyplot as plt
                from medis.twilight_colormaps import sunlight
                plt.figure()
                plt.title(
                    f"Atmosphere Phase Map t={t} lambda={eformat(wsamples[iw], 3, 2)}"
                )
                hcipy.imshow_field(wf2.phase, cmap=sunlight)
                plt.colorbar()
                plt.show(block=True)
Example #11
0
def get_atlast_aperture(normalized=False,
                        with_segment_gaps=True,
                        segment_transmissions=1,
                        write_to_disk=False,
                        outDir=None):
    """Make the ATLAST/HiCAT pupil mask.

    This function is a copy of make_hicat_aperture(), except that it also returns the segment positions.

    Parameters
    ----------
    normalized : boolean
        If this is True, the outer diameter will be scaled to 1. Otherwise, the
        diameter of the pupil will be 15.0 meters.
    with_segment_gaps : boolean
        Include the gaps between individual segments in the aperture.
    segment_transmissions : scalar or array_like
        The transmission for each of the segments. If this is a scalar, this transmission will
        be used for all segments.

    Returns
    -------
    Field generator
        The ATLAST aperture.
    CartesianGrid
        The segment positions.
    """
    pupil_diameter = PUP_DIAMETER
    segment_circum_diameter = 2 / np.sqrt(3) * pupil_diameter / 7
    num_rings = 3
    segment_gap = CONFIG_PASTIS.getfloat(which_tel, 'gaps')

    if not with_segment_gaps:
        segment_gap = 0

    if normalized:
        segment_circum_diameter /= pupil_diameter
        segment_gap /= pupil_diameter
        pupil_diameter = 1.0

    segment_positions = hcipy.make_hexagonal_grid(
        segment_circum_diameter / 2 * np.sqrt(3), num_rings)
    segment_positions = segment_positions.subset(lambda grid: ~(
        hcipy.circular_aperture(segment_circum_diameter)(grid) > 0))

    hexagon = hcipy.hexagonal_aperture(segment_circum_diameter - segment_gap)

    def segment(grid):
        return hexagon(grid.rotated(np.pi / 2))

    segmented_aperture = hcipy.make_segmented_aperture(segment,
                                                       segment_positions,
                                                       segment_transmissions)

    def func(grid):
        res = segmented_aperture(grid)

        return hcipy.Field(res, grid)

    # Save pupil to disk, as pdf and fits
    if write_to_disk:
        pupil_grid = hcipy.make_pupil_grid(dims=pupil_size,
                                           diameter=pupil_diameter)
        atlast = hcipy.evaluate_supersampled(func, pupil_grid, 8)

        hcipy.imshow_field(atlast)
        for i in range(36):
            plt.annotate(str(i + 1),
                         size='x-large',
                         xy=(segment_positions.x[i] - pupil_diameter * 0.03,
                             segment_positions.y[i] - pupil_diameter * 0.02))
            # -0.03/-0.02 is for shifting the numbers closer to the segment centers. Scaling that by pupil_diameter
            # keeps them in place.
        plt.savefig(os.path.join(outDir, 'ATLAST_pupil.pdf'))

        util.write_fits(atlast.shaped, os.path.join(outDir, 'pupil.fits'))

    return func, segment_positions
Example #12
0
def gen_atmos(plot=False, debug=True):
    """
    generates atmospheric phase distortions using hcipy (updated from original using CAOS)

    read more on HCIpy here: https://hcipy.readthedocs.io/en/latest/index.html
    In hcipy, the atmosphere evolves as a function of time, specified by the user. User can thus specify the
    timescale of evolution through both velocity of layer and time per step in the obs_sequence, in loop for
    medis_main.gen_timeseries().

    :param plot: turn plotting on or off
    :return:

    todo add simple mp.Pool.map code to make maps in parrallel
    """
    if tp.use_atmos is False:
        pass  # only make new atmosphere map if using the atmosphere
    else:

        if sp.verbose: dprint("Making New Atmosphere Model")
        # Saving Parameters
        # np.savetxt(iop.atmosconfig, ['Grid Size', 'Wvl Range', 'Number of Frames', 'Layer Strength', 'Outer Scale', 'Velocity', 'Scale Height', cp.model])
        # np.savetxt(iop.atmosconfig, ['ap.grid_size', 'ap.wvl_range', 'ap.numframes', 'atmp.cn_sq', 'atmp.L0', 'atmp.vel', 'atmp.h', 'cp.model'])
        # np.savetxt(iop.atmosconfig, [ap.grid_size, ap.wvl_range, ap.numframes, atmp.cn_sq, atmp.L0, atmp.vel, atmp.h, cp.model], fmt='%s')

        wsamples = np.linspace(ap.wvl_range[0], ap.wvl_range[1], ap.n_wvl_init)
        wavefronts = []

        ##################################
        # Initiate HCIpy Atmosphere Type
        ##################################
        pupil_grid = hcipy.make_pupil_grid(sp.grid_size, tp.entrance_d)
        if atmp.model == 'single':
            layers = [
                hcipy.InfiniteAtmosphericLayer(pupil_grid, atmp.cn_sq, atmp.L0,
                                               atmp.vel, atmp.h, 2)
            ]
        elif atmp.model == 'hcipy_standard':
            # Make multi-layer atmosphere
            # layers = hcipy.make_standard_atmospheric_layers(pupil_grid, atmp.L0)
            heights = np.array([500, 1000, 2000, 4000, 8000, 16000])
            velocities = np.array([10, 10, 10, 10, 10, 10])
            Cn_squared = np.array(
                [0.2283, 0.0883, 0.0666, 0.1458, 0.3350, 0.1350]) * 3.5e-12

            layers = []
            for h, v, cn in zip(heights, velocities, Cn_squared):
                layers.append(
                    hcipy.InfiniteAtmosphericLayer(pupil_grid, cn, atmp.L0, v,
                                                   h, 2))

        elif atmp.model == 'evolving':
            raise NotImplementedError
        atmos = hcipy.MultiLayerAtmosphere(layers, scintilation=False)

        for wavelength in wsamples:
            wavefronts.append(
                hcipy.Wavefront(
                    hcipy.Field(np.ones(pupil_grid.size), pupil_grid),
                    wavelength))

        if atmp.correlated_sampling:
            # Damage Detection and Localization from Dense Network of Strain Sensors

            # fancy sampling goes here
            normal = corrsequence(sp.numframes,
                                  atmp.tau / sp.sample_time)[1] * atmp.std
            uniform = (special.erf(normal / np.sqrt(2)) + 1)

            times = np.cumsum(uniform) * sp.sample_time

            if debug:
                import matplotlib.pylab as plt
                plt.plot(normal)
                plt.figure()
                plt.plot(uniform)
                plt.figure()
                plt.hist(uniform)
                plt.figure()
                plt.plot(
                    np.arange(0, sp.numframes * sp.sample_time,
                              sp.sample_time))
                plt.plot(times)
                plt.show()
        else:
            times = np.arange(0, sp.numframes * sp.sample_time, sp.sample_time)

        ###########################################
        # Evolving Wavefront using HCIpy tools
        ###########################################
        for it, t in enumerate(times):
            atmos.evolve_until(t)
            for iw, wf in enumerate(wavefronts):
                wf2 = atmos.forward(wf)

                filename = get_filename(
                    it, wsamples[iw],
                    (iop.atmosdir, sp.sample_time, atmp.model))
                if sp.verbose: dprint(f"atmos file = {filename}")
                hdu = fits.ImageHDU(
                    wf2.phase.reshape(sp.grid_size, sp.grid_size))
                hdu.header['PIXSIZE'] = tp.entrance_d / sp.grid_size
                hdu.writeto(filename, overwrite=True)

                if plot and iw == 0:
                    import matplotlib.pyplot as plt
                    from medis.twilight_colormaps import sunlight
                    plt.figure()
                    plt.title(
                        f"Atmosphere Phase Map t={t} lambda={eformat(wsamples[iw], 3, 2)}"
                    )
                    hcipy.imshow_field(wf2.phase, cmap=sunlight)
                    plt.colorbar()
                    plt.show(block=True)
Example #13
0
    def calc_psf(self,
                 ref=False,
                 display_intermediate=False,
                 return_intermediate=None):
        """Calculate the PSF of the segmented telescope, normalized to contrast units.

        Parameters:
        ----------
        ref : bool
            Keyword for additionally returning the refrence PSF without the FPM.
        display_intermediate : bool
            Keyword for display of all planes.
        return_intermediate : string
            Either 'intensity', return the intensity in all planes; except phase on the SM (first plane)
            or 'efield', return the E-fields in all planes. Default none.
        Returns:
        --------
        wf_im_coro.intensity : Field
            Coronagraphic image, normalized to contrast units by max of reference image (even when ref
            not returned).
        wf_im_ref.intensity : Field, optional
            Reference image without FPM.
        intermediates : dict of Fields, optional
            Intermediate plane intensity images; except for full wavefront on segmented mirror.
        wf_im_coro : Wavefront
            Wavefront in last focal plane.
        wf_im_ref : Wavefront, optional
            Wavefront of reference image without FPM.
        intermediates : dict of Wavefronts, optional
            Intermediate plane E-fields; except intensity in focal plane after FPM.
        """

        # Create fake FPM for plotting
        fpm_plot = 1 - hc.circular_aperture(2 * self.fpm_rad * self.lamDrad)(
            self.focal_det)

        # Create apodozer as hc.Apodizer() object to be able to propagate through it
        apod_prop = hc.Apodizer(self.apodizer)

        # Calculate all wavefronts of the full propagation
        wf_sm = self.sm(self.wf_aper)
        wf_apod = apod_prop(wf_sm)
        wf_lyot = self.coro(wf_apod)
        wf_im_coro = self.prop(wf_lyot)

        # Wavefronts in extra planes
        wf_before_fpm = self.prop(wf_apod)
        int_after_fpm = np.log10(
            wf_before_fpm.intensity / wf_before_fpm.intensity.max()
        ) * fpm_plot  # this is the intensity straight
        wf_before_lyot = self.coro_no_ls(wf_apod)

        # Wavefronts of the reference propagation
        wf_ref_pup = hc.Wavefront(self.apodizer * self.lyotstop,
                                  wavelength=self.wvln)
        wf_im_ref = self.prop(wf_ref_pup)

        # Display intermediate planes
        if display_intermediate:

            plt.figure(figsize=(15, 15))

            plt.subplot(331)
            hc.imshow_field(wf_sm.phase, mask=self.aper, cmap='RdBu')
            plt.title('Seg aperture phase')

            plt.subplot(332)
            hc.imshow_field(wf_apod.intensity, cmap='inferno')
            plt.title('Apodizer')

            plt.subplot(333)
            hc.imshow_field(wf_before_fpm.intensity /
                            wf_before_fpm.intensity.max(),
                            norm=LogNorm(),
                            cmap='inferno')
            plt.title('Before FPM')

            plt.subplot(334)
            hc.imshow_field(int_after_fpm / wf_before_fpm.intensity.max(),
                            cmap='inferno')
            plt.title('After FPM')

            plt.subplot(335)
            hc.imshow_field(wf_before_lyot.intensity /
                            wf_before_lyot.intensity.max(),
                            norm=LogNorm(vmin=1e-3, vmax=1),
                            cmap='inferno')
            plt.title('Before Lyot stop')

            plt.subplot(336)
            hc.imshow_field(wf_lyot.intensity / wf_lyot.intensity.max(),
                            norm=LogNorm(vmin=1e-3, vmax=1),
                            cmap='inferno',
                            mask=self.lyotstop)
            plt.title('After Lyot stop')

            plt.subplot(337)
            hc.imshow_field(wf_im_coro.intensity / wf_im_ref.intensity.max(),
                            norm=LogNorm(vmin=1e-10, vmax=1e-3),
                            cmap='inferno')
            plt.title('Final image')
            plt.colorbar()

        if return_intermediate == 'intensity':

            # Return the intensity in all planes; except phase on the SM (first plane)
            intermediates = {
                'seg_mirror':
                wf_sm.phase,
                'apod':
                wf_apod.intensity,
                'before_fpm':
                wf_before_fpm.intensity / wf_before_fpm.intensity.max(),
                'after_fpm':
                int_after_fpm / wf_before_fpm.intensity.max(),
                'before_lyot':
                wf_before_lyot.intensity / wf_before_lyot.intensity.max(),
                'after_lyot':
                wf_lyot.intensity / wf_lyot.intensity.max()
            }

            if ref:
                return wf_im_coro.intensity, wf_im_ref.intensity, intermediates
            else:
                return wf_im_coro.intensity, intermediates

        if return_intermediate == 'efield':

            # Return the E-fields in all planes; except intensity in focal plane after FPM
            intermediates = {
                'seg_mirror': wf_sm,
                'apod': wf_apod,
                'before_fpm': wf_before_fpm,
                'after_fpm': int_after_fpm,
                'before_lyot': wf_before_lyot,
                'after_lyot': wf_lyot
            }

            if ref:
                return wf_im_coro, wf_im_ref, intermediates
            else:
                return wf_im_coro, intermediates

        if ref:
            return wf_im_coro.intensity, wf_im_ref.intensity

        return wf_im_coro.intensity
Example #14
0
def num_matrix_luvoir(design, savepsfs=False, saveopds=True):
    """
    Generate a numerical PASTIS matrix for a LUVOIR A coronagraph.
    -- Depracated function, the LUVOIR PASTIS matrix is better calculated with num_matrix_multiprocess(), which can
    do this for your choice of one of the implemented instruments (LUVOIR, HiCAT, JWST). --

    All inputs are read from the (local) configfile and saved to the specified output directory.
    The LUVOIR STDT delivery in May 2018 included three different apodizers
    we can work with, you pick which of the three you want with the 'design' parameter.
    :param design: string, what coronagraph design to use - 'small', 'medium' or 'large'
    :param savepsfs: bool, if True, all PSFs will be saved to disk individually, as fits files, additionally to the
                     total PSF cube. If False, the total cube will still get saved at the very end of the script.
    :param saveopds: bool, if True, all pupil surface maps of aberrated segment pairs will be saved to disk as PDF
    :return overall_dir: string, experiment directory
    """

    # Keep track of time
    start_time = time.time()

    ### Parameters

    # System parameters
    overall_dir = util.create_data_path(CONFIG_PASTIS.get('local', 'local_data_path'), telescope='luvoir-'+design)
    os.makedirs(overall_dir, exist_ok=True)
    resDir = os.path.join(overall_dir, 'matrix_numerical')

    # Create necessary directories if they don't exist yet
    os.makedirs(resDir, exist_ok=True)
    os.makedirs(os.path.join(resDir, 'OTE_images'), exist_ok=True)
    os.makedirs(os.path.join(resDir, 'psfs'), exist_ok=True)

    # Set up logger
    util.setup_pastis_logging(resDir, f'pastis_matrix_{design}')
    log.info('Building numerical matrix for LUVOIR\n')

    # Read calibration aberration
    zern_number = CONFIG_PASTIS.getint('calibration', 'local_zernike')
    zern_mode = util.ZernikeMode(zern_number)                       # Create Zernike mode object for easier handling

    # General telescope parameters
    nb_seg = CONFIG_PASTIS.getint('LUVOIR', 'nb_subapertures')
    wvln = CONFIG_PASTIS.getfloat('LUVOIR', 'lambda') * 1e-9  # m
    diam = CONFIG_PASTIS.getfloat('LUVOIR', 'diameter')  # m
    wfe_aber = CONFIG_PASTIS.getfloat('LUVOIR', 'calibration_aberration') * 1e-9   # m

    # Image system parameters
    sampling = CONFIG_PASTIS.getfloat('LUVOIR', 'sampling')

    # Record some of the defined parameters
    log.info(f'LUVOIR apodizer design: {design}')
    log.info(f'Wavelength: {wvln} m')
    log.info(f'Telescope diameter: {diam} m')
    log.info(f'Number of segments: {nb_seg}')
    log.info(f'Sampling: {sampling} px per lambda/D')
    log.info(f'wfe_aber: {wfe_aber} m')

    #  Copy configfile to resulting matrix directory
    util.copy_config(resDir)

    ### Instantiate Luvoir telescope with chosen apodizer design
    optics_input = CONFIG_PASTIS.get('LUVOIR', 'optics_path')
    luvoir = LuvoirAPLC(optics_input, design, sampling)

    ### Reference images for contrast normalization and coronagraph floor
    unaberrated_coro_psf, ref = luvoir.calc_psf(ref=True, display_intermediate=False, return_intermediate=False)
    norm = np.max(ref)

    dh_intensity = (unaberrated_coro_psf / norm) * luvoir.dh_mask
    contrast_floor = np.mean(dh_intensity[np.where(luvoir.dh_mask != 0)])
    log.info(f'contrast floor: {contrast_floor}')

    ### Generating the PASTIS matrix and a list for all contrasts
    contrast_matrix = np.zeros([nb_seg, nb_seg])   # Generate empty matrix
    all_psfs = []
    all_contrasts = []

    for i in range(nb_seg):
        for j in range(nb_seg):

            log.info(f'\nSTEP: {i+1}-{j+1} / {nb_seg}-{nb_seg}')

            # Put aberration on correct segments. If i=j, apply only once!
            luvoir.flatten()
            luvoir.set_segment(i+1, wfe_aber/2, 0, 0)
            if i != j:
                luvoir.set_segment(j+1, wfe_aber/2, 0, 0)

            log.info('Calculating coro image...')
            image, inter = luvoir.calc_psf(ref=False, display_intermediate=False, return_intermediate='intensity')
            # Normalize PSF by reference image
            psf = image / norm
            all_psfs.append(psf.shaped)

            # Save image to disk
            if savepsfs:   # TODO: I might want to change this to matplotlib images since I save the PSF cube anyway.
                filename_psf = f'psf_{zern_mode.name}_{zern_mode.convention + str(zern_mode.index)}_segs_{i+1}-{j+1}'
                hcipy.write_fits(psf, os.path.join(resDir, 'psfs', filename_psf + '.fits'))

            # Save OPD images for testing
            if saveopds:
                opd_name = f'opd_{zern_mode.name}_{zern_mode.convention + str(zern_mode.index)}_segs_{i+1}-{j+1}'
                plt.clf()
                hcipy.imshow_field(inter['seg_mirror'], mask=luvoir.aperture, cmap='RdBu')
                plt.savefig(os.path.join(resDir, 'OTE_images', opd_name + '.pdf'))

            log.info('Calculating mean contrast in dark hole')
            dh_intensity = psf * luvoir.dh_mask
            contrast = np.mean(dh_intensity[np.where(luvoir.dh_mask != 0)])
            log.info(f'contrast: {float(contrast)}')    # contrast is a Field, here casting to normal float
            all_contrasts.append(contrast)

            # Fill according entry in the matrix and subtract baseline contrast
            contrast_matrix[i,j] = contrast - contrast_floor

    # Transform saved lists to arrays
    all_psfs = np.array(all_psfs)
    all_contrasts = np.array(all_contrasts)

    # Save the PSF image *cube* as well (as opposed to each one individually)
    hcipy.write_fits(all_psfs, os.path.join(resDir, 'psfs', 'psf_cube.fits'),)
    np.savetxt(os.path.join(resDir, 'pair-wise_contrasts.txt'), all_contrasts, fmt='%e')

    # Filling the off-axis elements
    log.info('\nCalculating off-axis matrix elements...')
    matrix_two_N = np.copy(contrast_matrix)      # This is just an intermediary copy so that I don't mix things up.
    matrix_pastis = np.copy(contrast_matrix)     # This will be the final PASTIS matrix.

    for i in range(nb_seg):
        for j in range(nb_seg):
            if i != j:
                matrix_off_val = (matrix_two_N[i,j] - matrix_two_N[i,i] - matrix_two_N[j,j]) / 2.
                matrix_pastis[i,j] = matrix_off_val
                log.info(f'Off-axis for i{i+1}-j{j+1}: {matrix_off_val}')

    # Normalize matrix for the input aberration - this defines what units the PASTIS matrix will be in. The PASTIS
    # matrix propagation function (util.pastis_contrast()) then needs to take in the aberration vector in these same
    # units. I have chosen to keep this to 1nm, so, we normalize the PASTIS matrix to units of nanometers.
    matrix_pastis /= np.square(wfe_aber * 1e9)    #  1e9 converts the calibration aberration back to nanometers

    # Save matrix to file
    filename_matrix = f'PASTISmatrix_num_{zern_mode.name}_{zern_mode.convention + str(zern_mode.index)}'
    hcipy.write_fits(matrix_pastis, os.path.join(resDir, filename_matrix + '.fits'))
    log.info(f'Matrix saved to: {os.path.join(resDir, filename_matrix + ".fits")}')

    # Tell us how long it took to finish.
    end_time = time.time()
    log.info(f'Runtime for matrix_building.py: {end_time - start_time}sec = {(end_time - start_time) / 60}min')
    log.info(f'Data saved to {resDir}')
    
    return overall_dir
def num_matrix_luvoir(design):
    """
    Generate a numerical PASTIS matrix for a LUVOIR A coronagraph.

    All inputs are read from the (local) configfile and saved to the specified output directory.
    The LUVOIR STDT delivery in May 2018 included three different apodizers
    we can work with, so I will implement an easy way of making a choice between them.
    small, medium and large
    """

    # Keep track of time
    start_time = time.time()  # runtime is currently around 150 minutes
    print('Building numerical matrix for LUVOIR\n')

    ### Parameters

    # System parameters
    resDir = os.path.join(CONFIG_INI.get('local', 'local_data_path'), 'active',
                          'matrix_numerical')
    zern_number = CONFIG_INI.getint('calibration', 'zernike')
    zern_mode = util.ZernikeMode(
        zern_number)  # Create Zernike mode object for easier handling

    # General telescope parameters
    nb_seg = CONFIG_INI.getint('LUVOIR', 'nb_subapertures')
    wvln = CONFIG_INI.getfloat('LUVOIR', 'lambda') * 1e-9  # m
    diam = CONFIG_INI.getfloat('LUVOIR', 'diameter')  # m
    nm_aber = CONFIG_INI.getfloat('calibration',
                                  'single_aberration') * 1e-9  # m

    # Image system parameters
    im_lamD = 30  # image size in lambda/D
    sampling = 4

    # Print some of the defined parameters
    print('LUVOIR apodizer design: {}'.format(design))
    print()
    print('Wavelength: {} m'.format(wvln))
    print('Telescope diameter: {} m'.format(diam))
    print('Number of segments: {}'.format(nb_seg))
    print()
    print('Image size: {} lambda/D'.format(im_lamD))
    print('Sampling: {} px per lambda/D'.format(sampling))

    ### Setting up the paths

    # If subfolder "matrix_numerical" doesn't exist yet, create it.
    if not os.path.isdir(resDir):
        os.mkdir(resDir)

    # If subfolder "OTE_images" doesn't exist yet, create it.
    if not os.path.isdir(os.path.join(resDir, 'OTE_images')):
        os.mkdir(os.path.join(resDir, 'OTE_images'))

    # If subfolder "psfs" doesn't exist yet, create it.
    if not os.path.isdir(os.path.join(resDir, 'psfs')):
        os.mkdir(os.path.join(resDir, 'psfs'))

    ### Instantiate Luvoir telescope with chosen apodizer design
    optics_input = '/Users/ilaginja/Documents/LabWork/ultra/LUVOIR_delivery_May2019/'
    luvoir = LuvoirAPLC(optics_input, design, sampling)

    ### Dark hole mask
    dh_outer = hc.circular_aperture(2 * luvoir.apod_dict[design]['owa'] *
                                    luvoir.lam_over_d)(luvoir.focal_det)
    dh_inner = hc.circular_aperture(2 * luvoir.apod_dict[design]['iwa'] *
                                    luvoir.lam_over_d)(luvoir.focal_det)
    dh_mask = (dh_outer - dh_inner).astype('bool')

    ### Reference images for contrast normalization and coronagraph floor
    unaberrated_coro_psf, ref = luvoir.calc_psf(ref=True,
                                                display_intermediate=False,
                                                return_intermediate=False)
    norm = np.max(ref)

    dh_intensity = unaberrated_coro_psf / norm * dh_mask
    contrast_floor = np.mean(dh_intensity[np.where(dh_intensity != 0)])
    print(contrast_floor)

    ### Generating the PASTIS matrix and a list for all contrasts
    matrix_direct = np.zeros([nb_seg, nb_seg])  # Generate empty matrix
    all_psfs = []
    all_contrasts = []

    print('nm_aber: {} m'.format(nm_aber))

    for i in range(nb_seg):
        for j in range(nb_seg):

            print('\nSTEP: {}-{} / {}-{}'.format(i + 1, j + 1, nb_seg, nb_seg))

            # Put aberration on correct segments. If i=j, apply only once!
            luvoir.flatten()
            luvoir.set_segment(i + 1, nm_aber / 2, 0, 0)
            if i != j:
                luvoir.set_segment(j + 1, nm_aber / 2, 0, 0)

            print('Calculating coro image...')
            image, inter = luvoir.calc_psf(ref=False,
                                           display_intermediate=False,
                                           return_intermediate='intensity')
            # Normalize PSF by reference image
            psf = image / norm

            # Save image to disk
            filename_psf = 'psf_' + zern_mode.name + '_' + zern_mode.convention + str(
                zern_mode.index) + '_segs_' + str(i + 1) + '-' + str(j + 1)
            hc.write_fits(psf,
                          os.path.join(resDir, 'psfs', filename_psf + '.fits'))
            all_psfs.append(psf)

            # Save OPD images for testing (are these actually surface images, not OPD?)
            opd_name = 'opd_' + zern_mode.name + '_' + zern_mode.convention + str(
                zern_mode.index) + '_segs_' + str(i + 1) + '-' + str(j + 1)
            plt.clf()
            hc.imshow_field(inter['seg_mirror'],
                            mask=luvoir.aperture,
                            cmap='RdBu')
            plt.savefig(os.path.join(resDir, 'OTE_images', opd_name + '.pdf'))

            print('Calculating mean contrast in dark hole')
            dh_intensity = psf * dh_mask
            contrast = np.mean(dh_intensity[np.where(dh_intensity != 0)])
            print('contrast:', contrast)
            all_contrasts.append(contrast)

            # Fill according entry in the matrix and subtract baseline contrast
            matrix_direct[i, j] = contrast - contrast_floor

    # Transform saved lists to arrays
    all_psfs = np.array(all_psfs)
    all_contrasts = np.array(all_contrasts)

    # Filling the off-axis elements
    matrix_two_N = np.copy(
        matrix_direct
    )  # This is just an intermediary copy so that I don't mix things up.
    matrix_pastis = np.copy(
        matrix_direct)  # This will be the final PASTIS matrix.

    for i in range(nb_seg):
        for j in range(nb_seg):
            if i != j:
                matrix_off_val = (matrix_two_N[i, j] - matrix_two_N[i, i] -
                                  matrix_two_N[j, j]) / 2.
                matrix_pastis[i, j] = matrix_off_val
                print('Off-axis for i{}-j{}: {}'.format(
                    i + 1, j + 1, matrix_off_val))

    # Normalize matrix for the input aberration - the whole code is set up to be normalized to 1 nm, and even if
    # the units entered are in m for the sake of HCIPy, everything else is assuming the baseline is 1nm, so the
    # normalization can be taken out if we're working with exactly 1 nm for the aberration, even if entered in meters.
    #matrix_pastis /= np.square(nm_aber)

    # Save matrix to file
    filename_matrix = 'PASTISmatrix_num_' + zern_mode.name + '_' + zern_mode.convention + str(
        zern_mode.index)
    hc.write_fits(matrix_pastis, os.path.join(resDir,
                                              filename_matrix + '.fits'))
    print('Matrix saved to:', os.path.join(resDir, filename_matrix + '.fits'))

    # Save the PSF image *cube* as well (as opposed to each one individually)
    hc.write_fits(
        all_psfs,
        os.path.join(resDir, 'psfs', 'psf_cube' + '.fits'),
    )
    np.savetxt(os.path.join(resDir, 'contrasts.txt'), all_contrasts, fmt='%e')

    # Tell us how long it took to finish.
    end_time = time.time()
    print('Runtime for matrix_building.py:', end_time - start_time, 'sec =',
          (end_time - start_time) / 60, 'min')
    print('Data saved to {}'.format(resDir))
def clean_vapp():
    import numpy as np
    import matplotlib.pyplot as plt

    from hcipy import read_fits, make_pupil_grid, make_focal_grid, FraunhoferPropagator, circular_aperture, evaluate_supersampled, imshow_field, imsave_field, Field, LyotCoronagraph, Wavefront

    script_path = os.path.realpath(__file__).split("vApp_reduction", 1)[0]
    full_path = script_path + "vApp_reduction/data/"
    amplitude_file = full_path + 'SCExAO_vAPP_amplitude_resampled.fits'
    phase_file = full_path + 'SCExAO_vAPP_phase_resampled.fits'

    # loading the files required for generating the vAPP.
    amplitude_temp = read_fits(amplitude_file)
    phase_temp = read_fits(phase_file)

    # number of pixels along one axis in the pupil
    Npix = amplitude_temp.shape[0]

    # generating the grids
    pupil_grid = make_pupil_grid(Npix)
    focal_grid = make_focal_grid(pupil_grid, 4, 25)

    # Mapping from pupil plane to focal plane
    propagator = FraunhoferPropagator(pupil_grid, focal_grid)

    # converting the amplitude and phase to fields
    amplitude = Field(amplitude_temp.ravel(), pupil_grid)
    phase = Field(phase_temp.ravel(), pupil_grid)

    # the wavefront for the three PSFs
    pupil_wf_PSF_1 = Wavefront(amplitude *
                               np.exp(1j * phase))  # coronagraphic PSF 1
    pupil_wf_PSF_2 = Wavefront(amplitude *
                               np.exp(-1j * phase))  # coronagraphic PSF 2
    pupil_wf_PSF_3 = Wavefront(amplitude)  # leakage

    # Propagating them to the focal plane
    focal_wf_PSF_1 = propagator(pupil_wf_PSF_1)
    focal_wf_PSF_2 = propagator(pupil_wf_PSF_2)
    focal_wf_PSF_3 = propagator(pupil_wf_PSF_3)

    # setting the total power in the images
    focal_wf_PSF_1.total_power = 1
    focal_wf_PSF_2.total_power = 1
    focal_wf_PSF_3.total_power = 1

    # the strenght of the leakage term
    leakage = 0.02

    # getting the power and scaling with leakage
    PSF_1_pwr = focal_wf_PSF_1.power * (1 - leakage / 2)
    PSF_2_pwr = focal_wf_PSF_2.power * (1 - leakage / 2)
    PSF_3_pwr = focal_wf_PSF_3.power * leakage

    # generating the total PSF of the vAPP
    total_PSF = PSF_1_pwr + PSF_2_pwr + PSF_3_pwr

    # normalizing to sum = 1
    total_PSF /= np.sum(total_PSF)

    fig = plt.figure()
    imshow_field(np.log10(total_PSF / total_PSF.max()), vmin=-5, vmax=0)

    cbar = plt.colorbar()
    cbar.set_label(r"$^{10}\log(contrast)$")
    plt.ylabel(r"$\lambda/D$")
    plt.xlabel(r"$\lambda/D$")

    plt.show()
    output_path = get_output_path("miscellaneous")
    fig.savefig(output_path + "clean_vapp")

    fig = plt.figure()
    imshow_field(np.log10(total_PSF / total_PSF.max()), vmin=-5, vmax=0)

    bbox_props = dict(boxstyle="circle,pad=0.3",
                      fill=False,
                      alpha=1,
                      fc=None,
                      ec="red",
                      lw=5)
    plt.text(10.3,
             10.7,
             " ",
             ha="center",
             va="center",
             rotation=45,
             size=110,
             bbox=bbox_props)
    plt.text(-10.3,
             -10.7,
             " ",
             ha="center",
             va="center",
             rotation=45,
             size=110,
             bbox=bbox_props)
    bbox_props = dict(boxstyle="circle,pad=0.3",
                      fill=False,
                      alpha=1,
                      fc=None,
                      ec="white",
                      lw=5)
    plt.text(0,
             0,
             " ",
             ha="center",
             va="center",
             rotation=45,
             size=55,
             bbox=bbox_props)
    plt.text(8,
             -15,
             " ",
             ha="center",
             va="center",
             rotation=45,
             size=55,
             bbox=bbox_props)
    plt.text(-8,
             15,
             " ",
             ha="center",
             va="center",
             rotation=45,
             size=55,
             bbox=bbox_props)

    cbar = plt.colorbar()
    cbar.set_label(r"$^{10}\log(contrast)$")
    plt.ylabel(r"$\lambda/D$")
    plt.xlabel(r"$\lambda/D$")

    plt.show()
    output_path = get_output_path("miscellaneous")
    fig.savefig(output_path + "clean_vapp_annotated")
Example #17
0
    u, avg, s = tele.run_closed_loop(leak,
                                     gain,
                                     fileout,
                                     run_for,
                                     freq,
                                     save_every,
                                     wl=wl)

    print(s)
    plt.imshow(np.abs(u))
    plt.show()

    #planar wf masked by aperture
    wf = tele.wf_pupil_hires

    hc.imshow_field(wf.electric_field)
    plt.show()

    #turbulence induced abberation
    wf = tele.propagate_through_turb(wf)

    hc.imshow_field(wf.electric_field)
    plt.show()

    #partial AO correction
    wf = tele.DM_hires.forward(wf)

    hc.imshow_field(wf.electric_field)
    plt.show()

    #beam shrinking
Example #18
0
    
    array = np.array([[0.0]*N]*N)
    
    for i in range(0,N):
        for j in range (0, N):
            x = abs(int(N/2) - i)
            y = abs(int(N/2) - j)
            r = np.sqrt(x**2 + y**2)
            if r < 3.5*N/16 and r > 2*N/16:
                array[i][j] = 1.0
    
    array_flat = array.flatten()
    return hcipy.Field(array_flat, focal_grid)

annulus = make_FPM(focal_grid)
hcipy.imshow_field(annulus)
plt.show()


# In[100]:


def score_matrix3(aberrations, show=False):
    
    # Make segmented mirror
    aper, segments = hcipy.make_hexagonal_segmented_aperture(num_rings,
                                                         segment_flat_to_flat,
                                                         gap_size,
                                                         starting_ring=1,
                                                         return_segments=True)