def parse_aperture(aperture_name):
    '''
    Return [image mask, pupil mask, fov_pixels, trim_fov_pixels, pixelscale]
    '''
    
    aperture_keys = ['mask210r','mask335r','mask430r','masklwb','maskswb',
                     'fqpm1065','fqpm1140','fqpm1550','lyot2300']
    assert aperture_name in aperture_keys, \
        'Aperture {} not recognized! Must be one of {}'.format(aperture_name, aperture_keys)

    nc = webbpsf.NIRCam()
    miri = webbpsf.MIRI()

    aperture_dict = {
        'mask210r' : ['MASK210R','CIRCLYOT', 101, None, nc._pixelscale_short],
        'mask335r' : ['MASK335R','CIRCLYOT', 101, None, nc._pixelscale_long],
        'mask430r' : ['MASK430R','CIRCLYOT', 101, None, nc._pixelscale_long],
        'masklwb' : ['MASKLWB','WEDGELYOT', 351, 101, nc._pixelscale_long],
        'maskswb' : ['MASKSWB','WEDGELYOT', 351, 101, nc._pixelscale_short],
        'fqpm1065' : ['FQPM1065','MASKFQPM', 81, None, miri.pixelscale],
        'fqpm1140' : ['FQPM1140','MASKFQPM', 81, None, miri.pixelscale],
        'fqpm1550' : ['FQPM1550','MASKFQPM', 81, None, miri.pixelscale],
        'lyot2300' : ['LYOT2300','MASKLYOT', 81, None, miri.pixelscale]
        }
  
    return aperture_dict[aperture_name]
def get_psf( wave, instrument, aperture_name, source_offset=(0, 0), otf_options=None,
        full_aperture=None):
    #Make the instrument and determine the mode
    if instrument.upper() == 'NIRCAM':
        ins = webbpsf.NIRCam()
        
        # WebbPSF needs to know the filter to select the optimal 
        # offset for the bar masks. The filter is not passed into
        # get_psf but is stored in the full aperture name in self._psfs
        if aperture_name in ['masklwb', 'maskswb']:
            # Everything after the aperture name is the filter name.
            full_aperture = self._psfs[0]['aperture_name']
            fname = full_aperture[full_aperture.find(aperture_name) + len(aperture_name):]
            ins.filter = fname
        if wave > 2.5:
            # need to toggle to LW detector.
            ins.detector='A5'
            ins.pixelscale = ins._pixelscale_long
    elif instrument.upper() == 'MIRI':
        ins = webbpsf.MIRI()
    else:
        raise ValueError('Only NIRCam and MIRI are supported instruments!')
    image_mask, pupil_mask, fov_pixels, trim_fov_pixels, pix_scl = parse_aperture(aperture_name)
    ins.image_mask = image_mask
    ins.pupil_mask = pupil_mask

    # Apply any extra options if specified by the user:
    for key in options.on_the_fly_webbpsf_options:
        ins.options[key] = options.on_the_fly_webbpsf_options[key]

    if options.on_the_fly_webbpsf_opd is not None:
        ins.pupilopd = options.on_the_fly_webbpsf_opd

    #get offset
    ins.options['source_offset_r'] = source_offset[0]
    ins.options['source_offset_theta'] = source_offset[1]
    ins.options['output_mode'] = 'oversampled'
    ins.options['parity'] = 'odd'

    psf_result = calc_psf_and_center(ins, wave, source_offset[0], source_offset[1], 3,
                            pix_scl, fov_pixels, trim_fov_pixels=trim_fov_pixels)

    pix_scl = psf_result[0].header['PIXELSCL']
    upsamp = psf_result[0].header['OVERSAMP']
    diff_limit = psf_result[0].header['DIFFLMT']
    psf = psf_result[0].data

    psf = {
        'int': psf,
        'wave': wave,
        'pix_scl': pix_scl,
        'diff_limit': diff_limit,
        'upsamp': upsamp,
        'instrument': instrument,
        'aperture_name': aperture_name,
        'source_offset': source_offset
    }

    return psf
