29def sim(obs, log=False, debug=False, chatter=2, edisp=False, seed=0,
30 emin=None, emax=None, nbins=0, onsrc=None, onrad=0.2, addbounds=False,
31 binsz=0.05, npix=200, proj='TAN', coord='GAL', nthreads=0):
33 Simulate events for all observations in the container
35 Simulate events for all observations using ctobssim. If the number of
36 energy bins is positive, the events are binned into a counts cube using
37 ctbin. If multiple observations are simulated, the counts cube is a
38 stacked cube and the corresponding response cubes are computed using
39 ctexpcube, ctpsfcube, ctbkgcube and optionally ctedispcube. The response
40 cubes are attached to the first observation in the container, which
41 normally is the observation with the counts cube.
45 obs : `~gammalib.GObservations`
46 Observation container without events
49 debug : bool, optional
51 chatter : int, optional
53 edisp : bool, optional
54 Apply energy dispersion?
56 Seed value for simulations
57 emin : float, optional
58 Minimum energy of counts cube for binned (TeV)
59 emax : float, optional
60 Maximum energy of counts cube for binned (TeV)
62 Number of energy bins (0=unbinned)
64 Name of source for On region (None if no On/Off obs. is used)
65 onrad : float, optional
66 Radius for On region (deg)
67 addbounds : bool, optional
68 Add boundaries at observation energies
69 binsz : float, optional
70 Pixel size for binned simulation (deg/pixel)
72 Number of pixels in X and Y for binned simulation
74 Projection for binned simulation
76 Coordinate system for binned simulation
77 nthreads : str, optional
78 Number of parallel processes for On/Off spectra computation (0=all available CPUs)
82 obs : `~gammalib.GObservations`
83 Observation container filled with simulated events
86 obssim = ctools.ctobssim(obs)
88 obssim[
'edisp'] = edisp
89 obssim[
'nthreads'] = nthreads
90 obssim[
'chatter'] = chatter
91 obssim[
'debug'] = debug
109 if emin ==
None or emax ==
None:
112 for run
in obssim.obs():
113 emin = min(run.events().ebounds().emin().TeV(), emin)
114 emax = max(run.events().ebounds().emax().TeV(), emax)
120 model = obssim.obs().models()[onsrc]
121 ra = model[
'RA'].value()
122 dec = model[
'DEC'].value()
126 phagen[
'inmodel'] =
'NONE'
127 phagen[
'srcname'] = onsrc
128 phagen[
'ebinalg'] =
'LOG'
129 phagen[
'emin'] = emin
130 phagen[
'emax'] = emax
131 phagen[
'enumbins'] = nbins
132 phagen[
'srcshape'] =
'CIRCLE'
133 phagen[
'coordsys'] =
'CEL'
136 phagen[
'rad'] = onrad
137 phagen[
'stack'] =
False
138 phagen[
'inexclusion'] =
'NONE'
139 phagen[
'bkgmethod'] =
'REFLECTED'
140 phagen[
'nthreads'] = nthreads
152 obs = phagen.obs().copy()
158 binning = ctools.ctbin(obssim.obs())
159 binning[
'ebinalg'] =
'LOG'
160 binning[
'emin'] = emin
161 binning[
'emax'] = emax
162 binning[
'enumbins'] = nbins
163 binning[
'usepnt'] =
True
164 binning[
'nxpix'] = npix
165 binning[
'nypix'] = npix
166 binning[
'binsz'] = binsz
167 binning[
'coordsys'] = coord
168 binning[
'proj'] = proj
169 binning[
'nthreads'] = nthreads
170 binning[
'chatter'] = chatter
171 binning[
'debug'] = debug
175 binning.logFileOpen()
183 if len(obssim.obs()) > 1:
187 cntcube = binning.cube()
193 log=log, debug=debug,
198 binning.obs()[0].response(response[
'expcube'],
200 response[
'edispcube'],
203 binning.obs()[0].response(response[
'expcube'],
208 binning.obs().models(response[
'models'])
213 obs = binning.obs().copy()
220 obs = obssim.obs().copy()
232def set_obs(pntdir, tstart=0.0, duration=1800.0, deadc=0.98, \
233 emin=0.1, emax=100.0, rad=5.0, \
234 instrument='CTA', irf='South_50h', caldb='prod2', \
235 obsid='000000', mjdref=51544.5):
237 Set a single CTA observation
239 The function sets a single CTA observation containing an empty CTA
240 event list. By looping over this function CTA observations can be
241 added to the observation container.
245 pntdir : `~gammalib.GSkyDir`
247 tstart : float, optional
249 duration : float, optional
250 Duration of observation (s)
251 deadc : float, optional
252 Deadtime correction factor
253 emin : float, optional
254 Minimum event energy (TeV)
255 emax : float, optional
256 Maximum event energy (TeV)
257 rad : float, optional
258 ROI radius used for analysis (deg)
259 instrument : str, optional
260 Name of Cherenkov Telescope
262 Instrument response function
263 caldb : str, optional
264 Calibration database path
265 obsid : str, optional
266 Observation identifier
270 obs : `~gammalib.GCTAObservation`
274 obs = gammalib.GCTAObservation()
277 mission = gammalib.toupper(instrument)
278 obs.instrument(mission)
281 db = gammalib.GCaldb()
282 if (gammalib.dir_exists(caldb)):
285 db.open(mission, caldb)
288 pnt = gammalib.GCTAPointing()
293 roi = gammalib.GCTARoi()
294 instdir = gammalib.GCTAInstDir()
300 ref = gammalib.GTimeReference(mjdref,
's',
'TT',
'LOCAL')
301 gti = gammalib.GGti(ref)
302 gti.append(gammalib.GTime(tstart, ref),
303 gammalib.GTime(tstart+duration, ref))
306 ebounds = gammalib.GEbounds(gammalib.GEnergy(emin,
'TeV'),
307 gammalib.GEnergy(emax,
'TeV'))
310 events = gammalib.GCTAEventList()
315 events.ebounds(ebounds)
321 obs.response(irf, db)
325 obs.livetime(duration*deadc)
337 emin=0.1, emax=100.0, rad=5.0, \
338 irf='South_50h', caldb='prod2'):
340 Returns an observation container filled with a list of CTA observations
342 The list is defined by the obsdeflist parameter which is a dictionnary
343 containing the mandatory keywords 'ra' and 'dec' that specify the
344 pointing direction for a given observation. Optional keyword give control
345 over other observation proposerties, such as duration, deadtime correction,
346 energy range, etc. If an optional keyword is not specified, the function
347 keyword is used instead.
351 obsdeflist : list of dict
352 Observation definition list
353 tstart : float, optional
355 duration : float, optional
356 Duration of observation (s)
357 deadc : float, optional
358 Deadtime correction factor
359 emin : float, optional
360 Minimum event energy (TeV)
361 emax : float, optional
362 Maximum event energy (TeV)
363 rad : float, optional
364 ROI radius used for analysis (deg)
366 Instrument response function
367 caldb : str, optional
368 Calibration database path
372 obs : `~gammalib.GObservations`
373 Observation container filled with CTA observation
376 obs = gammalib.GObservations()
383 for obsdef
in obsdeflist:
386 pntdir = gammalib.GSkyDir()
387 pntdir.radec_deg(obsdef[
'ra'], obsdef[
'dec'])
390 obsid =
'%6.6d' % obs_id
395 duration=obsdef.setdefault(
'duration', duration),
396 deadc=obsdef.setdefault(
'deadc', deadc),
397 emin=obsdef.setdefault(
'emin', emin),
398 emax=obsdef.setdefault(
'emax', emax),
399 rad=obsdef.setdefault(
'rad', rad),
400 irf=obsdef.setdefault(
'irf', irf),
401 caldb=obsdef.setdefault(
'caldb', caldb),
408 obs_start += duration
420 Sets a number of standard patterns
425 Observation pattern ("single", "four")
427 Right Ascension of pattern centre (deg)
428 dec : float, optional
429 Declination of pattern centre (deg)
430 offset : float, optional
431 Offset from pattern centre (deg)
436 Observation definition list
443 if pattern ==
'single':
444 obsdef = {
'ra': ra,
'dec': dec}
445 obsdeflist.append(obsdef)
450 elif pattern ==
'four':
453 centre = gammalib.GSkyDir()
454 centre.radec_deg(ra, dec)
457 for phi
in [0.0, 90.0, 180.0, 270.0]:
458 pntdir = centre.copy()
459 pntdir.rotate_deg(phi, offset)
460 obsdeflist.append({
'ra': pntdir.ra_deg(),
'dec': pntdir.dec_deg()})
464 msg =
'Observation pattern "%s" not recognized.' % (pattern)
465 raise RuntimeError(msg)
475 deadc=0.98, pattern='single', offset=1.5):
477 Set an observation container filled with CTA observations
482 Right Ascension of pattern centre (deg)
484 Declination of pattern centre (deg)
486 ROI radius used for analysis (deg)
488 Start time of observation (s)
490 Duration of each observation (s)
491 emin : float, optional
492 Minimum event energy (TeV)
493 emax : float, optional
494 Maximum event energy (TeV)
496 Instrument response function
498 Calibration database path
499 deadc : float, optional
500 Deadtime correction factor
501 pattern : str, optional
502 Observation pattern ("single", "four")
503 offset : float, optional
504 Offset from pattern centre (deg)
508 obs : `~gammalib.GObservations()
509 Observation container
515 obs =
set_obs_list(obsdeflist, tstart=tstart, duration=duration,
516 emin=emin, emax=emax, rad=rad, irf=irf, caldb=caldb,
527 log=False, debug=False, chatter=2):
529 Get stacked response cubes
531 The number of energies bins are set to at least 30 bins per decade, unless
532 the counts cube has more energy bins per decade.
536 obs : `~gammalib.GObservations`
537 Observation container
538 cntcube : `~gammalib.GCTAEventCube`
540 edisp : bool, optional
541 Apply energy dispersion?
542 addbounds : bool, optional
543 Add boundaries at observation energies
546 debug : bool, optional
548 chatter : int, optional
554 Dictionary of response cubes
557 xref = cntcube.counts().projection().crval(0)
558 yref = cntcube.counts().projection().crval(1)
559 binsz = cntcube.counts().projection().cdelt(1)
560 coordsys = cntcube.counts().projection().coordsys()
561 proj = cntcube.counts().projection().code()
564 emin = cntcube.emin().TeV()
565 emax = cntcube.emax().TeV()
566 ebins = cntcube.ebins()
569 if coordsys ==
'EQU':
579 enumbins = int((math.log10(emax) - math.log10(emin)) * 30.0)
586 psf_binsz = 10.0 * binsz
587 psf_nxpix = max(nxpix // 10, 2)
588 psf_nypix = max(nypix // 10, 2)
591 expcube = ctools.ctexpcube(obs)
592 expcube[
'incube'] =
'NONE'
593 expcube[
'ebinalg'] =
'LOG'
594 expcube[
'xref'] = xref
595 expcube[
'yref'] = yref
596 expcube[
'binsz'] = binsz
597 expcube[
'nxpix'] = nxpix
598 expcube[
'nypix'] = nypix
599 expcube[
'enumbins'] = enumbins
600 expcube[
'emin'] = emin
601 expcube[
'emax'] = emax
602 expcube[
'coordsys'] = coordsys
603 expcube[
'proj'] = proj
604 expcube[
'addbounds'] = addbounds
605 expcube[
'debug'] = debug
606 expcube[
'chatter'] = chatter
608 expcube.logFileOpen()
612 psfcube = ctools.ctpsfcube(obs)
613 psfcube[
'incube'] =
'NONE'
614 psfcube[
'ebinalg'] =
'LOG'
615 psfcube[
'xref'] = xref
616 psfcube[
'yref'] = yref
617 psfcube[
'binsz'] = psf_binsz
618 psfcube[
'nxpix'] = psf_nxpix
619 psfcube[
'nypix'] = psf_nypix
620 psfcube[
'enumbins'] = enumbins
621 psfcube[
'emin'] = emin
622 psfcube[
'emax'] = emax
623 psfcube[
'coordsys'] = coordsys
624 psfcube[
'proj'] = proj
625 psfcube[
'addbounds'] = addbounds
626 psfcube[
'debug'] = debug
627 psfcube[
'chatter'] = chatter
629 psfcube.logFileOpen()
635 bkgcube = ctools.ctbkgcube(obs)
636 bkgcube.cntcube(cntcube)
637 bkgcube[
'debug'] = debug
638 bkgcube[
'chatter'] = chatter
640 bkgcube.logFileOpen()
645 edispcube = ctools.ctedispcube(obs)
646 edispcube[
'incube'] =
'NONE'
647 edispcube[
'ebinalg'] =
'LOG'
648 edispcube[
'xref'] = xref
649 edispcube[
'yref'] = yref
650 edispcube[
'binsz'] = psf_binsz
651 edispcube[
'nxpix'] = psf_nxpix
652 edispcube[
'nypix'] = psf_nypix
653 edispcube[
'enumbins'] = enumbins
654 edispcube[
'emin'] = emin
655 edispcube[
'emax'] = emax
656 edispcube[
'coordsys'] = coordsys
657 edispcube[
'proj'] = proj
658 edispcube[
'addbounds'] = addbounds
659 edispcube[
'debug'] = debug
660 edispcube[
'chatter'] = chatter
662 edispcube.logFileOpen()
667 response[
'expcube'] = expcube.expcube().copy()
668 response[
'psfcube'] = psfcube.psfcube().copy()
669 response[
'bkgcube'] = bkgcube.bkgcube().copy()
670 response[
'models'] = bkgcube.models().copy()
672 response[
'edispcube'] = edispcube.edispcube().copy()
683 Bin an observation and return an observation container with a single
688 cls : `~ctools.cscript`
690 obs : `~gammalib.GObservations`
691 Observation container
692 nthreads : str, optional
693 Number of parallel processes for On/Off spectra computation (0=all available CPUs)
697 obs : `~gammalib.GObservations`
698 Observation container where the first observation is a binned observation
701 if cls._logExplicit():
702 cls._log.header3(
'Binning events')
705 cntcube = ctools.ctbin(obs)
706 cntcube[
'usepnt'] =
False
707 cntcube[
'ebinalg'] =
'LOG'
708 cntcube[
'xref'] = cls[
'xref'].real()
709 cntcube[
'yref'] = cls[
'yref'].real()
710 cntcube[
'binsz'] = cls[
'binsz'].real()
711 cntcube[
'nxpix'] = cls[
'nxpix'].integer()
712 cntcube[
'nypix'] = cls[
'nypix'].integer()
713 cntcube[
'enumbins'] = cls[
'enumbins'].integer()
714 cntcube[
'emin'] = cls[
'emin'].real()
715 cntcube[
'emax'] = cls[
'emax'].real()
716 cntcube[
'coordsys'] = cls[
'coordsys'].string()
717 cntcube[
'proj'] = cls[
'proj'].string()
718 cntcube[
'nthreads'] = nthreads
723 cube = cntcube.cube()
726 if cls._logExplicit():
727 cls._log.header3(
'Creating stacked response')
733 new_obs = cntcube.obs().copy()
736 if cls[
'edisp'].boolean():
737 new_obs[0].response(response[
'expcube'], response[
'psfcube'],
738 response[
'edispcube'], response[
'bkgcube'])
740 new_obs[0].response(response[
'expcube'], response[
'psfcube'],
744 models = response[
'models']
747 new_obs.models(models)
756def get_onoff_obs(cls, obs, nthreads=0, ra = None, dec = None, srcname = ''):
758 Create On/Off observations container from given observations
762 cls : `~ctools.cscript`
764 obs : `~gammalib.GObservations`
765 Observation container
766 nthreads : str, optional
767 Number of parallel processes for On/Off spectra computation (0=all available CPUs)
769 R.A. of source region centre
770 dec : float, optional
771 Dec. of source region centre
772 srcname : str, optional
777 onoff_obs : `~gammalib.GObservations`
778 Observation container with On/Off observations
781 if cls._logExplicit():
782 cls._log.header3(
'Creating On/Off observations')
789 if cls.has_par(
'inmodel')
and obs.models().size() == 0:
790 if cls[
'inmodel'].is_valid():
791 inmodel = cls[
'inmodel'].value()
792 if srcname ==
'' and cls.has_par(
'srcname'):
793 srcname = cls[
'srcname'].value()
794 if cls.has_par(
'use_model_bkg'):
795 use_model_bkg = cls[
'use_model_bkg'].boolean()
799 phagen[
'inmodel'] = inmodel
800 phagen[
'srcname'] = srcname
801 phagen[
'emin'] = cls[
'emin'].real()
802 phagen[
'emax'] = cls[
'emax'].real()
803 phagen[
'enumbins'] = cls[
'enumbins'].integer()
804 phagen[
'ebinalg'] =
'LOG'
805 phagen[
'srcshape'] = cls[
'srcshape'].string()
807 if ra !=
None and dec !=
None:
808 phagen[
'coordsys'] =
'CEL'
813 phagen[
'coordsys'] = cls[
'coordsys'].string()
814 if cls[
'coordsys'].string() ==
'CEL':
815 phagen[
'ra'] = cls[
'xref'].real()
816 phagen[
'dec'] = cls[
'yref'].real()
817 elif cls[
'coordsys'].string() ==
'GAL':
818 phagen[
'glon'] = cls[
'xref'].real()
819 phagen[
'glat'] = cls[
'yref'].real()
820 if cls[
'srcshape'].string() ==
'CIRCLE':
821 phagen[
'rad'] = cls[
'rad'].real()
822 elif cls[
'srcshape'].string() ==
'RECT':
823 phagen[
'width'] = cls[
'width'].real()
824 phagen[
'height'] = cls[
'height'].real()
825 phagen[
'posang'] = cls[
'posang'].real()
826 phagen[
'bkgmethod'] = cls[
'bkgmethod'].string()
827 if cls[
'bkgmethod'].string() ==
'REFLECTED':
828 phagen[
'bkgregmin'] = cls[
'bkgregmin'].integer()
829 phagen[
'use_model_bkg'] = use_model_bkg
830 phagen[
'maxoffset'] = cls[
'maxoffset'].real()
831 phagen[
'stack'] =
True
832 phagen[
'etruemin'] = cls[
'etruemin'].real()
833 phagen[
'etruemax'] = cls[
'etruemax'].real()
834 phagen[
'etruebins'] = cls[
'etruebins'].integer()
835 phagen[
'chatter'] = cls[
'chatter'].integer()
836 phagen[
'clobber'] = cls[
'clobber'].boolean()
837 phagen[
'debug'] = cls[
'debug'].boolean()
838 phagen[
'nthreads'] = nthreads
844 use_inexclusion =
False
846 if hasattr(cls,
'exclusion_map'):
847 exclusion_map = cls.exclusion_map()
848 if exclusion_map
is not None:
852 phagen.exclusion_map(exclusion_map)
856 if cls.has_par(
'inexclusion'):
858 if cls[
'inexclusion'].is_valid():
860 use_inexclusion =
True
862 inexclusion = cls[
'inexclusion'].value()
863 phagen[
'inexclusion'] = inexclusion
866 if not use_excl_map
and not use_inexclusion:
868 phagen[
'inexclusion'] =
'NONE'
874 onoff_obs = phagen.obs().copy()
878 if cls[
'statistic'].string() !=
'DEFAULT':
879 for observation
in onoff_obs:
880 observation.statistic(cls[
'statistic'].string())
891 Calculate residuals given counts and models, according to algorithm
894 Can handle GSkyMap or GNdarray objects
899 cls : `~ctools.cscript`
901 counts : `~gammalib.GSkyMap/~gammalib.GNdarray'
903 model : `~gammalib.GSkyMap/~gammalib.GNdarray'
908 residuals : `~gammalib.GSkyMap/~gammalib.GNdarray'
912 if counts.classname() ==
'GNdarray':
913 nelem = counts.size()
914 elif counts.classname() ==
'GSkyMap':
915 nelem = counts.npix()
917 msg =
'cscripts.obsutils.residuals only handles ' \
918 +
'gammalib.GNdarray or gammalib.GSkyMap objects.\n'
919 raise RuntimeError(msg)
922 residuals = counts.copy()
925 algorithm = cls[
'algorithm'].string()
928 if algorithm ==
'SUB':
932 elif algorithm ==
'SUBDIV':
937 elif algorithm ==
'SUBDIVSQRT':
939 residuals /= model.sqrt()
942 elif algorithm ==
'SIGNIFICANCE':
945 sign = (residuals - model).sign()
948 for i
in range(nelem):
956 data_val = residuals[i]
958 log_val = math.log(data_val / model_val)
959 residuals[i] = (data_val * log_val) + model_val - data_val
960 if residuals[i] < 0.0:
966 residuals[i] = model_val
974 residuals = residuals.sqrt()
979 raise TypeError(
'Algorithm "' + algorithm +
'" not known')
990 Create counts cube from observations
994 cls : `~ctools.cscript`
996 obs : `~gammalib.GObservations`
997 Observation container
1001 cntcube : `~gammalib.GCTAEventCube`
1005 ctbin = ctools.ctbin(obs)
1008 ctbin[
'xref'] = cls[
'xref'].real()
1009 ctbin[
'yref'] = cls[
'yref'].real()
1010 ctbin[
'proj'] = cls[
'proj'].string()
1011 ctbin[
'coordsys'] = cls[
'coordsys'].string()
1012 ctbin[
'ebinalg'] = cls[
'ebinalg'].string()
1013 ctbin[
'nxpix'] = cls[
'nxpix'].integer()
1014 ctbin[
'nypix'] = cls[
'nypix'].integer()
1015 ctbin[
'binsz'] = cls[
'binsz'].real()
1016 if cls[
'ebinalg'].string() ==
'FILE':
1017 ctbin[
'ebinfile'] = cls[
'ebinfile'].filename().file()
1019 ctbin[
'enumbins'] = cls[
'enumbins'].integer()
1020 ctbin[
'emin'] = cls[
'emin'].real()
1021 ctbin[
'emax'] = cls[
'emax'].real()
1022 if cls[
'ebinalg'].string() ==
'POW':
1023 ctbin[
'ebingamma'] = cls[
'ebingamma'].real()
1024 ctbin[
'chatter'] = cls[
'chatter'].integer()
1025 ctbin[
'clobber'] = cls[
'clobber'].boolean()
1026 ctbin[
'debug'] = cls[
'debug'].boolean()
const GCTAEventCube & cube(const int &index=0) const
Return event cube at index.
set_obs_patterns(pattern, ra=83.6331, dec=22.0145, offset=1.5)
set_obs(pntdir, tstart=0.0, duration=1800.0, deadc=0.98, emin=0.1, emax=100.0, rad=5.0, instrument='CTA', irf='South_50h', caldb='prod2', obsid='000000', mjdref=51544.5)
set_observations(ra, dec, rad, tstart, duration, emin, emax, irf, caldb, deadc=0.98, pattern='single', offset=1.5)
residuals(cls, counts, model)
create_counts_cube(cls, obs)
get_stacked_response(obs, cntcube, edisp=False, addbounds=False, log=False, debug=False, chatter=2)
sim(obs, log=False, debug=False, chatter=2, edisp=False, seed=0, emin=None, emax=None, nbins=0, onsrc=None, onrad=0.2, addbounds=False, binsz=0.05, npix=200, proj='TAN', coord='GAL', nthreads=0)
get_onoff_obs(cls, obs, nthreads=0, ra=None, dec=None, srcname='')
get_stacked_obs(cls, obs, nthreads=0)
set_obs_list(obsdeflist, tstart=0.0, duration=1800.0, deadc=0.98, emin=0.1, emax=100.0, rad=5.0, irf='South_50h', caldb='prod2')