MaCh3  2.5.0
Reference Guide
Functions
M3::Utils Namespace Reference

Utility helpers used across MaCh3. More...

Functions

void MaCh3Welcome ()
 KS: Prints welcome message with MaCh3 logo. More...
 
std::string GetMaCh3Version ()
 KS: Get version of MaCh3. More...
 
void GetOSInfo ()
 KS: Find out more about operational system. More...
 
void GetCPUInfo ()
 KS: Check what CPU you are using. More...
 
void NThreadsSanity ()
 KS: Check if user is not using huge number of threads and throw error. More...
 
void GetGPUInfo ()
 KS: Check what GPU you are using. More...
 
void GetDiskUsage ()
 KS: Find out about Disk usage. More...
 
std::string TerminalToString (std::string cmd)
 KS: Convoluted code to grab output from terminal to string. More...
 
void EstimateDataTransferRate (TChain *chain, const Long64_t entry)
 KS: Check what CPU you are using. More...
 
void PrintProgressBar (const Long64_t Done, const Long64_t All)
 KS: Simply print progress bar. More...
 
int getValue (const std::string &Type)
 CW: Get info like RAM. More...
 
int parseLine (const std::string &line)
 CW: Get memory, which is probably silly. More...
 
void PrintConfig (const YAML::Node &node)
 KS: Print Yaml config using logger. More...
 
void Print (const TTree *tree)
 
void MaCh3Usage (int argc, char **argv)
 KS: Almost all MaCh3 executables have the same usage, prepare simple printer. More...
 
double GetMassFromPDG (const int PDG)
 Return mass for given PDG. More...
 
int PDGToNuOscillatorFlavour (const int NuPdg)
 Convert from PDG flavour to NuOscillator type beware that in the case of anti-neutrinos the NuOscillator type simply gets multiplied by -1. More...
 
std::string FormatDouble (const double value, const int precision)
 Convert double into string for precision, useful for playing with yaml if you don't want to have in config floating point precision... More...
 

Detailed Description

Utility helpers used across MaCh3.

Function Documentation

◆ EstimateDataTransferRate()

void M3::Utils::EstimateDataTransferRate ( TChain *  chain,
const Long64_t  entry 
)

KS: Check what CPU you are using.

Definition at line 212 of file Monitor.cpp.

212  {
213 // ************************
214  TStopwatch timer;
215 
216  timer.Start();
217  Int_t bytesProcessed{ chain->GetEntry(entry) };
218 
219  timer.Stop();
220 
221  Double_t timeInSeconds = timer.RealTime();
222  Double_t dataRateMBps = (double(bytesProcessed) / (1024.0 * 1024.0)) / timeInSeconds;
223 
224  MACH3LOG_INFO("Data transfer: {} B, rate: {:.2f} MB/s", bytesProcessed, dataRateMBps);
225 }
#define MACH3LOG_INFO
Definition: MaCh3Logger.h:35

◆ FormatDouble()

std::string M3::Utils::FormatDouble ( const double  value,
const int  precision 
)
inline

Convert double into string for precision, useful for playing with yaml if you don't want to have in config floating point precision...

Definition at line 833 of file SampleStructs.h.

833  {
834  // ***************************
835  std::ostringstream oss;
836  oss << std::fixed << std::setprecision(precision) << value;
837  return oss.str();
838  }

◆ GetCPUInfo()

void M3::Utils::GetCPUInfo ( )

KS: Check what CPU you are using.

Definition at line 100 of file Monitor.cpp.

