Commit 98512543ccdb27175e193d5f10d7f44f287b8191

Authored by Domenico Tiziani
1 parent 02f82e70

Implement ctbin unstacked for command line

src/ctbin/ctbin.cpp
... ... @@ -255,6 +255,12 @@ void ctbin::run(void)
255 255 log_string(NORMAL, msg);
256 256 }
257 257  
  258 + // Initialise cubes and ids if unstacked
  259 + if (!m_stack) {
  260 + m_cubes = std::vector<GCTAEventCube>(obs_list.size());
  261 + m_ids = std::vector<std::string>(obs_list.size());
  262 + }
  263 +
258 264 // Write header into logger
259 265 log_header1(TERSE, gammalib::number("Bin observation", m_obs.size()));
260 266  
... ... @@ -265,52 +271,108 @@ void ctbin::run(void)
265 271 // Get pointer to observation
266 272 GCTAObservation* obs = obs_list[i];
267 273  
  274 + // Make sure that the observation holds a CTA event list. If this
  275 + // is not the case then throw an exception.
  276 + const GCTAEventList* events = dynamic_cast<const GCTAEventList*>
  277 + (obs->events());
  278 + if (events == NULL) {
  279 + std::string msg = "CTA Observation does not contain an event "
  280 + "list. An event list is needed to fill the "
  281 + "counts cube.";
  282 + throw GException::invalid_value(G_FILL_CUBE, msg);
  283 + }
  284 +
268 285 // Fill the cube
269   - fill_cube(obs);
  286 + GSkyMap counts = fill_cube(obs);
270 287  
271 288 // Set the counts cube weights
272   - set_weights(obs);
  289 + GSkyMap weights = set_weights(obs);
273 290  
274 291 // Dispose events to free memory
275 292 obs->dispose_events();
276 293  
277   - } // endfor: looped over observations
278   -
279   - // Compute total livetime in all observations
280   - double livetime = 0.0;
281   - for (int i = 0; i < obs_list.size(); ++i) {
282   - livetime += obs_list[i]->livetime();
283   - }
  294 + #pragma omp critical(ctbin_fill_cube)
  295 + if (m_stack) {
  296 +
  297 +
  298 + m_counts += counts;
  299 +
  300 + for (int iebin = 0; iebin < m_ebounds.size(); ++iebin) {
  301 + for (int pixel = 0; pixel < m_counts.npix(); ++pixel) {
  302 + if (weights(pixel, iebin) == 1.0) {
  303 + m_weights(pixel, iebin) = 1.0;
  304 + }
  305 + }
  306 + }
  307 +
  308 +
  309 + // If GTI is empty then set its time reference from the observation.
  310 + // From then on we keep that time reference
  311 + if (m_gti.is_empty()) {
  312 + m_gti.reference(events->gti().reference());
  313 + }
  314 +
  315 + // Append GTIs
  316 + m_gti.extend(events->gti());
  317 +
  318 + // Update ontime and livetime
  319 + m_ontime += obs->ontime();
  320 + m_livetime += obs->livetime();
  321 +
  322 + } else { // don't stack cubes
  323 +
  324 + // Construct a cube from this observation
  325 + GCTAEventCube cube(counts, weights, m_ebounds, events->gti());
  326 + m_cubes[i] = cube;
  327 + obs->events(cube);
  328 +
  329 + // Store id of the observation
  330 + m_ids[i] = obs->id();
  331 +
  332 + }
284 333  
285   - // Compute livetime fraction per energy bin so that varying energy
286   - // thresholds are correctly taken into account in the weighting
287   - // array. Computational speed is not optimum, we have to see later
288   - // whether this is an issue.
289   - for (int iebin = 0; iebin < m_ebounds.size(); ++iebin) {
290   - double livetime_ebin = 0.0;
291   - for (int i = 0; i < obs_list.size(); ++i) {
292   - const GCTAEventList* events = dynamic_cast<const GCTAEventList*>(obs_list[i]->events());
293   - std::vector<bool> usage = cube_layer_usage(m_ebounds, events->ebounds());
294   - if (usage[iebin]) {
295   - livetime_ebin += obs_list[i]->livetime();
296   - }
297   - }
298   - if (livetime > 0.0) {
299   - double fraction = livetime_ebin / livetime;
300   - for (int pixel = 0; pixel < m_counts.npix(); ++pixel) {
301   - if (m_weights(pixel, iebin) > 0.0) {
302   - m_weights(pixel, iebin) *= fraction;
303   - }
304   - }
305   - }
306   - }
307 334  
308   - // Build event cube (needs to come before obs_cube() since this method
309   - // relies on correct setting of m_cube)
310   - m_cube = GCTAEventCube(m_counts, m_weights, m_ebounds, m_gti);
  335 + } // endfor: looped over observations