Example #3
0
def main():
    # save the figures
    figdir = 'Figures'

    # just listing the wide filters
    nircam_bandpasses = 'F070W,F090W,F115W,F150W,F200W,F277W,F356W,F444W'
    miri_bandpasses = 'F560W,F770W,F1000W,F1130W,F1280W,F1500W,F1800W,F2100W,F2550W'
    nircam_bandpasses = nircam_bandpasses.split(',')
    miri_bandpasses = miri_bandpasses.split(',')

    # configure the instruments
    nircam = W.NIRCam()
    miri = W.MIRI()

    # load the bandpasses
    bandpasses = {}
    for bp in nircam_bandpasses:
        nircam.filter = bp
        bpmodel = nircam._getSynphotBandpass(nircam.filter)
        bandpasses[bp] = bpmodel
    for bp in miri_bandpasses:
        miri.filter = bp
        bpmodel = miri._getSynphotBandpass(miri.filter)
        bandpasses[bp] = bpmodel

    # we just need a couple of bandpasses for testing
    use_bandpasses = nircam_bandpasses + miri_bandpasses[0:3]

    # init the kilonova model and create some arrays to store output
    kn = Kilonova()

    # do this for a few distances
    for j, dmpc in enumerate(DISTANCE):
        time = []
        rfphase = []
        flux = {}

        if j == 0:
            fig = plt.figure(figsize=(8, 15))
            ax = fig.add_subplot(1, 1, 1)

        for i, phase in enumerate(kn._times):
            # get the kilonova model and spectrum for this phase and distance
            lam, flam = kn.get_model(phase)
            lamz, fnorm = kn.get_norm_model(phase, dmpc)
            name = 'kilonova_{:+.2f}'.format(phase)
            spec = S.ArraySpectrum(wave=lamz,
                                   flux=fnorm,
                                   waveunits='angstrom',
                                   fluxunits='flam',
                                   name=name)

            # get synthetic mags in each passband
            for bp in use_bandpasses:
                passband = bandpasses[bp]
                obs = S.Observation(spec, passband, force='taper')
                try:
                    mag = obs.effstim('abmag')
                except ValueError as e:
                    mag = np.nan
                thispb = flux.get(bp)
                if thispb is None:
                    thispb = [
                        mag,
                    ]
                else:
                    thispb.append(mag)
                flux[bp] = thispb

            # keep a track of rest-frame phase + observer frame days (should make much difference at these distances)
            dist = c.Distance(dmpc * u.megaparsec)
            z = dist.z
            rfphase.append(phase)
            time.append(phase * (1. + z))

            # write output photometry tables
            if i % 5 == 0:
                # convert flam -> fnu -> mJy (YUCK)
                lam_micron = lamz * ANGSTROM_TO_MICRON
                f_nu = (((lamz * ANGSTROM_TO_CM)**2.) /
                        SPEED_OF_LIGHT) * fnorm / ANGSTROM_TO_MICRON
                f_mjy = f_nu * FNU_TO_MJY
                table_name = 'Tables/kilonova_orig_{}Mpc_p{:+.2f}.txt'.format(
                    dmpc, phase)
                this_spec = at.Table([lam_micron, f_mjy],
                                     names=['wave_micron', 'flux_mjy'])
                this_spec.sort('wave_micron')
                this_spec.write(table_name,
                                format='ascii.fixed_width',
                                delimiter=' ',
                                overwrite='True')

                # plot output spectral sequence
                if j == 0:
                    fplot = flam / flam.mean()
                    ax.plot(lam * ANGSTROM_TO_MICRON, fplot + 180 - i, 'k-')

        # finalize spectral sequence plot
        if j == 0:
            ax.tick_params(axis='both', which='major', labelsize='large')
            ax.set_xlabel(r'Rest Wavelength ($\mu$m)', fontsize='xx-large')
            ax.set_ylabel(r'Relative F$_{\lambda}$ + constant',
                          fontsize='xx-large')
            ax.set_xlim(0.5, 9.5)
            fig.tight_layout(rect=[0, 0, 1, 0.96])
            plt.savefig('{}/kilonova_spec.pdf'.format(figdir))
            plt.close(fig)

        # dump output mag tables
        arrays = [
            rfphase,
            time,
        ] + [flux[bp] for bp in use_bandpasses]
        names = ['rfphase', 'ofphase'] + [bp for bp in use_bandpasses]
        out = at.Table(arrays, names=names)
        out.write('Tables/kilonova_phottable_{}Mpc.txt'.format(dmpc),
                  delimiter=' ',
                  format='ascii.fixed_width',
                  overwrite=True)

        # plot up the lightcurves
        npbs = len(use_bandpasses)
        color = iter(plt.cm.tab20(np.linspace(0, 1, npbs)))
        with PdfPages('{}/kilonova_phot_{}Mpc.pdf'.format(figdir,
                                                          dmpc)) as pdf:
            fig = plt.figure(figsize=(10, 10))
            for i, bp in enumerate(use_bandpasses):

                # save four passbands per page
                if i % 4 == 0 and i > 0:
                    fig.suptitle(
                        'Kilonova Synthetic Photometry {} Mpc'.format(dmpc),
                        fontsize='xx-large')
                    fig.tight_layout(rect=[0, 0, 1, 0.93])
                    pdf.savefig(fig)
                    plt.close(fig)
                    fig = plt.figure(figsize=(10, 10))

                # plot up a passband
                ax = fig.add_subplot(2, 2, i % 4 + 1)
                thiscol = next(color)
                ax.plot(out['ofphase'],
                        out[bp],
                        marker='o',
                        linestyle='-',
                        lw=0.5,
                        label=bp,
                        color=thiscol)
                ax.tick_params(axis='both', which='major', labelsize='large')
                ax.set_ylabel('{} (AB mag)'.format(bp), fontsize='xx-large')
                ax.set_xlabel('Observer-frame Phase (Days)',
                              fontsize='xx-large')
                ax.legend(loc='upper right', frameon=False)
                ymin, ymax = ax.get_ylim()
                ax.set_ylim((ymax, ymin))

                # finalize lightcurve plot
                if i == npbs - 1:
                    fig.suptitle(
                        'Kilonova Synthetic Photometry {} Mpc'.format(dmpc),
                        fontsize='xx-large')
                    fig.tight_layout(rect=[0, 0, 1, 0.93])
                    pdf.savefig(fig)
                    plt.close(fig)
