Commit ca5c9a3639442bfb60b00fc48504190056b75040

Authored by Jürgen Knödlseder
1 parent fbba1ce7

Add hidden fix_ext_for_initial parameter

If the hidden fix_ext_for_initial parameter is set to yes the script will fix any spatial extension parameters for the initial fit iteration and then free the fixed parameters for any subsequent iterations. This stabilizes the fit for extended sources.
modules/comscripts/comlixfit.par
@@ -26,14 +26,15 @@ outmodel, f, a, results.xml,,, "Output model definition file" @@ -26,14 +26,15 @@ outmodel, f, a, results.xml,,, "Output model definition file"
26 # 26 #
27 # Script parameters 27 # Script parameters
28 #================== 28 #==================
29 -max_iter, i, h, 50,1,1000, "Maximum number of SRCLIX iterations"  
30 -like_accuracy, r, h, 0.05,1.0e-30,1.0, "Absolute accuracy of maximum likelihood value"  
31 -fix_spat_for_ts, b, h, no,,, "Fix spatial parameters for TS computation?"  
32 -bkgmethod, s, a, BGDLIXE,PHINOR|BGDLIXA|BGDLIXE,, "Method for background computation"  
33 -nrunav, i, h, 3,,, "Number of Chi/Psi bins used for running average"  
34 -navgr, i, h, 9,,, "Number of Chi/Psi bins used for averaging"  
35 -nincl, i, h, 5,,, "Number of Phibar layers to include"  
36 -nexcl, i, h, 0,,, "Number of Phibar layers to exclude" 29 +max_iter, i, h, 50,1,1000, "Maximum number of SRCLIX iterations"
  30 +like_accuracy, r, h, 0.05,1.0e-30,1.0, "Absolute accuracy of maximum likelihood value"
  31 +fix_spat_for_ts, b, h, no,,, "Fix spatial parameters for TS computation?"
  32 +fix_ext_for_initial, b, h, no,,, "Fix extension parameters for initial fit iteration?"
  33 +bkgmethod, s, a, BGDLIXE,PHINOR|BGDLIXA|BGDLIXE,, "Method for background computation"
  34 +nrunav, i, h, 3,,, "Number of Chi/Psi bins used for running average"
  35 +navgr, i, h, 5,,, "Number of Chi/Psi bins used for averaging"
  36 +nincl, i, h, 5,,, "Number of Phibar layers to include"
  37 +nexcl, i, h, 0,,, "Number of Phibar layers to exclude"
37 38
38 # 39 #
39 # Standard parameters 40 # Standard parameters
modules/comscripts/comlixfit.py
@@ -39,6 +39,9 @@ class comlixfit(ctools.cslikelihood): @@ -39,6 +39,9 @@ class comlixfit(ctools.cslikelihood):
39 # Initialise application by calling the base class constructor 39 # Initialise application by calling the base class constructor
40 self._init_cslikelihood(self.__class__.__name__, ctools.__version__, argv) 40 self._init_cslikelihood(self.__class__.__name__, ctools.__version__, argv)
41 41
  42 + # Initialise members
  43 + self._fixed_pars = []
  44 +
42 # Return 45 # Return
43 return 46 return
44 47
@@ -59,6 +62,7 @@ class comlixfit(ctools.cslikelihood): @@ -59,6 +62,7 @@ class comlixfit(ctools.cslikelihood):
59 self['max_iter'].integer() 62 self['max_iter'].integer()
60 self['like_accuracy'].real() 63 self['like_accuracy'].real()
61 self['fix_spat_for_ts'].boolean() 64 self['fix_spat_for_ts'].boolean()
  65 + self['fix_ext_for_initial'].boolean()
62 66
63 # Get parameters 67 # Get parameters
64 bkgmethod = self['bkgmethod'].string() 68 bkgmethod = self['bkgmethod'].string()
@@ -156,6 +160,65 @@ class comlixfit(ctools.cslikelihood): @@ -156,6 +160,65 @@ class comlixfit(ctools.cslikelihood):
156 # Return 160 # Return
157 return 161 return
158 162
  163 + def _fix_ext_pars(self):
  164 + """
  165 + Fix spatial extension parameters
  166 + """
  167 + # Initialise list of fixed parameters
  168 + self._fixed_pars = []
  169 +
  170 + # Set list of spatial extension parameters
  171 + pars = ['Radius', 'Width', 'Sigma', 'PA', 'MajorRadius', 'MinorRadius']
  172 +
  173 + # Loop over all sky models
  174 + for model in self.obs().models():
  175 + if model.classname() == 'GModelSky':
  176 +
  177 + # Loop over all parameters and fix all encountered spatial
  178 + # extension parameters
  179 + for par in pars:
  180 + if model.spatial().has_par(par):
  181 + if model[par].is_free():
  182 +
  183 + # Fix parameter
  184 + model[par].fix()
  185 +
  186 + # Bookkeeping fixed parameters
  187 + fixed = {'name': model.name(), 'par': par}
  188 + self._fixed_pars.append(fixed)
  189 +
  190 + # Log action
  191 + value = '%s[%s]' % (model.name(), par)
  192 + self._log_value(gammalib.EXPLICIT, 'Fixed parameter', value)
  193 +
  194 + # Return
  195 + return
  196 +
  197 + def _free_fixed_ext_pars(self):
  198 + """
  199 + Free fixed spatial extension parameters
  200 + """
  201 + # Continue only if there are fixed spatial extension parameters
  202 + if len(self._fixed_pars) > 0:
  203 +
  204 + # Loop over fixed parameters
  205 + for fixed_par in self._fixed_pars:
  206 +
  207 + # Free parameter
  208 + name = fixed_par['name']
  209 + par = fixed_par['par']
  210 + self.obs().models()[name][par].free()
  211 +
  212 + # Log action
  213 + value = '%s[%s]' % (name, par)
  214 + self._log_value(gammalib.EXPLICIT, 'Free fixed parameter', value)
  215 +
  216 + # Clear list of fixed parameters
  217 + self._fixed_pars = []
  218 +
  219 + # Return
  220 + return
  221 +
