13 #include <type_traits> 19 #define INIT_ENTRY(name) {#name,name} 23 std::vector<unsigned> id_;
24 std::vector<unsigned> size_;
28 QuickUnion(
const unsigned NBranches) {
30 id_.resize(NBranches);
31 size_.resize(NBranches);
32 for(
unsigned i = 0;
i < NBranches; ++
i ) {
38 int count()
const {
return count_; }
40 unsigned find(
unsigned p) {
41 while( p != id_[p] ) {
48 bool connected(
unsigned p,
unsigned q) {
return find(p) ==
find(q); }
50 void unite(
unsigned p,
unsigned q) {
51 unsigned rootP =
find(p);
52 unsigned rootQ =
find(q);
55 if(size_[rootP] < size_[rootQ] ) {
56 id_[rootP] = rootQ; size_[rootQ] += size_[rootP];
58 id_[rootQ] = rootP; size_[rootP] += size_[rootQ];
88 for(
unsigned i = 0;
i < rowsize; ++
i ) {
89 for(
unsigned j = 0; j < rowsize; ++j ) {
97 for(
const auto& conf : confs ) {
102 size_t split = linkTypeStr.find(
':');
103 if( split == std::string::npos ) {
105 <<
"\"" << linkTypeStr <<
"\" is not a valid link type definition." 106 <<
" This string should have the form \"linkFrom:linkTo\"";
108 std::string link1(prefix+linkTypeStr.substr(0,split));
109 std::string link2(prefix+linkTypeStr.substr(split+1,std::string::npos));
112 <<
"One of \"" << link1 <<
"\" or \"" << link2
113 <<
"\" are invalid block element types!";
122 const bool useKDTree = conf.getParameter<
bool>(
"useKDTree");
126 kdtrees_.back()->setTargetType(std::min(type1,type2));
135 for(
const auto& conf : confs ) {
146 cout<<
"~PFBlockAlgo - number of remaining elements: " 153 for(
const auto& kdtree :
kdtrees_ ) {
163 for(
unsigned i = 0;
i < elem_size; ++
i ) {
164 for(
unsigned j = 0; j < elem_size; ++j ) {
165 if( qu.connected(
i,j) || j ==
i )
continue;
184 std::unordered_multimap<unsigned,unsigned> blocksmap(
elements_.size());
185 std::vector<unsigned>
keys;
189 while( key != qu.find(key) ) key = qu.find(key);
190 auto pos = std::lower_bound(keys.begin(),keys.end(),
key);
192 keys.insert(
pos,key);
194 blocksmap.emplace(key,
i);
197 for(
auto key : keys ) {
199 auto range = blocksmap.equal_range(
key);
200 auto& the_block = blocks.back();
201 ElementList::value_type::pointer
p1(
elements_[range.first->second].get());
202 the_block.addElement(
p1);
203 const unsigned block_size = blocksmap.count(
key) + 1;
205 std::unordered_map<std::pair<unsigned int,unsigned int>,
double > links(
min(1000000u,block_size*block_size));
206 auto itr = range.first;
208 for( ; itr != range.second; ++itr ) {
209 ElementList::value_type::pointer
p2(
elements_[itr->second].get());
212 the_block.addElement(
p2);
216 links.emplace( std::make_pair(
p1->index(),
p2->index()), dist );
229 const std::unordered_map<std::pair<unsigned int,unsigned int>,
double>& links )
const {
235 unsigned elsize = els.
size();
237 for(
unsigned i1=0; i1<elsize; ++i1 ) {
238 for(
unsigned i2=0; i2<i1; ++i2 ) {
249 const auto link_itr = links.find(std::make_pair(i2,i1));
250 if( link_itr != links.end() ) {
251 dist = link_itr->second;
258 const auto minmax = std::minmax(type1,type2);
259 const unsigned index = rowsize*minmax.second + minmax.first;
261 if (bTestLink)
link( & els[i1], & els[i2], dist);
275 double& dist)
const {
282 std::cout <<
" PFBlockAlgo links type1 " << type1
283 <<
" type2 " << type2 << std::endl;
292 importer->updateEventSetup(es);
301 ranges_.fill(std::make_pair(0,0));
308 [](
const auto&
a,
const auto&
b) {
return a->type() <
b->type(); } );
313 ranges_[current_type].first = 0;
317 if( the_type != current_type ) {
320 current_type = the_type;
328 for (ElementList::iterator it =
elements_.begin();
330 for(
const auto& kdtree :
kdtrees_ ) {
331 if( (*it)->type() == kdtree->targetType() ) {
332 kdtree->insertTargetElt(it->get());
334 if( (*it)->type() == kdtree->fieldType() ) {
335 kdtree->insertFieldClusterElt(it->get());
343 if(! out)
return out;
345 out<<
"====== Particle Flow Block Algorithm ======= ";
347 out<<
"number of unassociated elements : "<<a.
elements_.size()<<endl;
351 out<<
"\t"<< *element <<endl;
Abstract base class for a PFBlock element (track, cluster...)
def create(alignables, pedeDump, additionalData, outputFile, config)
friend std::ostream & operator<<(std::ostream &, const PFBlockAlgo &)
const edm::OwnVector< reco::PFBlockElement > & elements() const
const LinkData & linkData() const
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
void setLink(unsigned i1, unsigned i2, double dist, LinkData &linkData, LinkTest test=LINKTEST_RECHIT) const
const std::unordered_map< std::string, reco::PFBlockElement::Type > elementTypes_
std::vector< std::unique_ptr< KDTreeLinkerBase > > kdtrees_
void updateEventSetup(const edm::EventSetup &)
void setImporters(const std::vector< edm::ParameterSet > &, edm::ConsumesCollector &)
std::vector< PFBlock > PFBlockCollection
collection of PFBlock objects
void packLinks(reco::PFBlock &block, const std::unordered_map< std::pair< unsigned int, unsigned int >, double > &links) const
std::vector< std::unique_ptr< BlockElementLinkerBase > > linkTests_
unsigned int linkTestSquare_[reco::PFBlockElement::kNBETypes][reco::PFBlockElement::kNBETypes]
void link(const reco::PFBlockElement *el1, const reco::PFBlockElement *el2, double &dist) const
check whether 2 elements are linked. Returns distance
std::vector< std::unique_ptr< BlockElementImporterBase > > importers_
reco::PFBlockCollection findBlocks()
build blocks
void buildElements(const edm::Event &)
bool debug_
if true, debug printouts activated
void setLinkers(const std::vector< edm::ParameterSet > &)
T get(const Candidate &c)