def test_get_local_s2n(): spec = XSpectrum1D.from_file(data_path('UM184_nF.fits')) wv0 = 4000 * u.AA s2n, sig_s2n = spec.get_local_s2n(wv0, 20, flux_th=0.9) np.testing.assert_allclose(s2n, 9.30119800567627, rtol=1e-5) np.testing.assert_allclose(sig_s2n, 1.0349911451339722, rtol=1e-5) # test with continuum spec.co = np.ones_like(spec.flux) s2n, sig_s2n = spec.get_local_s2n(wv0, 20, flux_th=0.9) np.testing.assert_allclose(s2n, 10.330545425415039, rtol=1e-5) np.testing.assert_allclose(sig_s2n, 0.4250050187110901, rtol=1e-5) # test errors # out of range with pytest.raises(IOError): spec.get_local_s2n(1215*u.AA, 20) # sig not defined spec = XSpectrum1D.from_tuple((spec.wavelength, spec.flux)) with pytest.raises(ValueError): spec.get_local_s2n(wv0, 20) # bad shape for flux_th with pytest.raises(ValueError): spec.get_local_s2n(wv0, 20, flux_th=np.array([1,2,3,4,5])) # npix too big with pytest.raises(ValueError): spec.get_local_s2n(wv0, 1 + len(spec.wavelength))
def test_from_tuple(): tmp = ascii.read(data_path('UM184.dat.gz'), names=['wave', 'flux', 'sig']) idl = dict(wave=np.array(tmp['wave']), flux=np.array(tmp['flux']), sig=np.array(tmp['sig'])) spec = XSpectrum1D.from_tuple((idl['wave'], idl['flux'], idl['sig'])) # np.testing.assert_allclose(spec.data['wave'][spec.select], idl['wave']) np.testing.assert_allclose(spec.data['sig'][spec.select], idl['sig'], atol=2e-3, rtol=0) assert spec.wavelength.unit == u.Unit('AA') # spec = XSpectrum1D.from_tuple((idl['wave'], idl['flux'])) np.testing.assert_allclose(spec.data['wave'][spec.select], idl['wave']) # continuum co = np.ones_like(idl['flux']) spec = XSpectrum1D.from_tuple((idl['wave'], idl['flux'], idl['sig'], co)) np.testing.assert_allclose(spec.data['wave'][spec.select], idl['wave']) co = None spec = XSpectrum1D.from_tuple((idl['wave'], idl['flux'], idl['sig'], co)) np.testing.assert_allclose(spec.data['wave'][spec.select], idl['wave'])
def test_get_local_s2n(): spec = XSpectrum1D.from_file(data_path('UM184_nF.fits')) wv0 = 4000 * u.AA s2n, sig_s2n = spec.get_local_s2n(wv0, 20, flux_th=0.9) np.testing.assert_allclose(s2n, 9.30119800567627, rtol=1e-5) np.testing.assert_allclose(sig_s2n, 1.0349911451339722, rtol=1e-5) # test with continuum spec.co = np.ones_like(spec.flux) s2n, sig_s2n = spec.get_local_s2n(wv0, 20, flux_th=0.9) np.testing.assert_allclose(s2n, 10.330545425415039, rtol=1e-5) np.testing.assert_allclose(sig_s2n, 0.4250050187110901, rtol=1e-5) # test errors # out of range with pytest.raises(IOError): spec.get_local_s2n(1215 * u.AA, 20) # sig not defined spec = XSpectrum1D.from_tuple((spec.wavelength, spec.flux)) with pytest.raises(ValueError): spec.get_local_s2n(wv0, 20) # bad shape for flux_th with pytest.raises(ValueError): spec.get_local_s2n(wv0, 20, flux_th=np.array([1, 2, 3, 4, 5])) # npix too big with pytest.raises(ValueError): spec.get_local_s2n(wv0, 1 + len(spec.wavelength))
def init_conti_full(self): print("Initializing the continuum") spec = self.spec_widg.orig_spec spec.select = self.model_spec # Just in case, but this should already be the case # Full Model (LLS+continuum) self.full_model = XSpectrum1D.from_tuple( (spec.wavelength, np.ones(len(spec.wavelength)))) self.conti_dict = pycc.init_conti_dict( Norm=float(np.median(spec.flux.value)), piv_wv=1215. * (1 + self.zqso), #piv_wv2=915.*(1+zqso), igm='True') # Read Telfer and apply IGM if self.template is not None: tspec = lsi.readspec(self.template) # assume wavelengths tspec = XSpectrum1D.from_tuple( (tspec.wavelength.value * (1 + self.zqso), tspec.flux.value)) else: tspec = pycq.get_telfer_spec( zqso=self.zqso, igm=(self.conti_dict['igm'] == 'True')) # Rebin self.continuum = tspec.rebin(spec.wavelength) # Reset pivot wave self.conti_dict['piv_wv'] = 915. * (1 + self.zqso) #self.conti_dict['piv_wv'] = 1215.*(1+zqso) #self.conti_dict['piv_wv2'] = 915.*(1+zqso) self.base_continuum = self.continuum.flux self.update_conti() self.spec_widg.continuum = self.continuum
def load_spectrum(spec_fil): '''Load X-Shooter spectra''' # Load Spectrum uvb_spec = XSpectrum1D.from_file(spec_fil) vis_specfil = spec_fil.replace('uvb', 'vis') vis_spec = XSpectrum1D.from_file(vis_specfil) comb_spec = uvb_spec.splice(vis_spec) comb_spec.filename = spec_fil # Return return comb_spec
def insert_dlas(sightline, overlap=False, rstate=None, slls=False, mix=False, high=False, noise=False): """ Insert a DLA into input spectrum Also adjusts the noise Will also add noise 'everywhere' if requested Parameters ---------- sightline:dla_cnn.data_model.sightline.Sightline object overlap: bool noise: bool, optional Returns ------- None """ #init if rstate is None: rstate = np.random.RandomState() spec = XSpectrum1D.from_tuple( (10**sightline.loglam, sightline.flux)) #generate xspectrum1d # Generate DLAs dlas = [] spec_dlas = [] zabslist = init_zabs(sightline, overlap) for zabs in zabslist: # Random NHI NHI = uniform_NHI(slls=slls, mix=mix, high=high) spec_dla = Dla((1 + zabs) * 1215.6701, NHI, '00' + str(jj)) if (slls or mix): dla = LLSSystem((sightline.ra, sightline.dec), zabs, None, NHI=NHI) else: dla = DLASystem((sightline.ra, sightline.dec), zabs, None, NHI) dlas.append(dla) spec_dlas.append(spec_dla) # Insert dlas to one sightline vmodel, _ = hi_model(dlas, spec, fwhm=3.) #add noise if noise: rand = rstate.randn(len(sightline.flux)) noise = rand * sightline.error * np.sqrt(1 - vmodel.flux.value**2) else: noise = 0 final_spec = XSpectrum1D.from_tuple( (vmodel.wavelength, spec.flux.value * vmodel.flux.value + noise)) #generate new sightline sightline.flux = final_spec.flux.value sightline.dlas = spec_dlas sightline.s2n = estimate_s2n(sightline)
def test_wvmnx(): npix = 1000 # Without sig spec = XSpectrum1D.from_tuple((np.linspace(5000.,6000,npix), np.ones(npix))) assert spec.wvmin.value == 5000. assert spec.wvmax.value == 6000. # With sig spec = XSpectrum1D.from_tuple((np.linspace(5000.,6000,npix), np.ones(npix), np.ones(npix)*0.1)) assert spec.wvmin.value == 5000. assert spec.wvmax.value == 6000.
def xspectrum1d_from_mpdaf_spec(sp, airvac='air'): """Gets a XSpectrum1D object in vacuum from an MPDAF Spectrum""" nomask = ~sp.mask fl = sp.data[nomask] er = np.sqrt(sp.var[nomask]) wv = sp.wave.coord()[nomask] meta = dict(airvac=airvac) spec = XSpectrum1D.from_tuple((wv, fl, er), meta=meta) spec.airtovac() spec2 = XSpectrum1D.from_tuple((spec.wavelength, fl, er)) return spec2
def test_mask_edge(): wave = 3000. + np.arange(1000) flux = np.ones_like(wave) sig = 0.1*np.ones_like(wave) sig[900:] = 0. sig[800:825] = 0. wave[900:] = 0. # WARNING, the data are sorted first! # spec = XSpectrum1D.from_tuple((wave,flux,sig), masking='edges') assert len(spec.wavelength) == 900 spec2 = XSpectrum1D.from_tuple((wave,flux,sig), masking='all') assert len(spec2.wavelength) == 875
def test_errors(): # from_tuple try: spec = XSpectrum1D.from_tuple('this_is_not_a_tuple') except IOError: pass try: n_tuple = np.array([np.ones(5), np.ones(5)]), np.ones(5) spec = XSpectrum1D.from_tuple(n_tuple) except IOError: pass # wrong instances flux = [1,2,3] wave = [1,2,3] try: spec = XSpectrum1D(wave, flux) except IOError: pass #wrong shapes flux = np.ones(5) wave = np.array([1,2,3]) try: spec = XSpectrum1D(wave, flux) except IOError: pass try: spec = XSpectrum1D(wave, np.ones(len(wave)), sig=np.ones(2)) except IOError: pass try: spec = XSpectrum1D(wave, np.ones(len(wave)), co=np.ones(2), verbose = True) # test verbose here too except IOError: pass # wrong masking try: spec = XSpectrum1D(wave, np.ones(len(wave)), masking = 'wrong_masking') except IOError: pass #wrong units input try: spec = XSpectrum1D(wave, np.ones(len(wave)), units = 'not_a_dict') except IOError: pass try: spec = XSpectrum1D(wave, np.ones(len(wave)), units =dict(wrong_key=2)) except IOError: pass
def test_masking(): wave = 3000. + np.arange(1000) flux = np.ones_like(wave) sig = 0.1 * np.ones_like(wave) sig[900:] = 0. sig[800:825] = 0. wave[900:] = 0. # WARNING, the data are sorted first! # spec = XSpectrum1D.from_tuple((wave, flux, sig), masking='edges') assert len(spec.wavelength) == 900 spec2 = XSpectrum1D.from_tuple((wave, flux, sig), masking='all') assert len(spec2.wavelength) == 875 spec3 = XSpectrum1D.from_tuple((wave, flux, sig), masking='none') assert len(spec3.wavelength) == len(wave)
def test_errors(): # from_tuple try: spec = XSpectrum1D.from_tuple('this_is_not_a_tuple') except IOError: pass try: n_tuple = np.array([np.ones(5), np.ones(5)]), np.ones(5) spec = XSpectrum1D.from_tuple(n_tuple) except IOError: pass # wrong instances flux = [1, 2, 3] wave = [1, 2, 3] try: spec = XSpectrum1D(wave, flux) except IOError: pass #wrong shapes flux = np.ones(5) wave = np.array([1, 2, 3]) try: spec = XSpectrum1D(wave, flux) except IOError: pass try: spec = XSpectrum1D(wave, np.ones(len(wave)), sig=np.ones(2)) except IOError: pass try: spec = XSpectrum1D(wave, np.ones(len(wave)), co=np.ones(2), verbose=True) # test verbose here too except IOError: pass # wrong masking try: spec = XSpectrum1D(wave, np.ones(len(wave)), masking='wrong_masking') except IOError: pass #wrong units input try: spec = XSpectrum1D(wave, np.ones(len(wave)), units='not_a_dict') except IOError: pass try: spec = XSpectrum1D(wave, np.ones(len(wave)), units=dict(wrong_key=2)) except IOError: pass
def load_1dspec(fname, exten=None, extract='OPT', objname=None, flux=False): """ Parameters ---------- fname : str Name of the file exten : int, optional Extension of the spectrum If not given, all spectra in the file are loaded extract : str, optional Extraction type ('opt', 'box') objname : str, optional Identify extension based on input object name flux : bool, optional Return fluxed spectra? Returns ------- spec : XSpectrum1D """ # Identify extension from objname? if objname is not None: hdulist = fits.open(fname) hdu_names = [hdu.name for hdu in hdulist] exten = hdu_names.index(objname) if exten < 0: msgs.error("Bad input object name: {:s}".format(objname)) # Keywords for Table rsp_kwargs = {} if flux: rsp_kwargs['flux_tag'] = '{:s}_FLAM'.format(extract) rsp_kwargs['sig_tag'] = '{:s}_FLAM_SIG'.format(extract) else: rsp_kwargs['flux_tag'] = '{:s}_COUNTS'.format(extract) rsp_kwargs['sig_tag'] = '{:s}_COUNTS_SIG'.format(extract) # Use the WAVE_GRID (for 2d coadds) if it exists, otherwise use WAVE rsp_kwargs['wave_tag'] = '{:s}_WAVE_GRID'.format(extract) # Load try: spec = XSpectrum1D.from_file(fname, exten=exten, **rsp_kwargs) except ValueError: rsp_kwargs['wave_tag'] = '{:s}_WAVE'.format(extract) spec = XSpectrum1D.from_file(fname, exten=exten, **rsp_kwargs) # Return return spec
def xspectrum1d_from_mpdaf_spec(sp, airvac='air'): """Gets a XSpectrum1D object in vacuum from an MPDAF Spectrum It does not take into account whether the wv is in air or vac anymore """ nomask = ~sp.mask fl = sp.data[nomask] er = np.sqrt(sp.var[nomask]) wv = sp.wave.coord()[nomask] meta = dict(airvac=airvac) spec = XSpectrum1D.from_tuple((wv, fl, er), meta=meta) #spec.airtovac() # print("\t Hola!!!!!!!!!!!!!!1") spec2 = XSpectrum1D.from_tuple((spec.wavelength, fl, er)) return spec2
def test_readwrite_meta_as_dicts(spec): sp = XSpectrum1D.from_tuple((np.array([5,6,7]), np.ones(3), np.ones(3)*0.1)) sp.meta['headers'][0] = dict(a=1, b='abc') sp2 = XSpectrum1D.from_tuple((np.array([8,9,10]), np.ones(3), np.ones(3)*0.1)) sp2.meta['headers'][0] = dict(c=2, d='efg') spec = ltsu.collate([sp,sp2]) # Write spec.write_to_fits(data_path('tmp.fits')) spec.write_to_hdf5(data_path('tmp.hdf5')) # Read and test newspec = io.readspec(data_path('tmp.hdf5')) assert newspec.meta['headers'][0]['a'] == 1 assert newspec.meta['headers'][0]['b'] == 'abc' newspec2 = io.readspec(data_path('tmp.fits')) assert 'METADATA' in newspec2.meta['headers'][0].keys()
def test_from_tuple(): idl = ascii.read(data_path('UM184.dat.gz'), names=['wave', 'flux', 'sig']) spec = XSpectrum1D.from_tuple((idl['wave'],idl['flux'],idl['sig'])) # np.testing.assert_allclose(spec.dispersion.value, idl['wave']) np.testing.assert_allclose(spec.sig, idl['sig'], atol=2e-3, rtol=0) assert spec.dispersion.unit == u.Unit('AA') # spec = XSpectrum1D.from_tuple((idl['wave'],idl['flux'])) np.testing.assert_allclose(spec.dispersion.value, idl['wave']) # continuum co = np.ones_like(idl['flux']) spec = XSpectrum1D.from_tuple((idl['wave'],idl['flux'],idl['sig'], co)) np.testing.assert_allclose(spec.dispersion.value, idl['wave'])
def dummy_spectrum(s2n=10., rstate=None, seed=1234, wave=None): """ Parameters ---------- s2n seed wave Returns ------- spec : XSpectrum1D """ if rstate is None: rstate=np.random.RandomState(seed) if wave is None: wave = np.linspace(4000., 5000., 2000) # Create flux = np.ones_like(wave) sig = np.ones_like(wave) / s2n ispec = XSpectrum1D.from_tuple((wave,flux,sig)) # Noise and append spec = ispec.add_noise(rstate=rstate) flux, sig, mask = spec.data['flux'], spec.data['sig'], spec.data['flux'].mask ivar = utils.inverse(sig**2) return flux, ivar, mask
def parse_DESI_brick(hdulist, select=0, **kwargs): """ Read a spectrum from a DESI brick format HDU list Parameters ---------- hdulist : FITS HDU list select : int, optional Spectrum selected. Default is 0 Returns ------- xspec1d : XSpectrum1D Parsed spectrum """ fx = hdulist[0].data # Sig if hdulist[1].name in ['ERROR', 'SIG']: sig = hdulist[1].data else: ivar = hdulist[1].data sig = np.zeros_like(ivar) gdi = ivar > 0. sig[gdi] = np.sqrt(1. / ivar[gdi]) # Wave wave = hdulist[2].data wave = give_wv_units(wave) if wave.shape != fx.shape: wave = np.tile(wave, (fx.shape[0], 1)) # Finish xspec1d = XSpectrum1D(wave, fx, sig, select=select, **kwargs) return xspec1d
def spec_from_array(wave, flux, sig, **kwargs): """ Make an XSpectrum1D from numpy arrays of wave, flux and sig Parameters ---------- If wave is unitless, Angstroms are assumed If flux is unitless, it is made dimensionless The units for sig and co are taken from flux. Return spectrum from arrays of wave, flux and sigma """ # Get rid of 0 wavelength good_wave = (wave > 1.0 * units.AA) wave, flux, sig = wave[good_wave], flux[good_wave], sig[good_wave] ituple = (wave, flux, sig) spectrum = XSpectrum1D.from_tuple(ituple, **kwargs) # Polish a bit -- Deal with NAN, inf, and *very* large values that will exceed # the floating point precision of float32 for var which is sig**2 (i.e. 1e38) bad_flux = np.any([ np.isnan(spectrum.flux), np.isinf(spectrum.flux), np.abs(spectrum.flux) > 1e30, spectrum.sig**2 > 1e10, ], axis=0) if np.sum(bad_flux): msgs.warn( "There are some bad flux values in this spectrum. Will zero them out and mask them (not ideal)" ) spectrum.data['flux'][spectrum.select][bad_flux] = 0. spectrum.data['sig'][spectrum.select][bad_flux] = 0. return spectrum
def get_telfer_spec(zqso=0., igm=False, fN_gamma=None, LL_flatten=True): '''Generate a Telfer QSO composite spectrum Parameters: ---------- zqso: float, optional Redshift of the QSO igm: bool, optional Include IGM opacity? [False] fN_gamma: float, optional Power-law evolution in f(N,X) LL_flatten: bool, optional Set Telfer to a constant below the LL? Returns: -------- telfer_spec: XSpectrum1D Spectrum ''' # Read telfer = ascii.read( xa_path+'/data/quasar/telfer_hst_comp01_rq.ascii', comment='#') scale = telfer['flux'][(telfer['wrest'] == 1450.)] telfer_spec = XSpectrum1D.from_tuple((telfer['wrest']*(1+zqso), telfer['flux']/scale[0])) # Observer frame # IGM? if igm is True: '''The following is quite experimental. Use at your own risk. ''' import multiprocessing from xastropy.igm.fN import model as xifm from xastropy.igm import tau_eff as xit fN_model = xifm.default_model() # Expanding range of zmnx (risky) fN_model.zmnx = (0.,5.) if fN_gamma is not None: fN_model.gamma = fN_gamma # Parallel igm_wv = np.where(telfer['wrest']<1220.)[0] adict = [] for wrest in telfer_spec.dispersion[igm_wv].value: tdict = dict(ilambda=wrest, zem=zqso, fN_model=fN_model) adict.append(tdict) # Run #xdb.set_trace() pool = multiprocessing.Pool(4) # initialize thread pool N threads ateff = pool.map(xit.map_etl, adict) # Apply telfer_spec.flux[igm_wv] *= np.exp(-1.*np.array(ateff)) # Flatten? if LL_flatten: wv_LL = np.where(np.abs(telfer_spec.dispersion/(1+zqso)-914.*u.AA)<3.*u.AA)[0] f_LL = np.median(telfer_spec.flux[wv_LL]) wv_low = np.where(telfer_spec.dispersion/(1+zqso)<911.7*u.AA)[0] telfer_spec.flux[wv_low] = f_LL # Return return telfer_spec
def __init__(self): super().__init__() self.setWindowTitle('My simple dialog app') button = QPushButton('Press me for a dialog!') button.clicked.connect(self.button_clicked) self.setCentralWidget(button) #Add your flux extraction code in here sp = XSpectrum1D.from_file('./example-data/test.fits') wave = sp.wavelength.value flux = sp.flux.value error = sp.sig.value q = np.where((wave > 1330) & (wave < 1340)) self.wave = wave[q] self.flux = flux[q] self.error = error[q] sizeObj = QDesktopWidget().screenGeometry(-1) print('Screen size:' + str(sizeObj.height()) + 'x' + str(sizeObj.width())) availObj = QDesktopWidget().availableGeometry(-1) print('Availble size:' + str(availObj.height()) + 'x' + str(availObj.width())) self.move(sizeObj.width() // 2, sizeObj.height() // 2)
def fit_cont(filename): from linetools.spectra.xspectrum1d import XSpectrum1D import re from astropy.coordinates import SkyCoord from linetools.isgm import abssystem as lt_absys from linetools.spectralline import AbsLine from linetools.isgm.abscomponent import AbsComponent from linetools import line_utils as ltlu from linetools.spectralline import AbsLine, SpectralLine import numpy from astropy.io import fits from glob import glob from astropy import units as u from linetools.lists.linelist import LineList import warnings warnings.filterwarnings('ignore') # Create a spectrum class object from the fits file sp = XSpectrum1D.from_file(filename) data, radec = get_prop(filename) # Call the GUI to interactively fit the continuum sp.fit_continuum(kind='QSO', redshift=data['zq']) # Normalize the Continuum sp.normalize(co=sp.co) # Write the Normalized Continuum to a new fits file sp.write_to_fits('n_' + filename) return print(filename + ' has been normalized and written to ' + 'n_' + filename)
def compare_s2n(pp,lrdx_sciobj,pypit_boxfile, iso): '''Compare boxcar S/N ''' # Read/Load pypit_boxspec = lsio.readspec(pypit_boxfile) # Read LowRedux sig = np.sqrt(lrdx_sciobj['MASK_BOX']/(lrdx_sciobj['SIVAR_BOX'] + (lrdx_sciobj['MASK_BOX']==0))) lwrdx_boxspec = XSpectrum1D.from_tuple( (lrdx_sciobj['WAVE_BOX'], lrdx_sciobj['FLUX_BOX'], sig) ) # Plot plt.clf() fig = plt.figure(figsize=(16,7)) fig.suptitle("Instr={:s}, Setup={:s} :: Boxcar S/N for {:s} :: PYPIT ({:s})".format(iso[0], iso[1], iso[2], pypit.version), fontsize=18.) ax = plt.gca() ymax = np.median(pypit_boxspec.flux)*2. # PYPIT gdpy = pypit_boxspec.sig > 0. pys2n = pypit_boxspec.flux[gdpy]/pypit_boxspec.sig[gdpy] ax.plot(pypit_boxspec.dispersion[gdpy],pys2n, 'k-', drawstyle='steps', label='PYPIT') # LowRedux gdlx = lwrdx_boxspec.sig > 0. ax.plot(lwrdx_boxspec.dispersion[gdlx], lwrdx_boxspec.flux[gdlx]/lwrdx_boxspec.sig[gdlx], '-', color='blue', label='LowRedux') # Axes ax.set_xlim(np.min(pypit_boxspec.dispersion.value), np.max(pypit_boxspec.dispersion.value)) ax.set_ylim(0.,np.median(pys2n)*2.) ax.set_xlabel('Wavelength',fontsize=17.) ax.set_ylabel('S/N per pixel',fontsize=17.) # Legend legend = plt.legend(loc='upper right', borderpad=0.3, handletextpad=0.3, fontsize='x-large') # Finish plt.tight_layout(pad=0.2,h_pad=0.,w_pad=0.1,rect=[0, 0.03, 1, 0.95]) pp.savefig(bbox_inches='tight') plt.close()
def dump_bestfit(ppfit, outfile=None, z=0.): """ Create the bestfit in the observer frame and with vacuum wavelengths Parameters ---------- ppfit outfile Returns ------- bestfit: XSpectrum1D """ meta = dict(airvac='air', headers=[None]) # Spectrum bestfit = XSpectrum1D.from_tuple( (ppfit.lam * (1 + z), ppfit.bestfit / (1 + z)), meta=meta) # Convert to vacuum bestfit.airtovac() # Write if outfile is not None: bestfit.write(outfile) # Return return bestfit
def extract_spectrum(cube,pixels,wvslice=None): from linetools.spectra.xspectrum1d import XSpectrum1D if isinstance(cube,str): cube = DataCube(cube) if wvslice is not None: cube = kt.slice_cube(cube,wvslice[0],wvslice[1]) dat = cube.data # Get rid of NaNs dc = dat.copy() nans = np.where(np.isnan(dc)) dc[nans]=0 # Perform the extraction spaxels = [] for i,px in enumerate(pixels): thisspec = dc[:,px[0],px[1]] spaxels.append(thisspec) spaxels=np.array(spaxels) medspec = np.median(spaxels, axis=0) # Get the wavelength array newwavearr = cube.wavelength # Create the spectrum try: spec = XSpectrum1D(wave = newwavearr,flux=medspec) except: import pdb; pdb.set_trace() return spec
def grab_specmeta(self, rows, verbose=None, masking='edges', use_XSpec=True, **kwargs): """ Grab the spectra and meta data for an input set of rows Aligned to the rows input Parameters ---------- rows : int or ndarray verbose kwargs Returns ------- spec : XSpectrum1D or ndarray Spectra requested, ordered by the input rows meta : Table -- THIS MAY BE DEPRECATED Meta table, ordered by the input rows """ if isinstance(rows, (int, np.int64)): rows = np.array([rows]) # Insures meta and other arrays are proper if verbose is None: verbose = self.verbose # Check spectra even exist! (can be only meta data) if 'spec' not in list(self.hdf[self.group].keys()): warnings.warn("No spectra in group: {:s}".format(self.group)) return None, None # Check memory if self.stage_data(rows, **kwargs): if verbose: print("Loaded spectra") # Load msk = np.array([False] * len(self.meta)) msk[rows] = True tmp_data = self.hdf[self.group]['spec'][msk] # Replicate and sort according to input rows idx = match_ids(rows, np.where(msk)[0]) data = tmp_data[idx] else: print("Staging failed.. Not returning spectra") return # Generate XSpectrum1D if 'co' in data.dtype.names: co = data['co'] else: co = None if use_XSpec: spec = XSpectrum1D(data['wave'], data['flux'], sig=data['sig'], co=co, masking=masking) else: spec = data # Return return spec, self.meta[rows]
def test_readwrite_meta_as_dicts(spec): sp = XSpectrum1D.from_tuple((np.array([5, 6, 7]), np.ones(3), np.ones(3) * 0.1)) sp.meta['headers'][0] = dict(a=1, b='abc') sp2 = XSpectrum1D.from_tuple( (np.array([8, 9, 10]), np.ones(3), np.ones(3) * 0.1)) sp2.meta['headers'][0] = dict(c=2, d='efg') spec = ltsu.collate([sp, sp2]) # Write spec.write_to_fits(data_path('tmp.fits')) spec.write_to_hdf5(data_path('tmp.hdf5')) # Read and test newspec = io.readspec(data_path('tmp.hdf5')) assert newspec.meta['headers'][0]['a'] == 1 assert newspec.meta['headers'][0]['b'] == 'abc' newspec2 = io.readspec(data_path('tmp.fits')) assert 'METADATA' in newspec2.meta['headers'][0].keys()
def parse_linetools_spectrum_format(hdulist): """ Parse an old linetools-format spectrum from an hdulist Parameters ---------- hdulist : FITS HDU list Returns ------- xspec1d : XSpectrum1D Parsed spectrum """ if 'WAVELENGTH' not in hdulist: pdb.set_trace() #spec1d = spec_read_fits.read_fits_spectrum1d( # os.path.expanduser(datfil), dispersion_unit='AA') xspec1d = XSpectrum1D.from_spec1d(spec1d) else: wave = hdulist['WAVELENGTH'].data * u.AA fx = hdulist['FLUX'].data # Error array if 'ERROR' in hdulist: sig = hdulist['ERROR'].data else: sig = None if 'CONTINUUM' in hdulist: co = hdulist['CONTINUUM'].data else: co = None xspec1d = XSpectrum1D.from_tuple((wave, fx, sig, co)) if 'METADATA' in hdulist[0].header: # import pdb; pdb.set_trace() # patch for reading continuum metadata; todo: should be fixed properly!!! if "contpoints" in hdulist[0].header['METADATA']: aux_s = hdulist[0].header['METADATA'] if aux_s.endswith("}\' /"): aux_s = aux_s[:-3] # delete these extra characters hdulist[0].header['METADATA'] = aux_s xspec1d.meta.update(json.loads(hdulist[0].header['METADATA'])) return xspec1d
def test_from_file(): spec = XSpectrum1D.from_file(data_path('UM184_nF.fits')) idl = ascii.read(data_path('UM184.dat.gz'), names=['wave', 'flux', 'sig']) np.testing.assert_allclose(spec.dispersion.value, idl['wave']) np.testing.assert_allclose(spec.sig, idl['sig'], atol=2e-3, rtol=0) assert spec.dispersion.unit == u.Unit('AA')
def wfc3_continuum(wfc3_indx=None, zqso=0., wave=None, smooth=3., NHI_max=17.5, rstate=None): '''Use the WFC3 data + models from O'Meara+13 to generate a continuum Parameters ---------- wfc3_indx : int, optional Index of WFC3 data to use zqso : float, optional Redshift of the QSO wave : Quantity array, optional Wavelengths to rebin on smooth : float, optional Number of pixels to smooth on NHI_max : float, optional Maximum NHI for the sightline Returns ------- wfc3_continuum : XSpectrum1D of the continuum idx : int Index of the WFC3 spectrum used ''' # Random number if rstate is None: rstate = np.random.RandomState() # Open wfc3_models_hdu = fits.open(os.getenv('DROPBOX_DIR')+'XQ-100/LLS/wfc3_conti_models.fits') nwfc3 = len(wfc3_models_hdu)-1 # Load up models wfc_models = [] for ii in range(1,nwfc3-1): wfc_models.append( Table(wfc3_models_hdu[ii].data) ) # Grab a random one if wfc3_indx is None: need_c = True while(need_c): idx = rstate.randint(0,nwfc3-1) if wfc_models[idx]['TOTNHI'] > NHI_max: continue if wfc_models[idx]['QSO'] in ['J122836.05+510746.2', 'J122015.50+460802.4']: continue # These QSOs are NG need_c=False else: idx = wfc3_indx # Generate spectrum wfc_spec = XSpectrum1D.from_tuple( (wfc_models[idx]['WREST'].flatten()*(1+zqso), wfc_models[idx]['FLUX'].flatten()) ) # Smooth wfc_smooth = wfc_spec.gauss_smooth(fwhm=smooth) # Rebin? if wave is not None: wfc_rebin = wfc_smooth.rebin(wave) return wfc_rebin, idx else: return wfc_smooth, idx
def __init__(self, filepath=''): self.fitsobj = FitsObj(wave=[]) self.filepath = filepath self.warning = '' try: self.sp = XSpectrum1D.from_file(self.filepath) except (OSError, KeyError, AttributeError): self.warning += 'XSpectrum1D cannot read this file.'
def loop_grab_spec(self, survey, IDs, verbose=None, **kwargs): """ Grab spectra using staged IDs All IDs must occur in each of the surveys listed Order of spectra and meta tables will match the input IDs Parameters ---------- survey : str or list IDs : int or intarr Returns ------- spec : XSpectrum1D Spectra requested, ordered by the IDs meta : Table Meta table, ordered by the IDs """ if verbose is None: verbose = self.verbose if isinstance(survey, list): all_spec = [] all_meta = [] for isurvey in survey: spec, meta = self.grab_spec(isurvey, IDs, **kwargs) if spec is not None: all_spec.append(spec.copy()) all_meta.append(meta.copy()) return all_spec, all_meta # Grab IDs if self.stage_data(survey, IDs, **kwargs): if np.sum(self.survey_bool) == 0: if verbose: print("No spectra matching in survey {:s}".format(survey)) return None, None else: if verbose: print("Loaded spectra") tmp_data = self.hdf[survey]['spec'][self.survey_bool] # Replicate and sort according to input IDs data = tmp_data[self.indices] else: print("Staging failed.. Not returning spectra") return # Generate XSpectrum1D if 'co' in data.dtype.names: co = data['co'] else: co = None spec = XSpectrum1D(data['wave'], data['flux'], sig=data['sig'], co=co, masking='edges') # Return return spec, self.meta
def parse_hdf5(inp, close=True, **kwargs): """ Read a spectrum from HDF5 written in XSpectrum1D format Expects: meta, data, units Parameters ---------- inp : str or hdf5 Returns ------- """ import json import h5py # Path path = kwargs.pop('path', '/') # Open if isinstance(inp, basestring): hdf5 = h5py.File(inp, 'r') else: hdf5 = inp # Data data = hdf5[path+'data'].value # Meta if 'meta' in hdf5[path].keys(): meta = json.loads(hdf5[path+'meta'].value) # Headers for jj,heads in enumerate(meta['headers']): try: meta['headers'][jj] = fits.Header.fromstring(meta['headers'][jj]) except TypeError: # dict if not isinstance(meta['headers'][jj], dict): raise IOError("Bad meta type") else: meta = None # Units units = json.loads(hdf5[path+'units'].value) for key,item in units.items(): if item == 'dimensionless_unit': units[key] = u.dimensionless_unscaled else: units[key] = getattr(u, item) # Other arrays try: sig = data['sig'] except (NameError, IndexError): sig = None try: co = data['co'] except (NameError, IndexError): co = None # Finish if close: hdf5.close() return XSpectrum1D(data['wave'], data['flux'], sig=sig, co=co, meta=meta, units=units, **kwargs)
def main(args): from scipy.io.idl import readsav from linetools.spectra.xspectrum1d import XSpectrum1D # Read lrdx_sky = readsav(args.lowrdx_sky) # Generate xspec = XSpectrum1D.from_tuple((lrdx_sky['wave_calib'], lrdx_sky['sky_calib'])) # Write xspec.write_to_fits(args.new_file)
def load_spec(self): '''Input the Spectrum ''' from linetools.spectra.xspectrum1d import XSpectrum1D if self._specfil is None: self.get_specfil() # if self.verbose: print('SdssQso: Loading spectrum from {:s}'.format(self._specfil)) self.spec = XSpectrum1D.from_file(self._specfil)
def calculate_empirical_rms(spec, test=False): fl = spec.flux.value wv = spec.wavelength.value min_cond = ltu.is_local_minima(fl) max_cond = ltu.is_local_maxima(fl) min_local_inds = np.where(min_cond)[0] max_local_inds = np.where(max_cond)[0] interpolated_max = interp1d(wv[max_local_inds], fl[max_local_inds], kind='linear', bounds_error=False, fill_value=0) interpolated_min = interp1d(wv[min_local_inds], fl[min_local_inds], kind='linear', bounds_error=False, fill_value=0) # these are the envelopes fl_max = interpolated_max(wv) fl_min = interpolated_min(wv) # take the mid value fl_mid = 0.5 * (fl_max + fl_min) # reference flux # the idea here is that these will be the intrinsic rms per pixel (both are the same though) max_mean_diff = np.abs(fl_mid - fl_max) min_mean_diff = np.abs(fl_mid - fl_min) sigma = 0.5 * ( max_mean_diff + min_mean_diff ) # anyways these two differences are the same by definition if test: # fluxes wv_mins = wv[min_local_inds] wv_maxs = wv[max_local_inds] plt.figure() plt.plot(wv, fl, drawstyle='steps-mid') plt.plot(wv_mins, fl[min_local_inds], marker='o', color='r', label='Local minimum') plt.plot(wv_maxs, fl[max_local_inds], marker='o', color='green', label='Local maximum') plt.plot(wv, fl_mid, color='black', label='flux_mid') # sigmas plt.plot(wv, sigma, marker='o-', color='pink', label='Empirical sigma') plt.plot(wv, spec.sig.value, color='yellow', label='Original sigma') plt.legend() plt.show() return XSpectrum1D.from_tuple((wv, fl, sigma))
def test_addmask(): spec = XSpectrum1D.from_file(data_path('UM184_nF.fits')) assert not spec.data['flux'][0].mask[100] mask = spec.data['flux'][0].mask.copy() mask[100:110] = True spec.add_to_mask(mask) assert spec.data['flux'][0].mask[100] # Compressed badp = spec.flux < 0.1 spec.add_to_mask(badp, compressed=True) assert np.sum(spec.data['flux'][0].mask) > 3000
def writeVPmodel(outfile, wave, fitpars, normflux, normsig): from astropy.table import Table model = voigtfunc(wave, fitpars) modeltab = Table([wave, model, normflux, normsig], names=['wavelength', 'model', 'normflux', 'normsig']) # modeltab.write(outfile, format='fits', overwrite=True) dummycont = np.ones(len(wave)) spec = XSpectrum1D.from_tuple((modeltab['wavelength'], modeltab['model'], modeltab['normsig'], dummycont)) spec.write_to_fits(outfile) print 'Voigt profile model written to:' print outfile
def test_copy(spec): # From existing spec2 = spec.copy() assert spec.wavelength[0] == spec2.wavelength[0] assert spec.flux[-1] == spec2.flux[-1] # wave = np.arange(3000., 6500) npix = len(wave) spect = XSpectrum1D.from_tuple((wave*u.AA,np.ones(npix))) specf = spect.copy() assert specf.sig_is_set is False
def dumb_spec(): """ Generate a dummy spectrum Returns ------- """ npix = 1000 dspec = XSpectrum1D.from_tuple((np.arange(npix)+5000., np.ones(npix), np.ones(npix))) # return dspec
def test_copy(spec): # From existing spec2 = spec.copy() assert spec.wavelength[0] == spec2.wavelength[0] assert spec.flux[-1] == spec2.flux[-1] # wave = np.arange(3000., 6500) npix = len(wave) spect = XSpectrum1D.from_tuple((wave * u.AA, np.ones(npix))) specf = spect.copy() assert specf.sig_is_set is False
def test_from_tuple(): tmp = ascii.read(data_path('UM184.dat.gz'), names=['wave', 'flux', 'sig']) idl = dict(wave=np.array(tmp['wave']), flux=np.array(tmp['flux']), sig=np.array(tmp['sig'])) spec = XSpectrum1D.from_tuple((idl['wave'],idl['flux'], idl['sig'])) # np.testing.assert_allclose(spec.data['wave'][spec.select], idl['wave']) np.testing.assert_allclose(spec.data['sig'][spec.select], idl['sig'], atol=2e-3, rtol=0) assert spec.wavelength.unit == u.Unit('AA') # spec = XSpectrum1D.from_tuple((idl['wave'],idl['flux'])) np.testing.assert_allclose(spec.data['wave'][spec.select], idl['wave']) # continuum co = np.ones_like(idl['flux']) spec = XSpectrum1D.from_tuple((idl['wave'],idl['flux'],idl['sig'], co)) np.testing.assert_allclose(spec.data['wave'][spec.select], idl['wave']) co = None spec = XSpectrum1D.from_tuple((idl['wave'],idl['flux'],idl['sig'], co)) np.testing.assert_allclose(spec.data['wave'][spec.select], idl['wave'])
def test_fluxmodel(): # Init lls = LLSSystem((0.*u.deg, 0.*u.deg), 2.5, None, NHI=17.9) # Fill LLS lines lls.fill_lls_lines() # Generate a spectrum wave = np.arange(3000., 6500) npix = len(wave) spec = XSpectrum1D.from_tuple((wave*u.AA,np.ones(npix))) # Model model = lls.flux_model(spec) np.testing.assert_allclose(model.flux[100].value,0.009424664763760516)
def parse_linetools_spectrum_format(hdulist, **kwargs): """ Parse an old linetools-format spectrum from an hdulist Parameters ---------- hdulist : FITS HDU list Returns ------- xspec1d : XSpectrum1D Parsed spectrum """ if 'WAVELENGTH' not in hdulist: pdb.set_trace() xspec1d = XSpectrum1D.from_spec1d(spec1d) else: wave = hdulist['WAVELENGTH'].data * u.AA fx = hdulist['FLUX'].data # Error array if 'ERROR' in hdulist: sig = hdulist['ERROR'].data else: sig = None if 'CONTINUUM' in hdulist: co = hdulist['CONTINUUM'].data else: co = None xspec1d = XSpectrum1D.from_tuple((wave, fx, sig, co), **kwargs) if 'METADATA' in hdulist[0].header: # Prepare for JSON (bug fix of sorts) metas = hdulist[0].header['METADATA'] ipos = metas.rfind('}') xspec1d.meta.update(json.loads(metas[:ipos+1])) return xspec1d
def load_spec_order(fname,objid=None,order=None,extract='OPT',flux=True): """ Loading single order spectrum from a PypeIt 1D specctrum fits file :param file: :param objid: :param order: :param extract: :param flux: :return: """ if objid is None: objid = 0 if order is None: msgs.error('Please specify which order you want to load') # read extension name into a list primary_header = fits.getheader(fname, 0) nspec = primary_header['NSPEC'] extnames = [primary_header['EXT0001']] * nspec for kk in range(nspec): extnames[kk] = primary_header['EXT' + '{0:04}'.format(kk + 1)] extnameroot = extnames[0] # Figure out which extension is the required data ordername = '{0:04}'.format(order) extname = extnameroot.replace('OBJ0000', objid) extname = extname.replace('ORDER0000', 'ORDER' + ordername) try: exten = extnames.index(extname) + 1 msgs.info("Loading extension {:s} of spectrum {:s}".format(extname, fname)) except: msgs.error("Spectrum {:s} does not contain {:s} extension".format(fname, extname)) spectrum = load.load_1dspec(fname, exten=exten, extract=extract, flux=flux) # Polish a bit -- Deal with NAN, inf, and *very* large values that will exceed # the floating point precision of float32 for var which is sig**2 (i.e. 1e38) bad_flux = np.any([np.isnan(spectrum.flux), np.isinf(spectrum.flux), np.abs(spectrum.flux) > 1e30, spectrum.sig ** 2 > 1e10, ], axis=0) # Sometimes Echelle spectra have zero wavelength bad_wave = spectrum.wavelength < 1000.0*units.AA bad_all = bad_flux + bad_wave ## trim bad part wave_out,flux_out,sig_out = spectrum.wavelength[~bad_all],spectrum.flux[~bad_all],spectrum.sig[~bad_all] spectrum_out = XSpectrum1D.from_tuple((wave_out,flux_out,sig_out), verbose=False) #if np.sum(bad_flux): # msgs.warn("There are some bad flux values in this spectrum. Will zero them out and mask them (not ideal)") # spectrum.data['flux'][spectrum.select][bad_flux] = 0. # spectrum.data['sig'][spectrum.select][bad_flux] = 0. return spectrum_out
def test_airtovac_andback(spec): npix = 1000 spec = XSpectrum1D.from_tuple((np.linspace(5000.,6000,npix), np.ones(npix))) # Airtovac spec.meta['airvac'] = 'air' spec.airtovac() # Test np.testing.assert_allclose(spec.wavelength[0].value, 5001.394869990007, rtol=1e-5) assert spec.meta['airvac'] == 'vac' # Vactoair spec.vactoair() np.testing.assert_allclose(spec.wavelength[0].value, 5000., rtol=1e-5) assert spec.meta['airvac'] == 'air'
def parse_UVES_popler(hdulist): """ Read a spectrum from a UVES_popler-style fits file. """ from linetools.spectra.xspectrum1d import XSpectrum1D hd = hdulist[0].header uwave = setwave(hd) * u.Angstrom co = hdulist[0].data[3] fx = hdulist[0].data[0] * co # Flux sig = hdulist[0].data[1] * co xspec1d = XSpectrum1D.from_tuple((uwave, fx, sig)) xspec1d.co = co return xspec1d
def parse_linetools_spectrum_format(hdulist): """ Parse an old linetools-format spectrum from an hdulist Parameters ---------- hdulist : FITS HDU list Returns ------- xspec1d : XSpectrum1D Parsed spectrum """ if 'WAVELENGTH' not in hdulist: pdb.set_trace() #spec1d = spec_read_fits.read_fits_spectrum1d( # os.path.expanduser(datfil), dispersion_unit='AA') xspec1d = XSpectrum1D.from_spec1d(spec1d) else: wave = hdulist['WAVELENGTH'].data * u.AA fx = hdulist['FLUX'].data # Error array if 'ERROR' in hdulist: sig = hdulist['ERROR'].data else: sig = None if 'CONTINUUM' in hdulist: co = hdulist['CONTINUUM'].data else: co = None xspec1d = XSpectrum1D.from_tuple((wave, fx, sig, co)) if 'METADATA' in hdulist[0].header: xspec1d.meta.update(json.loads(hdulist[0].header['METADATA'])) return xspec1d
def parse_UVES_popler(hdulist): """ Read a spectrum from a UVES_popler-style fits file. """ from linetools.spectra.xspectrum1d import XSpectrum1D hd = hdulist[0].header uwave = setwave(hd) * u.Angstrom co = hdulist[0].data[3] fx = hdulist[0].data[0] * co # Flux sig = hdulist[0].data[1] * co xspec1d = XSpectrum1D.from_array(uwave, u.Quantity(fx), uncertainty=StdDevUncertainty(sig)) xspec1d.co = co return xspec1d
def test_rebin(spec): # Add units funit = u.erg/u.s/u.cm**2 spec.units['flux'] = funit # Rebin new_wv = np.arange(3000., 9000., 5) * u.AA newspec = spec.rebin(new_wv, do_sig=True) # Test np.testing.assert_allclose(newspec.flux[1000].value, 1.0192499, rtol=1e-5) assert newspec.flux.unit == funit # Without sig spec_nosig = XSpectrum1D.from_tuple((spec.wavelength, spec.flux)) newspec = spec.rebin(new_wv) assert newspec.sig_is_set is False
def get_telfer_spec(zqso=0., igm=False): '''Generate a Telfer QSO composite spectrum Paraemters: ---------- zqso: float, optional Redshift of the QSO igm: bool, optional Include IGM opacity? [False] Returns: -------- telfer_spec: XSpectrum1D Spectrum ''' # Read telfer = ascii.read( xa_path+'/data/quasar/telfer_hst_comp01_rq.ascii', comment='#') scale = telfer['flux'][(telfer['wrest'] == 1450.)] telfer_spec = XSpectrum1D.from_tuple((telfer['wrest']*(1+zqso), telfer['flux']/scale[0])) # Observer frame # IGM? if igm is True: '''The following is quite experimental. Use at your own risk. ''' import multiprocessing from xastropy.igm.fN import model as xifm from xastropy.igm import tau_eff as xit fN_model = xifm.default_model() # Expanding range of zmnx (risky) fN_model.zmnx = (0.,5.) # Parallel igm_wv = np.where(telfer['wrest']<1220.)[0] adict = [] for wrest in telfer_spec.dispersion[igm_wv].value: tdict = dict(ilambda=wrest, zem=zqso, fN_model=fN_model) adict.append(tdict) # Run #xdb.set_trace() pool = multiprocessing.Pool(4) # initialize thread pool N threads ateff = pool.map(xit.map_etl, adict) # Apply telfer_spec.flux[igm_wv] *= np.exp(-1.*np.array(ateff)) # Return return telfer_spec
def main() : parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser.add_argument('lowrdx_sky', type = str, default = None, help = 'LowRedux Sky Spectrum (IDL save file)') parser.add_argument('new_file', type = str, default = None, help = 'PYPIT FITS sky spectrum') args = parser.parse_args() # Read lrdx_sky = readsav(args.lowrdx_sky) # Generate xspec = XSpectrum1D.from_tuple((lrdx_sky['wave_calib'], lrdx_sky['sky_calib'])) # Write xspec.write_to_fits(args.new_file)
def spec_from_array(wave,flux,sig,**kwargs): """ return spectrum from arrays of wave, flux and sigma """ ituple = (wave, flux, sig) spectrum = XSpectrum1D.from_tuple(ituple, **kwargs) # Polish a bit -- Deal with NAN, inf, and *very* large values that will exceed # the floating point precision of float32 for var which is sig**2 (i.e. 1e38) bad_flux = np.any([np.isnan(spectrum.flux), np.isinf(spectrum.flux), np.abs(spectrum.flux) > 1e30, spectrum.sig ** 2 > 1e10, ], axis=0) if np.sum(bad_flux): msgs.warn("There are some bad flux values in this spectrum. Will zero them out and mask them (not ideal)") spectrum.data['flux'][spectrum.select][bad_flux] = 0. spectrum.data['sig'][spectrum.select][bad_flux] = 0. return spectrum
def compare_boxcar(pp,lrdx_sciobj,pypit_boxfile, iso): '''Compare boxcar extractions ''' # Read/Load pypit_boxspec = lsio.readspec(pypit_boxfile) # Read LowRedux sig = np.sqrt(lrdx_sciobj['MASK_BOX']/(lrdx_sciobj['SIVAR_BOX'] + (lrdx_sciobj['MASK_BOX']==0))) lwrdx_boxspec = XSpectrum1D.from_tuple( (lrdx_sciobj['WAVE_BOX'], lrdx_sciobj['FLUX_BOX'], sig) ) # Plot plt.clf() fig = plt.figure(figsize=(16,11)) gs = gridspec.GridSpec(2, 1) fig.suptitle("Instr={:s}, Setup={:s} :: Boxcar Extractions for {:s} :: PYPIT ({:s})".format(iso[0], iso[1], iso[2], pypit.version), fontsize=18.) for qq in range(2): ax = plt.subplot(gs[qq]) if qq == 0: xlim = None else: xlim = (6700,7000) ymax = np.median(pypit_boxspec.flux)*2. # PYPIT ax.plot(pypit_boxspec.dispersion, pypit_boxspec.flux, 'k-', drawstyle='steps',label='PYPIT') ax.plot(pypit_boxspec.dispersion, pypit_boxspec.sig, 'g-', drawstyle='steps') # LowRedux ax.plot(lwrdx_boxspec.dispersion, lwrdx_boxspec.flux, '-', color='blue',label='LowRedux') ax.plot(lwrdx_boxspec.dispersion, lwrdx_boxspec.sig, '-', color='gray') # Axes if xlim is None: ax.set_xlim(np.min(pypit_boxspec.dispersion.value), np.max(pypit_boxspec.dispersion.value)) else: ax.set_xlim(xlim) ax.set_ylim(0.,ymax) ax.set_xlabel('Wavelength',fontsize=19.) ax.set_ylabel('electrons',fontsize=19.) # Legend legend = plt.legend(loc='upper right', borderpad=0.3, handletextpad=0.3, fontsize='x-large') # Finish plt.tight_layout(pad=0.2,h_pad=0.,w_pad=0.1,rect=[0, 0.03, 1, 0.95]) pp.savefig(bbox_inches='tight') plt.close()