Commit 706e318f0551e239951821e28ddd02a442680bf9

Authored by Michael Mayer
1 parent 51c98949

Modified ctmodel following the discussions on #1439. In addition, csresmap was a…

…lso modified consistently, csresmap can now also take two maps (cnt and model) as input and compute the residuals directly. The algorithm parameter has been made unhidden
scripts/csresmap.py
@@ -101,6 +101,8 @@ class csresmap(ctools.cscript): @@ -101,6 +101,8 @@ class csresmap(ctools.cscript):
101 # Create default parfile 101 # Create default parfile
102 pars = gammalib.GApplicationPars() 102 pars = gammalib.GApplicationPars()
103 pars.append(gammalib.GApplicationPar("inobs","f","a","events.fits","","","Event list, counts cube, or observation definition file")) 103 pars.append(gammalib.GApplicationPar("inobs","f","a","events.fits","","","Event list, counts cube, or observation definition file"))
  104 + pars.append(gammalib.GApplicationPar("cntcube","f","h","NONE","","","Input model cube (generated with ctmodel)"))
  105 + pars.append(gammalib.GApplicationPar("modcube","f","h","NONE","","","Input counts cube (generated with ctbin)"))
104 pars.append(gammalib.GApplicationPar("inmodel","f","a","$CTOOLS/share/models/crab.xml","","","Source model")) 106 pars.append(gammalib.GApplicationPar("inmodel","f","a","$CTOOLS/share/models/crab.xml","","","Source model"))
105 pars.append(gammalib.GApplicationPar("outmap","f","a","resmap.fits","","","Output residual map")) 107 pars.append(gammalib.GApplicationPar("outmap","f","a","resmap.fits","","","Output residual map"))
106 pars.append(gammalib.GApplicationPar("caldb","s","a","prod2","","","Calibration database")) 108 pars.append(gammalib.GApplicationPar("caldb","s","a","prod2","","","Calibration database"))
@@ -117,7 +119,7 @@ class csresmap(ctools.cscript): @@ -117,7 +119,7 @@ class csresmap(ctools.cscript):
117 pars.append(gammalib.GApplicationPar("nxpix","i","a","200","","","Size of the X axis in pixels")) 119 pars.append(gammalib.GApplicationPar("nxpix","i","a","200","","","Size of the X axis in pixels"))
118 pars.append(gammalib.GApplicationPar("nypix","i","a","200","","","Size of the Y axis in pixels")) 120 pars.append(gammalib.GApplicationPar("nypix","i","a","200","","","Size of the Y axis in pixels"))
119 pars.append(gammalib.GApplicationPar("binsz","r","a","0.02","","","Pixel size (deg/pixel)")) 121 pars.append(gammalib.GApplicationPar("binsz","r","a","0.02","","","Pixel size (deg/pixel)"))
120 - pars.append(gammalib.GApplicationPar("algorithm","s","h","SUBDIV","SUB|SUBDIV|SUBDIVSQRT","","Residual map computation algorithm")) 122 + pars.append(gammalib.GApplicationPar("algorithm","s","a","SUBDIV","SUB|SUBDIV|SUBDIVSQRT","","Residual map computation algorithm"))
121 pars.append_standard() 123 pars.append_standard()
122 pars.append(gammalib.GApplicationPar("logfile","f","h","csresmap.log","","","Log filename")) 124 pars.append(gammalib.GApplicationPar("logfile","f","h","csresmap.log","","","Log filename"))
123 pars.save(parfile) 125 pars.save(parfile)
@@ -131,30 +133,58 @@ class csresmap(ctools.cscript): @@ -131,30 +133,58 @@ class csresmap(ctools.cscript):
131 """ 133 """
132 # Get parameters 134 # Get parameters
133 135
134 - # Set observation if not done before  
135 - if self.obs.size() == 0:  
136 - self.require_inobs("csresmap.get_parameters()")  
137 - self.obs = self.get_observations()  
138 -  
139 - # Set models if we have none  
140 - if self.obs.models().size() == 0:  
141 - self.obs.models(self["inmodel"].filename())  
142 -  
143 - # Read other parameters  
144 - self.m_outfile = self["outmap"].filename()  
145 - self.m_xref = self["xref"].real()  
146 - self.m_yref = self["yref"].real()  
147 - self.m_emin = self["emin"].real()  
148 - self.m_emax = self["emax"].real()  
149 - self.m_enumbins = self["enumbins"].integer()  
150 - self.m_ebinalg = self["ebinalg"].string()  
151 - self.m_coordsys = self["coordsys"].string()  
152 - self.m_proj = self["proj"].string()  
153 - self.m_nxpix = self["nxpix"].integer()  
154 - self.m_nypix = self["nypix"].integer()  
155 - self.m_binsz = self["binsz"].real() 136 + # Initialise some flags
  137 + self.m_use_maps = False
  138 + self.m_skip_binning = False
  139 +
  140 + # First check for cntcube and modcube parameters
  141 + self.m_cntcube = self["cntcube"].filename()
  142 + self.m_modcube = self["modcube"].filename()
  143 + if not (self.m_cntcube == "NONE" or self.m_modcube == "NONE"):
  144 +
  145 + # Signal that we can use the maps directly without ctbin and ctmodel
  146 + self.m_use_maps = True
  147 +
  148 + # If not two maps are given, proceed to set up observation
  149 + if not self.m_use_maps:
  150 +
  151 + # Set observation if not done before
  152 + if self.obs.size() == 0:
  153 + self.require_inobs("csresmap.get_parameters()")
  154 + self.obs = self.get_observations()
  155 +
  156 + # Check if we have exactly one binned CTA observation
  157 + if self.obs.size() == 1:
  158 +
  159 + if self.obs[0].classname() == "GCTAObservation":
  160 + if self.obs[0].eventtype() == "CountsCube":
  161 + # Skip ctbin step later on
  162 + self.m_skip_binning = True
  163 +
  164 +
  165 + # Set models if we have none
  166 + if self.obs.models().size() == 0:
  167 + self.obs.models(self["inmodel"].filename())
  168 +
  169 + # Skip query for spatial parameters if a binning is provided in the observation
  170 + if not self.m_skip_binning:
  171 + # Read other parameters
  172 + self.m_xref = self["xref"].real()
  173 + self.m_yref = self["yref"].real()
  174 + self.m_emin = self["emin"].real()
  175 + self.m_emax = self["emax"].real()
  176 + self.m_enumbins = self["enumbins"].integer()
  177 + self.m_ebinalg = self["ebinalg"].string()
  178 + self.m_coordsys = self["coordsys"].string()
  179 + self.m_proj = self["proj"].string()
  180 + self.m_nxpix = self["nxpix"].integer()
  181 + self.m_nypix = self["nypix"].integer()
  182 + self.m_binsz = self["binsz"].real()
  183 +
  184 + # Read necessary parameters
  185 + self.m_outfile = self["outmap"].filename()
