def setUp(self):

        self.holeshape = "hex"

        # directory containing the test data
        data_dir = os.path.join(os.path.dirname(__file__),
                                'test_data/find_affine2d_parameters')
        self.data_dir = data_dir
        print(data_dir)
        if not os.path.exists(data_dir):
            os.makedirs(data_dir)

        pixel = 0.0656 * u.arcsec.to(u.rad)
        npix = 87
        wave = np.array([
            (1.0, 4.3e-6),
        ])  # m
        over = 3
        holeshape = 'hex'

        rotd_true = 9.25
        rotdegs = (8.0, 9.0, 10.0, 11.0, 12.0
                   )  # search in this range of rotation (degrees)

        # store the real affine to be uased to create test data
        self.affine = utils.Affine2d(
            rotradccw=np.pi * utils.avoidhexsingularity(rotd_true) / 180.0,
            name="{0:.4}".format(float(rotd_true)))
        self.affine.show(label="Creating affine2d for PSF data")

        # create image data to find its rotation, as a sample test...
        imagefn = data_dir + "/imagedata.fits"
        jw = NRM_Model(mask='jwst', holeshape="hex", affine2d=self.affine)
        jw.set_pixelscale(pixel)
        jw.simulate(fov=npix, bandpass=wave, over=over)
        fits.writeto(imagefn, jw.psf, overwrite=True)
        imagedata = jw.psf.copy()
        del jw
        fits.getdata(imagefn)
        psf_offset = (0.0, 0.0)
        print("driver:", rotdegs)
        mx, my, sx, sy, xo, yo, = (1.0, 1.0, 0.0, 0.0, 0.0, 0.0)
        aff_best_rot = FAP.find_rotation(imagedata,
                                         psf_offset,
                                         rotdegs,
                                         mx,
                                         my,
                                         sx,
                                         sy,
                                         xo,
                                         yo,
                                         pixel,
                                         npix,
                                         wave,
                                         over,
                                         holeshape,
                                         outdir=data_dir)

        print(aff_best_rot)
        self.aff_best_rot = aff_best_rot
def test_offset_residuals():
    """
    Use same affine object for simulation and analysis
    """
    pixelscale_as = 0.0656
    arcsec2rad = u.arcsec.to(u.rad)

    #psf_offsets = ((0,0), (1.0,0), )

    #psf_offsets = ((0,0), (1.0,0), (0, 1.0), (1.0,1.0))

    bandpass = np.array([
        (1.0, 4.3e-6),
    ])
    # Loop over psf_offsets

    jw = NRM_Model(mask='jwst', holeshape='hex')
    jw.set_pixelscale(pixelscale_as * arcsec2rad)

    jw.simulate(fov=35,
                bandpass=bandpass,
                over=oversample,
                psf_offset=psf_offsets)
    fits.writeto(fitsimdir + "offset_data.fits", jw.psf, overwrite=True)

    jw.make_model(fov=35,
                  bandpass=bandpass,
                  over=oversample,
                  psf_offset=psf_offsets)

    jw.fit_image(jw.psf, modelin=jw.model)
    fits.writeto(fitsimdir + "residual_offset.fits",
                 jw.residual,
                 overwrite=True)
Example #3
0
def create_data(imdir, rot, ov):
    """ imdir: directory for simulated fits image data
        rot: pupil rotation in degrees
        ov: oversample for simulation
        Writes sim data to fitsimdir
    """
    npix = 81
    wave = 4.3e-6  # SI 
    fnfmt = '/psf_nrm_{2:.1f}_{0}_{1}_rot{3:.3f}d.fits' # expects strings of  %(npix, holeshape, wave/um, rot_d)

    rot = utils.avoidhexsingularity(rot) # in utils
    affine_rot = utils.Affine2d(rotradccw=np.pi*rot/180.0, name="rot{0:.3f}d".format(rot)) # in utils

    jw = NRM_Model(mask='jwst', holeshape='hex', affine2d=affine_rot)
    jw.set_pixelscale(PIXELSCALE_r)
    jw.simulate(fov=81, bandpass=MONOF430M, over=ov)

    psffn = fnfmt.format(npix, 'hex', wave/um, rot)
    fits.writeto(imdir+psffn, jw.psf, overwrite=True)
    header = fits.getheader(imdir+psffn)
    header = utils.affinepars2header(header, affine_rot)
    fits.update(imdir+psffn, jw.psf, header=header)
    del jw

    return psffn  # filename only, not full path
def find_rotation(
        imagedata,
        rotdegs,
        mx,
        my,
        sx,
        sy,
        xo,
        yo,  # for Affine2d
        pixel,
        npix,
        bandpass,
        over,
        holeshape,
        outdir=None):  # for nrm_model
    """ AS AZG 2018 08 Ann Arbor Develop the rotation loop first """

    vprint("Before Loop: ", rotdegs)

    #Extend this name to include multi-paramater searches?
    psffmt = 'psf_nrm_{0:d}_{1:s}_{2:.3f}um_r{3:.3f}deg.fits'
    # expect (npix, holeshape, bandpass/um, scl)

    if hasattr(rotdegs, '__iter__') is False:
        rotdegs = (rotdegs, )

    affine2d_list = create_afflist_rot(rotdegs, mx, my, sx, sy, xo, yo)
    crosscorr_rots = []

    for (rot, aff) in zip(rotdegs, affine2d_list):

        vprint(aff.name + "...")
        jw = NRM_Model(mask='jwst',
                       holeshape=holeshape,
                       over=over,
                       affine2d=aff)
        jw.set_pixelscale(pixel)
        jw.simulate(fov=npix, bandpass=bandpass, over=over)
        psffn = psffmt.format(npix, holeshape, bandpass / um, rot)
        if outdir:
            fits.PrimaryHDU(data=jw.psf).writeto(outdir + "/" + psffn,
                                                 overwrite=True)
            fits.writeto(psffn, jw.psf, overwrite=True)
            header = fits.getheader(psffn)
            utils.affinepars2header(header, aff)
            fits.update(psffn, jw.psf, header=header)

        crosscorr_rots.append(utils.rcrosscorrelate(imagedata, jw.psf).max())
        del jw

    vprint("Debug: ", crosscorr_rots, rotdegs)
    rot_measured_d, max_cor = utils.findpeak_1d(crosscorr_rots, rotdegs)
    vprint("Rotation measured: max correlation {1:.3e}", rot_measured_d,
           max_cor)

    # return convenient affine2d
    return utils.Affine2d(rotradccw=np.pi * rot_measured_d / 180.0,
                          name="{0:.4f}".format(rot_measured_d))
Example #5
0
def simulate_data(affine2d=None):

    print(" simulate_data: ")
    jw = NRM_Model(mask='jwst', holeshape="hex")
    jw.simulate(fov=fov,
                bandpass=bandpass,
                over=oversample,
                psf_offset=psf_offset_det)
    fits.PrimaryHDU(data=jw.psf).writeto(fitsimdir + "all_effects_data.fits",
                                         overwrite=True)

    #**********Convert simulated data to mirage format.*******
    utils.amisim2mirage(fitsimdir, ("all_effects_data", ), mirexample, filt)
Example #6
0
def simulate_data(affine2d=None, psf_offset_det=None, pistons_w=None):

    np.set_printoptions(precision=4, formatter={'float': lambda x: '{:+.1e}'.format(x)}, linewidth=80)
    default_printoptions()


    #***********ADD EFFECTS TO SIMULATE*******************
    jw = NRM_Model(mask='jwst', holeshape="hex", affine2d=affine2d)
    jw.set_pixelscale(pixelscale_as*arcsec2rad)
    jw.simulate(fov=fov, bandpass=bandpass, over=oversample)
    fits.PrimaryHDU(data=jw.psf).writeto(fitsimdir+"all_effects_data.fits",overwrite=True)

    #**********Convert simulated data to mirage format.*******
    utils.amisim2mirage(fitsimdir, ("all_effects_data",), mirexample, filt)
