Example #1
0
 def calc(*args):
     progress.visible = True
     if monochromatic_toggle.value is True:
         psf = instrument.calc_psf(
             monochromatic=monochromatic_wavelength.value * 1e-6,
             display=True,
             outfile=OUTPUT_FILENAME,
             overwrite=True
         )
     else:
         source = poppy.specFromSpectralType(source_selection.value)
         _log.debug("Got source type {}: {}".format(source_selection.value, source))
         psf = instrument.calc_psf(
             source=source,
             display=True,
             outfile=OUTPUT_FILENAME,
             overwrite=True
         )
     fig, (ax_oversamp, ax_detsamp) = plt.subplots(1, 2,figsize=(12, 4))
     title1 = "PSF sim for {}, {}\n".format(instrument.name, instrument.filter)
     poppy.display_PSF(psf, ax=ax_oversamp,
                       title=title1+"Oversampled PSF")
     poppy.display_PSF(psf, ax=ax_detsamp, ext='DET_SAMP',
                       title=title1+'Detector pixel sampled PSF')
     progress.visible = None
     download_link.visible = True
Example #2
0
 def calc(*args):
     progress.visible = True
     if monochromatic_toggle.value is True:
         psf = instrument.calcPSF(
             monochromatic=monochromatic_wavelength.value * 1e-6,
             display=True,
             outfile=OUTPUT_FILENAME,
             overwrite=True)
     else:
         source = poppy.specFromSpectralType(source_selection.value)
         _log.debug("Got source type {}: {}".format(source_selection.value,
                                                    source))
         psf = instrument.calcPSF(source=source,
                                  display=True,
                                  outfile=OUTPUT_FILENAME,
                                  overwrite=True)
     fig, (ax_oversamp, ax_detsamp) = plt.subplots(1, 2, figsize=(12, 4))
     title1 = "PSF sim for {}, {}\n".format(instrument.name,
                                            instrument.filter)
     poppy.display_PSF(psf,
                       ax=ax_oversamp,
                       title=title1 + "Oversampled PSF")
     poppy.display_PSF(psf,
                       ax=ax_detsamp,
                       ext='DET_SAMP',
                       title=title1 + 'Detector pixel sampled PSF')
     progress.visible = None
     download_link.visible = True
Example #3
0
def validate_miri_coron():
    """Validate MIRI coronagraphic performance against the simulations in Cavarroc et al. 2008 SPIE


    """


    miri = webbpsf_core.MIRI()

    miri.filter = 'FND'
    miri.image_mask = 'FQPM1140'


    im_nd_onaxis = miri.calcPSF(fov_arcsec=10)

    miri.options['source_offset_x'] = 2
    miri.options['source_offset_y'] = 2

    im_nd_offaxis = miri.calcPSF(fov_arcsec=10)

    P.subplot(211)
    poppy.display_PSF(im_nd_offaxis, colorbar=False)
    P.subplot(212)
    poppyt.display_PSF(im_nd_onaxis, colorbar=False)

    stop()
Example #4
0
 def ev_displayPSF(self):
     "Event handler for Displaying the PSF"
     #self._updateFromGUI()
     #if self.PSF_HDUlist is not None:
     plt.clf()
     poppy.display_PSF(self.PSF_HDUlist, vmin = self.advanced_options['psf_vmin'], vmax = self.advanced_options['psf_vmax'],
             scale = self.advanced_options['psf_scale'], cmap= self.advanced_options['psf_cmap'], normalize=self.advanced_options['psf_normalize'])
     self._refresh_window()
Example #5
0
 def ev_displayPSF(self):
     "Event handler for Displaying the PSF"
     #self._updateFromGUI()
     #if self.PSF_HDUlist is not None:
     plt.clf()
     poppy.display_PSF(self.PSF_HDUlist, vmin = self.advanced_options['psf_vmin'], vmax = self.advanced_options['psf_vmax'],
             scale = self.advanced_options['psf_scale'], cmap= self.advanced_options['psf_cmap'], normalize=self.advanced_options['psf_normalize'])
     self._refresh_window()
Example #6
0
def test_MatrixFT_FFT_Lyot_propagation_equivalence(display=False):
    """ Using a simple Lyot coronagraph prescription,
    perform a simple numerical check for consistency
    between calcPSF result of standard (FFT) propagation and
    MatrixFTCoronagraph subclass of OpticalSystem."""

    D = 2.
    wavelen = 1e-6
    ovsamp = 4

    fftcoron_annFPM_osys = poppy.OpticalSystem(oversample=ovsamp)
    fftcoron_annFPM_osys.addPupil(poppy.CircularAperture(radius=D / 2))
    spot = poppy.CircularOcculter(radius=0.4)
    diaphragm = poppy.InverseTransmission(poppy.CircularOcculter(radius=1.2))
    annFPM = poppy.CompoundAnalyticOptic(opticslist=[diaphragm, spot])
    fftcoron_annFPM_osys.addImage(annFPM)
    fftcoron_annFPM_osys.addPupil(poppy.CircularAperture(radius=0.9 * D / 2))
    fftcoron_annFPM_osys.addDetector(pixelscale=0.05, fov_arcsec=3.)

    # Re-cast as MFT coronagraph with annular diaphragm FPM
    matrixFTcoron_annFPM_osys = poppy.MatrixFTCoronagraph(
        fftcoron_annFPM_osys,
        occulter_box=diaphragm.uninverted_optic.radius_inner)

    annFPM_fft_psf = fftcoron_annFPM_osys.calcPSF(wavelen)
    annFPM_mft_psf = matrixFTcoron_annFPM_osys.calcPSF(wavelen)

    diff_img = annFPM_mft_psf[0].data - annFPM_fft_psf[0].data
    abs_diff_img = np.abs(diff_img)

    if display:
        plt.figure(figsize=(16, 3))
        plt.subplot(131)
        poppy.display_PSF(annFPM_fft_psf,
                          vmin=1e-10,
                          vmax=1e-6,
                          title='Annular FPM Lyot coronagraph, FFT')
        plt.subplot(132)
        poppy.display_PSF(annFPM_mft_psf,
                          vmin=1e-10,
                          vmax=1e-6,
                          title='Annular FPM Lyot coronagraph, Matrix FT')
        plt.subplot(133)
        plt.imshow((annFPM_mft_psf[0].data - annFPM_fft_psf[0].data),
                   cmap='gist_heat')
        plt.colorbar()
        plt.title('Difference (MatrixFT - FFT)')
        plt.show()

    print("Max of absolute difference: %.10g" % np.max(abs_diff_img))

    assert (np.all(abs_diff_img < 2e-7))
