LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
CMergeBookKeeper.cxx
Go to the documentation of this file.
1 #ifndef RECOTOOL_CMERGEBOOKKEEPER_CXX
2 #define RECOTOOL_CMERGEBOOKKEEPER_CXX
3 
4 #include "CMergeBookKeeper.h"
5 
6 namespace cmtool {
7 
8  CMergeBookKeeper::CMergeBookKeeper(unsigned short nclusters)
9  {
10  Reset(nclusters);
11  }
12 
13  void CMergeBookKeeper::Reset(unsigned short nclusters)
14  {
15  _prohibit_merge.clear();
16  _prohibit_merge.reserve(nclusters);
18  std::vector<unsigned short>::reserve(nclusters);
19 
20  for(size_t i=0; i<nclusters; ++i) {
21  this->push_back(i);
22  _prohibit_merge.push_back(std::vector<bool>(nclusters-i,false));
23  }
24  _out_cluster_count = nclusters;
25 
26  }
27 
28  void CMergeBookKeeper::ProhibitMerge(unsigned short index1, unsigned short index2)
29  {
30  if(index1 == index2)
31 
32  throw CMTException(Form("<<%s>> Two input clusters identical (%d)",__FUNCTION__,index1));
33 
34 
35  if( index1 >= this->size() || index2 >= this->size() )
36 
37  throw CMTException(Form("Input cluster index (%d and/or %d) out of range",index1,index2));
38 
39  auto out_index1 = this->at(index1);
40  auto out_index2 = this->at(index2);
41 
42  if(out_index1 == out_index2)
43  throw CMTException(Form("Cluster %d and %d already merged!",index1,index2));
44 
45  if(out_index2 < out_index1) std::swap(out_index1,out_index2);
46 
47  _prohibit_merge.at(out_index1).at(out_index2-out_index1) = true;
48 
49  }
50 
51  bool CMergeBookKeeper::MergeAllowed(unsigned short index1,
52  unsigned short index2)
53  {
54 
55  if(index1 == index2)
56 
57  throw CMTException(Form("<<%s>> Two input clusters identical (%d)",__FUNCTION__,index1));
58 
59 
60  if( index1 >= this->size() || index2 >= this->size() )
61 
62  throw CMTException(Form("Input cluster index (%d and/or %d) out of range",index1,index2));
63 
64  auto out_index1 = this->at(index1);
65  auto out_index2 = this->at(index2);
66 
67  if(out_index1 == out_index2) return true;
68 
69  if(out_index2 < out_index1) std::swap(out_index1,out_index2);
70 
71  return !(_prohibit_merge.at(out_index1).at(out_index2-out_index1));
72 
73  }
74 
75  void CMergeBookKeeper::Merge(unsigned short index1, unsigned short index2)
76  {
77 
78  if(index1 == index2)
79 
80  throw CMTException(Form("<<%s>> Two input clusters identical (%d)",__FUNCTION__,index1));
81 
82 
83  if( index1 >= this->size() || index2 >= this->size() )
84 
85  throw CMTException(Form("Input cluster index (%d and/or %d) out of range",index1,index2));
86 
87  auto out_index1 = this->at(index1);
88  auto out_index2 = this->at(index2);
89 
90  if(out_index1 == out_index2) return;
91 
92  if(out_index2 < out_index1) std::swap(out_index1,out_index2);
93 
94  if(_prohibit_merge.at(out_index1).at(out_index2-out_index1))
95 
96  throw CMTException(Form("Clusters (%d,%d) correspond to output (%d,%d) which is prohibited to merge",
97  index1,index2,
98  out_index1,out_index2));
99 
100  //
101  // Merge cluster indexes
102  //
103  for(auto &v : (*this)) {
104 
105  if( v == out_index1 || v == out_index2 )
106  v = out_index1;
107  else if( v > out_index2 )
108  v -= 1;
109  }
110 
111  //
112  // Merge prohibit rule
113  //
114  // (1) handle index < out_index1
115  for(size_t index=0; index < out_index1; ++index) {
116 
117  size_t tmp_out_index1 = out_index1 - index;
118  size_t tmp_out_index2 = out_index2 - index;
119 
120  _prohibit_merge.at(index).at(tmp_out_index1) = ( _prohibit_merge.at(index).at(tmp_out_index1)
121  ||
122  _prohibit_merge.at(index).at(tmp_out_index2)
123  );
124 
125  for(size_t in_index=tmp_out_index2;
126  //in_index < _prohibit_merge.at(index).size() - 1;
127  in_index < (_out_cluster_count - index - 1);
128  ++in_index) {
129 
130  /*
131  if(in_index >= (_out_cluster_count - 1 - index))
132 
133  _prohibit_merge.at(index).at(in_index) = false;
134 
135  else
136  */
137  _prohibit_merge.at(index).at(in_index) = _prohibit_merge.at(index).at(in_index+1);
138  }
139 
140  //(*_prohibit_merge.at(index).rbegin()) = false;
141  _prohibit_merge.at(index).at(_out_cluster_count - index - 1) = false;
142 
143  }
144 
145  // (2) handle index == out_index1
146  for(size_t in_index = 1;
147  //in_index < _prohibit_merge.at(out_index1).size() - 1;
148  in_index < (_out_cluster_count - out_index1 - 1);
149  ++in_index) {
150  if( (in_index + out_index1) < out_index2 ) {
151  /*
152  std::cout<<Form("Inspecting1 : (%d,%zu) to (%zu,%zu)",
153  out_index1,in_index,
154  (in_index + out_index1),(out_index2 - (in_index+out_index1)))
155  << std::endl;
156  */
157  _prohibit_merge.at(out_index1).at(in_index) = ( _prohibit_merge.at(out_index1).at(in_index)
158  ||
159  _prohibit_merge.at(in_index + out_index1).at(out_index2 - (in_index+out_index1))
160  );
161  }
162  else {
163  /*
164  std::cout<<Form("Inspecting2 : (%d,%zu) to (%d,%zu) ...",
165  out_index1,in_index+1,
166  out_index2,(in_index+out_index1-out_index2));
167  if(_prohibit_merge.at(out_index1).at(in_index+1)) std::cout<<"T";
168  else std::cout<<"F";
169  std::cout<<",";
170  if(_prohibit_merge.at(out_index2).at(in_index+out_index1-out_index2)) std::cout<<"T";
171  else std::cout<<"F";
172  std::cout<<std::endl;
173  */
174  _prohibit_merge.at(out_index1).at(in_index) = ( _prohibit_merge.at(out_index1).at(in_index+1)
175  ||
176  _prohibit_merge.at(out_index2).at(in_index+1+out_index1-out_index2)
177  );
178 
179  }
180  }
181  //(*_prohibit_merge.at(out_index1).rbegin()) = false;
182  _prohibit_merge.at(out_index1).at(_out_cluster_count - out_index1 - 1) = false;
183 
184  // (3) handle out_index1 < index < out_index2
185  for(size_t index = out_index1+1;
186  index < out_index2;
187  ++index){
188  for(size_t in_index = (out_index2 - index);
189  //in_index < (_prohibit_merge.at(index).size() - 1);
190  in_index < (_out_cluster_count - index - 1);
191  ++in_index)
192 
193  _prohibit_merge.at(index).at(in_index) = _prohibit_merge.at(index).at(in_index+1);
194 
195  //(*_prohibit_merge.at(index).rbegin()) = false;
196  _prohibit_merge.at(index).at(_out_cluster_count - index - 1) = false;
197  }
198  // (4) handle out_index2 <= index
199  for(size_t index = out_index2;
200  //index < (_prohibit_merge.size() - 1);
201  index < (_out_cluster_count - 1);
202  ++index) {
203 
204  for(size_t in_index = 0;
205  in_index < _prohibit_merge.at(index).size();
206  ++in_index)
207 
208  if(in_index < _prohibit_merge.at(index+1).size())
209  _prohibit_merge.at(index).at(in_index) = _prohibit_merge.at(index+1).at(in_index);
210 
211  else
212  _prohibit_merge.at(index).at(in_index) = false;
213 
214  }
215 
216  _out_cluster_count -=1;
217 
218  }
219 
221  {
222  std::cout<<"Merge Result:"<<std::endl;
223  for(auto const& v : *this)
224  std::cout<<v<< " ";
225  std::cout<<std::endl<<std::endl;
226 
227  std::cout<<"Prohibit Status:"<<std::endl;
228  for(auto const &bs : _prohibit_merge) {
229 
230  for(auto const &b : bs) {
231 
232  if(b) std::cout<<"\033[93mT\033[00m ";
233  else std::cout<<"\033[95mF\033[00m ";
234 
235  }
236  std::cout<<std::endl;
237  }
238  std::cout<<std::endl;
239 
240  }
241 
242  bool CMergeBookKeeper::IsMerged(unsigned short index1, unsigned short index2) const
243  {
244  if( index1 >= this->size() || index2 >= this->size() )
245  throw CMTException(Form("Invalid cluster index: %d or %d",index1,index2));
246 
247  return this->at(index1) == this->at(index2);
248  }
249 
250 
251  std::vector<unsigned short> CMergeBookKeeper::GetMergedSet(unsigned short index1) const
252  {
253 
254  if( index1 >= this->size() )
255  throw CMTException(Form("Invalid cluster index: %d ",index1));
256 
257  auto out_index = this->at(index1);
258  std::vector<unsigned short> result;
259 
260  for(size_t i=0; i<this->size(); ++i)
261  if( this->at(i) == out_index ) result.push_back(i);
262 
263  return result;
264  }
265 
266  void CMergeBookKeeper::PassResult(std::vector<std::vector<unsigned short> > &result) const
267  {
268 
269  result.clear();
270  result.resize(_out_cluster_count, std::vector<unsigned short>());
271 
272  for(size_t i=0; i<this->size(); ++i)
273  result.at(this->at(i)).push_back(i);
274  }
275 
277  {
278  // Check length compatibility between this instance's result and "another"
279  std::vector<std::vector<unsigned short> > my_result;
280  this->PassResult(my_result);
281  if(my_result.size() != another.size()) {
282  throw CMTException(Form("Input has an incompatible size (%zu != %zu)",
283  my_result.size(),
284  another.size())
285  );
286  return;
287  }
288 
289  // Check if "another" result is different from input
290  std::vector<std::vector<unsigned short> > another_result;
291  another.PassResult(another_result);
292  if(another_result.size() >= my_result.size())
293  throw CMTException(Form("The input has equal or more number of output clusters (%zu>=%zu)",
294  another_result.size(),
295  my_result.size())
296  );
297 
298  // Combine
299  for(auto const& ares : another_result) {
300 
301  if(ares.size()==1) continue;
302 
303  // Get one of cluster to be used for merging
304  unsigned short target = my_result.at(ares.at(0)).at(0);
305 
306  for(auto const &res_index : ares) {
307 
308  for(auto const &orig_index : my_result.at(res_index)) {
309 
310  if(target == orig_index) continue;
311 
312  else this->Merge(target,orig_index);
313 
314  }
315 
316  }
317 
318  }
319 
320  }
321 
322 }
323 
324 #endif
cout<< "-> Edep in the target
Definition: analysis.C:54
void ProhibitMerge(unsigned short index1, unsigned short index2)
Method to set a pair of clusters to prohibit from merging.
Class def header for a class CMergeBookKeeper.
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
std::vector< unsigned short > GetMergedSet(unsigned short index1) const
CMergeBookKeeper(unsigned short nclusters=0)
Default constructor.
size_t _out_cluster_count
Number of output clusters.
std::vector< std::vector< bool > > _prohibit_merge
void Combine(const CMergeBookKeeper &another)
void Merge(unsigned short index1, unsigned short index2)
Method to merge 2 clusters via index numbers.
bool MergeAllowed(unsigned short index1, unsigned short index2)
Method to inqury if a combination is prohibited to merge.
void PassResult(std::vector< std::vector< unsigned short > > &result) const
bool IsMerged(unsigned short index1, unsigned short index2) const
vec_iX clear()
void Reset(unsigned short nclusters=0)
Reset method.