Commit 2de25f8ed3c99a7b3c746f2cad8757efa05a263b
Merge branch '1439-adapt-ctools-to-consistently-handle-observation-types' into integration
Conflicts: scripts/csresmap.py
Showing
4 changed files
with
191 additions
and
69 deletions
scripts/csresmap.py
| ... | ... | @@ -42,9 +42,12 @@ class csresmap(ctools.cscript): |
| 42 | 42 | self.version = "1.0.0" |
| 43 | 43 | |
| 44 | 44 | # Initialise some members |
| 45 | - self.obs = None | |
| 46 | - self.algorithm = "SUB" | |
| 47 | - self.resmap = None | |
| 45 | + self.obs = None | |
| 46 | + self.algorithm = "SUB" | |
| 47 | + self.resmap = None | |
| 48 | + self.m_modcube = "None" | |
| 49 | + self.m_use_maps = False | |
| 50 | + self.m_skip_binning = False | |
| 48 | 51 | |
| 49 | 52 | # Initialise some members |
| 50 | 53 | if len(argv) > 0 and isinstance(argv[0],gammalib.GObservations): |
| ... | ... | @@ -101,6 +104,10 @@ class csresmap(ctools.cscript): |
| 101 | 104 | # Create default parfile |
| 102 | 105 | pars = gammalib.GApplicationPars() |
| 103 | 106 | pars.append(gammalib.GApplicationPar("inobs","f","a","events.fits","","","Event list, counts cube, or observation definition file")) |
| 107 | + pars.append(gammalib.GApplicationPar("modcube","f","a","NONE","","","Model cube file (generated with ctmodel)")) | |
| 108 | + pars.append(gammalib.GApplicationPar("expcube","f","a","NONE","","","Exposure cube file (only needed for stacked analysis)")) | |
| 109 | + pars.append(gammalib.GApplicationPar("psfcube","f","a","NONE","","","PSF cube file (only needed for stacked analysis)")) | |
| 110 | + pars.append(gammalib.GApplicationPar("bkgcube","s","a","NONE","","","Background cube file (only needed for stacked analysis)")) | |
| 104 | 111 | pars.append(gammalib.GApplicationPar("inmodel","f","a","$CTOOLS/share/models/crab.xml","","","Source model")) |
| 105 | 112 | pars.append(gammalib.GApplicationPar("outmap","f","a","resmap.fits","","","Output residual map")) |
| 106 | 113 | pars.append(gammalib.GApplicationPar("caldb","s","a","prod2","","","Calibration database")) |
| ... | ... | @@ -117,7 +124,7 @@ class csresmap(ctools.cscript): |
| 117 | 124 | pars.append(gammalib.GApplicationPar("nxpix","i","a","200","","","Size of the X axis in pixels")) |
| 118 | 125 | pars.append(gammalib.GApplicationPar("nypix","i","a","200","","","Size of the Y axis in pixels")) |
| 119 | 126 | 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")) | |
| 127 | + pars.append(gammalib.GApplicationPar("algorithm","s","a","SUBDIV","SUB|SUBDIV|SUBDIVSQRT","","Residual map computation algorithm")) | |
| 121 | 128 | pars.append_standard() |
| 122 | 129 | pars.append(gammalib.GApplicationPar("logfile","f","h","csresmap.log","","","Log filename")) |
| 123 | 130 | pars.save(parfile) |
| ... | ... | @@ -129,32 +136,64 @@ class csresmap(ctools.cscript): |
| 129 | 136 | """ |
| 130 | 137 | Get parameters from parfile and setup the observation. |
| 131 | 138 | """ |
| 132 | - # Get parameters | |
| 133 | - | |
| 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() | |
| 139 | + # Initialise some flags | |
| 140 | + self.m_use_maps = False | |
| 141 | + self.m_skip_binning = False | |
| 138 | 142 | |
| 139 | - # Set models if we have none | |
| 140 | - if self.obs.models().size() == 0: | |
| 141 | - self.obs.models(self["inmodel"].filename()) | |
| 143 | + # First check if the inobs parameter is a counts cube | |
| 144 | + if self["inobs"].filename() != "NONE": | |
| 145 | + if gammalib.is_fits(self["inobs"].filename()): | |
| 146 | + cta = gammalib.GCTAObservation() | |
| 147 | + cta.load(self["inobs"].filename()) | |
| 148 | + if self.obs[0].eventtype() == "CountsCube": | |
| 149 | + self.m_skip_binning = True | |
| 142 | 150 | |
| 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() | |
| 151 | + # If we have a counts cube, then ask whether we also have a model | |
| 152 | + if self.m_skip_binning: | |
| 153 | + self.m_modcube = self["modcube"].filename() | |
| 154 | + if self.m_modcube != "NONE": | |
| 155 | + self.m_use_maps = True | |
| 156 | + | |
| 157 | + # If not two maps are given, proceed to set up observation | |
| 158 | + if not self.m_use_maps: | |
| 159 | + | |
| 160 | + # Set observation if not done before | |
| 161 | + if self.obs.size() == 0: | |
| 162 | + self.require_inobs("csresmap.get_parameters()") | |
| 163 | + self.obs = self.get_observations() | |
| 164 | + | |
| 165 | + # Check if we have exactly one binned CTA observation | |
| 166 | + if self.obs.size() == 1: | |
| 167 | + | |
| 168 | + if self.obs[0].classname() == "GCTAObservation": | |
| 169 | + if self.obs[0].eventtype() == "CountsCube": | |
| 170 | + # Skip ctbin step later on | |
| 171 | + self.m_skip_binning = True | |
| 172 | + | |
| 173 | + | |
| 174 | + # Set models if we have none | |
| 175 | + if self.obs.models().size() == 0: | |
| 176 | + self.obs.models(self["inmodel"].filename()) | |
| 177 | + | |
| 178 | + # Skip query for spatial parameters if a binning is provided in the observation | |
| 179 | + if not self.m_skip_binning: | |
| 180 | + # Read other parameters | |
| 181 | + self.m_xref = self["xref"].real() | |
| 182 | + self.m_yref = self["yref"].real() | |
| 183 | + self.m_emin = self["emin"].real() | |
| 184 | + self.m_emax = self["emax"].real() | |
| 185 | + self.m_enumbins = self["enumbins"].integer() | |
| 186 | + self.m_ebinalg = self["ebinalg"].string() | |
| 187 | + self.m_coordsys = self["coordsys"].string() | |
| 188 | + self.m_proj = self["proj"].string() | |
| 189 | + self.m_nxpix = self["nxpix"].integer() | |
| 190 | + self.m_nypix = self["nypix"].integer() | |
| 191 | + self.m_binsz = self["binsz"].real() | |
| 192 | + | |
| 193 | + # Read necessary parameters | |
| 194 | + self.m_outfile = self["outmap"].filename() | |
| 156 | 195 | self.m_algorithm = self["algorithm"].string() |
| 157 | - | |
| 196 | + | |
| 158 | 197 | # Set some fixed parameters |
| 159 | 198 | self.m_log = False # Logging in client tools |
| 160 | 199 | self.m_chatter = self["chatter"].integer() |
| ... | ... | @@ -210,53 +249,76 @@ class csresmap(ctools.cscript): |
| 210 | 249 | self.log(str(self.obs)) |
| 211 | 250 | self.log("\n") |
| 212 | 251 | |
| 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"] = self.m_nxpix | |
| 221 | - bin["nypix"] = self.m_nypix | |
| 222 | - bin["proj"] = self.m_proj | |
| 223 | - bin["coordsys"] = self.m_coordsys | |
| 224 | - bin["xref"] = self.m_xref | |
| 225 | - bin["yref"] = self.m_yref | |
| 226 | - bin["enumbins"] = self.m_enumbins | |
| 227 | - bin["ebinalg"] = self.m_ebinalg | |
| 228 | - bin["emin"] = self.m_emin | |
| 229 | - bin["emax"] = self.m_emax | |
| 230 | - bin["binsz"] = self.m_binsz | |
| 231 | - bin["chatter"] = self.m_chatter | |
| 232 | - bin["clobber"] = self.m_clobber | |
| 233 | - bin["debug"] = self.m_debug | |
| 234 | - bin.run() | |
| 252 | + countmap = gammalib.GSkymap() | |
| 253 | + modelmap = gammalib.GSkymap() | |
| 254 | + | |
| 255 | + # Use input file directly if given | |
| 256 | + if self.m_use_maps: | |
| 257 | + countmap = gammalib.GSkymap(self.m_cntcube) | |
| 258 | + modelmap = gammalib.GSkymap(self.m_modcube) | |
| 259 | + | |
| 260 | + else: | |
| 261 | + | |
| 262 | + cta_counts_cube = gammalib.GCTAEventCube() | |
| 263 | + | |
| 264 | + if self.m_skip_binning: | |
| 265 | + cta_counts_cube = gammalib.GCTAEventCube(self.obs[0].events().clone()) | |
| 235 | 266 | |
| 267 | + else: | |
| 268 | + | |
| 269 | + # Write header | |
| 270 | + if self.logTerse(): | |
| 271 | + self.log("\n") | |
| 272 | + self.log.header1("Generate binned map (ctbin)") | |
| 273 | + | |
| 274 | + # Create countsmap | |
| 275 | + bin = ctools.ctbin(self.obs) | |
| 276 | + bin["nxpix"].integer(self.m_nxpix) | |
| 277 | + bin["nypix"].integer(self.m_nypix) | |
| 278 | + bin["proj"].string(self.m_proj) | |
| 279 | + bin["coordsys"].string(self.m_coordsys) | |
| 280 | + bin["xref"].real(self.m_xref) | |
| 281 | + bin["yref"].real(self.m_yref) | |
| 282 | + bin["enumbins"].integer(self.m_enumbins) | |
| 283 | + bin["ebinalg"].string(self.m_ebinalg) | |
| 284 | + bin["emin"].real(self.m_emin) | |
| 285 | + bin["emax"].real(self.m_emax) | |
| 286 | + bin["binsz"].real(self.m_binsz) | |
| 287 | + bin["chatter"].integer(self.m_chatter) | |
| 288 | + bin["clobber"].boolean(self.m_clobber) | |
| 289 | + bin["debug"].boolean(self.m_debug) | |
| 290 | + bin.run() | |
| 291 | + | |
| 292 | + # Retrieve counts cube | |
| 293 | + cta_counts_cube = bin.cube() | |
| 294 | + | |
| 295 | + # Assign GCTAEventCube to skymap | |
| 296 | + countmap = cta_counts_cube.map() | |
| 297 | + | |
| 298 | + # Write header | |
| 299 | + if self.logTerse(): | |
| 300 | + self.log("\n") | |
| 301 | + self.log.header1("Generate model map (ctmodel)") | |
| 302 | + | |
| 303 | + # Create model map | |
| 304 | + model = ctools.ctmodel(self.obs) | |
| 305 | + model.cube(cta_counts_cube) | |
| 306 | + model["chatter"].integer(self.m_chatter) | |
| 307 | + model["clobber"].boolean(self.m_clobber) | |
| 308 | + model["debug"].boolean(self.m_debug) | |
| 309 | + model.run() | |
| 310 | + | |
| 311 | + # Get model map into GSkymap object | |
| 312 | + modelmap = model.cube().map().copy() | |
| 313 | + | |
| 314 | + | |
| 236 | 315 | # Store counts map as residual map. Note that we need a |
| 237 | 316 | # special construct here to avoid memory leaks. This seems |
| 238 | 317 | # to be a SWIG feature as SWIG creates a new object when |
| 239 | 318 | # calling bin.cube() |
| 240 | - #residualmap = bin.cube().map() | |
| 241 | - counts_cube = bin.cube() | |
| 242 | - self.resmap = counts_cube.map().copy() | |
| 319 | + #residualmap = bin.cube().map() | |
| 320 | + self.resmap = countmap.copy() | |
| 243 | 321 | 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"] = self.m_chatter | |
| 254 | - model["clobber"] = self.m_clobber | |
| 255 | - model["debug"] = self.m_debug | |
| 256 | - model.run() | |
| 257 | - | |
| 258 | - # Get model map into GSkymap object | |
| 259 | - modelmap = model.cube().map() | |
| 260 | 322 | modelmap.stack_maps() |
| 261 | 323 | |
| 262 | 324 | # Continue calculations depending on given algorithm | ... | ... |
src/ctmodel/ctmodel.cpp
| ... | ... | @@ -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 | 292 | // Fill the cube |
| 274 | 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 | 301 | // Dispose events to free memory if event file exists on disk |
| 277 | 302 | if (obs->eventfile().length() > 0 && |
| 278 | 303 | gammalib::file_exists(obs->eventfile())) { |
| ... | ... | @@ -374,6 +399,7 @@ void ctmodel::init_members(void) |
| 374 | 399 | m_gti.clear(); |
| 375 | 400 | m_has_cube = false; |
| 376 | 401 | m_append_cube = false; |
| 402 | + m_binned = false; | |
| 377 | 403 | |
| 378 | 404 | // Return |
| 379 | 405 | return; |
| ... | ... | @@ -397,6 +423,7 @@ void ctmodel::copy_members(const ctmodel& app) |
| 397 | 423 | m_gti = app.m_gti; |
| 398 | 424 | m_has_cube = app.m_has_cube; |
| 399 | 425 | m_append_cube = app.m_append_cube; |
| 426 | + m_binned = app.m_binned; | |
| 400 | 427 | |
| 401 | 428 | // Return |
| 402 | 429 | return; |
| ... | ... | @@ -430,6 +457,36 @@ void ctmodel::get_parameters(void) |
| 430 | 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 | 490 | // Read model definition file if required |
| 434 | 491 | if (m_obs.models().size() == 0) { |
| 435 | 492 | |
| ... | ... | @@ -583,3 +640,4 @@ void ctmodel::fill_cube(const GCTAObservation* obs) |
| 583 | 640 | // Return |
| 584 | 641 | return; |
| 585 | 642 | } |
| 643 | + | ... | ... |
src/ctmodel/ctmodel.hpp
test/test_cscripts.sh.in
| ... | ... | @@ -182,7 +182,8 @@ chmod +x @abs_top_srcdir@/scripts/csresmap.py |
| 182 | 182 | xref=83.63 \ |
| 183 | 183 | yref=22.01 \ |
| 184 | 184 | proj="CAR" \ |
| 185 | - binsz=0.05 > csresmap.log | |
| 185 | + binsz=0.05 \ | |
| 186 | + algorithm="SUBDIV" > csresmap.log | |
| 186 | 187 | $ECHO -n "." |
| 187 | 188 | if [ -s "resmap.fits" ] |
| 188 | 189 | then | ... | ... |