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