Example #7
0
def simulate_data(affine2d=None, psf_offset_det=None, pistons_w=None):

    print(" simulate_data: ", affine2d.name)

    #************ADD PISTONS TO PERFECT DATA******************
    pistons_w = pistons_w - pistons_w.mean()
    pistons_m = pistons_w * lamc
    pistons_r = pistons_w * 2.0 * np.pi

    utils.show_pistons_w(pistons_w, str="simulate_data: input pistons")

    np.set_printoptions(precision=4,
                        formatter={'float': lambda x: '{:+.1e}'.format(x)},
                        linewidth=80)
    print(" simulate_data: pistons_um", pistons_m / 1e-6)
    print(" simulate_data: pistons_r", pistons_r)
    print(" simulate_data: pistons_w stdev/w", round(pistons_w.std(), 4))
    print(" simulate_data: pistons_w stdev/r",
          round(pistons_w.std() * 2 * np.pi, 4))
    print(" simulate_data: pistons_w mean/r",
          round(pistons_w.mean() * 2 * np.pi, 4))
    default_printoptions()

    #***********ADD EFFECTS TO SIMULATE*******************
    jw = NRM_Model(mask='jwst', holeshape="hex", affine2d=affine2d)
    jw.set_pixelscale(pixelscale_as * arcsec2rad)
    jw.set_pistons(pistons_m)
    print(" simulate: ", psf_offset_det, type(psf_offset_det))
    jw.simulate(fov=fov,
                bandpass=bandpass,
                over=oversample,
                psf_offset=psf_offset_det)
    fits.PrimaryHDU(data=jw.psf).writeto(fitsimdir + "all_effects_data.fits",
                                         overwrite=True)

    #**********Convert simulated data to mirage format.*******
    utils.amisim2mirage(fitsimdir, ("all_effects_data", ), mirexample, filt)
Example #8
0
class Affine2dMakeModelRotTestCase(unittest.TestCase):
    def setUp(self):

        allholes = ('b4', 'c2', 'b5', 'b2', 'c1', 'b6', 'c6')
        b4, c2, b5, b2, c1, b6, c6 = allholes
        self.hc = (b2, b6, b5)  # holechoices
        self.hstr = holes2string(self.hc)
        self.holeshape = "hex"

        # directory containing the test data
        data_dir = os.path.join(os.path.dirname(__file__),
                                'test_data/affine2d_makemodel_rot')
        self.data_dir = data_dir
        print(data_dir)
        if not os.path.exists(data_dir):
            os.makedirs(data_dir)

    # expects strings of  % (self.npix, self.holeshape, self.wave/um, rot, self.hstr)
        self.fnfmt = data_dir + '/psf_nrm_{2:.1f}_{0}_{1}_{3:.0f}_{4:s}.fits'

        self.fmt = "    ({0:+.3f}, {1:+.3f}) -> ({2:+.3f}, {3:+.3f})"
        self.pixel = 0.0656
        self.npix = 87
        self.wave = 4.3e-6  # m
        self.over = 11

        mx, my = 1.0, 1.0
        sx, sy = 0.0, 0.0
        xo, yo = 0.0, 0.0
        affine_ideal = Affine2d(mx=mx,
                                my=my,
                                sx=sx,
                                sy=sy,
                                xo=xo,
                                yo=yo,
                                name="Ideal")

        rots = (0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75,
                80, 85, 90, 95)
        rots = (
            0.000,
            10.000,
        )
        for rot in rots:

            rot = avoidhexsingularity(rot)  # in utils
            affine_rot = Affine2d(rotradccw=np.pi * rot / 180.0,
                                  name="{0:.0f}".format(rot))  # in utils
            aff = affine_rot

            # holeshape is hex or circ g7s6 jwst
            # because model_array requires
            # a primary beam for one slice of the model
            self.jw = NRM_Model(
                mask='jwst',
                holeshape=self.holeshape,
                #chooseholes=self.hc,
                affine2d=aff)
            self.jw.set_pixelscale(self.pixel * arcsec2rad)
            self.jw.simulate(fov=self.npix, bandpass=self.wave, over=self.over)
            # write psf
            psffn = self.fnfmt.format(self.npix, self.holeshape,
                                      self.wave / um, rot, self.hstr)
            fits.writeto(psffn, self.jw.psf, overwrite=True)
            header = fits.getheader(psffn)
            header = affinepars2header(header, aff)
            fits.update(psffn, self.jw.psf, header=header)
            print("test:  psf shape", self.jw.psf.shape)

            modelslices = self.jw.make_model(fov=self.npix,
                                             bandpass=self.wave,
                                             over=self.over)
            print("test:  modelslices type", type(modelslices))
            print("test:  modelslices shape", modelslices.shape)
            modelfn = psffn.replace("psf_nrm", "model")

            # write model
            model_for_fitsfile = np.zeros(
                (modelslices.shape[2], modelslices.shape[0],
                 modelslices.shape[1]))
            for sl in range(modelslices.shape[2]):
                model_for_fitsfile[sl, :, :] = modelslices[:, :, sl]
            print("test:  model_for_fitsfile type", type(model_for_fitsfile))
            print("test:  model_for_fitsfile shape", model_for_fitsfile.shape)
            fits.writeto(modelfn, model_for_fitsfile[6, :, :], overwrite=True)
            header = fits.getheader(modelfn)
            header = affinepars2header(header, aff)
            fits.update(modelfn, model_for_fitsfile[6, :, :], header=header)

            del self.jw

            del aff
            del affine_rot

    def test_psf(self):
        """ 
            sanity check and code development tool than a routine test.
        """
        self.assertTrue(0.0 < 1e-15, 'error: test_affine2d failed')
    def setUp(self):

        # setup parameters for simulation
        verbose = 1
        overwrite = 1

        monochromatic_wavelength_m = np.array([
            (1.0, 4.3e-6),
        ])
        mask = 'MASK_NRM'
        filter = 'F430M'
        pixel = 0.0656  # arcsec
        filter_name = 'Monochromatic ' + np.str(monochromatic_wavelength_m)

        self.filter = filter
        self.filter_name = filter_name
        self.monochromatic_wavelength_m = monochromatic_wavelength_m

        # directory containing the test data
        datadir = os.path.join(os.path.dirname(__file__),
                               'test_data/find_pass_affine')
        if not os.path.exists(datadir):
            os.makedirs(datadir)
        self.datadir = datadir

        # file containing the test data
        imagefn = datadir + "/simulated_image.fits"
        # use millidegrees and integers
        imagefn = imagefn.replace(
            ".fits",
            "_truerotmd{0:+05d}.fits".format(int(1000.0 * float(rotd_true))))
        self.imagefn = imagefn

        # savedir for reduced quantities
        self.savedir = imagefn.replace(
            ".fits",
            "_truerotmd{0:+05d}.fits".format(int(1000.0 * float(rotd_true))))
        self.savedir = self.datadir + '/'

        print('\n')
        print('  >> >> >> >> set-up  self.imagefn %s' % self.imagefn)
        print('  >> >> >> >> set-up  self.datadir %s' % self.datadir)
        print('  >> >> >> >> set-up  self.savedir %s' % self.savedir)

        # Create test data on disk

        print("avoidhexsingularity:  ", utils.avoidhexsingularity(rotd_true))
        affine = utils.Affine2d(rotradccw=np.pi *
                                utils.avoidhexsingularity(rotd_true) / 180.0,
                                name="{0:.3}".format(float(rotd_true)))
        affine.show(label="Creating PSF data with Affine2d")
        #
        from nrm_analysis.fringefitting.LG_Model import NRM_Model
        jw = NRM_Model(mask='jwst', holeshape="hex", affine2d=affine)
        jw.set_pixelscale(pixel * arcsec2rad)
        jw.simulate(fov=n_image,
                    bandpass=monochromatic_wavelength_m,
                    over=oversample)
        # PSF without oversampling
        fits.writeto(imagefn, jw.psf, overwrite=True)
        header = fits.getheader(imagefn)
        header['PIXELSCL'] = (pixel, "arcseconds")
        header['FILTER'] = filter_name
        header['PUPIL'] = mask
        header = utils.affinepars2header(header, affine)
        fits.update(imagefn, jw.psf, header=header)
        self.simulated_image = jw.psf.copy()
        self.affine = affine  # Affine2d parameters used to create test simulated_image ("true" value)
        del jw
        del affine
