Commit cfa7379fa139515e72e707a703b2d574cc4794b7

Authored by Jürgen Knödlseder
1 parent 1e00ea3d

Increase ctool branch coverage (#1828)

src/cterror/cterror.cpp
... ... @@ -250,85 +250,80 @@ void cterror::run(void)
250 250 log_value(NORMAL, "Maximum log likelihood", gammalib::str(m_best_logL,3));
251 251 log_string(NORMAL, m_obs.models().print(m_chatter));
252 252  
253   - // Continue only if source model exists
254   - if (m_obs.models().contains(m_srcname)) {
  253 + // Save best fitting models
  254 + GModels models_best = m_obs.models();
255 255  
256   - // Save best fitting models
257   - GModels models_best = m_obs.models();
  256 + // Get pointer on model
  257 + GModel* model = models_best[m_srcname];
258 258  
259   - // Get pointer on model
260   - GModel* model = models_best[m_srcname];
  259 + // Get number of parameters
  260 + int npars = model->size();
261 261  
262   - // Get number of parameters
263   - int npars = model->size();
  262 + // Loop over parameters of sky model
  263 + for (int i = 0; i < npars; ++i) {
264 264  
265   - // Loop over parameters of sky model
266   - for (int i = 0; i < npars; ++i) {
267   -
268   - // Skip parameter if it is fixed
269   - if (model->at(i).is_fixed()) {
270   - continue;
271   - }
  265 + // Skip parameter if it is fixed
  266 + if (model->at(i).is_fixed()) {
  267 + continue;
  268 + }
272 269  
273   - // Initialise with best fitting models
274   - m_obs.models(models_best);
275   -
276   - // Get pointer on model parameter
277   - GModels& current_models = const_cast<GModels&>(m_obs.models());
278   - m_model_par = &(current_models[m_srcname]->at(i));
279   -
280   - // Extract current value
281   - m_value = m_model_par->factor_value();
282   -
283   - // Compute parameter bracketing
284   - double parmin = std::max(m_model_par->factor_min(),
285   - m_value - 10.0*m_model_par->factor_error());
286   - double parmax = std::min(m_model_par->factor_max(),
287   - m_value + 10.0*m_model_par->factor_error());
288   -
289   - // Write header and initial parameters into logger
290   - log_header1(TERSE, "Compute error for source \""+m_srcname+"\""
291   - " parameter \""+m_model_par->name()+"\"");
292   - log_value(NORMAL, "Confidence level",
293   - gammalib::str(m_confidence*100.0)+" %");
294   - log_value(NORMAL, "Log-likelihood difference", m_dlogL);
295   - log_value(NORMAL, "Initial factor range",
296   - "["+gammalib::str(parmin)+", "+gammalib::str(parmax)+"]");
297   -
298   - // Compute lower and upper boundaries
299   - double value_lo = error_bisection(parmin, m_value);
300   - double value_hi = error_bisection(m_value, parmax);
301   -
302   - // Compute errors
303   - double error = 0.5 * (value_hi - value_lo);
304   - double error_neg = m_value - value_lo;
305   - double error_pos = value_hi - m_value;
306   - double error_value = std::abs(error*m_model_par->scale());
307   - double error_value_neg = std::abs(error_neg*m_model_par->scale());
308   - double error_value_pos = std::abs(error_pos*m_model_par->scale());
309   -
310   - // Write results into logger
311   - std::string unit = " " + m_model_par->unit();
312   - log_value(NORMAL, "Lower parameter factor", value_lo);
313   - log_value(NORMAL, "Upper parameter factor", value_hi);
314   - log_value(NORMAL, "Error from curvature",
315   - gammalib::str(m_model_par->error()) + unit);
316   - log_value(NORMAL, "Error from profile",
317   - gammalib::str(error_value) + unit);
318   - log_value(NORMAL, "Negative profile error",
319   - gammalib::str(error_value_neg) + unit);
320   - log_value(NORMAL, "Positive profile error",
321   - gammalib::str(error_value_pos) + unit);
322   -
323   - // Save error result
324   - model->at(i).factor_error(error);
325   -
326   - } // endfor: looped over spectral parameters
327   -
328   - // Restore best fitting models (now with new errors computed)
  270 + // Initialise with best fitting models
329 271 m_obs.models(models_best);
330 272  
331   - } // endif: source model exists
  273 + // Get pointer on model parameter
  274 + GModels& current_models = const_cast<GModels&>(m_obs.models());
  275 + m_model_par = &(current_models[m_srcname]->at(i));
  276 +
  277 + // Extract current value
  278 + m_value = m_model_par->factor_value();
  279 +
  280 + // Compute parameter bracketing
  281 + double parmin = std::max(m_model_par->factor_min(),
  282 + m_value - 10.0*m_model_par->factor_error());
  283 + double parmax = std::min(m_model_par->factor_max(),
  284 + m_value + 10.0*m_model_par->factor_error());
  285 +
  286 + // Write header and initial parameters into logger
  287 + log_header1(TERSE, "Compute error for source \""+m_srcname+"\""
  288 + " parameter \""+m_model_par->name()+"\"");
  289 + log_value(NORMAL, "Confidence level",
  290 + gammalib::str(m_confidence*100.0)+" %");
  291 + log_value(NORMAL, "Log-likelihood difference", m_dlogL);
  292 + log_value(NORMAL, "Initial factor range",
  293 + "["+gammalib::str(parmin)+", "+gammalib::str(parmax)+"]");
  294 +
  295 + // Compute lower and upper boundaries
  296 + double value_lo = error_bisection(parmin, m_value);
  297 + double value_hi = error_bisection(m_value, parmax);
  298 +
  299 + // Compute errors
  300 + double error = 0.5 * (value_hi - value_lo);
  301 + double error_neg = m_value - value_lo;
  302 + double error_pos = value_hi - m_value;
  303 + double error_value = std::abs(error*m_model_par->scale());
  304 + double error_value_neg = std::abs(error_neg*m_model_par->scale());
  305 + double error_value_pos = std::abs(error_pos*m_model_par->scale());
  306 +
  307 + // Write results into logger
  308 + std::string unit = " " + m_model_par->unit();
  309 + log_value(NORMAL, "Lower parameter factor", value_lo);
  310 + log_value(NORMAL, "Upper parameter factor", value_hi);
  311 + log_value(NORMAL, "Error from curvature",
  312 + gammalib::str(m_model_par->error()) + unit);
  313 + log_value(NORMAL, "Error from profile",
  314 + gammalib::str(error_value) + unit);
  315 + log_value(NORMAL, "Negative profile error",
  316 + gammalib::str(error_value_neg) + unit);
  317 + log_value(NORMAL, "Positive profile error",
  318 + gammalib::str(error_value_pos) + unit);
  319 +
  320 + // Save error result
  321 + model->at(i).factor_error(error);
  322 +
  323 + } // endfor: looped over spectral parameters
  324 +
  325 + // Restore best fitting models (now with new errors computed)
  326 + m_obs.models(models_best);
332 327  
333 328 // Recover optimizer
334 329 m_opt = best_opt;
... ...
src/cterror/cterror.par
... ... @@ -35,7 +35,7 @@ outmodel, f, a, &quot;results.xml&quot;,,, &quot;Output model XML file&quot;
35 35 #=============================
36 36 confidence, r, h, 0.68,0.0,1.0, "Confidence level"
37 37 tol, r, h, 1e-3,,, "Computation tolerance"
38   -max_iter, i, h, 50,,, "Maximum number of iterations"
  38 +max_iter, i, h, 50,1,1000, "Maximum number of iterations"
39 39  
40 40 #
41 41 # Standard parameters
... ...
src/ctulimit/ctulimit.cpp
... ... @@ -228,17 +228,9 @@ void ctulimit::run(void)
228 228 // Get task parameters
229 229 get_parameters();
230 230  
231   - // Set energy dispersion flag for all CTA observations and save old
  231 + // Set energy dispersion flags of all CTA observations and save old
232 232 // values in save_edisp vector
233   - std::vector<bool> save_edisp;
234   - save_edisp.assign(m_obs.size(), false);
235   - for (int i = 0; i < m_obs.size(); ++i) {
236   - GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]);
237   - if (obs != NULL) {
238   - save_edisp[i] = obs->response()->apply_edisp();
239   - obs->response()->apply_edisp(m_apply_edisp);
240   - }
241   - }
  233 + std::vector<bool> save_edisp = set_edisp(m_obs, m_apply_edisp);
