#ifndef __JSUPPORT__JMONTECARLOFILESUPPORTKIT__ #define __JSUPPORT__JMONTECARLOFILESUPPORTKIT__ #include "km3net-dataformat/offline/Head.hh" #include "km3net-dataformat/offline/MultiHead.hh" #include "km3net-dataformat/offline/Evt.hh" #include "km3net-dataformat/offline/io_ascii.hh" #include "JLang/JASCIIFileReader.hh" #include "JLang/JGZFileReader.hh" #include "JLang/JStreamObjectOutput.hh" #include "JLang/JAbstractObjectIterator.hh" #include "JLang/JObjectOutput.hh" #include "JLang/JException.hh" #include "JAAnet/JHead.hh" #include "JAAnet/JHeadToolkit.hh" #include "JSupport/JMonteCarloFileReader.hh" #include "JSupport/JMonteCarloFileWriter.hh" #include "JSupport/JMultipleFileScanner.hh" /** * \author mdejong */ /** * Read header from input. * * \param in input stream * \param header header * \return input stream */ inline std::istream& operator>>(std::istream& in, Head& header) { header.clear(); read(header, in); return in; } /** * \cond NEVER * Write header to output. * * \param out output stream * \param header header * \return output stream * \endcond */ /* inline std::ostream& operator<<(std::ostream& out, const Head& header) { write(header, out); return out; } */ /** * Write multi-header to output. * * \param out output stream * \param header header * \return output stream * \endcond */ inline std::ostream& operator<<(std::ostream& out, const MultiHead& header) { for (MultiHead::const_iterator i = header.begin(); i != header.end(); ++i) { write(*i, out); } return out; } /** * Read event from input. * * \param in input stream * \param evt event * \return input stream */ inline std::istream& operator>>(std::istream& in, Evt& evt) { evt = Evt(); read(evt, in, false); return in; } /** * Write event to output. * * \param out output stream * \param evt event * \return output stream * \endcond */ inline std::ostream& operator<<(std::ostream& out, const Evt& evt) { using namespace std; const ios_base::fmtflags flags = out.flags(); write(evt, out << fixed); out.flags(flags); return out; } /** * Read hit from input. * * \param in input stream * \param hit hit * \return input stream */ inline std::istream& operator>>(std::istream& in, Hit& hit) { hit = Hit(); read(hit, in, false); return in; } /** * Write hit to output. * * \param out output stream * \param hit hit * \return output stream * \endcond */ inline std::ostream& operator<<(std::ostream& out, const Hit& hit) { using namespace std; const ios_base::fmtflags flags = out.flags(); write(hit, out << fixed); out.flags(flags); return out; } namespace JSUPPORT {} namespace JPP { using namespace JSUPPORT; } namespace JSUPPORT { using JAANET::JHead; using JLANG::JASCIIFileReader; using JLANG::JGZFileReader; using JLANG::JStreamObjectOutput; using JLANG::JRewindableAbstractObjectIterator; using JLANG::JNullPointerException; using JLANG::JException; /** * Template definition of Monte Carlo object reader. */ template class JFileReader_t> class JMonteCarloFileReader; /** * Template specialisation of JMonteCarloFileReader for Head. * * This class re-implements the methods open of the JLANG::JAccessible and method hasNext * of the JLANG::JObjectIterator interface so that only one Head is read per file. */ template class JFileReader_t> class JMonteCarloFileReader : public JFileReader_t { public: /** * Default constructor. */ JMonteCarloFileReader() : JFileReader_t(), do_next(false) {} /** * Open file. * * \param file_name file name */ virtual void open(const char* file_name) override { JFileReader_t::open(file_name); do_next = true; } /** * Check availability of next element. * * \return true if the iteration has more elements; else false */ virtual bool hasNext() override { if (do_next) { do_next = false; return JFileReader_t::hasNext(); } else { return false; } } private: bool do_next; }; /** * Template specialisation of JMonteCarloFileReader for Event. * * This class re-implements the method open of the JLANG::JAccessible interface * so that the Head is skipped for each file. */ template class JFileReader_t> class JMonteCarloFileReader : public JFileReader_t { public: /** * Open file. * * \param file_name file name */ virtual void open(const char* file_name) override { using namespace std; JFileReader_t::open(file_name); if (this->is_open()) { Head buffer; static_cast(*this) >> buffer; } } }; /** * Template implementation of Monte Carlo object reader for ASCII formatted file (i.e.\ '.evt') */ template<> class JMonteCarloASCIIFileReader : public JMonteCarloFileReader {}; /** * Template implementation of Monte Carlo object reader for ASCII formatted file (i.e.\ '.evt') */ template<> class JMonteCarloASCIIFileReader : public JMonteCarloFileReader {}; /** * Template implementation of Monte Carlo object reader for gzipped ASCII formatted file (i.e.\ '.gz') */ template<> class JMonteCarloGZFileReader : public JMonteCarloFileReader {}; /** * Template implementation of Monte Carlo object reader for gzipped ASCII formatted file (i.e.\ '.gz') */ template<> class JMonteCarloGZFileReader : public JMonteCarloFileReader {}; /** * Template specialisation of JMonteCarloStreamObjectOutput for Head. * * This class provides for a ASCII formatted stream output without separator. */ template<> class JMonteCarloStreamObjectOutput : public JStreamObjectOutput { protected: /** * Constructor. * * \param out output stream */ JMonteCarloStreamObjectOutput(std::ostream& out) : JStreamObjectOutput(out, "") {} }; /** * Template specialisation of JMonteCarloStreamObjectOutput for Evt. * * This class provides for a ASCII formatted stream output without separator. */ template<> class JMonteCarloStreamObjectOutput : public JStreamObjectOutput { protected: /** * Constructor. * * \param out output stream */ JMonteCarloStreamObjectOutput(std::ostream& out) : JStreamObjectOutput(out, "") {} }; /** * Template specialisation of JMultipleFileScanner for Monte Carlo header. * * This class re-implements the methods rewind and setObject of the JLANG::JRewindableAbstractObjectIterator interface * so that all header objects in the complete file list are read and added. * It provides for the method JSUPPORT::getHeader which returns the sum of all headers. */ template<> class JMultipleFileScanner : public virtual JMultipleFileScanner<>, public JRewindableAbstractObjectIterator { public: /** * Default constructor. */ JMultipleFileScanner() : JMultipleFileScanner<>(), JRewindableAbstractObjectIterator(), do_next(true) {} /** * Copy constructor. * The file list is copied. * * \param file_list JMultipleFileScanner */ JMultipleFileScanner(const JMultipleFileScanner_t& file_list) : JMultipleFileScanner<>(), JRewindableAbstractObjectIterator(), do_next(true) { static_cast(*this) = file_list; } /** * Rewind. */ virtual void rewind() override { do_next = true; } /** * Set object. * * \param object reference to object to be set * \return true if set; else false */ virtual bool setObject(Head& object) override { if (do_next) { using namespace JLANG; JHead header; do_next = false; unsigned int count = 0; JFileScanner scanner; for (const_iterator i = this->begin(); i != this->end(); ++i) { scanner.open(i->c_str()); if (scanner.hasNext()) { const JHead buffer = *scanner.next(); if (count == 0) header = buffer; else if (header.match(buffer)) header.add(buffer); else THROW(JException, "JMultipleFileScanner::setObject(): inconsistent headers."); ++count; } scanner.close(); } copy(header, object); if (count != 0 && count != this->size()) { if (!merge) { THROW(JException, "JMultipleFileScanner::setObject(): missing header(s): " << count << " != " << this->size()); } } return count != 0; } else { return false; } } /** * Get Monte Carlo Header. * * \return header */ const Head& getHeader() { const Head* p = NULL; if (!this->hasNext() || (p = this->next()) == NULL) { throw JNullPointerException("JMultipleFileScanner::getHeader(): Missing Header."); } rewind(); return *p; } static bool merge; //!< Allow merging of files w/o header. private: bool do_next; }; /** * Initialisation of merge option. */ bool JMultipleFileScanner::merge = false; /** * Get Monte Carlo header. * * \param file_list file list * \return Monte Carlo header */ inline Head getHeader(const JMultipleFileScanner_t& file_list) { return JMultipleFileScanner(file_list).getHeader(); } /** * Get list of files compatible with geven header. * * Note that the option corresponds to that of method JHead::match. * * \param input file list * \param test test function * \return file list */ template JMultipleFileScanner_t getAAnetFiles(const JMultipleFileScanner_t& input, JFunction_t test) { using namespace JPP; JMultipleFileScanner_t result; for (JMultipleFileScanner_t::const_iterator i = input.begin(); i != input.end(); ++i) { if (test(getHeader(*i))) { result.push_back(*i); } } return result; } } #endif