def psf(filt, fbp, cw, ew, beta, data_dir,
              oversample = 11, 
              n_image = 81, 
              pixelscale_as=0.0656, 
              f2f = 0.82, 
              saveover=False):
    
    arcsec2rad = u.arcsec.to(u.rad)

    WGHT = fbp[:,0]
    WAVE = fbp[:,1]

    # setup parameters for simulation
    verbose = 1
    overwrite = 1

    mask = 'MASK_NRM'

    # directory containing the test data
    if not os.path.exists(data_dir):
        os.makedirs(data_dir)

    name_seed = 'PSF_%s_%s_x%d_%.2f'%(mask,filt,oversample,f2f) # original
    # only det sampling needed here...
    name_seed = '%s_%d_%s_det.fits'%(filt, n_image, "A0V")  # for ami_sim input photometry in NIRISSami_apt_calcPSF
    name_seed = '%s_%d_%s_x%d.fits'%(filt, n_image, "flat", oversample)  # for ami_sim PSF to give to driver_scene
    name_seed_det = '%s_%d_%s_det.fits'%(filt, n_image, "flat")  # for ami_sim PSF for examining by eye 
    print(name_seed)
    psf_image = os.path.join(data_dir,name_seed)
    psf_image_without_oversampling = os.path.join(data_dir, name_seed_det)

    from nrm_analysis.fringefitting.LG_Model import NRM_Model
    jw = NRM_Model(mask='jwst',holeshape="hex")
    jw.set_pixelscale(pixelscale_as*arcsec2rad)
    jw.simulate(fov=n_image, 
        bandpass=fbp, 
        over=oversample)
    print("simulateG7S6psf: simulation oversampling is", oversample)
    (year, month, day, hour, minute, second, weekday, DOY, DST) =  time.gmtime()

    # oversampled psf is used as the fine psf to create jitter and dither errors. 
    # ami_sim driver scene expects ODD numbers of pixels to a side.
    # We oversize to 81 x 81 pixels here.  
    # When adding mirage headers to ami_sim 'data' we should trim to 80x80.
    # oversampled psf is used as the fine psf to create jitter and dither errors. 

    if saveover:  # oversampled psf is used as the fine psf to createjitter and dither errors. 
        # PSF on oversampled pixels
        psf_over_n =  filt_psftot[filt] * jw.psf_over/jw.psf_over.sum()  # wp psf total ~15%
        fits.writeto(psf_image, psf_over_n, overwrite=True)
        header = fits.getheader(psf_image)
        header['PIXELSCL'] = pixelscale_as/oversample, "arcsec per pixel"
        header['FILTER'] = filt
        header['PUPIL'] = mask 
        header["OVER"] = ( oversample, "oversample")
        header["SPTYPE"] = "FLAT",  "source spectral type unspecified"
        header["NWAVES"] = fbp.shape[0]
        header["WAVELEN"] = cw, "Weighted mean wavelength in meters "
        header["FILT_EW"] = ew, "Filter equiv width"
        header["FILT_BP"] = beta, "Fractional bandpass = WL/EqW"
        for i in range(len(WAVE)):
            header["WAVE%d"%i] = WAVE[i], "Wavelength %d"%i
            header["WGHT%d"%i] = WGHT[i], "Wavelength weight %d"%i
        header["FT"] = ( "analytical", "hexee * fringes")
        header['NRM_GEOM'] =  'G7S6', 'Beaulieu, PGT, AS, active ctrs'
        header['F2F'] = jw.d, "flat2flat hole size m"
        header['NRM_X_A1'] = jw.ctrs[0,0], 'X coordinate (m) of NRM sub-aperture 0'          
        header['NRM_Y_A1'] = jw.ctrs[0,1], 'Y coordinate (m) of NRM sub-aperture 0'         
        header['NRM_X_A2'] = jw.ctrs[1,0], 'X coordinate (m) of NRM sub-aperture 1'          
        header['NRM_Y_A2'] = jw.ctrs[1,1], 'Y coordinate (m) of NRM sub-aperture 1'          
        header['NRM_X_A3'] = jw.ctrs[2,0], 'X coordinate (m) of NRM sub-aperture 2'          
        header['NRM_Y_A3'] = jw.ctrs[2,1], 'Y coordinate (m) of NRM sub-aperture 2'          
        header['NRM_X_A4'] = jw.ctrs[3,0], 'X coordinate (m) of NRM sub-aperture 3'          
        header['NRM_Y_A4'] = jw.ctrs[3,1], 'Y coordinate (m) of NRM sub-aperture 3'          
        header['NRM_X_A5'] = jw.ctrs[4,0], 'X coordinate (m) of NRM sub-aperture 4'          
        header['NRM_Y_A5'] = jw.ctrs[4,1], 'Y coordinate (m) of NRM sub-aperture 4'          
        header['NRM_X_A6'] = jw.ctrs[5,0], 'X coordinate (m) of NRM sub-aperture 5'          
        header['NRM_Y_A6'] = jw.ctrs[5,1], 'Y coordinate (m) of NRM sub-aperture 5'          
        header['NRM_X_A7'] = jw.ctrs[6,0], 'X coordinate (m) of NRM sub-aperture 6'          
        header['NRM_Y_A7'] = jw.ctrs[6,1], 'Y coordinate (m) of NRM sub-aperture 6'   
        header['NORMALIZ'] = 'first', 'PM psf.sum=1, this.sum = mask throughput'
        header['PSFTOT'] = filt_psftot[filt], "sum of webbpsf sim done at 11x over"
        header['PSFPEAK'] = psf_over_n.max()
        header["SRC"] = ( "simulateG7S6psf.py", "ImplaneIA/notebooks/")
        header['AUTHOR'] = '%s@%s' % (os.getenv('USER'), os.getenv('HOST')), 'username@host for calculation'
        header['DATE'] = '%4d-%02d-%02dT%02d:%02d:%02d' %  (year, month, day, hour, minute, second), 'Date of calculation'
        header['F2F'] = (0.82, "flat2flat hole size m")
        fits.update(psf_image, psf_over_n, header=header)

    # PSF on detector pixels
    psf_det_n = filt_psftot[filt] * jw.psf/jw.psf.sum()
    fits.writeto(psf_image_without_oversampling, psf_det_n, overwrite=True)
    header = fits.getheader(psf_image_without_oversampling)
    header['PIXELSCL'] = pixelscale_as, "arcsec per pixel"
    header['FILTER'] = filt
    header['PUPIL'] = mask 
    header["OVER"] = ( oversample, "oversample pre-rebin")
    header["SPTYPE"] = "FLAT", "source spectral type"
    header["NWAVES"] = fbp.shape[0]
    header["WAVELEN"] = cw, "Weighted mean wavelength in meters "
    header["FILT_EW"] = ew, "Filter equiv width"
    header["FILT_BP"] = beta, "Fractional bandpass = WL/EqW"
    for i in range(len(WAVE)):
        header["WAVE%d"%i] = WAVE[i], "Wavelength %d"%i
        header["WGHT%d"%i] = WGHT[i], "Wavelength weight %d"%i
    header["FT"] = ( "analytical", "hexee * fringes")
    header['NRM_GEOM'] =  'G7S6', 'Beaulieu, PGT, AS active ctrs'
    header['F2F'] = jw.d, "flat2flat hole size m"
    header['NRM_X_A1'] = jw.ctrs[0,0], 'X coordinate (m) of NRM sub-aperture 0'          
    header['NRM_Y_A1'] = jw.ctrs[0,1], 'Y coordinate (m) of NRM sub-aperture 0'         
    header['NRM_X_A2'] = jw.ctrs[1,0], 'X coordinate (m) of NRM sub-aperture 1'          
    header['NRM_Y_A2'] = jw.ctrs[1,1], 'Y coordinate (m) of NRM sub-aperture 1'          
    header['NRM_X_A3'] = jw.ctrs[2,0], 'X coordinate (m) of NRM sub-aperture 2'          
    header['NRM_Y_A3'] = jw.ctrs[2,1], 'Y coordinate (m) of NRM sub-aperture 2'          
    header['NRM_X_A4'] = jw.ctrs[3,0], 'X coordinate (m) of NRM sub-aperture 3'          
    header['NRM_Y_A4'] = jw.ctrs[3,1], 'Y coordinate (m) of NRM sub-aperture 3'          
    header['NRM_X_A5'] = jw.ctrs[4,0], 'X coordinate (m) of NRM sub-aperture 4'          
    header['NRM_Y_A5'] = jw.ctrs[4,1], 'Y coordinate (m) of NRM sub-aperture 4'          
    header['NRM_X_A6'] = jw.ctrs[5,0], 'X coordinate (m) of NRM sub-aperture 5'          
    header['NRM_Y_A6'] = jw.ctrs[5,1], 'Y coordinate (m) of NRM sub-aperture 5'          
    header['NRM_X_A7'] = jw.ctrs[6,0], 'X coordinate (m) of NRM sub-aperture 6'          
    header['NRM_Y_A7'] = jw.ctrs[6,1], 'Y coordinate (m) of NRM sub-aperture 6'   
    header['NORMALIZ'] = 'first', 'PM psf.sum=1, this.sum = mask throughput'
    header['PSFTOT'] = psf_det_n.sum()
    header['PSFPEAK'] = psf_det_n.max()
    header['CPF'] = psf_det_n.max() / psf_det_n.sum(), 'Central pixel fraction'
    header["SRC"] = ( "simulateG7S6psf_for_ami_sim.py", "ImplaneIA/notebooks/")
    header['AUTHOR'] = '%s@%s' % (os.getenv('USER'), os.getenv('HOST')), 'username@host for calculation'
    header['DATE'] = '%4d-%02d-%02dT%02d:%02d:%02d' %  (year, month, day, hour, minute, second), 'Date of calculation'
    fits.update(psf_image_without_oversampling, psf_det_n, header=header)