242 234  
243 235 // Write input observation container into logger
244 236 log_observations(NORMAL, m_obs, "Input observation");
... ... @@ -338,13 +330,8 @@ void ctulimit::run(void)
338 330 // Recover optimizer
339 331 m_opt = best_opt;
340 332  
341   - // Restore energy dispersion flag for all CTA observations
342   - for (int i = 0; i < m_obs.size(); ++i) {
343   - GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]);
344   - if (obs != NULL) {
345   - obs->response()->apply_edisp(save_edisp[i]);
346   - }
347   - }
  333 + // Restore energy dispersion flags of all CTA observations
  334 + restore_edisp(m_obs, save_edisp);
348 335  
349 336 // Return
350 337 return;
... ...
test/test_ctedispcube.py
... ... @@ -206,6 +206,7 @@ class Test(test):
206 206 edispcube['yref'] = 22.01
207 207 edispcube['migramax'] = 2.0
208 208 edispcube['migrabins'] = 10
  209 + edispcube['addbounds'] = True
209 210 edispcube['outcube'] = 'ctedispcube_py3.fits'
210 211 edispcube['logfile'] = 'ctedispcube_py3.log'
211 212 edispcube['chatter'] = 4
... ...
test/test_cterror.py
... ... @@ -161,6 +161,41 @@ class Test(test):
161 161 # Check that the cleared copy has also cleared the observations
162 162 self._check_obs(cpy_error.obs(), nobs=0, nmodels=0)
163 163  
  164 + # Prepare observation container with a single event list
  165 + obs = gammalib.GObservations()
  166 + obs.append(gammalib.GCTAObservation(self._events))
  167 + obs.models(gammalib.GModels(self._model))
  168 +
  169 + # Setup cterror tool from observation container
  170 + error = ctools.cterror(obs)
  171 + error['srcname'] = 'Crab'
  172 + error['caldb'] = self._caldb
  173 + error['irf'] = self._irf
  174 + error['outmodel'] = 'cterror_py3.xml'
  175 + error['logfile'] = 'cterror_py3.log'
  176 + error['chatter'] = 4
  177 +
  178 + # Execute cterror tool
  179 + error.logFileOpen() # Make sure we get a log file
  180 + error.execute()
  181 +
  182 + # Check result file
  183 + self._check_result_file('cterror_py3.xml')
  184 +
  185 + # And now a run with not enough iterations
  186 + error['max_iter'] = 1
  187 + error['outmodel'] = 'cterror_py4.xml'
  188 + error['logfile'] = 'cterror_py4.log'
  189 +
  190 + # Execute cterror tool and catch the exception
  191 + error.logFileOpen() # Make sure we get a log file
  192 + self.test_try('Test cterror with not enough iterations')
  193 + try:
  194 + error.execute()
  195 + self.test_try_failure('Exception not thrown')
  196 + except ValueError:
  197 + self.test_try_success()
  198 +
