musrfit 1.10.0
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-2026 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#include <cstddef>
41
42#include <iostream>
43#include <fstream>
44#include <sstream>
45#include <string>
46#include <vector>
47#include <memory>
48
49#include <boost/algorithm/string.hpp>
50
51#include <TObject.h>
52#include <TObjArray.h>
53#include <TObjString.h>
54#include <TFile.h>
55#include <TFolder.h>
56#include <TString.h>
57#include <TFolder.h>
58#include <TH1F.h>
59#include <TKey.h>
60
61#ifdef HAVE_GIT_REV_H
62#include "git-revision.h"
63#endif
64
65#include "PFindRun.h"
66#include "PStartupHandler.h"
67#include "TMusrRunHeader.h"
68#include "TLemRunHeader.h"
69#include "MuSR_td_PSI_bin.h"
70#include "mud.h"
71
72#ifdef PNEXUS_ENABLED
73#include "PNeXus.h"
74#endif
75
76#define DH_MUSR_ROOT 0
77#define DH_MUSR_ROOT_DIR 1
78#define DH_LEM_ROOT 2
79
80//------------------------------------------------------------------------
85{
86 std::cout << std::endl << "usage: dump_header [-rn <runNo> | -fn <fileName>] [-ff, --fileFormat <fileFormat>]";
87 std::cout << std::endl << " [-y, --year <year>] [-s, --summary] [-i, --instrument <inst>]";
88 std::cout << std::endl << " [-c, --counts] | ";
89 std::cout << std::endl << " --help | --version";
90 std::cout << std::endl;
91 std::cout << std::endl << " Dumps the header information of a given muSR data file onto the standard output.";
92 std::cout << std::endl << " If no <fileFormat> info is povided, it will try to guess what <fileFormat> it might be.";
93 std::cout << std::endl << " For <runNo> guessing of the file format is not possible. The default assumption here is 'MusrRoot'.";
94 std::cout << std::endl;
95 std::cout << std::endl << " -rn, --runNo <runNo> : run number of the header to be dumped.";
96 std::cout << std::endl << " -fn, --fileName <fileName> : muSR data file name.";
97 std::cout << std::endl << " -ff, --fileFormat <fileFormat> : where <fileFormat> can be:";
98 std::cout << std::endl << " MusrRoot (default), NeXus, ROOT (old LEM), PSI-BIN, PSI-MDU, MUD, WKM";
99 std::cout << std::endl << " NeXus is only supported if enabled.";
100 std::cout << std::endl << " -y, --year <year> : <year> has to be 4 digit, e.g. 2005, if provided it is used to";
101 std::cout << std::endl << " generate the file name for the given <runNo>, otherwise the current";
102 std::cout << std::endl << " year is used. If a file name is given, this option has no effect.";
103 std::cout << std::endl << " -s, --summary : this option is used for LE-uSR data sets only. It will, additionally";
104 std::cout << std::endl << " to the header information, print the summary file content.";
105 std::cout << std::endl << " -i, --instrument <inst> : where <inst> is the requested instrument:";
106 std::cout << std::endl << " lem (default) | gps | ltf | dolly | gpd | hifi | flame | vms.";
107 std::cout << std::endl << " -c, --counts : will show detector counts as well.";
108 std::cout << std::endl << " -h, --help : will show this help";
109 std::cout << std::endl << " -v, --version : will show the current version.";
110 std::cout << std::endl << std::endl;
111}
112
113//------------------------------------------------------------------------
123int dump_header_root(const std::string fileName, const bool summary, const bool counts)
124{
125 TFile f(fileName.c_str());
126 if (f.IsZombie()) {
127 std::cerr << std::endl;
128 std::cerr << "**ERROR** couldn't invoke ROOT/MusrRoot file object." << std::endl;
129 std::cerr << std::endl;
130 return 1;
131 }
132
133 UInt_t fileType = DH_MUSR_ROOT;
134 UInt_t noOfHistos{0};
135 PIntVector redGreenOffset;
136
137
138 TFolder *folder;
139 f.GetObject("RunInfo", folder); // try first LEM-ROOT style file (used until 2011).
140 if (!folder) { // either something is wrong, or it is a MusrRoot file
141 TObject *obj = f.FindObjectAny("RunHeader");
142 if (obj == nullptr) {
143 std::cerr << std::endl << "**ERROR** Couldn't neither obtain RunInfo (LEM), nor RunHeader (MusrRoot) from " << fileName << std::endl;
144 f.Close();
145 return 1;
146 }
147 if (!strcmp(obj->ClassName(), "TFolder")) {
148 fileType = DH_MUSR_ROOT;
149 } else if (!strcmp(obj->ClassName(), "TDirectoryFile")) {
150 fileType = DH_MUSR_ROOT_DIR;
151 } else {
152 std::cerr << std::endl << "**ERROR** RunHeader (MusrRoot) from '" << fileName << "' is neither a TFolder nor a TDirectory. Found: '" << obj->ClassName() << "'" << std::endl;
153 f.Close();
154 return 1;
155 }
156 } else {
157 fileType = DH_LEM_ROOT;
158 }
159
160 std::unique_ptr<TMusrRunHeader> header;
161 bool ok;
162 Int_t ival;
163
164 if (fileType == DH_LEM_ROOT) { // ROOT (LEM)
165 // read header and check if some missing run info need to be fed
166 TLemRunHeader* runHeader = dynamic_cast<TLemRunHeader*>(folder->FindObjectAny("TLemRunHeader"));
167
168 // check if run header is valid
169 if (runHeader == nullptr) {
170 std::cerr << std::endl << "**ERROR** Couldn't obtain run header info from ROOT file " << fileName << std::endl;
171 f.Close();
172 return 1;
173 }
174
175 std::cout << std::endl << "-------------------";
176 std::cout << std::endl << "fileName = " << fileName << ", fileFormat = ROOT (PSI LEM).";
177 std::cout << std::endl << "-------------------";
178 std::cout << std::endl << "Run Title : " << runHeader->GetRunTitle().GetString().Data();
179 std::cout << std::endl << "Run Number : " << runHeader->GetRunNumber();
180 std::cout << std::endl << "Run Start Time : " << runHeader->GetStartTimeString().GetString().Data();
181 std::cout << std::endl << "Run Stop Time : " << runHeader->GetStopTimeString().GetString().Data();
182 std::cout << std::endl << "Laboratory : PSI";
183 std::cout << std::endl << "Instrument : LEM";
184 std::cout << std::endl << "Beamline : muE4";
185 std::cout << std::endl << "Muon Beam Momentum : 28 MeV/c";
186 std::cout << std::endl << "Muon Species : positive muons";
187 std::cout << std::endl << "Muon Source : Target E - slow muons";
188 std::cout << std::endl << "Setup : " << runHeader->GetLemSetup().GetString().Data();
189 std::cout << std::endl << "Comment : n/a";
190 std::cout << std::endl << "Sample Name : n/a";
191 std::cout << std::endl << "Sample Orientation : n/a";
192 std::cout << std::endl << "Sample Temperature : " << runHeader->GetSampleTemperature() << "+-" << runHeader->GetSampleTemperatureError() << " K";
193 std::cout << std::endl << "Sample Mag. Field : " << runHeader->GetSampleBField() << "+-" << runHeader->GetSampleBFieldError() << " G";
194 std::cout << std::endl << "No of Histos : " << runHeader->GetNHist();
195 std::cout << std::endl << "Time Resolution : " << runHeader->GetTimeResolution() << " ns";
196 std::cout << std::endl << "-------------------";
197 std::cout << std::endl << "LEM Specific Entries :";
198 std::cout << std::endl << "Moderator : " << runHeader->GetModerator().GetString().Data();
199 std::cout << std::endl << "Moderator HV : " << runHeader->GetModeratorHV() << " kV";
200 std::cout << std::endl << "Sample HV : " << runHeader->GetSampleHV() << " kV";
201 std::cout << std::endl << "Impl. Energy : " << runHeader->GetImpEnergy() << " keV";
202 std::cout << std::endl << "-------------------";
203 std::cout << std::endl << "Detector Info (for all detectors the same): ";
204 std::cout << std::endl << "-------------------";
205 std::cout << std::endl << "Histo Length : " << runHeader->GetNChannels();
206 double *timeZero = nullptr;
207 timeZero = runHeader->GetTimeZero();
208 if (timeZero != nullptr) {
209 std::cout << std::endl << "Time Zero Bin : " << timeZero[0];
210 std::cout << std::endl << "First Good Bin : " << timeZero[0];
211 } else {
212 std::cout << std::endl << "Time Zero Bin : ??";
213 std::cout << std::endl << "First Good Bin : ??";
214 }
215 std::cout << std::endl << "Last Good Bin : " << runHeader->GetNChannels()-1;
216 std::cout << std::endl << "-------------------" << std::endl << std::endl;
217 } else { // MusrRoot
218 // invoke the MusrRoot header object
219 header = std::make_unique<TMusrRunHeader>(fileName.c_str(), true); // read quite
220 if (header == nullptr) {
221 std::cerr << std::endl << "**ERROR** Couldn't invoke MusrRoot RunHeader from file:" << fileName;
222 std::cerr << std::endl;
223 f.Close();
224 return 1;
225 }
226
227 // check if TFolder or TDirectory is needed
228 if (fileType == DH_MUSR_ROOT) { // TFolder
229 f.GetObject("RunHeader", folder);
230 if (folder == nullptr) {
231 std::cerr << std::endl << "**ERROR** Couldn't get folder from MusrRoot RunHeader from file:" << fileName;
232 std::cerr << std::endl;
233 f.Close();
234 return 1;
235 }
236 // try to populate the MusrRoot header object
237 if (!header->ExtractAll(folder)) {
238 std::cerr << std::endl << "**ERROR** Couldn't invoke MusrRoot RunHeader content from file:" << fileName;
239 std::cerr << std::endl;
240 f.Close();
241 return 1;
242 }
243 } else { // TDirectory
244 TDirectoryFile *runHeader = nullptr;
245 f.GetObject("RunHeader", runHeader);
246 if (runHeader == nullptr) {
247 std::cerr << std::endl << "**ERROR** Couldn't get runHeader (TDirectory) from MusrRoot RunHeader from file:" << fileName;
248 std::cerr << std::endl;
249 f.Close();
250 return 1;
251 }
252 // try to populate the MusrRoot header object
253 if (!header->ExtractAll(runHeader)) {
254 std::cerr << std::endl << "**ERROR** Couldn't invoke MusrRoot RunHeader in file:" << fileName;
255 std::cerr << std::endl;
256 f.Close();
257 return 1;
258 }
259 }
260
261 header->DumpHeader();
262
263 if (counts) {
264 PIntVector ivec;
265 header->Get("RunInfo/No of Histos", ival, ok);
266 if (ok)
267 noOfHistos = ival;
268 header->Get("RunInfo/RedGreen Offsets", ivec, ok);
269 if (ok)
270 redGreenOffset = ivec;
271 }
272 }
273
274 // summary as well?
275 if (summary && ((fileType == DH_MUSR_ROOT) || (fileType == DH_MUSR_ROOT_DIR))) {
276 TObjArray *runSum=nullptr;
277 TDirectoryFile *runSumDir=nullptr;
278
279 if (fileType == DH_MUSR_ROOT) // TFolder
280 runSum = static_cast<TObjArray*>(folder->FindObject("RunSummary"));
281 else // TDirectory
282 f.GetObject("RunHeader/RunSummary", runSumDir);
283
284 if (!runSum && !runSumDir) { // something is wrong!!
285 std::cerr << std::endl << "**ERROR** Couldn't obtain RunSummary " << fileName << std::endl;
286 f.Close();
287 return 1;
288 }
289 std::cout << "++++++++++++++++++++" << std::endl;
290 std::cout << " Run Summary" << std::endl;
291 std::cout << "++++++++++++++++++++" << std::endl;
292 TObjString *tstr;
293 TString str;
294 if (runSum) {
295 for (Int_t i=0; i<runSum->GetEntries(); i++) {
296 tstr = static_cast<TObjString*>(runSum->At(i));
297 str = tstr->String();
298 std::cout << str;
299 if (!str.Contains("\r") && !str.Contains("\n"))
300 std::cout << std::endl;
301 }
302 } else if (runSumDir) {
303 TIter next(runSumDir->GetListOfKeys());
304 TKey *key;
305 while ((key = (TKey*)next())) {
306 if (TString(key->GetClassName()) == "TObjString") {
307 tstr = dynamic_cast<TObjString*>(key->ReadObj());
308 str = tstr->String();
309 std::cout << str;
310 if (!str.Contains("\r") && !str.Contains("\n"))
311 std::cout << std::endl;
312 }
313 }
314 }
315 }
316
317 // detector counts as well?
318 if (counts && (fileType == DH_MUSR_ROOT)) {
319 // dump the detector counts
320 std::cout << "Detector counts (all, between fgb and lgb)" << std::endl;
321 f.GetObject("histos", folder);
322 if ((folder != nullptr) && (header != nullptr)) {
323 char detectorLabel[64];
324 TH1F *histo{nullptr};
325 UInt_t total{0}, total_good{0}, ta, tg;
326 Int_t fgb, lgb;
327 for (UInt_t i=0; i<redGreenOffset.size(); i++) {
328 std::cout << " Group " << i+1 << " (Offset=" << redGreenOffset[i] << ") : " << std::endl;
329 total = 0;
330 total_good = 0;
331 for (UInt_t j=0; j<noOfHistos; j++) {
332 // get fgb, lgb
333 fgb = -1;
334 snprintf(detectorLabel, sizeof(detectorLabel), "DetectorInfo/Detector%03d/First Good Bin", redGreenOffset[i]+j+1);
335 header->Get(detectorLabel, ival, ok);
336 if (ok) {
337 fgb = ival;
338 }
339 lgb = -1;
340 snprintf(detectorLabel, sizeof(detectorLabel), "DetectorInfo/Detector%03d/Last Good Bin", redGreenOffset[i]+j+1);
341 header->Get(detectorLabel, ival, ok);
342 if (ok) {
343 lgb = ival;
344 }
345 // get histo info
346 snprintf(detectorLabel, sizeof(detectorLabel), "hDecay%03d", redGreenOffset[i]+j+1);
347 histo = (TH1F*) folder->FindObjectAny(detectorLabel);
348 if (histo != nullptr) {
349 ta = histo->Integral(0, histo->GetNbinsX()+1);
350 tg = histo->Integral(fgb, lgb);
351 std::cout << " " << histo->GetTitle() << ":\t " << ta << ", " << tg << std::endl;
352 total += ta;
353 total_good += tg;
354 }
355 }
356 if (i % 2 == 0)
357 std::cout << " total counts of group " << i+1 << ":\t\t\t " << total << ", " << total_good << std::endl;
358 else
359 std::cout << " total counts of group " << i+1 << ":\t\t\t\t\t " << total << ", " << total_good << std::endl;
360 }
361 } else {
362 std::cout << "Sorry, no histos folder found" << std::endl;
363 f.Close();
364 return 0;
365 }
366 }
367
368 f.Close();
369
370 return 0;
371}
372
373//------------------------------------------------------------------------
382int dump_header_nexus(const std::string fileName, const bool counts) {
383
384#ifdef PNEXUS_ENABLED
385 nxs::HDFType type = nxs::checkHDFType(fileName);
386
387 // check for type errors, missing enabled HDF4
388 switch (type) {
390 std::cout << std::endl << ">> PRunDataHandler::ReadNexusFile(): HDF4 file." << std::endl;
391#ifndef HAVE_HDF4
392 std::cerr << std::endl << ">> PRunDataHandler::ReadNexusFile(): **ERROR**, HDF4 is not enabled." << std::endl;
393 return 1;
394#endif
395 break;
397 std::cout << std::endl << ">> PRunDataHandler::ReadNexusFile(): HDF5 file." << std::endl;
398 break;
400 std::cerr << std::endl << ">> PRunDataHandler::ReadNexusFile(): Not a valid NeXus file." << std::endl;
401 return 1;
402 }
403
404 if (type == nxs::HDFType::HDF4) {
405#ifdef HAVE_HDF4
406 std::unique_ptr<nxH4::PNeXus> nxs_file = std::make_unique<nxH4::PNeXus>(fileName);
407 if (nxs_file == nullptr) {
408 std::cerr << std::endl << "**ERROR** allocation of nxH4::PNeXus object failed." << std::endl;
409 }
410 nxs_file->Dump();
411#endif
412 } else { // HDF5
413 std::unique_ptr<nxH5::PNeXus> nxs_file = std::make_unique<nxH5::PNeXus>(fileName);
414 if (nxs_file == nullptr) {
415 std::cerr << std::endl << "**ERROR** allocation of nxH5::PNeXus object failed." << std::endl;
416 }
417 nxs_file->Dump();
418 }
419#else
420 std::cout << std::endl << "NeXus not enabled, hence the header information cannot be dumped." << std::endl << std::endl;
421#endif
422
423 return 0;
424}
425
426//------------------------------------------------------------------------
434std::vector<std::string> dump_header_instrument_info(std::string fileName)
435{
436 std::vector<std::string> result;
437 std::string fln(fileName);
438 boost::to_lower(fln);
439
440 if ((fln.find(".bin") != std::string::npos) || (fln.find(".mdu") != std::string::npos)) { // PSI-BIN or PSI-MDU format
441 if (fln.find("_gps_") != std::string::npos) {
442 result.push_back("GPS");
443 result.push_back("piM3.2");
444 result.push_back("28 MeV/c");
445 result.push_back("likely to be positive muons");
446 result.push_back("Target M");
447 } else if (fln.find("_ltf_") != std::string::npos) {
448 result.push_back("LTF");
449 result.push_back("piM3.1");
450 result.push_back("28 MeV/c");
451 result.push_back("likely to be positive muons");
452 result.push_back("Target M");
453 } else if (fln.find("_dolly_") != std::string::npos) {
454 result.push_back("DOLLY");
455 result.push_back("piE1");
456 result.push_back("28 MeV/c");
457 result.push_back("likely to be positive muons");
458 result.push_back("Target E");
459 } else if (fln.find("_alc_") != std::string::npos) {
460 result.push_back("ALC");
461 result.push_back("piE3");
462 result.push_back("28 MeV/c");
463 result.push_back("likely to be positive muons");
464 result.push_back("Target E");
465 } else if (fln.find("_hifi_") != std::string::npos) {
466 result.push_back("HAL9500");
467 result.push_back("piE3");
468 result.push_back("28 MeV/c");
469 result.push_back("likely to be positive muons");
470 result.push_back("Target E");
471 } else if (fln.find("_gpd_") != std::string::npos) {
472 result.push_back("GPD");
473 result.push_back("muE1");
474 result.push_back("60-125 MeV/c");
475 result.push_back("likely to be positive muons");
476 result.push_back("Target E");
477 } else {
478 result.push_back("???");
479 result.push_back("???");
480 result.push_back("??? MeV/c");
481 result.push_back("???");
482 result.push_back("???");
483 }
484 }
485
486 return result;
487}
488
489//------------------------------------------------------------------------
499int dump_header_psi_bin(const std::string fileName, const std::string fileFormat, const bool counts)
500{
501 MuSR_td_PSI_bin psiBin;
502 int status;
503 bool success = false;
504
505 // read psi bin file
506 status = psiBin.Read(fileName.c_str());
507 switch (status) {
508 case 0: // everything perfect
509 success = true;
510 break;
511 case 1: // couldn't open file, or failed while reading the header
512 std::cout << std::endl << "**ERROR** couldn't open psi-bin file, or failed while reading the header." << std::endl;
513 success = false;
514 break;
515 case 2: // unsupported version of the data
516 std::cout << std::endl << "**ERROR** psi-bin file: unsupported version of the data." << std::endl;
517 success = false;
518 break;
519 case 3: // error when allocating data buffer
520 std::cout << std::endl << "**ERROR** psi-bin file: error when allocating data buffer." << std::endl;
521 success = false;
522 break;
523 case 4: // number of histograms/record not equals 1
524 std::cout << std::endl << ">> **ERROR** psi-bin file: number of histograms/record not equals 1." << std::endl;
525 success = false;
526 break;
527 default: // you never should have reached this point
528 std::cout << std::endl << ">> **ERROR** psi-bin file: no clue why you reached this point." << std::endl;
529 success = false;
530 break;
531 }
532
533 // if any reading error happend, get out of here
534 if (!success)
535 return 1;
536
537 std::vector<std::string> vstr;
538 std::vector<double> dVal, dErrVal;
539 std::cout << std::endl << "-------------------";
540 std::cout << std::endl << "fileName = " << fileName << ", fileFormat = " << fileFormat;
541 std::cout << std::endl << "-------------------";
542 std::cout << std::endl << "Run Title : " << psiBin.GetComment();
543 std::cout << std::endl << "Run Number : " << psiBin.GetRunNumberInt();
544 vstr = psiBin.GetTimeStartVector();
545 if (vstr.size() < 2) {
546 std::cout << std::endl << "**ERROR** couldn't obtain \"Run Start Time\" will quit." << std::endl << std::endl;
547 return 1;
548 }
549 std::cout << std::endl << "Run Start Time : " << vstr[0] << "; " << vstr[1];
550 vstr = psiBin.GetTimeStopVector();
551 if (vstr.size() < 2) {
552 std::cout << std::endl << "**ERROR** couldn't obtain \"Run Stop Time\" will quit." << std::endl << std::endl;
553 return 1;
554 }
555 std::cout << std::endl << "Run Stop Time : " << vstr[0] << "; " << vstr[1];
556 std::cout << std::endl << "Laboratory : PSI";
557 vstr = dump_header_instrument_info(fileName);
558 if (vstr.size() < 5) {
559 std::cout << std::endl << "**ERROR** couldn't obtain \"Instrument\" will quit." << std::endl << std::endl;
560 return 1;
561 }
562 std::cout << std::endl << "Instrument : " << vstr[0];
563 std::cout << std::endl << "Beamline : " << vstr[1];
564 std::cout << std::endl << "Muon Beam Momentum : " << vstr[2];
565 std::cout << std::endl << "Muon Species : " << vstr[3];
566 std::cout << std::endl << "Muon Source : " << vstr[4];
567 std::cout << std::endl << "Setup : " << psiBin.GetComment();
568 std::cout << std::endl << "Comment : n/a";
569 std::cout << std::endl << "Sample Name : " << psiBin.GetSample();
570 std::cout << std::endl << "Sample Orientation : " << psiBin.GetOrient();
571 dVal = psiBin.GetTemperaturesVector();
572 dErrVal = psiBin.GetDevTemperaturesVector();
573 if (dVal.size() != dErrVal.size()) {
574 std::cout << std::endl << "Sample Temperature : " << psiBin.GetTemp();
575 } else {
576 for (unsigned int i=0; i<dVal.size(); i++) {
577 std::cout << std::endl << "Sample Temp. " << i+1 << " : " << dVal[i] << " (" << dErrVal[i] << ") K";
578 }
579 }
580 std::cout << std::endl << "Sample Mag. Field : " << psiBin.GetField();
581 std::cout << std::endl << "No of Histos : " << psiBin.GetNumberHistoInt();
582 std::cout << std::endl << "Time Resolution : " << psiBin.GetBinWidthNanoSec() << " ns";
583 for (int i=0; i<psiBin.GetNumberHistoInt(); i++) {
584 std::cout << std::endl << "-------------------";
585 std::cout << std::endl << "Histo No : " << i;
586 std::cout << std::endl << "Histo Name : " << psiBin.GetNameHisto(i);
587 std::cout << std::endl << "Histo Length : " << psiBin.GetHistoLengthBin();
588 std::cout << std::endl << "Time Zero Bin : " << psiBin.GetT0Int(i);
589 std::cout << std::endl << "First Good Bin : " << psiBin.GetFirstGoodInt(i);
590 std::cout << std::endl << "Last Good Bin : " << psiBin.GetLastGoodInt(i);
591 if (counts)
592 std::cout << std::endl << "No of Events : " << psiBin.GetEventsHistoLong(i);
593 }
594 std::cout << std::endl << "-------------------" << std::endl << std::endl;
595
596 return 0;
597}
598
599//------------------------------------------------------------------------
607int dump_header_mud(const std::string fileName, const bool counts)
608{
609 int fh;
610 UINT32 type, val;
611 char str[1024];
612 int success;
613
614 char fln[256];
615 memset(fln, '\0', sizeof(fln));
616 strncpy(fln, fileName.c_str(), sizeof(fln));
617 fh = MUD_openRead(fln, &type);
618 if (fh == -1) {
619 std::cerr << std::endl << "**ERROR** Couldn't open mud-file " << fileName << ", sorry." << std::endl;
620 return 1;
621 }
622
623 std::cout << std::endl << "-------------------";
624 std::cout << std::endl << "fileName = " << fileName << ", fileFormat = MUD";
625 std::cout << std::endl << "-------------------";
626 // run title
627 success = MUD_getTitle( fh, str, sizeof(str) );
628 if (success)
629 std::cout << std::endl << "Run Title : " << str;
630 else
631 std::cout << std::endl << "Run Title : ???";
632 // run number
633 success = MUD_getRunNumber( fh, &val );
634 if (success)
635 std::cout << std::endl << "Run Number : " << val;
636 else
637 std::cout << std::endl << "Run Number : ???";
638 // start time
639 time_t tval;
640 struct tm *dt;
641 success = MUD_getTimeBegin( fh, &val );
642 tval = static_cast<time_t>(val);
643 if (success) {
644 dt = localtime(static_cast<const time_t*>(&tval));
645 if (dt != nullptr) {
646 strftime(str, sizeof(str), "%F; %T", dt);
647 std::cout << std::endl << "Run Start Time : " << str;
648 } else {
649 std::cout << std::endl << "Run Start Time : ??";
650 }
651 } else {
652 std::cout << std::endl << "Run Start Time : ???";
653 }
654 // stop time
655 success = MUD_getTimeEnd( fh, &val );
656 tval = static_cast<time_t>(val);
657 if (success) {
658 dt = localtime(static_cast<const time_t*>(&tval));
659 if (dt != nullptr) {
660 strftime(str, sizeof(str), "%F; %T", dt);
661 std::cout << std::endl << "Run Stop Time : " << str;
662 } else {
663 std::cout << std::endl << "Run Stop Time : ??";
664 }
665 } else {
666 std::cout << std::endl << "Run Stop Time : ???";
667 }
668 // laboratory
669 success = MUD_getLab( fh, str, sizeof(str) );
670 if (success)
671 std::cout << std::endl << "Laboratory : " << str;
672 else
673 std::cout << std::endl << "Laboratory : ???";
674 // instrument
675 success = MUD_getApparatus( fh, str, sizeof(str) );
676 if (success)
677 std::cout << std::endl << "Instrument : " << str;
678 else
679 std::cout << std::endl << "Instrument : ???";
680 // beamline
681 success = MUD_getArea( fh, str, sizeof(str) );
682 if (success)
683 std::cout << std::endl << "Beamline : " << str;
684 else
685 std::cout << std::endl << "Beamline : ???";
686
687 std::cout << std::endl << "Muon Beam Momentum : ???";
688 std::cout << std::endl << "Muon Species : positive muon?";
689 std::cout << std::endl << "Muon Source : ???";
690
691 // method
692 success = MUD_getMethod( fh, str, sizeof(str) );
693 if (success)
694 std::cout << std::endl << "Method : " << str;
695 else
696 std::cout << std::endl << "Method : ???";
697
698 // sample
699 success = MUD_getSample( fh, str, sizeof(str) );
700 if (success)
701 std::cout << std::endl << "Sample Name : " << str;
702 else
703 std::cout << std::endl << "Sample Name : ???";
704
705 // orientation
706 success = MUD_getOrient( fh, str, sizeof(str) );
707 if (success)
708 std::cout << std::endl << "Sample Orientation : " << str;
709 else
710 std::cout << std::endl << "Sample Orientation : ???";
711
712 // temperature
713 success = MUD_getTemperature( fh, str, sizeof(str) );
714 if (success)
715 std::cout << std::endl << "Sample Temperature : " << str;
716 else
717 std::cout << std::endl << "Sample Temperature : ???";
718
719 // magnetic field
720 success = MUD_getField( fh, str, sizeof(str) );
721 if (success)
722 std::cout << std::endl << "Sample Magn. Field : " << str;
723 else
724 std::cout << std::endl << "Sample Magn. Field : ???";
725
726 // number of histograms
727 int noHistos = 0;
728 success = MUD_getHists(fh, &type, &val);
729 if (success) {
730 std::cout << std::endl << "No of Histos : " << val;
731 noHistos = val;
732 } else {
733 std::cout << std::endl << "No of Histos : ???";
734 }
735
736 // time resolution
737 REAL64 timeResolution = 0.0; // in seconds!!
738 success = MUD_getHistSecondsPerBin( fh, 1, &timeResolution );
739 timeResolution *= 1.0e9; // sec -> nsec
740 if (success)
741 std::cout << std::endl << "Time Resolution : " << timeResolution << " ns";
742 else
743 std::cout << std::endl << "Time Resolution : ??? ns";
744
745 // detector related stuff
746 for (int i=0; i<noHistos; i++) {
747 std::cout << std::endl << "-------------------";
748 std::cout << std::endl << "Histo No " << i+1;
749
750 success = MUD_getHistTitle( fh, i+1, str, 1023);
751 if (success)
752 std::cout << std::endl << "Histo Name : " << str;
753 else
754 std::cout << std::endl << "Histo Name : ???";
755
756 success = MUD_getHistNumBins( fh, i+1, &val );
757 if (success)
758 std::cout << std::endl << "Histo Length : " << val;
759 else
760 std::cout << std::endl << "Histo Length : ???";
761
762 success = MUD_getHistT0_Bin( fh, i+1, &val );
763 if (success)
764 std::cout << std::endl << "Time Zero Bin : " << val;
765 else
766 std::cout << std::endl << "Time Zero Bin : ???";
767
768 success = MUD_getHistGoodBin1( fh, i+1, &val );
769 if (success)
770 std::cout << std::endl << "First Good Bin : " << val;
771 else
772 std::cout << std::endl << "First Good Bin : ???";
773
774 success = MUD_getHistGoodBin2( fh, i+1, &val );
775 if (success)
776 std::cout << std::endl << "Last Good Bin : " << val;
777 else
778 std::cout << std::endl << "Last Good Bin : ???";
779 if (counts) {
780 success = MUD_getHistNumEvents( fh, i+1, &val );
781 if (success) {
782 std::cout << std::endl << "#Events : " << val;
783 }
784 }
785 }
786
787 std::cout << std::endl << "-------------------" << std::endl << std::endl;
788
789 MUD_closeRead(fh);
790
791 return 0;
792}
793
794//------------------------------------------------------------------------
801int dump_header_wkm(const std::string fileName)
802{
803 std::ifstream fin(fileName.c_str(), std::ifstream::in);
804 if (!fin.is_open()) {
805 std::cout << std::endl << "**ERROR** haven't found \"" << fileName << "\", will quit." << std::endl << std::endl;
806 return 1;
807 }
808 std::cout << std::endl << "-------------------";
809 std::cout << std::endl << "fileName = " << fileName << ", fileFormat = WKM";
810 std::cout << std::endl << "-------------------";
811 char header[256];
812 while (fin.good()) {
813 fin.getline(header, 256);
814 if (strlen(header) == 0)
815 break;
816 std::cout << std::endl << header;
817 }
818 std::cout << std::endl << "-------------------" << std::endl << std::endl;
819 fin.close();
820
821 return 0;
822}
823
824//------------------------------------------------------------------------
832bool dump_is_number(const char *s)
833{
834 int i=0;
835
836 if (s == nullptr) // make sure it is not a null pointer
837 return false;
838
839 while (isdigit(s[i]))
840 i++;
841
842 if (s[i] == '\0')
843 return true;
844 else
845 return false;
846}
847
848//------------------------------------------------------------------------
855{
856 time_t rawtime;
857 struct tm *timeinfo;
858 char buffer[32];
859 memset(buffer, '\0', sizeof(buffer));
860
861 time (&rawtime);
862 timeinfo = localtime(&rawtime);
863 if (timeinfo != nullptr)
864 strftime(buffer, 32, "%Y", timeinfo);
865 else
866 strncpy(buffer, "1900", sizeof(buffer));
867
868 return atoi(buffer);
869}
870
871//------------------------------------------------------------------------
881int main(int argc, char *argv[])
882{
883 if (argc == 1) {
885 return 0;
886 }
887
888 std::string runNo("");
889 std::string fileName("");
890 std::string fileFormat("");
891 std::string year("");
892 std::string instrument("lem");
893 bool summary(false);
894 bool counts(false);
895
896 for (int i=1; i<argc; i++) {
897 if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h")) {
899 return 0;
900 } else if (!strcmp(argv[i], "--version") || !strcmp(argv[i], "-v")) {
901#ifdef HAVE_CONFIG_H
902#ifdef HAVE_GIT_REV_H
903 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;
904#else
905 std::cout << std::endl << "dump_header version: " << PACKAGE_VERSION << " (" << BUILD_TYPE << "), ROOT version: " << ROOT_VERSION_USED << std::endl << std::endl;
906#endif
907#else
908#ifdef HAVE_GIT_REV_H
909 std::cout << std::endl << "dump_header git-branch: " << GIT_BRANCH << ", git-rev: " << GIT_CURRENT_SHA1 << std::endl << std::endl;
910#else
911 std::cout << std::endl << "dump_header version: unknown" << std::endl << std::endl;
912#endif
913#endif
914 return 0;
915 } else if (!strcmp(argv[i], "-rn") || !strcmp(argv[i], "--runNo")) {
916 if (i+1 >= argc) {
917 std::cerr << std::endl << "**ERROR** found -rn, --runNo without <runNo>!" << std::endl;
919 return 1;
920 }
921 // make sure there is only one 'legal' run number
922 int count = 1;
923 while (dump_is_number(argv[i+count]) && (i+count < argc))
924 count++;
925 // make sure there is one and only one run number given
926 if (count == 1) {
927 std::cerr << std::endl << "**ERROR** found -rn, --runNo without <runNo>, or the provided <runNo> ('" << argv[i+1] << "') is not a number!" << std::endl;
929 return 1;
930 }
931 if (count > 2) {
932 std::cerr << std::endl << "**ERROR** found -rn, --runNo with more than one <runNo>! This is not yet supported." << std::endl;
934 return 1;
935 }
936 runNo = argv[i+1];
937 i++;
938 } else if (!strcmp(argv[i], "-fn") || !strcmp(argv[i], "--fileName")) {
939 if (i+1 >= argc) {
940 std::cerr << std::endl << "**ERROR** found -fn, --fileName without <fileName>!" << std::endl;
942 return 1;
943 }
944 fileName = argv[i+1];
945 i++;
946 } else if (!strcmp(argv[i], "--fileFormat") || !strcmp(argv[i], "-ff")) {
947 if (i+1 >= argc) {
948 std::cerr << std::endl << "**ERROR** found -ff, --fileFormat without <fileFormat>!" << std::endl;
950 return 1;
951 }
952 std::string ff(argv[i+1]);
953 if (!boost::iequals(ff, "MusrRoot") && !boost::iequals(ff, "NeXus") && !boost::iequals(ff, "ROOT") &&
954 !boost::iequals(ff, "PSI-BIN") && !boost::iequals(ff, "PSI-MDU") && !boost::iequals(ff, "MUD") &&
955 !boost::iequals(ff, "WKM")) { // none of the listed found
956 std::cerr << std::endl << "**ERROR** found unsupported muSR file data format: " << argv[i+1] << std::endl;
958 return 1;
959 }
960 fileFormat = argv[i+1];
961 i++;
962 } else if (!strcmp(argv[i], "-y") || !strcmp(argv[i], "--year")) {
963 if (i+1 >= argc) {
964 std::cerr << std::endl << "**ERROR** found -y, --year without <year>!" << std::endl;
966 return 1;
967 }
968 if (!dump_is_number(argv[i+1])) {
969 std::cerr << std::endl << "**ERROR** found -y, --year with sensless <year> '" << argv[i+1] << "'!" << std::endl;
971 return 1;
972 }
973 int yy = static_cast<int>(strtod(argv[i+1], static_cast<char**>(nullptr)));
974 if ((yy < 1950) || (yy > dump_current_year())) {
975 std::cerr << std::endl << "**ERROR** found -y, --year with <year> '" << yy << "'!";
976 std::cerr << std::endl << " Well, cannot handle files in the pre-muSR time nor in the future." << std::endl;
978 return 1;
979 }
980 year = argv[i+1];
981 i++;
982 } else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--summary")) {
983 summary = true;
984 } else if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "--counts")) {
985 counts = true;
986 } else if (!strcmp(argv[i], "-i") || !strcmp(argv[i], "--instrument")) {
987 if (i+1 >= argc) {
988 std::cerr << std::endl << "**ERROR** found option --instrument without <instrument> input!" << std::endl;
990 return 1;
991 }
992 if (strcmp(argv[i+1], "lem") && strcmp(argv[i+1], "gps") && strcmp(argv[i+1], "ltf") &&
993 strcmp(argv[i+1], "dolly") && strcmp(argv[i+1], "gpd") && strcmp(argv[i+1], "hifi") &&
994 strcmp(argv[i+1], "flame") && strcmp(argv[i+1], "vms")) {
995 std::cerr << std::endl << "**ERROR** found --instrument with unkown instrument name: '" << argv[i+1] << "'!" << std::endl;
997 return 1;
998 }
999 instrument = argv[i+1];
1000 i++;
1001 } else {
1002 std::cerr << std::endl << "**ERROR** found unkown option '" << argv[i] << "'." << std::endl;
1004 return 1;
1005 }
1006 }
1007
1008 // if year is not provided, take the current one
1009 if (year.empty()) {
1010 std::stringstream ss;
1011 ss << dump_current_year();
1012 year = ss.str();
1013 }
1014
1015 if ((runNo.length() != 0) && (fileName.length() != 0)) {
1016 std::cerr << std::endl << "**ERROR** currently only either runNo or fileName can be handled, not both simultanously." << std::endl;
1017 return 1;
1018 }
1019
1020 // invoke the startup handler in order to get the default search paths to the data files
1021 // read startup file
1022 char startup_path_name[128];
1023 memset(startup_path_name, '\0', sizeof(startup_path_name));
1024 std::unique_ptr<TSAXParser> saxParser = std::make_unique<TSAXParser>();
1025 std::unique_ptr<PStartupHandler> startupHandler = std::make_unique<PStartupHandler>();
1026 if (!startupHandler->StartupFileFound()) {
1027 std::cerr << std::endl << ">> musrfit **WARNING** couldn't find " << startupHandler->GetStartupFilePath().Data();
1028 std::cerr << std::endl;
1029 } else {
1030 strncpy(startup_path_name, startupHandler->GetStartupFilePath().Data(), sizeof(startup_path_name));
1031 saxParser->ConnectToHandler("PStartupHandler", startupHandler.get());
1032 //status = saxParser->ParseFile(startup_path_name);
1033 // parsing the file as above seems to lead to problems in certain environments;
1034 // use the parseXmlFile function instead (see PStartupHandler.cpp for the definition)
1035 int status = parseXmlFile(saxParser.get(), startup_path_name);
1036 // check for parse errors
1037 if (status) { // error
1038 std::cerr << std::endl << ">> musrfit **WARNING** Reading/parsing musrfit_startup.xml failed.";
1039 std::cerr << std::endl;
1040 }
1041 }
1042
1043 // try to find path-file-name via run name templates
1044 std::string pathFln("");
1045 if (fileName == "") { // only look for runs if the file name is not explicitly given
1046 int yy = static_cast<int>(strtod(year.c_str(), static_cast<char**>(nullptr)));
1047 int run = static_cast<int>(strtod(runNo.c_str(), static_cast<char**>(nullptr)));
1048 PFindRun findRun(startupHandler->GetDataPathList(), startupHandler->GetRunNameTemplateList(),
1049 instrument, yy, run, fileFormat);
1050 if (findRun.FoundPathName()) {
1051 pathFln = findRun.GetPathName().Data();
1052 } else {
1053 std::cout << "debug> Couldn't find run: " << run << " for instrument " << instrument << ", and year: " << year << std::endl;
1054 return 1;
1055 }
1056 } else { // file name explicitly provided, hence use this as pathFln
1057 pathFln = fileName;
1058 }
1059
1060 // if file format is not given explicitly try to guess it based on the file name extension
1061 if (fileFormat == "") {
1062 std::string fln(pathFln);
1063 boost::to_lower(fln);
1064 if (fln.find(".root") != std::string::npos)
1065 fileFormat = "MusrRoot"; // could be old ROOT (LEM) as well
1066 else if (fln.find(".nxs") != std::string::npos)
1067 fileFormat = "NeXus";
1068 else if (fln.find(".bin") != std::string::npos)
1069 fileFormat = "PSI-BIN";
1070 else if (fln.find(".mdu") != std::string::npos)
1071 fileFormat = "PSI-MDU";
1072 else if (fln.find(".msr") != std::string::npos)
1073 fileFormat = "MUD";
1074 else if ((fln.find(".nemu") != std::string::npos) || (fln.find(".wkm") != std::string::npos))
1075 fileFormat = "WKM";
1076
1077 if (fileFormat != "")
1078 std::cout << std::endl << "**INFO** the guessed file format is " << fileFormat << std::endl;
1079 }
1080 if (fileFormat == "") {
1081 std::cout << std::endl << "**ERROR** Couldn't guess your file format. You will need to provide it explicitly" << std::endl << std::endl;
1082 return 1;
1083 }
1084
1085 boost::to_lower(fileFormat);
1086
1087 if (boost::iequals(fileFormat, "MusrRoot") || boost::iequals(fileFormat, "ROOT")) {
1088 dump_header_root(pathFln, summary, counts);
1089 } else if (boost::iequals(fileFormat, "NeXus")) {
1090#ifdef PNEXUS_ENABLED
1091 dump_header_nexus(pathFln, counts);
1092#else
1093 std::cout << std::endl << "Sorry, NeXus is not enabled, hence I cannot help you." << std::endl;
1094#endif
1095 } else if (boost::iequals(fileFormat, "PSI-BIN") || boost::iequals(fileFormat, "PSI-MDU")) {
1096 dump_header_psi_bin(pathFln, fileFormat, counts);
1097 } else if (boost::iequals(fileFormat, "MUD")) {
1098 dump_header_mud(pathFln, counts);
1099 } else if (boost::iequals(fileFormat, "WKM")) {
1100 dump_header_wkm(pathFln);
1101 }
1102
1103 return 0;
1104}
std::vector< Int_t > PIntVector
Definition PMusr.h:367
NeXus HDF4/HDF5 file reader and writer for muon spin rotation data.
const char * startup_path_name
return status
int parseXmlFile(TSAXParser *, const char *)
Replacement function for TSAXParser::ParseFile().
std::string GetOrient()
Method returning a string containing the orientation specified in the title.
int GetT0Int(int i)
Method returning an integer representing the t0 point (from the "integer" t0 in the header) for a spe...
int GetLastGoodInt(int i)
Method returning an integer representing the last good bin specified in the header for a specified hi...
std::string GetNameHisto(int i)
Method returning a string containing the name of the histogram <i>
std::vector< double > GetTemperaturesVector()
Method returning a vector of doubles containing monitored values (usually temperatures)
std::string GetField()
Method returning a string containing the field specified in the title.
std::string GetTemp()
Method returning a string containing the temperature specified in the title.
std::vector< std::string > GetTimeStartVector()
Method returning a vector of strings containing 1) the date when the run was started and 2) the time ...
long GetEventsHistoLong(int i)
Method returning a long representing the number of events in a specified histograms.
std::vector< std::string > GetTimeStopVector()
Method returning a vector of strings containing 1) the date when the run was stopped and 2) the time ...
std::vector< double > GetDevTemperaturesVector()
Method returning a vector of doubles containing standard deviations of the monitored values (usually ...
double GetBinWidthNanoSec()
Method returning a double representing the bin-width in nanoseconds.
int Read(const char *fileName)
Method to read a PSI-bin or an MDU file.
std::string GetSample()
Method returning a string containing the fSample name.
int GetFirstGoodInt(int i)
Method returning an integer representing the first good bin specified in the header for a specified h...
std::string GetComment()
Method returning a string containing the comment specified in the title.
PFindRun - Locates muSR data files using template-based path resolution.
Definition PFindRun.h:68
Bool_t FoundPathName()
Searches for the run file using configured templates and paths.
Definition PFindRun.cpp:133
TString GetPathName()
Returns the full path to the found run file.
Definition PFindRun.h:128
int main(int argc, char *argv[])
#define DH_MUSR_ROOT
int dump_current_year()
void dump_header_syntax()
int dump_header_root(const std::string fileName, const bool summary, const bool counts)
bool dump_is_number(const char *s)
int dump_header_psi_bin(const std::string fileName, const std::string fileFormat, const bool counts)
int dump_header_wkm(const std::string fileName)
#define DH_LEM_ROOT
#define DH_MUSR_ROOT_DIR
std::vector< std::string > dump_header_instrument_info(std::string fileName)
int dump_header_nexus(const std::string fileName, const bool counts)
int dump_header_mud(const std::string fileName, const bool counts)
unsigned long UINT32
Definition mud.h:146
double REAL64
Definition mud.h:149
int MUD_getHistSecondsPerBin(int fd, int num, REAL64 *pSecondsPerBin)
int MUD_openRead(char *filename, UINT32 *pType)
int MUD_closeRead(int fd)
HDFType
Enumeration of supported HDF file types.
Definition PNeXus.h:141
@ HDF5
HDF5 format (magic: 0x89 'H' 'D' 'F' 0x0d 0x0a 0x1a 0x0a)
Definition PNeXus.h:143
@ Unknown
Unrecognized file format.
Definition PNeXus.h:144
@ HDF4
HDF4 format (magic: 0x0e 0x03 0x13 0x01)
Definition PNeXus.h:142
HDFType checkHDFType(const std::string &filename)
Determine the HDF format type of a file by reading its header.
Definition PNeXus.cpp:100