Commit d3460e5348315adf731b12cce4014f1a0a4f9f07
1 parent
7fc76690
Prefit models without test source in comlixmap (#4201)
Showing
5 changed files
with
114 additions
and
7 deletions
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 | ... | ... |
NEWS
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
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 | ... | ... |