100  {
101 // ************************
102  //KS: Use -m 1 to limit to only one grep because in one computing node there is a lot of CPU which are the same
103  MACH3LOG_INFO("Using following CPU:");
104 
105  MACH3LOG_INFO("{}", TerminalToString("cat /proc/cpuinfo | grep -m 1 name"));
106  MACH3LOG_INFO("{}", TerminalToString("cat /proc/cpuinfo | grep -m 1 MHz"));
107  //KS: Below code is convoluted because I mostly work on English based Linux but sometimes on Polish based Linux, this ensures it works on both. We can add support for other languages if needed
108  MACH3LOG_INFO("{}", TerminalToString("lscpu | grep -i Archit"));
109  MACH3LOG_INFO("{}", TerminalToString("lscpu | grep -m 1 -E 'L1d |L1d:'"));
110  MACH3LOG_INFO("{}", TerminalToString("lscpu | grep -m 1 -E 'L1i |L1i:'"));
111  MACH3LOG_INFO("{}", TerminalToString("lscpu | grep -m 1 -E 'L2 |L2:'"));
112  MACH3LOG_INFO("{}", TerminalToString("lscpu | grep -m 1 -E 'L3 |L3:'"));
113  MACH3LOG_INFO("{}", TerminalToString("lscpu | grep -m 1 -E 'Thread.* per core:|Wątków na rdzeń:'"));
114  MACH3LOG_INFO("{}", TerminalToString("lscpu | grep -m 1 -E '^CPU(:|\\(s\\)):?\\s+[0-9]+'"));
115  MACH3LOG_INFO("With available threads {}", M3::GetNThreads());
116 
117  NThreadsSanity();
118  //KS: /proc/cpuinfo and lscpu holds much more info I have limited it but one can expand it if needed
119 }
void NThreadsSanity()
KS: Check if user is not using huge number of threads and throw error.
Definition: Monitor.cpp:123
std::string TerminalToString(std::string cmd)
KS: Convoluted code to grab output from terminal to string.
Definition: Monitor.cpp:187
int GetNThreads()
number of threads which we need for example for TRandom3
Definition: Monitor.cpp:372

◆ GetDiskUsage()

void M3::Utils::GetDiskUsage ( )

KS: Find out about Disk usage.

Definition at line 177 of file Monitor.cpp.

177  {
178 // ************************
179  MACH3LOG_INFO("Disk Usage:");
180 
181  // Get disk usage
182  MACH3LOG_INFO("{}", TerminalToString("df -h --total | grep total"));
183 }

◆ GetGPUInfo()

void M3::Utils::GetGPUInfo ( )

KS: Check what GPU you are using.

Definition at line 144 of file Monitor.cpp.

144  {
145 // ************************
146 #ifdef MaCh3_CUDA
147  int nDevices;
148  cudaGetDeviceCount(&nDevices);
149  if (nDevices == 0) {
150  MACH3LOG_CRITICAL("MaCh3 compiled with CUDA support (for GPU acceleration) but could not find GPU");
151  MACH3LOG_CRITICAL("Either allocate GPU for your job or recompile MaCh3 without GPU support");
152  throw MaCh3Exception(__FILE__, __LINE__);
153  }
154 
155  MACH3LOG_INFO("Using following GPU:");
156  // Print GPU name
157  MACH3LOG_INFO("GPU Name: {}", TerminalToString("nvidia-smi --query-gpu=name --format=csv,noheader"));
158  // Print number of GPUs
159  MACH3LOG_INFO("Number of GPUs: {}", TerminalToString("nvidia-smi --query-gpu=count --format=csv,noheader"));
160  // Print total VRAM
161  MACH3LOG_INFO("Total VRAM: {} MB", TerminalToString("nvidia-smi --query-gpu=memory.total --format=csv,noheader,nounits"));
162  // Print Driver Version
163  MACH3LOG_INFO("Driver Version: {}", TerminalToString("nvidia-smi --query-gpu=driver_version --format=csv,noheader"));
164  // Print N GPU thread
165  MACH3LOG_INFO("Currently used GPU has: {} threads", GetNumGPUThreads());
166  // Print L2 cache
167  MACH3LOG_INFO("Currently used GPU has: {} KB L2 cache", GetL2CacheSize() / 1024);
168  // Shared memory info
169  MACH3LOG_INFO("Max shared memory per block: {} KB", GetSharedMemoryPerBlock() / 1024);
170  // Print 1D texture size
171  MACH3LOG_INFO("Max 1D texture size: {}", GetMaxTexture1DSize());
172 #endif
173 }
#define MACH3LOG_CRITICAL
Definition: MaCh3Logger.h:38
Custom exception class used throughout MaCh3.
size_t GetMaxTexture1DSize(const int device)
KS: Get the maximum size for 1D textures on the specified GPU device.
Definition: gpuUtils.cu:132
int GetNumGPUThreads(const int Device)
KS: Get number of GPU threads for currently used GPU.
Definition: gpuUtils.cu:100
size_t GetL2CacheSize(const int device)
KS: Get L2 cache size (in bytes) for the specified GPU device.
Definition: gpuUtils.cu:120
size_t GetSharedMemoryPerBlock(const int device)
KS: Returns the maximum shared memory per block for a given GPU device.
Definition: gpuUtils.cu:144