Example #7
0
def test_ThinLens(display=False):
    pupil_radius = 1

    pupil = optics.CircularAperture(radius=pupil_radius)
    # let's add < 1 wave here so we don't have to worry about wrapping
    lens = optics.ThinLens(nwaves=0.5,
                           reference_wavelength=1e-6,
                           radius=pupil_radius)
    # n.b. npix is 99 so that there are an integer number of pixels per meter (hence multiple of 3)
    # and there is a central pixel at 0,0 (hence odd npix)
    # Otherwise the strict test against half a wave min max doesn't work
    # because we're missing some (tiny but nonzero) part of the aperture
    wave = poppy_core.Wavefront(npix=99, diam=3.0, wavelength=1e-6)
    wave *= pupil
    wave *= lens

    assert np.allclose(wave.phase.max(), np.pi / 2)
    assert np.allclose(wave.phase.min(), -np.pi / 2)

    # regression test to ensure null optical elements don't change ThinLens behavior
    # see https://github.com/mperrin/poppy/issues/14
    osys = poppy_core.OpticalSystem()
    osys.addPupil(optics.CircularAperture(radius=1))
    for i in range(3):
        osys.addImage()
        osys.addPupil()

    osys.addPupil(
        optics.ThinLens(nwaves=0.5,
                        reference_wavelength=1e-6,
                        radius=pupil_radius))
    osys.addDetector(pixelscale=0.01, fov_arcsec=3.0)
    psf = osys.calcPSF(wavelength=1e-6)

    osys2 = poppy_core.OpticalSystem()
    osys2.addPupil(optics.CircularAperture(radius=1))
    osys2.addPupil(
        optics.ThinLens(nwaves=0.5,
                        reference_wavelength=1e-6,
                        radius=pupil_radius))
    osys2.addDetector(pixelscale=0.01, fov_arcsec=3.0)
    psf2 = osys2.calcPSF()

    if display:
        import poppy
        poppy.display_PSF(psf)
        poppy.display_PSF(psf2)

    assert np.allclose(psf[0].data, psf2[0].data), (
        "ThinLens shouldn't be affected by null optical elements! Introducing extra image planes "
        "made the output PSFs differ beyond numerical tolerances.")
Example #8
0
def test_MFT_FFT_equivalence_in_OpticalSystem(display=False):
    """ Test that propagating Wavefronts through an OpticalSystem
    using an MFT and an FFT give equivalent results.

    This is a somewhat higher level test that involves all the
    Wavefront class's _propagateTo() machinery, which is not
    tested in the above function. Hence the two closely related tests."""

    # Note that the Detector class and Wavefront propagation always uses
    # ADJUSTABLE-style MFTs (output centered in the array)
    # which is not compatible with FFT outputs for even-sized arrays.
    # Thus in order to get an exact equivalence, we have to set up our
    # OpticalSystem so that it, very unusually, uses an odd size for
    # its input wavefront. The easiest way to do this is to discretize
    # an AnalyticOpticalElement onto a specific grid.

    fits511 = optics.ParityTestAperture().to_fits('test.fits',
                                                  wavelength=1e-6,
                                                  npix=511)
    pup511 = poppy_core.FITSOpticalElement(transmission=fits511)

    # set up simple optical system that will just FFT
    fftsys = poppy_core.OpticalSystem(oversample=1)
    fftsys.add_pupil(pup511)
    fftsys.add_image()

    fftpsf, fftplanes = fftsys.calc_psf(display=False,
                                        return_intermediates=True)

    # set up equivalent using an MFT, tuned to get the exact same scale
    # for the image plane
    mftsys = poppy_core.OpticalSystem(oversample=1)
    mftsys.add_pupil(pup511)
    mftsys.add_detector(pixelscale=fftplanes[1].pixelscale,
                        fov_pixels=fftplanes[1].shape,
                        oversample=1)  #, offset=(pixscale/2, pixscale/2))

    mftpsf, mftplanes = mftsys.calc_psf(display=False,
                                        return_intermediates=True)

    if display:
        import poppy
        plt.figure(figsize=(15, 4))
        plt.subplot(131)
        poppy.display_PSF(fftpsf, title="FFT PSF")
        plt.subplot(132)
        poppy.display_PSF(mftpsf, title='MFT PSF')
        plt.subplot(133)
        poppy.display_PSF_difference(fftpsf, mftpsf, title='Diff FFT-MFT')

    assert (np.all(np.abs(mftpsf[0].data - fftpsf[0].data) < 1e-10))
Example #9
0
def test_MFT_FFT_equivalence_in_OpticalSystem(display=False):
    """ Test that propagating Wavefronts through an OpticalSystem
    using an MFT and an FFT give equivalent results.

    This is a somewhat higher level test that involves all the
    Wavefront class's _propagateTo() machinery, which is not
    tested in the above function. Hence the two closely related tests."""


    # Note that the Detector class and Wavefront propagation always uses
    # ADJUSTABLE-style MFTs (output centered in the array)
    # which is not compatible with FFT outputs for even-sized arrays.
    # Thus in order to get an exact equivalence, we have to set up our
    # OpticalSystem so that it, very unusually, uses an odd size for
    # its input wavefront. The easiest way to do this is to discretize
    # an AnalyticOpticalElement onto a specific grid.

    fits511 = optics.ParityTestAperture().to_fits('test.fits', wavelength=1e-6, npix=511)
    pup511 = poppy_core.FITSOpticalElement(transmission=fits511)


    # set up simple optical system that will just FFT
    fftsys = poppy_core.OpticalSystem(oversample=1)
    fftsys.add_pupil(pup511)
    fftsys.add_image()

    fftpsf, fftplanes = fftsys.calc_psf(display=False, return_intermediates=True)

    # set up equivalent using an MFT, tuned to get the exact same scale
    # for the image plane
    mftsys = poppy_core.OpticalSystem(oversample=1)
    mftsys.add_pupil(pup511)
    mftsys.add_detector(pixelscale=fftplanes[1].pixelscale , fov_pixels=fftplanes[1].shape, oversample=1) #, offset=(pixscale/2, pixscale/2))

    mftpsf, mftplanes = mftsys.calc_psf(display=False, return_intermediates=True)


    if display:
        import poppy
        plt.figure(figsize=(15,4))
        plt.subplot(131)
        poppy.display_PSF(fftpsf, title="FFT PSF")
        plt.subplot(132)
        poppy.display_PSF(mftpsf, title='MFT PSF')
        plt.subplot(133)
        poppy.display_PSF_difference(fftpsf, mftpsf, title='Diff FFT-MFT')



    assert( np.all(  np.abs(mftpsf[0].data-fftpsf[0].data) < 1e-10 ))
