CMS 3D CMS Logo

CMSSW_4_4_3_patch1/src/DataFormats/Common/interface/DetSetVectorNew.h

Go to the documentation of this file.
00001 #ifndef DataFormats_Common_DetSetVectorNew_h
00002 #define DataFormats_Common_DetSetVectorNew_h
00003 
00004 #include "DataFormats/Common/interface/CMS_CLASS_VERSION.h"
00005 // #include "DataFormats/Common/interface/DetSet.h"  // to get det_id_type
00006 #include "DataFormats/Common/interface/DetSetNew.h"
00007 #include "DataFormats/Common/interface/traits.h"
00008 
00009 #include <boost/iterator_adaptors.hpp>
00010 #include <boost/iterator/transform_iterator.hpp>
00011 #include <boost/iterator/counting_iterator.hpp>
00012 #include <boost/any.hpp>
00013 #include "boost/shared_ptr.hpp"
00014 
00015 
00016 #include<vector>
00017 
00018 namespace edm { namespace refhelper { template<typename T> struct FindForNewDetSetVector; } }
00019 
00020 //FIXME remove New when ready
00021 namespace edmNew {
00022   typedef uint32_t det_id_type;
00023 
00024   namespace dslv {
00025     template< typename T> class LazyGetter;
00026   }
00027 
00028   /* transient component of DetSetVector
00029    * for pure conviniency of dictioanary declaration
00030    */
00031   namespace dstvdetails {
00032     struct DetSetVectorTrans {
00033       DetSetVectorTrans(): filling(false){}
00034       bool filling;
00035       boost::any getter;
00036 
00037       typedef unsigned int size_type; // for persistency
00038       typedef unsigned int id_type;
00039 
00040       struct Item {
00041         Item(id_type i=0, int io=-1, size_type is=0) : id(i), offset(io), size(is){}
00042         id_type id;
00043         int offset;
00044         size_type size;
00045         bool operator<(Item const &rh) const { return id<rh.id;}
00046         operator id_type() const { return id;}
00047       };
00048 
00049     };
00050     void errorFilling();
00051     void errorIdExists(det_id_type iid);
00052     void throw_range(det_id_type iid);
00053    }
00054 
00065   template<typename T>
00066   class DetSetVector  : private dstvdetails::DetSetVectorTrans {
00067   public:
00068     typedef dstvdetails::DetSetVectorTrans Trans;
00069     typedef Trans::Item Item;
00070     typedef unsigned int size_type; // for persistency
00071     typedef unsigned int id_type;
00072     typedef T data_type;
00073     typedef edmNew::DetSetVector<T> self;
00074     typedef edmNew::DetSet<T> DetSet;
00075     typedef dslv::LazyGetter<T> Getter;
00076     // FIXME not sure make sense....
00077     typedef DetSet value_type;
00078     typedef id_type key_type;
00079 
00080 
00081     typedef std::vector<Item> IdContainer;
00082     typedef std::vector<data_type> DataContainer;
00083     typedef typename IdContainer::iterator IdIter;
00084     typedef typename std::vector<data_type>::iterator DataIter;
00085     typedef std::pair<IdIter,DataIter> IterPair;
00086     typedef typename IdContainer::const_iterator const_IdIter;
00087     typedef typename std::vector<data_type>::const_iterator const_DataIter;
00088     typedef std::pair<const_IdIter,const_DataIter> const_IterPair;
00089 
00090     typedef typename edm::refhelper::FindForNewDetSetVector<data_type>  RefFinder;
00091     
00092     struct IterHelp {
00093       typedef DetSet result_type;
00094       IterHelp() : v(0){}
00095       IterHelp(DetSetVector<T> const & iv) : v(&iv){}
00096       
00097        result_type & operator()(Item const& item) const {
00098         detset.set(*v,item);
00099         return detset;
00100       } 
00101     private:
00102       DetSetVector<T> const * v;
00103       mutable result_type detset;
00104     };
00105     
00106     typedef boost::transform_iterator<IterHelp,const_IdIter> const_iterator;
00107     typedef std::pair<const_iterator,const_iterator> Range;
00108 
00109     /* fill the lastest inserted DetSet
00110      */
00111     class FastFiller {
00112     public:
00113       typedef typename DetSetVector<T>::data_type value_type;
00114       typedef typename DetSetVector<T>::id_type key_type;
00115       typedef typename DetSetVector<T>::id_type id_type;
00116       typedef typename DetSetVector<T>::size_type size_type;
00117 
00118       FastFiller(DetSetVector<T> & iv, id_type id, bool isaveEmpty=false) : 
00119         v(iv), item(v.push_back(id)), saveEmpty(isaveEmpty) {
00120         if (v.filling) dstvdetails::errorFilling();
00121         v.filling=true;
00122       }
00123       FastFiller(DetSetVector<T> & iv, typename DetSetVector<T>::Item & it, bool isaveEmpty=false) : 
00124         v(iv), item(it), saveEmpty(isaveEmpty) {
00125         if (v.filling) dstvdetails::errorFilling();
00126         v.filling=true;
00127       }
00128       ~FastFiller() {
00129         if (!saveEmpty && item.size==0) {
00130           v.pop_back(item.id);
00131         }
00132         v.filling=false;
00133       }
00134       
00135       void abort() {
00136         v.pop_back(item.id);
00137         saveEmpty=true; // avoid mess in destructor
00138       }
00139 
00140       void reserve(size_type s) {
00141         v.m_data.reserve(item.offset+s);
00142       }
00143 
00144       void resize(size_type s) {
00145         v.m_data.resize(item.offset+s);
00146         item.size=s;
00147       }
00148 
00149       id_type id() const { return item.id;}
00150       size_type size() const { return item.size;}
00151       bool empty() const { return item.size==0;}
00152 
00153       data_type & operator[](size_type i) {
00154         return  v.m_data[item.offset+i];
00155       }
00156       DataIter begin() { return v.m_data.begin()+ item.offset;}
00157       DataIter end() { return v.m_data.end();}
00158 
00159       void push_back(data_type const & d) {
00160         v.m_data.push_back(d);
00161         item.size++;
00162       }
00163       data_type & back() { return v.m_data.back();}
00164       
00165     private:
00166       DetSetVector<T> & v;
00167       typename DetSetVector<T>::Item & item;
00168       bool saveEmpty;
00169     };
00170     friend class FastFiller;
00171 
00172     class FindForDetSetVector : public std::binary_function<const edmNew::DetSetVector<T>&, unsigned int, const T*> {
00173     public:
00174         typedef FindForDetSetVector self;
00175         typename self::result_type operator()(typename self::first_argument_type iContainer, typename self::second_argument_type iIndex) {
00176             return &(iContainer.m_data[iIndex]);
00177         }
00178     };
00179     friend class FindForDetSetVector;
00180 
00181     explicit DetSetVector(int isubdet=0) :
00182       m_subdetId(isubdet) {}
00183 
00184     DetSetVector(boost::shared_ptr<dslv::LazyGetter<T> > iGetter, const std::vector<det_id_type>& iDets,
00185                  int isubdet=0);
00186 
00187 
00188     ~DetSetVector() {
00189       // delete content if T is pointer...
00190     }
00191     
00192     void swap(DetSetVector & rh) {
00193       std::swap(m_subdetId,rh.m_subdetId);
00194       std::swap(m_ids,rh.m_ids);
00195       std::swap(m_data,rh.m_data);
00196     }
00197     
00198     void swap(IdContainer & iic, DataContainer & idc) {
00199       std::swap(m_ids,iic);
00200       std::swap(m_data,idc);
00201     }
00202     
00203     void reserve(size_t isize, size_t dsize) {
00204       m_ids.reserve(isize);
00205       m_data.reserve(dsize);
00206     }
00207     
00208     void resize(size_t isize, size_t dsize) {
00209       m_ids.resize(isize);
00210       m_data.resize(dsize);
00211     }
00212     
00213     // FIXME not sure what the best way to add one cell to cont
00214     DetSet insert(id_type iid, data_type const * idata, size_type isize) {
00215       Item & item = addItem(iid,isize);
00216       m_data.resize(m_data.size()+isize);
00217       std::copy(idata,idata+isize,m_data.begin()+item.offset);
00218      return DetSet(*this,item);
00219     }
00220     //make space for it
00221     DetSet insert(id_type iid, size_type isize) {
00222       Item & item = addItem(iid,isize);
00223       m_data.resize(m_data.size()+isize);
00224       return DetSet(*this,item);
00225     }
00226 
00227     // to be used with a FastFiller
00228     Item & push_back(id_type iid) {
00229       return addItem(iid,0);
00230     }
00231 
00232     // remove last entry (usually only if empty...)
00233     void pop_back(id_type iid) {
00234       const_IdIter p = findItem(iid);
00235       if (p==m_ids.end()) return; //bha!
00236       // sanity checks...  (shall we throw or assert?)
00237       if ((*p).size>0&& (*p).offset>-1 && 
00238           m_data.size()==(*p).offset+(*p).size)
00239         m_data.resize((*p).offset);
00240       m_ids.erase( m_ids.begin()+(p-m_ids.begin()));
00241     }
00242 
00243   private:
00244 
00245     Item & addItem(id_type iid,  size_type isize) {
00246       Item it(iid,size_type(m_data.size()),isize);
00247       IdIter p = std::lower_bound(m_ids.begin(),
00248                                   m_ids.end(),
00249                                   it);
00250       if (p!=m_ids.end() && !(it<*p)) dstvdetails::errorIdExists(iid);
00251       return *m_ids.insert(p,it);
00252     }
00253 
00254 
00255 
00256   public:
00257 
00258 
00259     //---------------------------------------------------------
00260     
00261     bool exists(id_type i) const  {
00262       return  findItem(i)!=m_ids.end(); 
00263     }
00264         
00265     bool isValid(id_type i) const {
00266       const_IdIter p = findItem(i);
00267       return p!=m_ids.end() && (*p).offset!=-1;
00268     }
00269 
00270     /*
00271     DetSet operator[](id_type i) {
00272       const_IdIter p = findItem(i);
00273       if (p==m_ids.end()) what???
00274       return DetSet(*this,p-m_ids.begin());
00275     }
00276     */
00277 
00278     
00279     DetSet operator[](id_type i) const {
00280       const_IdIter p = findItem(i);
00281       if (p==m_ids.end()) dstvdetails::throw_range(i);
00282       return DetSet(*this,*p);
00283     }
00284     
00285     // slow interface
00286     const_iterator find(id_type i) const {
00287       const_IdIter p = findItem(i);
00288       return (p==m_ids.end()) ? end() :
00289         boost::make_transform_iterator(p,
00290                                        IterHelp(*this));
00291     }
00292 
00293     // slow interface
00294     const_IdIter findItem(id_type i) const {
00295       std::pair<const_IdIter,const_IdIter> p =
00296         std::equal_range(m_ids.begin(),m_ids.end(),Item(i));
00297       return (p.first!=p.second) ? p.first : m_ids.end();
00298     }
00299     
00300     const_iterator begin() const {
00301       return  boost::make_transform_iterator(m_ids.begin(),
00302                                              IterHelp(*this));
00303     }
00304 
00305     const_iterator end() const {
00306       return  boost::make_transform_iterator(m_ids.end(),
00307                                              IterHelp(*this));
00308     }
00309     
00310 
00311     // return an iterator range (implemented here to avoid dereference of detset)
00312     template<typename CMP>
00313     Range equal_range(id_type i, CMP cmp) const {
00314       std::pair<const_IdIter,const_IdIter> p =
00315         std::equal_range(m_ids.begin(),m_ids.end(),i,cmp);
00316       return  Range(boost::make_transform_iterator(p.first,IterHelp(*this)),
00317                     boost::make_transform_iterator(p.second,IterHelp(*this))
00318                     );
00319     }
00320     
00321     int subdetId() const { return m_subdetId; }
00322 
00323     bool empty() const { return m_ids.empty();}
00324 
00325 
00326     size_type dataSize() const { return m_data.size(); }
00327     
00328     size_type size() const { return m_ids.size();}
00329     
00330     //FIXME fast interfaces, not consistent with associative nature of container....
00331 
00332     data_type operator()(size_t cell, size_t frame) const {
00333       return m_data[m_ids[cell].offset+frame];
00334     }
00335     
00336     data_type const * data(size_t cell) const {
00337       return &m_data[m_ids[cell].offset];
00338     }
00339     
00340     size_type detsetSize(size_t cell) const { return  m_ids[cell].size; }
00341 
00342     id_type id(size_t cell) const {
00343       return m_ids[cell].id;
00344     }
00345 
00346     Item const & item(size_t cell) const {
00347       return m_ids[cell];
00348     }
00349 
00350     //------------------------------
00351 
00352     // IdContainer const & ids() const { return m_ids;}
00353     DataContainer const & data() const { return  m_data;}
00354 
00355 
00356     void update(Item const & item) const {
00357       const_cast<self*>(this)->updateImpl(const_cast<Item&>(item));
00358     }
00359    
00360     //Used by ROOT storage
00361     CMS_CLASS_VERSION(10)
00362 
00363   private:
00364 
00365     void updateImpl(Item & item);
00366     
00367   private:
00368     // subdetector id (as returned by  DetId::subdetId())
00369     int m_subdetId;
00370     
00371     
00372     IdContainer m_ids;
00373     DataContainer m_data;
00374     
00375   };
00376   
00377  namespace dslv {
00378     template< typename T>
00379     class LazyGetter {
00380     public:
00381       virtual ~LazyGetter() {}
00382       virtual void fill(typename DetSetVector<T>::FastFiller&) = 0;
00383     };
00384   }
00385   
00386     
00387 
00388   template<typename T>
00389   inline DetSetVector<T>::DetSetVector(boost::shared_ptr<dslv::LazyGetter<T> > iGetter, 
00390                                        const std::vector<det_id_type>& iDets,
00391                                        int isubdet):  
00392     m_subdetId(isubdet) {
00393     getter=iGetter;
00394 
00395     m_ids.reserve(iDets.size());
00396     det_id_type sanityCheck = 0;
00397     for(std::vector<det_id_type>::const_iterator itDetId = iDets.begin(), itDetIdEnd = iDets.end();
00398         itDetId != itDetIdEnd;
00399         ++itDetId) {
00400       assert(sanityCheck < *itDetId && "vector of det_id_type was not ordered");
00401       sanityCheck = *itDetId;
00402       m_ids.push_back(*itDetId);
00403     }
00404   }
00405 
00406   template<typename T>
00407   inline void DetSetVector<T>::updateImpl(Item & item)  {
00408     // no getter or already updated
00409     if (getter.empty() || item.offset!=-1) return;
00410     item.offset = int(m_data.size());
00411     FastFiller ff(*this,item);
00412     (*boost::any_cast<boost::shared_ptr<Getter> >(&getter))->fill(ff);
00413   }
00414 
00415 
00416   template<typename T>
00417   inline DetSet<T>::DetSet(DetSetVector<T> const & icont,
00418                            typename DetSetVector<T>::Item const & item ) :
00419     m_id(0), m_data(0), m_size(0){
00420     icont.update(item);
00421     set(icont,item);
00422   }
00423   
00424   
00425   template<typename T>
00426   inline void DetSet<T>::set(DetSetVector<T> const & icont,
00427                              typename Container::Item const & item) {
00428     icont.update(item);
00429     m_id=item.id; 
00430     m_data=&icont.data()[item.offset]; 
00431     m_size=item.size;
00432   }
00433   
00434 }
00435 
00436 #include "DataFormats/Common/interface/Ref.h"
00437 #include <boost/mpl/assert.hpp>
00438 #include <boost/type_traits/is_same.hpp>
00439 
00440 //specialize behavior of edm::Ref to get access to the 'Det'
00441 namespace edm {
00442     /* Reference to an item inside a new DetSetVector ... */
00443     namespace refhelper {
00444         template<typename T>
00445             struct FindTrait<typename edmNew::DetSetVector<T>,T> {
00446                 typedef typename edmNew::DetSetVector<T>::FindForDetSetVector value;
00447             };
00448     }
00449     /* ... as there was one for the original DetSetVector*/
00450 
00451     /* Probably this one is not that useful .... */
00452     namespace refhelper {
00453         template<typename T>
00454             struct FindSetForNewDetSetVector : public std::binary_function<const edmNew::DetSetVector<T>&, unsigned int, edmNew::DetSet<T> > {
00455                 typedef FindSetForNewDetSetVector<T> self;
00456                 typename self::result_type operator()(typename self::first_argument_type iContainer, typename self::second_argument_type iIndex) {
00457                     return &(iContainer[iIndex]);
00458                 }
00459             };
00460 
00461         template<typename T>
00462             struct FindTrait<edmNew::DetSetVector<T>, edmNew::DetSet<T> > {
00463                 typedef FindSetForNewDetSetVector<T> value;
00464             };
00465     }
00466     /* ... implementation is provided, just in case it's needed */
00467 }
00468 
00469 namespace edmNew {
00470    //helper function to make it easier to create a edm::Ref to a new DSV
00471   template<class HandleT>
00472   edm::Ref<typename HandleT::element_type, typename HandleT::element_type::value_type::value_type>
00473   makeRefTo(const HandleT& iHandle,
00474              typename HandleT::element_type::value_type::const_iterator itIter) {
00475     BOOST_MPL_ASSERT((boost::is_same<typename HandleT::element_type, DetSetVector<typename HandleT::element_type::value_type::value_type> >));
00476     typename HandleT::element_type::size_type index = (itIter - &*iHandle->data().begin()); 
00477     return edm::Ref<typename HandleT::element_type,
00478                typename HandleT::element_type::value_type::value_type>
00479               (iHandle,index);
00480   }
00481 }
00482 
00483 
00484 #endif
00485