◆ GetMaCh3Version()

std::string M3::Utils::GetMaCh3Version ( )

KS: Get version of MaCh3.

Returns
The current MaCh3 version as a string.

This function fetches and returns the version of the MaCh3 software being used.

Definition at line 47 of file Monitor.cpp.

47  {
48 // ************************
49  //KS: Find MaCh3 version based on header file. There could be better way to just include version.h but as long as we don't have to hardcode version I am content
50  std::string MaCh3_VERSION = "";
51 
52  if(std::getenv("MaCh3_ROOT") == nullptr){
53  throw MaCh3Exception(__FILE__, __LINE__, "Error: you haven't sourced setup.MaCh3.sh in core!");
54  }
55 
56  std::string file = std::string(std::getenv("MaCh3_ROOT")) + "/version.h";
57  // Open the version.h file
58  std::ifstream versionFile(file);
59 
60  // Check if the file is opened successfully
61  if (!versionFile.is_open()) {
62  MACH3LOG_ERROR("Error: Couldn't open version.h {}", file);
63  throw MaCh3Exception(__FILE__, __LINE__);
64  }
65 
66  std::string line;
67  const std::string searchKey = "MaCh3_VERSION=";
68 
69  // Read each line from the file
70  while (std::getline(versionFile, line)) {
71  // Search for the line containing MaCh3_VERSION
72  auto pos = line.find(searchKey);
73  if (pos != std::string::npos) {
74  // Extract the version string
75  MaCh3_VERSION = line.substr(pos + searchKey.length());
76  MaCh3_VERSION.erase(0, MaCh3_VERSION.find_first_not_of("\"")); // Remove leading quote
77  MaCh3_VERSION.erase(MaCh3_VERSION.find_last_not_of("\";") + 1); // Remove trailing quote and semicolon
78  break; // Stop searching once found
79  }
80  }
81  // Close the file
82  versionFile.close();
83 
84  return MaCh3_VERSION;
85 }
#define MACH3LOG_ERROR
Definition: MaCh3Logger.h:37

◆ GetMassFromPDG()

double M3::Utils::GetMassFromPDG ( const int  PDG)
inline

Return mass for given PDG.

Note
Get the mass of a particle from the PDG In GeV, not MeV! [26] (particle masses) [36] (nuclear masses)
Todo:
this could be constexpr in c++17

Definition at line 749 of file SampleStructs.h.

749  {
750  // *****************************
751  switch (abs(PDG)) {
752  // Leptons
753  case 11: return 0.00051099895; // e
754  case 13: return 0.1056583755; // mu
755  case 15: return 1.77693; // tau
756  // Neutrinos
757  case 12:
758  case 14:
759  case 16:
760  return 0.;
761  // Photon
762  case 22: return 0.;
763  // Mesons
764  case 211: return 0.13957039; // pi_+/-
765  case 111: return 0.1349768; // pi_0
766  case 221: return 0.547862; // eta
767  case 311: // K_0
768  case 130: // K_0_L
769  case 310: // K_0_S
770  return 0.497611;
771  case 321: return 0.493677; // K_+/-
772  // Baryons
773  case 2112: return 0.939565; // n
774  case 2212: return 0.938272; // p
775  case 3122: return 1.115683; // lambda
776  case 3222: return 1.118937; // sig_+
777  case 3112: return 1.197449; // sig_-
778  case 3212: return 1.192642; // sig_0
779  // Nuclei
780  case 1000050110: return 10.255103; // Boron-11
781  case 1000060120: return 11.177929; // Carbon-12
782  case 1000070140: return 13.043781; // Nitrogen-14
783  case 1000080160: return 14.899169; // Oxygen-16
784  case 1000090190: return 17.696901; // Fluorine-19
785  case 1000110230: return 21.414835; // Sodium-23
786  case 1000130270: return 25.133144; // Aluminum-27
787  case 1000140280: return 26.060342; // Silicon-28
788  case 1000190390: return 36.294463; // Potassium-39
789  case 1000180400: return 37.224724; // Argon-40
790  case 1000220480: return 44.663224; // Titanium-48
791  case 1000300640: return 59.549619; // Zinc-64
792  default:
793  MACH3LOG_ERROR("Haven't got a saved mass for PDG: {}", PDG);
794  MACH3LOG_ERROR("Please implement me!");
795  throw MaCh3Exception(__FILE__, __LINE__);
796  } // End switch
797  return 0;
798  }