311 336  
312   - // Set a single cube in the observation container
313   - obs_cube();
  337 + if (m_stack) {
  338 + // Compute total livetime in all observations
  339 + double livetime = 0.0;
  340 + for (int i = 0; i < obs_list.size(); ++i) {
  341 + livetime += obs_list[i]->livetime();
  342 + }
  343 +
  344 + // Compute livetime fraction per energy bin so that varying energy
  345 + // thresholds are correctly taken into account in the weighting
  346 + // array. Computational speed is not optimum, we have to see later
  347 + // whether this is an issue.
  348 + for (int iebin = 0; iebin < m_ebounds.size(); ++iebin) {
  349 + double livetime_ebin = 0.0;
  350 + for (int i = 0; i < obs_list.size(); ++i) {
  351 + const GCTAEventList* events = dynamic_cast<const GCTAEventList*>
  352 + (obs_list[i]->events());
  353 + std::vector<bool> usage = cube_layer_usage(m_ebounds,
  354 + events->ebounds());
  355 + if (usage[iebin]) {
  356 + livetime_ebin += obs_list[i]->livetime();
  357 + }
  358 + }
  359 + if (livetime > 0.0) {
  360 + double fraction = livetime_ebin / livetime;
  361 + for (int pixel = 0; pixel < m_counts.npix(); ++pixel) {
  362 + if (m_weights(pixel, iebin) > 0.0) {
  363 + m_weights(pixel, iebin) *= fraction;
  364 + }
  365 + }
  366 + }
  367 + }
  368 +
  369 + // Build event cube (needs to come before obs_cube() since this method
  370 + // relies on correct setting of m_cube)
  371 + m_cube = GCTAEventCube(m_counts, m_weights, m_ebounds, m_gti);
  372 +
  373 + // Set a single cube in the observation container
  374 + obs_cube();
  375 + }
314 376  
315 377 // Write resulting observation container into logger
316 378 log_observations(NORMAL, m_obs, "Binned observation");
... ... @@ -335,6 +397,40 @@ void ctbin::save(void)
335 397 // Write header
336 398 log_header1(TERSE, "Save counts cube");
337 399  
  400 + if (!m_stack) {
  401 + std::cout << m_prefix << std::endl;
  402 +
  403 + // Loop over all observations
  404 + for (size_t i = 0; i < m_obs.size(); ++i) {
  405 +
  406 + // Loop over all ids of observations that were binned
  407 + for (size_t j = 0; j < m_ids.size(); ++j) {
  408 +
  409 + // Check if ids are equal
  410 + if (m_ids[j] == m_obs[i]->id()) {
  411 +
  412 + // Construct filename
  413 + std::string filename(m_ids[j]);
  414 + filename.insert(0, m_prefix);
  415 + filename.append(".fits");
  416 +
  417 + // Set filename for counts cube
  418 + GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]);
  419 + obs->eventfile(filename);
  420 +
  421 + // Save countscube
  422 + obs->save(filename, clobber());
  423 + }
  424 + }
  425 + }
  426 + if ((*this)["outcube"].is_valid()) {
  427 + // Get counts cube filename
  428 + m_outcube = (*this)["outcube"].filename();
  429 + m_obs.save(m_outcube);
  430 + }
  431 + return;
  432 + }
  433 +
