def GetAllCFHTBands(path): wl_u, tot_u, wl_g, tot_g, wl_r, tot_r, wl_i, tot_i, wl_z, tot_z = GetAllCFHTTransmissions( path) # Pysynphot requires to convert wl in a true numpy array # Pysynphot is not compatile with pandas wl_u = np.array(wl_u) wl_g = np.array(wl_g) wl_r = np.array(wl_r) wl_i = np.array(wl_i) wl_z = np.array(wl_z) tot_u = np.array(tot_u) tot_g = np.array(tot_g) tot_r = np.array(tot_r) tot_i = np.array(tot_i) tot_z = np.array(tot_z) bp_u = S.ArrayBandpass(wl_u, tot_u, name='CFHT_U') bp_g = S.ArrayBandpass(wl_g, tot_g, name='CFHT_G') bp_r = S.ArrayBandpass(wl_r, tot_r, name='CFHT_R') bp_i = S.ArrayBandpass(wl_i, tot_i, name='CHFT_I') bp_z = S.ArrayBandpass(wl_z, tot_z, name='CFHT_Z') return bp_u, bp_g, bp_r, bp_i, bp_z
def transmission(self, airmass=1.0, wavelength=None): '''Return the air transmission for a specified airmass. Parameters ---------- airmass : float or astropy.units.Quantity Airmass to use (default 1.0). The airmass may also be given as zenith angle [deg]. wavelength : astropy.units.Quantity Optional wavelength array. If given, the transmission is rebinned to this wavelength array, otherwise the unbinned data is returned. Returns ------- pysynphot.ArrayBandpass ArrayBandpass with transmission coefficients at each wavelength ''' import pysynphot as S if (isinstance(airmass, u.Quantity) and airmass.unit.physical_type == 'angle'): airmass = 1.0 / np.cos(airmass) res = self.zenith_transmission**airmass if wavelength is None: return S.ArrayBandpass(self.wavelength,res,name='sky_emission') else: res = rebin_1d_trans_box(res, self.wavelength, wavelength) return S.ArrayBandpass(wavelength,res,name='sky_emission')
def setUp(self): self.a = S.ArrayBandpass(wave=N.arange(4000, 5000), throughput=N.ones(1000)) self.disjoint = S.Box(1000, 100) self.full = S.ArrayBandpass(wave=N.arange(3000, 6000), throughput=N.ones(3000)) self.partial = S.ArrayBandpass(wave=N.arange(500, 4500), throughput=N.ones(4000))
def setUp(self): self.waveup = N.arange(10000, 10100, 10) self.wavedown = self.waveup[::-1] self.T = N.arange(10) + 5 self.Tflip = self.T.copy()[::-1] self.up = S.ArrayBandpass(wave=self.waveup, throughput=self.T) self.down = S.ArrayBandpass(wave=self.wavedown, throughput=self.T[::-1])
def _get_bandpass(self, wave): """ Get JWST instrument, mode, filter from self.bandpass, use that to create a JWSTInstrument instance, and then query that for throughput vs wavelength. Use pysynphot.ArrayBandpass() to convert the results to pysynphot-compatible form. Parameters ---------- wave: 1D np.ndarray Wavelength vector onto which JWST bandpass is interpolated Returns ------- bp: pysynphot.SpectralElement pysynphot bandpass converted to pandeia wavelength units. """ keys = get_key_list(self.bandpass, separator=',') if len(keys) != 3: msg = "JWST bandpass specification must be of the form <instrument>,<mode>,<filter>" raise EngineInputError(value=msg) instrument, mode, filt = keys config = {} config['instrument'] = {} config['instrument']['instrument'] = instrument config['instrument']['mode'] = mode config['instrument']['filter'] = filt inst = InstrumentFactory(config=config) thruput = inst.get_total_eff(wave) bp = psyn.ArrayBandpass(wave, thruput, waveunits=pandeia_waveunits) return bp
def get_ukirt_filt(name): """ Define UKIRT filters as pysynphot object """ try: t = Table.read('{0}/ukirt/{1}.dat'.format(filters_dir, name), format='ascii') except: raise ValueError('Could not find ukirt filter {0} in {1}/ukirt'.format( name, filters_dir)) # Convert wavelengths to angstroms (from microns) wave = t[t.keys()[0]] * 10000. trans = t[t.keys()[1]] # Change any negative numbers to 0 bad = np.where(trans < 0) trans[bad] = 0 spectrum = pysynphot.ArrayBandpass(wave, trans, waveunits='angstrom', name='ukirt_{0}'.format(name)) return spectrum
def get_2mass_filt(name): """ Define the 2mass filters as a pysynphot spectrum object """ # Read in filter info try: t = Table.read('{0}/2mass/{1}.dat'.format(filters_dir, name), format='ascii') except: raise ValueError( 'Could not find 2MASS filter file {0}/2mass/{1}.dat'.format( filters_dir, name)) wavelength = t[t.keys()[0]] transmission = t[t.keys()[1]] # Convert wavelength to Angstroms wavelength = wavelength * 10**4 # Make spectrum object spectrum = pysynphot.ArrayBandpass(wavelength, transmission, waveunits='angstrom', name='2MASS_{0}'.format(name)) return spectrum
def get_vista_filt(name): """ Define vista filter as pysynphot spectrum object """ # Read in filter info try: t = Table.read('{0}/vista/VISTA_Filters_at80K_forETC_{1}.dat'.format( filters_dir, name), format='ascii') except: raise ValueError( 'Could not find VISTA filter file {0}/vista/VISTA_Filters_at80K_forETC_{1}.dat' .format(filters_dir, name)) # Wavelength must be in angstroms, transmission in fraction wave = t['col1'] * 10 trans = t['col2'] * 0.01 # Change any negative numbers to 0, as well as anything shortward # of 0.4 microns or longward of 2.9 microns # (no VISTA filter transmissions beyond these boundaries) bad = np.where((trans < 0) | (wave < 4000) | (wave > 29000)) trans[bad] = 0 # Now we can define the VISTA filter bandpass objects spectrum = pysynphot.ArrayBandpass(wave, trans, waveunits='angstrom', name='VISTA_{0}'.format(name)) return spectrum
def get_ubv_filt(name): """ Define ubv (Johnson-Cousin filters) as pysynphot object """ try: t = Table.read('{0}/ubv/{1}.dat'.format(filters_dir, name), format='ascii') except: raise ValueError('Could not find ubv filter {0} in {1}/ubv'.format( name, filters_dir)) # Convert wavelength from nm to angstroms wave = t[t.keys()[0]] * 10. # Convert transmission to ratio (from percent) trans = t[t.keys()[1]] / 100. # Change any negative numbers to 0 bad = np.where(trans < 0) trans[bad] = 0 spectrum = pysynphot.ArrayBandpass(wave, trans, waveunits='angstrom', name='ubv_{0}'.format(name)) return spectrum
def get_decam_filt(name): """ Define DECAM filter as pysynphot object """ # Read in filter info try: t = Table.read('{0}/decam/DECam_filters.txt'.format(filters_dir), format='ascii') t.rename_column('Y', 'y') cols = np.array(t.keys()) idx = np.where(cols == name)[0][0] trans = t[cols[idx]] except: raise ValueError( 'Could not find DECAM filter {0} in {1}/decam/DECam_filters.txt'. format(name, filters_dir)) # Limit to unmasked regions only mask = np.ma.getmask(trans) good = np.where(mask == False) # Convert wavelengths from nm to angstroms, while eliminating masked regions wave = t['wavelength'][good] * 10. trans = trans[good] wave = np.ma.filled(wave) trans = np.ma.filled(trans) spectrum = pysynphot.ArrayBandpass(wave, trans, waveunits='angstrom', name='decam_{0}'.format(name)) return spectrum
def bandpass(self): if hasattr(self, "_bp"): return self._bp i = self.pandeia_instrument det_params = i.get_detector_pars() # 'rn_fudge': multiplied in to match IDT results. # 'var_fudge': chromatic fudge factor. quantum yield squared. # 'fullwell': # 'ff_electrons': # 'pix_size': # wr = i.get_wave_range() wave = np.linspace(wr['wmin'], wr['wmax'], num=500) pce = i.get_total_eff(wave) if pce[0] != 0.: wave = np.insert(wave, 0, wave[0] - (wave[1] - wave[0])) pce = np.insert(pce, 0, 0.) if pce[-1] != 0.: wave = np.append(wave, wave[-1] + (wave[-1] - wave[-2])) pce = np.append(pce, 0.) self._bp = ps.ArrayBandpass(wave=wave, throughput=pce, waveunits='micron', name='bp_{}_{}'.format( self.instrument, self.filter)) self._bp.convert('angstroms') return self._bp
def get_PS1_filt(name): """ Define PS1 filter as pysynphot object """ try: t = Table.read('{0}/ps1/PS1_filters.txt'.format(filters_dir), format='ascii') t.rename_column('col1', 'wave') t.rename_column('col2', 'open') t.rename_column('col3', 'g') t.rename_column('col4', 'r') t.rename_column('col5', 'i') t.rename_column('col6', 'z') t.rename_column('col7', 'y') cols = np.array(t.keys()) idx = np.where(cols == name)[0][0] trans = t[cols[idx]] except: raise ValueError('Could not find PS1 filter {0} in {1}/ps1'.format( name, filters_dir)) # Convert wavelengths from nm to angstroms wave = t['wave'] * 10. spectrum = pysynphot.ArrayBandpass(wave, trans, waveunits='angstrom', name='ps1_{0}'.format(name)) return spectrum
def get_nirc1_filt(name): """ Define Keck/NIRC filters as pysynphot object """ try: t = Table.read('{0}/nirc1/{1}.txt'.format(filters_dir, name), format='ascii') except: raise ValueError('Could not find NIRC1 filter {0} in {1}/nirc1'.format(name, filters_dir)) # Convert wavelengths to angstroms wave = t['col1'] * 10**4 trans = t['col2'] # Lets fix wavelength array for duplicate values or negative vals; # delete these entries diff = np.diff(wave) idx = np.where(diff <= 0)[0] while(len(idx) != 0): bad = idx + 1 wave = np.delete(wave, bad) trans = np.delete(trans, bad) diff = np.diff(wave) idx = np.where(diff <= 0)[0] # Change any negative transmission vals to 0 bad = np.where(trans < 0) trans[bad] = 0 spectrum = pysynphot.ArrayBandpass(wave, trans, waveunits='angstrom', name='nirc1_{0}'.format(name)) return spectrum
def get_jwst_filt(name): """ Define JWST filter as pysynphot object """ try: t = Table.read('{0}/jwst/{1}.txt'.format(filters_dir, name), format='ascii') except: raise ValueError('Could not find JWST filter {0} in {1}/jwst'.format( name, filters_dir)) # Convert wavelengths to angstroms wave = t['microns'] * 10**4. trans = t['throughput'] # Change any negative numbers to 0 bad = np.where(trans < 0) trans[bad] = 0 spectrum = pysynphot.ArrayBandpass(wave, trans, waveunits='angstrom', name='jwst_{0}'.format(name)) return spectrum
def apply_filter(stars, colour): """ Generates a binary filter based on the colour selected and passes the stars spectrum through this filter, being normalised to its actual magnitude as observed outputs an oberservation from this spectrum for use in other programs """ nwavels = 3501 wavels = np.linspace(3500, 7000, nwavels) if colour == "red": throughput = custom_bandpass(wavels, [5750, 6500]) # 750nm range elif colour == "green": throughput = custom_bandpass(wavels, [4750, 6000]) # 1250nm range elif colour == "blue": throughput = custom_bandpass(wavels, [4000, 5250]) # 1250nm range band_bin = S.ArrayBandpass(wavels, throughput) for star in stars: star_obj = star[0] mag = star[3] filtered_spec = star_obj.renorm(mag, 'vegamag', band_bin) observation = S.Observation(filtered_spec, band_bin, binset=wavels) star.append(filtered_spec) star.append(observation) return stars
def get_naco_filt(name): """ Define VLT NACO filters as pysynphot object """ try: t = Table.read('{0}/naco/{1}.dat'.format(filters_dir, name), format='ascii') except: raise ValueError('Could not find NACO filter {0} in {1}/naco'.format( name, filters_dir)) # Convert wavelengths to angstroms wave = t['col1'] * 10**4 trans = t['col2'] # Change any negative numbers to 0 bad = np.where(trans < 0) trans[bad] = 0 spectrum = pysynphot.ArrayBandpass(wave, trans, waveunits='angstrom', name='naco_{0}'.format(name)) return spectrum
def SVO_passband(pb, pbzp=None, List = False): """ Read a SVO passband using https://github.com/hover2pi/svo_filters. Parameters ---------- pb : str pysynphot obsmode or obsmode listed in `pbzptmag.txt` pbzp : float, optional AB magnitude zeropoint of the passband List : Bool, optional List all filters available through SVO Returns ------- pb : :py:class:`pysynphot.ArrayBandpass` or :py:class:`pysynphot.obsbandpass.ObsModeBandpass` The passband data. Has ``dtype=[('wave', '<f8'), ('throughput', '<f8')]`` pbzp : float passband AB zeropoint - potentially NaN if this was not supplied. If NaN this can be computed assuming an AB source - i.e. a source with a flux density of 3631 jy has magnitude = 0 in the bandpass. Notes ----- Note that this is a straight read of a single passband from a file. The zeropoint returned is whatever was provided (even if the value is not useful) or NaN. To load the passband and get the correct zeropoint, use :py:func:`source_synphot.passband.load_pbs` See Also -------- :py:func:`astropy.table.Table.read` :py:func:`pysynphot.ObsBandpass` """ from svo_filters import svo from astropy import units as u if List: print(list(svo.filters()['Band'])) if pbzp is None: pbzp = np.nan try: pbdata = svo.Filter(pb) wav = pbdata.wave.to(u.Angstrom).flatten().value wav, ind = np.unique(wav, return_index=True) out = S.ArrayBandpass(wav, pbdata.throughput.flatten()[ind], waveunits='Angstrom', name=pb) except (OSError,IOError) as e: message = 'No passband called {} in SVO'.format(pb) out = None if out is None: raise ValueError(message) return out, pbzp
def defarrays(self): #Supposes that the range variables have already been set w = N.arange(*self.sprange) f = N.zeros(w.shape) f[slice(*(self.spnonzero - w[0]))] += 1.0 self.sp = S.ArraySpectrum(wave=w, flux=f) w = N.arange(*self.bprange) t = N.zeros(w.shape) t[slice(*(self.bpnonzero - w[0]))] += 1 self.bp = S.ArrayBandpass(w, t)
def __call__(self, ebmv, sp=bb): """ Returns a pysynphot spectral element instance. If sp is not specified, use the default wavelength set from the BlackBody spectrum. Assume that sp.wave is in angstrom. """ t = self.function(sp.wave / 1.e4, ebmv, Alambda=False) ext = S.ArrayBandpass(wave=sp.wave, throughput=t, waveunits='angstrom') return ext
def get_gaia_filt(version, name): """ Define Gaia filters as pysynphot object version: specify dr1, dr2, or dr2_rev name: filter name """ # Set the filter directory if version == 'dr1': path = '{0}/gaia/dr1/'.format(filters_dir) elif version == 'dr2': path = '{0}/gaia/dr2/'.format(filters_dir) elif version == 'dr2_rev': path = '{0}/gaia/dr2_rev/'.format(filters_dir) else: raise ValueError( 'GAIA filter version {0} not understood. Please use dr1, dr2, or dr2_rev' .format(version)) # Get the filter info try: t = Table.read('{0}/Gaia_passbands.txt'.format(path), format='ascii') if version == 'dr1': t.rename_column('BP', 'Gbp') t.rename_column('RP', 'Grp') else: t.rename_column('col1', 'LAMBDA') t.rename_column('col2', 'G') t.rename_column('col4', 'Gbp') t.rename_column('col6', 'Grp') cols = np.array(t.keys()) idx = np.where(cols == name)[0][0] trans = t[cols[idx]] # Change 99 values where filters are undefined into 0, to ensure that # it doesn't mess up our flux values bad = np.where(trans > 90) trans[bad] = 0 except: raise ValueError('Could not find Gaia filter {0}'.format(name)) # Convert wavelengths to angstroms (from nm) wave = t['LAMBDA'] * 10 spectrum = pysynphot.ArrayBandpass(wave, trans, waveunits='angstrom', name='gaia_{0}_{1}'.format( version, name)) return spectrum
def testflip_bp(self): #create a bandpass with wavelength in descending order T = self.bp.throughput self.bp2 = S.ArrayBandpass(wave=self.bp.wave[::-1], throughput=T[::-1], waveunits=self.sp.waveunits) #.throughput calls __call__ calls resample ref = self.bp.throughput[::-1] tst = self.bp2.throughput idxr = N.where(ref != 0)[0] idxt = N.where(tst != 0)[0] self.assertEqualNumpy(idxr, idxt) self.assertApproxNumpy(ref[idxr], tst[idxr])
def monoband(lambda_central, width=100): """construct a uniform bandpass @ lambda_central & width""" # can just use pysynphot.Box... wlo = lambda_central - width + 1 w0 = lambda_central - width / 2. + 1 w1 = lambda_central + width / 2. + 1 whi = lambda_central + width waveset = arange(wlo, whi) fluxset1 = zeros(len(arange(wlo, w0))) fluxset2 = ones(len(arange(w0, w1))) fluxset3 = zeros(len(arange(w1, whi))) fluxset = concatenate([fluxset1, fluxset2, fluxset3]) uni = S.ArrayBandpass(waveset, fluxset) #uni = uni.compute(waveset) return uni
def get_keck_osiris_filt(name): """ Define keck osiris filters as pysynphot object """ try: t = Table.read('{0}/keck_osiris/{1}.txt'.format(filters_dir, name), format='ascii') except: raise ValueError('Could not find keck_osiris filter {0} in {1}/keck_osiris'.format(name, filters_dir)) # Convert wavelengths to angstroms (from nm), percentage throughput to fraction wave = t['col1'] * 10 trans = t['col2'] / 100. spectrum = pysynphot.ArrayBandpass(wave, trans, waveunits='angstrom', name='keck_osiris_{0}'.format(name)) return spectrum
def get_ztf_filt(name): """ Define ztf filters as pysynphot object """ try: t = Table.read('{0}/ztf/{1}.dat'.format(filters_dir, name), format='ascii') except: raise ValueError('Could not find ztf filter {0} in {1}/ztf'.format(name, filters_dir)) wave = t['Wavelength'] trans = t['Transmission'] spectrum = pysynphot.ArrayBandpass(wave, trans, waveunits='angstrom', name='ztf_{0}'.format(name)) return spectrum
def setUp(self): #Hand-make an observation with well defined ranges w = N.arange(1000, 1100, 0.5) self.sp = S.ArraySpectrum(wave=w, flux=(w - 1000), fluxunits='counts', name='slope1') #Hand make a box so it has fewer points self.bp = S.ArrayBandpass(wave=N.array( [1000, 1009.95, 1010, 1030, 1030.05, 1100]), throughput=N.array([0, 0, 1, 1, 0, 0]), name='HandBox') #self.bp=S.Box(1020,20) self.obs = S.Observation(self.sp, self.bp, binset=N.arange(w[6], w[40]))
def GetAllLSSTBands(path): wl_u,tot_u,wl_g,tot_g,wl_r,tot_r,wl_i,tot_i,wl_z,tot_z,wl_y4,tot_y4=GetAllLSSTTransmissions(path) bp_u = S.ArrayBandpass(wl_u*10.,tot_u, name='LSST_U') bp_g = S.ArrayBandpass(wl_g*10.,tot_g, name='LSST_G') bp_r = S.ArrayBandpass(wl_r*10,tot_r, name='LSST_R') bp_i = S.ArrayBandpass(wl_i*10.,tot_i, name='LSST_I') bp_z = S.ArrayBandpass(wl_z*10.,tot_z, name='LSST_Z') bp_y4 = S.ArrayBandpass(wl_y4*10,tot_y4, name='LSST_Y4') return bp_u,bp_g,bp_r,bp_i,bp_z,bp_y4
def make_bandpass(lam_obs, z_em): lam_ly = [ 1216 * (1. + z_em) + 0.01, 1216 * (1. + z_em) - 0.01, 1026 * (1. + z_em) + 0.01, 1026 * (1. + z_em) - 0.01 ] lam_ly += [ 973 * (1. + z_em) + 0.01, 973 * (1. + z_em) - 0.01, 950 * (1. + z_em) + 0.01, 950 * (1. + z_em) - 0.01 ] lam_obs = concatenate([lam_obs, lam_ly]) lam_obs = unique1d(lam_obs) lam_obs = sort(lam_obs) tau_eff = tau2(lam_obs, z_em) + tau3(lam_obs, z_em) + tau4( lam_obs, z_em) + tau5(lam_obs, z_em) #trans = exp(-1.*tau_eff) trans = where(lam_obs < (912. * (1. + z_em)), 0., exp(-1. * tau_eff)) # set transmitted flux to zero beyond Lyman limit bp = S.ArrayBandpass(wave=lam_obs, throughput=trans) return bp
def get_nirc2_filt(name): """ Define nirc2 filter as a pysynphot spectrum object """ # Read in filter info try: t = Table.read('{0}/nirc2/{1}.dat'.format(filters_dir, name), format='ascii') except: raise ValueError( 'Could not find NIRC2 filter file {0}/nirc2/{1}.dat'.format( filters_dir, name)) wavelength = t[t.keys()[0]] transmission = t[t.keys()[1]] # Lets fix wavelength array for duplicate values diff = np.diff(wavelength) idx = np.where(diff <= 0)[0] while len(idx) != 0: wavelength[idx + 1] += 1.0e-8 diff = np.diff(wavelength) idx = np.where(diff <= 0)[0] #print( 'Duplicate entry loop' ) # Get rid of all entries with negative transmission idx = np.where(transmission > 1)[0] # Convert wavelength to Angstroms, transmission to ratio wavelength = wavelength[idx] * 10**4 transmission = transmission[idx] / 100.0 # convert from % to ratio # Make spectrum object spectrum = pysynphot.ArrayBandpass(wavelength, transmission, waveunits='angstrom', name='NIRC2_{0}'.format(name)) return spectrum
def create_stellar_obs(aperture, central_obscuration, nwavels, wl_range, star_dict): """ Creates an observation object from pysynphot phoenix models Parameters: Aperture (cm): Aperture of the telescope central_obscuration (cm): diameter of central obscuration of telescope nwaels: number of wavelengths to sample wl_range (Angstroms): [first wavelength, last wavelength] star_dict: dictionary of the following structure {"mag": float, # vega mag "Teff": int, "Z": float, "log g": float} Returns: A pysynphot observation object describing the star being observed through the given telescope architecture """ # Set Telescope values r = (aperture - central_obscuration) / 2 collecting_area = (np.pi * r**2) S.refs.setref(area=collecting_area) # Takes units of cm^2 wavels = np.linspace(wl_range[0], wl_range[1], nwavels) throughput = np.ones(nwavels) bandpass = S.ArrayBandpass(wavels, throughput) # Create star object star_obj = S.Icat('phoenix', star_dict["Teff"], star_dict["Z"], star_dict["log g"]) spec_filt = star_obj.renorm(star_dict["mag"], 'vegamag', bandpass) # Create observation object obs = S.Observation(spec_filt, bandpass, binset=wavels) return obs
def ABmag(spec, bandpass): if bandpass == None: bandpass = S.ArrayBandpass(defwaveset, ones(len(defwaveset))) stflux = 10.**(48.6 / -2.5) abu = S.ArraySpectrum(defwaveset, ones(len(defwaveset)) * 10.**(48.6 / -2.5), fluxunits='fnu') #abu = spectrum.FlatSpectrum(10.**(48.6/-2.5),fluxunits='fnu') if bandpass.wave[-1] > spec.wave[-1]: # if bandpass wavelenth range is longer than spectrum n = searchsorted(bandpass.wave, spec.wave[-1]) merge = concatenate((spec.wave, bandpass.wave[n:])) merge = sort(unique(merge)) flux_standard = S.ArraySpectrum(merge, ones(len(merge)) * stflux, fluxunits='fnu') else: flux_standard = S.ArraySpectrum(spec.wave, ones(len(spec.wave)) * stflux, fluxunits='fnu') # Sets the wavelength array of abu # print spec.flux.min(),spec.flux.max() # print spec.flux # l = format("%10.1f %10.2e",spec.wave,spec.flux) # print l # print (spec*bandpass).integrate() # print (flux_standard*bandpass).integrate() numerator = (spec * bandpass).integrate() denominator = (flux_standard * bandpass).integrate() ratio = numerator / denominator if ratio <= 0.: abmag = 999. else: abmag = -2.5 * math.log10(ratio) return abmag