Example #11
0
def psf(filt, fbp, cw, ew, beta, data_dir,
              oversample = 11, 
              n_image = 81, 
              pixelscale_as=0.0656, 
              f2f = 0.82,
              saveover = True):
    
    arcsec2rad = u.arcsec.to(u.rad)

    WGHT = fbp[:,0]
    WAVE = fbp[:,1]

    # setup parameters for simulation
    verbose = 1
    overwrite = 1

    mask = 'MASK_NRM'

    # directory containing the test data
    if not os.path.exists(data_dir):
        os.makedirs(data_dir)

    name_seed = 'PSF_%s_%s_x%d_%.2f'%(mask,filt,oversample,f2f)

    psf_image_name = name_seed + '_ref.fits'
    psf_image = os.path.join(data_dir,psf_image_name)
    psf_image_without_oversampling = os.path.join(data_dir,psf_image_name.replace('.fits','_det.fits'))

    if (not os.path.isfile(psf_image_without_oversampling)) | (overwrite): 
        from nrm_analysis.fringefitting.LG_Model import NRM_Model
        jw = NRM_Model(mask='jwst',holeshape="hex")
        jw.set_pixelscale(pixelscale_as*arcsec2rad)
        jw.simulate(fov=n_image, 
            bandpass=fbp, 
            over=oversample)
        print("simulateG7S6psf: simulation oversampling is", oversample)
        (year, month, day, hour, minute, second, weekday, DOY, DST) =  time.gmtime()
        # optional writing of oversampled image
        if saveover:
            psf_over_n = jw.psf_over[:80*oversample,:80*oversample]/jw.psf_over[:80*oversample,:80*oversample].sum()
            psf_over_n = psf_over_n * filt_psftot[filt] # "sum of webbpsf sim done at 11x over"
            fits.writeto(psf_image, psf_over_n, overwrite=True)
            header = fits.getheader(psf_image)
            header['PIXELSCL'] = pixelscale_as/oversample, "arcsec per pixel"
            header['FILTER'] = filt
            header['PUPIL'] = mask 
            header["OVER"] = ( oversample, "oversample")
            header["SPTYPE"] = "FLAT",  "source spectral type unspecified"
            header["NWAVES"] = fbp.shape[0]
            header["WAVELEN"] = cw, "Weighted mean wavelength in meters "
            header["FILT_EW"] = ew, "Filter equiv width"
            header["FILT_BP"] = beta, "Fractional bandpass = WL/EqW"
            for i in range(len(WAVE)):
                header["WAVE%d"%i] = WAVE[i], "Wavelength %d"%i
                header["WGHT%d"%i] = WGHT[i], "Wavelength weight %d"%i
            header["FT"] = ( "analytical", "hexee * fringes")
            header['NRM_GEOM'] =  'G7S6', 'Beaulieu, PGT, AS, active ctrs'
            header['F2F'] = jw.d, "flat2flat hole size m"
            header['NRM_X_A1'] = jw.ctrs[0,0], 'X coordinate (m) of NRM sub-aperture 0'          
            header['NRM_Y_A1'] = jw.ctrs[0,1], 'Y coordinate (m) of NRM sub-aperture 0'         
            header['NRM_X_A2'] = jw.ctrs[1,0], 'X coordinate (m) of NRM sub-aperture 1'          
            header['NRM_Y_A2'] = jw.ctrs[1,1], 'Y coordinate (m) of NRM sub-aperture 1'          
            header['NRM_X_A3'] = jw.ctrs[2,0], 'X coordinate (m) of NRM sub-aperture 2'          
            header['NRM_Y_A3'] = jw.ctrs[2,1], 'Y coordinate (m) of NRM sub-aperture 2'          
            header['NRM_X_A4'] = jw.ctrs[3,0], 'X coordinate (m) of NRM sub-aperture 3'          
            header['NRM_Y_A4'] = jw.ctrs[3,1], 'Y coordinate (m) of NRM sub-aperture 3'          
            header['NRM_X_A5'] = jw.ctrs[4,0], 'X coordinate (m) of NRM sub-aperture 4'          
            header['NRM_Y_A5'] = jw.ctrs[4,1], 'Y coordinate (m) of NRM sub-aperture 4'          
            header['NRM_X_A6'] = jw.ctrs[5,0], 'X coordinate (m) of NRM sub-aperture 5'          
            header['NRM_Y_A6'] = jw.ctrs[5,1], 'Y coordinate (m) of NRM sub-aperture 5'          
            header['NRM_X_A7'] = jw.ctrs[6,0], 'X coordinate (m) of NRM sub-aperture 6'          
            header['NRM_Y_A7'] = jw.ctrs[6,1], 'Y coordinate (m) of NRM sub-aperture 6'   
            header['PSFTOT'] = filt_psftot[filt], "sum of webbpsf sim done at 11x over"
            header['PSFPEAK'] = psf_over_n.max()
            header["SRC"] = ( "simulateG7S6psf.py", "ImplaneIA/notebooks/")
            header['AUTHOR'] = '%s@%s' % (os.getenv('USER'), os.getenv('HOST')), 'username@host for calculation'
            header['DATE'] = '%4d-%02d-%02dT%02d:%02d:%02d' %  (year, month, day, hour, minute, second), 'Date of calculation'
            header['F2F'] = (0.82, "flat2flat hole size m")
            fits.update(psf_image, psf_over_n, header=header)
        # PSF without oversampling
        psf_det_n = jw.psf[:80,:80]/jw.psf[:80,:80].sum()  # we can delete this line but I'm in a hurry...
        webbpsfnorm = filt_cpf[filt] / psf_det_n.max()
        psf_det_n = psf_det_n * webbpsfnorm # forces central pixel values to agree ^see above
        fits.writeto(psf_image_without_oversampling, psf_det_n, overwrite=True)
        header = fits.getheader(psf_image_without_oversampling)
        header['PIXELSCL'] = pixelscale_as, "arcsec per pixel"
        header['FILTER'] = filt
        header['PUPIL'] = mask 
        header["OVER"] = ( oversample, "oversample pre-rebin")
        header["SPTYPE"] = "FLAT", "source spectral type unspecified"
        header["NWAVES"] = fbp.shape[0]
        header["WAVELEN"] = cw, "Weighted mean wavelength in meters "
        header["FILT_EW"] = ew, "Filter equiv width"
        header["FILT_BP"] = beta, "Fractional bandpass = WL/EqW"
        for i in range(len(WAVE)):
            header["WAVE%d"%i] = WAVE[i], "Wavelength %d"%i
            header["WGHT%d"%i] = WGHT[i], "Wavelength weight %d"%i
        header["FT"] = ( "analytical", "hexee * fringes")
        header['NRM_GEOM'] =  'G7S6', 'Beaulieu, PGT, AS active ctrs'
        header['F2F'] = jw.d, "flat2flat hole size m"
        header['NRM_X_A1'] = jw.ctrs[0,0], 'X coordinate (m) of NRM sub-aperture 0'          
        header['NRM_Y_A1'] = jw.ctrs[0,1], 'Y coordinate (m) of NRM sub-aperture 0'         
        header['NRM_X_A2'] = jw.ctrs[1,0], 'X coordinate (m) of NRM sub-aperture 1'          
        header['NRM_Y_A2'] = jw.ctrs[1,1], 'Y coordinate (m) of NRM sub-aperture 1'          
        header['NRM_X_A3'] = jw.ctrs[2,0], 'X coordinate (m) of NRM sub-aperture 2'          
        header['NRM_Y_A3'] = jw.ctrs[2,1], 'Y coordinate (m) of NRM sub-aperture 2'          
        header['NRM_X_A4'] = jw.ctrs[3,0], 'X coordinate (m) of NRM sub-aperture 3'          
        header['NRM_Y_A4'] = jw.ctrs[3,1], 'Y coordinate (m) of NRM sub-aperture 3'          
        header['NRM_X_A5'] = jw.ctrs[4,0], 'X coordinate (m) of NRM sub-aperture 4'          
        header['NRM_Y_A5'] = jw.ctrs[4,1], 'Y coordinate (m) of NRM sub-aperture 4'          
        header['NRM_X_A6'] = jw.ctrs[5,0], 'X coordinate (m) of NRM sub-aperture 5'          
        header['NRM_Y_A6'] = jw.ctrs[5,1], 'Y coordinate (m) of NRM sub-aperture 5'          
        header['NRM_X_A7'] = jw.ctrs[6,0], 'X coordinate (m) of NRM sub-aperture 6'          
        header['NRM_Y_A7'] = jw.ctrs[6,1], 'Y coordinate (m) of NRM sub-aperture 6'   
        header['PSFTOT'] = psf_det_n.sum()
        header['PSFPEAK'] = psf_det_n.max()
        header['CPF'] = filt_cpf[filt]
        header["SRC"] = ( "simulateG7S6psf.py", "ImplaneIA/notebooks/")
        header['AUTHOR'] = '%s@%s' % (os.getenv('USER'), os.getenv('HOST')), 'username@host for calculation'
        header['DATE'] = '%4d-%02d-%02dT%02d:%02d:%02d' %  (year, month, day, hour, minute, second), 'Date of calculation'
        fits.update(psf_image_without_oversampling, psf_det_n, header=header)