Example #10
0
def make_hawki_poppy_psf():
    import poppy

    osys = poppy.OpticalSystem()
    m1 = poppy.CircularAperture(radius=4.1)
    spiders = poppy.SecondaryObscuration(secondary_radius=0.6,
                                         n_supports=4,
                                         support_width=0.1)
    vlt = poppy.CompoundAnalyticOptic(opticslist=[m1, spiders], name='VLT')

    psfs = []
    seeing = 0.4
    see_psf = simcado.psf.seeing_psf(fwhm=seeing, size=384, pix_res=0.106 / 2)

    for lam in [1.2, 1.6, 2.2]:
        osys = poppy.OpticalSystem()
        osys.add_pupil(vlt)
        osys.add_detector(pixelscale=0.106, fov_arcsec=0.106 * 192)
        diff_psf = osys.calc_psf(lam * 1e-6)

        tmp = deepcopy(diff_psf)
        tmp[0].data = fftconvolve(diff_psf[0].data,
                                  see_psf[0].data,
                                  mode="same")
        tmp[0].data /= np.sum(tmp[0].data)

        tmp[0].header["SEEING"] = seeing
        tmp[0].header["CDELT1"] = tmp[0].header["PIXELSCL"]
        tmp[0].header["CDELT2"] = tmp[0].header["PIXELSCL"]

        psfs += tmp

    hdus = fits.HDUList(psfs)
    for i in range(1, len(hdus)):
        hdus[i] = fits.ImageHDU(data=hdus[i].data, header=hdus[i].header)

    hdus.writeto("HAWK-I_config/PSF_HAWKI_poppy.fits", clobber=True)

    fname = "HAWK-I_config/PSF_HAWKI_poppy.fits"

    plt.figure(figsize=(15, 4))
    for i in range(3):
        plt.subplot(1, 3, i + 1)
        poppy.display_PSF(fname,
                          ext=i,
                          title="HAWKI PSF lambda=" +
                          str(fits.getheader(fname, ext=i)["WAVELEN"]))

    plt.show()
Example #11
0
def test_ThinLens(display=False):
    pupil_radius = 1

    pupil = optics.CircularAperture(radius=pupil_radius)
    # let's add < 1 wave here so we don't have to worry about wrapping
    lens = optics.ThinLens(nwaves=0.5, reference_wavelength=1e-6, radius=pupil_radius)
    # n.b. npix is 99 so that there are an integer number of pixels per meter (hence multiple of 3)
    # and there is a central pixel at 0,0 (hence odd npix)
    # Otherwise the strict test against half a wave min max doesn't work
    # because we're missing some (tiny but nonzero) part of the aperture
    wave = poppy_core.Wavefront(npix=99, diam=3.0, wavelength=1e-6)
    wave *= pupil
    wave *= lens

    assert np.allclose(wave.phase.max(),  np.pi/2)
    assert np.allclose(wave.phase.min(), -np.pi/2)

    # regression test to ensure null optical elements don't change ThinLens behavior
    # see https://github.com/mperrin/poppy/issues/14
    osys = poppy_core.OpticalSystem()
    osys.addPupil(optics.CircularAperture(radius=1))
    for i in range(3):
        osys.addImage()
        osys.addPupil()

    osys.addPupil(optics.ThinLens(nwaves=0.5, reference_wavelength=1e-6,
                                  radius=pupil_radius))
    osys.addDetector(pixelscale=0.01, fov_arcsec=3.0)
    psf = osys.calcPSF(wavelength=1e-6)

    osys2 = poppy_core.OpticalSystem()
    osys2.addPupil(optics.CircularAperture(radius=1))
    osys2.addPupil(optics.ThinLens(nwaves=0.5, reference_wavelength=1e-6,
                                   radius=pupil_radius))
    osys2.addDetector(pixelscale=0.01, fov_arcsec=3.0)
    psf2 = osys2.calcPSF()


    if display:
        import poppy
        poppy.display_PSF(psf)
        poppy.display_PSF(psf2)

    assert np.allclose(psf[0].data,psf2[0].data), (
        "ThinLens shouldn't be affected by null optical elements! Introducing extra image planes "
        "made the output PSFs differ beyond numerical tolerances."
    )
def test_MatrixFT_FFT_Lyot_propagation_equivalence(display=False):
    """ Using a simple Lyot coronagraph prescription,
    perform a simple numerical check for consistency
    between calcPSF result of standard (FFT) propagation and
    MatrixFTCoronagraph subclass of OpticalSystem."""

    D = 2.
    wavelen = 1e-6
    ovsamp = 4

    fftcoron_annFPM_osys = poppy.OpticalSystem( oversample=ovsamp )
    fftcoron_annFPM_osys.addPupil( poppy.CircularAperture(radius=D/2) )
    spot = poppy.CircularOcculter( radius=0.4  )
    diaphragm = poppy.InverseTransmission( poppy.CircularOcculter( radius=1.2 ) )
    annFPM = poppy.CompoundAnalyticOptic( opticslist = [diaphragm, spot] )
    fftcoron_annFPM_osys.addImage( annFPM )
    fftcoron_annFPM_osys.addPupil( poppy.CircularAperture(radius=0.9*D/2) )
    fftcoron_annFPM_osys.addDetector( pixelscale=0.05, fov_arcsec=3. )
    
    # Re-cast as MFT coronagraph with annular diaphragm FPM
    matrixFTcoron_annFPM_osys = poppy.MatrixFTCoronagraph( fftcoron_annFPM_osys, occulter_box=diaphragm.uninverted_optic.radius_inner )
    
    annFPM_fft_psf = fftcoron_annFPM_osys.calcPSF(wavelen)
    annFPM_mft_psf = matrixFTcoron_annFPM_osys.calcPSF(wavelen)

    diff_img = annFPM_mft_psf[0].data - annFPM_fft_psf[0].data
    abs_diff_img = np.abs(diff_img)
   
    if display: 
        plt.figure(figsize=(16,3))
        plt.subplot(131)
        poppy.display_PSF(annFPM_fft_psf, vmin=1e-10, vmax=1e-6, title='Annular FPM Lyot coronagraph, FFT')
        plt.subplot(132)
        poppy.display_PSF(annFPM_mft_psf, vmin=1e-10, vmax=1e-6, title='Annular FPM Lyot coronagraph, Matrix FT')
        plt.subplot(133)
        plt.imshow( (annFPM_mft_psf[0].data - annFPM_fft_psf[0].data), cmap='gist_heat')
        plt.colorbar()
        plt.title('Difference (MatrixFT - FFT)')
        plt.show()

    print("Max of absolute difference: %.10g" % np.max(abs_diff_img))

    assert( np.all(abs_diff_img < 2e-7) )