156 self.m_algorithm = self["algorithm"].string() 186 self.m_algorithm = self["algorithm"].string()
157 - 187 +
158 # Set some fixed parameters 188 # Set some fixed parameters
159 self.m_log = False # Logging in client tools 189 self.m_log = False # Logging in client tools
160 self.m_chatter = self["chatter"].integer() 190 self.m_chatter = self["chatter"].integer()
@@ -210,53 +240,76 @@ class csresmap(ctools.cscript): @@ -210,53 +240,76 @@ class csresmap(ctools.cscript):
210 self.log(str(self.obs)) 240 self.log(str(self.obs))
211 self.log("\n") 241 self.log("\n")
212 242
213 - # Write header  
214 - if self.logTerse():  
215 - self.log("\n")  
216 - self.log.header1("Generate binned map (ctbin)")  
217 -  
218 - # Create countsmap  
219 - bin = ctools.ctbin(self.obs)  
220 - bin["nxpix"].integer(self.m_nxpix)  
221 - bin["nypix"].integer(self.m_nypix)  
222 - bin["proj"].string(self.m_proj)  
223 - bin["coordsys"].string(self.m_coordsys)  
224 - bin["xref"].real(self.m_xref)  
225 - bin["yref"].real(self.m_yref)  
226 - bin["enumbins"].integer(self.m_enumbins)  
227 - bin["ebinalg"].string(self.m_ebinalg)  
228 - bin["emin"].real(self.m_emin)  
229 - bin["emax"].real(self.m_emax)  
230 - bin["binsz"].real(self.m_binsz)  
231 - bin["chatter"].integer(self.m_chatter)  
232 - bin["clobber"].boolean(self.m_clobber)  
233 - bin["debug"].boolean(self.m_debug)  
234 - bin.run() 243 + countmap = gammalib.GSkymap()
  244 + modelmap = gammalib.GSkymap()
  245 +
  246 + # Use input file directly if given
  247 + if self.m_use_maps:
  248 + countmap = gammalib.GSkymap(self["cntcube"].filename())
  249 + modelmap = gammalib.GSkymap(self["modcube"].filename())
  250 +
  251 + else:
  252 +
  253 + cta_counts_cube = gammalib.GCTAEventCube()
  254 +
  255 + if self.m_skip_binning:
  256 + cta_counts_cube = gammalib.GCTAEventCube(self.obs[0].events().clone())
