def test_collate(spec,spec2): coll_spec = ltsu.collate([spec,spec2], masking='edges') assert coll_spec.nspec == 2 assert coll_spec.totpix == 20379 # Now a 2 and a 1 coll_spec2 = ltsu.collate([coll_spec,spec2], masking='edges') assert coll_spec2.nspec == 3 assert coll_spec2.totpix == 20379
def test_collate(spec, spec2): coll_spec = ltsu.collate([spec, spec2], masking='edges') assert coll_spec.nspec == 2 assert coll_spec.totpix == 20379 # Now a 2 and a 1 coll_spec2 = ltsu.collate([coll_spec, spec2], masking='edges') assert coll_spec2.nspec == 3 assert coll_spec2.totpix == 20379
def coadd_cos_from_x1dfiles(filenames, wv_array=None, A_pix=0.01*u.AA): spec_list = [] #TODO: mask out x1d spectral regions with bad values. for filename in filenames: sp = readspec(filename) import pdb; pdb.set_trace() # mask = spec_list += [sp] # spec_list contains all individual spectra specs = collate(spec_list) # now all in a single XSpectrum1D object #rebin if wv_array is None: # bring them to a unique native wavelength grid using PYPIT A_pix = A_pix.to("AA").value cat_wave = arco.new_wave_grid(specs.data['wave'], wave_method='pixel', A_pix=A_pix) else: cat_wave = wv_array.to('AA').value specs = specs.rebin(cat_wave*u.AA, all=True, do_sig=True, masking='none',grow_bad_sig=True) # estimate weights for coaddition (PYPYT) sn2, weights = arco.sn_weight(specs) # coaddition spec1d = arco.one_d_coadd(specs, weights) return spec1d
def load_spec(files, iextensions=None, extract='opt', flux=True): """ Load a list of spectra into one XSpectrum1D object Parameters ---------- files : list List of filenames iextensions : int or list, optional List of extensions, 1 per filename or an int which is the extension in each file extract : str, optional Extraction method ('opt', 'box') flux : bool, optional Apply to fluxed spectra? Returns ------- spectra : XSpectrum1D -- All spectra are collated in this one object """ from linetools.spectra.utils import collate # Extensions if iextensions is None: msgs.warn("Extensions not provided. Assuming first extension for all") extensions = np.ones(len(files), dtype='int8') elif isinstance(iextensions, int): extensions = np.ones(len(files), dtype='int8') * iextensions else: extensions = np.array(iextensions) # Load spectra spectra_list = [] for ii, fname in enumerate(files): msgs.info("Loading extension {:d} of spectrum {:s}".format( extensions[ii], fname)) spectrum = arload.load_1dspec(fname, exten=extensions[ii], 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) 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. # Append spectra_list.append(spectrum) # Join into one XSpectrum1D object spectra = collate(spectra_list) # Return return spectra
def ech_load_spec(files, objid=None, order=None, extract='OPT', flux=True): """Loading Echelle spectra from a list of PypeIt 1D spectrum fits files Parameters: files (str) : The list of file names of your spec1d file objid (str) : The id (one per fits file) of the object you want to load. (default is the first object) order (int) : which order you want to load (default is None, loading all orders) extract (str) : 'OPT' or 'BOX' flux (bool) : default is True, loading fluxed spectra returns: spectrum_out : XSpectrum1D """ nfiles = len(files) if objid is None: objid = ['OBJ0000'] * nfiles elif len(objid) == 1: objid = objid * nfiles elif len(objid) != nfiles: msgs.error( 'The length of objid should be either 1 or equal to the number of spectra files.' ) fname = files[0] ext_final = fits.getheader(fname, -1) norder = ext_final['ECHORDER'] + 1 msgs.info('spectrum {:s} has {:d} orders'.format(fname, norder)) if norder <= 1: msgs.error( 'The number of orders have to be greater than one for echelle. Longslit data?' ) # Load spectra spectra_list = [] for ii, fname in enumerate(files): if order is None: msgs.info('Loading all orders into a gaint spectra') for iord in range(norder): spectrum = load_spec_order(fname, objid=objid[ii], order=iord, extract=extract, flux=flux) # Append spectra_list.append(spectrum) elif order >= norder: msgs.error( 'order number cannot greater than the total number of orders') else: spectrum = load_spec_order(fname, objid=objid[ii], order=order, extract=extract, flux=flux) # Append spectra_list.append(spectrum) # Join into one XSpectrum1D object spectra = collate(spectra_list) # Return return spectra
def coadd_cos_from_x1dfiles(filenames, wv_array=None, A_pix=0.01 * u.AA): spec_list = [] #TODO: mask out x1d spectral regions with bad values. for filename in filenames: sp = readspec(filename) import pdb pdb.set_trace() # mask = spec_list += [sp] # spec_list contains all individual spectra specs = collate(spec_list) # now all in a single XSpectrum1D object #rebin if wv_array is None: # bring them to a unique native wavelength grid using PYPIT A_pix = A_pix.to("AA").value cat_wave = arco.new_wave_grid(specs.data['wave'], wave_method='pixel', A_pix=A_pix) else: cat_wave = wv_array.to('AA').value specs = specs.rebin(cat_wave * u.AA, all=True, do_sig=True, masking='none', grow_bad_sig=True) # estimate weights for coaddition (PYPYT) sn2, weights = arco.sn_weight(specs) # coaddition spec1d = arco.one_d_coadd(specs, weights) return spec1d
def dummy_spectra(s2n=10., seed=1234, wvmnx=None, npix=None): """ Generate a set of normalized spectra with varying wavelength and noise Parameters ---------- s2n : float, optional Returns ------- dspec : XSpectrum1D """ rstate=np.random.RandomState(seed) if wvmnx is None: wvmnx = [[5000., 6000.], [4000.5, 5800.5], [4500.8, 6300.8], ] if npix is None: npix = [1000, 1001, 1100] slist = [] for ii, inpix in enumerate(npix): wave = np.linspace(wvmnx[ii][0], wvmnx[ii][1], inpix) #flux = np.ones_like(wave) #sig = np.ones_like(wave) / s2n #spec = XSpectrum1D.from_tuple((wave,flux,sig)) ## Noise and append #slist.append(spec.add_noise(seed=seed)) slist.append(dummy_spectrum(wave=wave, s2n=s2n, rstate=rstate)) # Collate dspec = collate(slist, masking='edges') # return dspec
def test_rebin_to_rest(spec,spec2): zarr = np.array([2.1,2.2]) # Build spectra array coll_spec = ltsu.collate([spec,spec2]) rest_spec = ltsu.rebin_to_rest(coll_spec, zarr, 100*u.km/u.s, debug=False) # Test assert rest_spec.totpix == 3716 np.testing.assert_allclose(rest_spec.wvmin.value, 986.3506403, rtol=1e-5)
def spectra_from_meta(self, meta, subset=False, debug=False, **kwargs): """ Returns one spectrum per row in the input meta data table This meta data table should have been generated by a meta query Parameters ---------- meta : Table Must include a column 'GROUP' indicating the group for each row This automatically generated by any of the meta query methods subset : bool, optional Return a subset of the spectra if only a fraction of the meta rows have them Otherwise raise an Error Returns ------- spec : XSpectrum1D An object containing all of the spectra These are aligned with the input meta table sub_meta : Table, optional Returned if subset=True """ from linetools.spectra import utils as ltsu # Checks if 'GROUP' not in meta.keys(): print("Input meta data table must include a GROUP column") print("We suspect yours was not made by a meta query. Try one") raise IOError("And then try again.") # groups = np.unique(meta['GROUP'].data) all_spec = [] sv_rows = [] for group in groups: sub_meta = meta['GROUP'] == group # Grab spec = self[group].spec_from_meta(meta[sub_meta]) if (spec is None) and (not subset): print( "One or more rows of your input meta does *not* have spectra" ) raise ValueError( "Use subset=True to return only the subset that do") else: if spec is not None: all_spec.append(spec) sv_rows.append(np.where(sub_meta)[0]) # Collate spec = ltsu.collate(all_spec, masking='edges') # Re-order idx = np.concatenate(sv_rows) srt = np.argsort(idx) spec2 = spec[srt] # Return if subset: return spec2, meta[idx[srt]] else: return spec2
def test_median_ratio_flux(): """ Test median ratio flux algorithm """ # Setup spec1 = dummy_spectrum(s2n=10) spec2 = dummy_spectrum(s2n=10) spec2.data['flux'][0,:] *= 2. spec = collate([spec1,spec2]) smask = spec.data['sig'].filled(0.) > 0. # Put in a bad pixel med_flux = coadd.median_ratio_flux(spec, smask, 1, 0) np.testing.assert_allclose(med_flux, 0.5, atol=0.05)
def test_smash_spectra(spec,spec2): # Try to stack 2 spectra with different wavelengths coll_spec = ltsu.collate([spec,spec2]) with pytest.raises(AssertionError): stack = ltsu.smash_spectra(coll_spec) # Stack rebinned zarr = np.array([2.1,2.2]) rest_spec = ltsu.rebin_to_rest(coll_spec, zarr, 100*u.km/u.s, debug=False) stack = ltsu.smash_spectra(rest_spec, method='average') # Test assert stack.totpix == 3716 np.testing.assert_allclose(stack.flux[1].value, -3.3213510, rtol=1e-5)
def coadd_stis_from_x1dfiles(filenames, wv_array=None, rebin=None, debug=True): """ Parameters ---------- filenames : list List of filenames with x1d STIS data Must be of the same object and same configuration wv_array : Quantity array Wavelength array to perform the co-add rebin : int, optional If given, it rebins the current sampling by rebin number of pixels Returns ------- spec1d : XSpectrum1D Co-added version of all the spectra """ spec_list = [] for filename in filenames: aux = load_single_x1d_stis(filename, debug=debug) for sp in aux: spec_list += [sp] # spec_list contains all echelle orders from different files and multi-extensions specs = collate(spec_list) # now all in a single XSpectrum1D object if wv_array is None: # bring them to a unique native wavelength grid using PYPIT cat_wave = arco.new_wave_grid(specs.data['wave'], wave_method='velocity') else: cat_wave = wv_array.to('AA').value if rebin is not None: rebin = int(rebin) cat_wave = cat_wave[::rebin] specs = specs.rebin(cat_wave * u.AA, all=True, do_sig=True, masking='none', grow_bad_sig=True) # estimate weights for coaddition (PYPYT) sn2, weights = arco.sn_weight(specs, smask=None) # coaddition spec1d = arco.one_d_coadd(specs, None, weights) # spec1d = arco.coadd_spectra(specs, wave_grid_method='velocity', scale_method='auto') return spec1d
def write_magecube_as_xspectrum1d(magecube_filename, airvac='air'): magecube = Cube(magecube_filename) nw, ny, nx = magecube.shape assert nx == 1, "Your magecube does not have the conventional astrometry, where the slit is aligned in the y-axis" spec_list = [] for ii in range(ny): sp = magecube[:, ii, 0] spec = ntu.xspectrum1d_from_mpdaf_spec(sp, airvac=airvac) spec_list += [spec] specs = collate(spec_list) new_name = magecube_filename.replace('.fits', '_xspec.fits') specs.write(new_name) return specs
def write_magecube_as_xspectrum1d(magecube_filename, airvac='air'): magecube = Cube(magecube_filename) nw, ny, nx = magecube.shape assert nx == 1, "Your magecube does not have the conventional astrometry, where the slit is aligned in the y-axis" spec_list = [] for ii in range(ny): sp = magecube[:,ii-1,0] spec = ntu.xspectrum1d_from_mpdaf_spec(sp, airvac=airvac) spec_list += [spec] specs = collate(spec_list) new_name = magecube_filename.replace('.fits','_xspec.fits') specs.write(new_name) return specs
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_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_slice(): spec = io.readspec(data_path('UM184_nF.fits')) spec2 = io.readspec(data_path('PH957_f.fits')) spec3 = spec2.copy() # Collate to make a multispec spectrum mspec = lsu.collate([spec,spec2,spec3]) # Array newspec = mspec[np.array([0,1])] # Test assert newspec.nspec == 2 assert not newspec.co_is_set # Int newspec2 = mspec[1] assert newspec2.nspec == 1 # Slice newspec3 = mspec[0:2] assert newspec3.nspec == 2
def test_slice(): spec = io.readspec(data_path('UM184_nF.fits')) spec2 = io.readspec(data_path('PH957_f.fits')) spec3 = spec2.copy() # Collate to make a multispec spectrum mspec = lsu.collate([spec, spec2, spec3]) # Array newspec = mspec[np.array([0, 1])] # Test assert newspec.nspec == 2 assert not newspec.co_is_set # Int newspec2 = mspec[1] assert newspec2.nspec == 1 # Slice newspec3 = mspec[0:2] assert newspec3.nspec == 2
def coadd_stis_from_x1dfiles(filenames, wv_array=None, rebin=None, debug=False): """ Parameters ---------- filenames : list List of filenames with x1d STIS data Must be of the same object and same configuration wv_array : Quantity array Wavelength array to perform the co-add rebin : int, optional If given, it rebins the current sampling by rebin number of pixels Returns ------- spec1d : XSpectrum1D Co-added version of all the spectra """ spec_list = [] for filename in filenames: aux = load_single_x1d_stis(filename, debug=debug) for sp in aux: spec_list += [sp] # spec_list contains all echelle orders from different files and multi-extensions specs = collate(spec_list) # now all in a single XSpectrum1D object if wv_array is None: # bring them to a unique native wavelength grid using PYPIT cat_wave = arco.new_wave_grid(specs.data['wave'], wave_method='velocity') else: cat_wave = wv_array.to('AA').value if rebin is not None: rebin = int(rebin) cat_wave = cat_wave[::rebin] specs = specs.rebin(cat_wave*u.AA, all=True, do_sig=True, masking='none',grow_bad_sig=True) # estimate weights for coaddition (PYPYT) sn2, weights = arco.sn_weight(specs, smask=None) # coaddition spec1d = arco.one_d_coadd(specs, weights) return spec1d
def ech_load_spec(files,objid=None,order=None,extract='OPT',flux=True): """ files: A list of file names objid: extract: flux: """ nfiles = len(files) if objid is None: objid = ['OBJ0000'] * nfiles elif len(objid) == 1: objid = objid * nfiles elif len(objid) != nfiles: msgs.error('The length of objid should be either 1 or equal to the number of spectra files.') fname = files[0] ext_final = fits.getheader(fname, -1) norder = ext_final['ORDER'] + 1 msgs.info('spectrum {:s} has {:d} orders'.format(fname, norder)) if norder <= 1: msgs.error('The number of orders have to be greater than one for echelle. Longslit data?') # Load spectra spectra_list = [] for ii, fname in enumerate(files): if order is None: msgs.info('Loading all orders into a gaint spectra') for iord in range(norder): spectrum = load_spec_order(fname,objid=objid[ii],order=iord,extract=extract,flux=flux) # Append spectra_list.append(spectrum) elif order >= norder: msgs.error('order number cannot greater than the total number of orders') else: spectrum = load_spec_order(fname, objid=objid[ii], order=order, extract=extract, flux=flux) # Append spectra_list.append(spectrum) # Join into one XSpectrum1D object spectra = collate(spectra_list) # Return return spectra
def clean(spec, red): """ :param spec: (numpy array) XSpectrum1D objects :param red: (numpy array) their redshift values (z) :returns: rest_spec: (numpy array) truncatted, normalized and restframed XSpectrum1D objects """ import numpy as np import astropy.units as u from linetools.spectra import utils as ltsu from linetools.spectra.xspectrum1d import XSpectrum1D r = range(len(spec)) temp = [np.asarray(spec[i].wavelength / (1 + red[i])) for i in r] # truncating each spectra to only include wavelength values from 1000 to 1450 wv_coverage = [(1000 < entry) & (entry < 1450) for entry in temp] wave = np.asarray([spec[i].wavelength[wv_coverage[i]] for i in r]) flux = np.asarray([spec[i].flux[wv_coverage[i]] for i in r]) error = np.asarray([spec[i].sig[wv_coverage[i]] for i in r]) temp = [np.asarray(wave[i] / (1 + red[i])) for i in r] # normalizing just between the SiII lines wv_norm = [(1260 < entry) & (entry < 1304) for entry in temp] # just between the SiII lines flux_range = np.asarray([flux[i][wv_norm[i]] for i in r]) medians = np.asarray([np.median(flux_range[i]) for i in r]) norm_flux = np.asarray([(flux[i] / medians[i]) for i in r]) # getting a single XSpec object to feed into the stack spec = [XSpectrum1D(wave[i], norm_flux[i], error[i]) for i in r] collate = ltsu.collate(spec) rest_spec = ltsu.rebin_to_rest(collate, red, 300 * u.km / u.s, grow_bad_sig=True) return rest_spec
def spectra_from_meta(self, meta, debug=False): """ Returns one spectrum per row in the input meta data table This meta data table should have been generated by a meta query Parameters ---------- meta : Table Must include a column 'GROUP' indicating the group for each row This automatically generated by any of the meta query methods Returns ------- spec : XSpectrum1D An object containing all of the spectra These are aligned with the input meta table """ from linetools.spectra import utils as ltsu # Checks if 'GROUP' not in meta.keys(): print("Input meta data table must include a GROUP column") print("We suspect yours was not made by a meta query. Try one") raise IOError("And then try again.") # groups = np.unique(meta['GROUP'].data) all_spec = [] sv_rows = [] for group in groups: sub_meta = meta['GROUP'] == group sv_rows.append(np.where(sub_meta)[0]) # Grab all_spec.append(self[group].spec_from_meta(meta[sub_meta])) # Collate spec = ltsu.collate(all_spec) # Re-order idx = np.concatenate(sv_rows) srt = np.argsort(idx) spec2 = spec[srt] # return spec2
def specm(spec,spec2): specm = ltsu.collate([spec,spec2], masking='edges') return specm
def specmr(specr, spec2): # With bad pixels replaced specmr = ltsu.collate([specr, spec2]) return specmr
def make_set(ntrain, slines, outroot=None, tol=1 * u.arcsec, igmsp_survey='SDSS_DR7', frac_without=0., seed=1234, zmin=None, zmax=4.5, high=False, slls=False, mix=False, low_s2n=False): """ Generate a training set Parameters ---------- ntrain : int Number of training sightlines to generate slines : Table Table of sightlines without DLAs (usually from SDSS or BOSS) igmsp_survey : str, optional Dataset name for spectra frac_without : float, optional Fraction of sightlines (on average) without a DLA seed : int, optional outroot : str, optional Root for output filenames root+'.fits' for spectra root+'.json' for DLA info zmin : float, optional Minimum redshift for training; defaults to min(slines['ZEM']) zmax : float, optional Maximum redshift to train on mix : bool, optional Mix of SLLS and DLAs low_s2n : bool, optional Reduce the S/N artificially, i.e. add noise Returns ------- """ from linetools.spectra.utils import collate # Init and checks igmsp = IgmSpec() assert igmsp_survey in igmsp.groups rstate = np.random.RandomState(seed) rfrac = rstate.random_sample(ntrain) if zmin is None: zmin = np.min(slines['ZEM']) rzem = zmin + rstate.random_sample(ntrain) * (zmax - zmin) fNHI = init_fNHI(slls=slls, mix=mix, high=high) all_spec = [] full_dict = {} # Begin looping for qq in range(ntrain): print("qq = {:d}".format(qq)) full_dict[qq] = {} # Grab sightline isl = np.argmin(np.abs(slines['ZEM'] - rzem[qq])) full_dict[qq]['sl'] = isl # sightline specl, meta = igmsp.spectra_from_coord( (slines['RA'][isl], slines['DEC'][isl]), groups=['SDSS_DR7'], tol=tol, verbose=False) assert len(meta) == 1 spec = specl # Meta data for header mdict = {} for key in meta.keys(): mdict[key] = meta[key][0] mhead = Header(mdict) # Clear? if rfrac[qq] < frac_without: spec.meta['headers'][0] = mdict.copy() #mhead all_spec.append(spec) full_dict[qq]['nDLA'] = 0 continue # Insert at least one DLA spec, dlas = insert_dlas(spec, mhead['zem_GROUP'], rstate=rstate, fNHI=fNHI, slls=slls, mix=mix, high=high, low_s2n=low_s2n) spec.meta['headers'][0] = mdict.copy() #mhead all_spec.append(spec) full_dict[qq]['nDLA'] = len(dlas) for kk, dla in enumerate(dlas): full_dict[qq][kk] = {} full_dict[qq][kk]['NHI'] = dla.NHI full_dict[qq][kk]['zabs'] = dla.zabs # Generate one object final_spec = collate(all_spec) # Write? if outroot is not None: # Spectra final_spec.write_to_hdf5(outroot + '.hdf5') # Dict -> JSON gdict = ltu.jsonify(full_dict) ltu.savejson(outroot + '.json', gdict, overwrite=True) #, easy_to_read=True) # Return return final_spec, full_dict
def __init__(self, redrock_file, parent=None, zdict=None, coadd_dict=None, outfile='tmp.json', unit_test=False, screen_scale=1., **kwargs): QMainWindow.__init__(self, parent) """ redrock_file = str Input RedRock output FITS file from our redrock script parent : Widget parent, optional zsys : float, optional intial redshift either from a previous vet_rr json or the original rr guesses screen_scale : float, optional Scale the default sizes for the gui size """ # Load up self.outfile = outfile self.rr_hdul = fits.open(redrock_file) if coadd_dict is not None: self.slit_info = {} for key in coadd_dict.keys(): if isinstance(coadd_dict[key], dict): if '2D_xval' in coadd_dict[key].keys(): name = coadd_dict[key]['outfile'].replace('.fits', '') self.slit_info[name] = {} self.slit_info[name]['xval'] = coadd_dict[key][ '2D_xval'] self.slit_info[name]['Gslit'] = coadd_dict[key][ 'Gemini_slit'] else: self.slit_info = None # names, spectra, zs = [], [], [] names, spectra = [], [] if zdict is None: self.zdict = OrderedDict() load_z = True else: self.zdict = OrderedDict() load_z = False for hdu in self.rr_hdul[1:]: # Grab the spectrum spec_file = hdu.name # tmp = XSpectrum1D.from_file(spec_file.replace('FITS','fits')) spectra.append( XSpectrum1D.from_file(spec_file.replace('FITS', 'fits'), masking='edges')) names.append(spec_file.replace('.FITS', '')) # RedRock data = hdu.data # Init the dict if load_z: self.zdict[names[-1]] = {} self.zdict[names[-1]]['zRR'] = data['z'] self.zdict[names[-1]]['ZQ'] = -99 self.zdict[names[-1]]['Comment'] = '' self.zdict[names[-1]]['z'] = data['z'][0] else: self.zdict[names[-1]] = zdict[names[-1]] # Collate ispec = lspu.collate(spectra, masking='edges') # Fill ispec.labels = names ispec.stypes = ['galaxy'] * ispec.nspec # ispec.z = zs # DO NOT SET THE REDSHIFT HERE self.RRi = 0 self.scale = screen_scale # Needed to avoid crash in large spectral files rcParams['agg.path.chunksize'] = 20000 # avoid scientific notation in axes tick labels rcParams['axes.formatter.useoffset'] = False # Build a widget combining several others self.main_widget = QWidget() # Status bar self.create_status_bar() # ZQ window self.ZQ_widg = ltgsm.EditBox(-99, 'ZQ', '{:d}') self.ZQ_values = [-99, -1, 0, 1, 3, 4] # Comment window self.comment_widg = ltgsm.EditBox('', 'Comment', '{:s}') # Grab the pieces and tie together self.pltline_widg = ltgl.PlotLinesWidget(status=self.statusBar, screen_scale=self.scale) self.pltline_widg.setMaximumWidth(300 * self.scale) # Hook the spec widget to Plot Line self.spec_widg = ltgsp.ExamineSpecWidget(ispec, status=self.statusBar, parent=self, llist=self.pltline_widg.llist, screen_scale=self.scale, **kwargs) # Reset redshift from spec # Auto set line list if spec has proper object type if hasattr(self.spec_widg.spec, 'stypes'): if self.spec_widg.spec.stypes[ self.spec_widg.select].lower() == 'galaxy': self.pltline_widg.llist = ltgu.set_llist( 'Galaxy', in_dict=self.pltline_widg.llist) elif self.spec_widg.spec.stypes[ self.spec_widg.select].lower() == 'absorber': self.pltline_widg.llist = ltgu.set_llist( 'Strong', in_dict=self.pltline_widg.llist) self.pltline_widg.llist['Plot'] = True idx = self.pltline_widg.lists.index( self.pltline_widg.llist['List']) self.pltline_widg.llist_widget.setCurrentRow(idx) # self.pltline_widg.spec_widg = self.spec_widg # Multi spec self.mspec_widg = ltgsp.MultiSpecWidget(self.spec_widg, extra_method=self) self.spec_widg.canvas.mpl_connect('key_press_event', self.on_key) self.spec_widg.canvas.mpl_connect('button_press_event', self.on_click) self.prev_select = 0 # Index of previous spectrum; starts at 0 # Legend -- specific to this GUI self.legend = {} self.wv_dict = {'*': 3727., '(': 3950., ')': 4940., '_': 6564.} self.legend['zoom'] = self.wv_dict self.legend['&'] = 'Toggle through ZQ' self.legend[ '#'] = 'Toggle through zRR (WARNING: will not necessary start at the first one)' self.legend['%'] = 'Set z=0 (for stars)' self.legend['9'] = 'Skip to next spectrum with ZQ=-99' self.legend['x'] = 'Next spectrum' for key, value in self.legend.items(): print(key, value) # Extras extras = QWidget() extras.setMinimumWidth(180 * self.scale) extras.setMaximumWidth(280 * self.scale) vbox = QVBoxLayout() qbtn = QPushButton(self) qbtn.setText('Quit') qbtn.clicked.connect(self.quit) vbox.addWidget(self.pltline_widg) vbox.addWidget(self.ZQ_widg) vbox.addWidget(self.comment_widg) vbox.addWidget(self.mspec_widg) vbox.addWidget(qbtn) extras.setLayout(vbox) # Main window hbox = QHBoxLayout() hbox.addWidget(self.spec_widg) hbox.addWidget(extras) self.main_widget.setLayout(hbox) # Point MainWindow self.setCentralWidget(self.main_widget) if unit_test: self.quit() # Giddy up self.run_with_select(save=False)
def order_phot_scale(spectra, phot_scale_dicts, nsig=3.0, niter=5, debug=False): ''' Scale coadded spectra with photometric data. Parameters: spectra: XSpectrum1D spectra (longslit) or spectra list (echelle) phot_scale_dicts: A dict contains photometric information of each orders (if echelle). An example is given below. phot_scale_dicts = {0: {'filter': None, 'mag': None, 'mag_type': None, 'masks': None}, 1: {'filter': 'UKIRT-Y', 'mag': 20.33, 'mag_type': 'AB', 'masks': None}, 2: {'filter': 'UKIRT-J', 'mag': 20.19, 'mag_type': 'AB', 'masks': None}, 3: {'filter': 'UKIRT-H', 'mag': 20.02, 'mag_type': 'AB', 'masks': None}, 4: {'filter': 'UKIRT-K', 'mag': 19.92, 'mag_type': 'AB', 'masks': None}} Show QA plot if debug=True Return a new scaled XSpectrum1D spectra ''' from pypeit.core.flux_calib import scale_in_filter norder = spectra.nspec # scaling spectrum order by order. spectra_list_new = [] for iord in range(norder): phot_scale_dict = phot_scale_dicts[iord] if (phot_scale_dict['filter'] is not None) & (phot_scale_dict['mag'] is not None): speci = scale_in_filter(spectra[iord], phot_scale_dict) else: #ToDo: Think a better way to do the following try: spec0 = scale_in_filter(spectra[iord - 1], phot_scale_dicts[iord - 1]) speci = spectra[iord] med_flux = spec0.data['flux'] / speci.data['flux'] mn_scale, med_scale, std_scale = stats.sigma_clipped_stats( med_flux, sigma=nsig, iters=niter) med_scale = np.minimum(med_scale, 5.0) spectra.data['flux'] *= med_scale spectra.data['sig'] *= med_scale msgs.warn( "Not enough photometric information given. Scaled order {:d} to order {:d}" .format(iord, iord - 1)) except KeyError: msgs.warn( "Not enough photometric information given. Scale order {:d} to order {:d} failed" .format(iord, iord - 1)) try: spec0 = scale_in_filter(spectra[iord + 1], phot_scale_dicts[iord + 1]) speci = spectra[iord] med_flux = spec0.data['flux'] / speci.data['flux'] mn_scale, med_scale, std_scale = stats.sigma_clipped_stats( med_flux, sigma=nsig, iters=niter) med_scale = np.minimum(med_scale, 5.0) speci.data['flux'] *= med_scale speci.data['sig'] *= med_scale msgs.warn( "Not enough photometric information given. Scaled order {:d} to order {:d}" .format(iord, iord + 1)) except: msgs.warn( "Not enough photometric information given. No scaling on order {:d}" .format(iord)) speci = spectra[iord] spectra_list_new.append(speci) if debug: gdp = speci.sig > 0 plt.plot(spectra[iord].wavelength[gdp], spectra[iord].flux[gdp], 'k-', label='raw spectrum') plt.plot(speci.wavelength[gdp], speci.flux[gdp], 'b-', label='scaled spectrum') mny, medy, stdy = stats.sigma_clipped_stats(speci.flux[gdp], sigma=3, iters=5) plt.ylim([0.1 * medy, 4.0 * medy]) plt.legend() plt.xlabel('wavelength') plt.ylabel('Flux') plt.show() return collate(spectra_list_new)
def ech_coadd(files, objids=None, extract='OPT', flux=True, giantcoadd=False, orderscale='median', mergeorder=True, wave_grid_method='velocity', niter=5, wave_grid_min=None, wave_grid_max=None, v_pix=None, scale_method='auto', do_offset=False, sigrej_final=3., do_var_corr=False, SN_MIN_MEDSCALE=0.5, overlapfrac=0.01, num_min_pixels=10, phot_scale_dicts=None, qafile=None, outfile=None, do_cr=True, debug=False, **kwargs): """ routines for coadding spectra observed with echelle spectrograph. parameters: files (list): file names objids (str): objid extract (str): 'OPT' or 'BOX' flux (bool): fluxed or not giantcoadd (bool): coadding order by order or do it at once? wave_grid_method (str): default velocity niter (int): number of iteration for rejections wave_grid_min (float): min wavelength, None means it will find the min value from your spectra wave_grid_max (float): max wavelength, None means it will find the max value from your spectra v_pix (float): delta velocity, see coadd.py scale_method (str): see coadd.py do_offset (str): see coadd.py, not implemented yet. sigrej_final (float): see coadd.py do_var_corr (bool): see coadd.py, default False. It seems True will results in a large error SN_MIN_MEDSCALE (float): minimum SNR for scaling different orders overlapfrac (float): minimum overlap fraction for scaling different orders. qafile (str): name of qafile outfile (str): name of coadded spectrum do_cr (bool): remove cosmic rays? debug (bool): show debug plots? kwargs: see coadd.py returns: spec1d: coadded XSpectrum1D """ nfile = len(files) if nfile <= 1: msgs.info('Only one spectrum exits coadding...') return fname = files[0] ext_final = fits.getheader(fname, -1) norder = ext_final['ECHORDER'] + 1 msgs.info('spectrum {:s} has {:d} orders'.format(fname, norder)) if norder <= 1: msgs.error( 'The number of orders have to be greater than one for echelle. Longslit data?' ) if giantcoadd: msgs.info('Coadding all orders and exposures at once') spectra = load.ech_load_spec(files, objid=objids, order=None, extract=extract, flux=flux) wave_grid = np.zeros((2, spectra.nspec)) for i in range(spectra.nspec): wave_grid[0, i] = spectra[i].wvmin.value wave_grid[1, i] = spectra[i].wvmax.value ech_kwargs = { 'echelle': True, 'wave_grid_min': np.min(wave_grid), 'wave_grid_max': np.max(wave_grid), 'v_pix': v_pix } kwargs.update(ech_kwargs) # Coadding spec1d = coadd.coadd_spectra(spectra, wave_grid_method=wave_grid_method, niter=niter, scale_method=scale_method, do_offset=do_offset, sigrej_final=sigrej_final, do_var_corr=do_var_corr, qafile=qafile, outfile=outfile, do_cr=do_cr, debug=debug, **kwargs) else: msgs.info('Coadding individual orders first and then merge order') spectra_list = [] # Keywords for Table rsp_kwargs = {} rsp_kwargs['wave_tag'] = '{:s}_WAVE'.format(extract) rsp_kwargs['flux_tag'] = '{:s}_FLAM'.format(extract) rsp_kwargs['sig_tag'] = '{:s}_FLAM_SIG'.format(extract) #wave_grid = np.zeros((2,norder)) for iord in range(norder): spectra = load.ech_load_spec(files, objid=objids, order=iord, extract=extract, flux=flux) ech_kwargs = { 'echelle': False, 'wave_grid_min': spectra.wvmin.value, 'wave_grid_max': spectra.wvmax.value, 'v_pix': v_pix } #wave_grid[0,iord] = spectra.wvmin.value #wave_grid[1,iord] = spectra.wvmax.value kwargs.update(ech_kwargs) # Coadding the individual orders if qafile is not None: qafile_iord = qafile + '_%s' % str(iord) else: qafile_iord = None spec1d_iord = coadd.coadd_spectra( spectra, wave_grid_method=wave_grid_method, niter=niter, scale_method=scale_method, do_offset=do_offset, sigrej_final=sigrej_final, do_var_corr=do_var_corr, qafile=qafile_iord, outfile=None, do_cr=do_cr, debug=debug, **kwargs) spectrum = spec_from_array(spec1d_iord.wavelength, spec1d_iord.flux, spec1d_iord.sig, **rsp_kwargs) spectra_list.append(spectrum) spectra_coadd = collate(spectra_list) # Rebin the spectra # ToDo: we should read in JFH's wavelength grid here. # Join into one XSpectrum1D object # Final wavelength array kwargs['wave_grid_min'] = np.min( spectra_coadd.data['wave'][spectra_coadd.data['wave'] > 0]) kwargs['wave_grid_max'] = np.max( spectra_coadd.data['wave'][spectra_coadd.data['wave'] > 0]) wave_final = coadd.new_wave_grid(spectra_coadd.data['wave'], wave_method=wave_grid_method, **kwargs) # The rebin function in linetools can not work on collated spectra (i.e. filled 0). # Thus I have to rebin the spectra first and then collate again. spectra_list_new = [] for i in range(spectra_coadd.nspec): speci = spectra_list[i].rebin(wave_final * units.AA, all=True, do_sig=True, grow_bad_sig=True, masking='none') spectra_list_new.append(speci) spectra_coadd_rebin = collate(spectra_list_new) ## Note if orderscale == 'photometry': # Only tested on NIRES. if phot_scale_dicts is not None: spectra_coadd_rebin = order_phot_scale(spectra_coadd_rebin, phot_scale_dicts, debug=debug) else: msgs.warn( 'No photometric information is provided. Will use median scale.' ) orderscale = 'median' elif orderscale == 'median': #rmask = spectra_coadd_rebin.data['sig'].filled(0.) > 0. #sn2, weights = coadd.sn_weights(fluxes, sigs, rmask, wave) ## scaling different orders order_median_scale(spectra_coadd_rebin, nsig=sigrej_final, niter=niter, overlapfrac=overlapfrac, num_min_pixels=num_min_pixels, SN_MIN_MEDSCALE=SN_MIN_MEDSCALE, debug=debug) else: msgs.warn('No any scaling is performed between different orders.') if mergeorder: fluxes, sigs, wave = coadd.unpack_spec(spectra_coadd_rebin, all_wave=False) ## Megering orders msgs.info('Merging different orders') ## ToDo: Joe claimed not to use pixel depedent weighting. weights = 1.0 / sigs**2 weights[~np.isfinite(weights)] = 0.0 weight_combine = np.sum(weights, axis=0) weight_norm = weights / weight_combine weight_norm[np.isnan(weight_norm)] = 1.0 flux_final = np.sum(fluxes * weight_norm, axis=0) sig_final = np.sqrt(np.sum((weight_norm * sigs)**2, axis=0)) spec1d_final = spec_from_array(wave_final * units.AA, flux_final, sig_final, **rsp_kwargs) if outfile is not None: msgs.info( 'Saving the final calibrated spectrum as {:s}'.format( outfile)) coadd.write_to_disk(spec1d_final, outfile) if (qafile is not None) or (debug): # plot and save qa plt.figure(figsize=(12, 6)) ax1 = plt.axes([0.07, 0.13, 0.9, 0.4]) ax2 = plt.axes([0.07, 0.55, 0.9, 0.4]) plt.setp(ax2.get_xticklabels(), visible=False) medf = np.median(spec1d_final.flux) ylim = (np.sort([0. - 0.3 * medf, 5 * medf])) cmap = plt.get_cmap('RdYlBu_r') for idx in range(spectra_coadd_rebin.nspec): spectra_coadd_rebin.select = idx color = cmap(float(idx) / spectra_coadd_rebin.nspec) ind_good = spectra_coadd_rebin.sig > 0 ax1.plot(spectra_coadd_rebin.wavelength[ind_good], spectra_coadd_rebin.flux[ind_good], color=color) if (np.max(spec1d_final.wavelength) > (9000.0 * units.AA)): skytrans_file = resource_filename( 'pypeit', '/data/skisim/atm_transmission_secz1.5_1.6mm.dat') skycat = np.genfromtxt(skytrans_file, dtype='float') scale = 0.85 * ylim[1] ax2.plot(skycat[:, 0] * 1e4, skycat[:, 1] * scale, 'm-', alpha=0.5) ax2.plot(spec1d_final.wavelength, spec1d_final.sig, ls='steps-', color='0.7') ax2.plot(spec1d_final.wavelength, spec1d_final.flux, ls='steps-', color='b') ax1.set_xlim([ np.min(spec1d_final.wavelength.value), np.max(spec1d_final.wavelength.value) ]) ax2.set_xlim([ np.min(spec1d_final.wavelength.value), np.max(spec1d_final.wavelength.value) ]) ax1.set_ylim(ylim) ax2.set_ylim(ylim) ax1.set_xlabel('Wavelength (Angstrom)') ax1.set_ylabel('Flux') ax2.set_ylabel('Flux') plt.tight_layout(pad=0.2, h_pad=0., w_pad=0.2) if len(qafile.split('.')) == 1: msgs.info( "No fomat given for the qafile, save to PDF format.") qafile = qafile + '.pdf' if qafile: plt.savefig(qafile) msgs.info("Wrote coadd QA: {:s}".format(qafile)) if debug: plt.show() plt.close() ### Do NOT remove this part althoug it is deprecated. # we may need back to using this pieces of code after fixing the coadd.coadd_spectra problem on first order. #kwargs['echelle'] = True #kwargs['wave_grid_min'] = np.min(wave_grid) #kwargs['wave_grid_max'] = np.max(wave_grid) #spec1d_final = coadd.coadd_spectra(spectra_coadd_rebin, wave_grid_method=wave_grid_method, niter=niter, # scale_method=scale_method, do_offset=do_offset, sigrej_final=sigrej_final, # do_var_corr=do_var_corr, qafile=qafile, outfile=outfile, # do_cr=do_cr, debug=debug, **kwargs) return spec1d_final else: msgs.warn('Skipped merging orders') if outfile is not None: for iord in range(len(spectra_list)): outfile_iord = outfile.replace( '.fits', '_ORDER{:04d}.fits'.format(iord)) msgs.info( 'Saving the final calibrated spectrum of order {:d} as {:s}' .format(iord, outfile)) spectra_list[iord].write_to_fits(outfile_iord) return spectra_list
def test_collate(spec,spec2): coll_spec = ltsu.collate([spec,spec2]) assert coll_spec.nspec == 2 assert coll_spec.totpix == 20379
def specmr(specr, spec2): # With bad pixels replaced specmr = ltsu.collate([specr, spec2], masking='edges') return specmr
def specm(spec, spec2): specm = ltsu.collate([spec, spec2], masking='edges') return specm
def stacks(spec, red, N, zbin, plot=False): """ :param spec: (numpy array) XSpectrum1D objects :param red: (numpy array) their redshift values (z) :param N: (int) number of bootstrap iterations :param zbin: (str) redshift bin "lowz" or "hiz" """ import numpy as np from astropy.io import fits from numpy import random as ran from linetools.spectra import utils as ltsu from linetools.spectra.xspectrum1d import XSpectrum1D print("Number of spectra provided =", spec.nspec) # the actual stack stack = ltsu.smash_spectra(spec) z_med = np.median(red) # the bootstrap R = (spec.nspec) # restraints on the random variable N_stack = [] N_z_med = [] for i in np.arange(N): # this might take a while if i % 10 == 0: print(i) choice = np.asarray(ran.randint(0, R, R)) # the shuffle rand_spec = np.asarray([spec[index] for index in choice]) rand_red = np.asarray([red[index] for index in choice]) rand_collate = ltsu.collate(rand_spec) # collate and stack N_stack.append(ltsu.smash_spectra(rand_collate)) N_z_med.append(np.median(rand_red)) # matrix math to create the error array N_flux = np.array([entry.flux for entry in N_stack]) N_matrix = np.array([N_flux[i] - stack.flux for i in range(N)]) tranpose = np.transpose(N_matrix) # matrix math covariance = np.dot(tranpose, N_matrix) sigma = np.sqrt(np.diagonal(covariance) / (N - 1)) # the final error array composite = XSpectrum1D(stack.wavelength, stack.flux, sig=sigma) # plot with bootstrap generated error if plot == True: composite.plot() # writing out the stack hdr = fits.Header() hdr["REDSHIFT"] = z_med hdr["NSPEC"] = spec.nspec header = fits.PrimaryHDU(header=hdr) c_wave = fits.Column(name='WAVELENGTH', array=stack.wavelength, unit="angstroms", format="E") c_flux = fits.Column(name='FLUX', array=stack.flux, unit="relative flux", format="E") c_noise = fits.Column(name='FLUX_ERR', array=sigma, unit="relative flux", format="E") table = fits.BinTableHDU.from_columns([c_wave, c_flux, c_noise]) full_hdu = fits.HDUList([header, table]) full_hdu.writeto("../../fits/composites/" + zbin + "/composite.fits") # writing out the boostrap hdr = fits.Header() hdr["NSPEC"] = spec.nspec hdr["NBOOT"] = N header = fits.PrimaryHDU(header=hdr) c_wave = fits.Column(name='WAVELENGTH', array=stack.wavelength, unit="angstroms", format="E") c_noise = fits.Column(name='FLUX_ERR', array=sigma, unit="relative flux", format="E") table = fits.BinTableHDU.from_columns([c_wave, c_noise]) flux_data = fits.ImageHDU(N_flux, name="FLUX_ITERATIONS") full_hdu = fits.HDUList([header, table, flux_data]) full_hdu.writeto("../../fits/bootstrap/" + zbin + "/stacks.fits")
def build_spectra(tpe, spec_tbl=None, outfil=None): """ Generate an XSpectrum1D object of TPE spectra Parameters ---------- tpe : Table spec_tbl : str or Table, optional outfil : str, optional Returns ------- spec : XSpectrum1D """ from specdb.build import utils as spbu from linetools.spectra import utils as ltspu # Grab spectra table -- might read from disk eventually if spec_tbl is not None: if isinstance(spec_tbl, Table): pass elif isinstance(spec_tbl, basestring): spec_tbl = Table.read(spec_tbl) else: spec_tbl = get_spec_meta(tpe) assert len(tpe) == len(spec_tbl) # Load spectral sets igmsp = IgmSpec() qpq = IgmSpec(db_file=qpq_file, skip_test=True) # Grab igmspec spectra iigms = spec_tbl['DBASE'] == 'igmspec' sub_meta = spec_tbl[['GROUP', 'GROUP_ID']][iigms] igm_spec = igmsp.spectra_from_meta(sub_meta) # Grab QPQ iqpq = spec_tbl['DBASE'] == 'qpq' sub_meta = spec_tbl[['GROUP', 'GROUP_ID']][iqpq] qpq_spec = qpq.spectra_from_meta(sub_meta) # Cut TPE gdtpe = spec_tbl['GROUP_ID'] >= 0 cut_tpe = tpe[gdtpe] cut_stbl = spec_tbl[gdtpe] if np.sum(~gdtpe) > 0: print("These pairs had no good b/g spectrum") print(tpe[['BG_RA', 'BG_DEC']][~gdtpe]) # Collate coll_spec = ltspu.collate([igm_spec, qpq_spec]) # Reorder to match cut_tpe idxi = np.where(iigms)[0] idxq = np.where(iqpq)[0] alli = np.concatenate([idxi, idxq]) isrt = np.argsort(alli) fin_spec = coll_spec[isrt] # Check continua has_co = chk_continua(fin_spec, cut_tpe['FG_Z']) cut_stbl['HAS_CO'] = has_co if np.sum(~has_co) > 0: print("These spectra need a continuum") print(cut_stbl[['SPEC_FILE']][~has_co]) # Write if outfil is not None: hdf = h5py.File(outfil, 'w') fin_spec.write_to_hdf5('dumb', hdf5=hdf) # Add Tables spbu.clean_table_for_hdf(cut_tpe) hdf['TPE'] = cut_tpe spbu.clean_table_for_hdf(cut_stbl) hdf['SPEC_TBL'] = cut_stbl # Close hdf.close() print("Wrote: {:s}".format(outfil)) return cut_tpe, cut_stbl, fin_spec
def specm(spec, spec2): specm = ltsu.collate([spec, spec2]) return specm
def specmr(specr,spec2): # With bad pixels replaced specmr = ltsu.collate([specr,spec2], masking='edges') return specmr
def ech_coadd(files,objids=None,extract='OPT',flux=True,giantcoadd=False, wave_grid_method='velocity', niter=5,wave_grid_min=None, wave_grid_max=None,v_pix=None, scale_method='auto', do_offset=False, sigrej_final=3.,do_var_corr=False, qafile=None, outfile=None,do_cr=True, debug=False,**kwargs): nfile = len(files) if nfile <=1: msgs.info('Only one spectrum exits coadding...') return fname = files[0] ext_final = fits.getheader(fname, -1) norder = ext_final['ORDER'] + 1 msgs.info('spectrum {:s} has {:d} orders'.format(fname, norder)) if norder <= 1: msgs.error('The number of orders have to be greater than one for echelle. Longslit data?') if giantcoadd: msgs.info('Coadding all orders and exposures at once') spectra = ech_load_spec(files, objid=objids,order=None, extract=extract, flux=flux) wave_grid = np.zeros((2,spectra.nspec)) for i in range(spectra.nspec): wave_grid[0, i] = spectra[i].wvmin.value wave_grid[1, i] = spectra[i].wvmax.value ech_kwargs = {'echelle': True, 'wave_grid_min': np.min(wave_grid), 'wave_grid_max': np.max(wave_grid), 'v_pix': v_pix} kwargs.update(ech_kwargs) # Coadding spec1d = coadd.coadd_spectra(spectra, wave_grid_method=wave_grid_method, niter=niter, scale_method=scale_method, do_offset=do_offset, sigrej_final=sigrej_final, do_var_corr=do_var_corr, qafile=qafile, outfile=outfile, do_cr=do_cr, debug=debug,**kwargs) else: msgs.info('Coadding individual orders first and then merge order') spectra_list = [] # Keywords for Table rsp_kwargs = {} rsp_kwargs['wave_tag'] = '{:s}_WAVE'.format(extract) rsp_kwargs['flux_tag'] = '{:s}_FLAM'.format(extract) rsp_kwargs['sig_tag'] = '{:s}_FLAM_SIG'.format(extract) wave_grid = np.zeros((2,norder)) for iord in range(norder): spectra = ech_load_spec(files, objid=objids, order=iord, extract=extract, flux=flux) ech_kwargs = {'echelle': False, 'wave_grid_min': spectra.wvmin.value, 'wave_grid_max': spectra.wvmax.value, 'v_pix': v_pix} wave_grid[0,iord] = spectra.wvmin.value wave_grid[1,iord] = spectra.wvmax.value kwargs.update(ech_kwargs) # Coadding the individual orders if qafile is not None: qafile_iord = qafile+'_%s'%str(iord) else: qafile_iord = None spec1d_iord = coadd.coadd_spectra(spectra, wave_grid_method=wave_grid_method, niter=niter, scale_method=scale_method, do_offset=do_offset, sigrej_final=sigrej_final, do_var_corr=do_var_corr, qafile=qafile_iord, outfile=outfile, do_cr=do_cr, debug=debug, **kwargs) spectrum = spec_from_array(spec1d_iord.wavelength, spec1d_iord.flux, spec1d_iord.sig,**rsp_kwargs) spectra_list.append(spectrum) # Join into one XSpectrum1D object spectra_coadd = collate(spectra_list) kwargs['echelle'] = True kwargs['wave_grid_min'] = np.min(wave_grid) kwargs['wave_grid_max'] = np.max(wave_grid) # ToDo: Currently I'm not using the first order due to some problem. Need to add it back after fix the problem. spec1d = coadd.coadd_spectra(spectra_coadd[1:], wave_grid_method=wave_grid_method, niter=niter, scale_method=scale_method, do_offset=do_offset, sigrej_final=sigrej_final, do_var_corr=do_var_corr, qafile=qafile, outfile=outfile, do_cr=do_cr, debug=debug, **kwargs) return spec1d
def specm(spec,spec2): specm = ltsu.collate([spec,spec2]) return specm