musrfit  1.9.2
dump_header.cpp
Go to the documentation of this file.
1 /***************************************************************************
2 
3  dump_header.cpp
4 
5  Author: Andreas Suter
6  e-mail: andreas.suter@psi.ch
7 
8 ***************************************************************************/
9 
10 /***************************************************************************
11  * Copyright (C) 2007-2023 by Andreas Suter *
12  * andreas.suter@psi.ch *
13  * *
14  * This program is free software; you can redistribute it and/or modify *
15  * it under the terms of the GNU General Public License as published by *
16  * the Free Software Foundation; either version 2 of the License, or *
17  * (at your option) any later version. *
18  * *
19  * This program is distributed in the hope that it will be useful, *
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
22  * GNU General Public License for more details. *
23  * *
24  * You should have received a copy of the GNU General Public License *
25  * along with this program; if not, write to the *
26  * Free Software Foundation, Inc., *
27  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
28  ***************************************************************************/
29 
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33 
34 #include <unistd.h>
35 #include <cerrno>
36 #include <cctype>
37 #include <cstring>
38 #include <ctime>
39 #include <cassert>
40 
41 #include <iostream>
42 #include <fstream>
43 #include <sstream>
44 #include <string>
45 #include <vector>
46 #include <memory>
47 
48 #include <boost/algorithm/string.hpp>
49 
50 #include <TObject.h>
51 #include <TObjArray.h>
52 #include <TObjString.h>
53 #include <TFile.h>
54 #include <TFolder.h>
55 #include <TString.h>
56 #include <TFolder.h>
57 #include <TH1F.h>
58 
59 #ifdef HAVE_GIT_REV_H
60 #include "git-revision.h"
61 #endif
62 
63 #include "PFindRun.h"
64 #include "PStartupHandler.h"
65 #include "TMusrRunHeader.h"
66 #include "TLemRunHeader.h"
67 #include "MuSR_td_PSI_bin.h"
68 #include "mud.h"
69 
70 #ifdef PNEXUS_ENABLED
71 #include "PNeXus.h"
72 #endif
73 
74 #define DH_MUSR_ROOT 0
75 #define DH_LEM_ROOT 1
76 
77 //------------------------------------------------------------------------
82 {
83  std::cout << std::endl << "usage: dump_header [-rn <runNo> | -fn <fileName>] [-ff, --fileFormat <fileFormat>]";
84  std::cout << std::endl << " [-y, --year <year>] [-s, --summary] [-i, --instrument <inst>]";
85  std::cout << std::endl << " [-c, --counts] | ";
86  std::cout << std::endl << " --help | --version";
87  std::cout << std::endl;
88  std::cout << std::endl << " Dumps the header information of a given muSR data file onto the standard output.";
89  std::cout << std::endl << " If no <fileFormat> info is povided, it will try to guess what <fileFormat> it might be.";
90  std::cout << std::endl << " For <runNo> guessing of the file format is not possible. The default assumption here is 'MusrRoot'.";
91  std::cout << std::endl;
92  std::cout << std::endl << " -rn, --runNo <runNo> : run number of the header to be dumped.";
93  std::cout << std::endl << " -fn, --fileName <fileName> : muSR data file name.";
94  std::cout << std::endl << " -ff, --fileFormat <fileFormat> : where <fileFormat> can be:";
95  std::cout << std::endl << " MusrRoot (default), NeXus, ROOT (old LEM), PSI-BIN, PSI-MDU, MUD, WKM";
96  std::cout << std::endl << " NeXus is only supported if enabled.";
97  std::cout << std::endl << " -y, --year <year> : <year> has to be 4 digit, e.g. 2005, if provided it is used to";
98  std::cout << std::endl << " generate the file name for the given <runNo>, otherwise the current";
99  std::cout << std::endl << " year is used. If a file name is given, this option has no effect.";
100  std::cout << std::endl << " -s, --summary : this option is used for LE-uSR data sets only. It will, additionally";
101  std::cout << std::endl << " to the header information, print the summary file content.";
102  std::cout << std::endl << " -i, --instrument <inst> : where <inst> is the requested instrument:";
103  std::cout << std::endl << " lem (default) | gps | ltf | dolly | gpd | hifi | flame.";
104  std::cout << std::endl << " -c, --counts : will show detector counts as well.";
105  std::cout << std::endl << " -h, --help : will show this help";
106  std::cout << std::endl << " -v, --version : will show the current version.";
107  std::cout << std::endl << std::endl;
108 }
109 
110 //------------------------------------------------------------------------
120 int dump_header_root(const std::string fileName, const bool summary, const bool counts)
121 {
122  TFile f(fileName.c_str());
123  if (f.IsZombie()) {
124  std::cerr << std::endl;
125  std::cerr << "**ERROR** couldn't invoke ROOT/MusrRoot file object." << std::endl;
126  std::cerr << std::endl;
127  return 1;
128  }
129 
130  UInt_t fileType = DH_MUSR_ROOT;
131  UInt_t noOfHistos{0};
132  PIntVector redGreenOffset;
133 
134  TFolder *folder;
135  f.GetObject("RunInfo", folder); // try first LEM-ROOT style file (used until 2011).
136  if (!folder) { // either something is wrong, or it is a MusrRoot file
137  f.GetObject("RunHeader", folder);
138  if (!folder) { // something is wrong!!
139  std::cerr << std::endl << "**ERROR** Couldn't neither obtain RunInfo (LEM), nor RunHeader (MusrRoot) from " << fileName << std::endl;
140  f.Close();
141  return 1;
142  } else {
143  fileType = DH_MUSR_ROOT;
144  }
145  } else {
146  fileType = DH_LEM_ROOT;
147  }
148 
149  std::unique_ptr<TMusrRunHeader> header;
150  bool ok;
151  Int_t ival;
152 
153  if (fileType == DH_LEM_ROOT) { // ROOT (LEM)
154  // read header and check if some missing run info need to be fed
155  TLemRunHeader* runHeader = dynamic_cast<TLemRunHeader*>(folder->FindObjectAny("TLemRunHeader"));
156 
157  // check if run header is valid
158  if (runHeader == nullptr) {
159  std::cerr << std::endl << "**ERROR** Couldn't obtain run header info from ROOT file " << fileName << std::endl;
160  f.Close();
161  return 1;
162  }
163 
164  std::cout << std::endl << "-------------------";
165  std::cout << std::endl << "fileName = " << fileName << ", fileFormat = ROOT (PSI LEM).";
166  std::cout << std::endl << "-------------------";
167  std::cout << std::endl << "Run Title : " << runHeader->GetRunTitle().GetString().Data();
168  std::cout << std::endl << "Run Number : " << runHeader->GetRunNumber();
169  std::cout << std::endl << "Run Start Time : " << runHeader->GetStartTimeString().GetString().Data();
170  std::cout << std::endl << "Run Stop Time : " << runHeader->GetStopTimeString().GetString().Data();
171  std::cout << std::endl << "Laboratory : PSI";
172  std::cout << std::endl << "Instrument : LEM";
173  std::cout << std::endl << "Beamline : muE4";
174  std::cout << std::endl << "Muon Beam Momentum : 28 MeV/c";
175  std::cout << std::endl << "Muon Species : positive muons";
176  std::cout << std::endl << "Muon Source : Target E - slow muons";
177  std::cout << std::endl << "Setup : " << runHeader->GetLemSetup().GetString().Data();
178  std::cout << std::endl << "Comment : n/a";
179  std::cout << std::endl << "Sample Name : n/a";
180  std::cout << std::endl << "Sample Orientation : n/a";
181  std::cout << std::endl << "Sample Temperature : " << runHeader->GetSampleTemperature() << "+-" << runHeader->GetSampleTemperatureError() << " K";
182  std::cout << std::endl << "Sample Mag. Field : " << runHeader->GetSampleBField() << "+-" << runHeader->GetSampleBFieldError() << " G";
183  std::cout << std::endl << "No of Histos : " << runHeader->GetNHist();
184  std::cout << std::endl << "Time Resolution : " << runHeader->GetTimeResolution() << " ns";
185  std::cout << std::endl << "-------------------";
186  std::cout << std::endl << "LEM Specific Entries :";
187  std::cout << std::endl << "Moderator : " << runHeader->GetModerator().GetString().Data();
188  std::cout << std::endl << "Moderator HV : " << runHeader->GetModeratorHV() << " kV";
189  std::cout << std::endl << "Sample HV : " << runHeader->GetSampleHV() << " kV";
190  std::cout << std::endl << "Impl. Energy : " << runHeader->GetImpEnergy() << " keV";
191  std::cout << std::endl << "-------------------";
192  std::cout << std::endl << "Detector Info (for all detectors the same): ";
193  std::cout << std::endl << "-------------------";
194  std::cout << std::endl << "Histo Length : " << runHeader->GetNChannels();
195  double *timeZero;
196  timeZero = runHeader->GetTimeZero();
197  std::cout << std::endl << "Time Zero Bin : " << timeZero[0];
198  std::cout << std::endl << "First Good Bin : " << timeZero[0];
199  std::cout << std::endl << "Last Good Bin : " << runHeader->GetNChannels()-1;
200  std::cout << std::endl << "-------------------" << std::endl << std::endl;
201  } else { // MusrRoot
202  // invoke the MusrRoot header object
203  header = std::make_unique<TMusrRunHeader>(fileName.c_str(), true); // read quite
204 
205  // try to populate the MusrRoot header object
206  if (!header->ExtractAll(folder)) {
207  std::cerr << std::endl << "**ERROR** Couldn't invoke MusrRoot RunHeader in file:" << fileName;
208  std::cerr << std::endl;
209  f.Close();
210  return 1;
211  }
212 
213  header->DumpHeader();
214 
215  if (counts) {
216  PIntVector ivec;
217  header->Get("RunInfo/No of Histos", ival, ok);
218  if (ok)
219  noOfHistos = ival;
220  header->Get("RunInfo/RedGreen Offsets", ivec, ok);
221  if (ok)
222  redGreenOffset = ivec;
223  }
224  }
225 
226  // summary as well?
227  if (summary && (fileType == DH_MUSR_ROOT)) {
228  TObjArray *runSum=nullptr;
229  runSum = static_cast<TObjArray*>(folder->FindObject("RunSummary"));
230  if (!runSum) { // something is wrong!!
231  std::cerr << std::endl << "**ERROR** Couldn't obtain RunSummary " << fileName << std::endl;
232  f.Close();
233  return 1;
234  }
235  std::cout << "++++++++++++++++++++" << std::endl;
236  std::cout << " Run Summary" << std::endl;
237  std::cout << "++++++++++++++++++++" << std::endl;
238  TObjString *tstr;
239  TString str;
240  for (Int_t i=0; i<runSum->GetEntries(); i++) {
241  tstr = static_cast<TObjString*>(runSum->At(i));
242  str = tstr->String();
243  std::cout << str;
244  if (!str.Contains("\r") && !str.Contains("\n"))
245  std::cout << std::endl;
246  }
247  }
248 
249  // detector counts as well?
250  if (counts && (fileType == DH_MUSR_ROOT)) {
251  // dump the detector counts
252  std::cout << "Detector counts (all, between fgb and lgb)" << std::endl;
253  f.GetObject("histos", folder);
254  if ((folder != nullptr) && (header != nullptr)) {
255  char detectorLabel[64];
256  TH1F *histo{nullptr};
257  UInt_t total{0}, total_good{0}, ta, tg;
258  Int_t fgb, lgb;
259  for (UInt_t i=0; i<redGreenOffset.size(); i++) {
260  std::cout << " Group " << i+1 << " (Offset=" << redGreenOffset[i] << ") : " << std::endl;
261  total = 0;
262  total_good = 0;
263  for (UInt_t j=0; j<noOfHistos; j++) {
264  // get fgb, lgb
265  fgb = -1;
266  snprintf(detectorLabel, sizeof(detectorLabel), "DetectorInfo/Detector%03d/First Good Bin", redGreenOffset[i]+j+1);
267  header->Get(detectorLabel, ival, ok);
268  if (ok) {
269  fgb = ival;
270  }
271  lgb = -1;
272  snprintf(detectorLabel, sizeof(detectorLabel), "DetectorInfo/Detector%03d/Last Good Bin", redGreenOffset[i]+j+1);
273  header->Get(detectorLabel, ival, ok);
274  if (ok) {
275  lgb = ival;
276  }
277  // get histo info
278  snprintf(detectorLabel, sizeof(detectorLabel), "hDecay%03d", redGreenOffset[i]+j+1);
279  histo = (TH1F*) folder->FindObjectAny(detectorLabel);
280  if (histo != nullptr) {
281  ta = histo->Integral(0, histo->GetNbinsX()+1);
282  tg = histo->Integral(fgb, lgb);
283  std::cout << " " << histo->GetTitle() << ":\t " << ta << ", " << tg << std::endl;
284  total += ta;
285  total_good += tg;
286  }
287  }
288  if (i % 2 == 0)
289  std::cout << " total counts of group " << i+1 << ":\t\t\t " << total << ", " << total_good << std::endl;
290  else
291  std::cout << " total counts of group " << i+1 << ":\t\t\t\t\t " << total << ", " << total_good << std::endl;
292  }
293  } else {
294  std::cout << "Sorry, no histos folder found" << std::endl;
295  f.Close();
296  return 0;
297  }
298  }
299 
300  f.Close();
301 
302  return 0;
303 }
304 
305 //------------------------------------------------------------------------
314 int dump_header_nexus(const std::string fileName, const bool counts) {
315 
316 #ifdef PNEXUS_ENABLED
317  std::unique_ptr<PNeXus> nxs_file = std::make_unique<PNeXus>(fileName.c_str());
318 
319  if (nxs_file->IsValid(false)) {
320  nxs_file->Dump(counts);
321  } else {
322  std::cerr << std::endl;
323  std::cerr << "**ERROR** found invalid NeXus file." << std::endl;
324  std::cerr << std::endl;
325  return 1;
326  }
327 #else
328  std::cout << std::endl << "NeXus not enabled, hence the header information cannot be dumped." << std::endl << std::endl;
329 #endif
330 
331  return 0;
332 }
333 
334 //------------------------------------------------------------------------
342 std::vector<std::string> dump_header_instrument_info(std::string fileName)
343 {
344  std::vector<std::string> result;
345  std::string fln(fileName);
346  boost::to_lower(fln);
347 
348  if ((fln.find(".bin") != std::string::npos) || (fln.find(".mdu") != std::string::npos)) { // PSI-BIN or PSI-MDU format
349  if (fln.find("_gps_") != std::string::npos) {
350  result.push_back("GPS");
351  result.push_back("piM3.2");
352  result.push_back("28 MeV/c");
353  result.push_back("likely to be positive muons");
354  result.push_back("Target M");
355  } else if (fln.find("_ltf_") != std::string::npos) {
356  result.push_back("LTF");
357  result.push_back("piM3.1");
358  result.push_back("28 MeV/c");
359  result.push_back("likely to be positive muons");
360  result.push_back("Target M");
361  } else if (fln.find("_dolly_") != std::string::npos) {
362  result.push_back("DOLLY");
363  result.push_back("piE1");
364  result.push_back("28 MeV/c");
365  result.push_back("likely to be positive muons");
366  result.push_back("Target E");
367  } else if (fln.find("_alc_") != std::string::npos) {
368  result.push_back("ALC");
369  result.push_back("piE3");
370  result.push_back("28 MeV/c");
371  result.push_back("likely to be positive muons");
372  result.push_back("Target E");
373  } else if (fln.find("_hifi_") != std::string::npos) {
374  result.push_back("HAL9500");
375  result.push_back("piE3");
376  result.push_back("28 MeV/c");
377  result.push_back("likely to be positive muons");
378  result.push_back("Target E");
379  } else if (fln.find("_gpd_") != std::string::npos) {
380  result.push_back("GPD");
381  result.push_back("muE1");
382  result.push_back("60-125 MeV/c");
383  result.push_back("likely to be positive muons");
384  result.push_back("Target E");
385  } else {
386  result.push_back("???");
387  result.push_back("???");
388  result.push_back("??? MeV/c");
389  result.push_back("???");
390  result.push_back("???");
391  }
392  }
393 
394  return result;
395 }
396 
397 //------------------------------------------------------------------------
407 int dump_header_psi_bin(const std::string fileName, const std::string fileFormat, const bool counts)
408 {
409  MuSR_td_PSI_bin psiBin;
410  int status;
411  bool success = false;
412 
413  // read psi bin file
414  status = psiBin.Read(fileName.c_str());
415  switch (status) {
416  case 0: // everything perfect
417  success = true;
418  break;
419  case 1: // couldn't open file, or failed while reading the header
420  std::cout << std::endl << "**ERROR** couldn't open psi-bin file, or failed while reading the header." << std::endl;
421  success = false;
422  break;
423  case 2: // unsupported version of the data
424  std::cout << std::endl << "**ERROR** psi-bin file: unsupported version of the data." << std::endl;
425  success = false;
426  break;
427  case 3: // error when allocating data buffer
428  std::cout << std::endl << "**ERROR** psi-bin file: error when allocating data buffer." << std::endl;
429  success = false;
430  break;
431  case 4: // number of histograms/record not equals 1
432  std::cout << std::endl << ">> **ERROR** psi-bin file: number of histograms/record not equals 1." << std::endl;
433  success = false;
434  break;
435  default: // you never should have reached this point
436  std::cout << std::endl << ">> **ERROR** psi-bin file: no clue why you reached this point." << std::endl;
437  success = false;
438  break;
439  }
440 
441  // if any reading error happend, get out of here
442  if (!success)
443  return 1;
444 
445  std::vector<std::string> vstr;
446  std::vector<double> dVal, dErrVal;
447  std::cout << std::endl << "-------------------";
448  std::cout << std::endl << "fileName = " << fileName << ", fileFormat = " << fileFormat;
449  std::cout << std::endl << "-------------------";
450  std::cout << std::endl << "Run Title : " << psiBin.GetComment();
451  std::cout << std::endl << "Run Number : " << psiBin.GetRunNumberInt();
452  vstr = psiBin.GetTimeStartVector();
453  if (vstr.size() < 2) {
454  std::cout << std::endl << "**ERROR** couldn't obtain \"Run Start Time\" will quit." << std::endl << std::endl;
455  return 1;
456  }
457  std::cout << std::endl << "Run Start Time : " << vstr[0] << "; " << vstr[1];
458  vstr = psiBin.GetTimeStopVector();
459  if (vstr.size() < 2) {
460  std::cout << std::endl << "**ERROR** couldn't obtain \"Run Stop Time\" will quit." << std::endl << std::endl;
461  return 1;
462  }
463  std::cout << std::endl << "Run Stop Time : " << vstr[0] << "; " << vstr[1];
464  std::cout << std::endl << "Laboratory : PSI";
465  vstr = dump_header_instrument_info(fileName);
466  if (vstr.size() < 5) {
467  std::cout << std::endl << "**ERROR** couldn't obtain \"Instrument\" will quit." << std::endl << std::endl;
468  return 1;
469  }
470  std::cout << std::endl << "Instrument : " << vstr[0];
471  std::cout << std::endl << "Beamline : " << vstr[1];
472  std::cout << std::endl << "Muon Beam Momentum : " << vstr[2];
473  std::cout << std::endl << "Muon Species : " << vstr[3];
474  std::cout << std::endl << "Muon Source : " << vstr[4];
475  std::cout << std::endl << "Setup : " << psiBin.GetComment();
476  std::cout << std::endl << "Comment : n/a";
477  std::cout << std::endl << "Sample Name : " << psiBin.GetSample();
478  std::cout << std::endl << "Sample Orientation : " << psiBin.GetOrient();
479  dVal = psiBin.GetTemperaturesVector();
480  dErrVal = psiBin.GetDevTemperaturesVector();
481  if (dVal.size() != dErrVal.size()) {
482  std::cout << std::endl << "Sample Temperature : " << psiBin.GetTemp();
483  } else {
484  for (unsigned int i=0; i<dVal.size(); i++) {
485  std::cout << std::endl << "Sample Temp. " << i+1 << " : " << dVal[i] << " (" << dErrVal[i] << ") K";
486  }
487  }
488  std::cout << std::endl << "Sample Mag. Field : " << psiBin.GetField();
489  std::cout << std::endl << "No of Histos : " << psiBin.GetNumberHistoInt();
490  std::cout << std::endl << "Time Resolution : " << psiBin.GetBinWidthNanoSec() << " ns";
491  for (int i=0; i<psiBin.GetNumberHistoInt(); i++) {
492  std::cout << std::endl << "-------------------";
493  std::cout << std::endl << "Histo No : " << i;
494  std::cout << std::endl << "Histo Name : " << psiBin.GetNameHisto(i);
495  std::cout << std::endl << "Histo Length : " << psiBin.GetHistoLengthBin();
496  std::cout << std::endl << "Time Zero Bin : " << psiBin.GetT0Int(i);
497  std::cout << std::endl << "First Good Bin : " << psiBin.GetFirstGoodInt(i);
498  std::cout << std::endl << "Last Good Bin : " << psiBin.GetLastGoodInt(i);
499  if (counts)
500  std::cout << std::endl << "No of Events : " << psiBin.GetEventsHistoLong(i);
501  }
502  std::cout << std::endl << "-------------------" << std::endl << std::endl;
503 
504  return 0;
505 }
506 
507 //------------------------------------------------------------------------
515 int dump_header_mud(const std::string fileName, const bool counts)
516 {
517  int fh;
518  UINT32 type, val;
519  char str[1024];
520  int success;
521 
522  char fln[256];
523  strncpy(fln, fileName.c_str(), sizeof(fln));
524  fh = MUD_openRead(fln, &type);
525  if (fh == -1) {
526  std::cerr << std::endl << "**ERROR** Couldn't open mud-file " << fileName << ", sorry." << std::endl;
527  return 1;
528  }
529 
530  std::cout << std::endl << "-------------------";
531  std::cout << std::endl << "fileName = " << fileName << ", fileFormat = MUD";
532  std::cout << std::endl << "-------------------";
533  // run title
534  success = MUD_getTitle( fh, str, sizeof(str) );
535  if (success)
536  std::cout << std::endl << "Run Title : " << str;
537  else
538  std::cout << std::endl << "Run Title : ???";
539  // run number
540  success = MUD_getRunNumber( fh, &val );
541  if (success)
542  std::cout << std::endl << "Run Number : " << val;
543  else
544  std::cout << std::endl << "Run Number : ???";
545  // start time
546  time_t tval;
547  struct tm *dt;
548  success = MUD_getTimeBegin( fh, &val );
549  tval = static_cast<time_t>(val);
550  if (success) {
551  dt = localtime(static_cast<const time_t*>(&tval));
552  assert(dt);
553  strftime(str, sizeof(str), "%F; %T", dt);
554  std::cout << std::endl << "Run Start Time : " << str;
555  } else {
556  std::cout << std::endl << "Run Start Time : ???";
557  }
558  // stop time
559  success = MUD_getTimeEnd( fh, &val );
560  tval = static_cast<time_t>(val);
561  if (success) {
562  dt = localtime(static_cast<const time_t*>(&tval));
563  assert(dt);
564  strftime(str, sizeof(str), "%F; %T", dt);
565  std::cout << std::endl << "Run Stop Time : " << str;
566  } else {
567  std::cout << std::endl << "Run Stop Time : ???";
568  }
569  // laboratory
570  success = MUD_getLab( fh, str, sizeof(str) );
571  if (success)
572  std::cout << std::endl << "Laboratory : " << str;
573  else
574  std::cout << std::endl << "Laboratory : ???";
575  // instrument
576  success = MUD_getApparatus( fh, str, sizeof(str) );
577  if (success)
578  std::cout << std::endl << "Instrument : " << str;
579  else
580  std::cout << std::endl << "Instrument : ???";
581  // beamline
582  success = MUD_getArea( fh, str, sizeof(str) );
583  if (success)
584  std::cout << std::endl << "Beamline : " << str;
585  else
586  std::cout << std::endl << "Beamline : ???";
587 
588  std::cout << std::endl << "Muon Beam Momentum : ???";
589  std::cout << std::endl << "Muon Species : positive muon?";
590  std::cout << std::endl << "Muon Source : ???";
591 
592  // method
593  success = MUD_getMethod( fh, str, sizeof(str) );
594  if (success)
595  std::cout << std::endl << "Method : " << str;
596  else
597  std::cout << std::endl << "Method : ???";
598 
599  // sample
600  success = MUD_getSample( fh, str, sizeof(str) );
601  if (success)
602  std::cout << std::endl << "Sample Name : " << str;
603  else
604  std::cout << std::endl << "Sample Name : ???";
605 
606  // orientation
607  success = MUD_getOrient( fh, str, sizeof(str) );
608  if (success)
609  std::cout << std::endl << "Sample Orientation : " << str;
610  else
611  std::cout << std::endl << "Sample Orientation : ???";
612 
613  // temperature
614  success = MUD_getTemperature( fh, str, sizeof(str) );
615  if (success)
616  std::cout << std::endl << "Sample Temperature : " << str;
617  else
618  std::cout << std::endl << "Sample Temperature : ???";
619 
620  // magnetic field
621  success = MUD_getField( fh, str, sizeof(str) );
622  if (success)
623  std::cout << std::endl << "Sample Magn. Field : " << str;
624  else
625  std::cout << std::endl << "Sample Magn. Field : ???";
626 
627  // number of histograms
628  int noHistos = 0;
629  success = MUD_getHists(fh, &type, &val);
630  if (success) {
631  std::cout << std::endl << "No of Histos : " << val;
632  noHistos = val;
633  } else {
634  std::cout << std::endl << "No of Histos : ???";
635  }
636 
637  // time resolution
638  REAL64 timeResolution = 0.0; // in seconds!!
639  success = MUD_getHistSecondsPerBin( fh, 1, &timeResolution );
640  timeResolution *= 1.0e9; // sec -> nsec
641  if (success)
642  std::cout << std::endl << "Time Resolution : " << timeResolution << " ns";
643  else
644  std::cout << std::endl << "Time Resolution : ??? ns";
645 
646  // detector related stuff
647  for (int i=0; i<noHistos; i++) {
648  std::cout << std::endl << "-------------------";
649  std::cout << std::endl << "Histo No " << i+1;
650 
651  success = MUD_getHistTitle( fh, i+1, str, 1023);
652  if (success)
653  std::cout << std::endl << "Histo Name : " << str;
654  else
655  std::cout << std::endl << "Histo Name : ???";
656 
657  success = MUD_getHistNumBins( fh, i+1, &val );
658  if (success)
659  std::cout << std::endl << "Histo Length : " << val;
660  else
661  std::cout << std::endl << "Histo Length : ???";
662 
663  success = MUD_getHistT0_Bin( fh, i+1, &val );
664  if (success)
665  std::cout << std::endl << "Time Zero Bin : " << val;
666  else
667  std::cout << std::endl << "Time Zero Bin : ???";
668 
669  success = MUD_getHistGoodBin1( fh, i+1, &val );
670  if (success)
671  std::cout << std::endl << "First Good Bin : " << val;
672  else
673  std::cout << std::endl << "First Good Bin : ???";
674 
675  success = MUD_getHistGoodBin2( fh, i+1, &val );
676  if (success)
677  std::cout << std::endl << "Last Good Bin : " << val;
678  else
679  std::cout << std::endl << "Last Good Bin : ???";
680  if (counts) {
681  success = MUD_getHistNumEvents( fh, i+1, &val );
682  if (success) {
683  std::cout << std::endl << "#Events : " << val;
684  }
685  }
686  }
687 
688  std::cout << std::endl << "-------------------" << std::endl << std::endl;
689 
690  MUD_closeRead(fh);
691 
692  return 0;
693 }
694 
695 //------------------------------------------------------------------------
702 int dump_header_wkm(const std::string fileName)
703 {
704  std::ifstream fin(fileName.c_str(), std::ifstream::in);
705  if (!fin.is_open()) {
706  std::cout << std::endl << "**ERROR** haven't found \"" << fileName << "\", will quit." << std::endl << std::endl;
707  return 1;
708  }
709  std::cout << std::endl << "-------------------";
710  std::cout << std::endl << "fileName = " << fileName << ", fileFormat = WKM";
711  std::cout << std::endl << "-------------------";
712  char header[256];
713  while (fin.good()) {
714  fin.getline(header, 256);
715  if (strlen(header) == 0)
716  break;
717  std::cout << std::endl << header;
718  }
719  std::cout << std::endl << "-------------------" << std::endl << std::endl;
720  fin.close();
721 
722  return 0;
723 }
724 
725 //------------------------------------------------------------------------
733 bool dump_is_number(const char *s)
734 {
735  int i=0;
736 
737  if (s == nullptr) // make sure it is not a null pointer
738  return false;
739 
740  while (isdigit(s[i]))
741  i++;
742 
743  if (s[i] == '\0')
744  return true;
745  else
746  return false;
747 }
748 
749 //------------------------------------------------------------------------
756 {
757  time_t rawtime;
758  struct tm *timeinfo;
759  char buffer[32];
760 
761  time (&rawtime);
762  timeinfo = localtime(&rawtime);
763  strftime(buffer, 32, "%Y", timeinfo);
764 
765  return atoi(buffer);
766 }
767 
768 //------------------------------------------------------------------------
778 int main(int argc, char *argv[])
779 {
780  if (argc == 1) {
782  return 0;
783  }
784 
785  std::string runNo("");
786  std::string fileName("");
787  std::string fileFormat("");
788  std::string year("");
789  std::string instrument("lem");
790  bool summary(false);
791  bool counts(false);
792 
793  for (int i=1; i<argc; i++) {
794  if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h")) {
796  return 0;
797  } else if (!strcmp(argv[i], "--version") || !strcmp(argv[i], "-v")) {
798 #ifdef HAVE_CONFIG_H
799 #ifdef HAVE_GIT_REV_H
800  std::cout << std::endl << "dump_header version: " << PACKAGE_VERSION << ", git-branch: " << GIT_BRANCH << ", git-rev: " << GIT_CURRENT_SHA1 << " (" << BUILD_TYPE << "), ROOT version: " << ROOT_VERSION_USED << std::endl << std::endl;
801 #else
802  std::cout << std::endl << "dump_header version: " << PACKAGE_VERSION << " (" << BUILD_TYPE << "), ROOT version: " << ROOT_VERSION_USED << std::endl << std::endl;
803 #endif
804 #else
805 #ifdef HAVE_GIT_REV_H
806  std::cout << std::endl << "dump_header git-branch: " << GIT_BRANCH << ", git-rev: " << GIT_CURRENT_SHA1 << std::endl << std::endl;
807 #else
808  std::cout << std::endl << "dump_header version: unknown" << std::endl << std::endl;
809 #endif
810 #endif
811  return 0;
812  } else if (!strcmp(argv[i], "-rn") || !strcmp(argv[i], "--runNo")) {
813  if (i+1 >= argc) {
814  std::cerr << std::endl << "**ERROR** found -rn, --runNo without <runNo>!" << std::endl;
816  return 1;
817  }
818  // make sure there is only one 'legal' run number
819  int count = 1;
820  while (dump_is_number(argv[i+count]) && (i+count < argc))
821  count++;
822  // make sure there is one and only one run number given
823  if (count == 1) {
824  std::cerr << std::endl << "**ERROR** found -rn, --runNo without <runNo>, or the provided <runNo> ('" << argv[i+1] << "') is not a number!" << std::endl;
826  return 1;
827  }
828  if (count > 2) {
829  std::cerr << std::endl << "**ERROR** found -rn, --runNo with more than one <runNo>! This is not yet supported." << std::endl;
831  return 1;
832  }
833  runNo = argv[i+1];
834  i++;
835  } else if (!strcmp(argv[i], "-fn") || !strcmp(argv[i], "--fileName")) {
836  if (i+1 >= argc) {
837  std::cerr << std::endl << "**ERROR** found -fn, --fileName without <fileName>!" << std::endl;
839  return 1;
840  }
841  fileName = argv[i+1];
842  i++;
843  } else if (!strcmp(argv[i], "--fileFormat") || !strcmp(argv[i], "-ff")) {
844  if (i+1 >= argc) {
845  std::cerr << std::endl << "**ERROR** found -ff, --fileFormat without <fileFormat>!" << std::endl;
847  return 1;
848  }
849  std::string ff(argv[i+1]);
850  if (!boost::iequals(ff, "MusrRoot") && !boost::iequals(ff, "NeXus") && !boost::iequals(ff, "ROOT") &&
851  !boost::iequals(ff, "PSI-BIN") && !boost::iequals(ff, "PSI-MDU") && !boost::iequals(ff, "MUD") &&
852  !boost::iequals(ff, "WKM")) { // none of the listed found
853  std::cerr << std::endl << "**ERROR** found unsupported muSR file data format: " << argv[i+1] << std::endl;
855  return 1;
856  }
857  fileFormat = argv[i+1];
858  i++;
859  } else if (!strcmp(argv[i], "-y") || !strcmp(argv[i], "--year")) {
860  if (i+1 >= argc) {
861  std::cerr << std::endl << "**ERROR** found -y, --year without <year>!" << std::endl;
863  return 1;
864  }
865  if (!dump_is_number(argv[i+1])) {
866  std::cerr << std::endl << "**ERROR** found -y, --year with sensless <year> '" << argv[i+1] << "'!" << std::endl;
868  return 1;
869  }
870  int yy = static_cast<int>(strtod(argv[i+1], static_cast<char**>(nullptr)));
871  if ((yy < 1950) || (yy > dump_current_year())) {
872  std::cerr << std::endl << "**ERROR** found -y, --year with <year> '" << yy << "'!";
873  std::cerr << std::endl << " Well, cannot handle files in the pre-muSR time nor in the future." << std::endl;
875  return 1;
876  }
877  year = argv[i+1];
878  i++;
879  } else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--summary")) {
880  summary = true;
881  } else if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "--counts")) {
882  counts = true;
883  } else if (!strcmp(argv[i], "-i") || !strcmp(argv[i], "--instrument")) {
884  if (i+1 >= argc) {
885  std::cerr << std::endl << "**ERROR** found option --instrument without <instrument> input!" << std::endl;
887  return 1;
888  }
889  if (strcmp(argv[i+1], "lem") && strcmp(argv[i+1], "gps") && strcmp(argv[i+1], "ltf") &&
890  strcmp(argv[i+1], "dolly") && strcmp(argv[i+1], "gpd") && strcmp(argv[i+1], "hifi") &&
891  strcmp(argv[i+1], "flame")) {
892  std::cerr << std::endl << "**ERROR** found --instrument with unkown instrument name: '" << argv[i+1] << "'!" << std::endl;
894  return 1;
895  }
896  instrument = argv[i+1];
897  i++;
898  } else {
899  std::cerr << std::endl << "**ERROR** found unkown option '" << argv[i] << "'." << std::endl;
901  return 1;
902  }
903  }
904 
905  // if year is not provided, take the current one
906  if (year.empty()) {
907  std::stringstream ss;
908  ss << dump_current_year();
909  year = ss.str();
910  }
911 
912  if ((runNo.length() != 0) && (fileName.length() != 0)) {
913  std::cerr << std::endl << "**ERROR** currently only either runNo or fileName can be handled, not both simultanously." << std::endl;
914  return 1;
915  }
916 
917  // invoke the startup handler in order to get the default search paths to the data files
918  // read startup file
919  char startup_path_name[128];
920  std::unique_ptr<TSAXParser> saxParser = std::make_unique<TSAXParser>();
921  std::unique_ptr<PStartupHandler> startupHandler = std::make_unique<PStartupHandler>();
922  if (!startupHandler->StartupFileFound()) {
923  std::cerr << std::endl << ">> musrfit **WARNING** couldn't find " << startupHandler->GetStartupFilePath().Data();
924  std::cerr << std::endl;
925  } else {
926  strcpy(startup_path_name, startupHandler->GetStartupFilePath().Data());
927  saxParser->ConnectToHandler("PStartupHandler", startupHandler.get());
928  //status = saxParser->ParseFile(startup_path_name);
929  // parsing the file as above seems to lead to problems in certain environments;
930  // use the parseXmlFile function instead (see PStartupHandler.cpp for the definition)
931  int status = parseXmlFile(saxParser.get(), startup_path_name);
932  // check for parse errors
933  if (status) { // error
934  std::cerr << std::endl << ">> musrfit **WARNING** Reading/parsing musrfit_startup.xml failed.";
935  std::cerr << std::endl;
936  }
937  }
938 
939  // try to find path-file-name via run name templates
940  std::string pathFln("");
941  if (fileName == "") { // only look for runs if the file name is not explicitly given
942  int yy = static_cast<int>(strtod(year.c_str(), static_cast<char**>(nullptr)));
943  int run = static_cast<int>(strtod(runNo.c_str(), static_cast<char**>(nullptr)));
944  PFindRun findRun(startupHandler->GetDataPathList(), startupHandler->GetRunNameTemplateList(),
945  instrument, yy, run, fileFormat);
946  if (findRun.FoundPathName()) {
947  pathFln = findRun.GetPathName().Data();
948  } else {
949  std::cout << "debug> Couldn't find run: " << run << " for instrument " << instrument << ", and year: " << year << std::endl;
950  return 1;
951  }
952  } else { // file name explicitly provided, hence use this as pathFln
953  pathFln = fileName;
954  }
955 
956  // if file format is not given explicitly try to guess it based on the file name extension
957  if (fileFormat == "") {
958  std::string fln(pathFln);
959  boost::to_lower(fln);
960  if (fln.find(".root") != std::string::npos)
961  fileFormat = "MusrRoot"; // could be old ROOT (LEM) as well
962  else if (fln.find(".nxs") != std::string::npos)
963  fileFormat = "NeXus";
964  else if (fln.find(".bin") != std::string::npos)
965  fileFormat = "PSI-BIN";
966  else if (fln.find(".mdu") != std::string::npos)
967  fileFormat = "PSI-MDU";
968  else if (fln.find(".msr") != std::string::npos)
969  fileFormat = "MUD";
970  else if ((fln.find(".nemu") != std::string::npos) || (fln.find(".wkm") != std::string::npos))
971  fileFormat = "WKM";
972 
973  if (fileFormat != "")
974  std::cout << std::endl << "**INFO** the guessed file format is " << fileFormat << std::endl;
975  }
976  if (fileFormat == "") {
977  std::cout << std::endl << "**ERROR** Couldn't guess your file format. You will need to provide it explicitly" << std::endl << std::endl;
978  return 1;
979  }
980 
981  boost::to_lower(fileFormat);
982 
983  if (boost::iequals(fileFormat, "MusrRoot") || boost::iequals(fileFormat, "ROOT")) {
984  dump_header_root(pathFln, summary, counts);
985  } else if (boost::iequals(fileFormat, "NeXus")) {
986 #ifdef PNEXUS_ENABLED
987  dump_header_nexus(pathFln, counts);
988 #else
989  std::cout << std::endl << "Sorry, NeXus is not enabled, hence I cannot help you." << std::endl;
990 #endif
991  } else if (boost::iequals(fileFormat, "PSI-BIN") || boost::iequals(fileFormat, "PSI-MDU")) {
992  dump_header_psi_bin(pathFln, fileFormat, counts);
993  } else if (boost::iequals(fileFormat, "MUD")) {
994  dump_header_mud(pathFln, counts);
995  } else if (boost::iequals(fileFormat, "WKM")) {
996  dump_header_wkm(pathFln);
997  }
998 
999  return 0;
1000 }
void dump_header_syntax()
Definition: dump_header.cpp:81
int dump_header_mud(const std::string fileName, const bool counts)
std::vector< std::string > dump_header_instrument_info(std::string fileName)
int parseXmlFile(TSAXParser *, const char *)
#define DH_MUSR_ROOT
Definition: dump_header.cpp:74
std::vector< Int_t > PIntVector
Definition: PMusr.h:178
int dump_header_root(const std::string fileName, const bool summary, const bool counts)
int dump_header_wkm(const std::string fileName)
int main(int argc, char *argv[])
const char * startup_path_name
int dump_header_psi_bin(const std::string fileName, const std::string fileFormat, const bool counts)
#define DH_LEM_ROOT
Definition: dump_header.cpp:75
int dump_header_nexus(const std::string fileName, const bool counts)
int dump_current_year()
return status
bool dump_is_number(const char *s)