164 199 # Return
165 200 return
166 201  
... ...
test/test_ctlike.py
... ... @@ -160,6 +160,32 @@ class Test(test):
160 160 # Check that the cleared copy has also cleared the observations
161 161 self._check_obs(cpy_like.obs(), nobs=0, nmodels=0)
162 162  
  163 + # Prepare observation container with a single event list
  164 + obs = gammalib.GObservations()
  165 + obs.append(gammalib.GCTAObservation(self._events))
  166 +
  167 + # Prepare a special model to enforce TS computation
  168 + models = gammalib.GModels(self._model)
  169 + models['Crab'].tscalc(True)
  170 + obs.models(models)
  171 +
  172 + # Allocate ctlike tool from observation container
  173 + like = ctools.ctlike(obs)
  174 + like['caldb'] = self._caldb
  175 + like['irf'] = self._irf
  176 + like['refit'] = True
  177 + like['fix_spat_for_ts'] = True
  178 + like['outmodel'] = 'ctlike_py3.xml'
  179 + like['logfile'] = 'ctlike_py3.log'
  180 + like['chatter'] = 4
  181 +
  182 + # Execute ctlike
  183 + like.logFileOpen() # Needed to get a new log file
  184 + like.execute()
  185 +
  186 + # Check result file
  187 + self._check_result_file('ctlike_py3.xml')
  188 +