Example #13
0
 def calc(*args):
     progress.visible = True
     if monochromatic_toggle.value is True:
         psf = instrument.calcPSF(
             monochromatic=monochromatic_wavelength.value * 1e-6,
             display=True,
             outfile=OUTPUT_FILENAME,
             overwrite=True)
     else:
         source = poppy.specFromSpectralType(source_selection.value)
         _log.debug("Got source type {}: {}".format(source_selection.value,
                                                    source))
         psf = instrument.calcPSF(source=source,
                                  display=True,
                                  outfile=OUTPUT_FILENAME,
                                  overwrite=True)
     fig, (ax_oversamp, ax_detsamp) = plt.subplots(1, 2)
     poppy.display_PSF(psf, ax=ax_oversamp)
     poppy.display_PSF(psf, ax=ax_detsamp, ext='DET_SAMP')
     progress.visible = None
     download_link.visible = True
Example #14
0
 def calc(*args):
     progress.visible = True
     if monochromatic_toggle.value is True:
         psf = instrument.calc_psf(
             monochromatic=monochromatic_wavelength.value * 1e-6,
             display=True,
             outfile=OUTPUT_FILENAME,
             overwrite=True
         )
     else:
         source = poppy.specFromSpectralType(source_selection.value)
         _log.debug("Got source type {}: {}".format(source_selection.value, source))
         psf = instrument.calc_psf(
             source=source,
             display=True,
             outfile=OUTPUT_FILENAME,
             overwrite=True
         )
     fig, (ax_oversamp, ax_detsamp) = plt.subplots(1, 2)
     poppy.display_PSF(psf, ax=ax_oversamp)
     poppy.display_PSF(psf, ax=ax_detsamp, ext='DET_SAMP')
     progress.visible = None
     download_link.visible = True
Example #15
0
    def do_test_source_offset(self, iname, theta=0.0):

        nc = webbpsf.Instrument(iname)
        nc.pupilopd=None

        nsteps = 3
        oversample = 2

        shift_req = []
        psfs = []

        for i in range(nsteps+1):
            nc.options['source_offset_r'] = i*0.1
            nc.options['source_offset_theta'] = theta
            nc.options['source_offset_r'] = i*nc.pixelscale*5
            shift_req.append(nc.options['source_offset_r'])
            psfs.append(  nc.calcPSF(nlambda=1, oversample=oversample) )

        poppy.display_PSF(psfs[0])

        cent0 = np.asarray(poppy.measure_centroid(psfs[0]))
        center_pix = (psfs[0][0].data.shape[0]-1)/2.0
        self.assertAlmostEqual(cent0[0], center_pix, 3)
        self.assertAlmostEqual(cent0[1], center_pix, 3)
        _log.info("Center of unshifted image: (%d, %d)" % tuple(cent0))


        for i in range(1, nsteps+1):
            poppy.display_PSF(psfs[i])
            cent = poppy.measure_centroid(psfs[i])
            rx = shift_req[i] * (-np.sin(theta*np.pi/180))
            ry = shift_req[i] * (np.cos(theta*np.pi/180))
            _log.info("   Shift_requested:\t(%10.3f, %10.3f)" % (rx, ry))
            shift = (cent-cent0) * (nc.pixelscale/oversample)
            _log.info("   Shift_achieved: \t(%10.3f, %10.3f)" % (shift[1], shift[0]))
            self.assertAlmostEqual(rx, shift[1], 3)
            self.assertAlmostEqual(ry, shift[0], 3)
Example #16
0
def do_test_source_offset(iname, distance=0.5,  nsteps=1, theta=0.0, tolerance=0.05, monochromatic=None, display=False):
    """ Test source offsets
    Does the star PSF center end up in the desired location?

    The tolerance threshold for success is by default 1/20th of a pixel
    in the SI pixel units. But this can be adjusted by the calling function if needed.

    This is chosen somewhat arbitrarily as pretty good subpixel performance
    for most applications. Trying for greater accuracy would be limited by
    subpixel sampling in the simulations, as well as by the accuracy of the
    centroid measuring function itself.
    """
    _log.info("Calculating shifted image PSFs for "+iname)

    si = webbpsf_core.Instrument(iname)
    si.pupilopd=None

    if iname=='NIRSpec':
        si.image_mask = None # remove default MSA since it overcomplicates this test.

    oversample = 2

    # Calculations
    shift_req = []
    psfs = []

    # unshifted PSF
    #psfs.append(  nc.calc_psf(nlambda=1, oversample=oversample) )
    #shift_req.append(0)

    steps = np.linspace(0, distance, nsteps+1)
    for i, value in enumerate(steps):
        si.options['source_offset_r'] =  steps[i]
        si.options['source_offset_theta'] = theta
        #nc.options['source_offset_r'] = i*nc.pixelscale*5
        shift_req.append(si.options['source_offset_r'])
        psfs.append(  si.calc_psf(nlambda=1, monochromatic=monochromatic, oversample=oversample) )


    # Control case: an unshifted image
    cent0 = np.asarray(poppy.measure_centroid(psfs[0]))
    center_pix = (psfs[0][0].data.shape[0]-1)/2.0
    assert( abs(cent0[0] == center_pix) < 1e-3 )
    assert( abs(cent0[1] == center_pix) < 1e-3 )
    _log.info("Center of unshifted image: ({0:.3f}, {1:.3f}) pixels measured".format(*cent0))
    _log.info(" vs center of the array is ({0}, {0})".format(center_pix))

    if display:
        poppy.display_PSF(psfs[0])

    # Compare to shifted case(s)
    for i in range(1, nsteps+1):

        if display:
            poppy.display_PSF(psfs[i])

        cent = poppy.measure_centroid(psfs[i])
        rx = shift_req[i] * (-np.sin(theta*np.pi/180))
        ry = shift_req[i] * (np.cos(theta*np.pi/180))
        _log.info("   Shift_requested:\t(%10.3f, %10.3f) arcsec" % (rx, ry))
        shift = (cent-cent0) * (si.pixelscale/oversample)
        _log.info("   Shift_achieved: \t(%10.3f, %10.3f) arcsec" % (shift[1], shift[0]))

        deltax =  abs(rx -  shift[1])
        deltay =  abs(ry -  shift[0])
        _log.info("   X offset:\t{0:.3f}\t\tTolerance:\t{1:.3f}".format(deltax, (si.pixelscale*tolerance)))
        assert( deltax  <  (si.pixelscale*tolerance) )
        _log.info("   Y offset:\t{0:.3f}\t\tTolerance:\t{1:.3f}".format(deltay, (si.pixelscale*tolerance)))
        assert( deltay  <  (si.pixelscale*tolerance) )
