def clooge_edges(mids): """Just uses the midpoints of the midpoints to guess at the edges for a grid. Taking the midpoints of the returned bin edges will _not_ reproduce the input.""" edges = mnp.midpts(mids) beg = mids[0] - (edges[0] - mids[0]) end = mids[-1] + (mids[-1] - edges[-1]) return np.concatenate([[beg], edges, [end]])
def readcsv(specfile): if db.parse_observatory(specfile) in ['tmd', 'src']: data = np.loadtxt(specfile, skiprows=1, delimiter=',') wmid, f = data[:,1], data[:,2] f *= 100.0 # convert W/m2/nm to erg/s/cm2/AA wmid *= 10.0 # convert nm to AA we = np.zeros(len(wmid) + 1) we[1:-1] = midpts(wmid) dw0, dw1 = wmid[1] - wmid[0], wmid[-1] - wmid[-2] we[0], we[-1] = wmid[0] - dw0 / 2.0, wmid[-1] + dw1 / 2.0 w0, w1 = we[:-1], we[1:] good = ~np.isnan(f) w0, w1, f = w0[good], w1[good], f[good] spectbl = utils.vecs2spectbl(w0, w1, f, filename=specfile) return [spectbl] else: raise Exception('A parser for {} files has not been implemented.'.format(specfile[2:9]))
def readfits(specfile, observatory=None, spectrograph=None): """Read a fits file into standardized table.""" if observatory is None: observatory = db.parse_observatory(specfile) spec = fits.open(specfile) if any([ s in specfile for s in ['coadd', 'custom', 'mod', 'panspec', 'other', 'hlsp'] ]): return [readstdfits(specfile)] elif observatory == 'hst': if spectrograph is None: spectrograph = db.parse_spectrograph(specfile) if spectrograph in ['sts', 'cos']: sd, sh = spec[1].data, spec[1].header flux, err = sd['flux'], sd['error'] wmid, flags = sd['wavelength'], sd['dq'] exptarr, start, end = [ np.ones(flux.shape) * sh[s] for s in ['exptime', 'expstart', 'expend'] ] elif spectrograph == 'fos': template = specfile[:-8] + '{}' + '.fits' hdus = [ fits.open(template.format(ext)) for ext in ['c0f', 'c1f', 'c2f', 'cqf'] ] wmid, flux, err, flags = [h[0].data[:, ::-1] for h in hdus] start, end = [ np.ones(flux.shape) * hdus[0][0].header[s] for s in ['expstart', 'expend'] ] exptarr = np.ones( flux.shape) * hdus[0][1].data['exposure'][:, np.newaxis] else: raise NotImplementedError() shape = flux.shape insti = db.getinsti(specfile) iarr = np.ones(shape) * insti wedges = np.array([mids2edges(wm, 'left', 'linear-x') for wm in wmid]) w0, w1 = wedges[:, :-1], wedges[:, 1:] normfac = np.ones(shape) datas = np.array( [w0, w1, flux, err, exptarr, flags, iarr, normfac, start, end]) datas = datas.swapaxes(0, 1) spectbls = [__maketbl(d, specfile) for d in datas] #cull off-detector data spectbls = [__trimHSTtbl(spectbl) for spectbl in spectbls] elif observatory == 'fuse': spectbls = [] star = spec[0].header['targname'] expt = spec[0].header['obstime'] for sub in spec[1:]: w, f, e = [sub.data[s] for s in ['wave', 'flux', 'error']] wedges = midpts(w) wedges = np.insert(wedges, [0, len(wedges)], [2 * w[0] - wedges[0], 2 * w[-1] - wedges[-1]]) w0, w1 = wedges[:-1], wedges[1:] spectbl = utils.vecs2spectbl(w0, w1, f, e, exptime=expt, star=star, filename=specfile) spectbls.append(spectbl) elif observatory in ['xmm', 'cxo']: sh = spec[0].header star = db.parse_star(specfile) def groomwave(ext): wmid = spec[ext].data['Wave'] halfwidth = spec[ext].data['bin_width'] w0, w1 = wmid - halfwidth, wmid + halfwidth assert np.allclose(w0[1:], w1[:-1]) # there may still be slight mismatches, so fix it up betweens = (w0[1:] + w1[:-1]) / 2.0 w0[1:], w1[:-1] = betweens, betweens return w0, w1 # first the observed spectrum optel = db.parse_grating(specfile) if 'gj551' in specfile: expt = sh['pn_duration'] start = np.nan end = np.nan elif optel == 'pn---': expt = sh['spec_exptime_pn'] * 1000.0 start = Time(sh['pn_date-obs']).mjd end = Time(sh['pn_date-end']).mjd elif optel == 'multi': expt = (sh['spec_exptime_mos1'] + sh['spec_exptime_mos2'] + sh['spec_exptime_pn']) / 3.0 * 1000.0 start1 = Time(sh['mos1_date-obs']).mjd start2 = Time(sh['mos2_date-obs']).mjd start3 = Time(sh['pn_date-obs']).mjd end1 = Time(sh['mos1_date-end']).mjd end2 = Time(sh['mos2_date-end']).mjd end3 = Time(sh['pn_date-end']).mjd start = min([start1, start2, start3]) end = max([end1, end2, end3]) elif sh['instrume'] == 'ACIS': starts, ends, expts = [ _parse_keys_sequential(sh, root) for root in ['DATE_OBS', 'DATE_END', 'EXPTIME'] ] expt = sum(expts) * 1000.0 starts, ends = list(map(Time, [starts, ends])) start = min(starts.mjd) end = max(ends.mjd) else: start = 0.0 end = 0.0 expt = 0.0 if '1214' not in sh['target']: flux, err = [ spec['Obs Spectrum'].data[s] for s in ['CFlux', 'CFlux_err'] ] w0, w1 = groomwave('Obs Spectrum') insti = db.getinsti(specfile) obsspec = utils.vecs2spectbl(w0, w1, flux, err, expt, instrument=insti, start=start, end=end, star=star, filename=specfile) good = np.isfinite(obsspec['flux']) obsspec = obsspec[good] spectbls = [obsspec] else: spectbls = [] # next the model flux = spec['Model Spectrum'].data['Flux'] expt, err = 0.0, 0.0 w0, w1 = groomwave('Model Spectrum') name_pieces = db.parse_name(specfile).split('_') configuration = 'mod_apc_-----' name = '_'.join(name_pieces[:1] + [configuration] + name_pieces[4:]) insti = rc.getinsti(configuration) modspec = utils.vecs2spectbl(w0, w1, flux, err, expt, instrument=insti, name=name, filename=specfile) spectbls.append(modspec) else: raise Exception( 'fits2tbl cannot parse data from the {} observatory.'.format( observatory)) spec.close() for tbl in spectbls: tbl['w'] = (tbl['w0'] + tbl['w1']) / 2. return spectbls
ir = [7000, np.inf] broadband_edges = [xray[1], euv[1], fuv[1], nuv[1], vis[1]] broadbands = [xray, euv, fuv, nuv, vis, [ir[0], 55000]] broadband_names = ['X-ray', 'EUV', 'FUV', 'NUV', 'Visible', 'IR'] # ----------------------------------------------------------------------------- # PHOENIX DATABASE phoenixbaseurl = 'ftp://phoenix.astro.physik.uni-goettingen.de/HiResFITS/PHOENIX-ACES-AGSS-COND-2011/' phxrepo = os.path.join(datapath, 'phoenix') phxTgrid = np.hstack([np.arange(2300, 7000, 100), np.arange(7000, 12001, 200)]) phxggrid = np.arange(0.0, 6.1, 0.5) phxZgrid = np.hstack([np.arange(-4.0, -2.0, 1.0), np.arange(-2.0, 1.1, 0.5)]) phxagrid = np.arange(-0.2, 1.3, 0.2) phxgrids = [phxTgrid, phxggrid, phxZgrid, phxagrid] phxwave = fits.getdata(os.path.join(phxrepo, 'wavegrid_hires.fits')) phxwave = np.hstack([[499.95], midpts(phxwave), [54999.875]]) def phxurl(Teff, logg=4.5, FeH=0.0, aM=0.0, repo='ftp'): """ Constructs the URL for the phoenix spectrum file for a star with effective temperature Teff, log surface gravity logg, metalicity FeH, and alpha elemnt abundance aM. Does not check that the URL is actually valid, and digits beyond the precision of the numbers used in the path will be truncated. """ zstr = '{:+4.1f}'.format(FeH) if FeH == 0.0: zstr = '-' + zstr[1:] astr = '.Alpha={:+5.2f}'.format(aM) if aM != 0.0 else '' name = (