CMS 3D CMS Logo

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

Generated on Tue Jun 9 17:28:50 2009 for CMSSW by  doxygen 1.5.4