163 189 # Return
164 190 return
165 191  
... ...
test/test_ctmapcube.py
... ... @@ -177,6 +177,36 @@ class Test(test):
177 177 # Check that the cleared copy has also cleared the map cube
178 178 self._check_cube(cpy_mapcube.mapcube(), nmaps=0, npixels=0)
179 179  
  180 + # Allocate ctmapcube tools, set models and do now a linear
  181 + # binning; also do not use Gaussian point sources
  182 + mapcube = ctools.ctmapcube()
  183 + mapcube.models(gammalib.GModels(self._model))
  184 + mapcube['ebinalg'] = 'LIN'
  185 + mapcube['emin'] = 0.1
  186 + mapcube['emax'] = 100.0
  187 + mapcube['enumbins'] = 10
  188 + mapcube['nxpix'] = 100
  189 + mapcube['nypix'] = 100
  190 + mapcube['binsz'] = 0.04
  191 + mapcube['coordsys'] = 'CEL'
  192 + mapcube['proj'] = 'CAR'
  193 + mapcube['xref'] = 83.63
  194 + mapcube['yref'] = 22.01
  195 + mapcube['ptsrcsig'] = 0.0
  196 + mapcube['outcube'] = 'ctmapcube_py3.fits'
  197 + mapcube['logfile'] = 'ctmapcube_py3.log'
  198 + mapcube['chatter'] = 4
  199 +
  200 + # Execute mapcube
  201 + mapcube.logFileOpen() # Needed to get a new log file
  202 + mapcube.execute()
  203 +
  204 + # Check result file
  205 + self._check_result_file('ctmapcube_py3.fits')
  206 +
  207 + # Publish with a name
  208 + mapcube.publish('My map cube')
  209 +
180 210 # Return
181 211 return
182 212  
... ...
test/test_ctmodel.py
... ... @@ -189,11 +189,38 @@ class Test(test):
189 189 # Check that the cleared copy has also cleared the model cube
190 190 self._check_cube(cpy_model.cube(), nx=0, ny=0, nebins=0)
191 191  
  192 + # Get mixed observation container
  193 + obs = self._obs_mixed()
  194 +
  195 + # Setup ctmodel tool from observation container and get model cube
  196 + # definition from counts cube
  197 + model = ctools.ctmodel(obs)
  198 + model.models(gammalib.GModels(self._model))
  199 + model['incube'] = self._cntcube
  200 + model['expcube'] = 'NONE'
  201 + model['psfcube'] = 'NONE'
  202 + model['bkgcube'] = 'NONE'
  203 + model['caldb'] = self._caldb
  204 + model['irf'] = self._irf
  205 + model['outcube'] = 'ctmodel_py3.fits'
  206 + model['logfile'] = 'ctmodel_py3.log'
  207 + model['chatter'] = 4
  208 +
  209 + # Execute ctmodel tool
  210 + model.logFileOpen() # Needed to get a new log file
  211 + model.execute()
  212 +
  213 + # Check result file
  214 + self._check_result_file('ctmodel_py3.fits', nx=200, ny=200, nebins=20)
  215 +
  216 + # Publish with name
  217 + model.publish('My model')
  218 +
192 219 # Return
193 220 return
194 221  
195 222 # Check result file
196   - def _check_result_file(self, filename):
  223 + def _check_result_file(self, filename, nx=40, ny=40, nebins=10):
197 224 """
198 225 Check result file
199 226  
... ... @@ -201,12 +228,18 @@ class Test(test):
201 228 ----------
202 229 filename : str
203 230 Model cube file name
  231 + nx : int, optional
  232 + Number of pixels in X direction
  233 + ny : int, optional
  234 + Number of pixels in Y direction
  235 + nebins : int, optional
  236 + Number of energy bins
204 237 """
205 238 # Open result file
206 239 cube = gammalib.GCTAEventCube(filename)
207 240  
208 241 # Check cube
209   - self._check_cube(cube)
  242 + self._check_cube(cube, nx=nx, ny=ny, nebins=nebins)
210 243  
211 244 # Return
212 245 return
... ...
test/test_ctobssim.py
... ... @@ -154,6 +154,12 @@ class Test(test):
154 154 sim['logfile'] = 'ctobssim_py2.log'
155 155 sim['chatter'] = 3
156 156  
  157 + # Double maximum event range
  158 + max_rate = sim.max_rate()
  159 + sim.max_rate(2*max_rate)
  160 + self.test_value(sim.max_rate(), 2*max_rate, 1.0e-3,
  161 + 'Check setting of maximum event rate')
  162 +