159 # Public methods 222 # Public methods
160 def run(self): 223 def run(self):
161 """ 224 """
@@ -179,19 +242,26 @@ class comlixfit(ctools.cslikelihood): @@ -179,19 +242,26 @@ class comlixfit(ctools.cslikelihood):
179 eps = self['like_accuracy'].real() 242 eps = self['like_accuracy'].real()
180 delta = 0.0 243 delta = 0.0
181 244
182 - # Write header 245 + # Log header
183 self._log_header1(gammalib.NORMAL, 246 self._log_header1(gammalib.NORMAL,
184 'Iterative maximum likelihood model fitting') 247 'Iterative maximum likelihood model fitting')
185 248
186 # Loop over iterations 249 # Loop over iterations
187 for iter in range(niter): 250 for iter in range(niter):
188 251
189 - # Write iteration header 252 + # Log iteration header
190 self._log_header2(gammalib.EXPLICIT, 'Iteration %d' % (iter+1)) 253 self._log_header2(gammalib.EXPLICIT, 'Iteration %d' % (iter+1))
191 254
192 # Update observations 255 # Update observations
193 self._update_obs() 256 self._update_obs()
194 257
  258 + # Optionally fix or free fixed spatial extension parameters
  259 + if self['fix_ext_for_initial'].boolean():
  260 + if iter == 0:
  261 + self._fix_ext_pars()
  262 + else:
  263 + self._free_fixed_ext_pars()
  264 +
195 # Fit model 265 # Fit model
196 self.obs().optimize(self.opt()) 266 self.obs().optimize(self.opt())
197 267
@@ -210,12 +280,15 @@ class comlixfit(ctools.cslikelihood): @@ -210,12 +280,15 @@ class comlixfit(ctools.cslikelihood):
210 self._log_value(gammalib.NORMAL, 'logL after iteration %d' % (iter+1), 280 self._log_value(gammalib.NORMAL, 'logL after iteration %d' % (iter+1),
211 result) 281 result)
212 282
  283 + # Optionally log results
  284 + self._log_string(gammalib.VERBOSE, str(self.obs().models()))
  285 +
213 # Check for convergence 286 # Check for convergence
214 if iter > 0: 287 if iter > 0:
215 if delta < eps: 288 if delta < eps:
216 break 289 break
217 290
218 - # Write header 291 + # Log header
219 self._log_header1(gammalib.EXPLICIT, 292 self._log_header1(gammalib.EXPLICIT,
220 'Final maximum likelihood model fitting') 293 'Final maximum likelihood model fitting')
221 294
@@ -231,7 +304,7 @@ class comlixfit(ctools.cslikelihood): @@ -231,7 +304,7 @@ class comlixfit(ctools.cslikelihood):
231 self._log_value(gammalib.NORMAL, 'logL after final iteration', 304 self._log_value(gammalib.NORMAL, 'logL after final iteration',
232 result) 305 result)
233 306
234 - # Log header 307 + # Log results
235 self._log_header1(gammalib.NORMAL, 308 self._log_header1(gammalib.NORMAL,
236 'Maximum likelihood optimisation results') 309 'Maximum likelihood optimisation results')
237 self._log_string(gammalib.NORMAL, str(self.opt())) 310 self._log_string(gammalib.NORMAL, str(self.opt()))
@@ -244,7 +317,7 @@ class comlixfit(ctools.cslikelihood): @@ -244,7 +317,7 @@ class comlixfit(ctools.cslikelihood):
244 """ 317 """
245 Save observation definition file 318 Save observation definition file
246 """ 319 """
247 - # Write header 320 + # Log header
248 self._log_header1(gammalib.TERSE, 'Save observations') 321 self._log_header1(gammalib.TERSE, 'Save observations')
249 322
250 # Get output filenames 323 # Get output filenames