338 434 // Save only if filename is valid and if there is at least one
339 435 // observation
340 436 if ((*this)["outcube"].is_valid() && m_obs.size() > 0) {
... ... @@ -416,6 +512,8 @@ void ctbin::init_members(void)
416 512 m_cube.clear();
417 513 m_ontime = 0.0;
418 514 m_livetime = 0.0;
  515 + m_cubes.clear();
  516 + m_ids.clear();
419 517  
420 518 // Initialise cache members
421 519 m_dirs.clear();
... ... @@ -447,6 +545,8 @@ void ctbin::copy_members(const ctbin&amp; app)
447 545 m_cube = app.m_cube;
448 546 m_ontime = app.m_ontime;
449 547 m_livetime = app.m_livetime;
  548 + m_cubes = app.m_cubes;
  549 + m_ids = app.m_ids;
450 550  
451 551 // Copy cache members
452 552 m_dirs = app.m_dirs;
... ... @@ -496,6 +596,9 @@ void ctbin::get_parameters(void)
496 596 // Get stack parameter
497 597 m_stack = (*this)["stack"].boolean();
498 598  
  599 + // Get prefix parameter
  600 + m_prefix = (*this)["prefix"].string();
  601 +
499 602 // Get remaining parameters
500 603 m_publish = (*this)["publish"].boolean();
501 604 m_chatter = static_cast<GChatter>((*this)["chatter"].integer());
... ... @@ -538,7 +641,7 @@ void ctbin::get_parameters(void)
538 641 *
539 642 * Fills the events from an event list into the counts cube.
540 643 ***************************************************************************/
541   -void ctbin::fill_cube(GCTAObservation* obs)
  644 +GSkyMap ctbin::fill_cube(GCTAObservation* obs)
542 645 {
543 646 // Make sure that the observation holds a CTA event list. If this
544 647 // is not the case then throw an exception.
... ... @@ -573,6 +676,10 @@ void ctbin::fill_cube(GCTAObservation* obs)
573 676 int num_outside_ebds = 0;
574 677 int num_in_map = 0;
575 678  
  679 + // Initialise new empty counts map
  680 + GSkyMap counts(m_counts);
  681 + counts *= 0.;
  682 +
576 683 // Fill counts sky map
577 684 for (int i = 0; i < events->size(); ++i) {
578 685  
... ... @@ -619,8 +726,8 @@ void ctbin::fill_cube(GCTAObservation* obs)
619 726 }
620 727  
621 728 // Fill event in skymap
622   - #pragma omp critical(ctbin_fill_cube)
623   - m_counts(pixel, iebin) += 1.0;
  729 + //#pragma omp critical(ctbin_fill_cube)
  730 + counts(pixel, iebin) += 1.0;
624 731  
625 732 // Increment number of maps
626 733 num_in_map++;
... ... @@ -628,7 +735,7 @@ void ctbin::fill_cube(GCTAObservation* obs)
628 735 } // endfor: looped over all events
629 736  
630 737 // Update time information
631   - #pragma omp critical(ctbin_fill_cube)
  738 + /*#pragma omp critical(ctbin_fill_cube)
632 739 {
633 740 // If GTI is empty then set its time reference from the observation.
634 741 // From then on we keep that time reference
... ... @@ -642,7 +749,7 @@ void ctbin::fill_cube(GCTAObservation* obs)
642 749 // Update ontime and livetime
643 750 m_ontime += obs->ontime();
644 751 m_livetime += obs->livetime();
645   - }
  752 + }*/
646 753  
647 754 // Log filling results
648 755 #pragma omp critical(ctbin_fill_cube)
... ... @@ -657,7 +764,7 @@ void ctbin::fill_cube(GCTAObservation* obs)
657 764 }
658 765  
659 766 // Return
660   - return;
  767 + return counts;
661 768 }
662 769  
663 770  
... ... @@ -672,7 +779,7 @@ void ctbin::fill_cube(GCTAObservation* obs)
672 779 * Sets the counts cube weights for all bins that are considered for the
673 780 * specific observation to unity.
674 781 ***************************************************************************/
675   -void ctbin::set_weights(GCTAObservation* obs)
  782 +GSkyMap ctbin::set_weights(GCTAObservation* obs)