◆ GetOSInfo()

void M3::Utils::GetOSInfo ( )

KS: Find out more about operational system.

Definition at line 89 of file Monitor.cpp.

89  {
90 // ************************
91  MACH3LOG_INFO("Operating System Information:");
92 
93  // Distribution and version
94  MACH3LOG_INFO("Distribution: {}", TerminalToString("lsb_release -d | awk -F':' '{print $2}'"));
95  MACH3LOG_INFO("Kernel Version: {}", TerminalToString("uname -r"));
96 }

◆ getValue()

int M3::Utils::getValue ( const std::string &  Type)

CW: Get info like RAM.

Parameters
TypeThe type of system information to retrieve (e.g., RAM, CPU usage).
Returns
The requested system information as an integer.

This function fetches system information like RAM usage or other hardware details based on the specified type.

Definition at line 252 of file Monitor.cpp.

252  { //Note: this value is in KB!
253 // ***************************************************************************
254  std::ifstream file("/proc/self/status");
255  int result = -1;
256  std::string line;
257 
258  if (Type == "VmSize")
259  {
260  while (std::getline(file, line))
261  {
262  if (line.compare(0, 7, "VmSize:") == 0)
263  {
264  result = parseLine(line.substr(7));
265  break;
266  }
267  }
268  }
269  else if (Type == "VmRSS")
270  {
271  while (std::getline(file, line))
272  {
273  if (line.compare(0, 6, "VmRSS:") == 0)
274  {
275  result = parseLine(line.substr(6));
276  break;
277  }
278  }
279  }
280  else if (Type == "MemTotal")
281  {
282  std::ifstream meminfo("/proc/meminfo");
283  while (std::getline(meminfo, line))
284  {
285  if (line.find("MemTotal:") != std::string::npos) {
286  result = parseLine(line.substr(9));
287  break;
288  }
289  }
290  }
291  else
292  {
293  MACH3LOG_ERROR("Not supported getValue: {}", Type);
294  throw MaCh3Exception(__FILE__, __LINE__);
295  }
296  return result;
297 }
int parseLine(const std::string &line)
CW: Get memory, which is probably silly.
Definition: Monitor.cpp:301

◆ MaCh3Usage()

void M3::Utils::MaCh3Usage ( int  argc,
char **  argv 
)

KS: Almost all MaCh3 executables have the same usage, prepare simple printer.

Parameters
argcThe number of command-line arguments.
argvThe array of command-line arguments.

This function prints a simple usage guide for MaCh3 executables, typically called when incorrect arguments are passed.

Definition at line 360 of file Monitor.cpp.

360  {
361 // ***************************************************************************
362  if (argc != 2) {
363  MACH3LOG_ERROR("Wrong usage of MaCh3 executable!");
364  MACH3LOG_ERROR("Syntax is $: {} config.yaml", argv[0]);
365  MACH3LOG_ERROR("Where config.yaml is a valid config file, compatible with the manager class (manager/manager.cpp/h)");
366  throw MaCh3Exception(__FILE__, __LINE__);
367  }
368 }

◆ MaCh3Welcome()

void M3::Utils::MaCh3Welcome ( )

KS: Prints welcome message with MaCh3 logo.

Definition at line 13 of file Monitor.cpp.

