ndmspc  0.20250128.0
PointRun.cxx
1 #include <fstream>
2 #include <iostream>
3 #include <sstream>
4 #include <string>
5 #include <vector>
6 #include "TArrayD.h"
7 #include <TFileMerger.h>
8 #include <TString.h>
9 #include <TMacro.h>
10 #include <TROOT.h>
11 #include <TH1.h>
12 #include <TSystem.h>
13 #include <THnSparse.h>
14 #include "Core.h"
15 #include "Utils.h"
16 #include "PointRun.h"
17 
19 ClassImp(Ndmspc::PointRun);
21 
22 namespace Ndmspc {
23 std::string PointRun::fgEnvironment = "";
24 PointRun::PointRun(std::string macro) : TObject()
25 {
29 
30  TH1::AddDirectory(kFALSE);
31  fMacro = Utils::OpenMacro(macro.c_str());
32  if (fMacro) fMacro->Load();
33 }
34 
36 {
40 }
41 
42 bool PointRun::LoadConfig(std::string config, std::string userConfig, std::string environment,
43  std::string userConfigRaw, bool show, std::string outfilename)
44 {
48 
49  if (!Core::LoadConfig(config, userConfig, environment, userConfigRaw)) return 1;
50 
51  if (!gCfg["ndmspc"]["verbose"].is_null() && gCfg["ndmspc"]["verbose"].is_number_integer())
52  fVerbose = gCfg["ndmspc"]["verbose"].get<int>();
53 
54  if (!gCfg["ndmspc"]["file"]["cache"].is_null() && gCfg["ndmspc"]["file"]["cache"].is_string()) {
55  std::string cacheDir = gCfg["ndmspc"]["file"]["cache"].get<std::string>();
56  if (!cacheDir.empty()) {
57  Printf("Setting cache directory to '%s' ...", gSystem->ExpandPathName(cacheDir.c_str()));
58  TFile::SetCacheFileDir(gSystem->ExpandPathName(cacheDir.c_str()), 1, 1);
59  }
60  }
61 
62  if (show) Printf("%s", gCfg.dump(2).c_str());
63 
64  if (!outfilename.empty()) {
65  std::ofstream file(outfilename.c_str());
66  file << gCfg;
67  Printf("Config saved to file '%s' ...", outfilename.c_str());
68  return false;
69  }
70  return true;
71 }
72 
73 bool PointRun::Init(std::string extraPath)
74 {
78 
79  if (fVerbose >= 2) Printf("Ndmspc::PointRun::Init ...");
80  if (!gCfg["ndmspc"]["process"]["type"].get<std::string>().compare("all") &&
81  gCfg["ndmspc"]["process"]["ranges"].is_null() &&
82  !gCfg["ndmspc"]["output"]["delete"].get<std::string>().compare("onInit")) {
83 
84  if (gCfg["ndmspc"]["output"]["host"].get<std::string>().empty()) {
85  gCfg["ndmspc"]["output"]["opt"] = "";
86  }
87 
88  std::string outFileName;
89  if (!gCfg["ndmspc"]["output"]["dir"].get<std::string>().empty()) {
90  // outFileName = gCfg["ndmspc"]["output"]["host"].get<std::string>() + "/";
91 
92  outFileName += gCfg["ndmspc"]["output"]["dir"].get<std::string>();
93  outFileName += "/";
94 
95  std::string environment = gCfg["ndmspc"]["environment"].get<std::string>();
96  outFileName += environment + "/";
97 
98  outFileName += Utils::GetCutsPath(gCfg["ndmspc"]["cuts"]);
99  // std::string rebinStr = "";
100  // for (auto & cut : gCfg["ndmspc"]["cuts"]) {
101  // Int_t rebin = 1;
102  // Int_t rebin_start = 1;
103  // Int_t rebin_minimum = 1;
104  // if (cut["enabled"].is_boolean() && cut["enabled"].get<bool>() == false) continue;
105  // if (cut["rebin"].is_number_integer()) rebin = cut["rebin"].get<Int_t>();
106  // if (cut["rebin_start"].is_number_integer()) rebin_start = cut["rebin_start"].get<Int_t>();
107  //
108  // if (rebin_start > 1) {
109  // rebin_minimum = (rebin_start % rebin);
110  // }
111  // outFileName += cut["axis"].get<std::string>() + "_";
112  // rebinStr += std::to_string(rebin) + "-" + std::to_string(rebin_minimum) + "_";
113  // }
114  // outFileName[outFileName.size() - 1] = '/';
115  // rebinStr[rebinStr.size() - 1] = '/';
116  // outFileName += rebinStr;
117  //
118  outFileName += "bins";
119 
120  if (!extraPath.empty()) {
121  outFileName += "/" + extraPath;
122  outFileName.pop_back();
123  }
124  }
125 
126  if (!outFileName.empty()) {
127  if (gCfg["ndmspc"]["output"]["host"].is_string() &&
128  !gCfg["ndmspc"]["output"]["host"].get<std::string>().empty()) {
129 
130  Printf("Deleting output eos directory '%s' ...", outFileName.c_str());
131  std::string rmUrl =
132  TString::Format("%s/proc/user/?mgm.cmd=rm&mgm.path=%s&mgm.option=rf&mgm.format=json&filetype=raw",
133  gCfg["ndmspc"]["output"]["host"].get<std::string>().c_str(), outFileName.c_str())
134  .Data();
135 
136  if (fVerbose >= 2) Printf("rmUrl '%s' ...", rmUrl.c_str());
137  TFile * f = Ndmspc::Utils::OpenFile(rmUrl.c_str());
138  if (!f) return 1;
139  Printf("Directory '%s' deleted", outFileName.c_str());
140  f->Close();
141  }
142  else {
143  Printf("Directory '%s' deleted", outFileName.c_str());
144  gSystem->Exec(TString::Format("rm -rf %s", outFileName.c_str()));
145  }
146  }
147  // gCfg["ndmspc"]["output"]["delete"] = "";
148  }
149  if (fVerbose >= 2) Printf("Ndmspc::PointRun::Init done ...");
150 
151  return true;
152 }
153 
155 {
159 
160  if (fVerbose >= 2) Printf("[<-] Ndmspc::PointRun::OpenInputs");
161 
162  if (fInputFile && fInputList) return fInputList;
163 
164  if (gCfg["ndmspc"]["data"]["file"].get<std::string>().empty()) {
165  Printf("Error: Input file is empty !!! Aborting ...");
166  return nullptr;
167  }
168  if (fVerbose >= 0) Printf("Opening file '%s' ...", gCfg["ndmspc"]["data"]["file"].get<std::string>().c_str());
169  fInputFile = Ndmspc::Utils::OpenFile(gCfg["ndmspc"]["data"]["file"].get<std::string>().c_str());
170  if (!fInputFile) {
171  Printf("Error: Cannot open file '%s' !", gCfg["ndmspc"]["data"]["file"].get<std::string>().c_str());
172  return nullptr;
173  }
174 
175  if (!fInputList) fInputList = new TList();
176 
177  THnSparse *s, *stmp;
178  for (auto & obj : gCfg["ndmspc"]["data"]["objects"]) {
179  if (obj.get<std::string>().empty()) continue;
180 
181  std::string dirName;
182  if (!gCfg["ndmspc"]["data"]["directory"].is_null() && gCfg["ndmspc"]["data"]["directory"].is_string())
183  dirName = gCfg["ndmspc"]["data"]["directory"].get<std::string>();
184 
185  std::stringstream srcfull(obj.get<std::string>().c_str());
186 
187  std::string srcName, sparseName;
188 
189  getline(srcfull, srcName, ':');
190  getline(srcfull, sparseName, ':');
191  if (fVerbose >= 2) Printf("srcName=%s customName=%s", srcName.c_str(), sparseName.c_str());
192 
193  std::stringstream src(srcName.c_str());
194  std::string item;
195 
196  s = nullptr;
197  while (getline(src, item, '+')) {
198 
199  std::string objName;
200  if (!dirName.empty()) objName = dirName + "/";
201  objName += item;
202  if (fVerbose >= 1) Printf("Opening obj='%s' ...", objName.c_str());
203  if (s == nullptr) {
204 
205  s = (THnSparse *)fInputFile->Get(objName.c_str());
206  if (s == nullptr) {
207  if (fVerbose >= 1) Printf("Warning: Cannot open object '%s' !!!", objName.c_str());
208  continue;
209  }
210 
211  if (s && !sparseName.empty()) s->SetName(sparseName.c_str());
212  }
213  else {
214  if (fVerbose >= 1) Printf("Adding obj='%s' ...", objName.c_str());
215  stmp = (THnSparse *)fInputFile->Get(objName.c_str());
216  if (stmp == nullptr) {
217  if (fVerbose >= 1) Printf("Warning: Cannot open object '%s' !!!", objName.c_str());
218  continue;
219  }
220  if (s) s->Add(stmp);
221  }
222  }
223  if (s) {
224  fInputList->Add(s);
225  }
226  else {
227  if (fVerbose >= 1)
228  Printf("Warning : Could not open '%s' from file '%s' !!! Skipping ...", obj.get<std::string>().c_str(),
229  gCfg["ndmspc"]["data"]["file"].get<std::string>().c_str());
230  // return nullptr;
231  }
232  }
233 
234  TFunction * fun = gROOT->GetGlobalFunction("NdmspcOpenInputsUser", nullptr, kTRUE);
235  if (fun) {
236  gROOT->ProcessLine(TString::Format("NdmspcOpenInputsUser((Ndmspc::PointRun*)%p),", this));
237  }
238 
239  if (fVerbose >= 2) Printf("[->] Ndmspc::PointRun::OpenInputs");
240 
241  return fInputList;
242 }
243 
245 {
249 
250  if (fVerbose >= 2) Printf("[<-] Ndmspc::PointRun::CreateResult fResultObject=%p", (void *)fResultObject);
251 
252  if (fResultObject) return fResultObject;
253 
254  THnSparse * s = (THnSparse *)fInputList->At(0);
255 
256  int nDimsParams = 0;
257  int nDimsCuts = 0;
258  int nDimsProccess = fCurrentProcessHistogramAxes.size();
259 
260  for (auto & cut : gCfg["ndmspc"]["cuts"]) {
261  if (cut["enabled"].is_boolean() && cut["enabled"].get<bool>() == false) continue;
262  nDimsCuts++;
263  }
264 
265  for (auto & value : gCfg["ndmspc"]["result"]["axes"]) {
266  nDimsParams++;
267  }
268 
269  const Int_t ndims = nDimsCuts + nDimsParams + nDimsProccess + 1;
270  Int_t bins[ndims];
271  Double_t xmin[ndims];
272  Double_t xmax[ndims];
273  std::vector<std::string> names;
274  std::vector<std::string> titles;
275  std::vector<TAxis *> cutAxes;
276  fMapAxesType = new TH1S("mapAxesType", "Type Axes Map", ndims, 0, ndims);
277  // _currentOutputRootDirectory->Add
278 
279  Int_t nParameters = gCfg["ndmspc"]["result"]["parameters"]["labels"].size();
280  if (nParameters <= 0) return nullptr;
281 
282  Int_t i = 0;
283 
284  bins[i] = nParameters;
285  xmin[i] = 0;
286  xmax[i] = nParameters;
287  names.push_back("parameters");
288  titles.push_back("parameters");
289  fMapAxesType->GetXaxis()->SetBinLabel(i + 1, "par");
290 
291  i++;
292 
293  // cfg["ndmspc"]["output"]["post"]
294  int iTmp = 0;
295  for (auto & a : fCurrentProcessHistogramAxes) {
296  // a->Print();
297  bins[i] = a->GetNbins();
298  xmin[i] = a->GetXmin();
299  xmax[i] = a->GetXmax();
300  // TODO: handle variable binning
301 
302  names.push_back(a->GetName());
303  std::string t = a->GetTitle();
304  if (t.empty()) t = a->GetName();
305  titles.push_back(t);
306  if (iTmp < 2)
307  fMapAxesType->GetXaxis()->SetBinLabel(i + 1, "data");
308  else
309  fMapAxesType->GetXaxis()->SetBinLabel(i + 1, "sys-out");
310  iTmp++;
311  i++;
312  }
313 
314  Int_t rebin = 1;
315  Int_t rebin_start = 1;
316  for (auto & cut : gCfg["ndmspc"]["cuts"]) {
317  if (fVerbose >= 3) std::cout << "CreateResult() : " << cut.dump() << std::endl;
318 
319  Int_t rebin = 1;
320  Int_t rebin_start = 1;
321  Int_t rebin_minimum = 1;
322  if (cut["enabled"].is_boolean() && cut["enabled"].get<bool>() == false) continue;
323  if (cut["rebin"].is_number_integer()) rebin = cut["rebin"].get<Int_t>();
324  if (cut["rebin_start"].is_number_integer()) rebin_start = cut["rebin_start"].get<Int_t>();
325 
326  if (rebin_start > 1) {
327  rebin_minimum = (rebin_start % rebin);
328  }
329 
330  TAxis * a = (TAxis *)s->GetListOfAxes()->FindObject(cut["axis"].get<std::string>().c_str());
331  if (a == nullptr) return nullptr;
332 
333  if (rebin > 1) {
334  a = (TAxis *)a->Clone();
335  Int_t rebins_max = a->GetNbins() / rebin;
336  if ((a->GetNbins() - rebin_minimum + 1) % rebin == 0) rebins_max++;
337  Double_t arr[rebins_max];
338 
339  // Printf("Axis '%s' : rebin_max=%d rebin_minimum=%d nbins=%d", a->GetName(), rebins_max, rebin_minimum,
340  // a->GetNbins());
341  Int_t count = 0;
342  Int_t i;
343  for (i = rebin_minimum; i <= a->GetNbins(); i += rebin) {
344  // Printf("%d %f", i, a->GetBinUpEdge(i));
345  arr[count++] = a->GetBinLowEdge(i);
346  }
347  // Printf("%s %d %d", a->GetName(), count, rebins_max);
348  if (count < rebins_max) arr[count++] = a->GetBinLowEdge(i);
349  // for (Int_t i = 0; i < count; i++) {
350  // Printf("%s %d %f", a->GetName(), i, arr[i]);
351  // }
352  a->Set(count - 1, arr);
353  // Printf("Axis '%s' : %d", a->GetName(), a->GetNbins());
354  }
355  bins[i] = a->GetNbins();
356  xmin[i] = a->GetXmin();
357  xmax[i] = a->GetXmax();
358 
359  cutAxes.push_back(a);
360  names.push_back(a->GetName());
361  std::string t = a->GetTitle();
362  if (t.empty()) t = a->GetName();
363  titles.push_back(t);
364  fMapAxesType->GetXaxis()->SetBinLabel(i + 1, "proj");
365  i++;
366  }
367  // exit(1);
368 
369  for (auto & value : gCfg["ndmspc"]["result"]["axes"]) {
370  if (!value["labels"].is_null()) {
371  bins[i] = value["labels"].size();
372  xmin[i] = 0;
373  xmax[i] = value["labels"].size();
374  }
375  else if (!value["ranges"].is_null()) {
376  bins[i] = value["ranges"].size();
377  xmin[i] = 0;
378  xmax[i] = value["ranges"].size();
379  }
380  else {
381  Printf("Error: 'labels' or 'ranges' is missing !!!");
382  return nullptr;
383  }
384 
385  names.push_back(value["name"].get<std::string>().c_str());
386  titles.push_back(value["name"].get<std::string>().c_str());
387  fMapAxesType->GetXaxis()->SetBinLabel(i + 1, "sys-in");
388  i++;
389  }
390 
391  fCurrentPointLabels = names;
392 
393  THnSparse * fres = new THnSparseD("results", "Final results", i, bins, xmin, xmax);
394  if (!fres) {
395  Printf("Error: Could not create 'results' THnSparse object !!!");
396  return nullptr;
397  }
398  int iAxis = 0;
399  TAxis * a = fres->GetAxis(iAxis);
400  if (!a) {
401  Printf("Error: 'parameters' axis was not found !!!");
402  return nullptr;
403  }
404  int iLablel = 1;
405  for (auto & n : gCfg["ndmspc"]["result"]["parameters"]["labels"]) {
406  a->SetNameTitle(names.at(iAxis).c_str(), titles.at(iAxis).c_str());
407  a->SetBinLabel(iLablel++, n.get<std::string>().c_str());
408  }
409 
410  iAxis++;
411 
412  // cfg["ndmspc"]["output"]["post"]
413  // i = nDimsCuts + iPar + 1;
414  int iLabel;
415  int iPIdx = 0;
416  for (auto & axis : fCurrentProcessHistogramAxes) {
417  if (axis->GetXbins()->GetArray()) fres->GetAxis(iAxis)->Set(axis->GetNbins(), axis->GetXbins()->GetArray());
418  fres->GetAxis(iAxis)->SetNameTitle(names.at(iAxis).c_str(), titles.at(iAxis).c_str());
419 
420  for (iLabel = 1; iLabel < fCurrentProccessHistogram->GetAxis(iPIdx)->GetNbins() + 1; iLabel++) {
421  std::string l = fCurrentProccessHistogram->GetAxis(iPIdx)->GetBinLabel(iLabel);
422  if (!l.empty()) fres->GetAxis(iAxis)->SetBinLabel(iLabel, l.c_str());
423  }
424  fCurrentPoint[iAxis] = fCurrentProcessHistogramPoint[iPIdx];
425  iPIdx++;
426  iAxis++;
427  }
428 
429  // i = 1;
430  for (auto & a : cutAxes) {
431  // Printf("%s", )
432  fres->GetAxis(iAxis)->SetNameTitle(names.at(iAxis).c_str(), titles.at(iAxis).c_str());
433  if (a->GetXbins()->GetArray()) fres->GetAxis(iAxis)->Set(a->GetNbins(), a->GetXbins()->GetArray());
434  iAxis++;
435  }
436  int iPar = 0;
437  // int iLabel;
438  // for (auto & [key, value] : cfg["ndmspc"]["result"].items()) {
439  for (auto & value : gCfg["ndmspc"]["result"]["axes"]) {
440  iPar++;
441  iLabel = 1;
442  if (!value["labels"].is_null()) {
443  for (auto & n : value["labels"]) {
444  fres->GetAxis(iAxis)->SetNameTitle(names.at(iAxis).c_str(), titles.at(iAxis).c_str());
445  fres->GetAxis(iAxis)->SetBinLabel(iLabel++, n.get<std::string>().c_str());
446  }
447  }
448  iLabel = 1;
449  if (!value["ranges"].is_null()) {
450  for (auto & n : value["ranges"]) {
451  fres->GetAxis(iAxis)->SetNameTitle(names.at(iAxis).c_str(), titles.at(iAxis).c_str());
452  fres->GetAxis(iAxis)->SetBinLabel(iLabel++, n["name"].get<std::string>().c_str());
453  }
454  }
455  iAxis++;
456  }
457 
458  if (fVerbose >= 2) fres->Print("all");
459  // return nullptr;
460 
461  // TODO! port fres to fResultObject
462  if (fVerbose >= 2) Printf("[->] Ndmspc::PointRun::CreateResult fResultObject=%p", (void *)fres);
463  return fres;
464 }
465 
467 {
468  if (fVerbose >= 2) Printf("[<-] Ndmspc::PointRun::ApplyCuts");
469 
471  TString titlePostfix = "";
472  THnSparse * s;
473 
474  Int_t iCut = 0;
475  Int_t rebin = 1;
476  Int_t rebin_start = 1;
477 
478  fCurrentPoint[iCut] = 0;
479  for (size_t i = 0; i < fInputList->GetEntries(); i++) {
480  s = (THnSparse *)fInputList->At(i);
481  iCut = 1;
482  for (auto & cut : gCfg["ndmspc"]["cuts"]) {
483 
484  if (cut.is_null()) continue;
485 
486  if (cut["enabled"].is_boolean() && cut["enabled"].get<bool>() == false) continue;
487 
488  if (cut["rebin"].is_number_integer()) rebin = cut["rebin"].get<Int_t>();
489  if (cut["rebin_start"].is_number_integer()) rebin_start = cut["rebin_start"].get<Int_t>();
490 
491  if (cut["axis"].is_string() && cut["axis"].get<std::string>().empty()) {
492  std::cerr << "Error: Axis name is empty ('" << cut << "') !!! Exiting ..." << std::endl;
493  return false;
494  }
495  if (cut["bin"]["min"].get<Int_t>() < 0 || cut["bin"]["max"].get<Int_t>() < 0) {
496  std::cerr << "Error: Bin min or max is less then 0 ('" << cut << "') !!! Exiting ..." << std::endl;
497  return false;
498  }
499 
500  Int_t id = s->GetListOfAxes()->IndexOf(s->GetListOfAxes()->FindObject(cut["axis"].get<std::string>().c_str()));
501  if (id == s->GetListOfAxes()->GetEntries()) {
502  Printf("Axis '%s' was not found !!! Skipping ...", cut["axis"].get<std::string>().c_str());
503  return false;
504  }
505 
506  Int_t binLocal = Utils::GetBinFromBase(cut["bin"]["min"].get<int>(), rebin, rebin_start);
507  fCurrentPoint[iCut + fCurrentProcessHistogramPoint.size()] = binLocal;
508 
509  Int_t binMin = cut["bin"]["min"].get<Int_t>();
510  Int_t binMax = cut["bin"]["max"].get<Int_t>();
511  // Ndmspc::Utils::RebinBins(binMin, binMax, rebin);
512  // Int_t binDiff = cut["bin"]["max"].get<Int_t>() - cut["bin"]["min"].get<Int_t>() + 1;
513  // Int_t binMin = binLocal;
514  // Int_t binMax = binLocal + rebin * binDiff - 1;
515  if (fVerbose >= 2)
516  Printf("cut=%s binLocal=%d binMin=%d binMax=%d", cut["axis"].get<std::string>().c_str(), binLocal, binMin,
517  binMax);
518  s->GetAxis(id)->SetRange(binMin, binMax);
519 
520  if (i == 0) {
521  if (s->GetAxis(id)->IsAlphanumeric()) {
522  titlePostfix +=
523  TString::Format("%s[%s bin=%d] ", s->GetAxis(id)->GetName(), s->GetAxis(id)->GetBinLabel(binMin), binMin);
524  }
525  else {
526  titlePostfix += TString::Format("%s[%.2f,%.2f] ", s->GetAxis(id)->GetName(),
527  s->GetAxis(id)->GetBinLowEdge(binMin), s->GetAxis(id)->GetBinUpEdge(binMax));
528  }
529  }
530  iCut++;
531  }
532  }
533  if (!titlePostfix.IsNull()) {
534  titlePostfix.Remove(titlePostfix.Length() - 1);
535  Printf("Processing '%s' ...", titlePostfix.Data());
536  gCfg["ndmspc"]["projection"]["title"] = titlePostfix.Data();
537  }
538 
539  if (fVerbose >= 2) Printf("[->] Ndmspc::PointRun::ApplyCuts");
540  return true;
541 }
542 bool PointRun::ProcessSinglePoint()
543 {
544  if (fVerbose >= 2) Printf("[<-] Ndmspc::PointRun::ProcessSinglePoint");
545 
546  fIsProcessOk = false;
547 
548  if (!ApplyCuts()) return false;
549 
550  fIsSkipBin = false;
551 
552  if (fResultObject != nullptr) {
553  delete fResultObject;
554  fResultObject = nullptr;
555  }
556  fResultObject = CreateResult();
557  // fResultObject->Print();
558 
559  json resultAxes = gCfg["ndmspc"]["result"]["axes"];
560 
561  std::vector<std::string> names;
562  for (auto & value : resultAxes) {
563  std::string n = value["name"].get<std::string>();
564  names.push_back(n.c_str());
565  }
566 
567  // OutputFileOpen(cfg);
568 
569  if (fVerbose >= 1) Printf("Starting User Process() ...");
570  fBinCount++;
571  bool ok = ProcessRecursiveInner(resultAxes.size() - 1, names);
572 
573  if (fVerbose >= 1) Printf("User Process() done ...");
574 
575  // Store add fResultObject to final file
576  OutputFileClose();
577 
578  if (!fIsProcessOk) {
579  if (fVerbose >= 0) Printf("Skipping ...");
580  }
581 
582  if (fVerbose >= 2) Printf("[->] Ndmspc::PointRun::ProcessSinglePoint");
583  return true;
584 }
585 bool PointRun::ProcessRecursive(int i)
586 {
587  if (fVerbose >= 2) Printf("[<-] Ndmspc::PointRun::ProcessRecursive[%d]", i);
588 
589  if (i < 0) {
590  return ProcessSinglePoint();
591  }
592 
593  THnSparse * s = (THnSparse *)fInputList->At(0);
594  TAxis * a = (TAxis *)s->GetListOfAxes()->FindObject(gCfg["ndmspc"]["cuts"][i]["axis"].get<std::string>().c_str());
595  if (a == nullptr) {
596  Printf("Error: Axis canot be found");
597  return false;
598  }
599  Int_t start = 1;
600  Int_t end = a->GetNbins();
601  Int_t rebin = 1;
602  Int_t rebin_start = 1;
603  Int_t rebin_minimum = 1;
604  if (gCfg["ndmspc"]["cuts"][i]["rebin"].is_number_integer()) rebin = gCfg["ndmspc"]["cuts"][i]["rebin"].get<Int_t>();
605  if (gCfg["ndmspc"]["cuts"][i]["rebin_start"].is_number_integer())
606  rebin_start = gCfg["ndmspc"]["cuts"][i]["rebin_start"].get<Int_t>();
607 
608  gCfg["ndmspc"]["cuts"][i]["rebin_minimum"] = rebin_minimum;
609  if (rebin > 1) end /= rebin;
610  if (rebin_start > 1) {
611  rebin_minimum = (rebin_start % rebin);
612  gCfg["ndmspc"]["cuts"][i]["rebin_minimum"] = rebin_minimum;
613  start = (rebin_start / rebin) + 1;
614  end = (a->GetNbins() - rebin_minimum + 1) / rebin;
615  // Printf("%s start=%d end=%d rebin=%d nbins=%d rebin_start=%d rebin_minimum=%d", a->GetName(), start, end, rebin,
616  // a->GetNbins(), rebin_start, rebin_minimum);
617  // exit(1);
618  }
619 
620  if (gCfg["ndmspc"]["process"]["ranges"].is_array()) {
621  int range_min = gCfg["ndmspc"]["process"]["ranges"][i][0].get<int>();
622  int range_max = gCfg["ndmspc"]["process"]["ranges"][i][1].get<int>();
623  if (range_max > end || range_min < start || range_min > range_max || range_min > end || range_max < start) {
624  Printf("Error: Process range is out of bounds histogram(after rebin)=[%d,%d] request=[%d,%d] or requested min is "
625  "higher then requested max !!!",
626  start, end, range_min, range_max);
627  gSystem->Exit(1);
628  }
629  start = range_min;
630  if (gCfg["ndmspc"]["process"]["ranges"][i][1] < end) end = range_max;
631  // TODO: Handle rebin and rebin_start
632  }
633 
634  for (Int_t iBin = start; iBin <= end; iBin++) {
635  Int_t binMin = (iBin - 1) * rebin + rebin_minimum;
636  Int_t binMax = (iBin * rebin) - 1 + rebin_minimum;
637  if (fVerbose >= 2)
638  Printf("axis=%s rebin=%d rebin_minimum=%d binMin=%d binMax=%d [%f,%f]", a->GetName(), rebin, rebin_minimum,
639  binMin, binMax, a->GetBinLowEdge(binMin), a->GetBinUpEdge(binMax));
640  gCfg["ndmspc"]["cuts"][i]["bin"]["min"] = binMin;
641  gCfg["ndmspc"]["cuts"][i]["bin"]["max"] = binMax;
642  ProcessRecursive(i - 1);
643  }
644 
645  if (fVerbose >= 2) Printf("[->] Ndmspc::PointRun::ProcessRecursive[%d]", i);
646 
647  return true;
648 }
649 bool PointRun::ProcessRecursiveInner(Int_t i, std::vector<std::string> & n)
650 {
651  if (fVerbose >= 2) Printf("[<-] Ndmspc::PointRun::ProcessRecursiveInner[%d]", i);
652 
653  if (fIsSkipBin) return false;
654 
655  if (!fResultObject) {
656  fIsProcessExit = true;
657  return false;
658  }
659 
660  if (fIsProcessExit) gSystem->Exit(1);
661 
662  if (i < 0) {
663  TList * outputList = new TList();
664  SetOutputList(outputList);
665  if (fBinCount == 1 && fVerbose >= 0 && !fCurrentPointValue.is_null())
666  Printf("\tPoint: %s", fCurrentPointValue.dump().c_str());
667 
668  // TODO! Apply TMacro
669  if (fVerbose >= 2) Printf("Running point macro '%s.C' ...", fMacro->GetName());
670  /*fMacro.Exec();*/
671 
672  {
673  /*TRedirectOutputGuard g{"/dev/null"};*/
674  /*Longptr_t ok = fMacro->Exec(TString::Format("(Ndmspc::PointRun*)%p", this));*/
675  /*Longptr_t ok = fMacro->Exec(TString::Format("(Ndmspc::PointRun*)%p", this));*/
676  Longptr_t ok = gROOT->ProcessLine(TString::Format("%s((Ndmspc::PointRun*)%p);", fMacro->GetName(), this));
677  /*fMacro.Exec(TString::Format("(TList*)%p,(json*)%p", fInputList, &gCfg));*/
678 
679  /*fMacro.Exec(TString::Format("(TList*)%ld,(json&)%p,(THnSparse "*/
680  /* "*)%ld,(int*)%ld,(std::vector<std::string>*)%ld,(json*)%ld,(TList*)%ld,0,0",*/
681  /* (Longptr_t)fInputList, &gCfg, (Longptr_t)fResultObject,*/
682  /* (Longptr_t)fCurrentPoint, (Longptr_t)&fCurrentPointLabels,*/
683  /* (Longptr_t)&fCurrentPointValue, (Longptr_t)outputList)*/
684  /* .Data());*/
685  /*bool ok = NdmspcPointMacro(_currentInputList, cfg, fResultObject, _currentPoint, _currentPointLabels,*/
686  /* _currentPointValue, outputList, _currentSkipBin, _currentProcessExit);*/
687  /*gSystem->Exit(0);*/
688  if (ok && fVerbose >= 5) outputList->Print();
689  if (ok) {
690  fIsProcessOk = true;
691  }
692  else {
693  return false;
694  }
695  }
696  if (fCurrentOutputFile == nullptr) {
697  OutputFileOpen();
698  }
699 
700  TDirectory * outputDir = fCurrentOutputRootDirectory;
701 
702  int iPoint = 1;
703  std::string path;
704  for (int iPoint = 1; iPoint < fResultObject->GetNdimensions(); iPoint++) {
705  path += std::to_string(fCurrentPoint[iPoint]) + "/";
706  }
707 
708  // if (gCfg["ndmspc"]["output"]["post"].is_string()) {
709  // std::string post = gCfg["ndmspc"]["output"]["post"].get<std::string>();
710  // if (!post.empty()) {
711  // path += post;
712  // }
713  // }
714 
715  // Printf("path='%s'", path.c_str());
716 
717  fCurrentOutputRootDirectory->mkdir(path.c_str(), "", true);
718  outputDir = fCurrentOutputRootDirectory->GetDirectory(path.c_str());
719 
720  outputDir->cd();
721  outputList->Write();
722  return true;
723  }
724 
725  std::string axisName = gCfg["ndmspc"]["result"]["axes"][i]["name"].get<std::string>();
726  if (!gCfg["ndmspc"]["result"]["axes"][i]["labels"].is_null()) {
727  for (auto & v : gCfg["ndmspc"]["result"]["axes"][i]["labels"]) {
728  TAxis * a = (TAxis *)fResultObject->GetListOfAxes()->FindObject(axisName.c_str());
729  Int_t id = fResultObject->GetListOfAxes()->IndexOf(a);
730  fCurrentPoint[id] = a->FindBin(v.get<std::string>().c_str());
731  fCurrentPointValue[axisName] = v;
732  fCurrentPointLabels[id] = v.get<std::string>().c_str();
733  ProcessRecursiveInner(i - 1, n);
734  }
735  }
736  else if (!gCfg["ndmspc"]["result"]["axes"][i]["ranges"].is_null()) {
737  for (auto & v : gCfg["ndmspc"]["result"]["axes"][i]["ranges"]) {
738  TAxis * a = (TAxis *)fResultObject->GetListOfAxes()->FindObject(axisName.c_str());
739  Int_t id = fResultObject->GetListOfAxes()->IndexOf(a);
740  fCurrentPoint[id] = a->FindBin(v["name"].get<std::string>().c_str());
741  fCurrentPointValue[axisName] = v;
742  fCurrentPointLabels[id] = v["name"].get<std::string>().c_str();
743  ProcessRecursiveInner(i - 1, n);
744  }
745  }
746  else {
747  Printf("Error: ProcessRecursiveInner : No 'labels' or 'ranges' !!!");
748  return false;
749  }
750  return true;
751 
752  if (fVerbose >= 2) Printf("[->] Ndmspc::PointRun::ProcessRecursiveInner[%d]", i);
753  return true;
754 }
755 void PointRun::OutputFileOpen()
756 {
757 
758  if (fVerbose >= 2) Printf("[<-] Ndmspc::PointRun::OutputFileOpen");
759 
760  // TString outputFileName;
761 
762  fCurrentOutputFileName = "";
763 
764  if (!gCfg["ndmspc"]["output"]["host"].get<std::string>().empty())
765  fCurrentOutputFileName += gCfg["ndmspc"]["output"]["host"].get<std::string>().c_str();
766  if (!gCfg["ndmspc"]["output"]["dir"].get<std::string>().empty())
767  fCurrentOutputFileName += gCfg["ndmspc"]["output"]["dir"].get<std::string>().c_str();
768 
769  if (gCfg["ndmspc"]["cuts"].is_array() && !fCurrentOutputFileName.empty()) {
770 
771  // std::string axisName;
772  // std::string rebinStr = "";
773  // // cfgOutput["ndmspc"]["cuts"] = gCfg["ndmspc"]["cuts"];
774  // for (auto & cut : gCfg["ndmspc"]["cuts"]) {
775  // if (cut["enabled"].is_boolean() && cut["enabled"].get<bool>() == false) continue;
776  // Int_t rebin = 1;
777  // Int_t rebin_start = 1;
778  // Int_t rebin_minimum = 1;
779  //
780  // if (cut["rebin"].is_number_integer()) rebin = cut["rebin"].get<Int_t>();
781  // if (cut["rebin_start"].is_number_integer()) rebin_start = cut["rebin_start"].get<Int_t>();
782  //
783  // if (rebin_start > 1) {
784  // rebin_minimum = (rebin_start % rebin);
785  // }
786  //
787  // if (axisName.length() > 0) {
788  // axisName += "_";
789  // rebinStr += "_";
790  // }
791  // axisName += cut["axis"].get<std::string>();
792  // rebinStr += std::to_string(rebin);
793  // rebinStr += "-";
794  // rebinStr += std::to_string(rebin_minimum);
795  // }
796  std::string cutsName = Utils::GetCutsPath(gCfg["ndmspc"]["cuts"]);
797  // Printf("cutsName='%s'", cutsName.c_str());
798  // exit(1);
799 
800  if (cutsName.length() > 0) {
801  fCurrentOutputFileName += "/";
802  fCurrentOutputFileName += gCfg["ndmspc"]["environment"].get<std::string>().c_str();
803  fCurrentOutputFileName += "/";
804  fCurrentOutputFileName += cutsName.c_str();
805  // fCurrentOutputFileName += "/";
806  fCurrentOutputFileName += "bins";
807  fCurrentOutputFileName += "/";
808 
809  // TODO: check what is it used for. Remove it if not needed
810  if (gCfg["ndmspc"]["output"]["post"].is_string()) {
811  std::string post = gCfg["ndmspc"]["output"]["post"].get<std::string>();
812  if (!post.empty()) {
813  if (!fCurrentOutputFileName.empty() && fCurrentOutputFileName[fCurrentOutputFileName.size() - 1] != '/')
814  fCurrentOutputFileName += "/";
815  // _currentOutputFileName += "/bins/" + post;
816  fCurrentOutputFileName += post;
817  }
818  }
819 
820  for (auto & cut : gCfg["ndmspc"]["cuts"]) {
821  if (cut["enabled"].is_boolean() && cut["enabled"].get<bool>() == false) continue;
822  Int_t rebin = 1;
823  Int_t rebin_start = 1;
824  Int_t rebin_minimum = 1;
825 
826  if (cut["rebin"].is_number_integer()) rebin = cut["rebin"].get<Int_t>();
827  if (cut["rebin_start"].is_number_integer()) rebin_start = cut["rebin_start"].get<Int_t>();
828 
829  if (rebin_start > 1) {
830  rebin_minimum = (rebin_start % rebin);
831  if (rebin_minimum == 0) rebin_minimum = 1;
832  }
833 
834  Int_t bin_min = cut["bin"]["min"].get<Int_t>();
835  // Printf("bin_min=%d rebin_start=%d rebin=%d %d", bin_min, rebin_start, rebin,
836  // (bin_min - rebin_minimum) / rebin + 1);
837  Int_t bin_min_converted = (bin_min - rebin_minimum) / rebin + 1;
838  fCurrentOutputFileName += std::to_string(bin_min_converted) + "/";
839  }
840  }
841  }
842  else {
843  fCurrentOutputFileName += gCfg["ndmspc"]["environment"].get<std::string>().c_str();
844  fCurrentOutputFileName += "/";
845  }
846 
847  if (!fCurrentOutputFileName.empty() && fCurrentOutputFileName[fCurrentOutputFileName.size() - 1] != '/')
848  fCurrentOutputFileName += "/";
849 
850  if (!gCfg["ndmspc"]["output"]["file"].get<std::string>().empty())
851  fCurrentOutputFileName += gCfg["ndmspc"]["output"]["file"].get<std::string>().c_str();
852 
853  fCurrentOutputFileName = gSystem->ExpandPathName(fCurrentOutputFileName.c_str());
854  fCurrentOutputFile =
855  Ndmspc::Utils::OpenFile(TString::Format("%s%s", fCurrentOutputFileName.c_str(),
856  gCfg["ndmspc"]["output"]["opt"].get<std::string>().c_str())
857  .Data(),
858  "RECREATE");
859  // _currentOutputFile->cd();
860 
861  fCurrentOutputFile->mkdir("content");
862  fCurrentOutputRootDirectory = fCurrentOutputFile->GetDirectory("content");
863  fCurrentOutputRootDirectory->cd();
864 
865  if (fVerbose >= 2) Printf("[->] Ndmspc::PointRun::OutputFileOpen");
866 }
867 void PointRun::OutputFileClose()
868 {
869  if (fVerbose >= 2) Printf("[<-] Ndmspc::PointRun::OutputFileClose");
870 
871  if (fCurrentOutputFile == nullptr) return;
872 
873  if (fVerbose >= 2) Printf("Closing file '%s' ...", fCurrentOutputFileName.c_str());
874  fCurrentOutputRootDirectory->Write();
875 
876  fCurrentOutputFile->cd();
877  fResultObject->Write();
878  fMapAxesType->Write();
879  fCurrentOutputFile->Close();
880 
881  fCurrentOutputFile = nullptr;
882  fCurrentOutputRootDirectory = nullptr;
883 
884  if (fVerbose >= 0) Printf("Objects stored in '%s'", fCurrentOutputFileName.c_str());
885 
886  if (fVerbose >= 2) Printf("[->] Ndmspc::PointRun::OutputFileClose");
887 }
888 bool PointRun::Finish()
889 {
890 
891  if (fVerbose >= 2) Printf("[<-] Ndmspc::PointRun::Finish");
892  if (fInputList) {
893  fInputList->Clear();
894  delete fInputList;
895  fInputList = nullptr;
896  }
897 
898  if (fInputFile) {
899  fInputFile->Close();
900  delete fInputFile;
901  fInputFile = nullptr;
902  }
903  if (fVerbose >= 2) Printf("[->] Ndmspc::PointRun::Finish");
904 
905  return true;
906 }
907 int PointRun::ProcessSingleFile()
908 {
909 
910  std::string type;
911  if (gCfg["ndmspc"]["process"]["type"].is_string()) type = gCfg["ndmspc"]["process"]["type"].get<std::string>();
912 
913  if (type.empty()) {
914  Printf("Warning: [ndmspc][process][type] is missing or is empty in configuration !!! Setting it ot 'single' ...");
915  type = "single";
916  gCfg["ndmspc"]["process"]["type"] = type;
917  }
918 
919  TList * inputList = OpenInputs();
920  if (inputList == nullptr) return 1;
921 
922  if (!type.compare("single")) {
923  if (!ProcessSinglePoint()) return 3;
924  }
925  else if (!type.compare("all")) {
926  json cuts;
927  int iCut = 0;
928  for (auto & cut : gCfg["ndmspc"]["cuts"]) {
929  if (cut["enabled"].is_boolean() && cut["enabled"].get<bool>() == false) continue;
930  cuts[iCut++] = cut;
931  }
932  gCfg["ndmspc"]["cuts"] = cuts;
933 
934  ProcessRecursive(gCfg["ndmspc"]["cuts"].size() - 1);
935  }
936  else {
937  Printf("Error: Value [process][type]='%s' is not supported !!! Exiting ...", type.c_str());
938  return 4;
939  }
940  Finish();
941 
942  /*/// TODO! Handle failure*/
943  /*Init();*/
944  /*/// TODO! Handle failure*/
945  /*OpenInputs();*/
946 
947  /*Printf("Running point macro '%s.C' ...", fMacro.GetName());*/
948  /*fMacro.Exec();*/
949  return 0;
950 }
951 int PointRun::ProcessHistogramRun()
952 {
953 
954  if (fVerbose >= 2) Printf("[->] Ndmspc::PointRun::ProcessHistogramRun");
955 
956  std::string fileNameHistogram = gCfg["ndmspc"]["data"]["histogram"]["file"].get<std::string>();
957  std::string objName = gCfg["ndmspc"]["data"]["histogram"]["obj"].get<std::string>();
958 
959  TFile * fProccessHistogram = Ndmspc::Utils::OpenFile(fileNameHistogram.c_str());
960  if (!fProccessHistogram) {
961  Printf("Error: Proccess input histogram file '%s' could not opened !!!", fileNameHistogram.c_str());
962  return 1;
963  }
964  fCurrentProccessHistogram = (THnSparse *)fProccessHistogram->Get(objName.c_str());
965  if (!fCurrentProccessHistogram) {
966  Printf("Error: Proccess input histogram object '%s' could not opened !!!", objName.c_str());
967  return 1;
968  }
969  TObjArray * axesArray = fCurrentProccessHistogram->GetListOfAxes();
970  for (int iAxis = 0; iAxis < axesArray->GetEntries(); iAxis++) {
971 
972  TAxis * aTmp = (TAxis *)axesArray->At(iAxis);
973  // Printf("axis=%s", aTmp->GetName());
974  fCurrentProcessHistogramAxes.push_back(aTmp);
975  }
976 
977  if (gCfg["ndmspc"]["data"]["histogram"]["bins"].is_array()) {
978 
979  for (auto & v : gCfg["ndmspc"]["data"]["histogram"]["bins"]) {
980  Printf("%s", v.dump().c_str());
981  int i = 0;
982  Int_t p[v.size()];
983  for (auto & idx : v) {
984  p[i] = idx;
985  // _currentProcessHistogramPoint.push_back(idx);
986  i++;
987  }
988  fCurrentProccessHistogram->SetBinContent(p, 1);
989  }
990  }
991  /*fCurrentProccessHistogram->Print();*/
992  if (fCurrentProccessHistogram->GetNbins()) {
993  Int_t proccessPoint[fCurrentProccessHistogram->GetNdimensions()];
994  for (int iBin = 0; iBin < fCurrentProccessHistogram->GetNbins(); iBin++) {
995  fCurrentProcessHistogramPoint.clear();
996  fCurrentProccessHistogram->GetBinContent(iBin, proccessPoint);
997  // Printf("iBin=%d %d %d", iBin, proccessPoint[0], proccessPoint[1]);
998 
999  std::string path;
1000  for (auto & p : proccessPoint) {
1001  // printf("%d ", p);
1002  fCurrentProcessHistogramPoint.push_back(p);
1003  path += std::to_string(std::abs(p)) + "/";
1004  }
1005  // printf("\n");
1006  std::string fullPath = gCfg["ndmspc"]["data"]["histogram"]["base"].get<std::string>();
1007  fullPath += "/";
1008  fullPath += path;
1009  fullPath += gCfg["ndmspc"]["data"]["histogram"]["filename"].get<std::string>();
1010  // Printf("Path: %s %s", path.c_str(), fullPath.c_str());
1011  gCfg["ndmspc"]["data"]["file"] = fullPath;
1012 
1013  gCfg["ndmspc"]["output"]["post"] = path;
1014 
1015  // return 0;
1016  Init(path);
1017  Int_t rc = ProcessSingleFile();
1018  if (rc) {
1019  return rc;
1020  }
1021  }
1022  }
1023  else {
1024  Printf("Error: No entries in proccess histogram !!! Nothing to process !!!");
1025  return 1;
1026  }
1027 
1028  if (fVerbose >= 2) Printf("[->] Ndmspc::PointRun::ProcessHistogramRun");
1029  return 0;
1030 }
1031 bool PointRun::Run(std::string filename, std::string userConfig, std::string environment, std::string userConfigRaw,
1032  bool show, std::string outfilename)
1033 {
1034  if (fVerbose >= 2) Printf("[<-] Ndmspc::PointRun::Run");
1035 
1036  if (!fMacro) return 1;
1037 
1038  if (!LoadConfig(filename, userConfig, environment, userConfigRaw, show, outfilename)) return false;
1039  /*fVerbose = 2;*/
1040 
1041  if (!gCfg["ndmspc"]["data"]["histogram"].is_null() && !gCfg["ndmspc"]["data"]["histogram"]["enabled"].is_null() &&
1042  gCfg["ndmspc"]["data"]["histogram"]["enabled"].get<bool>() == true) {
1043  ProcessHistogramRun();
1044  }
1045  else {
1046  ProcessSingleFile();
1047  }
1048  if (fVerbose >= 2) Printf("[->] Ndmspc::PointRun::Run");
1049  return true;
1050 }
1051 
1052 bool PointRun::Generate(std::string name, std::string inFile, std::string inObjectName)
1053 {
1054 
1058 
1059  Printf("Genrating point run with name '%s' ...", name.c_str());
1060  json cfg = R"({
1061 
1062  "user": {
1063  "proj": 0,
1064  "minEntries": 1,
1065  "verbose": 0
1066  },
1067  "ndmspc": {
1068  "environments": {
1069  "local": {
1070  "output": { "dir": "$HOME/.ndmspc/analyses/generated", "host": "" }
1071  },
1072  },
1073  "environment": "local",
1074  "data": {
1075  "file": "input.root",
1076  "objects": ["hNSparse"]
1077  },
1078  "cuts": [],
1079  "result": {
1080  "parameters": { "labels": ["Integral"], "default": "Integral" }
1081  },
1082  "output": {
1083  "host": "",
1084  "dir": "",
1085  "file": "content.root",
1086  "opt": "?remote=1"
1087  },
1088  "process": {
1089  "type": "single"
1090  },
1091  "log": {
1092  "type": "error-only",
1093  "dir": "root://eos.ndmspc.io//eos/ndmspc/scratch/ndmspc/logs"
1094  },
1095  "job":{
1096  "inputs": []
1097  },
1098  "verbose": 0
1099  }
1100 })"_json;
1101 
1102  std::string macroTemplateHeader = R""""(
1103 #include <TROOT.h>
1104 #include <TList.h>
1105 #include <THnSparse.h>
1106 #include <TH1D.h>
1107 #include <ndmspc/PointRun.h>
1108 #include <ndmspc/Utils.h>
1109 )"""";
1110 
1111  std::string macroTemplate = R""""(
1112 {
1113  json cfg = pr->Cfg();
1114  TList * inputList = pr->GetInputList();
1115  THnSparse * resultObject = pr->GetResultObject();
1116  Int_t * point = pr->GetCurrentPoint();
1117  std::vector<std::string> pointLabels = pr->GetCurrentPointLabels();
1118  json pointValue = pr->GetCurrentPointValue();
1119  TList * outputList = pr->GetOutputList();
1120 
1121  int verbose = 0;
1122  if (!cfg["user"]["verbose"].is_null() && cfg["user"]["verbose"].is_number_integer()) {
1123  verbose = cfg["user"]["verbose"].get<int>();
1124  }
1125 
1126  THnSparse * hs = (THnSparse *)inputList->At(0);
1127 
1128  int projId = cfg["user"]["proj"].get<int>();
1129  TH1D * h = hs->Projection(projId, "O");
1130 
1131  TString titlePostfix = "(no cuts)";
1132  if (cfg["ndmspc"]["projection"]["title"].is_string())
1133  titlePostfix = cfg["ndmspc"]["projection"]["title"].get<std::string>();
1134  h->SetNameTitle("h", TString::Format("h - %s", titlePostfix.Data()).Data());
1135  outputList->Add(h);
1136 
1137  // Skip bin (do not save any output)
1138  if (h->GetEntries() < cfg["user"]["minEntries"].get<int>())
1139  return false;
1140 
1141  Double_t integral = h->Integral();
1142  if (verbose >= 0)
1143  Printf("Integral = %f ", integral);
1144 
1145 
1146  if (resultObject) {
1147  Ndmspc::Utils::SetResultValueError(cfg, resultObject, "Integral", point, integral, TMath::Sqrt(integral), false, true);
1148  }
1149 
1150  if (!gROOT->IsBatch() && !cfg["ndmspc"]["process"]["type"].get<std::string>().compare("single")) {
1151  h->DrawCopy();
1152  }
1153 
1154  return true;
1155 }
1156 
1157 )"""";
1158 
1159  cfg["ndmspc"]["data"]["file"] = inFile.c_str();
1160  cfg["ndmspc"]["data"]["objects"] = {inObjectName.c_str()};
1161 
1162  if (cfg["ndmspc"]["cuts"].size() == 0) {
1163  // Generate all axis
1164  // {"enabled": false, "axis": "hNSparseAxisName", "bin" : {"min":3, "max": 3}, "rebin":1}
1165  TFile * tmpFile = Ndmspc::Utils::OpenFile(inFile.c_str());
1166  if (!tmpFile) {
1167  Printf("Error: Problem opening file '%s' !!! Exiting ...", inFile.c_str());
1168  return 1;
1169  }
1170 
1171  THnSparse * tmpSparse = (THnSparse *)tmpFile->Get(inObjectName.c_str());
1172  if (!tmpSparse) {
1173  Printf("Error: Problem opening object '%s' !!! Exiting ...", inObjectName.c_str());
1174  return 1;
1175  }
1176  tmpSparse->ls();
1177  TObjArray * axes = tmpSparse->GetListOfAxes();
1178  TAxis * a;
1179  for (int i = 0; i < axes->GetEntries(); i++) {
1180  a = (TAxis *)axes->At(i);
1181  if (!a) continue;
1182  // a->Print();
1183  Printf("Init axis '%s' with enabled=false", a->GetName());
1184  cfg["ndmspc"]["cuts"][i]["enabled"] = false;
1185  cfg["ndmspc"]["cuts"][i]["axis"] = a->GetName();
1186  cfg["ndmspc"]["cuts"][i]["bin"]["min"] = 1;
1187  cfg["ndmspc"]["cuts"][i]["bin"]["max"] = 1;
1188  cfg["ndmspc"]["cuts"][i]["rebin"] = 1;
1189  }
1190 
1191  tmpFile->Close();
1192  }
1193 
1194  std::string outputConfig = name + ".json";
1195  std::ofstream fileConfig(outputConfig.c_str());
1196  fileConfig << std::setw(2) << cfg << std::endl;
1197 
1198  std::string outputMacro = name + ".C";
1199  std::ofstream file(outputMacro.c_str());
1200  file << macroTemplateHeader.c_str();
1201  file << "bool " << name.c_str() << "(Ndmspc::PointRun *pr)";
1202  file << macroTemplate.c_str();
1203 
1204  Printf("File '%s.C' and '%s.json' were generated ...", name.c_str(), name.c_str());
1205  return true;
1206 }
1207 
1208 bool PointRun::Merge(std::string config, std::string userConfig, std::string environment, std::string userConfigRaw,
1209  std::string fileOpt)
1210 {
1214 
1215  if (!Core::LoadConfig(config, userConfig, environment, userConfigRaw)) return false;
1216 
1217  if (gCfg["ndmspc"]["output"]["host"].get<std::string>().empty()) {
1218  gCfg["ndmspc"]["output"]["opt"] = "";
1219  }
1220 
1221  std::string hostUrl = gCfg["ndmspc"]["output"]["host"].get<std::string>();
1222  // if (hostUrl.empty()) {
1223  // Printf("Error: cfg[ndmspc][output][host] is empty!!!");
1224  // return 2;
1225  // }
1226  std::string path;
1227  if (!hostUrl.empty()) path = hostUrl + "/";
1228  path += gCfg["ndmspc"]["output"]["dir"].get<std::string>() + "/";
1229 
1230  path += environment + "/";
1231 
1232  // int nDimsCuts = 0;
1233  // std::string rebinStr = "";
1234  // for (auto & cut : gCfg["ndmspc"]["cuts"]) {
1235  // if (cut["enabled"].is_boolean() && cut["enabled"].get<bool>() == false) continue;
1236  // path += cut["axis"].get<std::string>() + "_";
1237  // rebinStr += std::to_string(cut["rebin"].get<Int_t>()) + "_";
1238  // nDimsCuts++;
1239  // }
1240  // path[path.size() - 1] = '/';
1241  // path += rebinStr;
1242  // path[path.size() - 1] = '/';
1243  path += Utils::GetCutsPath(gCfg["ndmspc"]["cuts"]);
1244 
1245  path = gSystem->ExpandPathName(path.c_str());
1246 
1247  std::string outFile = path + "results.root";
1248 
1249  path += "bins";
1250 
1251  TUrl url(path.c_str());
1252  std::string outHost = url.GetHost();
1253  std::string inputDirectory = url.GetFile();
1254  std::string linesMerge = "";
1255 
1256  if (outHost.empty()) {
1257  if (gSystem->AccessPathName(path.c_str())) {
1258  Printf("Error: Nothing to merge, because path '%s' does not exist !!!", path.c_str());
1259  return false;
1260  }
1261  Printf("Doing local find %s -name %s", path.c_str(), gCfg["ndmspc"]["output"]["file"].get<std::string>().c_str());
1262  linesMerge = gSystem->GetFromPipe(
1263  TString::Format("find %s -name %s", path.c_str(), gCfg["ndmspc"]["output"]["file"].get<std::string>().c_str())
1264  .Data());
1265  // Printf("%s", linesMerge.c_str());
1266  // gSystem->Exit(1);
1267  }
1268  else {
1269 
1270  Printf("Doing eos find -f %s", path.c_str());
1271 
1272  std::string contentFile = gCfg["ndmspc"]["output"]["file"].get<std::string>();
1273  TString findUrl;
1274 
1275  // Vector of string to save tokens
1276  std::vector<std::string> tokens;
1277 
1278  if (!inputDirectory.empty()) {
1279  findUrl = TString::Format(
1280  "root://%s//proc/user/?mgm.cmd=find&mgm.find.match=%s&mgm.path=%s&mgm.format=json&mgm.option=f&filetype=raw",
1281  outHost.c_str(), contentFile.c_str(), inputDirectory.c_str());
1282 
1283  TFile * f = Ndmspc::Utils::OpenFile(findUrl.Data());
1284  if (!f) return 1;
1285 
1286  // Printf("%lld", f->GetSize());
1287 
1288  int buffsize = 4096;
1289  char buff[buffsize + 1];
1290 
1291  Long64_t buffread = 0;
1292  std::string content;
1293  while (buffread < f->GetSize()) {
1294 
1295  if (buffread + buffsize > f->GetSize()) buffsize = f->GetSize() - buffread;
1296 
1297  // Printf("Buff %lld %d", buffread, buffsize);
1298  f->ReadBuffer(buff, buffread, buffsize);
1299  buff[buffsize] = '\0';
1300  content += buff;
1301  buffread += buffsize;
1302  }
1303 
1304  f->Close();
1305 
1306  std::string ss = "mgm.proc.stdout=";
1307  size_t pos = ss.size() + 1;
1308  content = content.substr(pos);
1309 
1310  // stringstream class check1
1311  std::stringstream check1(content);
1312 
1313  std::string intermediate;
1314 
1315  // Tokenizing w.r.t. space '&'
1316  while (getline(check1, intermediate, '&')) {
1317  tokens.push_back(intermediate);
1318  }
1319  }
1320  else {
1321  tokens.push_back(contentFile.c_str());
1322  }
1323  linesMerge = tokens[0];
1324  }
1325  std::stringstream check2(linesMerge);
1326  std::string line;
1327  std::string outFileLocal = "/tmp/ndmspc-merged-" + std::to_string(gSystem->GetPid()) + ".root";
1328  bool copy = true;
1329  if (hostUrl.empty()) {
1330  outFileLocal = outFile;
1331  copy = false;
1332  }
1333  outFileLocal = gSystem->ExpandPathName(outFileLocal.c_str());
1334 
1335  TFileMerger m(kFALSE);
1336  m.OutputFile(TString::Format("%s%s", outFileLocal.c_str(), fileOpt.c_str()));
1337  // m.AddObjectNames("results");
1338  // m.AddObjectNames("content");
1339  // Int_t default_mode = TFileMerger::kAll | TFileMerger::kIncremental;
1340  // Int_t mode = default_mode | TFileMerger::kOnlyListed;
1341  while (std::getline(check2, line)) {
1342 
1343  Printf("Adding file '%s' ...", line.data());
1344  if (!outHost.empty()) {
1345  m.AddFile(TString::Format("root://%s/%s", outHost.c_str(), line.c_str()).Data());
1346  }
1347  else {
1348  m.AddFile(line.c_str());
1349  }
1350  }
1351 
1352  Printf("Merging ...");
1353  m.Merge();
1354  // m.PartialMerge(mode);
1355  if (copy) {
1356  Printf("Copy '%s' to '%s' ...", outFileLocal.c_str(), outFile.c_str());
1357  TFile::Cp(outFileLocal.c_str(), outFile.c_str());
1358  std::string rm = "rm -f " + outFileLocal;
1359  Printf("Doing '%s' ...", rm.c_str());
1360  gSystem->Exec(rm.c_str());
1361  }
1362  Printf("Output: '%s'", outFile.c_str());
1363  Printf("Done ...");
1364 
1365  return true;
1366 }
1367 
1368 } // namespace Ndmspc
PointRun object.
Definition: PointRun.h:23
TFile * fInputFile
Bin Count (TODO! rename to axis level maybe)
Definition: PointRun.h:53
bool Init(std::string extraPath="")
Definition: PointRun.cxx:73
int fBinCount
Verbose level.
Definition: PointRun.h:52
THnSparse * CreateResult()
Definition: PointRun.cxx:244
TList * OpenInputs()
Definition: PointRun.cxx:154
PointRun(std::string macro="NdmspcPointRun.C")
Definition: PointRun.cxx:24
virtual ~PointRun()
Definition: PointRun.cxx:35
int fVerbose
Macro.
Definition: PointRun.h:51
static bool Generate(std::string name="myAnalysis", std::string inFile="myFile.root", std::string inObjectName="myNDHistogram")
Definition: PointRun.cxx:1052
bool LoadConfig(std::string config, std::string userConfig="", std::string environment="", std::string userConfigRaw="", bool show=false, std::string outfilename="")
Environment.
Definition: PointRun.cxx:42
static TFile * OpenFile(std::string filename, std::string mode="READ", bool createLocalDir=true)
Definition: Utils.cxx:18