235 257
  258 + else:
  259 +
  260 + # Write header
  261 + if self.logTerse():
  262 + self.log("\n")
  263 + self.log.header1("Generate binned map (ctbin)")
  264 +
  265 + # Create countsmap
  266 + bin = ctools.ctbin(self.obs)
  267 + bin["nxpix"].integer(self.m_nxpix)
  268 + bin["nypix"].integer(self.m_nypix)
  269 + bin["proj"].string(self.m_proj)
  270 + bin["coordsys"].string(self.m_coordsys)
  271 + bin["xref"].real(self.m_xref)
  272 + bin["yref"].real(self.m_yref)
  273 + bin["enumbins"].integer(self.m_enumbins)
  274 + bin["ebinalg"].string(self.m_ebinalg)
  275 + bin["emin"].real(self.m_emin)
  276 + bin["emax"].real(self.m_emax)
  277 + bin["binsz"].real(self.m_binsz)
  278 + bin["chatter"].integer(self.m_chatter)
  279 + bin["clobber"].boolean(self.m_clobber)
  280 + bin["debug"].boolean(self.m_debug)
  281 + bin.run()
  282 +
  283 + # Retrieve counts cube
  284 + cta_counts_cube = bin.cube()
  285 +
  286 + # Assign GCTAEventCube to skymap
  287 + countmap = cta_counts_cube.map()
  288 +
  289 + # Write header
  290 + if self.logTerse():
  291 + self.log("\n")
  292 + self.log.header1("Generate model map (ctmodel)")
  293 +
  294 + # Create model map
  295 + model = ctools.ctmodel(self.obs)
  296 + model.cube(cta_counts_cube)
  297 + model["chatter"].integer(self.m_chatter)
  298 + model["clobber"].boolean(self.m_clobber)
  299 + model["debug"].boolean(self.m_debug)
  300 + model.run()
  301 +
  302 + # Get model map into GSkymap object
  303 + modelmap = model.cube().map().copy()
  304 +
  305 +
236 # Store counts map as residual map. Note that we need a 306 # Store counts map as residual map. Note that we need a
237 # special construct here to avoid memory leaks. This seems 307 # special construct here to avoid memory leaks. This seems
238 # to be a SWIG feature as SWIG creates a new object when 308 # to be a SWIG feature as SWIG creates a new object when
239 # calling bin.cube() 309 # calling bin.cube()
240 - #residualmap = bin.cube().map()  
241 - counts_cube = bin.cube()  
242 - self.resmap = counts_cube.map().copy() 310 + #residualmap = bin.cube().map()
  311 + self.resmap = countmap.copy()
243 self.resmap.stack_maps() 312 self.resmap.stack_maps()
244 -  
245 - # Write header  
246 - if self.logTerse():  
247 - self.log("\n")  
248 - self.log.header1("Generate model map (ctmodel)")  
249 -  
250 - # Create model map  
251 - model = ctools.ctmodel(self.obs)  
252 - model.cube(bin.cube())  
253 - model["chatter"].integer(self.m_chatter)  
254 - model["clobber"].boolean(self.m_clobber)  
255 - model["debug"].boolean(self.m_debug)  
256 - model.run()  
257 -  
258 - # Get model map into GSkymap object  
259 - modelmap = model.cube().map()  
260 modelmap.stack_maps() 313 modelmap.stack_maps()
261 314
262 # Continue calculations depending on given algorithm 315 # Continue calculations depending on given algorithm
src/ctmodel/ctmodel.cpp
@@ -270,9 +270,34 @@ void ctmodel::run(void) @@ -270,9 +270,34 @@ void ctmodel::run(void)
270 } 270 }
271 } 271 }
272 272
  273 + // Fill cube and leave loop if we are binned mode (meaning we only have
  274 + // one binned observation)
  275 + if (m_binned && m_obs.size() == 1) {
  276 + fill_cube(obs);
  277 + break;
  278 + }
  279 +
  280 + // Skip observation if we don't have an unbinned observation
  281 + if (obs->eventtype() != "EventList") {
  282 +
  283 + // Log that we skip the this observation
  284 + if (logTerse()) {
  285 + log << "Warning: Skipping binned observation \""+obs->name()+"\"";
  286 + log << std::endl;
  287 + }
  288 + continue;
  289 + }
  290 +
  291 +