13  {
14 // *************************
15  // KS: Just make sure we only call it once
16  static bool MaCh3WelcomeInitialised = false;
17 
18  if(MaCh3WelcomeInitialised) return;
19 
20  std::string MaCh3_VERSION = GetMaCh3Version();
21 
22  MACH3LOG_INFO("##################################");
23  MACH3LOG_INFO("Welcome to: ");
24  MACH3LOG_INFO(" __ __ _____ _ ____ ");
25  MACH3LOG_INFO(" | \\/ | / ____| | |___ \\ ");
26  MACH3LOG_INFO(" | \\ / | __ _| | | |__ __) |");
27  MACH3LOG_INFO(" | |\\/| |/ _` | | | '_ \\ |__ < ");
28  MACH3LOG_INFO(" | | | | (_| | |____| | | |___) |");
29  MACH3LOG_INFO(" |_| |_|\\__,_|\\_____|_| |_|____/ ");
30  MACH3LOG_INFO("Version: {}", MaCh3_VERSION);
31  MACH3LOG_INFO("##################################");
32 
33  GetCPUInfo();
34 
35  GetGPUInfo();
36 
37  #ifdef MACH3_DEBUG
38  GetOSInfo();
39  GetDiskUsage();
40  #endif
41 
42  MaCh3WelcomeInitialised = true;
43 }
void GetGPUInfo()
KS: Check what GPU you are using.
Definition: Monitor.cpp:144
void GetDiskUsage()
KS: Find out about Disk usage.
Definition: Monitor.cpp:177
void GetOSInfo()
KS: Find out more about operational system.
Definition: Monitor.cpp:89
void GetCPUInfo()
KS: Check what CPU you are using.
Definition: Monitor.cpp:100
std::string GetMaCh3Version()
KS: Get version of MaCh3.
Definition: Monitor.cpp:47

◆ NThreadsSanity()

void M3::Utils::NThreadsSanity ( )

KS: Check if user is not using huge number of threads and throw error.

Definition at line 123 of file Monitor.cpp.

123  {
124 // ************************
125  //KS: If OMP_NUM_THREADS is exported, assume user did this on purpose
126  if (std::getenv("OMP_NUM_THREADS") != nullptr) return;
127 
128  const int nThreads = M3::GetNThreads();
129  constexpr int MaxAllowedThreads = 16;
130  constexpr int RecommendedThreads = 8;
131 
132  if (nThreads > MaxAllowedThreads) {
133  MACH3LOG_CRITICAL("You specified more than {} threads ({})", MaxAllowedThreads, nThreads);
134  MACH3LOG_CRITICAL("With so many threads code will be slower, please use:");
135  MACH3LOG_CRITICAL("export OMP_NUM_THREADS={}", RecommendedThreads);
136  MACH3LOG_CRITICAL("To use different number of threads");
137  throw MaCh3Exception(__FILE__, __LINE__, "Too many threads");
138  }
139 }

◆ parseLine()

int M3::Utils::parseLine ( const std::string &  line)

CW: Get memory, which is probably silly.

Parameters
lineThe line of text to parse.
Returns
The extracted memory value as an integer.

This function is used to parse a line of text and extract memory-related information.

Definition at line 301 of file Monitor.cpp.

301  {
302 // ***************************************************************************
303  std::istringstream iss(line);
304  int value;
305  iss >> value;
306  return value;
307 }

◆ PDGToNuOscillatorFlavour()

int M3::Utils::PDGToNuOscillatorFlavour ( const int  NuPdg)
inline

Convert from PDG flavour to NuOscillator type beware that in the case of anti-neutrinos the NuOscillator type simply gets multiplied by -1.

Definition at line 805 of file SampleStructs.h.

805  {
806  int NuOscillatorFlavour = M3::_BAD_INT_;
807  switch(std::abs(NuPdg)){
808  case NuPDG::kNue:
809  NuOscillatorFlavour = NuOscillator::kElectron;
810  break;
811  case NuPDG::kNumu:
812  NuOscillatorFlavour = NuOscillator::kMuon;
813  break;
814  case NuPDG::kNutau:
815  NuOscillatorFlavour = NuOscillator::kTau;
816  break;
817  default:
818  MACH3LOG_ERROR("Unknown Neutrino PDG {}, cannot convert to NuOscillator type", NuPdg);
819  break;
820  }
821 
822  //This is very cheeky but if the PDG is negative then multiply the PDG by -1
823  // This is consistent with the treatment that NuOscillator expects as enums only
824  // exist for the generic matter flavour and not the anti-matter version
825  if(NuPdg < 0){NuOscillatorFlavour *= -1;}
826 
827  return NuOscillatorFlavour;
828  }
@ kNutau
Tau neutrino.
Definition: SampleStructs.h:98
@ kNue
Electron neutrino.
Definition: SampleStructs.h:96
@ kNumu
Muon neutrino.
Definition: SampleStructs.h:97
constexpr static const int _BAD_INT_
Default value used for int initialisation.
Definition: Core.h:55