Example #17
0
def measure_strehl(HDUlist_or_filename=None, ext=0, slice=0, center=None, display=True, verbose=True, cache_perfect=False):
    """ Estimate the Strehl ratio for a PSF.

    This requires computing a simulated PSF with the same
    properties as the one under analysis.

    Note that this calculation will not be very accurate unless both PSFs are well sampled,
    preferably several times better than Nyquist. See
    `Roberts et al. 2004 SPIE 5490 <http://adsabs.harvard.edu/abs/2004SPIE.5490..504R>`_
    for a discussion of the various possible pitfalls when calculating Strehl ratios.

    WARNING: This routine attempts to infer how to calculate a perfect reference
    PSF based on FITS header contents. It will likely work for simple direct imaging
    cases with WebbPSF but will not work (yet) for more complicated cases such as
    coronagraphy, anything with image or pupil masks, etc. Code contributions to add
    such cases are welcomed.


    Parameters
    ----------
    HDUlist_or_filename : string
        Either a fits.HDUList object or a filename of a FITS file on disk
    ext : int
        Extension in that FITS file
    slice : int, optional
        If that extension is a 3D datacube, which slice (plane) of that datacube to use
    center : tuple
        center to compute around.  Default is image center. If the center is on the
        crosshairs between four pixels, then the mean of those four pixels is used.
        Otherwise, if the center is in a single pixel, then that pixel is used.
    verbose, display : bool
        control whether to print the results or display plots on screen.

    cache_perfect : bool
        use caching for perfect images? greatly speeds up multiple calcs w/ same config

    Returns
    ---------
    strehl : float
        Strehl ratio as a floating point number between 0.0 - 1.0

    """

    from .webbpsf_core import Instrument
    from poppy import display_PSF

    if isinstance(HDUlist_or_filename, six.string_types):
        HDUlist = fits.open(HDUlist_or_filename)
    elif isinstance(HDUlist_or_filename, fits.HDUList):
        HDUlist = HDUlist_or_filename
    else: raise ValueError("input must be a filename or HDUlist")

    image = HDUlist[ext].data
    header = HDUlist[ext].header

    if image.ndim >=3:  # handle datacubes gracefully
        image = image[slice,:,:]


    if center is None:
        # get exact center of image
        #center = (image.shape[1]/2, image.shape[0]/2)
        center = tuple( (a-1)/2.0 for a in image.shape[::-1])



    # Compute a comparison image
    _log.info("Now computing image with zero OPD for comparison...")
    inst = Instrument(header['INSTRUME'])
    inst.filter = header['FILTER']
    inst.pupilopd = None # perfect image
    inst.include_si_wfe = False # perfect image
    inst.pixelscale = header['PIXELSCL'] * header['OVERSAMP'] # same pixel scale pre-oversampling
    cache_key = (header['INSTRUME'], header['FILTER'], header['PIXELSCL'], header['OVERSAMP'],  header['FOV'],header['NWAVES'])
    try:
        comparison_psf = _Strehl_perfect_cache[cache_key]
    except KeyError:
        comparison_psf = inst.calcPSF(fov_arcsec = header['FOV'], oversample=header['OVERSAMP'], nlambda=header['NWAVES'])
        if cache_perfect: _Strehl_perfect_cache[cache_key ] = comparison_psf

    comparison_image = comparison_psf[0].data

    if (int(center[1]) == center[1]) and (int(center[0]) == center[0]):
        # individual pixel
        meas_peak =           image[center[1], center[0]]
        ref_peak = comparison_image[center[1], center[0]]
    else:
        # average across a group of 4
        bot = [np.floor(f) for f in center]
        top = [np.ceil(f)+1 for f in center]
        meas_peak =           image[bot[1]:top[1], bot[0]:top[0]].mean()
        ref_peak = comparison_image[bot[1]:top[1], bot[0]:top[0]].mean()
    strehl = (meas_peak/ref_peak)

    if display:
        plt.clf()
        plt.subplot(121)
        display_PSF(HDUlist, title="Observed PSF")
        plt.subplot(122)
        display_PSF(comparison_psf, title="Perfect PSF")
        plt.gcf().suptitle("Strehl ratio = %.3f" % strehl)


    if verbose:
        print("Measured peak:  {0:.3g}".format(meas_peak))
        print("Reference peak: {0:.3g}".format(ref_peak))
        print("  Strehl ratio: {0:.3f}".format(strehl))

    return strehl
Example #18
0
def test_ThinLens(display=False):
    pupil_radius = 1

    # let's add < 1 wave here so we don't have to worry about wrapping
    lens = optics.ThinLens(nwaves=0.5,
                           reference_wavelength=1e-6,
                           radius=pupil_radius)
    # n.b. npix is 99 so that there are an integer number of pixels per meter (hence multiple of 3)
    # and there is a central pixel at 0,0 (hence odd npix)
    # Otherwise the strict test against half a wave min max doesn't work
    # because we're missing some (tiny but nonzero) part of the aperture
    wave = poppy_core.Wavefront(npix=99, diam=3.0, wavelength=1e-6)
    wave *= lens

    # Now test the values at some precisely chosen pixels
    y, x = wave.coordinates()
    at_radius = np.where((x == 1) & (y == 0))
    assert np.allclose(wave.phase[at_radius],
                       -np.pi / 2), "Didn't get -1/2 wave OPD at edge of optic"
    assert len(
        at_radius[0]
    ) > 0, "Array indices messed up - need to have a pixel at exactly (1,0)"

    at_radius = np.where((x == 0) & (y == 1))
    assert np.allclose(wave.phase[at_radius],
                       -np.pi / 2), "Didn't get -1/2 wave OPD at edge of optic"
    assert len(
        at_radius[0]
    ) > 0, "Array indices messed up - need to have a pixel at exactly (0,1)"

    at_center = np.where((x == 0) & (y == 0))
    assert np.allclose(wave.phase[at_center],
                       np.pi / 2), "Didn't get 1/2 wave OPD at center of optic"
    assert len(
        at_radius[0]
    ) > 0, "Array indices messed up - need to have a pixel at exactly (0,0)"

    # TODO test intermediate pixel values between center and edge?

    # regression test to ensure null optical elements don't change ThinLens behavior
    # see https://github.com/mperrin/poppy/issues/14
    osys = poppy_core.OpticalSystem()
    osys.add_pupil(optics.CircularAperture(radius=1))
    for i in range(3):
        osys.add_image()
        osys.add_pupil()

    osys.add_pupil(
        optics.ThinLens(nwaves=0.5,
                        reference_wavelength=1e-6,
                        radius=pupil_radius))
    osys.add_detector(pixelscale=0.01, fov_arcsec=3.0)
    psf = osys.calc_psf(wavelength=1e-6)

    osys2 = poppy_core.OpticalSystem()
    osys2.add_pupil(optics.CircularAperture(radius=1))
    osys2.add_pupil(
        optics.ThinLens(nwaves=0.5,
                        reference_wavelength=1e-6,
                        radius=pupil_radius))
    osys2.add_detector(pixelscale=0.01, fov_arcsec=3.0)
    psf2 = osys2.calc_psf()

    if display:
        import poppy
        poppy.display_PSF(psf)
        poppy.display_PSF(psf2)

    assert np.allclose(psf[0].data, psf2[0].data), (
        "ThinLens shouldn't be affected by null optical elements! Introducing extra image planes "
        "made the output PSFs differ beyond numerical tolerances.")