Example #12
0
class Affine2dTestCase(unittest.TestCase):
    def setUp(self):

        # directory containing the test data
        data_dir = os.path.join(os.path.dirname(__file__),
                                'test_data/affine2d_xyscale_psf')
        self.data_dir = data_dir
        print(data_dir)
        if not os.path.exists(data_dir):
            os.makedirs(data_dir)
        self.fnfmt = data_dir + '/psf_nrm_{0:d}_{1:s}_{2:.3f}um_{3:s}.fits'
        # expects e.g. self.fnfmt.format(self.npix, 'hex', self.wave/um, aff.name)

        self.pixel = 0.0656 * u.arcsec.to(u.rad)
        self.npix = 87
        self.wave = np.array([
            (1.0, 4.3e-6),
        ])  # m
        self.over = 1

        ################
        self.pointsfmt = "    ({0:+.3f}, {1:+.3f}) -> ({2:+.3f}, {3:+.3f})"
        self.numtestfmt = "    min: {0:+.1e},  max: {1:+.1e},  avg: {2:+.1e},  sig: {3:+.1e}"  # min max avg stddev
        self.testpoints = (np.array((0, 0)), np.array((1, 0)), np.array(
            (0, 1)), np.array((1, 1)))

        xo, yo = 0.0, 0.0  # always set these for PSFs...

        mx, my = 1.0, 1.0
        sx, sy = 0.0, 0.0
        self.affine_ideal = Affine2d(mx=mx,
                                     my=my,
                                     sx=sx,
                                     sy=sy,
                                     xo=xo,
                                     yo=yo,
                                     name="Ideal")

        mx, my = -1.0, 1.0
        sx, sy = 0.0, 0.0
        self.affine_xrev = Affine2d(mx=mx,
                                    my=my,
                                    sx=sx,
                                    sy=sy,
                                    xo=xo,
                                    yo=yo,
                                    name="Xreverse")

        mx, my = 2.0, 1.0
        sx, sy = 0.0, 0.0
        self.affine_xmag = Affine2d(mx=mx,
                                    my=my,
                                    sx=sx,
                                    sy=sy,
                                    xo=xo,
                                    yo=yo,
                                    name="Xmag")

        mx, my = 1.0, 1.0
        sx, sy = 0.5, 0.0
        self.affine_sigx = Affine2d(mx=mx,
                                    my=my,
                                    sx=sx,
                                    sy=sy,
                                    xo=xo,
                                    yo=yo,
                                    name="Xshear")

        for aff in (self.affine_ideal, self.affine_xrev, self.affine_xmag,
                    self.affine_sigx):

            # circ g7s6 jwst created for info only
            self.jw = NRM_Model(mask='jwst', holeshape="circ", affine2d=aff)
            self.jw.set_pixelscale(self.pixel)
            self.jw.simulate(fov=self.npix, bandpass=self.wave, over=self.over)
            psffn = self.fnfmt.format(self.npix, 'circ',
                                      self.wave[:, 1][0] / um, aff.name)
            fits.writeto(psffn, self.jw.psf, overwrite=True)
            header = fits.getheader(psffn)
            header = affinepars2header(header, aff)
            fits.update(psffn, self.jw.psf, header=header)
            del self.jw

            # circonly g7s6 jwst created for info only
            self.jw = NRM_Model(mask='jwst',
                                holeshape="circonly",
                                affine2d=aff)
            self.jw.set_pixelscale(self.pixel)
            self.jw.simulate(fov=self.npix, bandpass=self.wave, over=self.over)
            psffn = self.fnfmt.format(self.npix, 'circonly',
                                      self.wave[:, 1][0] / um, aff.name)
            fits.writeto(psffn, self.jw.psf, overwrite=True)
            header = fits.getheader(psffn)
            header = affinepars2header(header, aff)
            fits.update(psffn, self.jw.psf, header=header)
            del self.jw

            # hex g7s6 jwst
            self.jw = NRM_Model(mask='jwst', holeshape="hex", affine2d=aff)
            self.jw.set_pixelscale(self.pixel)
            self.jw.simulate(fov=self.npix, bandpass=self.wave, over=self.over)
            psffn = self.fnfmt.format(self.npix, 'hex',
                                      self.wave[:, 1][0] / um, aff.name)
            fits.writeto(psffn, self.jw.psf, overwrite=True)
            header = fits.getheader(psffn)
            header = affinepars2header(header, aff)
            fits.update(psffn, self.jw.psf, header=header)
            del self.jw

            # hexonly g7s6 jwst
            self.jw = NRM_Model(mask='jwst', holeshape="hexonly", affine2d=aff)
            self.jw.set_pixelscale(self.pixel)
            self.jw.simulate(fov=self.npix, bandpass=self.wave, over=self.over)
            psffn = self.fnfmt.format(self.npix, 'hexonly',
                                      self.wave[:, 1][0] / um, aff.name)
            fits.writeto(psffn, self.jw.psf, overwrite=True)
            header = fits.getheader(psffn)
            header = affinepars2header(header, aff)
            fits.update(psffn, self.jw.psf, header=header)
            del self.jw

            # fringeonly g7s6 jwst
            self.jw = NRM_Model(mask='jwst',
                                holeshape="fringeonly",
                                affine2d=aff)
            self.jw.set_pixelscale(self.pixel)
            self.jw.simulate(fov=self.npix, bandpass=self.wave, over=self.over)
            psffn = self.fnfmt.format(self.npix, 'fringeonly',
                                      self.wave[:, 1][0] / um, aff.name)
            fits.writeto(psffn, self.jw.psf, overwrite=True)
            header = fits.getheader(psffn)
            header = affinepars2header(header, aff)
            fits.update(psffn, self.jw.psf, header=header)
            del self.jw

            del aff

        self.hextest = self.eval_psf_hex()
        self.fringeonlytest = self.eval_psf_fringeonly()
        self.hexonlytest = self.eval_psf_hexonly()
        self.evals = [self.hextest, self.fringeonlytest, self.hexonlytest]
        self.sigsum = self.hextest + self.fringeonlytest + self.hexonlytest

    """  Ideal and Xreverse_xflipped should be machine zero or close """

    def eval_psf_hex(self):
        psfIdeal = fits.getdata(
            self.fnfmt.format(self.npix, 'hex', self.wave[:, 1][0] / um,
                              "Ideal"))
        psfXrev = fits.getdata(
            self.fnfmt.format(self.npix, 'hex', self.wave[:, 1][0] / um,
                              "Xreverse"))
        psfdiff = psfIdeal - psfXrev[::-1, :]
        print("    Numerical Summary:         hex  psf: " +\
              self.numtestfmt.format(psfIdeal.min(), psfIdeal.max(), psfIdeal.mean(), psfIdeal.std()))
        print("    Numerical Summary:         hex test: " +\
              self.numtestfmt.format(psfdiff.min(), psfdiff.max(), psfdiff.mean(), psfdiff.std()))
        fits.PrimaryHDU(data=psfdiff).writeto(self.data_dir + "/diff_hex.fits",
                                              overwrite=True)
        return psfdiff.std()

    def eval_psf_fringeonly(self):
        psfIdeal = fits.getdata(
            self.fnfmt.format(self.npix, 'fringeonly', self.wave[:, 1][0] / um,
                              "Ideal"))
        psfXrev = fits.getdata(
            self.fnfmt.format(self.npix, 'fringeonly', self.wave[:, 1][0] / um,
                              "Xreverse"))
        psfdiff = psfIdeal - psfXrev[::-1, :]
        print("    Numerical Summary:  fringeonly  psf: " +\
              self.numtestfmt.format(psfIdeal.min(), psfIdeal.max(), psfIdeal.mean(), psfIdeal.std()))
        print("    Numerical Summary:  fringeonly test: " +\
              self.numtestfmt.format(psfdiff.min(), psfdiff.max(), psfdiff.mean(), psfdiff.std()))
        fits.PrimaryHDU(data=psfdiff).writeto(self.data_dir +
                                              "/diff_fringeonly.fits",
                                              overwrite=True)
        return psfdiff.std()

    def eval_psf_hexonly(self):
        psfIdeal = fits.getdata(
            self.fnfmt.format(self.npix, 'hexonly', self.wave[:, 1][0] / um,
                              "Ideal"))
        psfXrev = fits.getdata(
            self.fnfmt.format(self.npix, 'hexonly', self.wave[:, 1][0] / um,
                              "Xreverse"))
        psfdiff = psfIdeal - psfXrev[::-1, :]
        print("    Numerical Summary:     hexonly  psf: " +\
              self.numtestfmt.format(psfIdeal.min(), psfIdeal.max(), psfIdeal.mean(), psfIdeal.std()))
        print("    Numerical Summary:     hexonly test: " +\
              self.numtestfmt.format(psfdiff.min(), psfdiff.max(), psfdiff.mean(), psfdiff.std()))
        fits.PrimaryHDU(data=psfdiff).writeto(self.data_dir +
                                              "/diff_hexonly.fits",
                                              overwrite=True)
        return psfdiff.std()

    def test_psfs(self):
        print("Standard deviations of all three tests:", self.evals)
        self.assertTrue(self.sigsum < 1e-7,
                        'error: test_affine2d_xyscale_psf failed')
