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 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 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_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_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 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_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 _construct_lightcurves(self, channel_band, tstart=None, tstop=None, exclude=True, only_base=False): """ Construct light curves from event data, for each band of interest. Parameters ---------- channel_band : iterable of type ``[elow, ehigh]`` The lower/upper limits of the energies to be contained in the band of interest tstart : float, optional, default ``None`` A common start time (if start of observation is different from the first recorded event) tstop : float, optional, default ``None`` A common stop time (if start of observation is different from the first recorded event) exclude : bool, optional, default ``True`` if ``True``, exclude the band of interest from the reference band only_base : bool, optional, default ``False`` if ``True``, only return the light curve of the channel of interest, not that of the reference band Returns ------- base_lc : :class:`Lightcurve` object The light curve of the channels of interest ref_lc : :class:`Lightcurve` object (only returned if ``only_base`` is ``False``) The reference light curve for comparison with ``base_lc`` """ 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 = get_non_overlapping_ref_band( 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, dt=base_lc.dt, err_dist=base_lc.err_dist, skip_checks=True, ) 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