#ifndef __JDETECTOR__JMODULEADDRESSMAP__ #define __JDETECTOR__JMODULEADDRESSMAP__ #include #include #include #include "JLang/JString.hh" #include "JLang/JException.hh" #include "JDetector/JPMTReadoutAddress.hh" #include "JDetector/JPMTPhysicalAddress.hh" /** * \author mdejong */ namespace JDETECTOR {} namespace JPP { using namespace JDETECTOR; } namespace JDETECTOR { using JLANG::JIndexOutOfRange; /** * Data structure to translate PMT physical to readout address. */ struct JPMTAddressTranslator : public JPMTReadoutAddress, public JPMTPhysicalAddress { /** * Constructor. * * \param readout readout address * \param address physical address */ JPMTAddressTranslator(const JPMTReadoutAddress& readout, const JPMTPhysicalAddress& address) : JPMTReadoutAddress (readout), JPMTPhysicalAddress(address) {} /** * Convert PMT address translator to string. * * \return string */ std::string toString() const { return toString("% % %"); } /** * Convert PMT address translator to string. * * The targets target in the format string fmt are * consecutively replaced by tdc, ring and position. * * \param fmt format * \param target target * \return string */ std::string toString(const std::string& fmt, const std::string target = "%") const { JLANG::JString buffer(fmt); buffer.replace(target, tdc, 1); buffer.replace(target, ring, 1); buffer.replace(target, position, 1); return buffer; } }; /** * Lookup table for PMT addresses in optical module. */ class JModuleAddressMap : public std::vector { public: /** * Default constructor. * * The list of valid PMT address translations should be build according to the detector type. * The internal router is used to convert a readout channel (TDC) to a PMT readout address. */ JModuleAddressMap() : std::vector() {} /** * Test whether index is available. * * \param index index * \return true if index is available; else false */ bool has(const int index) const { return (index >= 0 && index < (int) this->size()); } /** * Test whether TDC is available. * * \param tdc TDC * \return true if TDC is available; else false */ bool hasTDC(const int tdc) const { return (tdc >= 0 && tdc < (int) router.size() && router[tdc] != -1); } /** * Test whether PMT is available. * * \param address PMT address * \return true if PMT is available; else false */ bool hasPMT(const JPMTPhysicalAddress& address) const { using namespace std; const_iterator p = lower_bound(this->begin(), this->end(), address, less()); return (p != this->end() && *p == address); } /** * Configure internal router. */ void configure() { using namespace std; sort(this->begin(), this->end(), less()); for (const_iterator i = this->begin(); i != this->end(); ++i) { if (i->tdc >= (int) router.size()) { router.resize(i->tdc + 1, -1); } router[i->tdc] = std::distance(const_iterator(this->begin()),i); } } /** * Swap readout addresses corresponding to indices. * * \param i1 first index * \param i2 second index */ void swap(const int i1, const int i2) { std::swap(router[at(i1).tdc], router[at(i2).tdc]); std::swap(static_cast(at(i1)), static_cast(at(i2))); } /** * Swap physical addresses corresponding to TDCs. * * \param tdc1 first TDC * \param tdc2 second TDC */ void swapTDC(const int tdc1, const int tdc2) { std::swap(static_cast(at(router[tdc1])), static_cast(at(router[tdc2]))); std::swap(router[tdc1], router[tdc2]); } /** * Get PMT logical index for given TDC channel. * * \param tdc TDC * \return PMT logical index */ int getIndex(const int tdc) const { return router.at(tdc); } /** * Get PMT address translator. * * \param tdc TDC * \return PMT address translator */ const JPMTAddressTranslator& getAddressTranslator(const int tdc) const { return at(getIndex(tdc)); } /** * Get PMT physical address. * * \param tdc TDC * \return PMT physical address */ const JPMTPhysicalAddress& getPMTPhysicalAddress(const int tdc) const { return getAddressTranslator(tdc); } /** * Get PMT address translator. * * \param address PMT physical address * \return PMT address translator */ const JPMTAddressTranslator& getAddressTranslator(const JPMTPhysicalAddress& address) const { using namespace std; const_iterator p = lower_bound(this->begin(), this->end(), address, less()); if (p != this->end() && *p == address) return *p; else THROW(JIndexOutOfRange, "Invalid PMT address " << address); } /** * Get PMT readout address. * * \param address PMT physical address * \return PMT readout address */ const JPMTReadoutAddress& getPMTReadoutAddress(const JPMTPhysicalAddress& address) const { return getAddressTranslator(address); } protected: std::vector router; }; } #endif