Example #4
0
def set_sim_params(args):
    #logging.basicConfig(level=logging.INFO, format='%(name)-12s: %(levelname)-8s %(message)s',)
    print "WebbPSF",pkg_resources.get_distribution("webbpsf").version," Poppy",pkg_resources.get_distribution("poppy").version
    #webbpsf.setup_logging(level='ERROR')

    nruns= args.nruns            #
    filt = args.f.upper()        #e.g. F430M
    mask_coron=args.mask.upper() #e.g. MASK430R
    pupil_stop=args.stop.upper() #e.g. CIRCLYOT
    instr=args.I.upper()

    if instr=='NIRCAM': lambda0=float(filt[1:4])/100
    elif instr=='MIRI': lambda0=float(filt[1:5])/100
    jitter= args.jitter 
    grid_step=args.gstep
    gridpoints=args.gnpts
    side=int(np.sqrt(gridpoints))
    max_step=np.floor(side/2)
    rms= args.rms 

    fovarcsec = args.fov #default 7.04 
    #fovpixels = 64

    sigmaTA = 4.7
    sigmaFSM= 2.0


    if instr=='NIRCAM': img=webbpsf.NIRCam()
    elif instr=='MIRI': img=webbpsf.MIRI()

    if filt not in img.filter_list:
        if instr == 'MIRI'  : print "\nFilter "+mask_coron+" not available. Select from: ",[f for f in img.filter_list if "C" in f[-1]],'\n'
        if instr == 'NIRCAM': print "\nFilter "+mask_coron+" not available. Select from: ",img.filter_list,'\n'
        sys.exit()

    if mask_coron not in img.image_mask_list:
        print "\nCoronagraphic mask "+mask_coron+" not available. Select from: ",img.image_mask_list,'\n'
        sys.exit()

    if pupil_stop not in img.pupil_mask_list[:2]:
        print "\nPupil mask "+pupil_stop+" not available. Select from: ",img.pupil_mask_list[:2],'\n' 
        sys.exit()

    opd_rms = [int(img.opd_list[i][-8:-5]) for i in xrange(len(img.opd_list))]
    if rms not in opd_rms:
        print "\nOPD rms ("+str(rms)+") not available. Select from: ",opd_rms,'\n'
        sys.exit()
    if instr=='NIRCAM' and args.noopd==False: opd='/Users/lajoie/WebbPSF/webbpsf-data/NIRCam/OPD/OPD_RevV_nircam_'+str(rms)+'.fits'
    if instr=='MIRI'   and args.noopd==False: opd='/Users/lajoie/WebbPSF/webbpsf-data/MIRI/OPD/OPD_RevV_miri_'+str(rms)+'.fits'

    img.filter=filt
    img._rotation=0.
    img.options["output_mode"]='detector sampled'
    if args.noopd==False: 
        img.pupilopd = (opd, 0) #select FITS extension for OPD
        print opd

    if instr=='NIRCAM': 
        outdir='./Results'+'/'+instr+'/'+filt+'_'+mask_coron+'/DitherStep'+str(int(grid_step))+'/Jitter'+str(int(jitter))+'/rms'+str(rms)+'nm/'
    else: outdir='./Results'+'/'+instr+'/'+filt+'/DitherStep'+str(int(grid_step))+'/Jitter'+str(int(jitter))+'/rms'+str(rms)+'nm/'

    if gridpoints != 9: 
        raw_input(" *** generating grids of %i points: ENTER to continue " %gridpoints)
        outdir = outdir[:-1]+"_Grid_%i_pts/" %gridpoints
        

    if not os.path.exists(outdir):
        os.makedirs(outdir)

    x0,y0 = get_source_offset(lambda0, filt, mask_coron)
    if np.abs(x0) > fovarcsec/2: 
        print "\n optimal bar occulter offset out of FOV. Please fix FOV in code (fovarcsec).\n   x_offset=%f Total fov=%f\n" %(x0,fovarcsec)
        sys.exit()

    generate_PSF(img, outdir, nruns, x0, y0, grid_step, side, max_step, sigmaTA, sigmaFSM, mask_coron, pupil_stop, lambda0, jitter, rms, fovarcsec)

    return