Example #19
0
def measure_strehl(HDUlist_or_filename=None,
                   ext=0,
                   slice=0,
                   center=None,
                   display=True,
                   verbose=True,
                   cache_perfect=False):
    """ Estimate the Strehl ratio for a PSF.

    This requires computing a simulated PSF with the same
    properties as the one under analysis.

    Note that this calculation will not be very accurate unless both PSFs are well sampled,
    preferably several times better than Nyquist. See
    `Roberts et al. 2004 SPIE 5490 <http://adsabs.harvard.edu/abs/2004SPIE.5490..504R>`_
    for a discussion of the various possible pitfalls when calculating Strehl ratios.

    WARNING: This routine attempts to infer how to calculate a perfect reference
    PSF based on FITS header contents. It will likely work for simple direct imaging
    cases with WebbPSF but will not work (yet) for more complicated cases such as
    coronagraphy, anything with image or pupil masks, etc. Code contributions to add
    such cases are welcomed.


    Parameters
    ----------
    HDUlist_or_filename : string
        Either a fits.HDUList object or a filename of a FITS file on disk
    ext : int
        Extension in that FITS file
    slice : int, optional
        If that extension is a 3D datacube, which slice (plane) of that datacube to use
    center : tuple
        center to compute around.  Default is image center. If the center is on the
        crosshairs between four pixels, then the mean of those four pixels is used.
        Otherwise, if the center is in a single pixel, then that pixel is used.
    verbose, display : bool
        control whether to print the results or display plots on screen.

    cache_perfect : bool
        use caching for perfect images? greatly speeds up multiple calcs w/ same config

    Returns
    ---------
    strehl : float
        Strehl ratio as a floating point number between 0.0 - 1.0

    """

    from .webbpsf_core import Instrument
    from poppy import display_PSF

    if isinstance(HDUlist_or_filename, six.string_types):
        HDUlist = fits.open(HDUlist_or_filename)
    elif isinstance(HDUlist_or_filename, fits.HDUList):
        HDUlist = HDUlist_or_filename
    else:
        raise ValueError("input must be a filename or HDUlist")

    image = HDUlist[ext].data
    header = HDUlist[ext].header

    if image.ndim >= 3:  # handle datacubes gracefully
        image = image[slice, :, :]

    if center is None:
        # get exact center of image
        #center = (image.shape[1]/2, image.shape[0]/2)
        center = tuple((a - 1) / 2.0 for a in image.shape[::-1])

    # Compute a comparison image
    _log.info("Now computing image with zero OPD for comparison...")
    inst = Instrument(header['INSTRUME'])
    inst.filter = header['FILTER']
    inst.pupilopd = None  # perfect image
    inst.include_si_wfe = False  # perfect image
    inst.pixelscale = header['PIXELSCL'] * header[
        'OVERSAMP']  # same pixel scale pre-oversampling
    cache_key = (header['INSTRUME'], header['FILTER'], header['PIXELSCL'],
                 header['OVERSAMP'], header['FOV'], header['NWAVES'])
    try:
        comparison_psf = _Strehl_perfect_cache[cache_key]
    except KeyError:
        comparison_psf = inst.calcPSF(fov_arcsec=header['FOV'],
                                      oversample=header['OVERSAMP'],
                                      nlambda=header['NWAVES'])
        if cache_perfect: _Strehl_perfect_cache[cache_key] = comparison_psf

    comparison_image = comparison_psf[0].data

    if (int(center[1]) == center[1]) and (int(center[0]) == center[0]):
        # individual pixel
        meas_peak = image[center[1], center[0]]
        ref_peak = comparison_image[center[1], center[0]]
    else:
        # average across a group of 4
        bot = [np.floor(f) for f in center]
        top = [np.ceil(f) + 1 for f in center]
        meas_peak = image[bot[1]:top[1], bot[0]:top[0]].mean()
        ref_peak = comparison_image[bot[1]:top[1], bot[0]:top[0]].mean()
    strehl = (meas_peak / ref_peak)

    if display:
        plt.clf()
        plt.subplot(121)
        display_PSF(HDUlist, title="Observed PSF")
        plt.subplot(122)
        display_PSF(comparison_psf, title="Perfect PSF")
        plt.gcf().suptitle("Strehl ratio = %.3f" % strehl)

    if verbose:
        print("Measured peak:  {0:.3g}".format(meas_peak))
        print("Reference peak: {0:.3g}".format(ref_peak))
        print("  Strehl ratio: {0:.3f}".format(strehl))

    return strehl
