ndmspc  v1.2.0-0.1.rc3
NBinning.cxx
1 #include <string>
2 #include <vector>
3 #include "TAxis.h"
4 #include <TAttAxis.h>
5 #include <TObjArray.h>
6 #include "NBinningDef.h"
7 #include "NBinningPoint.h"
8 #include "NDimensionalExecutor.h"
9 #include "NUtils.h"
10 #include "NLogger.h"
11 
12 #include "NBinning.h"
13 
15 ClassImp(Ndmspc::NBinning);
17 
18 namespace Ndmspc {
19 NBinning::NBinning() : TObject()
20 {
24 }
25 NBinning::NBinning(std::vector<TAxis *> axes) : TObject(), fAxes(axes)
26 {
30 
31  Initialize();
32 }
33 NBinning::NBinning(TObjArray * axes) : TObject()
34 {
38 
39  if (axes == nullptr) {
40  NLogError("NBinning(TObjArray * axes) : axes is nullptr");
41  return;
42  }
43 
44  for (int i = 0; i < axes->GetEntriesFast(); i++) {
45  TAxis * axis = dynamic_cast<TAxis *>(axes->At(i));
46  if (axis) {
47  fAxes.push_back((TAxis *)axis->Clone());
48  }
49  else {
50  NLogError("NBinning: Axis %d is not a TAxis", i);
51  }
52  }
53 
54  Initialize();
55 }
57 {
61 
62  // Cleanup fDefinitions
63  for (auto & def : fDefinitions) {
64  delete def.second;
65  }
66  fDefinitions.clear();
67 
68  // Cleanup fAxes
69  for (auto & axis : fAxes) {
70  if (axis) {
71  delete axis; // Delete the axis if it was created by this class
72  }
73  }
74 
75  delete fMap;
76  delete fContent;
77 }
79 {
83  fMap->Reset();
84  fContent->Reset();
85  if (fPoint != nullptr) {
86  fPoint->Reset();
87  }
88 }
89 
91 {
95 
96  if (fAxes.size() == 0) {
97  NLogError("No axes provided");
98  return;
99  }
100 
101  int dim = fAxes.size();
102  // Calculate maximyn=m of nbins
103  int nbinsMax = 0;
104  int nContentDims = 0;
105  Binning binningType;
106  for (int i = 0; i < dim; i++) {
107  int nbins = fAxes[i]->GetNbins();
108  if (nbins > nbinsMax) {
109  nbinsMax = nbins;
110  }
111  // NLogDebug("Axis %d: %s nbins=%d", i, fAxes[i]->GetName(), nbins);
112  // if (nbins == 1 || axes[i]->IsAlphanumeric()) {
113  TString axisname(fAxes[i]->GetName());
114  bool isUser = axisname.Contains("/U");
115  if (isUser) {
116  axisname.ReplaceAll("/U", "");
117  fAxes[i]->SetName(axisname.Data());
118  }
119 
120  if (isUser) {
121  binningType = Binning::kUser;
122  nContentDims++;
123  }
124  else if (fAxes[i]->IsAlphanumeric()) {
125  // TODO: Optimized beiing for alphanumeric axis (maybe no need to fix)
126  // binningType = Binning::kSingle;
127  // nContentDims++;
128  binningType = Binning::kMultiple;
129  nContentDims += 3;
130  }
131  else {
132  binningType = Binning::kMultiple;
133  nContentDims += 3;
134  }
135  fBinningTypes.push_back(binningType);
136  fAxisTypes.push_back(AxisType::kFixed);
137  }
138  int dimBinning = 4;
139  Int_t * nbinsBinning = new Int_t[dimBinning];
140  Double_t * xminBinning = new Double_t[dimBinning];
141  Double_t * xmaxBinning = new Double_t[dimBinning];
142  // set first item nbinsBinning to dim min to zero and max to dim
143 
144  nbinsBinning[0] = dim;
145  xminBinning[0] = 0;
146  xmaxBinning[0] = dim;
147  for (int i = 1; i < dimBinning; i++) {
148  nbinsBinning[i] = nbinsMax;
149  xminBinning[i] = 0;
150  xmaxBinning[i] = nbinsMax;
151  }
152 
153  if (fMap) {
154  delete fMap;
155  }
156  fMap = new THnSparseI("ngntBinningMap", "NGnTree binning map", dimBinning, nbinsBinning, xminBinning, xmaxBinning);
157  if (fMap == nullptr) {
158  NLogError("Cannot create binnings !!!");
159  return;
160  }
161  fMap->GetAxis(0)->SetNameTitle("dim", "dimension");
162  fMap->GetAxis(1)->SetNameTitle("rebin", "rebins");
163  fMap->GetAxis(2)->SetNameTitle("start", "rebins start");
164  fMap->GetAxis(3)->SetNameTitle("bin", "bin id");
165 
166  for (int i = 0; i < dim; i++) {
167  fMap->GetAxis(0)->SetBinLabel(i + 1, fAxes[i]->GetName());
168  }
169 
170  int dimBinningContent = nContentDims;
171  Int_t * nbinsBinningContent = new Int_t[dimBinningContent];
172  Double_t * xminBinningContent = new Double_t[dimBinningContent];
173  Double_t * xmaxBinningContent = new Double_t[dimBinningContent];
174  int iContentDim = 0;
175  for (int i = 0; i < dim; i++) {
176  if (fBinningTypes[i] == Binning::kSingle) {
177  // NLogDebug("Binning %d: %d", i, axes[idim]->GetNbins());
178  nbinsBinningContent[iContentDim] = fAxes[i]->GetNbins();
179  xminBinningContent[iContentDim] = 0;
180  xmaxBinningContent[iContentDim] = fAxes[i]->GetNbins();
181  iContentDim++;
182  NLogTrace("[S] Binning %d: %d", i, fAxes[i]->GetNbins());
183  }
184  else if (fBinningTypes[i] == Binning::kMultiple) {
185  for (int j = 0; j < 3; j++) {
186  nbinsBinningContent[iContentDim + j] = fAxes[i]->GetNbins();
187  xminBinningContent[iContentDim + j] = 0;
188  xmaxBinningContent[iContentDim + j] = fAxes[i]->GetNbins();
189  }
190  iContentDim += 3;
191  NLogTrace("[M] Binning %d: %d", i, fAxes[i]->GetNbins());
192  }
193  else if (fBinningTypes[i] == Binning::kUser) {
194  // NLogDebug("Binning %d: %d", i, axes[idim]->GetNbins());
195  nbinsBinningContent[iContentDim] = fAxes[i]->GetNbins();
196  xminBinningContent[iContentDim] = 0;
197  xmaxBinningContent[iContentDim] = fAxes[i]->GetNbins();
198  iContentDim++;
199  NLogTrace("[U] Binning %d: %d", i, fAxes[i]->GetNbins());
200  }
201  else {
202  NLogError("Invalid binning type %d", fBinningTypes[i]);
203  return;
204  }
205  }
206  fContent = new THnSparseI("ngntBinningContent", "NGnTree binning content", dimBinningContent, nbinsBinningContent,
207  xminBinningContent, xmaxBinningContent);
208 
209  int iContentAxis = 0;
210  std::vector<std::string> types = {"rebin", "start", "bin"};
211  for (int i = 0; i < dim; i++) {
212  std::string name = fAxes[i]->GetName();
213  std::string title = fAxes[i]->GetName();
214  // NLogTrace("Binning %d: %d %d", i, axes[i]->GetNbins(), fBinningTypes[i]);
215  if (fBinningTypes[i] == Binning::kSingle) {
216  fContent->GetAxis(iContentAxis)->SetNameTitle(name.c_str(), title.c_str());
217  iContentAxis++;
218  }
219  else if (fBinningTypes[i] == Binning::kMultiple) {
220  for (int j = 0; j < 3; j++) {
221  int imod = j % 3;
222  std::string n = name + "_" + types[imod];
223  std::string t = title + " (" + types[imod] + ")";
224  fContent->GetAxis(iContentAxis)->SetNameTitle(n.c_str(), t.c_str());
225  iContentAxis++;
226  }
227  // NLogDebug("Binning %d: %d", i, axes[idim]->GetNbins());
228  }
229  else if (fBinningTypes[i] == Binning::kUser) {
230  fContent->GetAxis(iContentAxis)->SetNameTitle(name.c_str(), title.c_str());
231  iContentAxis++;
232  }
233  }
234  for (int i = 0; i < fContent->GetNdimensions(); i++) {
235  NLogTrace("Axis[fContent] %d: %s nbins=%d", i, fContent->GetAxis(i)->GetName(), fContent->GetAxis(i)->GetNbins());
236  }
237 
238  fPoint = new NBinningPoint(this);
239 
240  delete[] nbinsBinning;
241  delete[] xminBinning;
242  delete[] xmaxBinning;
243 }
244 
245 void NBinning::Print(Option_t * option) const
246 {
250 
251  if (fMap == nullptr) {
252  NLogError("THnSparse fMap is null");
253  return;
254  }
255 
256  TString opt(option);
257  opt.ToLower();
258 
259  NLogInfo("NBinning base axes:");
260  for (size_t i = 0; i < fAxes.size(); i++) {
261  NLogInfo(" Axis %d: name='%s' title='%s' nbins=%d min=%.3f max=%.3f", i, fAxes[i]->GetName(), fAxes[i]->GetTitle(),
262  fAxes[i]->GetNbins(), fAxes[i]->GetXmin(), fAxes[i]->GetXmax());
263  }
264 
265  if (opt.Contains("A")) {
266  NLogInfo("NBinning map name='%s' title='%s'", fMap->GetName(), fMap->GetTitle());
267  NLogInfo(" dimensions: %d", fMap->GetNdimensions());
268  // loop over all axes and print name title
269  for (int i = 0; i < fMap->GetNdimensions(); i++) {
270  NLogInfo(" [%d] name='%s' title='%s' nbins=%d min=%.3f max=%.3f", i, fMap->GetAxis(i)->GetName(),
271  fMap->GetAxis(i)->GetTitle(), fMap->GetAxis(i)->GetNbins(), fMap->GetAxis(i)->GetXmin(),
272  fMap->GetAxis(i)->GetXmax());
273  }
274  NLogInfo(" filled bins = %lld", fMap->GetNbins());
275  NLogInfo("NBinning content name='%s' title='%s'", fContent->GetName(), fContent->GetTitle());
276  NLogInfo(" dimensions: %d", fContent->GetNdimensions());
277  // loop over all axes and print name title
278  for (int i = 0; i < fContent->GetNdimensions(); i++) {
279  NLogInfo(" [%d] name='%s' title='%s' nbins=%d min=%.3f max=%.3f", i, fContent->GetAxis(i)->GetName(),
280  fContent->GetAxis(i)->GetTitle(), fContent->GetAxis(i)->GetNbins(), fContent->GetAxis(i)->GetXmin(),
281  fContent->GetAxis(i)->GetXmax());
282  }
283  }
284  NLogInfo("NBinning content:");
285  NLogInfo(" filled bins = %lld", fContent->GetNbins());
286  // print list of definitions names from fDefinitions
287  NLogInfo("NBinning definitions:");
288  for (const auto & kv : fDefinitions) {
289  if (kv.first == fCurrentDefinitionName) {
290  NLogInfo(" '%s' (current)", kv.first.c_str());
291  }
292  else {
293  NLogInfo(" '%s'", kv.first.c_str());
294  }
295  }
296 
297  if (option && opt.Contains("all")) {
298  NLogInfo("NBinning content:");
299  PrintContent(option);
300  }
301 
302  // // loop over definition and print
303  // for (const auto & kv : fDefinition) {
304  // NLogInfo("Binning '%s':", kv.first.c_str());
305  // for (const auto & v : kv.second) {
306  // NLogInfo(" %s", NUtils::GetCoordsString(v, -1).c_str());
307  // }
308  // }
309 
310  // fMap->Print(option);
311 
312  // // Using executor print all bins
313  // NDimensionalExecutor executor(fMap, true);
314  // // NDimensionalExecutor executor(fMap, false);
315  // auto binning_task = [this, &all_bins](const std::vector<int> & coords) {
316  // fMap->Print();
317  // NUtils::PrintPointSafe(coords, -1);
318  // };
319  //
320  // executor.Execute(binning_task);
321 
322  // size_t num_threads_to_use = 0;
323  // // set num_threads_to_use to the number of available threads
324  // if (num_threads_to_use < 1) num_threads_to_use = std::thread::hardware_concurrency();
325  // NLogInfo("Using %zu threads ...", num_threads_to_use);
326  // std::vector<NThreadData> thread_data_vector(num_threads_to_use);
327  // for (size_t i = 0; i < thread_data_vector.size(); ++i) {
328  // thread_data_vector[i].SetAssignedIndex(i);
329  // }
330  //
331  // // 2. Define the lambda (type in signature updated)
332  // auto parallel_task = [](const std::vector<int> & coords, NThreadData & thread_obj) {
333  // NUtils::PrintPointSafe(coords, thread_obj.GetAssignedIndex());
334  // thread_obj.Process(coords);
335  // // thread_obj.Print();
336  // };
337  //
338  // // 3. Call ExecuteParallel (template argument updated)
339  // executor.ExecuteParallel<NThreadData>(parallel_task, thread_data_vector);
340 }
341 void NBinning::PrintContent(Option_t * option) const
342 {
346 
347  std::map<std::string, std::vector<int>> binningMap;
348 
349  TString opt(option);
350  // loop over all selected bins via ROOT iterarot for THnSparse
351  THnSparse * cSparse = fContent;
352  Int_t * bins = new Int_t[cSparse->GetNdimensions()];
353  Long64_t linBin = 0;
354  std::unique_ptr<ROOT::Internal::THnBaseBinIter> iter{cSparse->CreateIter(true /*use axis range*/)};
355  while ((linBin = iter->Next()) >= 0) {
356  Double_t v = cSparse->GetBinContent(linBin, bins);
357  Long64_t idx = cSparse->GetBin(bins, false);
358  std::string binCoords = NUtils::GetCoordsString(NUtils::ArrayToVector(bins, cSparse->GetNdimensions()), -1);
359  NLogTrace("Bin %lld: %f %s idx=%lld content=%f", linBin, v, binCoords.c_str(), idx, v);
360 
361  size_t iAxis = 0;
362  bool isValid = false;
363  // for (int i = 0; i < cSparse->GetNdimensions(); i += 3) {
364  int index = 0;
365  for (iAxis = 0; iAxis < fAxes.size(); iAxis++) {
366  int min;
367  int max;
368  // Print type of binning
369  // NLogTrace("Axis %d: %s [%s]", iAxis, fAxes[iAxis]->GetName(),
370  // fBinningTypes[iAxis] == Binning::kSingle ? "S" : "M");
371  if (fBinningTypes[iAxis] == Binning::kSingle) {
372  isValid = NUtils::GetAxisRangeInBase(fAxes[iAxis], 1, 1, bins[index], min, max);
373  binCoords += TString::Format(" | (S%c) %s %d %d %d [%d,%d] [%d,%d]", GetAxisTypeChar(iAxis),
374  fAxes[iAxis]->GetName(), 1, 1, bins[index], min, max, 1, fAxes[iAxis]->GetNbins())
375  .Data();
376  binningMap[fAxes[iAxis]->GetName()] = {1, 1, bins[index]};
377  index++;
378  }
379  else if (fBinningTypes[iAxis] == Binning::kMultiple) {
380  isValid = NUtils::GetAxisRangeInBase(fAxes[iAxis], bins[index], bins[index + 1], bins[index + 2], min, max);
381  binCoords +=
382  TString::Format(" | (M%c) %s %d %d %d [%d,%d] [%d,%d]", GetAxisTypeChar(iAxis), fAxes[iAxis]->GetName(),
383  bins[index], bins[index + 1], bins[index + 2], min, max, 1, fAxes[iAxis]->GetNbins())
384  .Data();
385  binningMap[fAxes[iAxis]->GetName()] = {bins[index], bins[index + 1], bins[index + 2]};
386  index += 3;
387  }
388  else if (fBinningTypes[iAxis] == Binning::kUser) {
389  isValid = NUtils::GetAxisRangeInBase(fAxes[iAxis], fAxes[iAxis]->GetNbins(), 1, 1, min, max);
390  binCoords += TString::Format(" | (U) %s %d %d %d [%d,%d] [%d,%d]", fAxes[iAxis]->GetName(),
391  fAxes[iAxis]->GetNbins(), 1, 1, min, max, 1, fAxes[iAxis]->GetNbins())
392  .Data();
393  // binningMap[fAxes[iAxis]->GetName()] = {1, 1, bins[index]};
394  binningMap[fAxes[iAxis]->GetName()] = {fAxes[iAxis]->GetNbins(), 1, 1};
395  index++;
396  }
397  else {
398  NLogError("[NBinning::PrintContent] Unknown binning type [%d]", fBinningTypes[iAxis]);
399  continue;
400  }
401  if (!isValid) {
402  NLogError("Cannot get axis range for axis %d", iAxis);
403  continue;
404  }
405  }
406  if (!isValid) {
407  // NLogError("Cannot get axis range for axis %d", iAxis);
408  NLogError("Bin %lld: %s [not valid for axis=%s]", linBin, binCoords.c_str(), fAxes[iAxis]->GetName());
409  continue;
410  }
411  NLogDebug("Bin %lld: %s", linBin, binCoords.c_str());
412  }
413  delete[] bins;
414 }
415 
417 {
421  Long64_t nBinsFilled = 0;
422 
423  // fContent->Reset();
424 
425  std::vector<int> mins(fMap->GetAxis(0)->GetNbins(), 1);
426  std::vector<int> maxs(fMap->GetAxis(0)->GetNbins(), 0);
427  std::vector<std::vector<std::vector<int>>> content(fMap->GetAxis(0)->GetNbins());
428 
429  // loop over all selected bins via ROOT iterarot for THnSparse
430  THnSparse * cSparse = fMap;
431  Int_t * p = new Int_t[cSparse->GetNdimensions()];
432  Long64_t linBin = 0;
433  std::unique_ptr<ROOT::Internal::THnBaseBinIter> iter{cSparse->CreateIter(true /*use axis range*/)};
434  // Print number of filled bins
435  // NLogInfo("Filled bins = %lld", cSparse->GetNbins());
436  while ((linBin = iter->Next()) >= 0) {
437  Double_t v = cSparse->GetBinContent(linBin, p);
438  // continue;
439  int idx = p[0] - 1;
440  NLogTrace("NBinning::FillAll: Bin %lld: %d %d %d %d type=%d content=%f", linBin, p[0], p[1], p[2], p[3],
441  fBinningTypes[idx], v);
442  if (fBinningTypes[idx] == Binning::kSingle) {
443 
444  content[idx].push_back({p[0], p[3]});
445  }
446  else if (fBinningTypes[idx] == Binning::kMultiple) {
447  // NLogDebug("Binning %d: %d", i, axes[idim]->GetNbins());
448  content[idx].push_back({p[0], p[1], p[2], p[3]});
449  }
450  else if (fBinningTypes[idx] == Binning::kUser) {
451  // TODO: Fix nbins for user binning (it should ok now)
452  content[idx].push_back({p[0], 1});
453  }
454  else {
455  NLogError("NBinning::FillAll: Unknown binning type %d", fBinningTypes[idx]);
456  continue;
457  }
458  maxs[idx] = maxs[idx] + 1;
459  }
460  delete[] p;
461 
462  Long64_t nTotalBins = 1;
463  // loop over content vector and set axis types
464  for (size_t i = 0; i < content.size(); i++) {
465  if (content[i].size() == 0) {
466  NLogWarning("NBinning::FillAll: No content for binning %zu", i);
467  continue;
468  }
469 
470  if (content[i].size() > 0) {
471  TAxis * axis = fAxes[i];
472  fAxisTypes[i] = AxisType::kVariable;
473  NLogTrace("NBinning::FillAll: Axis id=%d name=%s bins=%zu", i, axis->GetName(), content[i].size());
474  // check if i is persent in variable axes of def
475  bool found = false;
476  for (size_t j = 0; j < def->GetVariableAxes().size(); j++) {
477  if (def->GetVariableAxes()[j] == static_cast<int>(i)) {
478  NLogTrace("NBinning::FillAll: Axis id=%d name=%s already in variable axes of def", i, axis->GetName());
479  found = true;
480  break;
481  }
482  }
483  NLogTrace("NBinning::FillAll: Axis id=%d name=%s set to variable found=%d", i, axis->GetName(), found);
484  if (!found) def->AddVariableAxis(i);
485  }
486  nTotalBins *= content[i].size();
487  }
488 
489  def->Print();
490  NLogDebug("NBinning::FillAll: Filling total of %lld bins ...", nTotalBins);
491 
492  auto start_par = std::chrono::high_resolution_clock::now();
493  // Loop over all binning combinations
494  NDimensionalExecutor executor(mins, maxs);
495  auto binning_task = [&content, &nBinsFilled, &nTotalBins, start_par, def, this](const std::vector<int> & coords) {
496  std::vector<int> pointContentVector;
497  NLogTrace("Binning task: %s", NUtils::GetCoordsString(coords, -1).c_str());
498  for (size_t i = 0; i < coords.size(); i++) {
499  NLogTrace(" Binning %zu: coord=%d content size=%zu", i, coords[i], content[i].size());
500  if (content[i][coords[i] - 1].size() == 2) {
501  pointContentVector.push_back(content[i][coords[i] - 1][1]);
502  }
503  else {
504  pointContentVector.push_back(content[i][coords[i] - 1][1]);
505  pointContentVector.push_back(content[i][coords[i] - 1][2]);
506  pointContentVector.push_back(content[i][coords[i] - 1][3]);
507  }
508  }
509 
510  // NUtils::PrintPointSafe(pointContentVector, -1);
511  Int_t nContentDims = fContent->GetNdimensions();
512  NLogTrace("NBinning::FillAll: pointContentVector dims=%zu nContentDims=%d", pointContentVector.size(),
513  nContentDims);
514 
515  auto pointContent = std::make_unique<Int_t[]>(nContentDims);
516 
517  // Int_t pointContent[nContentDims];
518  NUtils::VectorToArray(pointContentVector, pointContent.get());
519  Long64_t pointContentBin = fContent->GetBin(pointContent.get());
520 
521  // ids.push_back(pointContentBin);
522  if (def) {
523  NBinningPoint point(this);
524  fContent->GetBinContent(pointContentBin, point.GetCoords());
525  point.RecalculateStorageCoords();
526  Long64_t linBin = def->GetContent()->GetBin(point.GetStorageCoords());
527  def->GetContent()->SetBinContent(linBin, pointContentBin);
528  def->GetIds().push_back(pointContentBin);
529  }
530 
531  NLogTrace("NBinning::FillAll: Setting content bin %lld", pointContentBin);
532 
533  fContent->SetBinContent(pointContentBin, 1);
534  nBinsFilled++;
535  // NLogDebug("NBinning::FillAll: Filled bin %lld: %s", nBinsFilled,
536  // NUtils::GetCoordsString(pointContentVector, -1).c_str());
537  NLogTrace("NBinning::FillAll: Filled bin %lld: %lld", nBinsFilled, nTotalBins);
538  int refreshRate = nTotalBins / 100;
539  if (refreshRate == 0) refreshRate = nTotalBins;
540  if (nBinsFilled % (refreshRate) == 0 && nBinsFilled != nTotalBins)
541  Ndmspc::NUtils::ProgressBar(nBinsFilled, nTotalBins, start_par, "I ");
542  // NLogDebug("NBinning::FillAll: [%3.2f%%] nBinsFilled=%lld", (double)nBinsFilled / nTotalBins * 100,
543  // nBinsFilled);
544  };
545  executor.Execute(binning_task);
546 
547  Ndmspc::NUtils::ProgressBar(nTotalBins, nTotalBins, start_par, "I ");
548 
549  auto end_par = std::chrono::high_resolution_clock::now();
550  std::chrono::duration<double, std::milli> par_duration = end_par - start_par;
551 
552  NLogInfo("NBinning::FillAll: Filled %lld bins in %s s", nTotalBins,
553  NUtils::FormatTime(par_duration.count() / 1000).c_str());
554 
555  fMap->Reset();
556 
557  return nBinsFilled;
558 }
559 
560 bool NBinning::AddBinning(size_t id, std::vector<int> binning, size_t n)
561 {
565 
566  if (fAxes.size() == 0) {
567  NLogError("AddBinning: No axes defined !!!");
568  return false;
569  }
570 
571  if (id <= 0 || id > fAxes.size()) {
572  NLogError("AddBinning: Invalid binning id %d", id);
573  return false;
574  }
575 
576  binning.insert(binning.begin(), id);
577  Int_t * point = new Int_t[fMap->GetNdimensions()];
578  NUtils::VectorToArray(binning, point);
579  if (binning.size() == 2) {
580  point[3] = point[1];
581  point[2] = 1;
582  point[1] = 1;
583  }
584  for (size_t i = 0; i < n; i++) {
585  NLogTrace("Adding binning %d: %d %d %d %d", i, point[0], point[1], point[2], point[3]);
586  fMap->SetBinContent(point, 1);
587  point[3] += 1;
588  }
589  delete[] point;
590 
591  return true;
592 }
593 bool NBinning::AddBinningVariable(size_t id, std::vector<int> mins)
594 {
598  if (id <= 0 || id > fAxes.size()) {
599  NLogError("AddBinningVariable: Invalid binning id %d", id);
600  return false;
601  }
602 
603  // lopp over all mins and set binning
604  for (size_t i = 1; i < mins.size(); i++) {
605 
606  if (mins[i] < 1 || mins[i] > fAxes[id - 1]->GetNbins() + 1) {
607  // NLogWarning("AddBinningVariable: Invalid binning value mins=%d", mins[i]);
608  return true;
609  }
610  // if (mins[i] == fAxes[id - 1]->GetNbins() || i == mins.size() - 1) mins[i]++;
611  int rebin = mins[i] - mins[i - 1];
612  if (rebin < 1) {
613  NLogError("AddBinningVariable: Invalid binning value rebin=%d", rebin);
614  return false;
615  }
616 
617  int rebin_start = mins[i - 1] % rebin;
618  int bin = mins[i] / rebin;
619 
620  // int rebin_start = ((mins[i - 1]) % rebin) + 1;
621  // int bin = (mins[i] / rebin);
622  if (rebin == 1) {
623  rebin_start = 1;
624  bin = mins[i - 1];
625  }
626  // rebin_start + 1 is just that it looks better in the output
627  // NLogDebug("Adding partial binning %d: %d %d %d %d [%d,%d]", i - 1, id, rebin, rebin_start + 1, bin,
628  // mins[i - 1], mins[i]);
629  AddBinning(id, {rebin, rebin_start, bin}, 1);
630  }
631 
632  return true;
633 }
634 bool NBinning::AddBinningViaBinWidths(size_t id, std::vector<std::vector<int>> widths)
635 {
639  // NLogTrace("Adding binning via bin widths for id=%d", id);
640  std::vector<int> mins;
641  // Print vector of widths
642  mins.push_back(1);
643  for (auto & w : widths) {
644  TAxis * axis = fAxes[id - 1];
645  int width = w[0];
646  int nWidths = w.size() > 1 ? w[1] : axis->GetNbins() / width;
647 
648  // NLogDebug(" width=%d nWidths=%d last min=%d", width, nWidths, mins[mins.size() - 1]);
649  for (int iWidth = 0; iWidth < nWidths; iWidth++) {
650  if (mins[mins.size() - 1] > axis->GetNbins()) {
651  // NLogWarning("NBinning::AddBinningViaBinWidths: Exceeding axis nbins %d", axis->GetNbins());
652  break;
653  }
654  mins.push_back(mins[mins.size() - 1] + width);
655  // NLogDebug(" width=%d nWidths=%d iWidth=%d -> min=%d", width, nWidths, iWidth, mins[mins.size() - 1]);
656  }
657  }
658 
659  NLogTrace("NBinning::AddBinningViaBinWidths: Adding binning via bin widths: %s",
660  NUtils::GetCoordsString(mins, -1).c_str());
661 
662  return AddBinningVariable(id, mins);
663 }
664 
665 std::vector<std::vector<int>> NBinning::GetCoordsRange(std::vector<int> c) const
666 {
667  std::vector<std::vector<int>> coordsRange;
668  std::vector<int> ids;
669  std::vector<int> mins;
670  std::vector<int> maxs;
671  // int iAxis = 0;
672  bool isValid;
673  int index = 0;
674  for (size_t iAxis = 0; iAxis < fAxes.size(); iAxis++) {
675  // for (int i = 0; i < fContent->GetNdimensions(); i += 3) {
676  int min;
677  int max;
678  if (fBinningTypes[iAxis] == Binning::kSingle) {
679  isValid = NUtils::GetAxisRangeInBase(fAxes[iAxis], 1, 1, c[index], min, max);
680  index++;
681  }
682  else if (fBinningTypes[iAxis] == Binning::kMultiple) {
683  isValid = NUtils::GetAxisRangeInBase(fAxes[iAxis], c[index], c[index + 1], c[index + 2], min, max);
684  index += 3;
685  }
686  else if (fBinningTypes[iAxis] == Binning::kUser) {
687  // isValid = NUtils::GetAxisRangeInBase(fAxes[iAxis], 1, 1, c[index], min, max);
688  isValid = NUtils::GetAxisRangeInBase(fAxes[iAxis], fAxes[iAxis]->GetNbins(), 1, 1, min, max);
689  index++;
690  }
691  else {
692  NLogError("NBinning::GetCoordsRange: Unknown binning type %d", fBinningTypes[iAxis]);
693  continue;
694  }
695  if (!isValid) {
696  // NLogError("Cannot get axis range for axis %d", iAxis);
697  return {};
698  }
699  // print min max
700  NLogDebug("Axis %d: %s [%d,%d]", iAxis, fAxes[iAxis]->GetName(), min, max);
701  ids.push_back(iAxis); // +1 because id starts from 1
702  mins.push_back(min);
703  maxs.push_back(max);
704  }
705 
706  coordsRange.push_back(ids);
707  coordsRange.push_back(mins);
708  coordsRange.push_back(maxs);
709  return coordsRange;
710 }
711 
712 Binning NBinning::GetBinningType(size_t i) const
713 {
714  if (i >= fBinningTypes.size()) {
715  NLogError("Invalid binning type %d", i);
716  // return Binning::kSingle;
717  return Binning::kUndefined;
718  }
719  return fBinningTypes[i];
720 }
721 std::vector<std::vector<int>> NBinning::GetAxisRanges(std::vector<int> c) const
722 {
726  std::vector<std::vector<int>> axisRanges;
727 
728  bool isValid;
729  int index = 0;
730  for (size_t iAxis = 0; iAxis < fAxes.size(); iAxis++) {
731  // for (int i = 0; i < fContent->GetNdimensions(); i += 3) {
732  int min;
733  int max;
734  if (fBinningTypes[iAxis] == Binning::kSingle) {
735  isValid = NUtils::GetAxisRangeInBase(fAxes[iAxis], 1, 1, c[index], min, max);
736  index++;
737  }
738  else if (fBinningTypes[iAxis] == Binning::kMultiple) {
739  isValid = NUtils::GetAxisRangeInBase(fAxes[iAxis], c[index], c[index + 1], c[index + 2], min, max);
740  index += 3;
741  }
742  else if (fBinningTypes[iAxis] == Binning::kUser) {
743  isValid = NUtils::GetAxisRangeInBase(fAxes[iAxis], fAxes[iAxis]->GetNbins(), 1, 1, min, max);
744  index++;
745  }
746  else {
747  NLogError("[NBinning::GetAxisRanges] Unknown binning type [%d]", fBinningTypes[iAxis]);
748  continue;
749  }
750  if (!isValid) {
751  // NLogError("Cannot get axis range for axis %d", iAxis);
752  return {};
753  }
754  // print min max
755  NLogTrace("Axis %d: %s [%d,%d]", iAxis, fAxes[iAxis]->GetName(), min, max);
756  axisRanges.push_back({(int)iAxis, min, max});
757  }
758 
759  return axisRanges;
760 }
761 std::vector<int> NBinning::GetAxisBinning(size_t axisId, const std::vector<int> & c) const
762 {
766  std::vector<int> binning;
767 
768  int index = 0;
769  for (size_t iAxis = 0; iAxis < fAxes.size(); iAxis++) {
770  // for (int i = 0; i < fContent->GetNdimensions(); i += 3) {
771  // int min;
772  // int max;
773  if (fBinningTypes[iAxis] == Binning::kSingle) {
774  if (iAxis == axisId) {
775  binning.push_back(1);
776  binning.push_back(1);
777  binning.push_back(c[index]);
778  break;
779  }
780  index++;
781  }
782  else if (fBinningTypes[iAxis] == Binning::kMultiple) {
783  if (iAxis == axisId) {
784  binning.push_back(c[index]);
785  binning.push_back(c[index + 1]);
786  binning.push_back(c[index + 2]);
787  break;
788  }
789  index += 3;
790  }
791  else if (fBinningTypes[iAxis] == Binning::kUser) {
792  if (iAxis == axisId) {
793  binning.push_back(c[index]);
794  binning.push_back(1);
795  binning.push_back(1);
796  break;
797  }
798  index++;
799  }
800  else {
801  NLogError("[NBinning::GetAxisBinning] Unknown binning type [%d]", fBinningTypes[iAxis]);
802  continue;
803  }
804  }
805 
806  return binning;
807 }
808 
809 bool NBinning::GetAxisRange(size_t axisId, double & min, double & max, std::vector<int> c) const
810 {
814  int minBin = 0;
815  int maxBin = 0;
816  Bool_t isValid = GetAxisRangeInBase(axisId, minBin, maxBin, c);
817 
818  min = fAxes[axisId]->GetBinLowEdge(minBin);
819  max = fAxes[axisId]->GetBinUpEdge(maxBin);
820  return isValid;
821 }
822 
823 bool NBinning::GetAxisRangeInBase(size_t axisId, int & min, int & max, std::vector<int> c) const
824 {
828  if (axisId >= fAxes.size()) {
829  NLogError("Invalid axis id %d", axisId);
830  return false;
831  }
832 
833  // Generate c if not provided
834 
835  int minBin = 0;
836  int maxBin = 0;
837  Bool_t isValid = false;
838  if (fBinningTypes[axisId] == Binning::kSingle) {
839  isValid = NUtils::GetAxisRangeInBase(fAxes[axisId], 1, 1, c[0], minBin, maxBin);
840  }
841  else if (fBinningTypes[axisId] == Binning::kMultiple) {
842  isValid = NUtils::GetAxisRangeInBase(fAxes[axisId], c[0], c[1], c[2], minBin, maxBin);
843  }
844 
845  min = minBin;
846  max = maxBin;
847  return isValid;
848 }
849 
851 {
855 
856  // TODO: Verify memery leak and its posible consequence for user
857 
858  TObjArray * axesArray = new TObjArray();
859 
860  // loop over all axes and create TObjArray
861  for (size_t i = 0; i < fAxes.size(); i++) {
862  TAxis * axis = (TAxis *)fAxes[i];
863  TAxis * axisNew = (TAxis *)axis->Clone();
864 
865  std::string name = axis->GetName();
866  NLogTrace("NBinning::GetListOfAxes(): Binning '%s': %d", name.c_str(), axis->GetNbins());
867 
868  auto bins = std::make_unique<double[]>(axis->GetNbins() + 1);
869  // double bins[axis->GetNbins() + 1];
870  int count = 0;
871  int iBin = 1; // start from bin 1
872  bins[count++] = axis->GetBinLowEdge(1);
873 
874  NBinningDef * def = GetDefinition();
875  std::map<std::string, std::vector<std::vector<int>>> definition = def->GetDefinition();
876  for (auto & v : definition.at(name)) {
877  NLogTrace(" %s", NUtils::GetCoordsString(v, -1).c_str());
878 
879  int n = v.size() > 1 ? v[1] : axis->GetNbins() / v[0];
880  for (int i = 0; i < n; i++) {
881  iBin += v[0];
882  bins[count++] = axis->GetBinLowEdge(iBin);
883  }
884  }
885  // loop over bins and print
886  for (int i = 0; i < count; i++) {
887  NLogTrace(" %s: %d %f", axis->GetName(), i + 1, bins[i]);
888  }
889  axisNew->Set(count - 1, bins.get());
890  axesArray->Add(axisNew);
891  }
892 
893  return axesArray;
894 }
895 
896 bool NBinning::SetAxisType(size_t axisId, AxisType at)
897 {
901  if (axisId >= fAxes.size()) {
902  NLogError("Invalid axis id %d", axisId);
903  return false;
904  }
905  fAxisTypes[axisId] = at;
906  return true;
907 }
908 
909 AxisType NBinning::GetAxisType(size_t i) const
910 {
914  if (i >= fAxisTypes.size()) {
915  NLogError("Invalid axis type %d", i);
916  return AxisType::kUndefined; // Undefined
917  }
918  return fAxisTypes[i];
919 }
920 char NBinning::GetAxisTypeChar(size_t i) const
921 {
922  if (i >= fAxisTypes.size()) {
923  NLogError("Invalid axis type %d", i);
924  return 'X'; // Undefined
925  }
926  switch (fAxisTypes[i]) {
927  case AxisType::kFixed: return 'F';
928  case AxisType::kVariable: return 'V';
929  case AxisType::kUndefined:
930  default: return 'X';
931  }
932 }
933 
934 std::vector<int> NBinning::GetAxisIndexes(AxisType type) const
935 {
939  std::vector<int> ids;
940  for (size_t i = 0; i < fAxes.size(); i++) {
941  if (fAxisTypes[i] == type) {
942  NLogTrace("Axis %d: %s type=%d", i, fAxes[i]->GetName(), fAxisTypes[i]);
943  ids.push_back(i);
944  }
945  else {
946  NLogTrace("Axis %d: %s type=%d [not selected]", i, fAxes[i]->GetName(), fAxisTypes[i]);
947  }
948  }
949  return ids;
950 }
951 
952 std::vector<TAxis *> NBinning::GetAxesByType(AxisType type) const
953 {
957  std::vector<TAxis *> axes;
958  for (size_t i = 0; i < fAxes.size(); i++) {
959  if (fAxisTypes[i] == type) {
960  NLogTrace("Axis %d: %s type=%d", i, fAxes[i]->GetName(), fAxisTypes[i]);
961  axes.push_back(fAxes[i]);
962  }
963  else {
964  NLogTrace("Axis %d: %s type=%d [not selected]", i, fAxes[i]->GetName(), fAxisTypes[i]);
965  }
966  }
967  return axes;
968 }
969 
970 std::vector<int> NBinning::GetAxisIndexesByNames(std::vector<std::string> names) const
971 {
975  std::vector<int> ids;
976  for (auto & name : names) {
977  for (size_t i = 0; i < fAxes.size(); i++) {
978  if (fAxes[i]->GetName() == name) {
979  NLogTrace("Axis %d: %s type=%d", i, fAxes[i]->GetName(), fAxisTypes[i]);
980  ids.push_back(i);
981  break; // break inner loop if found
982  }
983  }
984  }
985  return ids;
986 }
987 
988 std::vector<std::string> NBinning::GetAxisNamesByType(AxisType type) const
989 {
993  std::vector<std::string> names;
994  for (size_t i = 0; i < fAxes.size(); i++) {
995  if (fAxisTypes[i] == type) {
996  NLogTrace("Axis %d: %s type=%d", i, fAxes[i]->GetName(), fAxisTypes[i]);
997  names.push_back(fAxes[i]->GetName());
998  continue;
999  }
1000  else {
1001  NLogTrace("Axis %d: %s type=%d [not selected]", i, fAxes[i]->GetName(), fAxisTypes[i]);
1002  }
1003  }
1004  return names;
1005 }
1006 std::vector<std::string> NBinning::GetAxisNamesByIndexes(std::vector<int> ids) const
1007 {
1011  std::vector<std::string> names;
1012  for (auto & id : ids) {
1013  // FIXME: change to size_t
1014  if (id < 0 || id >= (int)fAxes.size()) {
1015  NLogError("Invalid axis id %d", id);
1016  continue;
1017  }
1018  NLogTrace("Axis %d: %s type=%d", id, fAxes[id]->GetName(), fAxisTypes[id]);
1019  names.push_back(fAxes[id]->GetName());
1020  }
1021  return names;
1022 }
1023 
1024 NBinningDef * NBinning::GetDefinition(const std::string & name)
1025 {
1026 
1030 
1031  if (name.empty()) {
1032  if (fCurrentDefinitionName.empty()) {
1033  return nullptr;
1034  }
1035  // check if current definition exists
1036  if (fDefinitions.find(fCurrentDefinitionName) == fDefinitions.end()) {
1037  NLogError("NBinning::GetDefinition: Current definition '%s' not found", fCurrentDefinitionName.c_str());
1038  return nullptr;
1039  }
1040  NLogTrace("NBinning::GetDefinition: Using current definition '%s'", fCurrentDefinitionName.c_str());
1042  }
1043 
1044  if (fDefinitions.find(name) == fDefinitions.end()) {
1045  NLogError("NBinning::GetDefinition: Definition '%s' not found", name.c_str());
1046  return nullptr;
1047  }
1048  NLogTrace("NBinning::GetDefinition: Using definition '%s'", name.c_str());
1049  fCurrentDefinitionName = name;
1050  return fDefinitions.at(name);
1051 }
1052 
1053 void NBinning::AddBinningDefinition(std::string name, std::map<std::string, std::vector<std::vector<int>>> binning,
1054  bool forceDefault)
1055 {
1059  if (fDefinitions.find(name) != fDefinitions.end()) {
1060  NLogError("Binning definition '%s' already exists", name.c_str());
1061  return;
1062  }
1063 
1064  NLogInfo("NBinning::AddBinningDefinition: Adding binning definition '%s'", name.c_str());
1065  NBinningDef * def = new NBinningDef(name, binning, this);
1066  fDefinitionNames.push_back(name);
1067  fDefinitions[name] = def;
1068  fCurrentDefinitionName = name;
1069  fMap->Reset();
1070  // loop over binning axes
1071  for (size_t i = 0; i < fAxes.size(); i++) {
1072  TAxis * axis = fAxes[i];
1073  std::string axisName = axis->GetName();
1074  // NLogDebug("Axis %zu: name='%s' title='%s' nbins=%d min=%.3f max=%.3f", i, axisName.c_str(),
1075  // axis->GetTitle(), axis->GetNbins(), axis->GetXmin(), axis->GetXmax());
1076 
1077  // TODO: Handle case when user wants to rebin alphanumeric axis. Now we are failing
1078  if (!binning[axisName].empty()) {
1079 
1080  // TODO: Handle case when user wants to rebin alphanumeric axis. Now we are failing
1081  if (axis->IsAlphanumeric() && (binning[axisName].size() != 1 || binning[axisName][0][0] != 1)) {
1082  NLogError("NBinning::AddBinningDefinition: Axis '%s' is alphanumeric and is binning provided in definition "
1083  "'%s'. Exiting ...",
1084  axisName.c_str(), name.c_str());
1085  exit(1);
1086  }
1087 
1088 
1089  AddBinningViaBinWidths(i + 1, binning[axisName]);
1090  SetAxisType(i, AxisType::kVariable);
1091  // GetDefinition()[axisName] = binning[axisName];
1092  // def->SetAxisDefinition(axisName, binning[axisName]);
1093  }
1094  else {
1095 
1096  // TODO: Handle case when user wants to rebin alphanumeric axis. Now we are failing
1097  if (axis->IsAlphanumeric()) {
1098  NLogError("NBinning::AddBinningDefinition: Axis '%s' is alphanumeric and no binning provided in definition "
1099  "'%s'. Exiting ...",
1100  axisName.c_str(), name.c_str());
1101  exit(1);
1102  }
1103 
1104  AddBinning(i + 1, {axis->GetNbins(), 1, 1}, 1);
1105  // GetDefinition()[axisName] = {{axis->GetNbins()}};
1106  // def->SetAxisDefinition(axisName, {{axis->GetNbins()}});
1107  }
1108  }
1109 
1110  // Long64_t nStart = fContent->GetNbins();
1111  // def->SetStartId(nStart);
1112  // std::vector<Long64_t> entries;
1113  Long64_t nFilled = FillAll(def);
1114  // def->Print();
1115  NLogTrace("NBinning::AddBinningDefinition: Filled %lld bins for definition '%s'", nFilled,
1116  NUtils::GetCoordsString(def->GetIds(), -1).c_str());
1117  // def->SetNEntries(nFilled);
1118 
1119  if (forceDefault || fCurrentDefinitionName.empty()) {
1120  fCurrentDefinitionName = name;
1121  NLogTrace("Set default binning definition '%s'", fCurrentDefinitionName.c_str());
1122  }
1123  else {
1124  NLogTrace("Added binning definition '%s' [not default]", name.c_str());
1125  }
1126 }
1127 
1129 {
1133 
1134  if (fPoint == nullptr) {
1135  fPoint = new NBinningPoint(this);
1136  }
1137  return fPoint;
1138 }
1139 
1140 NBinningPoint * NBinning::GetPoint(size_t id, std::string binning)
1141 {
1145 
1146  // TODO: Optimize speed here
1147 
1148  NBinningDef * def = GetDefinition(binning);
1149  if (def == nullptr) {
1150  NLogError("NBinning::FillPoint: Definition '%s' not found", binning.c_str());
1151  return nullptr;
1152  }
1153 
1154  if (fPoint == nullptr) {
1155  fPoint = new NBinningPoint(this);
1156  }
1157 
1158  Long64_t linBin = def->GetId(id);
1159  if (linBin < 0) {
1160  NLogError("NBinning::GetPoint: Invalid linear bin %lld for id=%d in definition '%s'", linBin, id, binning.c_str());
1161  return nullptr;
1162  }
1163  if (linBin >= fContent->GetNbins()) {
1164  NLogError("NBinning::GetPoint: Linear bin %lld out of range [0,%lld) for id=%d in definition '%s'", linBin,
1165  fContent->GetNbins(), id, binning.c_str());
1166  return nullptr;
1167  }
1168  fContent->GetBinContent(linBin, fPoint->GetCoords());
1170 
1171  return fPoint;
1172 }
1173 
1174 bool NBinning::SetCfg(const json & cfg)
1175 {
1179  GetPoint()->SetCfg(cfg);
1180 
1181  return true;
1182 }
1183 
1184 void NBinning::SetCurrentDefinitionName(const std::string & name)
1185 {
1190 
1191  if (name.empty()) {
1192  if (!fDefinitionNames.empty()) {
1194  NLogInfo("Binning definition name='' set to first available definition '%s'", fCurrentDefinitionName.c_str());
1195  return;
1196  }
1197  else {
1198  NLogError("Binning definition name='' and no definitions are available !!! Ignorred ...");
1199  return;
1200  }
1201  }
1202 
1203  if (fDefinitions.find(name) == fDefinitions.end()) {
1204  NLogError("Binning definition '%s' not found", name.c_str());
1205  return;
1206  }
1207 
1208  // check if name is already current
1209  if (fCurrentDefinitionName.compare(name) == 0) {
1210  NLogTrace("Binning definition '%s' is already current", name.c_str());
1211  return;
1212  }
1213 
1214  // Set current definition name
1215  fCurrentDefinitionName = name;
1216 
1217  // Reset Point
1218  if (fPoint == nullptr) {
1219  fPoint = new NBinningPoint(this);
1220  }
1221  fPoint->Reset();
1222 }
1223 
1224 } // namespace Ndmspc
Defines binning mapping and content for NDMSPC histograms.
Definition: NBinningDef.h:26
THnSparse * GetContent() const
Get the template content histogram.
Definition: NBinningDef.h:118
std::map< std::string, std::vector< std::vector< int > > > GetDefinition() const
Get the binning mapping definition.
Definition: NBinningDef.h:52
std::vector< int > GetVariableAxes() const
Get list of variable axes indices.
Definition: NBinningDef.h:71
virtual void Print(Option_t *option="") const
Print binning definition information.
void AddVariableAxis(size_t axis)
Add a variable axis index.
Definition: NBinningDef.h:77
Long64_t GetId(size_t index) const
Get bin ID at specified index.
std::vector< Long64_t > GetIds() const
Get list of bin IDs.
Definition: NBinningDef.h:93
Represents a single point in multi-dimensional binning.
Definition: NBinningPoint.h:21
bool RecalculateStorageCoords(Long64_t entry=-1, bool useBinningDefCheck=false)
Recalculate storage coordinates for the point.
Int_t * GetStorageCoords() const
Get pointer to storage coordinates array.
Definition: NBinningPoint.h:67
void SetCfg(json cfg)
Set configuration JSON object.
Int_t * GetCoords() const
Get pointer to content coordinates array.
Definition: NBinningPoint.h:55
virtual void Reset()
Reset the binning point to initial state.
NBinning object for managing multi-dimensional binning and axis definitions.
Definition: NBinning.h:45
NBinningDef * GetDefinition(const std::string &name="")
Get binning definition by name.
Definition: NBinning.cxx:1024
std::vector< std::string > GetAxisNamesByType(AxisType type) const
Get axis names by type.
Definition: NBinning.cxx:988
std::vector< int > GetAxisIndexes(AxisType type) const
Get indexes of axes by type.
Definition: NBinning.cxx:934
std::vector< std::string > GetAxisNamesByIndexes(std::vector< int > axisIds) const
Get axis names by indexes.
Definition: NBinning.cxx:1006
std::vector< AxisType > fAxisTypes
Axis types.
Definition: NBinning.h:325
std::vector< TAxis * > fAxes
List of axes.
Definition: NBinning.h:323
NBinningPoint * GetPoint()
Get the current binning point.
Definition: NBinning.cxx:1128
std::vector< int > GetAxisIndexesByNames(std::vector< std::string > axisNames) const
Get axis indexes by axis names.
Definition: NBinning.cxx:970
bool GetAxisRange(size_t axisId, double &min, double &max, std::vector< int > c) const
Get axis range for a specific axis and coordinates.
Definition: NBinning.cxx:809
std::vector< std::vector< int > > GetAxisRanges(std::vector< int > c) const
Get axis ranges for given coordinates.
Definition: NBinning.cxx:721
TObjArray * GenerateListOfAxes()
Generate a list of axes as TObjArray.
Definition: NBinning.cxx:850
bool AddBinningVariable(size_t id, std::vector< int > mins)
Add variable binning for a specific axis.
Definition: NBinning.cxx:593
NBinning()
Default constructor.
Definition: NBinning.cxx:19
virtual void Print(Option_t *option="") const
Print binning information.
Definition: NBinning.cxx:245
AxisType GetAxisType(size_t i) const
Get axis type for a specific axis.
Definition: NBinning.cxx:909
bool AddBinningViaBinWidths(size_t id, std::vector< std::vector< int >> widths)
Add binning via bin widths for a specific axis.
Definition: NBinning.cxx:634
void Initialize()
Initialize the binning object.
Definition: NBinning.cxx:90
bool SetCfg(const json &cfg)
Set configuration from JSON.
Definition: NBinning.cxx:1174
std::vector< std::string > fDefinitionNames
Binning definition names.
Definition: NBinning.h:328
THnSparse * fContent
Content histogram.
Definition: NBinning.h:322
void AddBinningDefinition(std::string name, std::map< std::string, std::vector< std::vector< int >>> binning, bool forceDefault=false)
Add a binning definition.
Definition: NBinning.cxx:1053
std::string fCurrentDefinitionName
Current definition name.
Definition: NBinning.h:326
std::map< std::string, NBinningDef * > fDefinitions
Binning definitions.
Definition: NBinning.h:327
Binning GetBinningType(size_t i) const
Get binning type for a specific axis.
Definition: NBinning.cxx:712
void PrintContent(Option_t *option="") const
Print binning content.
Definition: NBinning.cxx:341
bool GetAxisRangeInBase(size_t axisId, int &min, int &max, std::vector< int > c) const
Get axis range in base for a specific axis and coordinates.
Definition: NBinning.cxx:823
std::vector< int > GetAxisBinning(size_t axisId, const std::vector< int > &c) const
Get binning for a specific axis and coordinates.
Definition: NBinning.cxx:761
virtual ~NBinning()
Destructor.
Definition: NBinning.cxx:56
NBinningPoint * fPoint
! Binning point object
Definition: NBinning.h:329
char GetAxisTypeChar(size_t i) const
Get axis type as character for a specific axis.
Definition: NBinning.cxx:920
void Reset()
Reset the binning object to initial state.
Definition: NBinning.cxx:78
std::vector< std::vector< int > > GetCoordsRange(std::vector< int > c) const
Get coordinate ranges for given coordinates.
Definition: NBinning.cxx:665
bool SetAxisType(size_t id, AxisType type)
Set axis type for a specific axis.
Definition: NBinning.cxx:896
std::vector< TAxis * > GetAxesByType(AxisType type) const
Get axes by type.
Definition: NBinning.cxx:952
void SetCurrentDefinitionName(const std::string &name)
Set current definition name.
Definition: NBinning.cxx:1184
THnSparse * fMap
Mapping histogram.
Definition: NBinning.h:321
std::vector< Binning > fBinningTypes
Binning types.
Definition: NBinning.h:324
bool AddBinning(size_t id, std::vector< int > binning, size_t n=1)
Add binning for a specific axis.
Definition: NBinning.cxx:560
Long64_t FillAll(NBinningDef *def=nullptr)
Fill all bins according to definition.
Definition: NBinning.cxx:416
Executes a function over all points in an N-dimensional space, optionally in parallel.
void Execute(const std::function< void(const std::vector< int > &coords)> &func)
Execute a function over all coordinates in the N-dimensional space.
static std::string FormatTime(long long seconds)
Format time in seconds to human-readable string.
Definition: NUtils.cxx:1660
static bool GetAxisRangeInBase(TAxis *a, int rebin, int rebin_start, int bin, int &min, int &max)
Get axis range in base for rebinned axis.
Definition: NUtils.cxx:1338
static void ProgressBar(int current, int total, std::string prefix="", std::string suffix="", int barWidth=50)
Display progress bar.
Definition: NUtils.cxx:1673
static std::string GetCoordsString(const std::vector< int > &coords, int index=-1, int width=0)
Get string representation of coordinates.
Definition: NUtils.cxx:1588
static void VectorToArray(std::vector< int > v1, Int_t *v2)
Convert vector to array.
Definition: NUtils.cxx:1564
static std::vector< int > ArrayToVector(Int_t *v1, int size)
Convert array to vector.
Definition: NUtils.cxx:1551