Example #5
0
 def resetPSF(self):
     import webbpsf
     if self.filter not in self.FILTERS:
         raise ValueError("Filter %s is not a valid MIRI filter" %
                          (self.filter))
     have_psf = False
     if os.path.exists(os.path.join(self.out_path, "psf_cache")):
         if os.path.exists(
                 os.path.join(
                     self.out_path, "psf_cache",
                     "psf_{}_{}_{}.fits".format("MIRI", self.filter,
                                                self.oversample))):
             with pyfits.open(
                     os.path.join(
                         self.out_path,
                         "psf_cache", "psf_{}_{}_{}.fits".format(
                             "MIRI", self.filter, self.oversample))) as psf:
                 if psf[0].header['VERSION'] >= webbpsf.__version__ and (
                         self.psf_commands is None
                         or self.psf_commands == ''):
                     self.psf = AstroImage(data=psf[0].data,
                                           detname="MIRI {} PSF".format(
                                               self.filter),
                                           logger=self.logger)
                     have_psf = True
     if not have_psf:
         base_state = self.getState()
         self.updateState(
             base_state +
             "<br /><span class='indented'>Generating PSF</span>")
         self._log("info", "Creating PSF")
         ins = webbpsf.MIRI()
         self._log("info", "Setting PSF attributes")
         if self.psf_commands is not None and self.psf_commands != '':
             for attribute, value in self.psf_commands.iteritems():
                 self._log(
                     "info", "Setting PSF attribute {} to {}".format(
                         attribute, value))
                 setattr(ins, attribute, value)
         self._log("info", "Setting PSF filter to '{}'".format(self.filter))
         ins.filter = self.filter
         max_safe_size = int(
             np.floor(30. * self.PHOTPLAM[self.filter] /
                      (2. * self.SCALE[0])))
         max_ins_size = max(self.DETECTOR_SIZE) * self.oversample
         max_conv_size = int(
             np.floor(self.convolve_size / (2 * self.oversample)))
         psf_size = min(max_safe_size, max_ins_size, max_conv_size)
         self._log(
             "info", "PSF choosing between {}, {}, and {}, chose {}".format(
                 max_safe_size, max_ins_size, max_conv_size, psf_size))
         psf = ins.calcPSF(oversample=self.oversample, fov_pixels=psf_size)
         psf[0].header['VERSION'] = webbpsf.__version__
         if os.path.exists(os.path.join(self.out_path, "psf_cache")):
             dest = os.path.join(
                 self.out_path, "psf_cache",
                 "psf_{}_{}_{}.fits".format("MIRI", self.filter,
                                            self.oversample))
             pyfits.writeto(dest,
                            psf[0].data,
                            header=psf[0].header,
                            overwrite=True)
         self.psf = AstroImage(data=psf[0].data,
                               detname="MIRI %s PSF" % (self.filter),
                               logger=self.logger)
         self.updateState(base_state)
        # Add mode keyword to header
        hdulist = pf.open(longname, mode='update')
        prihdr = hdulist[0].header
        prihdr['APERTURE'] = (
            aperture, 'The observing aperture within the instrument FOV')
        hdulist.flush()
        hdulist.close()


doMIRI = False
doNIRSpec = False
doNIRCam = False
doNIRISS = True

if doMIRI:
    MIRI_FQPM = wp.MIRI()
    MIRI_FQPM.pupil_mask = 'MASKFQPM'
    MIRI_FQPM.image_mask = 'FQPM1065'
    psf_suite(nw=10,
              wmin=9.5,
              wmax=11.5,
              instrument=MIRI_FQPM,
              outname='MIRI_FQPM1065',
              fov_arcsec=12,
              aperture='FQPM1065')
    MIRI_FQPM.image_mask = 'FQPM1140'
    psf_suite(nw=10,
              wmin=10.5,
              wmax=12.5,
              instrument=MIRI_FQPM,
              outname='MIRI_FQPM1140',