Example #13
0
def find_scale(
        imagedata,
        affine_best,  # best current guess at data geometry cf analytical ideal
        scales,  # scales are near-unity
        pixel,
        npix,
        bandpass,
        over,
        holeshape,
        outdir=None):  # for nrm_model
    """  Preserve incoming "pixel" value, put the scale correction into the Affine2d object
         Is that kosher???  Should we change the pixel scale and leave affine2d the same?
         Affine2d can also incorporate unequal x and y scales, shears...
         For now place scale corrections into the Affine2d object     
         
         Note - placing isotropic scale change into Affine2d is equivalent to changing
         the effective image distance in the optical train while insisting that the
         mask physical geometry does not change, and the wavelength is perfectly knowm

         AS 2018 10  """

    affine_best.show("\tfind_scale")
    vprint("\tBefore Loop: ", scales)

    #Extend this name to include multi-paramater searches?
    psffmt = 'psf_nrm_{0:d}_{1:s}_{2:.3f}um_scl{3:.3f}.fits'
    # expect (npix, holeshape, bandpass/um, scl)

    if hasattr(scales, '__iter__') is False:
        scales = (scales, )

    affine2d_list = create_afflist_scales(scales, affine_best.mx,
                                          affine_best.my, affine_best.sx,
                                          affine_best.sy, affine_best.xo,
                                          affine_best.yo)
    crosscorrs = []

    for (scl, aff) in zip(scales, affine2d_list):

        vprint(aff.name + "...")
        jw = NRM_Model(mask='jwst',
                       holeshape=holeshape,
                       over=over,
                       affine2d=aff)
        jw.set_pixelscale(pixel)
        jw.simulate(fov=npix, bandpass=bandpass, over=over)
        psffn = psffmt.format(npix, holeshape, bandpass[:, 1][0] / um, scl)
        if outdir:
            fits.PrimaryHDU(data=jw.psf).writeto(outdir + "/" + psffn,
                                                 overwrite=True)
            fits.writeto(psffn, jw.psf, overwrite=True)
            header = fits.getheader(psffn)
            utils.affinepars2header(header, aff)
            fits.update(psffn, jw.psf, header=header)

        crosscorrs.append(utils.rcrosscorrelate(imagedata, jw.psf).max())
        del jw

    vprint("\tfind_affine2d_parameters: crosscorrelations", crosscorrs)
    vprint("\tfind_affine2d_parameters:            scales", scales)
    scl_measured, max_cor = utils.findpeak_1d(crosscorrs, scales)
    vprint(
        "\tfind_affine2d_parameters factor measured {0:.5f}  Max correlation {1:.3e}"
        .format(scl_measured, max_cor))
    vprint("\tfind_affine2d_parameters pitch from header  {0:.3f} mas".format(
        pixel * rad2mas))
    vprint(
        "\tfind_affine2d_parameters pitch  {0:.3f} mas (implemented using affine2d)"
        .format(scl_measured * pixel * rad2mas))

    # return convenient affine2d
    return utils.Affine2d(affine_best.mx * scl_measured,
                          affine_best.my * scl_measured,
                          affine_best.sx * scl_measured,
                          affine_best.sy * scl_measured,
                          affine_best.xo * scl_measured,
                          affine_best.yo * scl_measured,
                          name="scale_{0:.4f}".format(scl))
    def setUp(self):
    
        # setup parameters for simulation
        verbose = 1
        overwrite = 1

        monochromatic_wavelength_m = np.array([(1.0, 4.3e-6),])
        mask = 'MASK_NRM'
        filter = 'F430M'
        pixelscale_arcsec = 0.0656 
        filter_name = 'Monochromatic '+np.str(monochromatic_wavelength_m)

        self.filter = filter
        self.filter_name = filter_name
        self.monochromatic_wavelength_m = monochromatic_wavelength_m
        
        # directory containing the test data
        data_dir = os.path.join(os.path.dirname(__file__),'test_data/fringe_fitting')
        if not os.path.exists(data_dir):
            os.makedirs(data_dir)

        out_dir = data_dir

        name_seed = 'PSF_NIRISS_%s_%s'%(mask,filter)

        psf_image_name = name_seed + '_reference.fits'
        psf_image = os.path.join(data_dir,psf_image_name)
        psf_image_without_oversampling = os.path.join(data_dir,psf_image_name.replace('.fits','_without_oversampling.fits'))

        if (not os.path.isfile(psf_image_without_oversampling)) | (overwrite): 
            from nrm_analysis.fringefitting.LG_Model import NRM_Model
            jw = NRM_Model(mask='jwst',holeshape="hex")
            jw.set_pixelscale(pixelscale_arcsec*arcsec2rad)
            jw.simulate(fov=n_image, 
                bandpass=monochromatic_wavelength_m, 
                over=oversample)
            print("FringeFittingTestCase.SetUp: simulation oversampling is", oversample)
            
            # optional writing of oversampled image
            if 0:
                fits.writeto(psf_image,jw.psf_over, clobber=True)
                header = fits.getheader(psf_image)
                header['PIXELSCL'] = pixelscale_arcsec/oversample
                header['FILTER'] = filter_name
                header['PUPIL'] = mask 
                fits.update(psf_image,jw.psf_over/10000./28., header=header)

            # PSF without oversampling
            fits.writeto(psf_image_without_oversampling,jw.psf, clobber=True)
            header = fits.getheader(psf_image_without_oversampling)
            header['PIXELSCL'] = pixelscale_arcsec
            header['FILTER'] = filter_name
            header['PUPIL'] = mask 
            fits.update(psf_image_without_oversampling,jw.psf, header=header)
    
    
        # list of files produced for target
        file_list = glob.glob(os.path.join(data_dir,'*%s*.fits' % 'without_oversampling' ));
            
        self.simulated_image = file_list[0]
        self.psf_image_without_oversampling = psf_image_without_oversampling
