CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
PFBlockAlgo.cc
Go to the documentation of this file.
7 
9 
10 #include <stdexcept>
11 #include "TMath.h"
12 
13 using namespace std;
14 using namespace reco;
15 
16 #define INIT_ENTRY(name) {#name,name}
17 
18 //for debug only
19 //#define PFLOW_DEBUG
20 
22  blocks_( new reco::PFBlockCollection ),
23  debug_(false),
24  _elementTypes( {
25  INIT_ENTRY(PFBlockElement::TRACK),
26  INIT_ENTRY(PFBlockElement::PS1),
27  INIT_ENTRY(PFBlockElement::PS2),
30  INIT_ENTRY(PFBlockElement::GSF),
31  INIT_ENTRY(PFBlockElement::BREM),
32  INIT_ENTRY(PFBlockElement::HFEM),
33  INIT_ENTRY(PFBlockElement::HFHAD),
34  INIT_ENTRY(PFBlockElement::SC),
35  INIT_ENTRY(PFBlockElement::HO)
36  } ) {}
37 
38 void PFBlockAlgo::setLinkers(const std::vector<edm::ParameterSet>& confs) {
39  constexpr unsigned rowsize = reco::PFBlockElement::kNBETypes;
40  _linkTests.resize(rowsize*rowsize);
41  const std::string prefix("PFBlockElement::");
42  const std::string pfx_kdtree("KDTree");
43  for( const auto& conf : confs ) {
44  const std::string& linkerName =
45  conf.getParameter<std::string>("linkerName");
46  const std::string& linkTypeStr =
47  conf.getParameter<std::string>("linkType");
48  size_t split = linkTypeStr.find(':');
49  if( split == std::string::npos ) {
50  throw cms::Exception("MalformedLinkType")
51  << "\"" << linkTypeStr << "\" is not a valid link type definition."
52  << " This string should have the form \"linkFrom:linkTo\"";
53  }
54  std::string link1(prefix+linkTypeStr.substr(0,split));
55  std::string link2(prefix+linkTypeStr.substr(split+1,std::string::npos));
56  if( !(_elementTypes.count(link1) && _elementTypes.count(link2) ) ) {
57  throw cms::Exception("InvalidBlockElementType")
58  << "One of \"" << link1 << "\" or \"" << link2
59  << "\" are invalid block element types!";
60  }
61  const PFBlockElement::Type type1 = _elementTypes.at(link1);
62  const PFBlockElement::Type type2 = _elementTypes.at(link2);
63  const unsigned index = rowsize*std::max(type1,type2)+std::min(type1,type2);
64  BlockElementLinkerBase * linker =
65  BlockElementLinkerFactory::get()->create(linkerName,conf);
66  _linkTests[index].reset(linker);
67  // setup KDtree if requested
68  const bool useKDTree = conf.getParameter<bool>("useKDTree");
69  if( useKDTree ) {
70  _kdtrees.emplace_back( KDTreeLinkerFactory::get()->create(pfx_kdtree+
71  linkerName) );
72  _kdtrees.back()->setTargetType(std::min(type1,type2));
73  _kdtrees.back()->setFieldType(std::max(type1,type2));
74  }
75  }
76 }
77 
78 void PFBlockAlgo::setImporters(const std::vector<edm::ParameterSet>& confs,
79  edm::ConsumesCollector& sumes) {
80  _importers.reserve(confs.size());
81  for( const auto& conf : confs ) {
82  const std::string& importerName =
83  conf.getParameter<std::string>("importerName");
84  BlockElementImporterBase * importer =
85  BlockElementImporterFactory::get()->create(importerName,conf,sumes);
86  _importers.emplace_back(importer);
87  }
88 }
89 
91 
92 #ifdef PFLOW_DEBUG
93  if(debug_)
94  cout<<"~PFBlockAlgo - number of remaining elements: "
95  <<elements_.size()<<endl;
96 #endif
97 }
98 
99 void
101  // Glowinski & Gouzevitch
102  for( const auto& kdtree : _kdtrees ) {
103  kdtree->process();
104  }
105  // !Glowinski & Gouzevitch
106  // the blocks have not been passed to the event, and need to be cleared
107  if( blocks_.get() ) blocks_->clear();
108  else blocks_.reset( new reco::PFBlockCollection );
109  blocks_->reserve(elements_.size());
110  for(IE ie = elements_.begin();
111  ie != elements_.end();) {
112 
113 #ifdef PFLOW_DEBUG
114  if(debug_) {
115  cout<<" PFBlockAlgo::findBlocks() ----------------------"<<endl;
116  cout<<" element "<<**ie<<endl;
117  cout<<" creating new block"<<endl;
118  }
119 #endif
120 
121  blocks_->push_back( reco::PFBlock() );
122 
123  std::unordered_map<std::pair<size_t,size_t>, PFBlockLink > links;
124  links.reserve(elements_.size());
125 
126  ie = associate(elements_, links, blocks_->back());
127 
128  packLinks( blocks_->back(), links );
129  }
130  //std::cout << "(new) Found " << blocks_->size() << " PFBlocks!" << std::endl;
131 }
132 
133 // start from first element in elements_
134 // partition elements until block grows no further
135 // return the start of the new block
138  std::unordered_map<std::pair<size_t,size_t>,PFBlockLink>& links,
139  reco::PFBlock& block) {
140  if( elems.size() == 0 ) return elems.begin();
141  ElementList::iterator scan_upper(elems.begin()), search_lower(elems.begin()),
142  scan_lower(elems.begin());
143  ++scan_upper; ++search_lower;
144  double dist = -1;
146  PFBlock::LinkTest linktest = PFBlock::LINKTEST_RECHIT;
147  block.addElement(scan_lower->get()); // seed the block
148  // the terminating condition of this loop is when the next range
149  // to scan has zero length (i.e. you have found no more nearest neighbours)
150  do {
151  scan_upper = search_lower;
152  // for each element added in the previous iteration we check to see what
153  // elements are linked to it
154  for( auto comp = scan_lower; comp != scan_upper; ++comp ) {
155  // group everything that's linked to the current element:
156  // std::partition moves all elements that return true for the
157  // function defined below (a.k.a. the linking function) to the
158  // front of the range provided
159  search_lower =
160  std::partition(search_lower,elems.end(),
161  [&](ElementList::value_type& a){
162  dist = -1.0;
163  // compute linking info if it is possible
164  if( linkPrefilter(comp->get(), a.get()) ) {
165  link( comp->get(), a.get(),
166  linktype, linktest, dist );
167  }
168  if( dist >= -0.5 ) {
169  const unsigned lidx = ((*comp)->type() < a->type() ?
170  (*comp)->index() :
171  a->index() );
172  const unsigned uidx = ((*comp)->type() >= a->type() ?
173  (*comp)->index() :
174  a->index() );
175  block.addElement( a.get() );
176  links.emplace( std::make_pair(lidx,uidx),
177  PFBlockLink(linktype, linktest, dist,
178  lidx, uidx ) );
179  return true;
180  } else {
181  return false;
182  }
183  });
184  }
185  // we then update the scan range lower boundary to point to the
186  // first element that we added in this round of association
187  scan_lower = scan_upper;
188  } while( search_lower != scan_upper );
189  // return the pointer to the first element not in the PFBlock we just made
190  return elems.erase(elems.begin(),scan_upper);
191 }
192 
193 void
195  const std::unordered_map<std::pair<size_t,size_t>,PFBlockLink>& links ) const {
196 
197 
199 
200  block.bookLinkData();
201  unsigned elsize = els.size();
202  //First Loop: update all link data
203  for( unsigned i1=0; i1<elsize; ++i1 ) {
204  for( unsigned i2=0; i2<i1; ++i2 ) {
205 
206  // no reflexive link
207  //if( i1==i2 ) continue;
208 
209  double dist = -1;
210 
211  bool linked = false;
212  PFBlock::LinkTest linktest
213  = PFBlock::LINKTEST_RECHIT;
214 
215  // are these elements already linked ?
216  // this can be optimized
217  const auto link_itr = links.find(std::make_pair(i2,i1));
218  if( link_itr != links.end() ) {
219  dist = link_itr->second.dist();
220  linktest = link_itr->second.test();
221  linked = true;
222  }
223 
224  if(!linked) {
226  bool bTestLink = linkPrefilter(&els[i1], &els[i2]);
227  if (bTestLink) link( & els[i1], & els[i2], linktype, linktest, dist);
228  }
229 
230  //loading link data according to link test used: RECHIT
231  //block.setLink( i1, i2, chi2, block.linkData() );
232 #ifdef PFLOW_DEBUG
233  if( debug_ )
234  cout << "Setting link between elements " << i1 << " and " << i2
235  << " of dist =" << dist << " computed from link test "
236  << linktest << endl;
237 #endif
238  block.setLink( i1, i2, dist, block.linkData(), linktest );
239  }
240  }
241 
242 }
243 
244 // see plugins/linkers for the functions that calculate distances
245 // for each available link type
246 inline bool
248  const reco::PFBlockElement* next) const {
249  constexpr unsigned rowsize = reco::PFBlockElement::kNBETypes;
250  const PFBlockElement::Type& type1 = (last)->type();
251  const PFBlockElement::Type& type2 = (next)->type();
252  const unsigned index = rowsize*std::max(type1,type2) + std::min(type1,type2);
253  bool result = false;
254  if( index < _linkTests.size() && _linkTests[index] ) {
255  result = _linkTests[index]->linkPrefilter(last,next);
256  }
257  return result;
258 }
259 
260 inline void
262  const reco::PFBlockElement* el2,
263  PFBlockLink::Type& linktype,
264  reco::PFBlock::LinkTest& linktest,
265  double& dist) const {
266  constexpr unsigned rowsize = reco::PFBlockElement::kNBETypes;
267  dist=-1.0;
268  linktest = PFBlock::LINKTEST_RECHIT; //rechit by default
269  PFBlockElement::Type type1 = el1->type();
270  PFBlockElement::Type type2 = el2->type();
271  linktype = static_cast<PFBlockLink::Type>(1<<(type1-1)|1<<(type2-1));
272  const unsigned index = rowsize*std::max(type1,type2) + std::min(type1,type2);
273  if(debug_ ) {
274  std::cout << " PFBlockAlgo links type1 " << type1
275  << " type2 " << type2 << std::endl;
276  }
277 
278  // index is always checked in the preFilter above, no need to check here
279  dist = _linkTests[index]->testLink(el1,el2);
280 }
281 
283  for( auto& importer : _importers ) {
284  importer->updateEventSetup(es);
285  }
286 }
287 
288 // see plugins/importers and plugins/kdtrees
289 // for the definitions of available block element importers
290 // and kdtree preprocessors
291 void PFBlockAlgo::buildElements(const edm::Event& evt) {
292  // import block elements as defined in python configuration
293  for( const auto& importer : _importers ) {
294 
295  importer->importToBlock(evt,elements_);
296  }
297 
298  // -------------- Loop over block elements ---------------------
299 
300  // Here we provide to all KDTree linkers the collections to link.
301  // Glowinski & Gouzevitch
302 
303  for (ElementList::iterator it = elements_.begin();
304  it != elements_.end(); ++it) {
305  for( const auto& kdtree : _kdtrees ) {
306  if( (*it)->type() == kdtree->targetType() ) {
307  kdtree->insertTargetElt(it->get());
308  }
309  if( (*it)->type() == kdtree->fieldType() ) {
310  kdtree->insertFieldClusterElt(it->get());
311  }
312  }
313  }
314  //std::cout << "(new) imported: " << elements_.size() << " elements!" << std::endl;
315 }
316 
317 std::ostream& operator<<(std::ostream& out, const PFBlockAlgo& a) {
318  if(! out) return out;
319 
320  out<<"====== Particle Flow Block Algorithm ======= ";
321  out<<endl;
322  out<<"number of unassociated elements : "<<a.elements_.size()<<endl;
323  out<<endl;
324 
325  for(PFBlockAlgo::IEC ie = a.elements_.begin();
326  ie != a.elements_.end(); ++ie) {
327  out<<"\t"<<**ie <<endl;
328  }
329 
330 
331  // const PFBlockCollection& blocks = a.blocks();
332 
333  const std::auto_ptr< reco::PFBlockCollection >& blocks
334  = a.blocks();
335 
336  if(!blocks.get() ) {
337  out<<"blocks already transfered"<<endl;
338  }
339  else {
340  out<<"number of blocks : "<<blocks->size()<<endl;
341  out<<endl;
342 
343  for(PFBlockAlgo::IBC ib=blocks->begin();
344  ib != blocks->end(); ++ib) {
345  out<<(*ib)<<endl;
346  }
347  }
348 
349  return out;
350 }
351 
352 // a little history, ideas we may want to keep around for later
353  /*
354  // Links between the two preshower layers are not used for now - disable
355  case PFBlockLink::PS1andPS2:
356  {
357  PFClusterRef ps1ref = lowEl->clusterRef();
358  PFClusterRef ps2ref = highEl->clusterRef();
359  assert( !ps1ref.isNull() );
360  assert( !ps2ref.isNull() );
361  // PJ - 14-May-09 : A link by rechit is needed here !
362  // dist = testPS1AndPS2( *ps1ref, *ps2ref );
363  dist = -1.;
364  linktest = PFBlock::LINKTEST_RECHIT;
365  break;
366  }
367  case PFBlockLink::TRACKandPS1:
368  case PFBlockLink::TRACKandPS2:
369  {
370  //cout<<"TRACKandPS"<<endl;
371  PFRecTrackRef trackref = lowEl->trackRefPF();
372  PFClusterRef clusterref = highEl->clusterRef();
373  assert( !trackref.isNull() );
374  assert( !clusterref.isNull() );
375  // PJ - 14-May-09 : A link by rechit is needed here !
376  dist = testTrackAndPS( *trackref, *clusterref );
377  linktest = PFBlock::LINKTEST_RECHIT;
378  break;
379  }
380  // GSF Track/Brem Track and preshower cluster links are not used for now - disable
381  case PFBlockLink::PS1andGSF:
382  case PFBlockLink::PS2andGSF:
383  {
384  PFClusterRef psref = lowEl->clusterRef();
385  assert( !psref.isNull() );
386  const reco::PFBlockElementGsfTrack * GsfEl = dynamic_cast<const reco::PFBlockElementGsfTrack*>(highEl);
387  const PFRecTrack * myTrack = &(GsfEl->GsftrackPF());
388  // PJ - 14-May-09 : A link by rechit is needed here !
389  dist = testTrackAndPS( *myTrack, *psref );
390  linktest = PFBlock::LINKTEST_RECHIT;
391  break;
392  }
393  case PFBlockLink::PS1andBREM:
394  case PFBlockLink::PS2andBREM:
395  {
396  PFClusterRef psref = lowEl->clusterRef();
397  assert( !psref.isNull() );
398  const reco::PFBlockElementBrem * BremEl = dynamic_cast<const reco::PFBlockElementBrem*>(highEl);
399  const PFRecTrack * myTrack = &(BremEl->trackPF());
400  // PJ - 14-May-09 : A link by rechit is needed here !
401  dist = testTrackAndPS( *myTrack, *psref );
402  linktest = PFBlock::LINKTEST_RECHIT;
403  break;
404  }
405  */
const std::auto_ptr< reco::PFBlockCollection > & blocks() const
Definition: PFBlockAlgo.h:126
type
Definition: HCALResponse.h:21
Abstract base class for a PFBlock element (track, cluster...)
std::vector< LinkTestPtr > _linkTests
Definition: PFBlockAlgo.h:172
const std::unordered_map< std::string, reco::PFBlockElement::Type > _elementTypes
Definition: PFBlockAlgo.h:171
int ib
Definition: cuy.py:660
ElementList::const_iterator IEC
Definition: PFBlockAlgo.h:100
Type type() const
IE associate(ElementList &elems, std::unordered_map< std::pair< size_t, size_t >, PFBlockLink > &links, reco::PFBlock &)
size_type size() const
Definition: OwnVector.h:248
const edm::OwnVector< reco::PFBlockElement > & elements() const
Definition: PFBlock.h:107
std::auto_ptr< reco::PFBlockCollection > blocks_
Definition: PFBlockAlgo.h:157
const LinkData & linkData() const
Definition: PFBlock.h:112
tuple els
Definition: asciidump.py:420
std::ostream & operator<<(std::ostream &out, const ALILine &li)
Definition: ALILine.cc:187
ElementList elements_
Definition: PFBlockAlgo.h:160
ElementList::iterator IE
define these in *Fwd files in DataFormats/ParticleFlowReco?
Definition: PFBlockAlgo.h:99
void setLink(unsigned i1, unsigned i2, double dist, LinkData &linkData, LinkTest test=LINKTEST_RECHIT) const
Definition: PFBlock.cc:26
std::vector< std::unique_ptr< reco::PFBlockElement > > ElementList
Definition: PFBlockAlgo.h:94
Particle Flow Algorithm.
Definition: PFBlockAlgo.h:90
#define INIT_ENTRY(name)
Definition: PFBlockAlgo.cc:16
const T & max(const T &a, const T &b)
void addElement(reco::PFBlockElement *element)
Definition: PFBlock.cc:12
tuple result
Definition: query.py:137
void link(const reco::PFBlockElement *el1, const reco::PFBlockElement *el2, PFBlockLink::Type &linktype, reco::PFBlock::LinkTest &linktest, double &dist) const
check whether 2 elements are linked. Returns distance and linktype
void packLinks(reco::PFBlock &block, const std::unordered_map< std::pair< size_t, size_t >, PFBlockLink > &links) const
std::vector< KDTreePtr > _kdtrees
Definition: PFBlockAlgo.h:174
void updateEventSetup(const edm::EventSetup &)
void setImporters(const std::vector< edm::ParameterSet > &, edm::ConsumesCollector &)
Container::value_type value_type
std::vector< PFBlock > PFBlockCollection
collection of PFBlock objects
Definition: PFBlockFwd.h:11
void bookLinkData()
Definition: PFBlock.cc:20
tuple conf
Definition: dbtoconf.py:185
tuple out
Definition: dbtoconf.py:99
reco::PFBlockCollection::const_iterator IBC
Definition: PFBlockAlgo.h:101
list blocks
Definition: gather_cfg.py:90
bool linkPrefilter(const reco::PFBlockElement *last, const reco::PFBlockElement *next) const
Avoid to check links when not useful.
void findBlocks()
build blocks
double a
Definition: hdecay.h:121
tuple cout
Definition: gather_cfg.py:121
volatile std::atomic< bool > shutdown_flag false
void buildElements(const edm::Event &)
bool debug_
if true, debug printouts activated
Definition: PFBlockAlgo.h:163
void setLinkers(const std::vector< edm::ParameterSet > &)
double split
Definition: MVATrainer.cc:139
SurfaceDeformation * create(int type, const std::vector< double > &params)
T get(const Candidate &c)
Definition: component.h:55
#define constexpr
std::vector< ImporterPtr > _importers
Definition: PFBlockAlgo.h:168
Block of elements.
Definition: PFBlock.h:30