Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:03:50

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     void swap(IdContainer& iic, DataContainer& idc) {
0076       m_ids.swap(iic);
0077       m_data.swap(idc);
0078     }
0079 
0080     void reserve(size_t isize) {
0081       m_ids.reserve(isize);
0082       m_data.reserve(isize * m_stride);
0083     }
0084 
0085     void resize(size_t isize) {
0086       m_ids.resize(isize);
0087       m_data.resize(isize * m_stride);
0088     }
0089 
0090     void sort();
0091 
0092     // FIXME not sure what the best way to add one cell to cont
0093     void push_back(id_type iid, data_type const* idata) {
0094       m_ids.push_back(iid);
0095       size_t cs = m_data.size();
0096       m_data.resize(m_data.size() + m_stride);
0097       std::copy(idata, idata + m_stride, m_data.begin() + cs);
0098     }
0099     //make space for it
0100     void push_back(id_type iid) {
0101       m_ids.push_back(iid);
0102       m_data.resize(m_data.size() + m_stride);
0103     }
0104     // overwrite back (very ad hoc interface...)
0105     void set_back(id_type iid, data_type const* idata) {
0106       m_ids.back() = iid;
0107       size_t cs = m_data.size() - m_stride;
0108       std::copy(idata, idata + m_stride, m_data.begin() + cs);
0109     }
0110     void set_back(id_type iid) { m_ids.back() = iid; }
0111     void set_back(data_type const* idata) {
0112       size_t cs = m_data.size() - m_stride;
0113       std::copy(idata, idata + m_stride, m_data.begin() + cs);
0114     }
0115 
0116     DataFrame back() { return DataFrame(*this, size() - 1); }
0117 
0118     void pop_back() {
0119       m_ids.resize(m_ids.size() - 1);
0120       m_data.resize(m_data.size() - m_stride);
0121     }
0122 
0123     //---------------------------------------------------------
0124 
0125     IterPair pair(size_t i) { return IterPair(m_ids.begin() + i, m_data.begin() + i * m_stride); }
0126 
0127     const_IterPair pair(size_t i) const { return const_IterPair(m_ids.begin() + i, m_data.begin() + i * m_stride); }
0128 
0129     DataFrame operator[](size_t i) { return DataFrame(*this, i); }
0130 
0131     DataFrame operator[](size_t i) const { return DataFrame(*this, i); }
0132 
0133     /// slow interface
0134     /// The iterator returned can not safely be used across threads
0135     const_iterator find(id_type i) const {
0136       const_IdIter p = std::lower_bound(m_ids.begin(), m_ids.end(), i);
0137       return (p == m_ids.end() || (*p) != i)
0138                  ? end()
0139                  : boost::make_transform_iterator(boost::counting_iterator<int>(p - m_ids.begin()), IterHelp(*this));
0140     }
0141 
0142     /// The iterator returned can not safely be used across threads
0143     const_iterator begin() const {
0144       return boost::make_transform_iterator(boost::counting_iterator<int>(0), IterHelp(*this));
0145     }
0146     const_iterator end() const {
0147       return boost::make_transform_iterator(boost::counting_iterator<int>(size()), IterHelp(*this));
0148     }
0149 
0150     int subdetId() const { return m_subdetId; }
0151 
0152     size_type stride() const { return m_stride; }
0153 
0154     bool empty() const { return m_ids.empty(); }
0155 
0156     size_type size() const { return m_ids.size(); }
0157 
0158     data_type operator()(size_t cell, size_t frame) const { return m_data[cell * m_stride + frame]; }
0159 
0160     data_type const* frame(size_t cell) const { return &m_data[cell * m_stride]; }
0161 
0162     id_type id(size_t cell) const { return m_ids[cell]; }
0163 
0164     IdContainer const& ids() const { return m_ids; }
0165     DataContainer const& data() const { return m_data; }
0166 
0167   private:
0168     //for testing
0169     friend class ::TestDataFrame;
0170 
0171     template <typename DigiCollection>
0172     friend class ::TestEcalDigi;
0173 
0174     // subdetector id (as returned by  DetId::subdetId())
0175     int m_subdetId;
0176 
0177     // can be a enumerator, or a template argument
0178     size_type m_stride;
0179 
0180     IdContainer m_ids;
0181     DataContainer m_data;
0182   };
0183 
0184   inline DataFrame::DataFrame(DataFrameContainer const& icont, size_type i)
0185       : m_id(icont.id(i)), m_data(icont.frame(i)), m_size(icont.stride()) {}
0186 
0187   inline void DataFrame::set(DataFrameContainer const& icont, size_type i) {
0188     m_id = icont.id(i);
0189     m_data = icont.frame(i);
0190     m_size = icont.stride();
0191   }
0192 
0193   // Free swap function
0194   inline void swap(DataFrameContainer& lhs, DataFrameContainer& rhs) { lhs.swap(rhs); }
0195 
0196 }  // namespace edm
0197 
0198 #endif  // DataFormats_Common_DataFrameContainer_h