Skip to content

Commit a15d803

Browse files
committed
added reduce function
1 parent af90331 commit a15d803

1 file changed

Lines changed: 170 additions & 14 deletions

File tree

laspec/mrs.py

Lines changed: 170 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
import matplotlib.pyplot as plt
55
import numpy as np
6-
from astropy import constants as const
6+
from astropy import constants
77
from astropy import units as u
88
from astropy.coordinates import SkyCoord
99
from astropy import coordinates as coord
@@ -14,6 +14,8 @@
1414

1515
from .normalization import normalize_spectrum_general
1616

17+
SOL_kms = constants.c.value / 1000
18+
1719

1820
def datetime2jd(datetime='2018-10-24T05:07:06.0', format="isot", tz_correction=8):
1921
jd = Time(datetime, format=format).jd - tz_correction/24.
@@ -35,7 +37,7 @@ def eval_ltt(ra=180., dec=40., jd=2456326.4583333, site=None):
3537
return ltt_helio.jd
3638

3739

38-
def debad(wave, fluxnorm, nsigma=(3, 6), mfarg=21, gfarg=(51, 9), maskconv=7, maxiter=10):
40+
def debad(wave, fluxnorm, nsigma=(4, 8), mfarg=21, gfarg=(51, 9), maskconv=7, maxiter=3):
3941
"""
4042
Parameters
4143
----------
@@ -47,17 +49,16 @@ def debad(wave, fluxnorm, nsigma=(3, 6), mfarg=21, gfarg=(51, 9), maskconv=7, ma
4749
lower & upper sigma levels
4850
mfarg:
4951
median filter width / pixel
50-
gkarg:
52+
gfarg:
5153
Gaussian filter length & width / pixel
5254
maskconv:
5355
mask convolution --> cushion
5456
maxiter:
5557
max iteration
5658
57-
Return:
58-
-------
59+
Return
60+
------
5961
fluxnorm
60-
6162
"""
6263
npix = len(fluxnorm)
6364
indclip = np.zeros_like(fluxnorm, dtype=bool)
@@ -90,12 +91,14 @@ def debad(wave, fluxnorm, nsigma=(3, 6), mfarg=21, gfarg=(51, 9), maskconv=7, ma
9091

9192
class MrsSpec:
9293
""" MRS spectrum """
94+
name = ""
9395
# original quantities
9496
wave = np.array([], dtype=np.float)
9597
flux = np.array([], dtype=np.float)
9698
ivar = np.array([], dtype=np.float)
9799
mask = np.array([], dtype=np.bool) # True for problematic
98100
flux_err = np.array([], dtype=np.float)
101+
indcr = np.array([], dtype=np.float) # cosmic ray index
99102

100103
# normalized quantities
101104
flux_norm = np.array([], dtype=np.float)
@@ -225,7 +228,7 @@ def from_hdu(hdu=None, norm_type=None, **norm_kwargs):
225228
wave = 10 ** spec["LOGLAM"].data
226229
flux = spec["FLUX"].data
227230
ivar = spec["IVAR"].data
228-
mask = spec["ORMASK"].data > 0 # use ormask for coadded spec
231+
mask = spec["ORMASK"].data # use ormask for coadded spec
229232
info = dict(name=hdu.header["EXTNAME"],
230233
lmjmlist=hdu.header["LMJMLIST"], # not universal
231234
snr=np.float(hdu.header["SNR"]),
@@ -235,7 +238,7 @@ def from_hdu(hdu=None, norm_type=None, **norm_kwargs):
235238
wave = 10 ** spec["LOGLAM"].data
236239
flux = spec["FLUX"].data
237240
ivar = spec["IVAR"].data
238-
mask = spec["PIXMASK"].data > 0 # use pixmask for epoch spec
241+
mask = spec["PIXMASK"].data # use pixmask for epoch spec
239242
info = dict(name=hdu.header["EXTNAME"],
240243
lmjm=np.int(hdu.header["LMJM"]),
241244
exptime=np.float(hdu.header["EXPTIME"]),
@@ -263,8 +266,8 @@ def from_lrs(fp_lrs, norm_type="poly", **norm_kwargs):
263266
obsid=hdr["OBSID"],
264267
ra=hdr["RA"],
265268
dec=hdr["DEC"],
266-
rv=hdr["Z"] * const.c.value / 1000.,
267-
rv_err=hdr["Z_ERR"] * const.c.value / 1000.,
269+
rv=hdr["Z"] * SOL_kms,
270+
rv_err=hdr["Z_ERR"] * SOL_kms,
268271
subclass=hdr["SUBCLASS"],
269272
tsource=hdr["TSOURCE"],
270273
snr=hdr["SNRG"],
@@ -316,7 +319,7 @@ def wave_rv(self, rv=None):
316319
"""
317320
if rv is None:
318321
rv = self.rv
319-
return self.wave / (1 + rv * 1000 / const.c.value)
322+
return self.wave / (1 + rv / SOL_kms)
320323

321324
def plot(self):
322325
plt.plot(self.wave, self.flux)
@@ -333,6 +336,100 @@ def plot_err(self):
333336
def plot_norm_err(self):
334337
plt.plot(self.wave, self.flux_norm_err)
335338

339+
def reduce(self, wave_new=None, rv=0, npix_cushion=50, cr=True, nsigma=(4, 8), maxiter=5,
340+
norm_type="spline", niter=3):
341+
"""
342+
343+
Parameters
344+
----------
345+
wave_new:
346+
if specified, spectrum is interpolated to wave_new
347+
rv:
348+
if specified, radial velocity is corrected
349+
npix_cushion: int
350+
if speficied, cut the two ends
351+
cr:
352+
if True, remove cosmic rays using the *debad* function
353+
nsigma:
354+
sigma levels used in removing cosmic rays
355+
maxiter:
356+
max number of iterations used in removing cosmic rays
357+
norm_type:
358+
"spline" | None
359+
niter:
360+
number iterations in normalization
361+
362+
Returns
363+
-------
364+
wave_new, flux_norm, flux_norm_err
365+
"""
366+
# determine the chunk range
367+
if npix_cushion > 0:
368+
npix0 = npix_cushion
369+
npix1 = -npix_cushion
370+
else:
371+
npix0 = 0
372+
npix1 = len(self.wave)
373+
374+
# cut spectrum
375+
wave_obs = self.wave[npix0:npix1]
376+
flux_err = self.flux_err[npix0:npix1]
377+
mask = self.mask[npix0:npix1] > 0
378+
# remove cosmic rays if cr is True
379+
if cr:
380+
flux_obs = debad(self.wave, self.flux, nsigma=nsigma, maxiter=maxiter)[npix0:npix1]
381+
indcr = (np.abs(flux_obs - self.flux[npix0:npix1]) > 1e-5) * 1
382+
else:
383+
flux_obs = self.flux[npix0:npix1]
384+
indcr = np.zeros(flux_obs.shape, dtype=int)
385+
386+
# use new wavelength grid if wave_new is specified
387+
wave_obsz0 = wave_obs / (1 + rv / SOL_kms)
388+
if wave_new is None:
389+
wave_new = wave_obs
390+
flux_obs = np.interp(wave_new, wave_obsz0, flux_obs)
391+
flux_err = np.interp(wave_new, wave_obsz0, flux_err)
392+
mask = 1 * (np.interp(wave_new, wave_obsz0, mask) > 0)
393+
394+
msr = MrsSpec()
395+
msr.wave = wave_new
396+
msr.flux = flux_obs
397+
msr.ivar = flux_err**-2
398+
msr.flux_err = flux_err
399+
msr.mask = mask
400+
msr.indcr = indcr
401+
msr.name = self.name
402+
msr.isempty = self.isempty
403+
404+
# other information (optional)
405+
msr.info = self.info
406+
msr.rv = self.rv
407+
408+
# time and position info
409+
msr.filename = self.filename
410+
msr.snr = self.snr
411+
msr.exptime = self.exptime
412+
msr.lmjm = self.lmjm
413+
msr.lmjmlist = self.lmjmlist
414+
msr.obsid = self.obsid
415+
msr.seeing = self.seeing
416+
msr.lamplist = self.lamplist
417+
msr.ra = self.ra
418+
msr.dec = self.dec
419+
msr.fibertype = self.fibertype
420+
msr.fibermask = self.fibermask
421+
msr.jdbeg = self.jdbeg
422+
msr.jdend = self.jdend
423+
msr.jdmid = self.jdmid
424+
msr.jdltt = self.jdltt
425+
msr.hjdmid = self.hjdmid
426+
427+
# normalize spectrum if norm_type is specified
428+
if norm_type is not None:
429+
msr.normalize(norm_type=norm_type, niter=niter)
430+
431+
return msr
432+
336433

337434
class MrsEpoch:
338435
""" MRS epoch spcetrum """
@@ -480,7 +577,7 @@ def wave_rv(self, rv=None):
480577
"""
481578
if rv is None:
482579
rv = self.rv
483-
return self.wave / (1 + rv * 1000 / const.c.value)
580+
return self.wave / (1 + rv / SOL_kms)
484581

485582
def flux_norm_dbd(self, **kwargs):
486583
""" return fixed flux_norm """
@@ -501,6 +598,54 @@ def plot_err(self):
501598
def plot_norm_err(self):
502599
plt.plot(self.wave, self.flux_norm_err)
503600

601+
def plot_reduce(self):
602+
for i in range(self.nspec):
603+
msr = self.speclist[i].reduce(norm_type=None)
604+
msr.plot()
605+
606+
def plot_norm_reduce(self):
607+
for i in range(self.nspec):
608+
msr = self.speclist[i].reduce(norm_type="spline")
609+
msr.plot_norm()
610+
611+
def reduce(self, norm_type="spline", niter=3):
612+
"""
613+
614+
Parameters
615+
----------
616+
norm_type:
617+
type of normalization
618+
niter:
619+
number of iteration in normalization
620+
621+
Returns
622+
-------
623+
mer: MrsEpoch
624+
reduced epoch spectrum
625+
626+
"""
627+
mer = MrsEpoch([_.reduce() for _ in self.speclist], specnames=self.specnames, norm_type=norm_type, niter=niter)
628+
# header info
629+
mer.epoch = self.epoch
630+
mer.lmjm = self.lmjm
631+
mer.snr = self.snr
632+
mer.rv = self.rv
633+
# time and position info
634+
mer.filename = self.filename
635+
mer.obsid = self.obsid
636+
mer.seeing = self.seeing
637+
mer.ra = self.ra
638+
mer.dec = self.dec
639+
mer.fibertype = self.fibertype
640+
mer.fibermask = self.fibermask
641+
mer.jdbeg = self.jdbeg
642+
mer.jdend = self.jdend
643+
mer.jdmid = self.jdmid
644+
mer.jdltt = self.jdltt
645+
mer.jdmid_delta = self.jdmid_delta
646+
mer.hjdmid = self.hjdmid
647+
return mer
648+
504649
@property
505650
def exptime(self):
506651
return np.array([_.exptime for _ in self.speclist])
@@ -775,11 +920,14 @@ def test_meta():
775920

776921

777922
if __name__ == "__main__":
923+
import os
778924
os.chdir("/Users/cham/PycharmProjects/laspec/laspec/")
779925
fp_lrs = "./data/KIC8098300/DR6_low/spec-57287-KP193637N444141V03_sp10-161.fits.gz"
780926
fp_mrs = "./data/KIC8098300/DR7_medium/med-58625-TD192102N424113K01_sp12-076.fits.gz"
927+
import glob
781928
fps = glob.glob("./data/KIC8098300/DR7_medium/*.fits.gz")
782929
# read fits
930+
from laspec.mrs import MrsFits, MrsSpec, MrsEpoch, MrsSource
783931
mf = MrsFits(fp_mrs)
784932

785933
# print info
@@ -803,17 +951,25 @@ def test_meta():
803951
# a short way of doing this:
804952
me = mf.get_one_epoch(84420148)
805953
print(me)
806-
me = mf.get_one_epoch("COADD")
954+
me = mf.get_one_epoch("COADD", norm_type="spline")
807955
print(me, me.snr)
808956
mes = mf.get_all_epochs(including_coadd=False)
809957
print(mes)
810958

811959
msrc = MrsSource(mes)
812960
msrc1 = MrsSource.read(fps)
813961

962+
import matplotlib.pyplot as plt
814963
fig = plt.figure()
815-
plt.plot(me.wave, me.flux_norm)
964+
me.plot_norm()
965+
me.plot_norm_reduce()
816966

967+
print(me, me.reduce())
817968
# test lrs
818969
ls = MrsSpec.from_lrs(fp_lrs)
819970
ls.snr
971+
972+
# test reduce
973+
fig = plt.figure()
974+
msr = msB.reduce()
975+
msr.plot_norm()

0 commit comments

Comments
 (0)