157 163 # Run tool
158 164 sim.logFileOpen()
159 165 sim.run()
... ...
test/test_ctpsfcube.py
... ... @@ -187,27 +187,29 @@ class Test(test):
187 187 # Get mixed observation container
188 188 obs = self._obs_mixed()
189 189  
190   - # Set-up ctpsfcube from observation container
  190 + # Set-up ctpsfcube from observation container and input counts
  191 + # cube
191 192 psfcube = ctools.ctpsfcube(obs)
192   - psfcube['incube'] = 'NONE'
193   - psfcube['caldb'] = self._caldb
194   - psfcube['irf'] = self._irf
195   - psfcube['ebinalg'] = 'LOG'
196   - psfcube['emin'] = 0.1
197   - psfcube['emax'] = 100
198   - psfcube['enumbins'] = 20
199   - psfcube['nxpix'] = 10
200   - psfcube['nypix'] = 10
201   - psfcube['binsz'] = 0.4
202   - psfcube['coordsys'] = 'CEL'
203   - psfcube['proj'] = 'CAR'
204   - psfcube['xref'] = 83.63
205   - psfcube['yref'] = 22.01
206   - psfcube['amax'] = 0.3
207   - psfcube['anumbins'] = 10
208   - psfcube['outcube'] = 'ctpsfcube_py3.fits'
209   - psfcube['logfile'] = 'ctpsfcube_py3.log'
210   - psfcube['chatter'] = 4
  193 + psfcube['incube'] = self._cntcube
  194 + psfcube['caldb'] = self._caldb
  195 + psfcube['irf'] = self._irf
  196 + #psfcube['ebinalg'] = 'LOG'
  197 + #psfcube['emin'] = 0.1
  198 + #psfcube['emax'] = 100
  199 + #psfcube['enumbins'] = 20
  200 + #psfcube['nxpix'] = 10
  201 + #psfcube['nypix'] = 10
  202 + #psfcube['binsz'] = 0.4
  203 + #psfcube['coordsys'] = 'CEL'
  204 + #psfcube['proj'] = 'CAR'
  205 + #psfcube['xref'] = 83.63
  206 + #psfcube['yref'] = 22.01
  207 + psfcube['amax'] = 0.3
  208 + psfcube['anumbins'] = 10
  209 + psfcube['addbounds'] = True
  210 + psfcube['outcube'] = 'ctpsfcube_py3.fits'
  211 + psfcube['logfile'] = 'ctpsfcube_py3.log'
  212 + psfcube['chatter'] = 4
211 213  
212 214 # Execute ctpsfcube tool
213 215 psfcube.logFileOpen() # Make sure we get a log file
... ...
test/test_ctskymap.py
... ... @@ -18,6 +18,7 @@
18 18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 19 #
20 20 # ==========================================================================
  21 +import os
21 22 import gammalib
22 23 import ctools
23 24 from testing import test
... ... @@ -103,10 +104,25 @@ class Test(test):
103 104 """
104 105 Test ctskymap from Python
105 106 """
106   - # Set-up ctskymap
  107 + # Allocate ctskymap
107 108 skymap = ctools.ctskymap()
  109 +
  110 + # Check that empty ctskymap tool holds a map that has no pixels
  111 + self._check_map(skymap.map(), nx=0, ny=0)
  112 +
  113 + # Check that saving does not nothing
  114 + skymap['outmap'] = 'ctskymap_py0.fits'
  115 + skymap['logfile'] = 'ctskymap_py0.log'
  116 + skymap.logFileOpen()
  117 + skymap.save()
  118 + self.test_assert(not os.path.isfile('ctskymap_py0.fits'),
  119 + 'Check that no sky map has been created')
  120 +
  121 + # Check that clearing does not lead to an exception or segfault
  122 + skymap.clear()
  123 +
  124 + # Now set ctskymap parameters
108 125 skymap['inobs'] = self._events
109   - skymap['outmap'] = 'ctskymap_py1.fits'
110 126 skymap['emin'] = 0.1
111 127 skymap['emax'] = 100
112 128 skymap['nxpix'] = 200
... ... @@ -116,6 +132,7 @@ class Test(test):
116 132 skymap['proj'] = 'CAR'
117 133 skymap['xref'] = 83.63
118 134 skymap['yref'] = 22.01
  135 + skymap['outmap'] = 'ctskymap_py1.fits'