Example #20
0
def validate_vs_krist_sims(clobber=False, normalize=False, which='spot', no_sam=False):
    """ Compare with PSFs provided by John Krist
    """


    if which=='spot':
        image_mask =  'MASK430R'
        pupil_mask = 'CIRCLYOT'
    else:
        image_mask =  'MASKLWB'
        pupil_mask = 'WEDGELYOT'

    P.subplots_adjust(left=0.07, right=0.95, top=0.9, bottom=0.05)

    nc = webbpsf_core.NIRCam()
    nc.pupilopd=None
    nc.filter = 'F460M'
    nc.image_mask = image_mask
    nc.pupil_mask = pupil_mask
    nc.options['no_sam'] = no_sam
    nc.pixelscale = 0.065 # match the Krist sims exacly. vs 0.648 official

    cor_vmin = 1e-12
    cor_vmax=1e-5


    P.clf()

    fig = P.gcf()
    fig.text(0.2, 0.95, 'Krist', horizontalalignment='center', size=18)
    fig.text(0.50, 0.95, 'Perrin', horizontalalignment='center', size=18)
    fig.text(0.80, 0.95, 'Difference P-K', horizontalalignment='center', size=18)

    fig.text(0.05, 1./6, 'off-axis 4.6$\mu$m', verticalalignment='center', rotation='vertical' , size=18)
    fig.text(0.05, 0.48, 'occulted 4.6$\mu$m', verticalalignment='center', rotation='vertical' , size=18)
    fig.text(0.05, 5./6-0.05, image_mask + ' occulter', verticalalignment='center', rotation='vertical' , size=18)


    P.subplot(331)
    mask1 = 'nircam_4600nm_%s_occ.fits' % which
    mask1f = fits.open(mask1)
    poppy.display_PSF(mask1f, title="", pixelscale='PIXSIZE', vmin=0, vmax=1, scale='linear', cmap=matplotlib.cm.gray)

    P.subplot(332)
    os = nc._get_optical_system()
    os.planes[1].display(ax=P.gca(),  what='intensity', colorbar_orientation='vertical')
    P.gca().set_title('')
    P.gca().set_xbound(-8,8)
    P.gca().set_ybound(-8,8)

    wf = poppy.Wavefront(wavelength=4.6e-6,  npix = mask1f[0].data.shape[0], pixelscale = mask1f[0].header['PIXSIZE'])
    trans = os.planes[1].getPhasor(wf)**2

    P.subplot(333)

    if normalize:
        to_plot = (trans-mask1f[0].data) / (trans+mask1f[0].data)/2
        vmin, vmax = -1, 1
    else:
        to_plot = (trans-mask1f[0].data)
        vmin, vmax = -1e-3, 1e-3

    poppy.imshow_with_mouseover(to_plot, cmap=matplotlib.cm.gray, vmin=vmin, vmax=vmax, extent=[-8, 8, -8, 8])
    P.colorbar(P.gca().images[0], orientation='vertical')
    try:
        fits.PrimaryHDU(trans).writeto('test_nircam_4600nm_%s_occ.fits' % which, clobber=clobber)
    except:
        pass





    #---- occulted --
    P.subplot(334)
    k1 = 'nircam_4600nm_%s.fits' % which
    k1f = fits.open(k1)

    print("Total of %s is %f" % (k1, k1f[0].data.sum()))
    poppy.display_PSF(k1f,  title="", pixelscale='SAMPLING', vmin=cor_vmin, vmax=cor_vmax)

    P.subplot(335)
    my1 = 'test_'+k1
    mypsf1 = webbpsf_core.calc_or_load_psf('test_'+k1, nc, nlambda=1,monochromatic=4.6e-6, oversample=4, fov_pixels=247, clobber=clobber)
    print("Total of %s is %f" % (my1, mypsf1[0].data.sum()))
    #nc.calcPSF(nlambda=1)
    poppy.display_PSF(mypsf1, ext=1, title="", adjust_for_oversampling=True, vmin=cor_vmin, vmax=cor_vmax)

    P.subplot(336)
    poppy.display_PSF_difference( mypsf1, k1f,  ext2=0, ext1=1, title="", vmax=1e-7, normalize=normalize)


    #---- unocculted --
    P.subplot(337)
    k2 = 'nircam_4600nm_%s_fieldpsf.fits' % which
    k2f = fits.open(k2)
    poppy.display_PSF(k2f,  title="", pixelscale='SAMPLING')
    print("Total of %s is %f" % (k2, k2f[0].data.sum()))


    nc.image_mask = None # make a coronagraphic-off-axis type PSF but still on-axis in the array
    my2 = 'test_'+k2
    mypsf2 = webbpsf_core.calc_or_load_psf('test_'+k2, nc, nlambda=1, monochromatic=4.6e-6, oversample=4, fov_pixels=247, clobber=clobber)
    P.subplot(338)
    poppy.display_PSF(mypsf2,  title="", ext=1, adjust_for_oversampling=True)
    print("Total of %s is %f" % (my2, mypsf2[0].data.sum()))

    P.subplot(339)
    poppy.display_PSF_difference( mypsf2, k2f,  ext2=0, ext1=1, title="", vmax=1e-5, normalize=normalize)



    print("shape of %s is %s" % (k1, k1f[0].data.shape))
    print("shape of %s is %s" % (my1, mypsf1[1].data.shape))

    P.savefig('results_nircam_coron_comparison_%s.pdf' % which)
    stop()
Example #21
0
def validate_vs_jwpsf_nircam():
    """ Compare results from WebbPSF with earlier simulations produced with JWPSF
    """

    models = [ ('NIRCam','F200W', 'f200w_perfect_offset', '/Users/mperrin/software/jwpsf_v3.0/data/NIRCam/OPD/perfect_opd.fits', 0.034,True),
            ('NIRCam','F200W', 'f200w_perfect', '/Users/mperrin/software/jwpsf_v3.0/data/NIRCam/OPD/perfect_opd.fits', 0.034,False),
            ('NIRCam','F200W', 'f200w', '/Users/mperrin/software/jwpsf_v3.0/data/NIRCam/OPD/nircam_obs_w_rsrv1.fits', 0.034,True),
                ('MIRI','F1000W', 'f1000w', '/Users/mperrin/software/jwpsf_v3.0/data/MIRI/OPD/MIRI_OPDisim1.fits', 0.11,True)]


    fig = P.figure(1, figsize=(13,8.5), dpi=80)
    oversamp=4
    for params in models:

        nc = webbpsf_core.Instrument(params[0])
        nc.filter = params[1]
        nc.pupilopd = params[3] #'/Users/mperrin/software/jwpsf_v3.0/data/NIRCam/OPD/nircam_obs_w_rsrv1.fits'
        nc.pixelscale = params[4] #0.034 # this is wrong, but compute this way to match JWPSF exactly
        if params[5]:
            # offset by half a pixel to match the JWPSF convention
            nc.options['source_offset_r'] = params[4]/2 * N.sqrt(2)/oversamp  # offset half a pixel each in X and Y
            nc.options['source_offset_theta'] = -45


        jw_fn = 'jwpsf_%s_%s.fits' % (params[0].lower(), params[2].lower())
        my_fn = 'test_vs_' + jw_fn

        if not os.path.exists( my_fn):
            my_psf = nc.calcPSF(my_fn, oversample=oversamp, fov_pixels=512./oversamp)
        else:
            my_psf = fits.open(my_fn)

        jw_psf = fits.open(jw_fn)
        jw_psf[0].header.update('PIXELSCL', jw_psf[0].header['CDELT1']*3600)


        P.clf()
        #P.subplots_adjust(top=0.95, bottom=0.05, left=0.01, right=0.99)
        P.subplot(231)
        titlestr = "%s %s, \n"%  (params[0], params[2])
        poppy.display_PSF(my_psf, title=titlestr+"computed with WebbPSF" , colorbar=False)
        P.subplot(232)
        poppy.display_PSF(jw_psf, title=titlestr+"computed with JWPSF" , colorbar=False)
        P.subplot(233)
        poppy.display_PSF_difference(my_psf,jw_psf, title=titlestr+'Difference Image', colorbar=False)

        imagecrop = 30*params[4]

        P.subplot(234)
        poppy.display_PSF(my_psf, title=titlestr+"computed with WebbPSF", colorbar=False, imagecrop=imagecrop)
        centroid = poppy.measure_centroid(my_psf)
        P.gca().set_xlabel("centroid = (%.3f,%.3f)" % centroid)

        P.subplot(235)
        poppy.display_PSF(jw_psf, title=titlestr+"computed with JWPSF", colorbar=False, imagecrop=imagecrop)
        centroid = poppy.measure_centroid(jw_psf)
        P.gca().set_xlabel("centroid = (%.3f,%.3f)" % centroid)

        P.subplot(236)
        poppy.display_PSF_difference(my_psf,jw_psf, title='Difference Image', colorbar=False, imagecrop=imagecrop)

        P.savefig("results_vs_jwpsf_%s_%s.pdf" % (params[0], params[2]))
