def lcurve_from_txt(txt_file, outfile=None, noclobber=False, outdir=None, mjdref=None, gti=None): """ Load a lightcurve from a text file. Parameters ---------- txt_file : str File name of the input light curve in text format. Assumes two columns: time, counts. Times are seconds from MJDREF 55197.00076601852 (NuSTAR) if not otherwise specified. Returns ------- outfile : [str] Returned as a list with a single element for consistency with `lcurve_from_events` Other Parameters ---------------- outfile : str Output file name noclobber : bool If True, do not overwrite existing files mjdref : float, default 55197.00076601852 the MJD time reference gti : [[gti0_0, gti0_1], [gti1_0, gti1_1], ...] Good Time Intervals """ import numpy as np if mjdref is None: mjdref = np.longdouble('55197.00076601852') outfile = assign_value_if_none(outfile, hen_root(txt_file) + '_lc') outfile = outfile.replace(HEN_FILE_EXTENSION, '') + HEN_FILE_EXTENSION outdir = assign_value_if_none( outdir, os.path.dirname(os.path.abspath(txt_file))) _, outfile = os.path.split(outfile) mkdir_p(outdir) outfile = os.path.join(outdir, outfile) if noclobber and os.path.exists(outfile): warnings.warn('File exists, and noclobber option used. Skipping') return [outfile] time, counts = np.genfromtxt(txt_file, delimiter=' ', unpack=True) time = np.array(time, dtype=np.longdouble) counts = np.array(counts, dtype=np.float) lc = Lightcurve(time=time, counts=counts, gti=gti, mjdref=mjdref) lc.instr = 'EXTERN' logging.info('Saving light curve to %s' % outfile) save_lcurve(lc, outfile) return [outfile]
def test_somefunc(): lenbin = 100 T_exp = 590000 CR = 5e-3 epoch_89 = '/Users/baotong/Desktop/CDFS/txt_all_obs_0.5_8_ep3/epoch_src_test_single.txt' (TSTART, TSTOP, OBSID, exptime) = func.read_epoch(epoch_89) epoch_89 = (TSTART, TSTOP, OBSID, exptime) w = make_freq_range(dt=lenbin, epoch_file=epoch_89) # psd_model=build_psd(x=w,p=[2.3e-3, 3.4, 0., 4.3e-4],x_2=w, # p_2=[4.01e-4, 4.01e-4 / 16, 100, 2],type='bendp+lorentz') p_1 = [4.3e-4, 3.4, 0., 2e-2] p_2 = [2.67e-4, 16, 0.15, 2] psd_model = sim.build_psd(x=w, p=p_1, x_2=w, p_2=p_2, type='bendp+lorentz') frms = integrate.quad(func.bendp_lorentz, w[0], w[-1], args=(p_1, p_2))[0] frms = np.sqrt(frms) plt.loglog() plt.plot(w, psd_model) plt.xlabel('Frequency (Hz)', font2) plt.ylabel('Power', font2) plt.tick_params(labelsize=16) plt.show() lc = make_lc_from_psd(psd=psd_model, cts_rate=CR * lenbin, dt=lenbin, epoch_file=epoch_89, frms=frms) ps_org = plot_psd(lc) print('counts={0}'.format(np.sum(lc.counts))) lc_evt = Lightcurve(time=lc.time, counts=lc.counts, dt=lc.dt, gti=lc.gti) lc_evt.counts = np.random.poisson(lc_evt.counts) # ev_all = EventList() # ev_all.time = func.sim_evtlist(lc) # lc_evt = ev_all.to_lc(dt=lenbin, tstart=ev_all.time[0] - 0.5 * lenbin, # tseg=ev_all.time[-1] - ev_all.time[0]) ps_real = plot_psd(lc_evt) freq = np.arange(1 / T_exp, 0.5 / lenbin, 1 / (5 * T_exp)) freq = freq[np.where(freq > 1 / 10000.)] temp = func.get_LS(lc_evt.time, lc_evt.counts, freq=freq) # plt.subplot(121) plt.xlabel('Time', font2) plt.ylabel('Counts/bin', font2) plt.tick_params(labelsize=16) plt.plot(lc.time, lc.counts, color='red') # plt.subplot(122) plt.show() plt.plot(lc_evt.time, lc_evt.counts, color='green') print('counts={0}'.format(np.sum(lc_evt.counts))) plt.xlabel('Time', font2) plt.ylabel('Counts/bin', font2) plt.tick_params(labelsize=16) plt.show() evt = EventList() EventList.simulate_times(evt, lc=lc) print('counts={0}'.format(len(evt.time)))
def test_simulate_times_with_spline(self): """Simulate photon arrival times, with use_spline option enabled. """ lc = Lightcurve(self.time, self.counts_flat, gti=self.gti) times = simulate_times(lc, use_spline=True) lc_sim = Lightcurve.make_lightcurve(times, gti=lc.gti, dt=lc.dt, tstart=lc.tstart, tseg=lc.tseg) assert np.all((lc - lc_sim).counts < 3 * np.sqrt(lc.counts))
def _make_segment_spectrum(self, lc1, lc2, segment_size): # TODO: need to update this for making cross spectra. assert isinstance(lc1, Lightcurve) assert isinstance(lc2, Lightcurve) if lc1.tseg != lc2.tseg: raise ValueError("Lightcurves do not have same tseg.") # If dt differs slightly, its propagated error must not be more than # 1/100th of the bin if not np.isclose(lc1.dt, lc2.dt, rtol=0.01 * lc1.dt / lc1.tseg): raise ValueError("Light curves do not have same time binning dt.") # In case a small difference exists, ignore it lc1.dt = lc2.dt if self.gti is None: self.gti = cross_two_gtis(lc1.gti, lc2.gti) lc1.gti = lc2.gti = self.gti lc1._apply_gtis() lc2._apply_gtis() check_gtis(self.gti) cs_all = [] nphots1_all = [] nphots2_all = [] start_inds, end_inds = \ bin_intervals_from_gtis(self.gti, segment_size, lc1.time, dt=lc1.dt) for start_ind, end_ind in zip(start_inds, end_inds): time_1 = lc1.time[start_ind:end_ind] counts_1 = lc1.counts[start_ind:end_ind] counts_1_err = lc1.counts_err[start_ind:end_ind] time_2 = lc2.time[start_ind:end_ind] counts_2 = lc2.counts[start_ind:end_ind] counts_2_err = lc2.counts_err[start_ind:end_ind] gti1 = np.array([[time_1[0] - lc1.dt / 2, time_1[-1] + lc1.dt / 2]]) gti2 = np.array([[time_2[0] - lc2.dt / 2, time_2[-1] + lc2.dt / 2]]) lc1_seg = Lightcurve(time_1, counts_1, err=counts_1_err, err_dist=lc1.err_dist, gti=gti1, dt=lc1.dt) lc2_seg = Lightcurve(time_2, counts_2, err=counts_2_err, err_dist=lc2.err_dist, gti=gti2, dt=lc2.dt) cs_seg = Crossspectrum(lc1_seg, lc2_seg, norm=self.norm) cs_all.append(cs_seg) nphots1_all.append(np.sum(lc1_seg.counts)) nphots2_all.append(np.sum(lc2_seg.counts)) return cs_all, nphots1_all, nphots2_all
def test_simulate_times(self): """Simulate photon arrival times for an event list from light curve. """ lc = Lightcurve(self.time, self.counts_flat, gti=self.gti) times = simulate_times(lc) lc_sim = Lightcurve.make_lightcurve(times, gti=lc.gti, dt=lc.dt, tstart=lc.tstart, tseg=lc.tseg) print((lc - lc_sim).counts) assert np.all(np.abs((lc - lc_sim).counts) < 3 * np.sqrt(lc.counts))
def load_lcurve(fname): """Load light curve from a file.""" if get_file_format(fname) == 'pickle': data = _load_data_pickle(fname) elif get_file_format(fname) == 'nc': data = _load_data_nc(fname) lcurve = Lightcurve(data['time'], data['counts'], err=data['counts_err'], gti=data['gti'], err_dist=data['err_dist'], mjdref=data['mjdref']) if 'instr' in list(data.keys()): lcurve.instr = data["instr"] if 'expo' in list(data.keys()): lcurve.expo = data["expo"] if 'e_intervals' in list(data.keys()): lcurve.e_intervals = data["e_intervals"] if 'e_interval' in list(data.keys()): lcurve.e_interval = data["e_interval"] if 'use_pi' in list(data.keys()): lcurve.use_pi = bool(data["use_pi"]) if 'header' in list(data.keys()): lcurve.header = data["header"] if 'base' in list(data.keys()): lcurve.base = data["base"] return lcurve
def sim_bunch_lc(CR, dt, period, epoch_file, outpath, num_trials=100): lenbin = dt # epoch_89 = '/Users/baotong/Desktop/CDFS/txt_all_obs_0.5_8_ep3/epoch_src_89.txt' w = make_freq_range(dt=lenbin, epoch_file=epoch_file) qpo_f = 1. / period p_1 = [4.3e-4, 3.4, 0., 2.3e-3] p_2 = [qpo_f, 16, 0.05, 2] psd_model = build_psd(x=w, p=p_1, x_2=w, p_2=p_2, type='bendp+lorentz') # frms=integrate.quad(func.bendp_lorentz,w[0],w[-1],args=(p_1,p_2))[0] # frms=np.sqrt(frms) # psd_model=build_psd(x=w,p=[4.3e-4, 3.4, 0., 2.e-2],x_2=w, # p_2=[qpo_f, 16, 0.15, 2],type='bendp+lorentz') # psd_model = build_psd(x=w, p=[2.3e-3, 3.4, 0., 4.3e-4], # type='bendp') k_trial = 0 (TSTART, TSTOP, OBSID, exptime) = epoch_file with open( outpath + 'CR_{0}_P_{1}_REJ1034.txt'.format("%.0e" % CR, "%.0d" % period), 'a+') as f: # with open(outpath+'CR_{0}_P_{1}_REJ1034_fake4.txt'.format("%.0e" %CR ,"%.0d" %period),'a+') as f: # with open(outpath + 'CR_{0}_P_{1}_A002_R15_fake4.txt'.format("%.0e" % CR, "%.0d" % period), 'a+') as f: # with open(outpath+'CR_{0}_noQPO_REJ1034_R50.txt'.format("%.0e"%CR),'a+') as f: while k_trial < num_trials: lc = make_lc_from_psd(psd=psd_model, cts_rate=CR * lenbin, dt=lenbin, epoch_file=epoch_file) print('trial' + ': ' + str(k_trial)) lc_evt = Lightcurve(time=lc.time, counts=lc.counts, dt=lc.dt, gti=lc.gti) lc_evt.counts = np.random.poisson(lc_evt.counts) T_tot = TSTOP[-1] - TSTART[0] for i in range(len(OBSID)): lc_cut = lc_evt.truncate(start=TSTART[i], stop=TSTOP[i], method='time') if i == 0: lc_long = lc_cut else: lc_long = lc_long.join(lc_cut) print('counts={0}'.format(np.sum(lc_long.counts))) T_exp = lc_long.time[-1] - lc_long.time[0] freq = np.arange(1 / T_exp, 0.5 / lenbin, 1 / (5 * T_exp)) freq = freq[np.where(freq > 1 / 20000.)] # print(T_tot) # print(T_exp) temp = func.get_LS(lc_long.time, lc_long.counts, freq=freq) f.writelines((str(temp[0]) + ' ' + str(temp[1]) + ' ' + str(temp[2]) + ' ' + '\n')) k_trial += 1 f.close()
def setup_class(cls): from ..simulator import Simulator dt = 0.01 cls.time_lag = 5. data = np.load(os.path.join(datadir, "sample_variable_lc.npy")) flux = data times = np.arange(data.size) * dt maxfreq = 0.25 / cls.time_lag roll_amount = int(cls.time_lag // dt) good = slice(roll_amount, roll_amount + int(200 // dt)) rolled_flux = np.array(np.roll(flux, roll_amount)) times, flux, rolled_flux = times[good], flux[good], rolled_flux[good] length = times[-1] - times[0] test_lc1 = Lightcurve(times, flux, err_dist="gauss", dt=dt, skip_checks=True) test_lc2 = Lightcurve(test_lc1.time, rolled_flux, err_dist=test_lc1.err_dist, dt=dt) test_ev1, test_ev2 = EventList(), EventList() test_ev1.simulate_times(test_lc1) test_ev2.simulate_times(test_lc2) test_ev1.energy = np.random.uniform(0.3, 9, len(test_ev1.time)) test_ev2.energy = np.random.uniform(9, 12, len(test_ev2.time)) cls.lag = LagEnergySpectrum( test_ev1, freq_interval=[0, maxfreq], energy_spec=(0.3, 9, 1, "lin"), ref_band=[9, 12], bin_time=dt / 2, segment_size=length, events2=test_ev2, ) # Make single event list test_ev = test_ev1.join(test_ev2) cls.lag_same = LagEnergySpectrum( test_ev, freq_interval=[0, maxfreq], energy_spec=(0.3, 9, 1, "lin"), ref_band=[9, 12], bin_time=dt / 2, segment_size=length, )
def setup_class(cls): maxtime = 2 ** 21 time = np.arange(maxtime) counts1 = np.random.poisson(10, time.size) cls.lc1 = Lightcurve( time, counts1, skip_checks=True, gti=[[0, maxtime]] ) counts2 = np.random.poisson(10, time.size) cls.lc2 = Lightcurve( time, counts2, skip_checks=True, gti=[[0, maxtime]] )
def _construct_lightcurves(self, channel_band, tstart=None, tstop=None, exclude=True, only_base=False): if self.use_pi: energies1 = self.events1.pi energies2 = self.events2.pi else: energies2 = self.events2.energy energies1 = self.events1.energy gti = cross_two_gtis(self.events1.gti, self.events2.gti) tstart = assign_value_if_none(tstart, gti[0, 0]) tstop = assign_value_if_none(tstop, gti[-1, -1]) good = (energies1 >= channel_band[0]) & (energies1 < channel_band[1]) base_lc = Lightcurve.make_lightcurve(self.events1.time[good], self.bin_time, tstart=tstart, tseg=tstop - tstart, gti=gti, mjdref=self.events1.mjdref) if only_base: return base_lc if exclude: ref_intervals = self._decide_ref_intervals(channel_band, self.ref_band) else: ref_intervals = self.ref_band ref_lc = Lightcurve(base_lc.time, np.zeros_like(base_lc.counts), gti=base_lc.gti, mjdref=base_lc.mjdref, err_dist='gauss') for i in ref_intervals: good = (energies2 >= i[0]) & (energies2 < i[1]) new_lc = Lightcurve.make_lightcurve(self.events2.time[good], self.bin_time, tstart=tstart, tseg=tstop - tstart, gti=base_lc.gti, mjdref=self.events2.mjdref) ref_lc = ref_lc + new_lc ref_lc.err_dist = base_lc.err_dist return base_lc, ref_lc
def correct_lightcurve(lc_file, uf_file, outname=None, expo_limit=1e-7): """Apply exposure correction to light curve. Parameters ---------- lc_file : str The light curve file, in HENDRICS format uf_file : str The unfiltered event file, in FITS format Returns ------- outdata : str Output data structure Other Parameters ---------------- outname : str Output file name """ outname = _assign_value_if_none( outname, hen_root(lc_file) + "_lccorr" + HEN_FILE_EXTENSION) ftype, contents = get_file_type(lc_file) time = contents.time lc = contents.counts dt = contents.dt gti = contents.gti expo = get_exposure_from_uf(time, uf_file, dt=dt, gti=gti) newlc = np.array(lc / expo * dt, dtype=np.float64) newlc[expo < expo_limit] = 0 newlc_err = np.array(contents.counts_err / expo * dt, dtype=np.float64) newlc_err[expo < expo_limit] = 0 lcurve = Lightcurve(time, newlc, err=newlc_err, gti=gti, err_dist='gauss', mjdref=contents.mjdref) lcurve.expo = expo save_lcurve(lcurve, outname) return outname
def generate_deadtime_lc(ev, dt, tstart=0, tseg=None, deadtime=2.5e-3): ev = filter_for_deadtime(ev, deadtime) return Lightcurve.make_lightcurve(ev, dt=dt, tstart=tstart, tseg=tseg, gti=np.array([[tstart, tseg]]))
def setup_class(cls): from ..simulator import Simulator cls.bin_time = 0.01 data = np.load(os.path.join(datadir, "sample_variable_lc.npy")) # No need for huge count rates flux = data / 40 times = np.arange(data.size) * cls.bin_time gti = np.asarray([[0, data.size * cls.bin_time]]) test_lc = Lightcurve(times, flux, err_dist="gauss", gti=gti, dt=cls.bin_time, skip_checks=True) cls.test_ev1, cls.test_ev2 = EventList(), EventList() cls.test_ev1.simulate_times(test_lc) cls.test_ev2.simulate_times(test_lc) N1 = cls.test_ev1.time.size N2 = cls.test_ev2.time.size cls.test_ev1.energy = np.random.uniform(0.3, 12, N1) cls.test_ev2.energy = np.random.uniform(0.3, 12, N2) mask = np.sort(np.random.randint(0, min(N1, N2) - 1, 200000)) cls.test_ev1_small = cls.test_ev1.apply_mask(mask) cls.test_ev2_small = cls.test_ev2.apply_mask(mask)
def setup_class(cls): cls.pulse_frequency = 1 / 0.101 cls.tstart = 0 cls.tend = 25.25 cls.tseg = cls.tend - cls.tstart cls.dt = 0.00606 cls.times = np.arange(cls.tstart, cls.tend, cls.dt) + cls.dt / 2 cls.counts = \ 100 + 20 * np.cos(2 * np.pi * cls.times * cls.pulse_frequency) lc = Lightcurve(cls.times, cls.counts, gti=[[cls.tstart, cls.tend]]) events = EventList() events.simulate_times(lc) events.mjdref = 57000. cls.event_times = events.time cls.dum = 'events' + HEN_FILE_EXTENSION save_events(events, cls.dum) curdir = os.path.abspath(os.path.dirname(__file__)) cls.datadir = os.path.join(curdir, 'data') fits_file = os.path.join(cls.datadir, 'monol_testA.evt') command = 'HENreadevents {0}'.format(fits_file) sp.check_call(command.split()) cls.real_event_file = os.path.join( cls.datadir, 'monol_testA_nustar_fpma_ev' + HEN_FILE_EXTENSION)
def setup_class(cls): time = np.arange(0, 1e7) counts = np.random.poisson(10, time.size) cls.lc = Lightcurve(time, counts, skip_checks=True) evtimes = np.sort(np.random.uniform(0, 1e7, 10**7)) pi = np.random.randint(0, 100, evtimes.size) energy = pi * 0.04 + 1.6 cls.ev = EventList( time=evtimes, pi=pi, energy=energy, gti=[[0, 1e7]], dt=1e-5, notes="Bu", ) cls.ev_noattrs = copy.deepcopy(cls.ev) cls.ev_noattrs.energy = None cls.ev_noattrs.pi = None cls.ev_noattrs.mjdref = 0 cls.ev_noattrs.gti = None cls.ev_noattrs.dt = 0 cls.ev_noattrs.notes = None cls.lc_path = saveData(cls.lc, persist=False) cls.ev_path = saveData(cls.ev, persist=False) cls.ev_path_noattrs = saveData(cls.ev_noattrs, persist=False)
def _construct_lightcurves(self, channel_band, tstart=None, tstop=None, exclude=True, only_base=False): if self.use_pi: energies1 = self.events1.pi energies2 = self.events2.pi else: energies2 = self.events2.energy energies1 = self.events1.energy gti = cross_two_gtis(self.events1.gti, self.events2.gti) tstart = assign_value_if_none(tstart, gti[0, 0]) tstop = assign_value_if_none(tstop, gti[-1, -1]) good = (energies1 >= channel_band[0]) & (energies1 < channel_band[1]) base_lc = Lightcurve.make_lightcurve(self.events1.time[good], self.bin_time, tstart=tstart, tseg=tstop - tstart, gti=gti, mjdref=self.events1.mjdref) if only_base: return base_lc if exclude: ref_intervals = self._decide_ref_intervals(channel_band, self.ref_band) else: ref_intervals = self.ref_band ref_lc = Lightcurve(base_lc.time, np.zeros_like(base_lc.counts), gti=base_lc.gti, mjdref=base_lc.mjdref, err_dist='gauss') for i in ref_intervals: good = (energies2 >= i[0]) & (energies2 < i[1]) new_lc = Lightcurve.make_lightcurve(self.events2.time[good], self.bin_time, tstart=tstart, tseg=tstop - tstart, gti=base_lc.gti, mjdref=self.events2.mjdref) ref_lc = ref_lc + new_lc ref_lc.err_dist = base_lc.err_dist return base_lc, ref_lc
def _make_segment_spectrum(self, lc1, lc2, segment_size): # TODO: need to update this for making cross spectra. assert isinstance(lc1, Lightcurve) assert isinstance(lc2, Lightcurve) if lc1.dt != lc2.dt: raise ValueError("Light curves do not have same time binning dt.") if lc1.tseg != lc2.tseg: raise ValueError("Lightcurves do not have same tseg.") if self.gti is None: self.gti = cross_two_gtis(lc1.gti, lc2.gti) check_gtis(self.gti) cs_all = [] nphots1_all = [] nphots2_all = [] start_inds, end_inds = \ bin_intervals_from_gtis(self.gti, segment_size, lc1.time) for start_ind, end_ind in zip(start_inds, end_inds): time_1 = lc1.time[start_ind:end_ind] counts_1 = lc1.counts[start_ind:end_ind] counts_1_err = lc1.counts_err[start_ind:end_ind] time_2 = lc2.time[start_ind:end_ind] counts_2 = lc2.counts[start_ind:end_ind] counts_2_err = lc2.counts_err[start_ind:end_ind] lc1_seg = Lightcurve(time_1, counts_1, err=counts_1_err, err_dist=lc1.err_dist) lc2_seg = Lightcurve(time_2, counts_2, err=counts_2_err, err_dist=lc2.err_dist) cs_seg = Crossspectrum(lc1_seg, lc2_seg, norm=self.norm) cs_all.append(cs_seg) nphots1_all.append(np.sum(lc1_seg.counts)) nphots2_all.append(np.sum(lc2_seg.counts)) return cs_all, nphots1_all, nphots2_all
def test_simulate_times_with_spline(self): """Simulate photon arrival times, with use_spline option enabled. """ lc = Lightcurve(self.time, self.counts_flat, gti=self.gti) times = simulate_times(lc, use_spline=True) lc_sim = Lightcurve.make_lightcurve(times, gti=lc.gti, dt=lc.dt, tstart=lc.tstart, tseg=lc.tseg) assert np.all((lc - lc_sim).counts < 3 * np.sqrt(lc.counts))
def test_load_and_save_xps_no_all(self): lcurve1 = Lightcurve(np.linspace(0, 10, 150), np.random.poisson(30, 150), mjdref=54385.3254923845, gti=np.longdouble([[-0.5, 3.5]])) lcurve2 = Lightcurve(np.linspace(0, 10, 150), np.random.poisson(30, 150), mjdref=54385.3254923845, gti=np.longdouble([[-0.5, 3.5]])) xps = AveragedCrossspectrum(lcurve1, lcurve2, 1) outfile = 'small_xps' + HEN_FILE_EXTENSION save_pds(xps, outfile, save_all=False) xps2 = load_pds(outfile) assert np.allclose(xps.gti, xps2.gti) assert xps.m == xps2.m assert not hasattr(xps2, 'pds1')
def test_simulate_times(self): """Simulate photon arrival times for an event list from light curve. """ lc = Lightcurve(self.time, self.counts_flat, gti=self.gti) times = simulate_times(lc) lc_sim = Lightcurve.make_lightcurve(times, gti=lc.gti, dt=lc.dt, tstart=lc.tstart, tseg=lc.tseg) assert np.all((lc - lc_sim).counts < 3 * np.sqrt(lc.counts))
def test_get_lightcurve_dataset_from_stingray_Lightcurve(capsys): from stingray.lightcurve import Lightcurve from astropy.io.fits import Header lc = Lightcurve([0, 1], [2, 2]) ds = get_lightcurve_dataset_from_stingray_Lightcurve(lc) out, err = capsys.readouterr() assert err.strip().endswith("Light curve has no header") header = Header() header["Bu"] = "Bu" lc.header = header.tostring() ds = get_lightcurve_dataset_from_stingray_Lightcurve(lc) assert np.allclose(ds.tables["RATE"].columns["TIME"].values, lc.time) assert np.allclose(ds.tables["RATE"].columns["RATE"].values, lc.counts)
def test_load_and_save_xps_quick(self): lcurve1 = Lightcurve(np.linspace(0, 10, 150), np.random.poisson(30, 150), mjdref=54385.3254923845, gti=np.longdouble([[-0.5, 3.5]])) lcurve2 = Lightcurve(np.linspace(0, 10, 150), np.random.poisson(30, 150), mjdref=54385.3254923845, gti=np.longdouble([[-0.5, 3.5]])) xps = AveragedCrossspectrum(lcurve1, lcurve2, 1) save_pds(xps, self.dum) xps2 = load_pds(self.dum, nosub=True) assert np.allclose(xps.gti, xps2.gti) assert xps.m == xps2.m assert not hasattr(xps2, 'pds1')
def test_load_and_save_xps(self): lcurve1 = Lightcurve(np.linspace(0, 10, 150), np.random.poisson(30, 150), mjdref=54385.3254923845, gti = np.longdouble([[-0.5, 3.5]])) lcurve2 = Lightcurve(np.linspace(0, 10, 150), np.random.poisson(30, 150), mjdref=54385.3254923845, gti = np.longdouble([[-0.5, 3.5]])) xps = AveragedCrossspectrum(lcurve1, lcurve2, 1) save_pds(xps, self.dum) xps2 = load_pds(self.dum) assert np.allclose(xps.gti, xps2.gti) assert xps.m == xps2.m lag, lag_err = xps.time_lag() lag2, lag2_err = xps2.time_lag() assert np.allclose(lag, lag2)
def test_get_lightcurve_dataset_from_stingray_Lightcurve(capsys): from stingray.lightcurve import Lightcurve from astropy.io.fits import Header lc = Lightcurve([0, 1], [2, 2]) ds = get_lightcurve_dataset_from_stingray_Lightcurve(lc) out, err = capsys.readouterr() if err: assert err.strip().endswith("Light curve has no header") header = Header() header["Bu"] = "Bu" lc.header = header.tostring() ds = get_lightcurve_dataset_from_stingray_Lightcurve(lc) assert np.allclose(ds.tables["RATE"].columns["TIME"].values, lc.time) assert np.allclose(ds.tables["RATE"].columns["RATE"].values, lc.counts)
def test_load_and_save_lcurve(self): lcurve = Lightcurve(np.linspace(0, 10, 15), np.random.poisson(30, 15), mjdref=54385.3254923845, gti = np.longdouble([[-0.5, 3.5]])) save_lcurve(lcurve, self.dum) lcurve2 = load_lcurve(self.dum) assert np.allclose(lcurve.time, lcurve2.time) assert np.allclose(lcurve.counts, lcurve2.counts) assert np.allclose(lcurve.mjdref, lcurve2.mjdref) assert np.allclose(lcurve.gti, lcurve2.gti) assert lcurve.err_dist == lcurve2.err_dist
def setup_class(cls): cls.pulse_frequency = 1 / 0.101 cls.tstart = 0 cls.tend = 25.25 cls.tseg = cls.tend - cls.tstart cls.dt = 0.00606 cls.times = np.arange(cls.tstart, cls.tend, cls.dt) + cls.dt / 2 cls.counts = \ 100 + 20 * np.cos(2 * np.pi * cls.times * cls.pulse_frequency) lc = Lightcurve(cls.times, cls.counts, gti=[[cls.tstart, cls.tend]]) events = EventList() events.simulate_times(lc) cls.event_times = events.time cls.dum = 'events' + HEN_FILE_EXTENSION save_events(events, cls.dum)
def setup_class(cls): time = np.arange(0, 1e7) counts = np.random.poisson(10, time.size) cls.lc = Lightcurve(time, counts, skip_checks=True) evtimes = np.sort(np.random.uniform(0, 1e7, 10**7)) pi = np.random.randint(0, 100, evtimes.size) energy = pi * 0.04 + 1.6 cls.ev = EventList( time=evtimes, pi=pi, energy=energy, gti=[[0, 1e7]], dt=1e-5, notes="Bu", )
def pulsar_events_mp(length, period, ctrate, pulsed_fraction, mean_obs, bkg_ctrate, detlev, nbin=128): nustar_orb = 5808 dt = period / 20 # The total length of the time series should be the number of pointings times the time per orbit. # Add one orbit for buffer. N_orb = int(round(length / mean_obs, 0)) tot_len = (N_orb + 1) * nustar_orb # The orbital period is 5808s. Every 5808s, a continuous observation with min_obs < length < max_obs begins start_t = numpy.multiply( numpy.arange(N_orb), numpy.random.normal(loc=nustar_orb, scale=60, size=N_orb)) point_t = numpy.random.uniform(low=mean_obs - 500, high=mean_obs + 500, size=N_orb) end_t = numpy.add(start_t, point_t) times = numpy.arange(dt / 2, tot_len + dt / 2, dt) cont_lc = numpy.random.poisson( (ctrate * (1 + pulsed_fraction * numpy.cos(2 * numpy.pi / period * times)) * dt)) + numpy.random.poisson(bkg_ctrate * dt) lc = Lightcurve(time=times, counts=cont_lc, gti=numpy.column_stack((start_t, end_t)), dt=dt) exposure = numpy.sum(point_t) events = EventList() events.gti = lc.gti events.simulate_times(lc) phase = numpy.arange(0, 1, 1 / nbin) zsq = z_n(phase, n=2, norm=fold_events(events.time, 1 / period, nbin=nbin)[1]) detected = zsq > detlev return (detected, exposure)
def setup_class(cls): from ..simulator.simulator import Simulator dt = 0.1 simulator = Simulator(dt, 1000, rms=0.4, mean=200) test_lc1 = simulator.simulate(2) test_lc2 = Lightcurve(test_lc1.time, np.array(np.roll(test_lc1.counts, 2)), err_dist=test_lc1.err_dist, dt=dt) test_ev1, test_ev2 = EventList(), EventList() test_ev1.simulate_times(test_lc1) test_ev2.simulate_times(test_lc2) test_ev1.energy = np.random.uniform(0.3, 9, len(test_ev1.time)) test_ev2.energy = np.random.uniform(9, 12, len(test_ev2.time)) cls.lag = LagEnergySpectrum(test_ev1, [0., 0.5], (0.3, 9, 4, "lin"), [9, 12], bin_time=0.1, segment_size=30, events2=test_ev2)
def test_zhang_model_accurate(): bintime = 1 / 4096 deadtime = 2.5e-3 length = 2000 fftlen = 5 r = 300 events, events_dt = simulate_events(r, length, deadtime=deadtime) lc_dt = Lightcurve.make_lightcurve(events_dt, bintime, tstart=0, tseg=length) pds = AveragedPowerspectrum(lc_dt, fftlen, norm='leahy') zh_f, zh_p = pds_model_zhang(1000, r, deadtime, bintime, limit_k=100) deadtime_fun = interp1d(zh_f, zh_p, bounds_error=False, fill_value="extrapolate") ratio = pds.power / deadtime_fun(pds.freq) assert np.isclose(np.mean(ratio), 1, atol=0.001) assert np.isclose(np.std(ratio), 1 / np.sqrt(pds.m), atol=0.001)
def lcurve_from_fits(fits_file, gtistring='GTI', timecolumn='TIME', ratecolumn=None, ratehdu=1, fracexp_limit=0.9, outfile=None, noclobber=False, outdir=None): """ Load a lightcurve from a fits file and save it in HENDRICS format. .. note :: FITS light curve handling is still under testing. Absolute times might be incorrect depending on the light curve format. Parameters ---------- fits_file : str File name of the input light curve in FITS format Returns ------- outfile : [str] Returned as a list with a single element for consistency with `lcurve_from_events` Other Parameters ---------------- gtistring : str Name of the GTI extension in the FITS file timecolumn : str Name of the column containing times in the FITS file ratecolumn : str Name of the column containing rates in the FITS file ratehdu : str or int Name or index of the FITS extension containing the light curve fracexp_limit : float Minimum exposure fraction allowed outfile : str Output file name noclobber : bool If True, do not overwrite existing files """ logging.warning( """WARNING! FITS light curve handling is still under testing. Absolute times might be incorrect.""") # TODO: # treat consistently TDB, UTC, TAI, etc. This requires some documentation # reading. For now, we assume TDB from astropy.io import fits as pf from astropy.time import Time import numpy as np from .base import create_gti_from_condition outfile = assign_value_if_none(outfile, hen_root(fits_file) + '_lc') outfile = outfile.replace(HEN_FILE_EXTENSION, '') + HEN_FILE_EXTENSION outdir = assign_value_if_none( outdir, os.path.dirname(os.path.abspath(fits_file))) _, outfile = os.path.split(outfile) mkdir_p(outdir) outfile = os.path.join(outdir, outfile) if noclobber and os.path.exists(outfile): warnings.warn('File exists, and noclobber option used. Skipping') return [outfile] lchdulist = pf.open(fits_file) lctable = lchdulist[ratehdu].data # Units of header keywords tunit = lchdulist[ratehdu].header['TIMEUNIT'] try: mjdref = high_precision_keyword_read(lchdulist[ratehdu].header, 'MJDREF') mjdref = Time(mjdref, scale='tdb', format='mjd') except: mjdref = None try: instr = lchdulist[ratehdu].header['INSTRUME'] except: instr = 'EXTERN' # ---------------------------------------------------------------- # Trying to comply with all different formats of fits light curves. # It's a madness... try: tstart = high_precision_keyword_read(lchdulist[ratehdu].header, 'TSTART') tstop = high_precision_keyword_read(lchdulist[ratehdu].header, 'TSTOP') except: raise(Exception('TSTART and TSTOP need to be specified')) # For nulccorr lcs this whould work timezero = high_precision_keyword_read(lchdulist[ratehdu].header, 'TIMEZERO') # Sometimes timezero is "from tstart", sometimes it's an absolute time. # This tries to detect which case is this, and always consider it # referred to tstart timezero = assign_value_if_none(timezero, 0) # for lcurve light curves this should instead work if tunit == 'd': # TODO: # Check this. For now, I assume TD (JD - 2440000.5). # This is likely wrong timezero = Time(2440000.5 + timezero, scale='tdb', format='jd') tstart = Time(2440000.5 + tstart, scale='tdb', format='jd') tstop = Time(2440000.5 + tstop, scale='tdb', format='jd') # if None, use NuSTAR defaulf MJDREF mjdref = assign_value_if_none( mjdref, Time(np.longdouble('55197.00076601852'), scale='tdb', format='mjd')) timezero = (timezero - mjdref).to('s').value tstart = (tstart - mjdref).to('s').value tstop = (tstop - mjdref).to('s').value if timezero > tstart: timezero -= tstart time = np.array(lctable.field(timecolumn), dtype=np.longdouble) if time[-1] < tstart: time += timezero + tstart else: time += timezero try: dt = high_precision_keyword_read(lchdulist[ratehdu].header, 'TIMEDEL') if tunit == 'd': dt *= 86400 except: warnings.warn('Assuming that TIMEDEL is the difference between the' ' first two times of the light curve') dt = time[1] - time[0] # ---------------------------------------------------------------- ratecolumn = assign_value_if_none( ratecolumn, _look_for_array_in_array(['RATE', 'RATE1', 'COUNTS'], lctable.names)) rate = np.array(lctable.field(ratecolumn), dtype=np.float) try: rate_e = np.array(lctable.field('ERROR'), dtype=np.longdouble) except: rate_e = np.zeros_like(rate) if 'RATE' in ratecolumn: rate *= dt rate_e *= dt try: fracexp = np.array(lctable.field('FRACEXP'), dtype=np.longdouble) except: fracexp = np.ones_like(rate) good_intervals = (rate == rate) * (fracexp >= fracexp_limit) * \ (fracexp <= 1) rate[good_intervals] /= fracexp[good_intervals] rate_e[good_intervals] /= fracexp[good_intervals] rate[np.logical_not(good_intervals)] = 0 try: gtitable = lchdulist[gtistring].data gti_list = np.array([[a, b] for a, b in zip(gtitable.field('START'), gtitable.field('STOP'))], dtype=np.longdouble) except: gti_list = create_gti_from_condition(time, good_intervals) lchdulist.close() lc = Lightcurve(time=time, counts=rate, err=rate_e, gti=gti_list, mjdref=mjdref.mjd) lc.instr = instr lc.header = lchdulist[ratehdu].header.tostring() logging.info('Saving light curve to %s' % outfile) save_lcurve(lc, outfile) return [outfile]
def lcurve_from_events(f, safe_interval=0, pi_interval=None, e_interval=None, min_length=0, gti_split=False, ignore_gtis=False, bintime=1., outdir=None, outfile=None, noclobber=False): """Bin an event list in a light curve. Parameters ---------- f : str Input event file name bintime : float The bin time of the output light curve Returns ------- outfiles : list List of output light curves Other Parameters ---------------- safe_interval : float or [float, float] Seconds to filter out at the start and end of each GTI. If single float, these safe windows are equal, otherwise the two numbers refer to the start and end of the GTI respectively pi_interval : [int, int] PI channel interval to select. Default None, meaning that all PI channels are used e_interval : [float, float] Energy interval to select (only works if event list is calibrated with `calibrate`). Default None min_length : float GTIs below this length will be filtered out gti_split : bool If True, create one light curve for each good time interval ignore_gtis : bool Ignore good time intervals, and get a single light curve that includes possible gaps outdir : str Output directory outfile : str Output file noclobber : bool If True, do not overwrite existing files """ logging.info("Loading file %s..." % f) evdata = load_events(f) logging.info("Done.") if bintime < 0: bintime = 2 ** (bintime) bintime = np.longdouble(bintime) tag = '' gtis = evdata.gti tstart = np.min(gtis) tstop = np.max(gtis) events = evdata.time if hasattr(evdata, 'instr') and evdata.instr is not None: instr = evdata.instr else: instr = "unknown" if ignore_gtis: gtis = np.array([[tstart, tstop]]) evdata.gtis = gtis total_lc = evdata.to_lc(100) total_lc.instr = instr # Then, apply filters if pi_interval is not None and np.all(np.array(pi_interval) > 0): pis = evdata.pi good = np.logical_and(pis > pi_interval[0], pis <= pi_interval[1]) events = events[good] tag = '_PI%g-%g' % (pi_interval[0], pi_interval[1]) elif e_interval is not None and np.all(np.array(e_interval) > 0): if not hasattr(evdata, 'energy') or evdata.energy is None: raise \ ValueError("No energy information is present in the file." + " Did you run HENcalibrate?") es = evdata.energy good = np.logical_and(es > e_interval[0], es <= e_interval[1]) events = events[good] tag = '_E%g-%g' % (e_interval[0], e_interval[1]) else: pass if tag != "": save_lcurve(total_lc, hen_root(f) + '_std_lc' + HEN_FILE_EXTENSION) # Assign default value if None outfile = assign_value_if_none(outfile, hen_root(f) + tag + '_lc') # Take out extension from name, if present, then give extension. This # avoids multiple extensions outfile = outfile.replace(HEN_FILE_EXTENSION, '') + HEN_FILE_EXTENSION outdir = assign_value_if_none( outdir, os.path.dirname(os.path.abspath(f))) _, outfile = os.path.split(outfile) mkdir_p(outdir) outfile = os.path.join(outdir, outfile) if noclobber and os.path.exists(outfile): warnings.warn('File exists, and noclobber option used. Skipping') return [outfile] lc = Lightcurve.make_lightcurve(events, bintime, tstart=tstart, tseg=tstop-tstart, mjdref=evdata.mjdref) lc.instr = instr lc = filter_lc_gtis(lc, safe_interval=safe_interval, delete=False, min_length=min_length) if len(lc.gti) == 0: warnings.warn( "No GTIs above min_length ({0}s) found.".format(min_length)) return if gti_split: lcs = lc.split_by_gti() outfiles = [] for ib, l0 in enumerate(lcs): local_tag = tag + '_gti%d' % ib outf = hen_root(outfile) + local_tag + '_lc' + HEN_FILE_EXTENSION if noclobber and os.path.exists(outf): warnings.warn( 'File exists, and noclobber option used. Skipping') outfiles.append(outf) l0.instr = lc.instr save_lcurve(l0, outf) outfiles.append(outf) else: logging.info('Saving light curve to %s' % outfile) save_lcurve(lc, outfile) outfiles = [outfile] # For consistency in return value return outfiles
def _make_segment_spectrum(self, lc1, lc2, segment_size): """ Split the light curves into segments of size ``segment_size``, and calculate a cross spectrum for each. Parameters ---------- lc1, lc2 : :class:`stingray.Lightcurve` objects Two light curves used for computing the cross spectrum. segment_size : ``numpy.float`` Size of each light curve segment to use for averaging. Returns ------- cs_all : list of :class:`Crossspectrum`` objects A list of cross spectra calculated independently from each light curve segment nphots1_all, nphots2_all : ``numpy.ndarray` for each of ``lc1`` and ``lc2`` Two lists containing the number of photons for all segments calculated from ``lc1`` and ``lc2``. """ # TODO: need to update this for making cross spectra. assert isinstance(lc1, Lightcurve) assert isinstance(lc2, Lightcurve) if lc1.tseg != lc2.tseg: simon("Lightcurves do not have same tseg. This means that the data" "from the two channels are not completely in sync. This " "might or might not be an issue. Keep an eye on it.") # If dt differs slightly, its propagated error must not be more than # 1/100th of the bin if not np.isclose(lc1.dt, lc2.dt, rtol=0.01 * lc1.dt / lc1.tseg): raise ValueError("Light curves do not have same time binning dt.") # In case a small difference exists, ignore it lc1.dt = lc2.dt gti = cross_two_gtis(lc1.gti, lc2.gti) lc1.apply_gtis() lc2.apply_gtis() if self.gti is None: self.gti = gti else: if not np.all(self.gti == gti): self.gti = np.vstack([self.gti, gti]) check_gtis(self.gti) cs_all = [] nphots1_all = [] nphots2_all = [] start_inds, end_inds = \ bin_intervals_from_gtis(gti, segment_size, lc1.time, dt=lc1.dt) simon("Errorbars on cross spectra are not thoroughly tested. " "Please report any inconsistencies.") for start_ind, end_ind in zip(start_inds, end_inds): time_1 = lc1.time[start_ind:end_ind] counts_1 = lc1.counts[start_ind:end_ind] counts_1_err = lc1.counts_err[start_ind:end_ind] time_2 = lc2.time[start_ind:end_ind] counts_2 = lc2.counts[start_ind:end_ind] counts_2_err = lc2.counts_err[start_ind:end_ind] gti1 = np.array([[time_1[0] - lc1.dt / 2, time_1[-1] + lc1.dt / 2]]) gti2 = np.array([[time_2[0] - lc2.dt / 2, time_2[-1] + lc2.dt / 2]]) lc1_seg = Lightcurve(time_1, counts_1, err=counts_1_err, err_dist=lc1.err_dist, gti=gti1, dt=lc1.dt, skip_checks=True) lc2_seg = Lightcurve(time_2, counts_2, err=counts_2_err, err_dist=lc2.err_dist, gti=gti2, dt=lc2.dt, skip_checks=True) with warnings.catch_warnings(record=True) as w: cs_seg = Crossspectrum(lc1_seg, lc2_seg, norm=self.norm, power_type=self.power_type) cs_all.append(cs_seg) nphots1_all.append(np.sum(lc1_seg.counts)) nphots2_all.append(np.sum(lc2_seg.counts)) return cs_all, nphots1_all, nphots2_all
def main(args=None): """Main function called by the `HENcolors` command line script.""" import argparse description = \ 'Calculate color light curves' parser = argparse.ArgumentParser(description=description) parser.add_argument("files", help="List of files", nargs='+') parser.add_argument("-e", "--energies", nargs=4, required=True, type=str, default=None, help="The energy boundaries in keV used to calculate " "the color. E.g. -e 2 3 4 6 means that the " "color will be calculated as 4.-6./2.-3. keV. " "If --use-pi is specified, these are interpreted " "as PI channels") parser.add_argument("-b", "--bintime", type=str, default='100', help="Bin time; if negative, negative power of 2") parser.add_argument("-o", "--out", type=str, default=None, help='Output file') parser.add_argument('--use-pi', type=bool, default=False, help="Use the PI channel instead of energies") parser.add_argument("--loglevel", help=("use given logging level (one between INFO, " "WARNING, ERROR, CRITICAL, DEBUG; " "default:WARNING)"), default='WARNING', type=str) parser.add_argument("--debug", help="use DEBUG logging level", default=False, action='store_true') args = parser.parse_args(args) files = args.files if args.debug: args.loglevel = 'DEBUG' numeric_level = getattr(logging, args.loglevel.upper(), None) logging.basicConfig(filename='HENcolors.log', level=numeric_level, filemode='w') option = '--e-interval' if args.use_pi: option = '--pi-interval' for f in files: henlcurve( [f] + [option] + args.energies[:2] + ['-b', args.bintime, '-d', '.', '-o', 'lc0' + HEN_FILE_EXTENSION]) lc0 = load_lcurve('lc0' + HEN_FILE_EXTENSION) henlcurve( [f] + [option] + args.energies[2:] + ['-b', args.bintime, '-d', '.', '-o', 'lc1' + HEN_FILE_EXTENSION]) lc1 = load_lcurve('lc1' + HEN_FILE_EXTENSION) time = lc0.time counts = lc1.countrate / lc0.countrate counts_err = np.sqrt(lc1.countrate_err**2 + lc0.countrate_err**2) scolor = Lightcurve(time=time, counts=counts, err=counts_err, input_counts=False, err_dist='gauss', gti=lc0.gti) del lc0 del lc1 os.unlink('lc0' + HEN_FILE_EXTENSION) os.unlink('lc1' + HEN_FILE_EXTENSION) if args.out is None: label = '_E_' if args.use_pi: label = '_PI_' label += '{3}-{2}_over_{1}-{0}'.format(*args.energies) args.out = hen_root(f) + label + HEN_FILE_EXTENSION scolor.e_intervals = np.asarray([float(k) for k in args.energies]) scolor.use_pi = args.use_pi save_lcurve(scolor, args.out, lctype='Color')