676 783 {
677 784 // Make sure that the observation holds a CTA event list. If this
678 785 // is not the case then throw an exception.
... ... @@ -700,6 +807,10 @@ void ctbin::set_weights(GCTAObservation* obs)
700 807 // Get counts cube usage flags
701 808 std::vector<bool> usage = cube_layer_usage(m_ebounds, events->ebounds());
702 809  
  810 + // Initialise new empty weights map
  811 + GSkyMap weights(m_weights);
  812 + weights *= 0.;
  813 +
703 814 // Loop over all pixels in counts cube
704 815 for (int pixel = 0; pixel < m_counts.npix(); ++pixel) {
705 816  
... ... @@ -717,15 +828,15 @@ void ctbin::set_weights(GCTAObservation* obs)
717 828 }
718 829  
719 830 // Signal that bin was filled
720   - #pragma omp critical(ctbin_set_weights)
721   - m_weights(pixel, iebin) = 1.0;
  831 + //#pragma omp critical(ctbin_set_weights)
  832 + weights(pixel, iebin) = 1.0;
722 833  
723 834 } // endfor: looped over energy layers of counts cube
724 835  
725 836 } // endfor: looped over pixels of counts cube
726 837  
727 838 // Return
728   - return;
  839 + return weights;
729 840 }
730 841  
731 842  
... ... @@ -754,9 +865,9 @@ void ctbin::obs_cube(void)
754 865  
755 866 // Change the event type if we had an unbinned observation
756 867 if (obs->eventtype() == "EventList") {
757   -
  868 +
758 869 // Assign cube to the observation
759   - obs->events(this->cube());
  870 + obs->events(this->cube());
760 871  
761 872 }
762 873  
... ... @@ -788,49 +899,49 @@ void ctbin::obs_cube(void)
788 899 // Allocate observation container
789 900 GObservations container;
790 901  
791   - // Allocate CTA observation.
792   - GCTAObservation obs;
793   -
794   - // Attach event cube to CTA observation
795   - obs.events(this->cube());
796   -
797   - // Compute average pointing direction for all CTA event lists
798   - double ra = 0.0;
799   - double dec = 0.0;
800   - double number = 0.0;
801   - for (int i = 0; i < m_obs.size(); ++i) {
802   - GCTAObservation* cta = dynamic_cast<GCTAObservation*>(m_obs[i]);
803   - if ((cta != NULL) && (cta->eventtype() == "EventList")) {
804   - ra += cta->pointing().dir().ra();
805   - dec += cta->pointing().dir().dec();
806   - number += 1.0;
807   - }
808   - }
809   - if (number > 0.0) {
810   - ra /= number;
811   - dec /= number;
812   - }
813   - GSkyDir dir;
814   - dir.radec(ra, dec);
815   - GCTAPointing pointing(dir);
816   -
817   - // Compute deadtime correction
818   - double deadc = (m_ontime > 0.0) ? m_livetime / m_ontime : 0.0;
819   -
820   - // Set CTA observation attributes
821   - obs.pointing(pointing);
822   - obs.ra_obj(dir.ra_deg()); //!< Dummy
823   - obs.dec_obj(dir.dec_deg()); //!< Dummy
824   - obs.ontime(m_ontime);
825   - obs.livetime(m_livetime);
826   - obs.deadc(deadc);
  902 + // Allocate CTA observation.
  903 + GCTAObservation obs;
  904 +
  905 + // Attach event cube to CTA observation
  906 + obs.events(this->cube());
  907 +
  908 + // Compute average pointing direction for all CTA event lists
  909 + double ra = 0.0;
  910 + double dec = 0.0;
  911 + double number = 0.0;
  912 + for (int i = 0; i < m_obs.size(); ++i) {
  913 + GCTAObservation* cta = dynamic_cast<GCTAObservation*>(m_obs[i]);
  914 + if ((cta != NULL) && (cta->eventtype() == "EventList")) {
  915 + ra += cta->pointing().dir().ra();
  916 + dec += cta->pointing().dir().dec();
  917 + number += 1.0;
  918 + }
  919 + }
  920 + if (number > 0.0) {
  921 + ra /= number;
  922 + dec /= number;
  923 + }
  924 + GSkyDir dir;
  925 + dir.radec(ra, dec);
  926 + GCTAPointing pointing(dir);
  927 +
  928 + // Compute deadtime correction
  929 + double deadc = (m_ontime > 0.0) ? m_livetime / m_ontime : 0.0;
  930 +
  931 + // Set CTA observation attributes
  932 + obs.pointing(pointing);
  933 + obs.ra_obj(dir.ra_deg()); //!< Dummy
  934 + obs.dec_obj(dir.dec_deg()); //!< Dummy
  935 + obs.ontime(m_ontime);
  936 + obs.livetime(m_livetime);
  937 + obs.deadc(deadc);
  938 +
  939 + // Append CTA observation
  940 + container.append(obs);
