#ifndef __JTRIGGER__JBUILDL2__ #define __JTRIGGER__JBUILDL2__ #include #include #include "JTrigger/JHitToolkit.hh" #include "JTrigger/JSuperFrame1D.hh" #include "JTrigger/JSuperFrame2D.hh" #include "JTrigger/JSuperFrameClone2D.hh" #include "JTrigger/JHit.hh" #include "JTrigger/JHitL0.hh" #include "JTrigger/JHitL2.hh" #include "JTrigger/JHitR2.hh" #include "JTrigger/JBuildHelper.hh" #include "JTrigger/JBuildL1.hh" #include "JTrigger/JTriggerParameters.hh" #include "km3net-dataformat/online/JDAQSuperFrame.hh" #include "JDetector/JModule.hh" #include "JMath/JMathToolkit.hh" /** * \author mdejong */ namespace JTRIGGER {} namespace JPP { using namespace JTRIGGER; } namespace JTRIGGER { using KM3NETDAQ::JDAQSuperFrame; using JDETECTOR::JModule; /** * Template L2 builder. * * An L2 hit is a local coincidence between two or more hits from different PMTs * within the same optical module satisfying: * - minimal number of hits requirement; * - maximal time difference between hits; and * - maximal space angle requirement between the PMT axes. */ template class JBuildL2 : public JL2Parameters, public JBuildL1, public JBuildHelper< JBuildL2 > { public: using JBuildHelper< JBuildL2 >::operator(); typedef JHit_t value_type; /** * Constructor. * * \param parameters L2 parameters */ JBuildL2(const JL2Parameters& parameters) : JL2Parameters (parameters), JBuildL1(parameters) {} /** * Build hits from calibrated data. * * Only the input hits that satisfy the predefined requirements are copied from input to output.\n * The requirements are checked using the calibrated data of each PMT inside the same module. * The input data should be time sorted. * The output data are time sorted. * * \param inputL0 input L0 data * \param inputL1 input L1 data * \param out output L2 data */ template void operator()(const JSuperFrame2D& inputL0, const std::vector & inputL1, JOutput_t out) const { const JSuperFrameClone2D clone(inputL0); for (typename std::vector::const_iterator p = inputL1.begin(); p != inputL1.end(); ++p) { clone.fast_forward(*p); if (isL2(clone,*p)) { *out = *p; ++out; } } } /** * Build hits from calibrated data. * * Only the input hits that satisfy the predefined requirements are copied from input to output.\n * The requirements are checked using the calibrated data of each PMT inside the same module. * The input data should be time sorted. * The output data are time sorted. * * \param __begin begin L0 data * \param __end end L0 data * \param inputL1 input L1 data * \param out output L2 data */ template void operator()(T __begin, T __end, const std::vector & inputL1, JOutput_t out) const { const JSuperFrameClone2D clone(__begin, __end); for (typename std::vector::const_iterator p = inputL1.begin(); p != inputL1.end(); ++p) { clone.fast_forward(*p); if (isL2(clone,*p)) { *out = *p; ++out; } } } /** * Build hits from calibrated data. * * The calibrated data of each PMT inside the optical module are used to build L2 coincidences. * The predefined requirements are then checked using the same calibrated data of each PMT. * The output data are time sorted. * * \param inputL0 input L0 data * \param out output L2 data */ template void operator()(const JSuperFrame2D& inputL0, JOutput_t out) const { bufferL1.clear(); static_cast&>(*this)(inputL0, std::back_inserter(bufferL1)); (*this)(inputL0, bufferL1, out); } /** * Build hits from DAQ data. * * The time calibration is applied and the requirements are applied to the calibrated data. * The output data are time sorted. * * \param input DAQ super frame * \param module module * \param out output L2 data */ template void operator()(const JDAQSuperFrame& input, const JModule& module, JOutput_t out) const { if (!input.empty()) { (*this)(this->demultiplex(input, module), out); } } protected: /** * Test if requirements for given hit are satisfied.\n * The internal iterators of the cloned L0 data should be set before this test operation. * * \param clone L0 data * \param hit L1 hit * \return true is L2 condition is satisfied; else false */ bool isL2(const JSuperFrameClone2D& clone, const JHit_t& hit) const { using namespace JPP; if (numberOfHits < 2) { return true; } for (typename JSuperFrameClone2D::const_iterator i = clone.begin(); i != clone.end(); ++i) { if (this->getTimeDifference(hit,*(i->get())) <= TMaxLocal_ns) { int n = 1; for (typename JSuperFrameClone2D::const_iterator j = clone.begin(); j != clone.end(); ++j) { if (i != j) { if (this->getTimeDifference(hit,*(j->get())) <= TMaxLocal_ns) { if (getDot(i->getDirection(), j->getDirection()) >= ctMin) { if (++n >= numberOfHits) { return true; } } } } } } } return false; } mutable std::vector bufferL1; }; /** * Template specialisation of L2 builder for JHitL2 data type. */ template<> class JBuildL2 : public JBuildL2, public JBuildHelper< JBuildL2 > { public: using JBuildHelper< JBuildL2 >::operator(); typedef JHitL2 value_type; /** * Constructor. * * \param parameters L2 parameters */ JBuildL2(const JL2Parameters& parameters) : JBuildL2(parameters) {} /** * Build hits from calibrated data. * * Only the input hits that satify the predefined requirements are copied from input to output. * The requirements are checked using the calibrated data of each PMT inside the same module. * The input data should be time sorted. * The output data are time sorted. * * \param inputL0 input L0 data * \param inputL2 input L2 data * \param out output L2 data */ template void operator()(const JSuperFrame2D& inputL0, const std::vector & inputL2, JOutput_t out) const { const JSuperFrameClone2D clone(inputL0); for (typename std::vector::const_iterator p = inputL2.begin(); p != inputL2.end(); ++p) { JHitL2 hit(inputL0.getModuleID()); for (typename JSuperFrameClone2D::const_iterator i = clone.begin(); i != clone.end(); ++i) { for (typename JSuperFrameClone2D::value_type::const_iterator q = i->fast_forward(*p); this->getTimeDifference(*p,*q) <= TMaxLocal_ns; ++q) { hit.push_back(JHitL0(i->getPMTIdentifier(), i->getAxis(), *q)); } } *out = hit.sort(); ++out; } } /** * Build hits from calibrated data. * * The calibrated data of each PMT inside the optical module are used to build L2 coincidences. * The predefined requirements are then checked using the same calibrated data of each PMT. * The output data are time sorted. * * \param inputL0 input L0 data * \param out output L2 data */ template void operator()(const JSuperFrame2D& inputL0, JOutput_t out) const { bufferL2.clear(); static_cast&>(*this)(inputL0, std::back_inserter(bufferL2)); (*this)(inputL0, bufferL2, out); } /** * Build hits from DAQ data. * * The time calibration is applied and the requirements are applied to the calibrated data. * The output data are time sorted. * * \param input DAQ super frame * \param module module * \param out output L2 data */ template void operator()(const JDAQSuperFrame& input, const JModule& module, JOutput_t out) const { if (!input.empty()) { const JSuperFrame2D& bufferL0 = this->demultiplex(input, module); (*this)(bufferL0, out); } } protected: mutable std::vector bufferL2; }; /** * Template specialisation of L2 builder for JHitR2 data type. */ template<> class JBuildL2 : public JBuildL2, public JBuildHelper< JBuildL2 > { public: using JBuildHelper< JBuildL2 >::operator(); typedef JHitR2 value_type; /** * Constructor. * * \param parameters L2 parameters */ JBuildL2(const JL2Parameters& parameters) : JBuildL2(parameters) {} /** * Build hits from calibrated data. * * Only the input hits that satify the predefined requirements are copied from input to output. * The requirements are checked using the calibrated data of each PMT inside the same module. * The input data should be time sorted. * The output data are time sorted. * * \param inputL0 input L0 data * \param inputL2 input L2 data * \param out output L2 data */ template void operator()(const JSuperFrame2D& inputL0, const std::vector & inputL2, JOutput_t out) const { const JSuperFrameClone2D clone(inputL0); for (typename std::vector::const_iterator p = inputL2.begin(); p != inputL2.end(); ++p) { JHitR2 hit(inputL0.getModuleID(), inputL0.getPosition()); clone.fast_forward(*p); for (typename JSuperFrameClone2D::const_iterator i = clone.begin(); i != clone.end(); ++i) { if (i->getTimeDifference(*p) <= TMaxLocal_ns) { if (hit.getN() == 0) hit.set(i->getJHit()); else hit.add(i->getJHit()); if (i->getT() < hit.getT()) { hit.setPosition(i->getPosition()); } } } *out = hit; ++out; } } /** * Build hits from calibrated data. * * The calibrated data of each PMT inside the optical module are used to build L2 coincidences. * The predefined requirements are then checked using the same calibrated data of each PMT. * The output data are time sorted. * * \param inputL0 input L0 data * \param out output L2 data */ template void operator()(const JSuperFrame2D& inputL0, JOutput_t out) const { bufferL2.clear(); static_cast&>(*this)(inputL0, std::back_inserter(bufferL2)); (*this)(inputL0, bufferL2, out); } /** * Build hits from DAQ data. * * The time calibration is applied and the requirements are applied to the calibrated data. * The output data are time sorted. * * \param input DAQ super frame * \param module module * \param out output L2 data */ template void operator()(const JDAQSuperFrame& input, const JModule& module, JOutput_t out) const { if (!input.empty()) { const JSuperFrame2D& bufferL0 = this->demultiplex(input, module); (*this)(bufferL0, out); } } private: mutable std::vector bufferL2; }; } #endif