Commit 41c397c89510d1e413bbea3b148224ff1c67b9ca
1 parent
b0341d4a
Handle On/Off observations in cspull (#2260)
Showing
6 changed files
with
184 additions
and
124 deletions
ChangeLog
| 1 | -2017-10-22 | 1 | +2017-10-26 |
| 2 | 2 | ||
| 3 | * Version 1.5.0 released | 3 | * Version 1.5.0 released |
| 4 | ======================== | 4 | ======================== |
| 5 | 5 | ||
| 6 | + Handle On/Off observations by cspull (#2260) | ||
| 6 | Add "statistic" parameter to all likelihood tools and scripts (#2237) | 7 | Add "statistic" parameter to all likelihood tools and scripts (#2237) |
| 7 | Rename ctlike "stat" parameter to "statistic" (#2237) | 8 | Rename ctlike "stat" parameter to "statistic" (#2237) |
| 8 | Enable handling of On/Off observations in csspec (#2231) | 9 | Enable handling of On/Off observations in csspec (#2231) |
NEWS
| 1 | New Features and Important Changes in ctools 1.5.0 | 1 | New Features and Important Changes in ctools 1.5.0 |
| 2 | 2 | ||
| 3 | -21 October 2017 | 3 | +26 October 2017 |
| 4 | 4 | ||
| 5 | 5 | ||
| 6 | Introduction | 6 | Introduction |
| @@ -227,6 +227,10 @@ curve generation (#2237). | @@ -227,6 +227,10 @@ curve generation (#2237). | ||
| 227 | 227 | ||
| 228 | cspull - Generate pull distributions | 228 | cspull - Generate pull distributions |
| 229 | ------------------------------------ | 229 | ------------------------------------ |
| 230 | +The script now handles On/Off observation. The parameters "onsrc" and "onrad" | ||
| 231 | +were added to allow specifying the On region test source and On region radius | ||
| 232 | +(#2260). | ||
| 233 | + | ||
| 230 | The script now derived from the csobservation base class. A "statistic" | 234 | The script now derived from the csobservation base class. A "statistic" |
| 231 | parameter was added to allow setting the optimizer statistic for the pull | 235 | parameter was added to allow setting the optimizer statistic for the pull |
| 232 | distribution generation (#2237). | 236 | distribution generation (#2237). |
cscripts/cspull.par
| @@ -18,6 +18,8 @@ | @@ -18,6 +18,8 @@ | ||
| 18 | #============================ | 18 | #============================ |
| 19 | inobs, f, h, NONE,,, "Input event list, counts cube, or observation definition XML file" | 19 | inobs, f, h, NONE,,, "Input event list, counts cube, or observation definition XML file" |
| 20 | inmodel, f, a, $CTOOLS/share/models/crab.xml,,, "Input model definition XML file" | 20 | inmodel, f, a, $CTOOLS/share/models/crab.xml,,, "Input model definition XML file" |
| 21 | +onsrc, s, a, ,,, "Name of On source (only for On/Off analysis)" | ||
| 22 | +onrad, r, a, 0.2,,, "Radius of On region (deg)" | ||
| 21 | caldb, s, a, prod2,,, "Calibration database" | 23 | caldb, s, a, prod2,,, "Calibration database" |
| 22 | irf, s, a, South_0.5h,,, "Instrument response function" | 24 | irf, s, a, South_0.5h,,, "Instrument response function" |
| 23 | edisp, b, h, no,,, "Apply energy dispersion?" | 25 | edisp, b, h, no,,, "Apply energy dispersion?" |
cscripts/cspull.py
| @@ -40,18 +40,6 @@ class cspull(ctools.csobservation): | @@ -40,18 +40,6 @@ class cspull(ctools.csobservation): | ||
| 40 | # Initialise application by calling the appropriate class constructor | 40 | # Initialise application by calling the appropriate class constructor |
| 41 | self._init_csobservation(self.__class__.__name__, ctools.__version__, argv) | 41 | self._init_csobservation(self.__class__.__name__, ctools.__version__, argv) |
| 42 | 42 | ||
| 43 | - # Initialise some members | ||
| 44 | - self._edisp = False | ||
| 45 | - self._coordsys = 'CEL' | ||
| 46 | - self._proj = 'TAN' | ||
| 47 | - self._log_clients = False # Static parameter | ||
| 48 | - self._ntrials = 0 | ||
| 49 | - self._npix = 0 | ||
| 50 | - self._binsz = 0.0 | ||
| 51 | - self._enumbins = 0 | ||
| 52 | - self._seed = 1 | ||
| 53 | - self._chatter = 2 | ||
| 54 | - | ||
| 55 | # Return | 43 | # Return |
| 56 | return | 44 | return |
| 57 | 45 | ||
| @@ -62,7 +50,7 @@ class cspull(ctools.csobservation): | @@ -62,7 +50,7 @@ class cspull(ctools.csobservation): | ||
| 62 | Get parameters from parfile | 50 | Get parameters from parfile |
| 63 | """ | 51 | """ |
| 64 | # If there are no observations in container then get some ... | 52 | # If there are no observations in container then get some ... |
| 65 | - if self.obs().size() == 0: | 53 | + if self.obs().is_empty(): |
| 66 | self.obs(self._get_observations()) | 54 | self.obs(self._get_observations()) |
| 67 | 55 | ||
| 68 | # ... otherwise add response information and energy boundaries | 56 | # ... otherwise add response information and energy boundaries |
| @@ -73,25 +61,26 @@ class cspull(ctools.csobservation): | @@ -73,25 +61,26 @@ class cspull(ctools.csobservation): | ||
| 73 | # Set observation statistic | 61 | # Set observation statistic |
| 74 | self._set_obs_statistic(gammalib.toupper(self['statistic'].string())) | 62 | self._set_obs_statistic(gammalib.toupper(self['statistic'].string())) |
| 75 | 63 | ||
| 76 | - # Get number of energy bins | ||
| 77 | - self._enumbins = self['enumbins'].integer() | 64 | + # Query parameters for On/Off observation |
| 65 | + if len(self['onsrc'].string()) > 0: | ||
| 66 | + self['onrad'].real() | ||
| 78 | 67 | ||
| 79 | - # Read parameters for binned if requested | ||
| 80 | - if self._enumbins != 0: | ||
| 81 | - self._npix = self['npix'].integer() | ||
| 82 | - self._binsz = self['binsz'].real() | ||
| 83 | - self._coordsys = self['coordsys'].string() | ||
| 84 | - self._proj = self['proj'].string() | 68 | + # Query parameters for binned if requested |
| 69 | + elif self['enumbins'].integer() > 0: | ||
| 70 | + self['npix'].integer() | ||
| 71 | + self['binsz'].real() | ||
| 72 | + self['coordsys'].string() | ||
| 73 | + self['proj'].string() | ||
| 85 | 74 | ||
| 86 | # Set models if we have none | 75 | # Set models if we have none |
| 87 | - if self.obs().models().size() == 0: | 76 | + if self.obs().models().is_empty(): |
| 88 | self.obs().models(self['inmodel'].filename()) | 77 | self.obs().models(self['inmodel'].filename()) |
| 89 | 78 | ||
| 90 | - # Read other parameters | ||
| 91 | - self._ntrials = self['ntrials'].integer() | ||
| 92 | - self._edisp = self['edisp'].boolean() | ||
| 93 | - self._seed = self['seed'].integer() | ||
| 94 | - self._chatter = self['chatter'].integer() | 79 | + # Query other parameters |
| 80 | + self['ntrials'].integer() | ||
| 81 | + self['edisp'].boolean() | ||
| 82 | + self['seed'].integer() | ||
| 83 | + self['chatter'].integer() | ||
| 95 | 84 | ||
| 96 | # Query some parameters | 85 | # Query some parameters |
| 97 | self['outfile'].filename() | 86 | self['outfile'].filename() |
| @@ -118,14 +107,19 @@ class cspull(ctools.csobservation): | @@ -118,14 +107,19 @@ class cspull(ctools.csobservation): | ||
| 118 | Summary string | 107 | Summary string |
| 119 | """ | 108 | """ |
| 120 | # Extract information from observation | 109 | # Extract information from observation |
| 121 | - emin = obs.events().ebounds().emin().TeV() | ||
| 122 | - emax = obs.events().ebounds().emax().TeV() | ||
| 123 | - events = obs.events().number() | ||
| 124 | - binned = (obs.events().classname() == 'GCTAEventCube') | ||
| 125 | - if binned: | ||
| 126 | - mode = 'binned' | 110 | + if obs.classname() == 'GCTAOnOffObservation': |
| 111 | + emin = obs.on_spec().ebounds().emin().TeV() | ||
| 112 | + emax = obs.on_spec().ebounds().emin().TeV() | ||
| 113 | + mode = 'On/Off' | ||
| 127 | else: | 114 | else: |
| 128 | - mode = 'unbinned' | 115 | + emin = obs.events().ebounds().emin().TeV() |
| 116 | + emax = obs.events().ebounds().emax().TeV() | ||
| 117 | + binned = (obs.events().classname() == 'GCTAEventCube') | ||
| 118 | + if binned: | ||
| 119 | + mode = 'binned' | ||
| 120 | + else: | ||
| 121 | + mode = 'unbinned' | ||
| 122 | + events = obs.nobserved() | ||
| 129 | 123 | ||
| 130 | # Compose summary string | 124 | # Compose summary string |
| 131 | if events > 0: | 125 | if events > 0: |
| @@ -151,38 +145,55 @@ class cspull(ctools.csobservation): | @@ -151,38 +145,55 @@ class cspull(ctools.csobservation): | ||
| 151 | Dictionary of results | 145 | Dictionary of results |
| 152 | """ | 146 | """ |
| 153 | # Write header | 147 | # Write header |
| 154 | - if self._logNormal(): | ||
| 155 | - self._log.header2('Trial '+str(seed-self._seed+1)) | ||
| 156 | - | ||
| 157 | - # If we have a binned obeservation then specify the lower and | ||
| 158 | - # upper energy limit in TeV | ||
| 159 | - if self._enumbins > 0: | ||
| 160 | - emin = self['emin'].real() | ||
| 161 | - emax = self['emax'].real() | 148 | + self._log_header2(gammalib.NORMAL, 'Trial %d' % |
| 149 | + (seed-self['seed'].integer()+1)) | ||
| 150 | + | ||
| 151 | + # Get number of energy bins and On source name and initialise | ||
| 152 | + # some parameters | ||
| 153 | + nbins = self['enumbins'].integer() | ||
| 154 | + onsrc = self['onsrc'].string() | ||
| 155 | + emin = None | ||
| 156 | + emax = None | ||
| 157 | + binsz = 0.0 | ||
| 158 | + npix = 0 | ||
| 159 | + proj = 'TAN' | ||
| 160 | + coordsys = 'CEL' | ||
| 161 | + | ||
| 162 | + # If we have a On source name then set On region radius | ||
| 163 | + if len(onsrc) > 0: | ||
| 164 | + onrad = self['onrad'].real() | ||
| 165 | + emin = self['emin'].real() | ||
| 166 | + emax = self['emax'].real() | ||
| 162 | else: | 167 | else: |
| 163 | - emin = None | ||
| 164 | - emax = None | 168 | + |
| 169 | + # Reset On region source name and radius | ||
| 170 | + onrad = 0.0 | ||
| 171 | + onsrc = None | ||
| 172 | + | ||
| 173 | + # If we have a binned obeservation then specify the lower and | ||
| 174 | + # upper energy limit in TeV | ||
| 175 | + if nbins > 0: | ||
| 176 | + emin = self['emin'].real() | ||
| 177 | + emax = self['emax'].real() | ||
| 178 | + binsz = self['binsz'].real() | ||
| 179 | + npix = self['npix'].integer() | ||
| 180 | + proj = self['proj'].string() | ||
| 181 | + coordsys = self['coordsys'].string() | ||
| 165 | 182 | ||
| 166 | # Simulate events | 183 | # Simulate events |
| 167 | obs = obsutils.sim(self.obs(), | 184 | obs = obsutils.sim(self.obs(), |
| 168 | - emin=emin, | ||
| 169 | - emax=emax, | ||
| 170 | - nbins=self._enumbins, | ||
| 171 | - addbounds=True, | ||
| 172 | - seed=seed, | ||
| 173 | - binsz=self._binsz, | ||
| 174 | - npix=self._npix, | ||
| 175 | - proj=self._proj, | ||
| 176 | - coord=self._coordsys, | ||
| 177 | - edisp=self._edisp, | ||
| 178 | - log=self._log_clients, | ||
| 179 | - debug=self._logDebug(), | ||
| 180 | - chatter=self._chatter) | 185 | + emin=emin, emax=emax, nbins=nbins, |
| 186 | + onsrc=onsrc, onrad=onrad, | ||
| 187 | + addbounds=True, seed=seed, | ||
| 188 | + binsz=binsz, npix=npix, proj=proj, coord=coordsys, | ||
| 189 | + edisp=self['edisp'].boolean(), | ||
| 190 | + log=False, debug=self._logDebug(), | ||
| 191 | + chatter=self['chatter'].integer()) | ||
| 181 | 192 | ||
| 182 | # Determine number of events in simulation | 193 | # Determine number of events in simulation |
| 183 | nevents = 0.0 | 194 | nevents = 0.0 |
| 184 | for run in obs: | 195 | for run in obs: |
| 185 | - nevents += run.events().number() | 196 | + nevents += run.nobserved() |
| 186 | 197 | ||
| 187 | # Write simulation results | 198 | # Write simulation results |
| 188 | self._log_header3(gammalib.NORMAL, 'Simulation') | 199 | self._log_header3(gammalib.NORMAL, 'Simulation') |
| @@ -200,15 +211,15 @@ class cspull(ctools.csobservation): | @@ -200,15 +211,15 @@ class cspull(ctools.csobservation): | ||
| 200 | for model in models: | 211 | for model in models: |
| 201 | like = ctools.cterror(obs) | 212 | like = ctools.cterror(obs) |
| 202 | like['srcname'] = model.name() | 213 | like['srcname'] = model.name() |
| 203 | - like['edisp'] = self._edisp | 214 | + like['edisp'] = self['edisp'].boolean() |
| 204 | like['debug'] = self._logDebug() | 215 | like['debug'] = self._logDebug() |
| 205 | - like['chatter'] = self._chatter | 216 | + like['chatter'] = self['chatter'].integer() |
| 206 | like.run() | 217 | like.run() |
| 207 | else: | 218 | else: |
| 208 | like = ctools.ctlike(obs) | 219 | like = ctools.ctlike(obs) |
| 209 | - like['edisp'] = self._edisp | 220 | + like['edisp'] = self['edisp'].boolean() |
| 210 | like['debug'] = self._logDebug() | 221 | like['debug'] = self._logDebug() |
| 211 | - like['chatter'] = self._chatter | 222 | + like['chatter'] = self['chatter'].integer() |
| 212 | like.run() | 223 | like.run() |
| 213 | 224 | ||
| 214 | # Store results | 225 | # Store results |
| @@ -217,8 +228,7 @@ class cspull(ctools.csobservation): | @@ -217,8 +228,7 @@ class cspull(ctools.csobservation): | ||
| 217 | models = like.obs().models() | 228 | models = like.obs().models() |
| 218 | 229 | ||
| 219 | # Write result header | 230 | # Write result header |
| 220 | - if self._logNormal(): | ||
| 221 | - self._log.header3('Pulls') | 231 | + self._log_header3(gammalib.NORMAL, 'Pulls') |
| 222 | 232 | ||
| 223 | # Gather results in form of a list of result columns and a | 233 | # Gather results in form of a list of result columns and a |
| 224 | # dictionary containing the results. The result contains the | 234 | # dictionary containing the results. The result contains the |
| @@ -294,10 +304,10 @@ class cspull(ctools.csobservation): | @@ -294,10 +304,10 @@ class cspull(ctools.csobservation): | ||
| 294 | self._log_header1(gammalib.TERSE, 'Generate pull distribution') | 304 | self._log_header1(gammalib.TERSE, 'Generate pull distribution') |
| 295 | 305 | ||
| 296 | # Loop over trials | 306 | # Loop over trials |
| 297 | - for seed in range(self._ntrials): | 307 | + for seed in range(self['ntrials'].integer()): |
| 298 | 308 | ||
| 299 | # Make a trial and add initial seed | 309 | # Make a trial and add initial seed |
| 300 | - result = self._trial(seed + self._seed) | 310 | + result = self._trial(seed + self['seed'].integer()) |
| 301 | 311 | ||
| 302 | # Write out trial result | 312 | # Write out trial result |
| 303 | ioutils.write_csv_row(self['outfile'].filename().url(), seed, | 313 | ioutils.write_csv_row(self['outfile'].filename().url(), seed, |
cscripts/obsutils.py
| @@ -20,13 +20,14 @@ | @@ -20,13 +20,14 @@ | ||
| 20 | import math | 20 | import math |
| 21 | import gammalib | 21 | import gammalib |
| 22 | import ctools | 22 | import ctools |
| 23 | +import cscripts | ||
| 23 | 24 | ||
| 24 | 25 | ||
| 25 | # ===================== # | 26 | # ===================== # |
| 26 | # Simulate observations # | 27 | # Simulate observations # |
| 27 | # ===================== # | 28 | # ===================== # |
| 28 | def sim(obs, log=False, debug=False, chatter=2, edisp=False, seed=0, | 29 | def sim(obs, log=False, debug=False, chatter=2, edisp=False, seed=0, |
| 29 | - emin=None, emax=None, nbins=0, addbounds=False, | 30 | + emin=None, emax=None, nbins=0, onsrc=None, onrad=0.2, addbounds=False, |
| 30 | binsz=0.05, npix=200, proj='TAN', coord='GAL'): | 31 | binsz=0.05, npix=200, proj='TAN', coord='GAL'): |
| 31 | """ | 32 | """ |
| 32 | Simulate events for all observations in the container | 33 | Simulate events for all observations in the container |
| @@ -59,6 +60,10 @@ def sim(obs, log=False, debug=False, chatter=2, edisp=False, seed=0, | @@ -59,6 +60,10 @@ def sim(obs, log=False, debug=False, chatter=2, edisp=False, seed=0, | ||
| 59 | Maximum energy of counts cube for binned (TeV) | 60 | Maximum energy of counts cube for binned (TeV) |
| 60 | nbins : int, optional | 61 | nbins : int, optional |
| 61 | Number of energy bins (0=unbinned) | 62 | Number of energy bins (0=unbinned) |
| 63 | + onsrc : str, optional | ||
| 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) | ||
| 62 | addbounds : bool, optional | 67 | addbounds : bool, optional |
| 63 | Add boundaries at observation energies | 68 | Add boundaries at observation energies |
| 64 | binsz : float, optional | 69 | binsz : float, optional |
| @@ -105,61 +110,97 @@ def sim(obs, log=False, debug=False, chatter=2, edisp=False, seed=0, | @@ -105,61 +110,97 @@ def sim(obs, log=False, debug=False, chatter=2, edisp=False, seed=0, | ||
| 105 | emin = min(run.events().ebounds().emin().TeV(), emin) | 110 | emin = min(run.events().ebounds().emin().TeV(), emin) |
| 106 | emax = max(run.events().ebounds().emax().TeV(), emax) | 111 | emax = max(run.events().ebounds().emax().TeV(), emax) |
| 107 | 112 | ||
| 108 | - # Allocate ctbin application and set parameters | ||
| 109 | - binning = ctools.ctbin(obssim.obs()) | ||
| 110 | - binning['ebinalg'] = 'LOG' | ||
| 111 | - binning['emin'] = emin | ||
| 112 | - binning['emax'] = emax | ||
| 113 | - binning['enumbins'] = nbins | ||
| 114 | - binning['usepnt'] = True # Use pointing for map centre | ||
| 115 | - binning['nxpix'] = npix | ||
| 116 | - binning['nypix'] = npix | ||
| 117 | - binning['binsz'] = binsz | ||
| 118 | - binning['coordsys'] = coord | ||
| 119 | - binning['proj'] = proj | ||
| 120 | - binning['chatter'] = chatter | ||
| 121 | - binning['debug'] = debug | ||
| 122 | - | ||
| 123 | - # Optionally open the log file | ||
| 124 | - if log: | ||
| 125 | - binning.logFileOpen() | ||
| 126 | - | ||
| 127 | - # Run ctbin application. This will loop over all observations in | ||
| 128 | - # the container and bin the events in counts maps | ||
| 129 | - binning.run() | ||
| 130 | - | ||
| 131 | - # If we have multiple input observations then create stacked response | ||
| 132 | - # cubes and append them to the observation | ||
| 133 | - if len(obssim.obs()) > 1: | ||
| 134 | - | ||
| 135 | - # Get stacked response (use pointing for map centre) | ||
| 136 | - response = get_stacked_response(obssim.obs(), None, None, | ||
| 137 | - binsz=binsz, nxpix=npix, nypix=npix, | ||
| 138 | - emin=emin, emax=emax, enumbins=nbins, | ||
| 139 | - edisp=edisp, | ||
| 140 | - coordsys=coord, proj=proj, | ||
| 141 | - addbounds=addbounds, | ||
| 142 | - log=log, debug=debug, | ||
| 143 | - chatter=chatter) | ||
| 144 | - | ||
| 145 | - # Set stacked response | ||
| 146 | - if edisp: | ||
| 147 | - binning.obs()[0].response(response['expcube'], | ||
| 148 | - response['psfcube'], | ||
| 149 | - response['edispcube'], | ||
| 150 | - response['bkgcube']) | ||
| 151 | - else: | ||
| 152 | - binning.obs()[0].response(response['expcube'], | ||
| 153 | - response['psfcube'], | ||
| 154 | - response['bkgcube']) | ||
| 155 | - | ||
| 156 | - # Set new models | ||
| 157 | - binning.obs().models(response['models']) | ||
| 158 | - | ||
| 159 | - # Make a deep copy of the observation that will be returned | ||
| 160 | - # (the ctbin object will go out of scope one the function is | ||
| 161 | - # left) | ||
| 162 | - obs = binning.obs().copy() | 113 | + # If a On source is specified then create On/Off observations |
| 114 | + if onsrc != None: | ||
| 115 | + | ||
| 116 | + # Extract source position from model | ||
| 117 | + model = obssim.obs().models()[onsrc] | ||
| 118 | + ra = model['RA'].value() | ||
| 119 | + dec = model['DEC'].value() | ||
| 120 | + | ||
| 121 | + # Allocate csphagen application and set parameters | ||
| 122 | + phagen = cscripts.csphagen(obssim.obs()) | ||
| 123 | + phagen['ebinalg'] = 'LOG' | ||
| 124 | + phagen['emin'] = emin | ||
| 125 | + phagen['emax'] = emax | ||
| 126 | + phagen['enumbins'] = nbins | ||
| 127 | + phagen['coordsys'] = 'CEL' | ||
| 128 | + phagen['ra'] = ra | ||
| 129 | + phagen['dec'] = dec | ||
| 130 | + phagen['rad'] = onrad | ||
| 131 | + phagen['stack'] = False | ||
| 132 | + phagen['inexclusion'] = 'NONE' | ||
| 133 | + | ||
| 134 | + # Optionally open the log file | ||
| 135 | + if log: | ||
| 136 | + phagen.logFileOpen() | ||
| 137 | + | ||
| 138 | + # Run csphagen application | ||
| 139 | + phagen.run() | ||
| 140 | + | ||
| 141 | + # Make a deep copy of the observation that will be returned | ||
| 142 | + # (the csphagen object will go out of scope one the function is | ||
| 143 | + # left) | ||
| 144 | + obs = phagen.obs().copy() | ||
| 145 | + | ||
| 146 | + # ... otherwise use binned observations | ||
| 147 | + else: | ||
| 148 | + | ||
| 149 | + # Allocate ctbin application and set parameters | ||
| 150 | + binning = ctools.ctbin(obssim.obs()) | ||
| 151 | + binning['ebinalg'] = 'LOG' | ||
| 152 | + binning['emin'] = emin | ||
| 153 | + binning['emax'] = emax | ||
| 154 | + binning['enumbins'] = nbins | ||
| 155 | + binning['usepnt'] = True # Use pointing for map centre | ||
| 156 | + binning['nxpix'] = npix | ||
| 157 | + binning['nypix'] = npix | ||
| 158 | + binning['binsz'] = binsz | ||
| 159 | + binning['coordsys'] = coord | ||
| 160 | + binning['proj'] = proj | ||
| 161 | + binning['chatter'] = chatter | ||
| 162 | + binning['debug'] = debug | ||
| 163 | + | ||
| 164 | + # Optionally open the log file | ||
| 165 | + if log: | ||
| 166 | + binning.logFileOpen() | ||
| 167 | + | ||
| 168 | + # Run ctbin application. This will loop over all observations in | ||
| 169 | + # the container and bin the events in counts maps | ||
| 170 | + binning.run() | ||
| 171 | + | ||
| 172 | + # If we have multiple input observations then create stacked response | ||
| 173 | + # cubes and append them to the observation | ||
| 174 | + if len(obssim.obs()) > 1: | ||
| 175 | + | ||
| 176 | + # Get stacked response (use pointing for map centre) | ||
| 177 | + response = get_stacked_response(obssim.obs(), None, None, | ||
| 178 | + binsz=binsz, nxpix=npix, nypix=npix, | ||
| 179 | + emin=emin, emax=emax, enumbins=nbins, | ||
| 180 | + edisp=edisp, | ||
| 181 | + coordsys=coord, proj=proj, | ||
| 182 | + addbounds=addbounds, | ||
| 183 | + log=log, debug=debug, | ||
| 184 | + chatter=chatter) | ||
| 185 | + | ||
| 186 | + # Set stacked response | ||
| 187 | + if edisp: | ||
| 188 | + binning.obs()[0].response(response['expcube'], | ||
| 189 | + response['psfcube'], | ||
| 190 | + response['edispcube'], | ||
| 191 | + response['bkgcube']) | ||
| 192 | + else: | ||
| 193 | + binning.obs()[0].response(response['expcube'], | ||
| 194 | + response['psfcube'], | ||
| 195 | + response['bkgcube']) | ||
| 196 | + | ||
| 197 | + # Set new models | ||
| 198 | + binning.obs().models(response['models']) | ||
| 199 | + | ||
| 200 | + # Make a deep copy of the observation that will be returned | ||
| 201 | + # (the ctbin object will go out of scope one the function is | ||
| 202 | + # left) | ||
| 203 | + obs = binning.obs().copy() | ||
| 163 | 204 | ||
| 164 | else: | 205 | else: |
| 165 | 206 |
doc/source/admin/release_history/1.5.rst
| @@ -23,6 +23,8 @@ Bug fixes | @@ -23,6 +23,8 @@ Bug fixes | ||
| 23 | Improvements | 23 | Improvements |
| 24 | ------------ | 24 | ------------ |
| 25 | 25 | ||
| 26 | +* [`2260 <https://cta-redmine.irap.omp.eu/issues/2260>`_] - | ||
| 27 | + Handle On/Off observations by :ref:`cspull` | ||
| 26 | * [`2237 <https://cta-redmine.irap.omp.eu/issues/2237>`_] - | 28 | * [`2237 <https://cta-redmine.irap.omp.eu/issues/2237>`_] - |
| 27 | Add ``statistic`` parameters to :ref:`ctbutterfly`, :ref:`cterror`, | 29 | Add ``statistic`` parameters to :ref:`ctbutterfly`, :ref:`cterror`, |
| 28 | :ref:`cttsmap`, :ref:`ctulimit`, :ref:`cslightcrv, :ref:`csphasecrv`, | 30 | :ref:`cttsmap`, :ref:`ctulimit`, :ref:`cslightcrv, :ref:`csphasecrv`, |