25 from cscripts
import obsutils
26 from cscripts
import ioutils
27 from cscripts
import mputils
35 Generates a lightcurve
37 The cslightcrv class generates a light curve for Imaging Air Cherenkov
38 Telescope event data by performing a maximum likelihood fit using
39 ctlike in a series of time bins. The time bins can be either
40 specified in an ASCII file, as an interval divided into equally
41 sized time bins, or can be taken from the Good Time Intervals of the
44 The format of the ASCII file is one row per time bin, each specifying
45 the start of stop value of the bin, separated by a whitespace. The
46 times are given in Modified Julian Days (MJD).
49 >>> lcrv = cslightcrv()
51 >>> ... (querying for parameters) ...
52 >>> fits = lcrv.lightcurve()
53 Generates a light curve and retrieves the results in
56 >>> lcrv = cslightcrv()
58 >>> ... (querying for parameters) ...
59 Generates a light curve and saves results in a FITS file.
61 >>> lcrv = cslightcrv(obs)
63 >>> ... (querying for parameters) ...
64 Generates a light curve from the observations in an
65 observation container and saves results in a FITS file.
74 self._init_csobservation(self.__class__.__name__, ctools.__version__, argv)
91 Extend ctools.csobservation getstate method to include some members
99 state = {
'base' : ctools.csobservation.__getstate__(self),
113 Extend ctools.csobservation setstate method to include some members
120 ctools.csobservation.__setstate__(self, state[
'base'])
122 self.
_tbins = state[
'tbins']
124 self.
_onoff = state[
'onoff']
125 self.
_fits = state[
'fits']
135 Get parameters from parfile
139 self._setup_observations(self.obs(),
True,
True,
False)
142 self._set_obs_statistic(gammalib.toupper(self[
'statistic'].string()))
145 if self.obs().
models().size() == 0:
146 self.obs().
models(self[
'inmodel'].filename())
152 self.
_onoff = self._is_onoff()
155 self.
_srcname = self[
'srcname'].string()
162 self[
'edisp'].boolean()
163 self[
'calc_ts'].boolean()
164 self[
'calc_ulim'].boolean()
165 self[
'confidence'].real()
166 self[
'fix_bkg'].boolean()
167 self[
'fix_srcs'].boolean()
170 if self._read_ahead():
171 self[
'outfile'].query()
174 self._log_parameters(gammalib.TERSE)
184 Creates light curve time bins
188 gti : `~gammalib.GGti`
189 Light curve bins in form of Good Time Intervals
192 tref = gammalib.GTimeReference(self[
'mjdref'].real(),
's',
'TT',
'LOCAL')
195 gti = gammalib.GGti(tref)
200 algorithm = self[
'tbinalg'].string()
204 if algorithm ==
'FILE':
207 filename = self[
'tbinfile'].filename()
210 if filename.is_fits():
211 gti = gammalib.GGti(filename)
218 csv = gammalib.GCsv(filename)
219 for i
in range(csv.nrows()):
220 tmin = gammalib.GTime()
221 tmax = gammalib.GTime()
222 tmin.mjd(csv.real(i,0))
223 tmax.mjd(csv.real(i,1))
224 gti.append(tmin,tmax)
228 elif algorithm ==
'LIN':
231 time_min = self[
'tmin'].time(tref)
232 time_max = self[
'tmax'].time(tref)
233 nbins = self[
'tbins'].integer()
236 time_step = (time_max - time_min) / float(nbins)
237 for i
in range(nbins):
238 tmin = time_min + i *time_step
239 tmax = time_min + (i+1)*time_step
240 gti.append(tmin,tmax)
244 elif algorithm ==
'GTI':
247 for obs
in self.obs():
248 for i
in range(obs.events().gti().size()):
249 gti.append(obs.events().gti().tstart(i),
250 obs.events().gti().tstop(i))
257 Return list of free parameter names
262 List of free parameter names.
270 names.append(par.name())
277 Adjust model parameters dependent on user parameters
280 self._log_header1(gammalib.TERSE,
'Adjust model parameters')
283 for model
in self.obs().
models():
291 classname = model.classname()
294 self._log_header3(gammalib.NORMAL, model.name())
299 if self[
'calc_ts'].boolean():
305 elif ((self[
'fix_bkg'].boolean()
and classname !=
'GModelSky')
or
306 (self[
'fix_srcs'].boolean()
and classname ==
'GModelSky')):
310 self._log_value(gammalib.NORMAL, par.name(),
'fixed')
317 Creates FITS binary table containing light curve results
321 results : list of dict
322 List of result dictionaries
326 table : `~gammalib.GFitsBinTable`
327 FITS binary table containing light curve
333 table = gammalib.GFitsBinTable(nrows)
334 table.extname(
'LIGHTCURVE')
337 ioutils.append_result_column(table, results,
'MJD',
'days',
'mjd')
338 ioutils.append_result_column(table, results,
'e_MJD',
'days',
'e_mjd')
341 ioutils.append_model_par_column(table,
346 ioutils.append_result_column(table, results,
'TS',
'',
'ts')
349 ioutils.append_result_column(table, results,
'DiffUpperLimit',
350 'ph/cm2/s/MeV',
'ul_diff')
351 ioutils.append_result_column(table, results,
'FluxUpperLimit',
352 'ph/cm2/s',
'ul_flux')
353 ioutils.append_result_column(table, results,
'EFluxUpperLimit',
354 'erg/cm2/s',
'ul_eflux')
365 obs : `~gammalib.GObservations`
366 Observation container
370 ul_diff, ul_flux, ul_eflux : tuple of float
371 Upper limits, -1.0 of not computed
379 if self[
'calc_ulim'].boolean():
382 self._log_header3(gammalib.EXPLICIT,
'Computing upper limit')
391 source = cpy_obs.models()[self.
_srcname]
397 ulimit = ctools.ctulimit(cpy_obs)
400 ulimit[
'emin'] = self[
'emin'].real()
401 ulimit[
'emax'] = self[
'emax'].real()
402 ulimit[
'sigma_min'] = 0.0
403 ulimit[
'sigma_max'] = 3.0
404 ulimit[
'confidence'] = self[
'confidence'].real()
409 ul_diff = ulimit.diff_ulimit()
410 ul_flux = ulimit.flux_ulimit()
411 ul_eflux = ulimit.eflux_ulimit()
413 self._log_string(gammalib.TERSE,
'Upper limit calculation failed.')
419 return ul_diff, ul_flux, ul_eflux
423 Run likelihood analysis in one time bin
433 Results of the likelihood analysis
439 tmin = self._tbins.tstart(i)
440 tmax = self._tbins.tstop(i)
443 self._log_header2(gammalib.TERSE,
'MJD %f - %f ' %
444 (tmin.mjd(), tmax.mjd()))
447 twidth = 0.5 * (tmax - tmin)
448 tmean = tmin + twidth
451 result = {
'mjd': tmean.mjd(),
452 'e_mjd': twidth / gammalib.sec_in_day,
461 self._log_header3(gammalib.EXPLICIT,
'Selecting observations')
465 select[
'pntselect'] =
'CIRCLE'
466 select[
'coordsys'] =
'GAL'
469 select[
'rad'] = 180.0
470 select[
'tmin'] = tmin
471 select[
'tmax'] = tmax
481 self._log_header3(gammalib.EXPLICIT,
'Selecting events')
484 select = ctools.ctselect(obs)
485 select[
'emin'] = self[
'emin'].real()
486 select[
'emax'] = self[
'emax'].real()
487 select[
'tmin'] = tmin
488 select[
'tmax'] = tmax
489 select[
'rad'] =
'UNDEFINED'
490 select[
'ra'] =
'UNDEFINED'
491 select[
'dec'] =
'UNDEFINED'
507 new_obs = obsutils.get_stacked_obs(self, obs, nthreads=1)
512 new_obs = obsutils.get_onoff_obs(self, obs, nthreads=1)
515 models = new_obs.models()
518 if self[
'fix_bkg'].boolean():
520 if model.classname() !=
'GModelSky':
525 new_obs.models(models)
531 self._log_header3(gammalib.EXPLICIT,
'Fitting the data')
534 like = ctools.ctlike(obs)
535 like[
'edisp'] = self[
'edisp'].boolean()
540 if like.obs().logL() == 0.0:
543 self._log_value(gammalib.TERSE,
'Warning',
544 'No event in this time bin, skip bin.')
548 result[
'values'][par] = 0.0
549 result[
'values'][
'e_'+par] = 0.0
558 result[
'values'][par] = source[par].value()
559 result[
'values'][
'e_'+par] = source[par].error()
564 result[
'ul_diff'] = ul_diff
565 result[
'ul_flux'] = ul_flux
566 result[
'ul_eflux'] = ul_eflux
569 if self[
'calc_ts'].boolean():
570 result[
'ts'] = source.ts()
573 self._log.header3(
'Results')
576 value = source[par].value()
577 error = source[par].error()
578 unit = source[par].unit()
579 self._log_value(gammalib.NORMAL, par,
580 str(value)+
' +/- '+str(error)+
' '+unit)
582 self._log_value(gammalib.NORMAL,
'Upper flux limit',
583 str(result[
'ul_diff'])+
' ph/cm2/s/MeV')
584 self._log_value(gammalib.NORMAL,
'Upper flux limit',
585 str(result[
'ul_flux'])+
' ph/cm2/s')
586 self._log_value(gammalib.NORMAL,
'Upper flux limit',
587 str(result[
'ul_eflux'])+
' erg/cm2/s')
588 if self[
'calc_ts'].boolean():
589 self._log_value(gammalib.NORMAL,
'Test Statistic', result[
'ts'])
594 self._log_value(gammalib.TERSE,
'Warning',
595 'No observations available in this time bin, '
600 result[
'values'][par] = 0.0
601 result[
'values'][
'e_' + par] = 0.0
616 self._log_observations(gammalib.NORMAL, self.obs(),
'Observation')
619 tmin = self._tbins.tstart(0)
620 tmax = self._tbins.tstop(self._tbins.size()-1)
623 select = ctools.ctselect(self.obs())
624 select[
'emin'] = self[
'emin'].real()
625 select[
'emax'] = self[
'emax'].real()
626 select[
'tmin'] = tmin
627 select[
'tmax'] = tmax
628 select[
'rad'] =
'UNDEFINED'
629 select[
'ra'] =
'UNDEFINED'
630 select[
'dec'] =
'UNDEFINED'
634 self.obs(select.obs().copy())
637 self._log_header1(gammalib.TERSE,
638 gammalib.number(
'Selected observation',
645 self._log_header1(gammalib.TERSE,
'Generate lightcurve')
651 args = [(self,
'_timebin', i)
652 for i
in range(self._tbins.size())]
653 poolresults = mputils.process(self.
_nthreads, mputils.mpfunc, args)
657 for i
in range(self._tbins.size()):
658 results.append(poolresults[i][0])
659 self._log_string(gammalib.TERSE, poolresults[i][1][
'log'],
False)
664 for i
in range(self._tbins.size()):
671 self.
_fits = gammalib.GFits()
672 self._fits.append(table)
675 self._stamp(self.
_fits)
678 if self[
'publish'].boolean():
689 self._log_header1(gammalib.TERSE,
'Save light curve')
692 if self[
'outfile'].is_valid():
695 outfile = self[
'outfile'].filename()
698 self._log_value(gammalib.NORMAL,
'Light curve file', outfile.url())
701 self._fits.saveto(outfile, self._clobber())
716 self._log_header1(gammalib.TERSE,
'Publish light curve')
719 if self._fits.contains(
'LIGHTCURVE'):
723 user_name = self._name()
728 self._log_value(gammalib.NORMAL,
'Light curve name', user_name)
731 self._fits.publish(
'LIGHTCURVE', user_name)
738 Return light curve FITS file
742 fits : `~gammalib.GFits()`
743 FITS file containing light curve
754 models : `~gammalib.GModels()`
765 Return and optionally set the exclusion regions map
769 object : `~gammalib.GSkyRegion` or `~gammalib.GSkyMap` or `~gammalib.GFilename`
770 Exclusion regions object
774 region : `~gammalib.GSkyRegionMap`
775 Exclusion regions map
778 if object
is not None:
788 if __name__ ==
'__main__':