119 136 skymap['logfile'] = 'ctskymap_py1.log'
120 137 skymap['chatter'] = 2
121 138  
... ... @@ -127,21 +144,111 @@ class Test(test):
127 144 # Check result file
128 145 self._check_result_file('ctskymap_py1.fits')
129 146  
  147 + # Copy ctskymap tool
  148 + cpy_skymap = skymap.copy()
  149 +
  150 + # Check sky map of ctskymap copy
  151 + self._check_map(cpy_skymap.map())
  152 +
  153 + # Execute copy of ctskymap tool again, now with a higher chatter
  154 + # level than before
  155 + cpy_skymap['usepnt'] = True
  156 + cpy_skymap['emin'] = 0.2
  157 + cpy_skymap['emax'] = 150.0
  158 + cpy_skymap['outmap'] = 'ctskymap_py2.fits'
  159 + cpy_skymap['logfile'] = 'ctskymap_py2.log'
  160 + cpy_skymap['publish'] = True
  161 + cpy_skymap['chatter'] = 3
  162 + cpy_skymap.logFileOpen() # Needed to get a new log file
  163 + cpy_skymap.execute()
  164 +
  165 + # Check result file
  166 + self._check_result_file('ctskymap_py2.fits')
  167 +
  168 + # Now clear copy of ctskymap tool
  169 + cpy_skymap.clear()
  170 +
  171 + # Check that cleared ctskymap tool holds a map that has no pixels
  172 + self._check_map(cpy_skymap.map(), nx=0, ny=0)
  173 +
  174 + # Get mixed observation container
  175 + obs = self._obs_mixed()
  176 +
  177 + # Allocate ctskymap tool from observation container
  178 + skymap = ctools.ctskymap(obs)
  179 + skymap['emin'] = 0.1
  180 + skymap['emax'] = 100
  181 + skymap['nxpix'] = 200
  182 + skymap['nypix'] = 200
  183 + skymap['binsz'] = 0.02
  184 + skymap['coordsys'] = 'CEL'
  185 + skymap['proj'] = 'CAR'
  186 + skymap['xref'] = 83.63
  187 + skymap['yref'] = 22.01
  188 + skymap['outmap'] = 'ctskymap_py3.fits'
  189 + skymap['logfile'] = 'ctskymap_py3.log'
  190 + skymap['chatter'] = 4
  191 +
  192 + # Execute tool
  193 + skymap.logFileOpen() # Needed to get a new log file
  194 + skymap.execute()
  195 +
  196 + # Check result file
  197 + self._check_result_file('ctskymap_py3.fits')
  198 +
  199 + # Publish with name
  200 + skymap.publish('My sky map')
  201 +
130 202 # Return
131 203 return
132 204  
133 205 # Check result file
134   - def _check_result_file(self, filename):
  206 + def _check_result_file(self, filename, nx=200, ny=200):
135 207 """
136 208 Check result file
  209 +
  210 + Parameters
  211 + ----------
  212 + filename : str
  213 + Sky map file name
  214 + nx : int, optional
  215 + Number of X pixels
  216 + ny : int, optional
  217 + Number of Y pixels
137 218 """
138 219 # Open result file
139   - result = gammalib.GSkyMap(filename)
  220 + skymap = gammalib.GSkyMap(filename)
140 221  
  222 + # Check sky map
  223 + self._check_map(skymap, nx=nx, ny=ny)
  224 +
  225 + # Return
  226 + return
  227 +
  228 + # Check sky map
  229 + def _check_map(self, skymap, nx=200, ny=200):
  230 + """
  231 + Check sky map
  232 +
  233 + Parameters
  234 + ----------
  235 + skymap : `~gammalib.GSkyMap`
  236 + Sky map
  237 + nx : int, optional
  238 + Number of X pixels
  239 + ny : int, optional
  240 + Number of Y pixels
  241 + """
  242 + # Determine number of maps
  243 + if nx > 0 and ny > 0:
  244 + nmaps = 1
  245 + else:
  246 + nmaps = 0
  247 +
141 248 # Check dimensions
142   - self.test_value(result.nmaps(), 1, 'Check for one map')
143   - self.test_value(result.nx(), 200, 'Check for 200 pixels in X')
144   - self.test_value(result.ny(), 200, 'Check for 200 pixels in Y')
  249 + self.test_value(skymap.nmaps(), nmaps, 'Check number of maps')
  250 + self.test_value(skymap.nx(), nx, 'Check for number of X pixels')
  251 + self.test_value(skymap.ny(), ny, 'Check for number of Y pixels')