Example #22
0
def make_fig_instrument_comparison():
    """ Make the instrument comparison figure for the webbPSF web page.
    Argh I already wrote this once, now I need to write it again 'cause I can't find it...
    """

    # make figure size = array([ 14.325,   2.975]) in inches

    
    plt.clf()
    f, axarr = plt.subplots(1, 6, sharex=True, num=1, sharey=True)

    nc = webbpsf.NIRCam()
    nc.filter='F210M'
    webbpsf.calc_or_load_PSF('NIRCam_demo_F212.fits', nc, oversample=4, rebin=True, fov_arcsec=5)
    poppy.display_PSF('NIRCam_demo_F212.fits', ext=1, ax= axarr[0], colorbar=False, title="NIRCam F210M")

    nc = webbpsf.NIRCam()
    nc.filter='F444W'
    webbpsf.calc_or_load_PSF('NIRCam_demo_F444.fits', nc, oversample=4, rebin=True, fov_arcsec=5)
    poppy.display_PSF('NIRCam_demo_F444.fits', ext=1, ax= axarr[1], colorbar=False, title="NIRCam F444W")

    ns = webbpsf.NIRSpec()
    ns.filter='F110W'
    webbpsf.calc_or_load_PSF('NIRSpec_demo.fits', ns, oversample=4, rebin=True, fov_arcsec=5)
    poppy.display_PSF('NIRSpec_demo.fits', ext=1, ax= axarr[2], colorbar=False, title="NIRspec F110W")

    ni = webbpsf.NIRISS()
    ni.filter='F380M'
    webbpsf.calc_or_load_PSF('NIRISS_demo.fits', ni, oversample=4, rebin=True, fov_arcsec=5)
    poppy.display_PSF('NIRISS_demo.fits', ext=1, ax= axarr[3], colorbar=False, title="NIRISS F380M")


    mi = webbpsf.MIRI()
    mi.filter='F1000W'
    webbpsf.calc_or_load_PSF('MIRI_demo.fits', mi, oversample=4, rebin=True, fov_arcsec=5)
    poppy.display_PSF('MIRI_demo.fits', ext=1, ax= axarr[4], colorbar=False, title="MIRI F1000W")

    fg = webbpsf.FGS()
    webbpsf.calc_or_load_PSF('FGS_demo.fits', fg, oversample=4, rebin=True, fov_arcsec=5)
    poppy.display_PSF('FGS_demo.fits', ext=1, ax= axarr[5], colorbar=False, title="FGS")


    plt.subplots_adjust(hspace=0.01)
    for ax in axarr:
        ax.set_ylim(-2.5, 2.5)
        ax.set_xlim(-2.5, 2.5)


    plt.savefig('fig_instrument_comparison.pdf')
Example #23
0
def compare_pupils_tv( oversample=8, vmax=1e-5, skipone=True):
    """
    Compare PSFs with the Rev T and Rev V pupil shapes
    """
    P.clf()
    inst = webbpsf_core.NIRCam()
    inst.pupilopd=None

    fov_arcsec = 10
    nlambda=30

    inst.pupil = 'tricontagon.fits'
    psf_tri = webbpsf_core.calc_or_load_psf('test_NIRCam_perfect_tricontagon_o%d.fits' % oversample, inst, nlambda=nlambda, oversample=oversample, fov_arcsec=fov_arcsec)


    if not skipone:
        ax = P.subplot(1,3,1)
        poppy.display_PSF(psf_tri, normalize='peak', colorbar=False, title='Tricontagon')


        for i, rev in enumerate(['T','V']):
            inst.pupil = "pupil_Rev%s.fits" % rev
            psf = webbpsf_core.calc_or_load_psf('test_NIRCam_perfect_rev%s_o%d.fits'  % (rev, oversample),inst,  nlambda=nlambda, oversample=oversample, fov_arcsec=fov_arcsec)
            P.subplot(1,3,i+2)
            poppy.display_PSF(psf, normalize='peak', colorbar = (rev =='V'), title='OTE Rev '+rev)


        stop()
        P.clf()

    psf_V = fits.open('test_NIRCam_perfect_rev%s_o%d.fits'  % ('V', oversample))
    psf_T = fits.open('test_NIRCam_perfect_rev%s_o%d.fits'  % ('T', oversample))
    P.subplot(221)
    poppy.display_PSF_difference(psf_V, psf_tri, vmax=vmax, title="Rev V - tricontagon")
    P.subplot(222)
    poppy.display_PSF_difference(psf_V, psf_T,vmax=vmax, title="Rev V - Rev T")


    ax3 = P.subplot(223)
    ax3.set_ylabel('Azimuthally averaged profile')
    ax3.set_xlabel('Separation (arcsec)')

    ax4 = P.subplot(224)
    ax4.set_ylabel('Fractional Encircled Energy')
    ax4.set_xlabel('Separation (arcsec)')


    for p, label in zip([psf_tri, psf_T, psf_V], ['Tri', "Rev T", 'Rev V']):
        rad, rp = poppy.radial_profile(p)
        ee_fn = poppy.measure_EE(p)

        ax3.plot(rad,rp/rp.max())
        ax4.plot(rad, ee_fn(rad), label=label)

        print(poppy.measure_fwhm(p))
    ax4.legend(loc='lower right')
    ax3.set_yscale('log')
    ax3.set_xscale('log')
    #ax3.axhline([psf_V[0].data.max()*0.5], ls=":")

    #ax3.set_xbound(0,4)
    ax3.set_xbound(0.01,4)
    ax4.set_xbound(0,4)
    P.draw()


    stop()