273 // Fill the cube 292 // Fill the cube
274 fill_cube(obs); 293 fill_cube(obs);
275 294
  295 + // Leave loop if we are binned mode (meaning we only have
  296 + // one binned observation
  297 + if (m_binned && m_obs.size() == 1) {
  298 + break;
  299 + }
  300 +
276 // Dispose events to free memory if event file exists on disk 301 // Dispose events to free memory if event file exists on disk
277 if (obs->eventfile().length() > 0 && 302 if (obs->eventfile().length() > 0 &&
278 gammalib::file_exists(obs->eventfile())) { 303 gammalib::file_exists(obs->eventfile())) {
@@ -374,6 +399,7 @@ void ctmodel::init_members(void) @@ -374,6 +399,7 @@ void ctmodel::init_members(void)
374 m_gti.clear(); 399 m_gti.clear();
375 m_has_cube = false; 400 m_has_cube = false;
376 m_append_cube = false; 401 m_append_cube = false;
  402 + m_binned = false;
377 403
378 // Return 404 // Return
379 return; 405 return;
@@ -397,6 +423,7 @@ void ctmodel::copy_members(const ctmodel&amp; app) @@ -397,6 +423,7 @@ void ctmodel::copy_members(const ctmodel&amp; app)
397 m_gti = app.m_gti; 423 m_gti = app.m_gti;
398 m_has_cube = app.m_has_cube; 424 m_has_cube = app.m_has_cube;
399 m_append_cube = app.m_append_cube; 425 m_append_cube = app.m_append_cube;
  426 + m_binned = app.m_binned;
400 427
401 // Return 428 // Return
402 return; 429 return;
@@ -430,6 +457,36 @@ void ctmodel::get_parameters(void) @@ -430,6 +457,36 @@ void ctmodel::get_parameters(void)
430 m_obs = get_observations(); 457 m_obs = get_observations();
431 } 458 }
432 459
  460 + // Check if we got excactly one binned CTA observation
  461 + if (m_obs.size() == 1) {
  462 +
  463 + // Get CTA observation
  464 + GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[0]);
  465 +
  466 + // Continue only if observation is a CTA observation
  467 + if (obs != NULL) {
  468 +
  469 + // Check for binned observation
  470 + if (obs->eventtype() == "CountsCube") {
  471 +
  472 + // Set cube from binned observation
  473 + GCTAEventCube* evtcube = dynamic_cast<GCTAEventCube*>(const_cast<GEvents*>(obs->events()));
  474 +
  475 + cube(*evtcube);
  476 +
  477 + // Signal that cube has been set
  478 + m_has_cube = true;
  479 +
  480 + // Signal that we are in binned mode
  481 + m_binned = true;
  482 +
  483 + } // endif: observation was binned
  484 +
  485 + } // endif: observation was CTA
  486 +
  487 + } // endif: had exactly one observation
  488 +
  489 +
433 // Read model definition file if required 490 // Read model definition file if required
434 if (m_obs.models().size() == 0) { 491 if (m_obs.models().size() == 0) {
435 492
@@ -583,3 +640,4 @@ void ctmodel::fill_cube(const GCTAObservation* obs) @@ -583,3 +640,4 @@ void ctmodel::fill_cube(const GCTAObservation* obs)
583 // Return 640 // Return
584 return; 641 return;
585 } 642 }
  643 +
src/ctmodel/ctmodel.hpp
@@ -92,6 +92,7 @@ protected: @@ -92,6 +92,7 @@ protected:
92 GGti m_gti; //!< Model cube GTIs 92 GGti m_gti; //!< Model cube GTIs
93 bool m_has_cube; //!< Signal if cube has been set or loaded 93 bool m_has_cube; //!< Signal if cube has been set or loaded
94 bool m_append_cube; //!< Signal that cube should be appended 94 bool m_append_cube; //!< Signal that cube should be appended
  95 + bool m_binned; //!< Signals that we are in binned mode
95 }; 96 };
96 97
97 98
test/test_cscripts.sh.in
@@ -182,7 +182,8 @@ chmod +x @abs_top_srcdir@/scripts/csresmap.py @@ -182,7 +182,8 @@ chmod +x @abs_top_srcdir@/scripts/csresmap.py
182 xref=83.63 \ 182 xref=83.63 \
183 yref=22.01 \ 183 yref=22.01 \
184 proj="CAR" \ 184 proj="CAR" \
185 - binsz=0.05 > csresmap.log 185 + binsz=0.05 \
  186 + algorithm="SUBDIV" > csresmap.log
186 $ECHO -n "." 187 $ECHO -n "."
187 if [ -s "resmap.fits" ] 188 if [ -s "resmap.fits" ]
188 then 189 then