145 252  
146 253 # Return
147 254 return
... ...
test/test_ctulimit.py
... ... @@ -99,7 +99,25 @@ class Test(test):
99 99 """
100 100 Test ctulimit from Python
101 101 """
102   - # Set-up ctulimit
  102 + # Allocate ctulimit
  103 + ulimit = ctools.ctulimit()
  104 +
  105 + # Check that empty ctulimit tool holds zero upper limits
  106 + self.test_value(ulimit.diff_ulimit(), 0.0, 1.0e-23,
  107 + 'Check differential upper limit')
  108 + self.test_value(ulimit.flux_ulimit(), 0.0, 1.0e-17,
  109 + 'Check upper limit on photon flux')
  110 + self.test_value(ulimit.eflux_ulimit(), 0.0, 1.0e-16,
  111 + 'Check upper limit on energy flux')
  112 +
  113 + # Check that saving does not nothing
  114 + ulimit.logFileOpen()
  115 + ulimit.save()
  116 +
  117 + # Check that clearing does not lead to an exception or segfault
  118 + ulimit.clear()
  119 +
  120 + # Now set ctulimit parameters
103 121 ulimit = ctools.ctulimit()
104 122 ulimit['inobs'] = self._events
105 123 ulimit['inmodel'] = self._model
... ... @@ -114,8 +132,50 @@ class Test(test):
114 132 ulimit.run()
115 133 ulimit.save()
116 134  
117   - # Check result file
118   - self._check_result_file('ctulimit_py1.log')
  135 + # Check results
  136 + self.test_value(ulimit.diff_ulimit(), 8.86803e-18, 1.0e-23,
  137 + 'Check differential upper limit')
  138 + self.test_value(ulimit.flux_ulimit(), 6.10509e-12, 1.0e-17,
  139 + 'Check upper limit on photon flux')
  140 + self.test_value(ulimit.eflux_ulimit(), 2.75669e-11, 1.0e-16,
  141 + 'Check upper limit on energy flux')
  142 +
  143 + # Copy ctulimit tool
  144 + cpy_ulimit = ulimit.copy()
  145 +
  146 + # Check results of copy
  147 + self.test_value(cpy_ulimit.diff_ulimit(), 8.86803e-18, 1.0e-23,
  148 + 'Check differential upper limit')
  149 + self.test_value(cpy_ulimit.flux_ulimit(), 6.10509e-12, 1.0e-17,
  150 + 'ulimit upper limit on photon flux')
  151 + self.test_value(cpy_ulimit.eflux_ulimit(), 2.75669e-11, 1.0e-16,
  152 + 'Check upper limit on energy flux')
  153 +
  154 + # Execute copy of ctulimit tool again, now with a higher chatter
  155 + # level than before
  156 + cpy_ulimit['logfile'] = 'ctulimit_py2.log'
  157 + cpy_ulimit['chatter'] = 3
  158 + cpy_ulimit.logFileOpen() # Needed to get a new log file
  159 + cpy_ulimit.execute()
  160 +
  161 + # Check results
  162 + self.test_value(cpy_ulimit.diff_ulimit(), 8.86803e-18, 1.0e-23,
  163 + 'Check differential upper limit')
  164 + self.test_value(cpy_ulimit.flux_ulimit(), 6.10509e-12, 1.0e-17,
  165 + 'ulimit upper limit on photon flux')
  166 + self.test_value(cpy_ulimit.eflux_ulimit(), 2.75669e-11, 1.0e-16,
  167 + 'Check upper limit on energy flux')
  168 +
  169 + # Now clear copy of ctulimit tool
  170 + cpy_ulimit.clear()
  171 +
  172 + # Check that empty ctulimit tool holds zero upper limits
  173 + self.test_value(cpy_ulimit.diff_ulimit(), 0.0, 1.0e-23,
  174 + 'Check differential upper limit')
  175 + self.test_value(cpy_ulimit.flux_ulimit(), 0.0, 1.0e-17,
  176 + 'Check upper limit on photon flux')
  177 + self.test_value(cpy_ulimit.eflux_ulimit(), 0.0, 1.0e-16,
  178 + 'Check upper limit on energy flux')
119 179  
120 180 # Return
121 181 return
... ...