Commit d3460e5348315adf731b12cce4014f1a0a4f9f07

Authored by Jürgen Knödlseder
1 parent 7fc76690

Prefit models without test source in comlixmap (#4201)

ChangeLog
1   -2023-01-05
  1 +2023-01-18
2 2  
3 3 * Version 2.1.0 released
4 4 ========================
5 5  
  6 + Prefit models without test source in comlixmap (#4201)
6 7 Add inmap parameter to comlixmap (#4187)
7 8 Add comobsconv script (#4159)
8 9 Optionally write fitted null hypothesis model in cttsmap
... ...
1 1 New Features and Important Changes in ctools 2.1.0
2 2  
3   -5 January 2023
  3 +18 January 2023
4 4  
5 5  
6 6 Introduction
... ... @@ -331,6 +331,10 @@ None
331 331  
332 332 comlixmap - Generation of COMPTEL Test Statistic map using SRCLIX algorithm
333 333 ---------------------------------------------------------------------------
  334 +The script prefits now the models without test source before entering the TS
  335 +map computation. This may lead to a speed-up as fewer SRCLIX iterations will
  336 +be needed for each test source position (#4201).
  337 +
334 338 Added an "inmap" parameter to allow restart the computations from an existing
335 339 TS map without recomputation of values that exist. The script now also writes
336 340 parameter uncertainties in the resulting TS map FITS file (#4187).
... ...
README.md
1 1 ctools information
2 2 ==================
3   -* Version: 2.1.0.dev (5 January 2023)
  3 +* Version: 2.1.0.dev (18 January 2023)
4 4 * GammaLib dependency: 2.1.0.dev
5 5  
6 6 [![Build Status](https://cta-jenkins.irap.omp.eu/buildStatus/icon?job=ctools-integrate-os)](https://cta-jenkins.irap.omp.eu/job/ctools-integrate-os/)
... ...
doc/source/admin/release_history/2.1.rst
... ... @@ -28,6 +28,9 @@ Bug fixes
28 28 Improvements
29 29 ------------
30 30  
  31 +* [`4201 <https://cta-redmine.irap.omp.eu/issues/4201>`_] -
  32 + Prefit models without test source in :ref:`comlixmap`
  33 +
31 34  
32 35 New features
33 36 ------------
... ...
modules/comscripts/comlixmap.py
... ... @@ -2,7 +2,7 @@
2 2 # ==========================================================================
3 3 # Create SRCLIX TS map
4 4 #
5   -# Copyright (C) 2021-2022 Juergen Knoedlseder
  5 +# Copyright (C) 2021-2023 Juergen Knoedlseder
6 6 #
7 7 # This program is free software: you can redistribute it and/or modify
8 8 # it under the terms of the GNU General Public License as published by
... ... @@ -215,6 +215,79 @@ class comlixmap(ctools.cslikelihood):
215 215 # Return
216 216 return
217 217  
  218 + def _prefit_models(self):
  219 + """
  220 + Prefits models
  221 +
  222 + The method prefits models to the data.
  223 + """
  224 + # Get parameters and initialise some variables
  225 + niter = self['max_iter'].integer()
  226 + eps = self['like_accuracy'].real()
  227 + delta = 0.0
  228 +
  229 + # Loop over iterations
  230 + for iter in range(niter):
  231 +
  232 + # Update observations
  233 + self._update_obs()
  234 +
  235 + # If first iteration then initialise best observation
  236 + if iter == 0:
  237 + best_obs = self.obs().copy()
  238 +
  239 + # Fit model
  240 + self.obs().optimize(self.opt())
  241 +
  242 + # Compute log-likelihood difference or initialise
  243 + # log-likelihood value
  244 + if iter > 0:
  245 + delta = logL - self.opt().value()
  246 + else:
  247 + logL = self.opt().value()
  248 +
  249 + # If log-likelihood improved then update best observations and
  250 + # last log-likelihood value
  251 + if delta >= 0.0:
  252 + best_obs = self.obs().copy()
  253 + logL = self.opt().value()
  254 +
  255 + # Log maximum likelihood
  256 + if iter == 0:
  257 + result = '%.5f' % (self.opt().value())
  258 + else:
  259 + result = '%.5f (%.5f)' % (self.opt().value(), delta)
  260 + self._log_value(gammalib.NORMAL, 'logL after iteration %d' % (iter+1),
  261 + result)
  262 +
  263 + # Check for convergence
  264 + if iter > 0:
  265 + if delta < eps:
  266 + break
  267 +
  268 + # Use best observations for maximum likelihood fitting. This avoids
  269 + # that observations that have a worse log-likelihood than the best
  270 + # value are used for final model fitting.
  271 + self.obs(best_obs)
  272 +
  273 + # Compute log-likelihood and TS for best observations
  274 + value, opt = self._final_model_fit()
  275 +
  276 + # Compute log-likelihood difference
  277 + delta = logL - value
  278 +
  279 + # Log final maximum likelihood
  280 + result = '%.5f (%.5f)' % (value, delta)
  281 + self._log_value(gammalib.NORMAL, 'logL after final iteration',
  282 + result)
  283 +
  284 + # Log optimiser
  285 + self._log_string(gammalib.NORMAL, str(opt))
  286 +
  287 + # Return
  288 + return
  289 +
  290 +
218 291 def _create_maps(self):
219 292 """
220 293 Create sky maps based on user parameters
... ... @@ -357,7 +430,7 @@ class comlixmap(ctools.cslikelihood):
357 430 self.obs(best_obs)
358 431  
359 432 # Compute log-likelihood and TS for best observations
360   - value = self._final_model_fit()
  433 + value, _ = self._final_model_fit()
361 434  
362 435 # Compute log-likelihood difference
363 436 delta = logL - value
... ... @@ -456,6 +529,8 @@ class comlixmap(ctools.cslikelihood):
456 529 -------
457 530 logL : float
458 531 Log-likelihood of final model fit
  532 + opt : `~gammalib.GOptimizer`
  533 + Optimizer
459 534 """
460 535 # Create instance of model fitting tool
461 536 like = ctools.ctlike(self.obs())
... ... @@ -467,8 +542,8 @@ class comlixmap(ctools.cslikelihood):
467 542 # Recover results
468 543 self.obs(like.obs())
469 544  
470   - # Return log-likelihood value
471   - return (like.opt().value())
  545 + # Return log-likelihood value and optimiser
  546 + return (like.opt().value(), like.opt().copy())
472 547  
473 548  
474 549 # Public methods
... ... @@ -506,6 +581,30 @@ class comlixmap(ctools.cslikelihood):
506 581 self._log_string(gammalib.NORMAL, str(self.obs().models()))
507 582  
508 583 # Log header
  584 + self._log_header1(gammalib.NORMAL, 'Prefit models without test source')
  585 +
  586 + # Store initial models
  587 + models_orig = self.obs().models().copy()
  588 +
  589 + # Remove test sources from models
  590 + models = self.obs().models().copy()
  591 + for srcname in self._srcnames:
  592 + models.remove(srcname)
  593 + self.obs().models(models)
  594 +
  595 + # Prefit models
  596 + self._prefit_models()
  597 +
  598 + # Log prefitted models
  599 + self._log_string(gammalib.NORMAL, str(self.obs().models()))
  600 +
  601 + # Append removed test sources to prefitted model
  602 + models = self.obs().models().copy()
  603 + for srcname in self._srcnames:
  604 + models.append(models_orig[srcname])
  605 + self.obs().models(models)
  606 +
  607 + # Log header
509 608 self._log_header1(gammalib.NORMAL, 'Initialise TS map')
510 609  
511 610 # Create sky maps
... ...