CMS 3D CMS Logo

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