Example #15
0
def verify_pistons(arg):
    """
    Create simulated data with pistons,
    1. analyze the data by calling fit_image
    Do not use fringefitter since the data is perfecrly centered (the if loop).
    Check if input and output pistons match.
    
    2. analyze the data by calling fit_image via fringefitter
    Fringefitter finds the bestcenter and makes model with bestcenter.
    Since the data is perfecrly centered fringefitter should not affect output pistons.
    Check if input and output pistons match.
    """

    jw = NRM_Model(mask='jwst', holeshape="hex")
    pixelscale_as = 0.0656
    arcsec2rad = u.arcsec.to(u.rad)

    jw.set_pixelscale(pixelscale_as * arcsec2rad)

    np.random.seed(100)

    #lambda/14 ~ 80% strehl ratio
    phi = np.random.normal(0, 1.0, 7) / 14.0  # waves
    print("phi", phi, "varphi", phi.var(), "waves")
    phi = phi - phi.mean()

    print("phi_nb stdev/w", phi.std())
    print("phi_nb stdev/r", phi.std() * 2 * np.pi)
    print("phi_nb mean/r", phi.mean() * 2 * np.pi)
    pistons = phi * 4.3e-6  #OR

    print("/=====input pistons/m=======/\n", pistons)
    print("/=====input pistons/r=======/\n", pistons * (2 * np.pi) / 4.3e-6)

    jw.set_pistons(pistons)
    jw.simulate(fov=81, bandpass=4.3e-6, over=oversample)
    fits.PrimaryHDU(data=jw.psf).writeto(
        "implaneia_tests/perfect_wpistons.fits", overwrite=True)

    if arg == ("no_fringefitter"):

        jw.make_model(fov=81, bandpass=4.3e-6, over=oversample)
        jw.fit_image(jw.psf, modelin=jw.model)

        pos = np.get_printoptions()
        np.set_printoptions(precision=4,
                            formatter={'float': lambda x: '{:+.4e}'.format(x)},
                            linewidth=80)
        print("Residual/psfpeak array center:", jw.psf.shape)
        print((jw.residual / jw.psf.max())[36:-36, 36:-36])
        np.set_printoptions(pos)

        fits.PrimaryHDU(data=jw.residual).writeto(
            "residual_pistons_no_ff.fits", overwrite=True)
        #return jw
        #print("output pistons/r",jw.fringepistons)
        #print("output pistons/w",jw.fringepistons/(2*np.pi))
        #print("output pistons/m",jw.fringepistons*4.3e-6/(2*np.pi))
        #print("input pistons/m ",jw.phi)

    elif arg == ("use_fringefitter"):

        fits.PrimaryHDU(data=jw.psf).writeto(datadir +
                                             "/perfect_wpistons.fits",
                                             overwrite=True)

        amisim2mirage(datadir, ("perfect_wpistons", ), mirexample, filt)

        niriss = InstrumentData.NIRISS(filt)
        ff_t = nrm_core.FringeFitter(niriss,
                                     datadir=datadir,
                                     savedir=datadir,
                                     oversample=oversample,
                                     interactive=False)
        print(test_tar)
        ff_t.fit_fringes(test_tar)

        print("Residual:")
        #print(ff_t.nrm.residual)
        print("Residual/psfpeak array center:", ff_t.nrm.reference.shape)
        pos = np.get_printoptions()
        np.set_printoptions(precision=3,
                            formatter={'float': lambda x: '{:+.3e}'.format(x)},
                            linewidth=80)
        print((ff_t.nrm.residual / jw.psf.max())[36:-36, 36:-36])
        np.set_printoptions(pos)

        fits.PrimaryHDU(data=ff_t.nrm.residual).writeto(datadir+\
                        "/residual_pistons_with_ff.fits",overwrite=True)

        utils.compare_pistons(jw.phi * 2 * np.pi / 4.3e-6,
                              ff_t.nrm.fringepistons,
                              str="ff_t")
Example #16
0
class Affine2dTestCase(unittest.TestCase):

    def setUp(self):

        # directory containing the test data
        data_dir = os.path.join(os.path.dirname(__file__),'test_data/affine2d_rot_psf')
        self.data_dir = data_dir
        print(data_dir)
        if not os.path.exists(data_dir):
            os.makedirs(data_dir)
        self.fnfmt = data_dir+'/psf_nrm_{2:.1f}_{0}_{1}_{3:.0f}.fits' # expects strings of  %(imsize,hole)

        self.fmt = "    ({0:+.3f}, {1:+.3f}) -> ({2:+.3f}, {3:+.3f})"
        self.pixel = 0.0656 *  u.arcsec.to(u.rad)
        self.npix = 87
        self.wave = np.array([(1.0, 4.3e-6),]) # m
        self.over = 1

        mx, my = 1.0, 1.0
        sx, sy= 0.0, 0.0
        xo, yo= 0.0, 0.0
        affine_ideal = Affine2d(mx=mx,my=my, 
                                sx=sx,sy=sy, 
                                xo=xo,yo=yo, name="Ideal")

        for rot in (0,5,10,15,20,25,30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95):
            """
            print("           rot degrees pre", rot, end='')
            diagnostic = rot/15.0 - int(rot/15.0)
            print("  diagnostic", diagnostic, end='')
            rot = avoidhexsingularity(rot) # in utils
            print("   rot degrees post", rot)
            """
            rot = avoidhexsingularity(rot) # in utils
            affine_rot = Affine2d(rotradccw=np.pi*rot/180.0, name="{0:.0f}".format(rot)) # in utils
            aff = affine_rot

            # hexonly g7s6 jwst
            self.jw = NRM_Model(mask='jwst', holeshape="hexonly", affine2d=aff)
            self.jw.set_pixelscale(self.pixel*arcsec2rad)
            self.jw.simulate(fov=self.npix, bandpass=self.wave, over=self.over)
            psffn = self.fnfmt.format(self.npix, 'hexonly', self.wave[:,1][0]/um, rot)
            fits.writeto(psffn, self.jw.psf, overwrite=True)
            header = fits.getheader(psffn)
            header = affinepars2header(header, aff)
            fits.update(psffn, self.jw.psf, header=header)
            del self.jw

            del aff
            del affine_rot


    def test_psf(self):
        """ Read in PSFs with 0, 90 degree affines, 5 and 95 degree affines, 
            Rotate one set and subtract from the smaller rot PSF - should be zero if
            everything is correctly calculated.  If we nudge the PSF centers to avoid the 
            line singularity that hextransformEE will encounter if the psf is centrally 
            placed in a pixel.
            The file names are hand-edited to reflect the oversampling and rotations,
            so this is more a sanity check and code development tool than a routine test.
        """
        psf0  = fits.getdata(self.fnfmt.format(self.npix, 'hexonly', self.wave[:,1][0]/um, 0))
        psf90 = fits.getdata(self.fnfmt.format(self.npix, 'hexonly', self.wave[:,1][0]/um, 90))
        psf90r0 = np.rot90(psf90)
        psfdiff = psf0 - psf90r0
        fits.PrimaryHDU(data=psfdiff).writeto(self.data_dir+"/diff_90_0_off08_ov1.fits", overwrite=True)
        psf0  = fits.getdata(self.fnfmt.format(self.npix, 'hexonly', self.wave[:,1][0]/um, 5))
        psf90 = fits.getdata(self.fnfmt.format(self.npix, 'hexonly', self.wave[:,1][0]/um, 95))
        psf90r0 = np.rot90(psf90)
        psfdiff = psf0 - psf90r0
        fits.PrimaryHDU(data=psfdiff).writeto(self.data_dir+"/diff_95_5_off08_ov1.fits", overwrite=True)
        self.assertTrue(0.0 < 1e-15,  'error: test_affine2d failed')