◆ Print()

void M3::Utils::Print ( const TTree *  tree)
Parameters
treecontent of TTree using logger

Definition at line 326 of file Monitor.cpp.

326  {
327 // ***************************************************************************
328  if (!tree) return;
329 
330  // Create a temporary file to capture stdout
331  FILE* tmpFile = tmpfile();
332  if (!tmpFile) return;
333 
334  // Save old stdout
335  int oldStdout = dup(fileno(stdout));
336  // Redirect stdout to tmpFile
337  dup2(fileno(tmpFile), fileno(stdout));
338 
339  tree->Print(); // ROOT writes to stdout
340 
341  fflush(stdout);
342  // Restore old stdout
343  dup2(oldStdout, fileno(stdout));
344  close(oldStdout);
345 
346  // Read tmpFile content
347  fseek(tmpFile, 0, SEEK_SET);
348  char buffer[1024];
349  while (fgets(buffer, sizeof(buffer), tmpFile)) {
350  std::string line(buffer);
351  if (!line.empty() && line.back() == '\n') line.pop_back();
352  MACH3LOG_INFO("{}", line);
353  }
354 
355  fclose(tmpFile);
356 }

◆ PrintConfig()

void M3::Utils::PrintConfig ( const YAML::Node &  node)

KS: Print Yaml config using logger.

Parameters
nodeyaml config node

Definition at line 311 of file Monitor.cpp.

311  {
312 // ***************************************************************************
313  std::stringstream ss;
314  ss << node;
315  std::string yamlString = ss.str();
316 
317  std::istringstream iss(yamlString);
318  std::string line;
319  while (std::getline(iss, line)) {
320  MACH3LOG_INFO("{}", line);
321  }
322 }

◆ PrintProgressBar()

void M3::Utils::PrintProgressBar ( const Long64_t  Done,
const Long64_t  All 
)

KS: Simply print progress bar.

Parameters
DoneThe number of tasks completed.
AllThe total number of tasks.

This function prints a progress bar to the terminal, indicating the percentage of tasks completed.

Definition at line 229 of file Monitor.cpp.

229  {
230 // ************************
231  double progress = double(Done)/double(All);
232  const int barWidth = 20;
233  std::ostringstream progressBar;
234 
235  progressBar << "[";
236  int pos = int(barWidth * progress);
237  for (int i = 0; i < barWidth; ++i) {
238  if (i < pos)
239  progressBar << "=";
240  else if (i == pos)
241  progressBar << ">";
242  else
243  progressBar << " ";
244  }
245 
246  progressBar << "] " << std::setw(3) << Done <<"/"<< All<<" ("<<static_cast<int>(progress * 100.0)<<"%)\r";
247  MACH3LOG_INFO("{}", progressBar.str());
248 }

◆ TerminalToString()

std::string M3::Utils::TerminalToString ( std::string  cmd)

KS: Convoluted code to grab output from terminal to string.

Parameters
cmdThe terminal command to execute.
Returns
The output of the terminal command as a string.

Definition at line 187 of file Monitor.cpp.

187  {
188 // ************************
189  std::array<char, 128> buffer;
190  std::string result;
191 
192  struct PCloseDeleter {
193  void operator()(FILE* f) const {
194  if (f) pclose(f);
195  }
196  };
197  std::unique_ptr<FILE, PCloseDeleter> pipe(popen(cmd.c_str(), "r"));
198 
199  if (!pipe) {
200  throw MaCh3Exception(__FILE__, __LINE__, "popen() failed!");
201  }
202  while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
203  result += buffer.data();
204  }
205  // Remove trailing newline characters
206  result.erase(std::remove(result.begin(), result.end(), '\n'), result.end());
207  return result;
208 }