Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 12:52:57

0001 #ifndef DataFormats_Common_DataFrameContainer_h
0002 #define DataFormats_Common_DataFrameContainer_h
0003 
0004 #include "DataFormats/Common/interface/DataFrame.h"
0005 #include "FWCore/Utilities/interface/thread_safety_macros.h"
0006 
0007 #include <boost/iterator/transform_iterator.hpp>
0008 #include <boost/iterator/counting_iterator.hpp>
0009 
0010 #include <vector>
0011 #include <algorithm>
0012 #include <cstddef>  // for size_t
0013 #include <utility>  // for pair
0014 
0015 class TestDataFrame;
0016 
0017 template <typename DigiCollection>
0018 class TestEcalDigi;
0019 
0020 namespace edm {
0021 
0022   /** an optitimized container that linearized a "vector of vector".
0023    *  It corresponds to a set of fixed size array of 16bit words each belonging
0024    *  to a "channel" identified by an 32bit id
0025    *
0026    * FIXME interface to be finalized once use-cases fully identified
0027    *
0028    * although it can be sorted internally it is strongly adviced to
0029    * fill it already sorted....
0030    *
0031    *  NOTE: The iterator used by DataFrameContainer can not safely be used across threads, even if only call const methods
0032    */
0033   class DataFrameContainer {
0034   public:
0035     typedef unsigned int size_type;  // for persistency
0036     typedef unsigned int id_type;
0037     typedef unsigned short data_type;
0038     typedef std::vector<id_type> IdContainer;
0039     typedef std::vector<data_type> DataContainer;
0040     typedef std::vector<id_type>::iterator IdIter;
0041     typedef std::vector<data_type>::iterator DataIter;
0042     typedef std::pair<IdIter, DataIter> IterPair;
0043     typedef std::vector<id_type>::const_iterator const_IdIter;
0044     typedef std::vector<data_type>::const_iterator const_DataIter;
0045     typedef std::pair<const_IdIter, const_DataIter> const_IterPair;
0046 
0047     struct IterHelp {
0048       typedef DataFrame result_type;
0049       IterHelp(DataFrameContainer const& iv) : v(iv) {}
0050 
0051       DataFrame const& operator()(int i) const {
0052         frame.set(v, i);
0053         return frame;
0054       }
0055 
0056     private:
0057       DataFrameContainer const& v;
0058       CMS_SA_ALLOW mutable DataFrame frame;
0059     };
0060 
0061     typedef boost::transform_iterator<IterHelp, boost::counting_iterator<int> > const_iterator;
0062 
0063     DataFrameContainer() : m_subdetId(0), m_stride(0), m_ids(), m_data() {}
0064 
0065     explicit DataFrameContainer(size_t istride, int isubdet = 0, size_t isize = 0)
0066         : m_subdetId(isubdet), m_stride(istride), m_ids(isize), m_data(isize * m_stride) {}
0067 
0068     void swap(DataFrameContainer& rh) {
0069       std::swap(m_subdetId, rh.m_subdetId);
0070       std::swap(m_stride, rh.m_stride);
0071       m_ids.swap(rh.m_ids);
0072       m_data.swap(rh.m_data);
0073     }
0074 
0075     DataFrameContainer& operator=(DataFrameContainer const& rhs) {
0076       DataFrameContainer temp(rhs);
0077       this->swap(temp);
0078       return *this;
0079     }
0080 
0081     void swap(IdContainer& iic, DataContainer& idc) {
0082       m_ids.swap(iic);
0083       m_data.swap(idc);
0084     }
0085 
0086     void reserve(size_t isize) {
0087       m_ids.reserve(isize);
0088       m_data.reserve(isize * m_stride);
0089     }
0090 
0091     void resize(size_t isize) {
0092       m_ids.resize(isize);
0093       m_data.resize(isize * m_stride);
0094     }
0095 
0096     void sort();
0097 
0098     // FIXME not sure what the best way to add one cell to cont
0099     void push_back(id_type iid, data_type const* idata) {
0100       m_ids.push_back(iid);
0101       size_t cs = m_data.size();
0102       m_data.resize(m_data.size() + m_stride);
0103       std::copy(idata, idata + m_stride, m_data.begin() + cs);
0104     }
0105     //make space for it
0106     void push_back(id_type iid) {
0107       m_ids.push_back(iid);
0108       m_data.resize(m_data.size() + m_stride);
0109     }
0110     // overwrite back (very ad hoc interface...)
0111     void set_back(id_type iid, data_type const* idata) {
0112       m_ids.back() = iid;
0113       size_t cs = m_data.size() - m_stride;
0114       std::copy(idata, idata + m_stride, m_data.begin() + cs);
0115     }
0116     void set_back(id_type iid) { m_ids.back() = iid; }
0117     void set_back(data_type const* idata) {
0118       size_t cs = m_data.size() - m_stride;
0119       std::copy(idata, idata + m_stride, m_data.begin() + cs);
0120     }
0121 
0122     DataFrame back() { return DataFrame(*this, size() - 1); }
0123 
0124     void pop_back() {
0125       m_ids.resize(m_ids.size() - 1);
0126       m_data.resize(m_data.size() - m_stride);
0127     }
0128 
0129     //---------------------------------------------------------
0130 
0131     IterPair pair(size_t i) { return IterPair(m_ids.begin() + i, m_data.begin() + i * m_stride); }
0132 
0133     const_IterPair pair(size_t i) const { return const_IterPair(m_ids.begin() + i, m_data.begin() + i * m_stride); }
0134 
0135     DataFrame operator[](size_t i) { return DataFrame(*this, i); }
0136 
0137     DataFrame operator[](size_t i) const { return DataFrame(*this, i); }
0138 
0139     /// slow interface
0140     /// The iterator returned can not safely be used across threads
0141     const_iterator find(id_type i) const {
0142       const_IdIter p = std::lower_bound(m_ids.begin(), m_ids.end(), i);
0143       return (p == m_ids.end() || (*p) != i)
0144                  ? end()
0145                  : boost::make_transform_iterator(boost::counting_iterator<int>(p - m_ids.begin()), IterHelp(*this));
0146     }
0147 
0148     /// The iterator returned can not safely be used across threads
0149     const_iterator begin() const {
0150       return boost::make_transform_iterator(boost::counting_iterator<int>(0), IterHelp(*this));
0151     }
0152     const_iterator end() const {
0153       return boost::make_transform_iterator(boost::counting_iterator<int>(size()), IterHelp(*this));
0154     }
0155 
0156     int subdetId() const { return m_subdetId; }
0157 
0158     size_type stride() const { return m_stride; }
0159 
0160     bool empty() const { return m_ids.empty(); }
0161 
0162     size_type size() const { return m_ids.size(); }
0163 
0164     data_type operator()(size_t cell, size_t frame) const { return m_data[cell * m_stride + frame]; }
0165 
0166     data_type const* frame(size_t cell) const { return &m_data[cell * m_stride]; }
0167 
0168     id_type id(size_t cell) const { return m_ids[cell]; }
0169 
0170     IdContainer const& ids() const { return m_ids; }
0171     DataContainer const& data() const { return m_data; }
0172 
0173   private:
0174     //for testing
0175     friend class ::TestDataFrame;
0176 
0177     template <typename DigiCollection>
0178     friend class ::TestEcalDigi;
0179 
0180     // subdetector id (as returned by  DetId::subdetId())
0181     int m_subdetId;
0182 
0183     // can be a enumerator, or a template argument
0184     size_type m_stride;
0185 
0186     IdContainer m_ids;
0187     DataContainer m_data;
0188   };
0189 
0190   inline DataFrame::DataFrame(DataFrameContainer const& icont, size_type i)
0191       : m_id(icont.id(i)), m_data(icont.frame(i)), m_size(icont.stride()) {}
0192 
0193   inline void DataFrame::set(DataFrameContainer const& icont, size_type i) {
0194     m_id = icont.id(i);
0195     m_data = icont.frame(i);
0196     m_size = icont.stride();
0197   }
0198 
0199   // Free swap function
0200   inline void swap(DataFrameContainer& lhs, DataFrameContainer& rhs) { lhs.swap(rhs); }
0201 
0202 }  // namespace edm
0203 
0204 // The standard allows us to specialize std::swap for non-templates.
0205 // This ensures that DataFrameContainer::swap() will be used in algorithms.
0206 
0207 namespace std {
0208   template <>
0209   inline void swap(edm::DataFrameContainer& lhs, edm::DataFrameContainer& rhs) {
0210     lhs.swap(rhs);
0211   }
0212 }  // namespace std
0213 
0214 #endif  // DataFormats_Common_DataFrameContainer_h