Example #17
0
    def setUp(self):

        # directory containing the test data
        data_dir = os.path.join(os.path.dirname(__file__),
                                'test_data/psf_offset')
        self.data_dir = data_dir
        print(data_dir)
        if not os.path.exists(data_dir):
            os.makedirs(data_dir)

        self.pixel = 0.0656 * u.arcsec.to(u.rad)
        self.npix = 87
        self.wave = 4.3e-6  # m
        self.over = 1
        """
        mx, my = 1.0, 1.0
        sx, sy= 0.0, 0.0
        xo, yo= 0.0, 0.0
        affine_ideal = Affine2d(mx=mx,my=my, 
                                sx=sx,sy=sy, 
                                xo=xo,yo=yo, name="Ideal")
        """
        invert = False  # greyscale inversion (true/false)

        holeshape = "hex"
        pixel_as = 0.0656 / 1.3  # slightly finer-than-actual-detector sampling, for clearer images
        print(
            "\n\t*** Watch out *** if comparing to real data: slightly finer-than-actual-detector sampling used for clearer images\n"
        )
        fov = 101  # 'detpix' but at finer sampling than actual
        over = 1
        wav_m = 4.3e-6
        filt = 'F430M'
        band = 'Monochromatic ' + np.str(wav_m)

        psf_offsets = (
            (0, 0),
            (1.0, 0),
        )
        psf_offsets = ((0, 0), )
        psf_offsets = ((0, 0), (1.0, 0), (0, 1.0), (1.0, 1.0))
        print((enumerate(psf_offsets)))
        psfs = np.zeros(
            (len(psf_offsets), fov, fov))  # for easy to understand movie
        print(('psfs.shape', psfs.shape))
        fncube3 = data_dir + "/cube.fits"

        # Loop over psf_offsets
        for noff, psfo in enumerate(psf_offsets):
            jw3 = NRM_Model(mask='jwst',
                            holeshape=holeshape,
                            pixscale=arcsec2rad * pixel_as,
                            datapath="",
                            refdir="./refdir")
            #chooseholes=None)

            jw3.simulate(fov=fov, bandpass=wav_m, over=over, psf_offset=psfo)

            mnem = "imctr_%.1f_%.1f" % psfo
            fn3 = data_dir + "/" + mnem + '.fits'
            name_seed = mnem
            # PSF
            fits.writeto(fn3, jw3.psf, overwrite=True)
            header = fits.getheader(fn3)
            header['SEGNAMES'] = "asbuilt"
            header['PIXELSCL'] = pixel_as
            header['over'] = over
            header['FILTER'] = wav_m
            header['hole'] = holeshape
            header['PUPIL'] = 'asbuilt'
            header['psfoff0'] = (psfo[0], "ds9X / detector pixels")
            header['psfoff1'] = (psfo[1], "ds9Y / detector pixels")
            header['SRC'] = ("test_psf_offset.py", "generating code")
            header['author'] = ("*****@*****.**", "responsible person?")
            fits.update(fn3, jw3.psf, header=header)
            psfs[noff, :, :] = jw3.psf
            """ calls tkinter, needs $DISPLAY environment variable, breaks travis testing
            figname = UC.make_standard_image(
                                           fn3,
                                           image_title=name_seed,
                                           save_plot=1, 
                                           plot_dir=data_dir, 
                                           name_seed=name_seed, 
                                           stretch='linear', 
                                           x_axis_label=None, 
                                           y_axis_label=None,
                                           invert=invert,
                                           add_grid=True)
            print(figname + " written to " + data_dir)
            """

            del jw3

        fits.PrimaryHDU(data=psfs).writeto(fncube3,
                                           overwrite=True)  # good for movie
        """
def test_offset_residuals_with_offset_measured():
    """
    Simulate data with known offsets, analyze data using fringefitter.
    """

    pixelscale_as = 0.0656
    arcsec2rad = u.arcsec.to(u.rad)
    PIXELSCALE_r = pixelscale_as * arcsec2rad

    jw0 = NRM_Model(mask='jwst', holeshape="hex")
    jw0.set_pixelscale(pixelscale_as * arcsec2rad)

    jw0.simulate(fov=35,
                 bandpass=bandpass,
                 over=oversample,
                 psf_offset=(0.0, 0.0))
    fits.PrimaryHDU(data=jw0.psf).writeto(fitsimdir + "no_offset_data.fits",
                                          overwrite=True)

    jw = NRM_Model(mask='jwst', holeshape="hex")
    jw.set_pixelscale(pixelscale_as * arcsec2rad)

    jw.simulate(fov=35,
                bandpass=bandpass,
                over=oversample,
                psf_offset=psf_offsets)
    fits.PrimaryHDU(data=jw.psf).writeto(fitsimdir + "offset_data.fits",
                                         overwrite=True)
    fits.PrimaryHDU(data=(jw.psf - jw0.psf) / jw0.psf.max()).writeto(
        fitsimdir + "diff_from_center.fits", overwrite=True)

    amisim2mirage(fitsimdir, ("offset_data", ), mirexample, filt)

    niriss = InstrumentData.NIRISS(filt, bandpass=bandpass)
    ff_t = nrm_core.FringeFitter(niriss,
                                 datadir=fitsimdir,
                                 savedir=fitsimdir,
                                 oversample=oversample,
                                 interactive=False)
    print(test_tar)
    ff_t.fit_fringes(test_tar)

    jw_m = NRM_Model(mask='jwst', holeshape="hex")
    jw_m.set_pixelscale(pixelscale_as * arcsec2rad)

    #Look at measured offsets in the screen output and feed them to simulate to compare with simulated data created with input offsets.
    #nrm.bestcenter (0.4799802988666451, 6.984734412937637e-05)  nrm.xpos 0.4799802988666451  nrm.ypos 6.984734412937637e-05
    jw_m.simulate(fov=35,
                  bandpass=bandpass,
                  over=oversample,
                  psf_offset=(ff_t.nrm.xpos, ff_t.nrm.ypos))

    fits.PrimaryHDU(data=jw_m.psf).writeto(fitsimdir + "m_offset_data.fits",
                                           overwrite=True)
    fits.PrimaryHDU(data=(jw.psf - jw_m.psf) / jw0.psf.max()).writeto(
        fitsimdir + "m_diff_of_offsets.fits", overwrite=True)

    print("Residual:")
    #print(ff_t.nrm.residual)
    print("Residual/psfpeak array center:", ff_t.nrm.reference.shape)
    pos = np.get_printoptions()
    np.set_printoptions(precision=3,
                        formatter={'float': lambda x: '{:+.3e}'.format(x)},
                        linewidth=80)
    print((ff_t.nrm.residual / jw.psf.max())[36:-36, 36:-36])
    np.set_printoptions(pos)

    fits.PrimaryHDU(data=ff_t.nrm.residual).writeto(fitsimdir+\
                        "residual_offsets_with_ff.fits",overwrite=True)
Example #19
0
    def setUp(self):

        # setup parameters for simulation, most are passed on to driver_scene
        verbose = 0
        overwrite = 1

        apply_dither = 0
        apply_jitter = 0
        include_detection_noise = 0
        uniform_flatfield = 1

        OVERSAMPLE = 11
        monochromatic_wavelength_m = 4.3e-6

        create_calibrator = 0
        random_seed = 124
        flip = False
        mask = 'MASK_NRM'
        filter = 'F430M'
        n_image = 77

        filter_name = 'Monochromatic ' + np.str(monochromatic_wavelength_m)

        # directory containing the static test data
        data_dir = os.path.join(os.path.dirname(__file__), 'test_data')

        # define output directory for dynamically generated data
        out_dir = os.path.join(os.path.dirname(__file__), 'tmp_data')
        if not os.path.exists(out_dir):
            os.makedirs(out_dir)

        name_seed = 'PSF_NIRISS_%s_%s' % (mask, filter)
        point_source_image_name = 'point_source_image.fits'
        point_source_image = os.path.join(out_dir, point_source_image_name)

        psf_image_name = name_seed + '_reference.fits'
        psf_image = os.path.join(data_dir, psf_image_name)
        psf_image_without_oversampling = os.path.join(
            data_dir,
            psf_image_name.replace('.fits', '_without_oversampling.fits'))

        # generate delta-function like image to feed as point-source into scene_sim
        n_image2 = n_image * OVERSAMPLE
        data = np.zeros((n_image2, n_image2))
        bright_pixel_index = (np.int(np.floor(n_image2 / 2.)),
                              np.int(np.floor(n_image2 / 2.)))
        data[bright_pixel_index] = 1.
        fits.writeto(point_source_image, data, clobber=True)

        # following code can be used to regenerate reference PSF file, but it depends on nrm_analysis
        if 0:
            from nrm_analysis.fringefitting.LG_Model import NRM_Model
            jw = NRM_Model(mask='jwst', holeshape="hex", flip=flip)
            jw.simulate(fov=n_image,
                        bandpass=monochromatic_wavelength_m,
                        over=OVERSAMPLE,
                        pixel=mas2rad(PIXELSCL_arcsec * 1000))
            fits.writeto(psf_image, jw.psf_over, clobber=True)
            header = fits.getheader(psf_image)
            header['PIXELSCL'] = PIXELSCL_arcsec / OVERSAMPLE
            header['FILTER'] = filter_name
            header['PUPIL'] = mask
            fits.update(psf_image, jw.psf_over / 10000. / 28., header=header)

            # PSF without oversampling
            fits.writeto(psf_image_without_oversampling, jw.psf, clobber=True)
            header = fits.getheader(psf_image_without_oversampling)
            header['PIXELSCL'] = PIXELSCL_arcsec
            header['FILTER'] = filter_name
            header['PUPIL'] = mask
            fits.update(psf_image_without_oversampling, jw.psf, header=header)

        NGROUP = 1
        NINT = 1
        COUNTRATE = 5e8

        #     run driver_scene to generate target and calibrator images
        driver_scene.main(['--output_absolute_path','%s'%out_dir,\
                           '--overwrite','%d'%overwrite,'-utr','0', '-f','%s'%filter,'-v','%d'%verbose,'--apply_dither','%d'%apply_dither,'--apply_jitter','%d'%apply_jitter,\
                           '-p',psf_image,'-s','%s'%point_source_image,'-os','%d'%OVERSAMPLE,'-cr','%e'%COUNTRATE,'--include_detection_noise','%d'%include_detection_noise,\
                           '-tag',('%3.2e_NGROUP%d'%(COUNTRATE,NGROUP)).replace('.','p'),'--uniform_flatfield','%d'%uniform_flatfield,'--random_seed','%d'%random_seed,\
                           '--create_calibrator','%d'%create_calibrator,'--nint','%d'%NINT,'--ngroups','%d'%NGROUP])

        # directory where simulated data was written
        filter_dir = os.path.join(out_dir, filter)
        self.filter_dir = filter_dir

        # list of files produced for target
        file_list = glob.glob(os.path.join(filter_dir, '%s*.fits' % 't_'))

        self.simulated_image = file_list[0]
        self.psf_image_without_oversampling = psf_image_without_oversampling