#ifndef __JACOUSTICS__JEVENT__ #define __JACOUSTICS__JEVENT__ #include #include #include #include #include #include #include #include "JIO/JSerialisable.hh" #include "JIO/JSTDIO.hh" #include "JAcoustics/JCounter.hh" #include "JAcoustics/JTransmission.hh" /** * \file * * Acoustic event. * \author mdejong */ namespace JACOUSTICS {} namespace JPP { using namespace JACOUSTICS; } namespace JACOUSTICS { using JIO::JSerialisable; using JIO::JReader; using JIO::JWriter; /** * Acoustic event. */ struct JEvent : public JSerialisable, public JCounter, public std::vector, public TObject { /** * Auxiliary class to determine value of acoustic events.\n * This class can be used with JSUPPORT::JTreeScanner so to read acoustics events in order of time-of-emission. */ struct JEvaluator { /** * Default constructor. */ JEvaluator() {} /** * Get value of object. * * \param event event * \return value */ inline double operator()(const JEvent& event) const { return event.begin()->getToE(); } }; /** * Default constructor. */ JEvent() : JCounter(), overlays(0), id (-1) {} /** * Constructor. * * The transmissions will be sorted to ensure proper functioning of method JEvent::merge and class JEventOverlap. * * \param oid detector identifier * \param counter counter * \param id identifier * \param __begin begin of data * \param __end end of data */ template JEvent(const std::string& oid, const int counter, const int id, T __begin, T __end) : JCounter(counter), oid (oid), overlays(0), id (id) { using namespace std; for (T i = __begin; i != __end; ++i) { push_back(*i); } sort(this->begin(), this->end()); } /** * Virtual destructor. */ virtual ~JEvent() {} /** * Get detector identifier. * * \return detector identifier. */ const std::string& getOID() const { return oid; } /** * Get number of overlayed events. * * \return overlays */ int getOverlays() const { return overlays; } /** * Get emitter identifier. * * \return identifier */ int getID() const { return id; } /** * Merge event. * * It is assumed that the transmissions in both events are ordered * according the default less-than operator. * * \param event event */ void merge(const JEvent& event) { using namespace std; vector buffer; const_iterator __hit1 = this ->begin(); const_iterator __end1 = this ->end(); const_iterator __hit2 = event.begin(); const_iterator __end2 = event.end(); buffer.resize(this->size() + event.size()); iterator out = buffer.begin(); while (__hit1 != __end1 && __hit2 != __end2) { if (*__hit1 < *__hit2) { *out = *__hit1; ++__hit1; } else if (*__hit2 < *__hit1) { *out = *__hit2; ++__hit2; } else { *out = *__hit1; ++__hit1; ++__hit2; } ++out; } // append remaining hits from either set out = copy(__hit1, __end1, out); out = copy(__hit2, __end2, out); buffer.resize(distance(buffer.begin(), out)); this->swap(buffer); ++overlays; } /** * Swap events. * * \param first first event * \param second second event */ friend inline void swap(JEvent& first, JEvent& second) { std::swap(first.counter, second.counter); std::swap(first.oid, second.oid); std::swap(first.overlays, second.overlays); std::swap(first.id, second.id); static_cast&>(first).swap(static_cast&>(second)); } /** * Empty overlapping events. * * The events should be time sorted on input.\n * The time window applies to the difference between the first transmission * of an event and the last transmission of the previous event. * * \param p begin of events * \param q end of events * \param Tmax_s time window [s] * */ template static inline void overlap(T p, T q, const double Tmax_s) { for (T __q = p, __p = __q++; __p != q && __q != q; __p = __q++) { if (!__p->empty() && !__q->empty() && __q->begin()->getToE() < __p->rbegin()->getToE() + Tmax_s) { __p->clear(); // clear first for (__p = __q++; __p != q && __q != q; __p = __q++) { if (__q->begin()->getToE() < __p->rbegin()->getToE() + Tmax_s) __p->clear(); // clear intermediate else break; } __p->clear(); // clear last } } } /** * Less than operator for acoustics events. * * The less than operator is applied to the first hit in the events.\n * If there are no hits in either event, the counter of the events is used. * * \param first first event * \param second second event * \return true if first event earliear than second; else false */ friend inline bool operator<(const JEvent& first, const JEvent& second) { if (!first.empty() && !second.empty()) return first.begin()->getToE() < second.begin()->getToE(); else return first.getCounter() < second.getCounter(); } /** * Write event to output stream. * * \param out output stream * \param event event * \return output stream */ friend inline std::ostream& operator<<(std::ostream& out, const JEvent& event) { using namespace std; out << event.getOID() << endl; out << setw(8) << event.getCounter() << endl; out << setw(2) << event.getOverlays() << endl; out << setw(3) << event.getID() << endl; for (const_iterator i = event.begin(); i != event.end(); ++i) { out << setw(10) << i->getID() << ' ' << setw(10) << i->getRunNumber() << ' ' << fixed << setw(12) << setprecision(6) << i->getToA() << ' ' << fixed << setw(12) << setprecision(6) << i->getToE() << ' ' << fixed << setw(8) << setprecision(0) << i->getQ() << ' ' << fixed << setw(8) << setprecision(0) << i->getW() << endl; } return out; } /** * Read from input. * * \param in reader * \return reader */ virtual JReader& read(JReader& in) override { in >> static_cast(*this); in >> this->oid; in >> this->overlays; in >> this->id; in >> static_cast&>(*this); return in; } /** * Write to output. * * \param out writer * \return writer */ virtual JWriter& write(JWriter& out) const override { out << static_cast(*this); out << this->oid; out << this->overlays; out << this->id; out << static_cast&>(*this); return out; } ClassDefOverride(JEvent, 3); protected: std::string oid; int overlays; int id; }; } #endif