diff --git a/pyext/ctbin.i b/pyext/ctbin.i index e6c564c..b3cab33 100755 --- a/pyext/ctbin.i +++ b/pyext/ctbin.i @@ -49,6 +49,7 @@ public: void save(void); void publish(const std::string& name = ""); const GCTAEventCube& cube(void) const; + const GCTAEventCube& cube(const size_t& index) const; }; diff --git a/src/ctbin/ctbin.cpp b/src/ctbin/ctbin.cpp index f6e0ebf..d41128c 100755 --- a/src/ctbin/ctbin.cpp +++ b/src/ctbin/ctbin.cpp @@ -398,7 +398,6 @@ void ctbin::save(void) log_header1(TERSE, "Save counts cube"); if (!m_stack) { - std::cout << m_prefix << std::endl; // Loop over all observations for (size_t i = 0; i < m_obs.size(); ++i) { @@ -428,32 +427,33 @@ void ctbin::save(void) m_outcube = (*this)["outcube"].filename(); m_obs.save(m_outcube); } - return; - } - - // Save only if filename is valid and if there is at least one - // observation - if ((*this)["outcube"].is_valid() && m_obs.size() > 0) { - - // Get counts cube filename - m_outcube = (*this)["outcube"].filename(); - - // Get CTA observation from observation container - GCTAObservation* obs = dynamic_cast(m_obs[0]); - - // Save only if observation is valid - if (obs != NULL) { - - // Log counts cube file name - log_value(NORMAL, "Counts cube file", m_outcube.url()); - - // Save cube - obs->save(m_outcube, clobber()); - - } // endif: observation was valid - - } // endif: outcube file was valid + + } else { // else: stack + // Save only if filename is valid and if there is at least one + // observation + if ((*this)["outcube"].is_valid() && m_obs.size() > 0) { + + // Get counts cube filename + m_outcube = (*this)["outcube"].filename(); + + // Get CTA observation from observation container + GCTAObservation* obs = dynamic_cast(m_obs[0]); + + // Save only if observation is valid + if (obs != NULL) { + + // Log counts cube file name + log_value(NORMAL, "Counts cube file", m_outcube.url()); + + // Save cube + obs->save(m_outcube, clobber()); + + } // endif: observation was valid + + } // endif: outcube file was valid + + } // endelse: stack // Return return; } diff --git a/src/ctbin/ctbin.hpp b/src/ctbin/ctbin.hpp index 3f0b289..fa4034d 100755 --- a/src/ctbin/ctbin.hpp +++ b/src/ctbin/ctbin.hpp @@ -39,7 +39,7 @@ * * @brief Event binning tool * - * This class bins event list(s) into a single counts cube. The class can + * This class bins event list(s) into counts cubes. The class can * operate on predefined observation containers, on individual event list * FITS files, and on observation definition XML files. * @@ -47,6 +47,13 @@ * XML definition file, the class will merge these events into a single * counts cube. * + * If the hidden parameter stack=no is used, one counts cube is generated for + * each individual observation. These cubes are saved to a path that can be + * specified by the hidden parameter prefix, followed by the corresponding + * observation id. An observation definition XML file containing the paths + * to the newly generated counts cubes is written to path given in the + * parameter outcube. + * * Results are stored in an observation container that can be written to disk * in form of a single FITS file. On output, the observation container will * have merged the input event lists into a single observation. @@ -77,6 +84,7 @@ public: void save(void); void publish(const std::string& name = ""); const GCTAEventCube& cube(void) const; + const GCTAEventCube& cube(const size_t& index) const; protected: // Protected methods @@ -104,8 +112,8 @@ protected: GCTAEventCube m_cube; //!< Events cube (for cube() method) double m_ontime; //!< Total ontime double m_livetime; //!< Total livetime - std::vector m_cubes; - std::vector m_ids; + std::vector m_cubes; //!< Event cubes (for cube() method) + std::vector m_ids; //!< Observation ids // Cache members std::vector m_dirs; //!< Cached GSkyDir for each pixel in m_counts @@ -125,4 +133,19 @@ const GCTAEventCube& ctbin::cube(void) const return m_cube; } + +/***********************************************************************//** + * @brief Return event cube at index + * + * @param[in] index Index of cube + * @return Reference to event cube + * + * Returns a reference to the event cube at the given index. + ***************************************************************************/ +inline +const GCTAEventCube& ctbin::cube(const size_t& index) const +{ + return m_cubes[index]; +} + #endif /* CTBIN_HPP */ diff --git a/test/test_ctbin.py b/test/test_ctbin.py index 4bda73a..e1dd911 100755 --- a/test/test_ctbin.py +++ b/test/test_ctbin.py @@ -294,6 +294,42 @@ class Test(test): evt = gammalib.GCTAEventCube('ctbin_py4.fits') self._check_cube(evt, 245) + # Test unstacked version + pars = {'inobs': self._datadir+'/obs_unbinned_two.xml', 'ebinalg': 'LIN', 'emin': 1.0, + 'emax': 100.0, 'enumbins': 10, 'nxpix': 40, 'nypix': 40, + 'binsz': 0.1, 'coordsys': 'CEL', 'proj': 'CAR', + 'xref': 83.63, 'yref': 22.01, 'outcube': 'ctbin_py5.xml', + 'logfile': 'ctbin_py5.log', 'chatter': 2, + 'prefix': 'cntcube_py5_', 'stack' : False} + binning = ctools.ctbin() + binning.pardict(pars) + + binning.logFileOpen() + binning.run() + + # Check individual cubes + self._check_cube(binning.cube(0), 245) + self._check_cube(binning.cube(1), 245) + + # Save counts cube + binning.save() + + # Load observations + obs = gammalib.GObservations('ctbin_py5.xml') + self.test_value(obs.size(), 2, 'Check number of output observations') + + # Check counts cubes + evt = obs[0].events() + self._check_cube(evt, 245) + evt = obs[1].events() + self._check_cube(evt, 245) + + # Load counts cubes and check content + evt = gammalib.GCTAEventCube('cntcube_py5_00001.fits') + self._check_cube(evt, 245) + evt = gammalib.GCTAEventCube('cntcube_py5_00002.fits') + self._check_cube(evt, 245) + # Return return