827 941  
828 942 // Set models in observation container
829 943 container.models(m_obs.models());
830 944  
831   - // Append CTA observation
832   - container.append(obs);
833   -
834 945 // Copy over all remaining non-CTA observations
835 946 for (int i = 0; i < m_obs.size(); ++i) {
836 947 GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]);
... ...
src/ctbin/ctbin.hpp
... ... @@ -80,18 +80,19 @@ public:
80 80  
81 81 protected:
82 82 // Protected methods
83   - void init_members(void);
84   - void copy_members(const ctbin& app);
85   - void free_members(void);
86   - void get_parameters(void);
87   - void fill_cube(GCTAObservation* obs);
88   - void set_weights(GCTAObservation* obs);
89   - void obs_cube(void);
  83 + void init_members(void);
  84 + void copy_members(const ctbin& app);
  85 + void free_members(void);
  86 + void get_parameters(void);
  87 + GSkyMap fill_cube(GCTAObservation* obs);
  88 + GSkyMap set_weights(GCTAObservation* obs);
  89 + void obs_cube(void);
90 90  
91 91 // User parameters
92 92 GFilename m_outcube; //!< Output counts map file name
93 93 bool m_usepnt; //!< Use pointing instead of xref/yref parameters
94 94 bool m_stack; //!< Output one stacked cube or multiple cubes
  95 + std::string m_prefix; //!< Prefix for output path of multiple cubes
95 96 bool m_publish; //!< Publish counts cube?
96 97 GChatter m_chatter; //!< Chattiness
97 98  
... ... @@ -103,6 +104,8 @@ protected:
103 104 GCTAEventCube m_cube; //!< Events cube (for cube() method)
104 105 double m_ontime; //!< Total ontime
105 106 double m_livetime; //!< Total livetime
  107 + std::vector<GCTAEventCube> m_cubes;
  108 + std::vector<std::string> m_ids;
106 109  
107 110 // Cache members
108 111 std::vector<GSkyDir> m_dirs; //!< Cached GSkyDir for each pixel in m_counts
... ...
src/ctbin/ctbin.par
... ... @@ -19,6 +19,7 @@
19 19 inobs, f, a, events.fits,,, "Input event list or observation definition XML file"
20 20 outcube, f, a, cntcube.fits,,, "Output counts cube file"
21 21 stack, b, h, yes,,, "Stack events to one cube?"
  22 +prefix, s, h, binned_,,, "Prefix for counts cubes in observation definition XML file"
22 23  
23 24 #
24 25 # Energy binning parameters
... ...
test/test_ctbin.py
... ... @@ -117,11 +117,12 @@ class Test(test):
117 117  
118 118 # Setup ctbin command
119 119 cmd = ctbin+' inobs="'+self._datadir+'/obs_unbinned_two.xml"'+ \
120   - ' outcube="cntmap_cmd4.fits"'+\
  120 + ' outcube="obs_unbinned_two_binned.xml"'+\
121 121 ' emin=1.0 emax=100.0 enumbins=10 ebinalg="LOG"'+ \
122 122 ' nxpix=40 nypix=40 binsz=0.1 coordsys="CEL"'+ \
123 123 ' xref=83.63 yref=22.01 proj="CAR"'+ \
124   - ' logfile="ctbin_cmd4.log" chatter=1 stack=no'
  124 + ' logfile="ctbin_cmd4.log" chatter=1 stack=no'+ \
  125 + ' prefix="cntmap_cmd4_"'
125 126  
126 127 # Check if execution was successful
127 128 self.test_value(self._execute(cmd), 0,
... ...