musrfit 1.10.0
PRunDataHandler.cpp
Go to the documentation of this file.
1/***************************************************************************
2
3 PRunDataHandler.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 <sys/types.h>
35#include <sys/stat.h>
36#include <unistd.h>
37#include <cstdio>
38#include <ctime>
39#include <iostream>
40#include <iomanip>
41#include <fstream>
42#include <string>
43#include <sstream>
44#include <memory>
45#include <vector>
46
47#include <TROOT.h>
48#include <TSystem.h>
49#include <TString.h>
50#include <TObjArray.h>
51#include <TObjString.h>
52#include <TFile.h>
53#include <TFolder.h>
54#include <TH1F.h>
55#include <TDatime.h>
56#include <TDirectoryFile.h>
57
58#include "TMusrRunHeader.h"
59#include "TLemRunHeader.h"
60#include "MuSR_td_PSI_bin.h"
61#include "mud.h"
62#include "PStringUtils.h"
63
64#ifdef PNEXUS_ENABLED
65#include "PNeXus.h"
66#endif
67
68#include "PRunDataHandler.h"
69
70#define PRH_MUSR_ROOT 0
71#define PRH_MUSR_ROOT_DIR 1
72#define PRH_LEM_ROOT 2
73
74#define PRH_NPP_OFFSET 0
75#define PRH_PPC_OFFSET 20
76
77#define PHR_INIT_ALL 0
78#define PHR_INIT_MSR 1
79#define PHR_INIT_ANY2MANY 2
80
81//--------------------------------------------------------------------------
82// Constructor
83//--------------------------------------------------------------------------
91
92//--------------------------------------------------------------------------
93// Constructor
94//--------------------------------------------------------------------------
101PRunDataHandler::PRunDataHandler(TString fileName, const TString fileFormat) : fFileFormat(fileFormat)
102{
103 Init();
104
105 FileExistsCheck(fileName);
106}
107
108//--------------------------------------------------------------------------
109// Constructor
110//--------------------------------------------------------------------------
118PRunDataHandler::PRunDataHandler(TString fileName, const TString fileFormat, const PStringVector dataPath) : fDataPath(dataPath), fFileFormat(fileFormat)
119{
120 Init();
121
122 FileExistsCheck(fileName);
123}
124
125//--------------------------------------------------------------------------
126// Constructor
127//--------------------------------------------------------------------------
136PRunDataHandler::PRunDataHandler(TString fileName, const TString fileFormat, const TString dataPath, PRawRunData &runData)
137{
138 Init();
139}
140
141//--------------------------------------------------------------------------
142// Constructor
143//--------------------------------------------------------------------------
153
154//--------------------------------------------------------------------------
155// Constructor
156//--------------------------------------------------------------------------
164 fAny2ManyInfo(any2ManyInfo), fDataPath(dataPath)
165{
167}
168
169//--------------------------------------------------------------------------
170// Constructor
171//--------------------------------------------------------------------------
181
182//--------------------------------------------------------------------------
183// Constructor
184//--------------------------------------------------------------------------
193 fMsrInfo(msrInfo), fDataPath(dataPath)
194{
196}
197
198//--------------------------------------------------------------------------
199// Destructor
200//--------------------------------------------------------------------------
205{
206 fDataPath.clear();
207 fData.clear();
208}
209
210//--------------------------------------------------------------------------
211// GetRunData
212//--------------------------------------------------------------------------
224{
225 UInt_t i;
226
227 for (i=0; i<fData.size(); i++) {
228 if (!fData[i].GetRunName()->CompareTo(runName)) // run found
229 break;
230 }
231
232 if (i == fData.size())
233 return nullptr;
234 else
235 return &fData[i];
236}
237
238//--------------------------------------------------------------------------
239// GetRunData
240//--------------------------------------------------------------------------
251{
252 if (idx >= fData.size())
253 return nullptr;
254 else
255 return &fData[idx];
256}
257
258//--------------------------------------------------------------------------
259// ReadData
260//--------------------------------------------------------------------------
266{
267 if (fMsrInfo) { // i.e. msr-file triggered
268 if (!ReadFilesMsr()) // couldn't read file
269 fAllDataAvailable = false;
270 else
271 fAllDataAvailable = true;
272 } else if (!fRunPathName.IsWhitespace()) { // i.e. file name triggered
273 if (fFileFormat == "") { // try to guess the file format if fromat hasn't been provided
274 TString ext=fRunPathName;
275 Ssiz_t pos=ext.Last('.');
276 ext.Remove(0, pos+1);
277 if (!ext.CompareTo("bin", TString::kIgnoreCase))
278 fFileFormat = "psibin";
279 else if (!ext.CompareTo("root", TString::kIgnoreCase))
280 fFileFormat = "musrroot";
281 else if (!ext.CompareTo("msr", TString::kIgnoreCase))
282 fFileFormat = "mud";
283 else if (!ext.CompareTo("nxs", TString::kIgnoreCase))
284 fFileFormat = "nexus";
285 else if (!ext.CompareTo("mdu", TString::kIgnoreCase))
286 fFileFormat = "psimdu";
287 }
288 if ((fFileFormat == "MusrRoot") || (fFileFormat == "musrroot")) {
290 } else if ((fFileFormat == "NeXus") || (fFileFormat == "nexus")) {
292 } else if ((fFileFormat == "PsiBin") || (fFileFormat == "psibin") ||
293 (fFileFormat == "PsiMdu") || (fFileFormat == "psimdu")) {
295 } else if ((fFileFormat == "Mud") || (fFileFormat == "mud")) {
297 } else if ((fFileFormat == "Wkm") || (fFileFormat == "wkm")) {
299 } else {
300 std::cerr << std::endl << ">> PRunDataHandler::ReadData(): **ERROR** unkown file format \"" << fFileFormat << "\" found." << std::endl;
301 fAllDataAvailable = false;
302 }
303 } else {
304 std::cerr << std::endl << ">> PRunDataHandler::ReadData(): **ERROR** Couldn't read files." << std::endl;
305 fAllDataAvailable = false;
306 }
307}
308
309//--------------------------------------------------------------------------
310// ConvertData
311//--------------------------------------------------------------------------
316{
317 if (!ReadWriteFilesList()) // couldn't read file
318 fAllDataAvailable = false;
319 else
320 fAllDataAvailable = true;
321}
322
323//--------------------------------------------------------------------------
324// SetRunData
325//--------------------------------------------------------------------------
335{
336 if ((idx == 0) && (fData.size() == 0)) {
337 fData.resize(1);
338 }
339 if (idx >= fData.size()) {
340 std::cerr << std::endl << ">>PRunDataHandler::SetRunData(): **ERROR** idx=" << idx << " is out-of-range (0.." << fData.size() << ")." << std::endl;
341 return false;
342 }
343
344 fData[idx] = *data;
345
346 return true;
347}
348
349//--------------------------------------------------------------------------
350// WriteData
351//--------------------------------------------------------------------------
355Bool_t PRunDataHandler::WriteData(TString fileName)
356{
357 if ((fAny2ManyInfo == nullptr) && (fileName="")) {
358 std::cerr << std::endl << ">> PRunDataHandler::WriteData(): **ERROR** insufficient information: no fileName nor fAny2ManyInfo object.";
359 std::cerr << std::endl << " Cannot write data under this conditions." << std::endl;
360 return false;
361 }
362
363 // get output file format tag, first try via fAny2ManyInfo
364 Int_t outTag = A2M_UNDEFINED;
365 if (fAny2ManyInfo != nullptr) {
366 if (!fAny2ManyInfo->outFormat.CompareTo("musrroot", TString::kIgnoreCase))
367 outTag = A2M_MUSR_ROOT;
368 else if (!fAny2ManyInfo->outFormat.CompareTo("musrrootdir", TString::kIgnoreCase))
369 outTag = A2M_MUSR_ROOT_DIR;
370 else if (!fAny2ManyInfo->outFormat.CompareTo("psibin", TString::kIgnoreCase))
371 outTag = A2M_PSIBIN;
372 else if (!fAny2ManyInfo->outFormat.CompareTo("psimdu", TString::kIgnoreCase))
373 outTag = A2M_PSIMDU;
374 else if (!fAny2ManyInfo->outFormat.CompareTo("mud",TString::kIgnoreCase))
375 outTag = A2M_MUD;
376 else if (fAny2ManyInfo->outFormat.BeginsWith("nexus", TString::kIgnoreCase))
377 outTag = A2M_NEXUS;
378 else
379 outTag = A2M_UNDEFINED;
380 } else { // only fileName is given, try to guess from the extension
381 // STILL MISSING
382 }
383
384 if (outTag == A2M_UNDEFINED) {
385 std::cerr << std::endl << ">> PRunDataHandler::WriteData(): **ERROR** no valid output data file format found: '" << fAny2ManyInfo->outFormat.Data() << "'" << std::endl;
386 return false;
387 }
388
389 Bool_t success{true};
390 switch (outTag) {
391 case A2M_MUSR_ROOT:
393 if (fAny2ManyInfo->outFileName.Length() == 0)
394 success = WriteMusrRootFile(outTag, fileName);
395 else
396 success = WriteMusrRootFile(outTag, fAny2ManyInfo->outFileName);
397 break;
398 case A2M_PSIBIN:
399 case A2M_PSIMDU:
400 if (fAny2ManyInfo->outFileName.Length() == 0)
401 success = WritePsiBinFile(fileName);
402 else
403 success = WritePsiBinFile(fAny2ManyInfo->outFileName);
404 break;
405 case A2M_MUD:
406 if (fAny2ManyInfo->outFileName.Length() == 0)
407 success = WriteMudFile(fileName);
408 else
409 success = WriteMudFile(fAny2ManyInfo->outFileName);
410 break;
411 case A2M_NEXUS:
412 if (fAny2ManyInfo->outFileName.Length() == 0)
413 success = WriteNexusFile(fAny2ManyInfo->outFormat, fileName);
414 else
415 success = WriteNexusFile(fAny2ManyInfo->outFormat, fAny2ManyInfo->outFileName);
416 break;
417 default:
418 break;
419 }
420
421 return success;
422}
423
424//--------------------------------------------------------------------------
425// Init (private)
426//--------------------------------------------------------------------------
430void PRunDataHandler::Init(const Int_t tag)
431{
432 if ((tag==PHR_INIT_ALL) || (tag==PHR_INIT_ANY2MANY))
433 fMsrInfo = nullptr;
434 if ((tag==PHR_INIT_ALL) || (tag==PHR_INIT_MSR))
435 fAny2ManyInfo = nullptr;
436 fAllDataAvailable = false;
437 if (tag!=PHR_INIT_ALL)
438 fFileFormat = TString("");
439 fRunName = TString("");
440 fRunPathName = TString("");
441}
442
443//--------------------------------------------------------------------------
444// ReadFilesMsr (private)
445//--------------------------------------------------------------------------
455{
456 Bool_t success = true;
457
458 // loop over the full RUN list to see what needs to be read
459 PMsrRunList *runList = nullptr;
460 runList = fMsrInfo->GetMsrRunList();
461 if (runList == nullptr) {
462 std::cerr << std::endl << ">> PRunDataHandler::ReadFilesMsr(): **ERROR** Couldn't obtain run list from PMsrHandler: something VERY fishy";
463 std::cerr << std::endl;
464 return false;
465 }
466
467 char str[1024], *p_str=nullptr;
468 UInt_t year=0;
469 TString musrRoot("musr-root");
470
471 for (UInt_t i=0; i<runList->size(); i++) {
472 for (UInt_t j=0; j<runList->at(i).GetRunNameSize(); j++) {
473 fRunName = *(runList->at(i).GetRunName(j));
474 // check if file actually exists
475 if (!FileExistsCheck(runList->at(i), j))
476 return false;
477
478 // get year from string if LEM data file
479 strcpy(str, fRunName.Data());
480 p_str = strstr(str, "lem");
481 if (p_str != nullptr)
482 sscanf(p_str, "lem%d_his", &year);
483
484 // check special case for ROOT-NPP/ROOT-PPC (LEM)
485 if (!runList->at(i).GetFileFormat(j)->CompareTo("root-npp")) { // not post pile up corrected histos
486 // if LEM file header is already TMusrRoot, change the data-file-format
487 if (year >= 12)
488 runList->at(i).SetFileFormat(musrRoot, j);
489 // check if forward/backward histoNo are within proper bounds, i.e. < PRH_PPC_OFFSET
490 for (UInt_t k=0; k<runList->at(i).GetForwardHistoNoSize(); k++) {
491 if (runList->at(i).GetForwardHistoNo(k) > PRH_PPC_OFFSET)
492 runList->at(i).SetForwardHistoNo(runList->at(i).GetForwardHistoNo(k)-PRH_PPC_OFFSET, k);
493 }
494 for (UInt_t k=0; k<runList->at(i).GetBackwardHistoNoSize(); k++) {
495 if (runList->at(i).GetBackwardHistoNo(k) > PRH_PPC_OFFSET)
496 runList->at(i).SetBackwardHistoNo(runList->at(i).GetBackwardHistoNo(k)-PRH_PPC_OFFSET, k);
497 }
498 } else if (!runList->at(i).GetFileFormat(j)->CompareTo("root-ppc")) { // post pile up corrected histos
499 // if LEM file header is already TMusrRoot, change the data-file-format
500 if (year >= 12)
501 runList->at(i).SetFileFormat(musrRoot, j);
502 // check if forward/backward histoNo are within proper bounds, i.e. > PRH_PPC_OFFSET
503 for (UInt_t k=0; k<runList->at(i).GetForwardHistoNoSize(); k++) {
504 if (runList->at(i).GetForwardHistoNo(k) < PRH_PPC_OFFSET)
505 runList->at(i).SetForwardHistoNo(runList->at(i).GetForwardHistoNo(k)+PRH_PPC_OFFSET, k);
506 }
507 for (UInt_t k=0; k<runList->at(i).GetBackwardHistoNoSize(); k++) {
508 if (runList->at(i).GetBackwardHistoNo(k) < PRH_PPC_OFFSET)
509 runList->at(i).SetBackwardHistoNo(runList->at(i).GetBackwardHistoNo(k)+PRH_PPC_OFFSET, k);
510 }
511 }
512
513 // check is file is already read
514 if (FileAlreadyRead(*(runList->at(i).GetRunName(j))))
515 continue;
516 // everything looks fine, hence try to read the data file
517 if (!runList->at(i).GetFileFormat(j)->CompareTo("root-npp")) { // not post pile up corrected histos
518 success = ReadRootFile();
519 } else if (!runList->at(i).GetFileFormat(j)->CompareTo("root-ppc")) { // post pile up corrected histos
520 success = ReadRootFile();
521 } else if (!runList->at(i).GetFileFormat(j)->CompareTo("musr-root")) { // MusrRoot style file
522 success = ReadRootFile();
523 } else if (!runList->at(i).GetFileFormat(j)->CompareTo("nexus")) {
524 success = ReadNexusFile();
525 } else if (!runList->at(i).GetFileFormat(j)->CompareTo("psi-bin")) {
526 success = ReadPsiBinFile();
527 } else if (!runList->at(i).GetFileFormat(j)->CompareTo("psi-mdu")) {
528 success = ReadPsiBinFile();
529 } else if (!runList->at(i).GetFileFormat(j)->CompareTo("mud")) {
530 success = ReadMudFile();
531 } else if (!runList->at(i).GetFileFormat(j)->CompareTo("wkm")) {
532 success = ReadWkmFile();
533 } else if (!runList->at(i).GetFileFormat(j)->CompareTo("mdu-ascii")) {
534 success = ReadMduAsciiFile();
535 } else if (!runList->at(i).GetFileFormat(j)->CompareTo("ascii")) {
536 success = ReadAsciiFile();
537 } else if (!runList->at(i).GetFileFormat(j)->CompareTo("db")) {
538 success = ReadDBFile();
539 } else if (!runList->at(i).GetFileFormat(j)->CompareTo("dat")) {
540 success = ReadDatFile();
541 } else {
542 success = false;
543 }
544 }
545 }
546
547 return success;
548}
549
550//--------------------------------------------------------------------------
551// ReadWriteFilesList (private)
552//--------------------------------------------------------------------------
564{
565 if ((fAny2ManyInfo->inFileName.size() == 0) && (fAny2ManyInfo->runList.size() == 0)) {
566 std::cerr << std::endl << ">> PRunDataHandler::ReadWriteFilesList(): **ERROR** Couldn't obtain run list from fAny2ManyInfo: something VERY fishy";
567 std::cerr << std::endl;
568 return false;
569 }
570
571 // get input file format tag
572 Int_t inTag = A2M_UNDEFINED;
573 if (!fAny2ManyInfo->inFormat.CompareTo("root", TString::kIgnoreCase))
574 inTag = A2M_ROOT;
575 else if (!fAny2ManyInfo->inFormat.CompareTo("musrroot", TString::kIgnoreCase))
576 inTag = A2M_MUSR_ROOT;
577 else if (!fAny2ManyInfo->inFormat.CompareTo("psi-bin", TString::kIgnoreCase))
578 inTag = A2M_PSIBIN;
579 else if (!fAny2ManyInfo->inFormat.CompareTo("psi-mdu", TString::kIgnoreCase))
580 inTag = A2M_PSIMDU;
581 else if (!fAny2ManyInfo->inFormat.CompareTo("mud", TString::kIgnoreCase))
582 inTag = A2M_MUD;
583 else if (!fAny2ManyInfo->inFormat.CompareTo("nexus", TString::kIgnoreCase))
584 inTag = A2M_NEXUS;
585 else if (!fAny2ManyInfo->inFormat.CompareTo("wkm", TString::kIgnoreCase))
586 inTag = A2M_WKM;
587 else
588 inTag = A2M_UNDEFINED;
589
590 if (inTag == A2M_UNDEFINED) {
591 std::cerr << std::endl << ">> PRunDataHandler::ReadWriteFilesList(): **ERROR** no valid input data file format found: '" << fAny2ManyInfo->inFormat.Data() << "'" << std::endl;
592 return false;
593 }
594
595 // get output file format tag
596 Int_t outTag = A2M_UNDEFINED;
597 if (!fAny2ManyInfo->outFormat.CompareTo("root", TString::kIgnoreCase))
598 outTag = A2M_ROOT;
599 else if (!fAny2ManyInfo->outFormat.CompareTo("musrroot", TString::kIgnoreCase))
600 outTag = A2M_MUSR_ROOT;
601 else if (!fAny2ManyInfo->outFormat.CompareTo("musrrootdir", TString::kIgnoreCase))
602 outTag = A2M_MUSR_ROOT_DIR;
603 else if (!fAny2ManyInfo->outFormat.CompareTo("psi-bin", TString::kIgnoreCase))
604 outTag = A2M_PSIBIN;
605 else if (!fAny2ManyInfo->outFormat.CompareTo("mud",TString::kIgnoreCase))
606 outTag = A2M_MUD;
607 else if (fAny2ManyInfo->outFormat.BeginsWith("nexus", TString::kIgnoreCase))
608 outTag = A2M_NEXUS;
609 else if (!fAny2ManyInfo->outFormat.CompareTo("wkm", TString::kIgnoreCase))
610 outTag = A2M_WKM;
611 else if (!fAny2ManyInfo->outFormat.CompareTo("ascii", TString::kIgnoreCase))
612 outTag = A2M_ASCII;
613 else
614 outTag = A2M_UNDEFINED;
615
616 if (outTag == A2M_UNDEFINED) {
617 std::cerr << std::endl << ">> PRunDataHandler::ReadWriteFilesList(): **ERROR** no valid output data file format found: '" << fAny2ManyInfo->outFormat.Data() << "'" << std::endl;
618 return false;
619 }
620
621 if (fAny2ManyInfo->inFileName.size() != 0) { // file name list given
622
623 // loop over all runs of the run list
624 for (UInt_t i=0; i<fAny2ManyInfo->inFileName.size(); i++) {
625 if (!FileExistsCheck(true, i)) {
626 std::cerr << std::endl << ">> PRunDataHandler::ReadWriteFilesList(): **ERROR** Couldn't find file " << fAny2ManyInfo->inFileName[i].Data() << std::endl;
627 return false;
628 }
629
630 // read input file
631 Bool_t success = false;
632 switch (inTag) {
633 case A2M_ROOT:
634 case A2M_MUSR_ROOT:
635 success = ReadRootFile();
636 break;
637 case A2M_PSIBIN:
638 case A2M_PSIMDU:
639 success = ReadPsiBinFile();
640 break;
641 case A2M_NEXUS:
642 success = ReadNexusFile();
643 break;
644 case A2M_MUD:
645 success = ReadMudFile();
646 break;
647 case A2M_WKM:
648 success = ReadWkmFile();
649 break;
650 default:
651 break;
652 }
653
654 if (!success) {
655 std::cerr << std::endl << ">> PRunDataHandler::ReadWriteFilesList(): **ERROR** Couldn't read file " << fAny2ManyInfo->inFileName[i].Data() << std::endl;
656 return false;
657 }
658
659 // write 'converted' output data file
660 success = false;
661 switch (outTag) {
662 case A2M_ROOT:
663 if (fAny2ManyInfo->outFileName.Length() == 0)
664 success = WriteRootFile();
665 else
666 success = WriteRootFile(fAny2ManyInfo->outFileName);
667 break;
668 case A2M_MUSR_ROOT:
670 if (fAny2ManyInfo->outFileName.Length() == 0)
671 success = WriteMusrRootFile(outTag);
672 else
673 success = WriteMusrRootFile(outTag, fAny2ManyInfo->outFileName);
674 break;
675 case A2M_PSIBIN:
676 if (fAny2ManyInfo->outFileName.Length() == 0)
677 success = WritePsiBinFile();
678 else
679 success = WritePsiBinFile(fAny2ManyInfo->outFileName);
680 break;
681 case A2M_PSIMDU:
682 if (fAny2ManyInfo->outFileName.Length() == 0)
683 success = WritePsiBinFile();
684 else
685 success = WritePsiBinFile(fAny2ManyInfo->outFileName);
686 break;
687 case A2M_NEXUS:
688 if (fAny2ManyInfo->outFileName.Length() == 0)
689 success = WriteNexusFile(fAny2ManyInfo->outFormat);
690 else
691 success = WriteNexusFile(fAny2ManyInfo->outFormat, fAny2ManyInfo->outFileName);
692 break;
693 case A2M_MUD:
694 if (fAny2ManyInfo->outFileName.Length() == 0)
695 success = WriteMudFile();
696 else
697 success = WriteMudFile(fAny2ManyInfo->outFileName);
698 break;
699 case A2M_WKM:
700 if (fAny2ManyInfo->outFileName.Length() == 0)
701 success = WriteWkmFile();
702 else
703 success = WriteWkmFile(fAny2ManyInfo->outFileName);
704 break;
705 case A2M_ASCII:
706 if (fAny2ManyInfo->outFileName.Length() == 0)
707 success = WriteAsciiFile();
708 else
709 success = WriteAsciiFile(fAny2ManyInfo->outFileName);
710 break;
711 default:
712 break;
713 }
714
715 if (success == false) {
716 std::cerr << std::endl << ">> PRunDataHandler::ReadWriteFilesList(): **ERROR** Couldn't write converted output file." << std::endl;
717 return false;
718 }
719
720 // throw away the current data set
721 fData.clear();
722 }
723 }
724
725 if (fAny2ManyInfo->runList.size() != 0) { // run list given
726
727 // loop over all runs of the run list
728 for (UInt_t i=0; i<fAny2ManyInfo->runList.size(); i++) {
729 if (!FileExistsCheck(false, i)) {
730 std::cerr << std::endl << ">> PRunDataHandler::ReadWriteFilesList(): **ERROR** Couldn't find run " << fAny2ManyInfo->runList[i] << std::endl;
731 return false;
732 }
733
734 // read input file
735 Bool_t success = false;
736 switch (inTag) {
737 case A2M_ROOT:
738 case A2M_MUSR_ROOT:
739 success = ReadRootFile();
740 break;
741 case A2M_PSIBIN:
742 case A2M_PSIMDU:
743 success = ReadPsiBinFile();
744 break;
745 case A2M_NEXUS:
746 success = ReadNexusFile();
747 break;
748 case A2M_MUD:
749 success = ReadMudFile();
750 break;
751 case A2M_WKM:
752 success = ReadWkmFile();
753 break;
754 default:
755 break;
756 }
757
758 if (!success) {
759 std::cerr << std::endl << ">> PRunDataHandler::ReadWriteFilesList(): **ERROR** Couldn't read file " << fRunPathName.Data() << std::endl;
760 return false;
761 }
762
763 TString year("");
764 TDatime dt;
765 year += dt.GetYear();
766 if (fAny2ManyInfo->year.Length() > 0)
767 year = fAny2ManyInfo->year;
768 Bool_t ok;
769 TString fln = FileNameFromTemplate(fAny2ManyInfo->outTemplate, fAny2ManyInfo->runList[i], year, ok);
770 if (!ok) {
771 std::cerr << std::endl << ">> PRunDataHandler::ReadWriteFilesList(): **ERROR** Couldn't create necessary output file name." << std::endl;
772 return false;
773 }
774
775 // write 'converted' output data file
776 success = false;
777 switch (outTag) {
778 case A2M_ROOT:
779 success = WriteRootFile(fln);
780 break;
781 case A2M_MUSR_ROOT:
783 success = WriteMusrRootFile(outTag, fln);
784 break;
785 case A2M_PSIBIN:
786 success = WritePsiBinFile(fln);
787 break;
788 case A2M_PSIMDU:
789 success = WritePsiBinFile(fln);
790 break;
791 case A2M_NEXUS:
792 success = WriteNexusFile(fAny2ManyInfo->outFormat, fln);
793 break;
794 case A2M_MUD:
795 success = WriteMudFile(fln);
796 break;
797 case A2M_WKM:
798 success = WriteWkmFile(fln);
799 break;
800 case A2M_ASCII:
801 success = WriteAsciiFile(fln);
802 break;
803 default:
804 break;
805 }
806
807 if (success == false) {
808 std::cerr << std::endl << ">> PRunDataHandler::ReadWriteFilesList(): **ERROR** Couldn't write converted output file." << std::endl;
809 return false;
810 }
811
812 // throw away the current data set
813 fData.clear();
814 }
815
816 }
817
818 // check if compression is wished
819 if (fAny2ManyInfo->compressionTag > 0) {
820 TString fln = fAny2ManyInfo->outPath + fAny2ManyInfo->compressFileName;
821
822 // currently system call is used, which means this is only running under Linux and Mac OS X but not under Windows
823 char cmd[256];
824 if (fAny2ManyInfo->outPathFileName.size() == 1) {
825 if (fAny2ManyInfo->compressionTag == 1) // gzip
826 fln += TString(".tar.gz");
827 else // bzip2
828 fln += TString(".tar.bz2");
829 if (fAny2ManyInfo->compressionTag == 1) // gzip
830 snprintf(cmd, sizeof(cmd), "tar -zcf %s %s", fln.Data(), fAny2ManyInfo->outPathFileName[0].Data());
831 else // bzip2
832 snprintf(cmd, sizeof(cmd), "tar -jcf %s %s", fln.Data(), fAny2ManyInfo->outPathFileName[0].Data());
833 if (system(cmd) == -1) {
834 std::cerr << "**ERROR** cmd: " << cmd << " failed." << std::endl;
835 }
836 } else {
837 fln += TString(".tar");
838 for (UInt_t i=0; i<fAny2ManyInfo->outPathFileName.size(); i++) {
839 if (i==0) {
840 snprintf(cmd, sizeof(cmd), "tar -cf %s %s", fln.Data(), fAny2ManyInfo->outPathFileName[i].Data());
841 } else {
842 snprintf(cmd, sizeof(cmd), "tar -rf %s %s", fln.Data(), fAny2ManyInfo->outPathFileName[i].Data());
843 }
844 if (system(cmd) == -1) {
845 std::cerr << "**ERROR** cmd: " << cmd << " failed." << std::endl;
846 }
847 }
848 if (fAny2ManyInfo->compressionTag == 1) { // gzip
849 snprintf(cmd, sizeof(cmd), "gzip %s", fln.Data());
850 fln += ".gz";
851 } else {
852 snprintf(cmd, sizeof(cmd), "bzip2 -z %s", fln.Data());
853 fln += ".bz2";
854 }
855 if (system(cmd) == -1) {
856 std::cerr << "**ERROR** cmd: " << cmd << " failed." << std::endl;
857 }
858 }
859
860 // check if the compressed file shall be streamed to the stdout
861 if (fAny2ManyInfo->useStandardOutput) {
862 // stream file to stdout
863 std::ifstream is;
864 int length=1024;
865 char *buffer;
866
867 is.open(fln.Data(), std::ios::binary);
868 if (!is.is_open()) {
869 std::cerr << std::endl << "PRunDataHandler::ReadWriteFilesList(): **ERROR** Couldn't open the file for streaming." << std::endl;
870 remove(fln.Data());
871 return false;
872 }
873
874 // get length of file
875 is.seekg(0, std::ios::end);
876 length = is.tellg();
877 is.seekg(0, std::ios::beg);
878
879 if (length == -1) {
880 std::cerr << std::endl << "PRunDataHandler::ReadWriteFilesList(): **ERROR** Couldn't determine the file size." << std::endl;
881 remove(fln.Data());
882 return false;
883 }
884
885 // allocate memory
886 buffer = new char [length];
887
888 // read data as a block
889 while (!is.eof()) {
890 is.read(buffer, length);
891 std::cout.write(buffer, length);
892 }
893
894 is.close();
895
896 delete [] buffer;
897
898 // delete temporary root file
899 remove(fln.Data());
900 }
901
902 // remove all the converted files
903 for (UInt_t i=0; i<fAny2ManyInfo->outPathFileName.size(); i++)
904 remove(fAny2ManyInfo->outPathFileName[i].Data());
905 }
906
907 return true;
908}
909
910//--------------------------------------------------------------------------
911// FileAlreadyRead (private)
912//--------------------------------------------------------------------------
923Bool_t PRunDataHandler::FileAlreadyRead(TString runName)
924{
925 for (UInt_t i=0; i<fData.size(); i++) {
926 if (!fData[i].GetRunName()->CompareTo(runName)) { // run alread read
927 return true;
928 }
929 }
930
931 return false;
932}
933
934//--------------------------------------------------------------------------
935// TestFileName (private)
936//--------------------------------------------------------------------------
944void PRunDataHandler::TestFileName(TString &runName, const TString &ext)
945{
946 TString tmpStr(runName), tmpExt(ext);
947
948 // check first if the file exists with the default extension which is not given with the run name
949 tmpStr += TString(".") + ext;
950 if (gSystem->AccessPathName(tmpStr.Data()) != true) { // found
951 runName = tmpStr;
952 return;
953 }
954
955 // test if the file exists with the given run name but an only upper-case extension which is not included in the file name
956 tmpStr = runName;
957 tmpExt.ToUpper();
958 tmpStr += TString(".") + tmpExt;
959 if (gSystem->AccessPathName(tmpStr.Data()) != true) { // found
960 runName = tmpStr;
961 return;
962 }
963
964 // test if the file exists with the given run name but an only lower-case extension which is not included in the file name
965 tmpStr = runName;
966 tmpExt.ToLower();
967 tmpStr += TString(".") + tmpExt;
968 if (gSystem->AccessPathName(tmpStr.Data()) != true) { // found
969 runName = tmpStr;
970 return;
971 }
972
973 // test if the file exists with only upper-case letters
974 tmpStr = runName + TString(".") + tmpExt;
975 tmpStr.ToUpper();
976 if (gSystem->AccessPathName(tmpStr.Data()) != true) { // found
977 runName = tmpStr;
978 return;
979 }
980
981 // test if the file exists with only lower-case letters
982 tmpStr.ToLower();
983 if (gSystem->AccessPathName(tmpStr.Data()) != true) { // found
984 runName = tmpStr;
985 return;
986 }
987
988 tmpStr = runName;
989
990 // the extension is already part of the file name, therefore, do not append it
991 if (tmpStr.EndsWith(ext.Data(), TString::kIgnoreCase)) {
992 if (gSystem->AccessPathName(tmpStr.Data()) != true) { // found
993 runName = tmpStr;
994 return;
995 }
996
997 // assume some extension is part of the given file name but the real data file ends with an lower-case extension
998 tmpExt.ToLower();
999 tmpStr = tmpStr.Replace(static_cast<Ssiz_t>(tmpStr.Length()-tmpExt.Length()), tmpExt.Length(), tmpExt);
1000 if (gSystem->AccessPathName(tmpStr.Data()) != true) { // found
1001 runName = tmpStr;
1002 return;
1003 }
1004
1005 // assume some extension is part of the given file name but the real data file ends with an upper-case extension
1006 tmpExt.ToUpper();
1007 tmpStr = runName;
1008 tmpStr = tmpStr.Replace(static_cast<Ssiz_t>(tmpStr.Length()-tmpExt.Length()), tmpExt.Length(), tmpExt);
1009 if (gSystem->AccessPathName(tmpStr.Data()) != true) { // found
1010 runName = tmpStr;
1011 return;
1012 }
1013
1014 // test if the file exists with only lower-case letters and the extension already included in the file name
1015 tmpStr = runName;
1016 tmpStr.ToLower();
1017 if (gSystem->AccessPathName(tmpStr.Data()) != true) { // found
1018 runName = tmpStr;
1019 return;
1020 }
1021
1022 // test if the file exists with only upper-case letters and the extension already included in the file name
1023 tmpStr = runName;
1024 tmpStr.ToUpper();
1025 if (gSystem->AccessPathName(tmpStr.Data()) != true) { // found
1026 runName = tmpStr;
1027 return;
1028 }
1029 }
1030
1031 // if the file has not been found, set the run name to be empty
1032 runName = "";
1033
1034 return;
1035}
1036
1037//--------------------------------------------------------------------------
1038// FileExistsCheck (private)
1039//--------------------------------------------------------------------------
1050Bool_t PRunDataHandler::FileExistsCheck(PMsrRunBlock &runInfo, const UInt_t idx)
1051{
1052 Bool_t success = true;
1053
1054 // local init
1055 TROOT root("PRunBase", "PRunBase", nullptr);
1056 TString pathName = "???";
1057 TString str, *pstr;
1058 TString ext;
1059
1060 pstr = runInfo.GetBeamline(idx);
1061 if (pstr == nullptr) {
1062 std::cerr << std::endl << ">> PRunDataHandler::FileExistsCheck: **ERROR** Couldn't obtain beamline data." << std::endl;
1063 assert(0);
1064 }
1065 pstr->ToLower();
1066 runInfo.SetBeamline(*pstr, idx);
1067 pstr = runInfo.GetInstitute(idx);
1068 if (pstr == nullptr) {
1069 std::cerr << std::endl << ">> PRunDataHandler::FileExistsCheck: **ERROR** Couldn't obtain institute data." << std::endl;
1070 assert(0);
1071 }
1072 pstr->ToLower();
1073 runInfo.SetInstitute(*pstr, idx);
1074 pstr = runInfo.GetFileFormat(idx);
1075 if (pstr == nullptr) {
1076 std::cerr << std::endl << ">> PRunDataHandler::FileExistsCheck: **ERROR** Couldn't obtain file format data." << std::endl;
1077 assert(0);
1078 }
1079 pstr->ToLower();
1080 runInfo.SetFileFormat(*pstr, idx);
1081
1082 // file extensions for the various formats
1083 if (!runInfo.GetFileFormat(idx)->CompareTo("root-npp")) // not post pile up corrected histos
1084 ext = TString("root");
1085 else if (!runInfo.GetFileFormat(idx)->CompareTo("root-ppc")) // post pile up corrected histos
1086 ext = TString("root");
1087 else if (!runInfo.GetFileFormat(idx)->CompareTo("musr-root")) // post pile up corrected histos
1088 ext = TString("root");
1089 else if (!runInfo.GetFileFormat(idx)->CompareTo("nexus"))
1090 ext = TString("NXS");
1091 else if (!runInfo.GetFileFormat(idx)->CompareTo("psi-bin"))
1092 ext = TString("bin");
1093 else if (!runInfo.GetFileFormat(idx)->CompareTo("psi-mdu"))
1094 ext = TString("mdu");
1095 else if (!runInfo.GetFileFormat(idx)->CompareTo("mud"))
1096 ext = TString("msr");
1097 else if (!runInfo.GetFileFormat(idx)->CompareTo("wkm")) {
1098 if (!runInfo.GetBeamline(idx)->CompareTo("mue4"))
1099 ext = TString("nemu");
1100 else
1101 ext = *runInfo.GetBeamline(idx);
1102 }
1103 else if (!runInfo.GetFileFormat(idx)->CompareTo("mdu-ascii"))
1104 ext = TString("mdua");
1105 else if (!runInfo.GetFileFormat(idx)->CompareTo("ascii"))
1106 ext = TString("dat");
1107 else if (!runInfo.GetFileFormat(idx)->CompareTo("db"))
1108 ext = TString("db");
1109 else if (!runInfo.GetFileFormat(idx)->CompareTo("dat"))
1110 ext = TString("dat");
1111 else
1112 success = false;
1113
1114 // unkown file format found
1115 if (!success) {
1116 pstr = runInfo.GetFileFormat(idx);
1117 if (pstr == nullptr) {
1118 std::cerr << std::endl << ">> PRunDataHandler::FileExistsCheck: **ERROR** Couldn't obtain file format data." << std::endl;
1119 assert(0);
1120 }
1121 pstr->ToUpper();
1122 std::cerr << std::endl << ">> PRunDataHandler::FileExistsCheck: **ERROR** File Format '" << pstr->Data() << "' unsupported.";
1123 std::cerr << std::endl << ">> support file formats are:";
1124 std::cerr << std::endl << ">> ROOT-NPP -> root not post pileup corrected for lem";
1125 std::cerr << std::endl << ">> ROOT-PPC -> root post pileup corrected for lem";
1126 std::cerr << std::endl << ">> MUSR-ROOT -> MusrRoot file format";
1127 std::cerr << std::endl << ">> NEXUS -> nexus file format, HDF4, HDF5, or XML";
1128 std::cerr << std::endl << ">> PSI-BIN -> psi bin file format";
1129 std::cerr << std::endl << ">> PSI-MDU -> psi mdu file format (see also MDU-ASCII)";
1130 std::cerr << std::endl << ">> MUD -> triumf mud file format";
1131 std::cerr << std::endl << ">> WKM -> wkm ascii file format";
1132 std::cerr << std::endl << ">> MDU-ASCII -> psi mdu ascii file format";
1133 std::cerr << std::endl << ">> ASCII -> column like file format";
1134 std::cerr << std::endl << ">> DB -> triumf db file \"format\"";
1135 std::cerr << std::endl << ">> DAT -> csv like file \"format\" as exported by msr2data.";
1136 std::cerr << std::endl;
1137 return success;
1138 }
1139
1140 // check if the file is in the local directory
1141 str = *runInfo.GetRunName(idx);
1142 TestFileName(str, ext);
1143 if (!str.IsNull()) {
1144 pathName = str;
1145 }
1146
1147 // check if the file is found in the <msr-file-directory>
1148 if (pathName.CompareTo("???") == 0) { // not found in local directory search
1149 str = *fMsrInfo->GetMsrFileDirectoryPath() + *runInfo.GetRunName(idx);
1150 TestFileName(str, ext);
1151 if (!str.IsNull()) {
1152 pathName = str;
1153 }
1154 }
1155
1156 // check if the file is found in the directory given in the startup file
1157 if (pathName.CompareTo("???") == 0) { // not found in local directory search and not found in the <msr-file-directory> search
1158 for (UInt_t i=0; i<fDataPath.size(); i++) {
1159 str = fDataPath[i] + TString("/") + *runInfo.GetRunName(idx);
1160 TestFileName(str, ext);
1161 if (!str.IsNull()) {
1162 pathName = str;
1163 break;
1164 }
1165 }
1166 }
1167
1168 // check if the file is found in the directories given by MUSRFULLDATAPATH
1169 const Char_t *musrpath = gSystem->Getenv("MUSRFULLDATAPATH");
1170 if (pathName.CompareTo("???") == 0) { // not found in local directory and xml path
1171 str = TString(musrpath);
1172 // MUSRFULLDATAPATH has the structure: path_1:path_2:...:path_n
1173 std::vector<std::string> tokens = PStringUtils::Split(str.Data(), ":");
1174 for (UInt_t i=0; i<tokens.size(); i++) {
1175 str = TString(tokens[i]) + TString("/") + *runInfo.GetRunName(idx);
1176 TestFileName(str, ext);
1177 if (!str.IsNull()) {
1178 pathName = str;
1179 break;
1180 }
1181 }
1182 }
1183
1184 // check if the file is found in the generated default path
1185 if (pathName.CompareTo("???") == 0) { // not found in MUSRFULLDATAPATH search
1186 str = TString(musrpath);
1187 // MUSRFULLDATAPATH has the structure: path_1:path_2:...:path_n
1188 std::vector<std::string> tokens = PStringUtils::Split(str.Data(), ":");
1189 pstr = runInfo.GetInstitute(idx);
1190 if (pstr == nullptr) {
1191 std::cerr << std::endl << ">> PRunDataHandler::FileExistsCheck: **ERROR** Couldn't obtain institute data." << std::endl;
1192 assert(0);
1193 }
1194 pstr->ToUpper();
1195 runInfo.SetInstitute(*pstr, idx);
1196 pstr = runInfo.GetBeamline(idx);
1197 if (pstr == nullptr) {
1198 std::cerr << std::endl << ">> PRunDataHandler::FileExistsCheck: **ERROR** Couldn't obtain beamline data." << std::endl;
1199 assert(0);
1200 }
1201 pstr->ToUpper();
1202 runInfo.SetBeamline(*pstr, idx);
1203 for (UInt_t i=0; i<tokens.size(); i++) {
1204 str = TString(tokens[i]) + TString("/DATA/") +
1205 *runInfo.GetInstitute(idx) + TString("/") +
1206 *runInfo.GetBeamline(idx) + TString("/") +
1207 *runInfo.GetRunName(idx);
1208 TestFileName(str, ext);
1209 if (!str.IsNull()) { // found
1210 pathName = str;
1211 break;
1212 }
1213 }
1214 }
1215
1216 // no proper path name found
1217 if (pathName.CompareTo("???") == 0) {
1218 std::cerr << std::endl << ">> PRunDataHandler::FileExistsCheck(): **ERROR** Couldn't find '" << runInfo.GetRunName(idx)->Data() << "' in any standard path.";
1219 std::cerr << std::endl << ">> standard search pathes are:";
1220 std::cerr << std::endl << ">> 1. the local directory";
1221 std::cerr << std::endl << ">> 2. the data directory given in the startup XML file";
1222 std::cerr << std::endl << ">> 3. the directories listed in MUSRFULLDATAPATH";
1223 std::cerr << std::endl << ">> 4. default path construct which is described in the manual";
1224 return false;
1225 }
1226
1227 fRunPathName = pathName;
1228
1229 return true;
1230}
1231
1232//--------------------------------------------------------------------------
1233// FileExistsCheck (private)
1234//--------------------------------------------------------------------------
1245Bool_t PRunDataHandler::FileExistsCheck(const Bool_t fileName, const Int_t idx)
1246{
1247 TString pathName("???");
1248 TString str("");
1249 TString fln("");
1250
1251 if (fileName) { // single input file name
1252 if (idx >= static_cast<Int_t>(fAny2ManyInfo->inFileName.size())) {
1253 std::cerr << std::endl << ">> PRunDataHandler::FileExistsCheck(): **ERROR** idx=" << idx << " out of range. (inFileName.size()==" << fAny2ManyInfo->inFileName.size() << ")" << std::endl;
1254 return false;
1255 }
1256 fln = fAny2ManyInfo->inFileName[idx];
1257 } else { // run file list entry shall be handled
1258 if (idx >= static_cast<Int_t>(fAny2ManyInfo->runList.size())) {
1259 std::cerr << std::endl << ">> PRunDataHandler::FileExistsCheck(): **ERROR** idx=" << idx << " out of range. (inFileName.size()==" << fAny2ManyInfo->runList.size() << ")" << std::endl;
1260 return false;
1261 }
1262 // check for input/output templates
1263 if ((fAny2ManyInfo->inTemplate.Length() == 0) || (fAny2ManyInfo->outTemplate.Length() == 0)) {
1264 std::cerr << std::endl << ">> PRunDataHandler::FileExistsCheck(): **ERROR** when using run lists, input/output templates are needed as well." << std::endl;
1265 return false;
1266 }
1267 // make the input file name according to the input template
1268 TString year("");
1269 TDatime dt;
1270 year += dt.GetYear();
1271 if (fAny2ManyInfo->year.Length() > 0)
1272 year = fAny2ManyInfo->year;
1273 Bool_t ok;
1274 fln = FileNameFromTemplate(fAny2ManyInfo->inTemplate, fAny2ManyInfo->runList[idx], year, ok);
1275 if (!ok)
1276 return false;
1277 }
1278
1279 // check if the file is in the local directory
1280 if (gSystem->AccessPathName(fln) != true) { // found in the local dir
1281 pathName = fln;
1282 }
1283 // check if the file is found in the directory given in the startup file
1284 if (pathName.CompareTo("???") == 0) { // not found in local directory search
1285 for (UInt_t i=0; i<fDataPath.size(); i++) {
1286 str = fDataPath[i] + TString("/") + fln;
1287 if (gSystem->AccessPathName(str.Data())!=true) { // found
1288 pathName = str;
1289 break;
1290 }
1291 }
1292 }
1293 // check if the file is found in the directories given by MUSRFULLDATAPATH
1294 const Char_t *musrpath = gSystem->Getenv("MUSRFULLDATAPATH");
1295 if (pathName.CompareTo("???") == 0) { // not found in local directory and xml path
1296 str = TString(musrpath);
1297 // MUSRFULLDATAPATH has the structure: path_1:path_2:...:path_n
1298 std::vector<std::string> tokens = PStringUtils::Split(str.Data(), ":");
1299 for (UInt_t i=0; i<tokens.size(); i++) {
1300 str = TString(tokens[i]) + TString("/") + fln;
1301 if (gSystem->AccessPathName(str.Data())!=true) { // found
1302 pathName = str;
1303 break;
1304 }
1305 }
1306 }
1307 // no proper path name found
1308 if (pathName.CompareTo("???") == 0) {
1309 std::cerr << std::endl << ">> PRunDataHandler::FileExistsCheck(): **ERROR** Couldn't find '" << fln.Data() << "' in any standard path.";
1310 std::cerr << std::endl << ">> standard search pathes are:";
1311 std::cerr << std::endl << ">> 1. the local directory";
1312 std::cerr << std::endl << ">> 2. the data directory given in the startup XML file";
1313 std::cerr << std::endl << ">> 3. the directories listed in MUSRFULLDATAPATH";
1314 return false;
1315 }
1316
1317 fRunPathName = pathName;
1318
1319 return true;
1320}
1321
1322//--------------------------------------------------------------------------
1323// FileExistsCheck (private)
1324//--------------------------------------------------------------------------
1334Bool_t PRunDataHandler::FileExistsCheck(const TString fileName)
1335{
1336 TString pathName("???");
1337 TString str("");
1338
1339 // check if the file is in the local directory
1340 if (gSystem->AccessPathName(fileName) != true) { // found in the local dir
1341 pathName = fileName;
1342 }
1343 // check if the file is found in the directory given in the startup file
1344 if (pathName.CompareTo("???") == 0) { // not found in local directory search
1345 for (UInt_t i=0; i<fDataPath.size(); i++) {
1346 str = fDataPath[i] + TString("/") + fileName;
1347 if (gSystem->AccessPathName(str.Data())!=true) { // found
1348 pathName = str;
1349 break;
1350 }
1351 }
1352 }
1353 // check if the file is found in the directories given by MUSRFULLDATAPATH
1354 const Char_t *musrpath = gSystem->Getenv("MUSRFULLDATAPATH");
1355 if (pathName.CompareTo("???") == 0) { // not found in local directory and xml path
1356 str = TString(musrpath);
1357 // MUSRFULLDATAPATH has the structure: path_1:path_2:...:path_n
1358 std::vector<std::string> tokens = PStringUtils::Split(str.Data(), ":");
1359 for (UInt_t i=0; i<tokens.size(); i++) {
1360 str = TString(tokens[i]) + TString("/") + fileName;
1361 if (gSystem->AccessPathName(str.Data())!=true) { // found
1362 pathName = str;
1363 break;
1364 }
1365 }
1366 }
1367 // no proper path name found
1368 if (pathName.CompareTo("???") == 0) {
1369 std::cerr << std::endl << ">> PRunDataHandler::FileExistsCheck(): **ERROR** Couldn't find '" << fileName.Data() << "' in any standard path.";
1370 std::cerr << std::endl << ">> standard search pathes are:";
1371 std::cerr << std::endl << ">> 1. the local directory";
1372 std::cerr << std::endl << ">> 2. the data directory given in the startup XML file";
1373 std::cerr << std::endl << ">> 3. the directories listed in MUSRFULLDATAPATH";
1374 return false;
1375 }
1376
1377 fRunPathName = pathName;
1378
1379 return true;
1380}
1381
1382//--------------------------------------------------------------------------
1383// ReadRootFile (private)
1384//--------------------------------------------------------------------------
1394{
1395 PDoubleVector histoData;
1396 PRawRunData runData;
1397 PRawRunDataSet dataSet;
1398
1399 TFile f(fRunPathName.Data());
1400 if (f.IsZombie()) {
1401 return false;
1402 }
1403
1404 UInt_t fileType = PRH_MUSR_ROOT;
1405
1406 TFolder *folder;
1407 f.GetObject("RunInfo", folder); // try first LEM-ROOT style file (used until 2011).
1408 if (!folder) { // either something is wrong, or it is a MusrRoot file
1409 TObject *obj = f.FindObjectAny("RunHeader");
1410 if (obj == nullptr) { // something is wrong!!
1411 std::cerr << std::endl << ">> PRunDataHandler::ReadRootFile: **ERROR** Couldn't neither obtain RunInfo (LEM),";
1412 std::cerr << std::endl << " nor RunHeader (MusrRoot) from " << fRunPathName.Data() << std::endl;
1413 f.Close();
1414 return false;
1415 }
1416 if (!strcmp(obj->ClassName(), "TFolder"))
1417 fileType = PRH_MUSR_ROOT;
1418 else if (!strcmp(obj->ClassName(), "TDirectoryFile"))
1419 fileType = PRH_MUSR_ROOT_DIR;
1420 else {
1421 std::cerr << std::endl << "PRunDataHandler::ReadRootFile: **ERROR** RunHeader (MusrRoot) from '" << fRunPathName.Data() << "' is neither a TFolder nor a TDirectory. Found: '" << obj->ClassName() << "'" << std::endl;
1422 f.Close();
1423 return false;
1424 }
1425 } else {
1426 fileType = PRH_LEM_ROOT;
1427 }
1428
1429 if (fileType == PRH_LEM_ROOT) {
1430 // read header and check if some missing run info need to be fed
1431 TLemRunHeader *runHeader = dynamic_cast<TLemRunHeader*>(folder->FindObjectAny("TLemRunHeader"));
1432
1433 // check if run header is valid
1434 if (!runHeader) {
1435 std::cerr << std::endl << ">> PRunDataHandler::ReadRootFile: **ERROR** Couldn't obtain run header info from ROOT file " << fRunPathName.Data() << std::endl;
1436 f.Close();
1437 return false;
1438 }
1439
1440 // set laboratory / beamline / instrument
1441 runData.SetLaboratory("PSI");
1442 runData.SetBeamline("muE4");
1443 runData.SetInstrument("LEM");
1444 runData.SetMuonSource("low energy muon source");
1445 runData.SetMuonSpecies("positive muons");
1446
1447 // get run title
1448 TObjString ostr = runHeader->GetRunTitle();
1449 runData.SetRunTitle(ostr.GetString());
1450
1451 // get run number
1452 runData.SetRunNumber(static_cast<Int_t>(runHeader->GetRunNumber()));
1453
1454 // get temperature
1455 runData.ClearTemperature();
1456 runData.SetTemperature(0, runHeader->GetSampleTemperature(), runHeader->GetSampleTemperatureError());
1457
1458 // get field
1459 runData.SetField(runHeader->GetSampleBField());
1460
1461 // get implantation energy
1462 runData.SetEnergy(runHeader->GetImpEnergy());
1463
1464 // get moderator HV
1465 runData.SetTransport(runHeader->GetModeratorHV());
1466
1467 // get setup
1468 runData.SetSetup(runHeader->GetLemSetup().GetString());
1469
1470 // get start time/date
1471 // start date
1472 time_t idt = static_cast<time_t>(runHeader->GetStartTime());
1473 runData.SetStartDateTime(idt);
1474 struct tm *dt = localtime(&idt);
1475 char str[128];
1476 strftime(str, sizeof(str), "%F", dt);
1477 TString stime(str);
1478 runData.SetStartDate(stime);
1479 // start time
1480 memset(str, 0, sizeof(str));
1481 strftime(str, sizeof(str), "%T", dt);
1482 stime = str;
1483 runData.SetStartTime(stime);
1484
1485 // get stop time/date
1486 // stop date
1487 idt = static_cast<time_t>(runHeader->GetStopTime());
1488 runData.SetStopDateTime(idt);
1489 dt = localtime(&idt);
1490 memset(str, 0, sizeof(str));
1491 strftime(str, sizeof(str), "%F", dt);
1492 stime = str;
1493 runData.SetStopDate(stime);
1494 // stop time
1495 memset(str, 0, sizeof(str));
1496 strftime(str, sizeof(str), "%T", dt);
1497 stime = str;
1498 runData.SetStopTime(stime);
1499
1500 // get time resolution
1501 runData.SetTimeResolution(runHeader->GetTimeResolution());
1502
1503 // get number of histogramms
1504 Int_t noOfHistos = runHeader->GetNHist();
1505
1506 // get t0's there will be handled together with the data
1507 Double_t *t0 = runHeader->GetTimeZero();
1508
1509 // read run summary to obtain ring anode HV values
1510 TObjArray *runSummary = dynamic_cast<TObjArray*>(folder->FindObjectAny("RunSummary"));
1511
1512 // check if run summary is valid
1513 if (!runSummary) {
1514 std::cout << std::endl << "**INFO** Couldn't obtain run summary info from ROOT file " << fRunPathName.Data() << std::endl;
1515 // this is not fatal... only RA-HV values are not available
1516 } else { // it follows a (at least) little bit strange extraction of the RA values from Thomas' TObjArray...
1517 //streaming of a ASCII-file would be more easy
1518 TString s;
1519 TObjArrayIter summIter(runSummary);
1520 TObjString *os(dynamic_cast<TObjString*>(summIter.Next()));
1521 while (os != nullptr) {
1522 s = os->GetString();
1523 // a summary line has the structure 'RA-L = val RA-R = val ...', i.e. the value
1524 // follows two tokens after the tag. More than one RA-value may be on one line.
1525 std::vector<std::string> oa = PStringUtils::Split(s.Data(), " ");
1526 for (UInt_t k=0; k+2 < oa.size(); k++) {
1527 if (oa[k+1] != "=")
1528 continue;
1529 if (oa[k] == "RA-L")
1530 runData.SetRingAnode(0, TString(oa[k+2]).Atof());
1531 else if (oa[k] == "RA-R")
1532 runData.SetRingAnode(1, TString(oa[k+2]).Atof());
1533 else if (oa[k] == "RA-T")
1534 runData.SetRingAnode(2, TString(oa[k+2]).Atof());
1535 else if (oa[k] == "RA-B")
1536 runData.SetRingAnode(3, TString(oa[k+2]).Atof());
1537 }
1538
1539 os = dynamic_cast<TObjString*>(summIter.Next()); // next summary line...
1540 }
1541 }
1542
1543 // read data ---------------------------------------------------------
1544
1545 // check if histos folder is found
1546 f.GetObject("histos", folder);
1547 if (!folder) {
1548 std::cerr << std::endl << ">> PRunDataHandler::ReadRootFile: **ERROR** Couldn't obtain histos from " << fRunPathName.Data() << std::endl;
1549 f.Close();
1550 return false;
1551 }
1552
1553 // get all the data
1554 Char_t histoName[32];
1555 for (Int_t i=0; i<noOfHistos; i++) {
1556 snprintf(histoName, sizeof(histoName), "hDecay%02d", i);
1557 TH1F *histo = dynamic_cast<TH1F*>(folder->FindObjectAny(histoName));
1558 if (!histo) {
1559 std::cerr << std::endl << ">> PRunDataHandler::ReadRootFile: **ERROR** Couldn't get histo " << histoName;
1560 std::cerr << std::endl;
1561 f.Close();
1562 return false;
1563 }
1564
1565 // fill data
1566 for (Int_t j=1; j<=histo->GetNbinsX(); j++) {
1567 histoData.push_back(histo->GetBinContent(j));
1568 }
1569
1570 // fill the data set
1571 dataSet.Clear();
1572 dataSet.SetName(histo->GetTitle());
1573 dataSet.SetHistoNo(i+1);
1574 dataSet.SetTimeZeroBin(t0[i]);
1575 dataSet.SetTimeZeroBinEstimated(histo->GetMaximumBin());
1576 dataSet.SetFirstGoodBin(static_cast<Int_t>(t0[i]));
1577 dataSet.SetLastGoodBin(histo->GetNbinsX()-1);
1578 dataSet.SetData(histoData);
1579 runData.SetDataSet(dataSet);
1580
1581 // clear histoData for the next histo
1582 histoData.clear();
1583 }
1584 // check if any post pileup histos are present at all (this is not the case for LEM data 2006 and earlier)
1585 snprintf(histoName, sizeof(histoName), "hDecay%02d", POST_PILEUP_HISTO_OFFSET);
1586 if (!folder->FindObjectAny(histoName)) {
1587 std::cerr << std::endl << ">> PRunDataHandler::ReadRootFile: **WARNING** Couldn't get histo " << histoName;
1588 std::cerr << std::endl << ">> most probably this is an old (2006 or earlier) LEM file without post pileup histos.";
1589 std::cerr << std::endl;
1590 } else {
1591 for (Int_t i=0; i<noOfHistos; i++) {
1592 snprintf(histoName, sizeof(histoName), "hDecay%02d", i+POST_PILEUP_HISTO_OFFSET);
1593 TH1F *histo = dynamic_cast<TH1F*>(folder->FindObjectAny(histoName));
1594 if (!histo) {
1595 std::cerr << std::endl << ">> PRunDataHandler::ReadRootFile: **ERROR** Couldn't get histo " << histoName;
1596 std::cerr << std::endl;
1597 f.Close();
1598 return false;
1599 }
1600
1601 // fill data
1602 for (Int_t j=1; j<=histo->GetNbinsX(); j++)
1603 histoData.push_back(histo->GetBinContent(j));
1604
1605 // fill the data set
1606 dataSet.Clear();
1607 dataSet.SetName(histo->GetTitle());
1609 dataSet.SetTimeZeroBin(t0[i]);
1610 dataSet.SetTimeZeroBinEstimated(histo->GetMaximumBin());
1611 dataSet.SetFirstGoodBin(static_cast<Int_t>(t0[i]));
1612 dataSet.SetLastGoodBin(histo->GetNbinsX()-1);
1613 dataSet.SetData(histoData);
1614 runData.SetDataSet(dataSet);
1615
1616 // clear histoData for the next histo
1617 histoData.clear();
1618 }
1619 }
1620 } else { // MusrRoot file
1621 // invoke the MusrRoot header object
1622 std::unique_ptr<TMusrRunHeader> header = std::make_unique<TMusrRunHeader>(true); // read quiet
1623 if (header == nullptr) {
1624 std::cerr << std::endl << ">> PRunDataHandler::ReadRootFile: **ERROR** Couldn't invoke MusrRoot RunHeader in file:" << fRunPathName;
1625 std::cerr << std::endl;
1626 f.Close();
1627 return false;
1628 }
1629
1630 // check if TFolder or TDirectory is needed
1631 if (fileType == PRH_MUSR_ROOT) { // TFolder
1632 f.GetObject("RunHeader", folder);
1633
1634 // try to populate the MusrRoot header object
1635 if (!header->ExtractAll(folder)) {
1636 std::cerr << std::endl << ">> PRunDataHandler::ReadRootFile: **ERROR** Couldn't invoke MusrRoot RunHeader (TFolder) in file:" << fRunPathName;
1637 std::cerr << std::endl;
1638 f.Close();
1639 return false;
1640 }
1641 } else { // TDirectory
1642 TDirectoryFile *runHeader = nullptr;
1643 f.GetObject("RunHeader", runHeader);
1644
1645 // try to populate the MusrRoot header object
1646 if (!header->ExtractAll(runHeader)) {
1647 std::cerr << std::endl << ">> PRunDataHandler::ReadRootFile: **ERROR** Couldn't invoke MusrRoot RunHeader (TDirectoryFile) in file:" << fRunPathName;
1648 std::cerr << std::endl;
1649 f.Close();
1650 return false;
1651 }
1652 }
1653
1654 // get all the header information
1655 Bool_t ok;
1656 TString str, path, pathName;
1657 Int_t ival, noOfHistos=0;
1658 Double_t dval;
1660 PIntVector ivec, redGreenOffsets;
1661
1662 header->Get("RunInfo/Version", str, ok);
1663 if (ok)
1664 runData.SetVersion(str);
1665
1666 header->Get("RunInfo/Generic Validator URL", str, ok);
1667 if (ok)
1668 runData.SetGenericValidatorUrl(str);
1669
1670 header->Get("RunInfo/Specific Validator URL", str, ok);
1671 if (ok)
1672 runData.SetSpecificValidatorUrl(str);
1673
1674 header->Get("RunInfo/Generator", str, ok);
1675 if (ok)
1676 runData.SetGenerator(str);
1677
1678 header->Get("RunInfo/File Name", str, ok);
1679 if (ok)
1680 runData.SetFileName(str);
1681
1682 header->Get("RunInfo/Run Title", str, ok);
1683 if (ok)
1684 runData.SetRunTitle(str);
1685
1686 header->Get("RunInfo/Run Number", ival, ok);
1687 if (ok)
1688 runData.SetRunNumber(ival);
1689
1690 header->Get("RunInfo/Run Start Time", str, ok);
1691 if (ok) {
1692 Ssiz_t pos = str.Index(' ');
1693 TString substr = str;
1694 substr.Remove(pos, str.Length());
1695 runData.SetStartDate(substr);
1696 substr = str;
1697 substr.Remove(0, pos+1);
1698 runData.SetStartTime(substr);
1699 }
1700
1701 header->Get("RunInfo/Run Stop Time", str, ok);
1702 if (ok) {
1703 Ssiz_t pos = str.Index(' ');
1704 TString substr = str;
1705 substr.Remove(pos, str.Length());
1706 runData.SetStopDate(substr);
1707 substr = str;
1708 substr.Remove(0, pos+1);
1709 runData.SetStopTime(substr);
1710 }
1711
1712 header->Get("RunInfo/Laboratory", str, ok);
1713 if (ok)
1714 runData.SetLaboratory(str);
1715
1716 header->Get("RunInfo/Instrument", str, ok);
1717 if (ok)
1718 runData.SetInstrument(str);
1719
1720 header->Get("RunInfo/Muon Beam Momentum", prop, ok);
1721 if (ok) {
1722 if (!prop.GetUnit().CompareTo("MeV/c"))
1723 runData.SetMuonBeamMomentum(prop.GetValue());
1724 }
1725
1726 header->Get("RunInfo/Muon Species", str, ok);
1727 if (ok)
1728 runData.SetMuonSpecies(str);
1729
1730 header->Get("RunInfo/Muon Source", str, ok);
1731 if (ok)
1732 runData.SetMuonSource(str);
1733
1734 header->Get("RunInfo/Muon Spin Angle", prop, ok);
1735 if (ok) {
1736 runData.SetMuonSpinAngle(prop.GetValue());
1737 }
1738
1739 header->Get("RunInfo/Setup", str, ok);
1740 if (ok)
1741 runData.SetSetup(str);
1742
1743 header->Get("RunInfo/Comment", str, ok);
1744 if (ok)
1745 runData.SetComment(str);
1746
1747 header->Get("RunInfo/Sample Name", str, ok);
1748 if (ok)
1749 runData.SetSample(str);
1750
1751 header->Get("RunInfo/Sample Temperature", prop, ok);
1752 if (ok)
1753 runData.SetTemperature(0, prop.GetValue(), prop.GetError());
1754
1755 header->Get("RunInfo/Sample Magnetic Field", prop, ok);
1756 if (ok) {
1757 dval = MRH_UNDEFINED;
1758 if (!prop.GetUnit().CompareTo("G") || !prop.GetUnit().CompareTo("Gauss"))
1759 dval = prop.GetValue();
1760 else if (!prop.GetUnit().CompareTo("T") || !prop.GetUnit().CompareTo("Tesla"))
1761 dval = prop.GetValue() * 1.0e4;
1762 runData.SetField(dval);
1763 }
1764
1765 header->Get("RunInfo/No of Histos", ival, ok);
1766 if (ok) {
1767 noOfHistos = ival;
1768 }
1769
1770 header->Get("RunInfo/Time Resolution", prop, ok);
1771 if (ok) {
1772 dval = -1.0;
1773 if (!prop.GetUnit().CompareTo("ps") || !prop.GetUnit().CompareTo("picosec"))
1774 dval = prop.GetValue()/1.0e3;
1775 else if (!prop.GetUnit().CompareTo("ns") || !prop.GetUnit().CompareTo("nanosec"))
1776 dval = prop.GetValue();
1777 else if (!prop.GetUnit().CompareTo("us") || !prop.GetUnit().CompareTo("microsec"))
1778 dval = prop.GetValue()*1.0e3;
1779 else
1780 std::cerr << std::endl << ">> PRunDataHandler::ReadRootFile: **ERROR** Found unrecognized Time Resolution unit: " << prop.GetUnit() << std::endl;
1781 runData.SetTimeResolution(dval);
1782 }
1783
1784 header->Get("RunInfo/RedGreen Offsets", ivec, ok);
1785 if (ok) {
1786 // check if any2many is used and a group histo list is defined, if NOT, only take the 0-offset data!
1787 if (fAny2ManyInfo) { // i.e. any2many is called
1788 if (fAny2ManyInfo->groupHistoList.size() == 0) { // NO group list defined -> use only the 0-offset data
1789 redGreenOffsets.push_back(0);
1790 } else { // group list defined
1791 // make sure that the group list elements is a subset of present RedGreen offsets
1792 Bool_t found = false;
1793 for (UInt_t i=0; i<fAny2ManyInfo->groupHistoList.size(); i++) {
1794 found = false;
1795 for (UInt_t j=0; j<ivec.size(); j++) {
1796 if (fAny2ManyInfo->groupHistoList[i] == ivec[j])
1797 found = true;
1798 }
1799 if (!found) {
1800 std::cerr << std::endl << ">> PRunDataHandler::ReadRootFile: **ERROR** requested histo group " << fAny2ManyInfo->groupHistoList[i];
1801 std::cerr << std::endl << ">> which is NOT present in the data file." << std::endl;
1802 return false;
1803 }
1804 }
1805 // found all requested histo groups, hence stuff it to the right places
1806 redGreenOffsets = fAny2ManyInfo->groupHistoList;
1807 runData.SetRedGreenOffset(fAny2ManyInfo->groupHistoList);
1808 }
1809 } else { // not any2many, i.e. musrfit, musrview, ...
1810 redGreenOffsets = ivec;
1811 runData.SetRedGreenOffset(ivec);
1812 }
1813 }
1814
1815 header->Get("RunInfo/Sample Orientation", str, ok);
1816 if (ok)
1817 runData.SetOrientation(str);
1818
1819 // check further for LEM specific stuff in RunInfo
1820
1821 header->Get("RunInfo/Moderator HV", prop, ok);
1822 if (ok)
1823 runData.SetTransport(prop.GetValue());
1824
1825 header->Get("RunInfo/Implantation Energy", prop, ok);
1826 if (ok)
1827 runData.SetEnergy(prop.GetValue());
1828
1829 // read the SampleEnvironmentInfo
1830
1831 header->Get("SampleEnvironmentInfo/Cryo", str, ok);
1832 if (ok)
1833 runData.SetCryoName(str);
1834
1835 // read the MagneticFieldEnvironmentInfo
1836
1837 header->Get("MagneticFieldEnvironmentInfo/Magnet Name", str, ok);
1838 if (ok)
1839 runData.SetMagnetName(str);
1840
1841 // read the BeamlineInfo
1842
1843 header->Get("BeamlineInfo/Name", str, ok);
1844 if (ok)
1845 runData.SetBeamline(str);
1846
1847 // read run summary to obtain ring anode HV values
1848 TObjArray *runSummary = nullptr;
1849 if (fileType == PRH_MUSR_ROOT) // TFolder
1850 runSummary = dynamic_cast<TObjArray*>(folder->FindObjectAny("RunSummary"));
1851 else { // TDirectory
1852 f.GetObject("RunHeader/RunSummary", runSummary);
1853 }
1854
1855 // check if run summary is valid
1856 if (!runSummary) {
1857 std::cout << std::endl << "**INFO** Couldn't obtain run summary info from ROOT file " << fRunPathName.Data() << std::endl;
1858 // this is not fatal... only RA-HV values are not available
1859 } else { // it follows a (at least) little bit strange extraction of the RA values from Thomas' TObjArray...
1860 //streaming of a ASCII-file would be more easy
1861 TString s;
1862 TObjArrayIter summIter(runSummary);
1863 TObjString *os(dynamic_cast<TObjString*>(summIter.Next()));
1864 while (os != nullptr) {
1865 s = os->GetString();
1866 // a summary line has the structure 'RA-L = val RA-R = val ...', i.e. the value
1867 // follows two tokens after the tag. More than one RA-value may be on one line.
1868 std::vector<std::string> oa = PStringUtils::Split(s.Data(), " ");
1869 for (UInt_t k=0; k+2 < oa.size(); k++) {
1870 if (oa[k+1] != "=")
1871 continue;
1872 if (oa[k] == "RA-L")
1873 runData.SetRingAnode(0, TString(oa[k+2]).Atof());
1874 else if (oa[k] == "RA-R")
1875 runData.SetRingAnode(1, TString(oa[k+2]).Atof());
1876 else if (oa[k] == "RA-T")
1877 runData.SetRingAnode(2, TString(oa[k+2]).Atof());
1878 else if (oa[k] == "RA-B")
1879 runData.SetRingAnode(3, TString(oa[k+2]).Atof());
1880 }
1881
1882 os = dynamic_cast<TObjString*>(summIter.Next()); // next summary line...
1883 }
1884 }
1885
1886 // read data ---------------------------------------------------------
1887
1888 if (fileType == PRH_MUSR_ROOT) { // TFolder
1889 // check if histos folder is found
1890 f.GetObject("histos", folder);
1891 if (!folder) {
1892 std::cerr << std::endl << ">> PRunDataHandler::ReadRootFile: **ERROR** Couldn't obtain histos from " << fRunPathName.Data() << std::endl;
1893 f.Close();
1894 return false;
1895 }
1896
1897 // get all the data
1898 for (UInt_t i=0; i<redGreenOffsets.size(); i++) {
1899 for (Int_t j=0; j<noOfHistos; j++) {
1900 str.Form("hDecay%03d", redGreenOffsets[i]+j+1);
1901 TH1F *histo = dynamic_cast<TH1F*>(folder->FindObjectAny(str.Data()));
1902 if (!histo) {
1903 std::cerr << std::endl << ">> PRunDataHandler::ReadRootFile: **ERROR** Couldn't get histo " << str;
1904 std::cerr << std::endl;
1905 f.Close();
1906 return false;
1907 }
1908
1909 dataSet.Clear();
1910 dataSet.SetTitle(histo->GetTitle());
1911 dataSet.SetHistoNo(redGreenOffsets[i]+j+1);
1912
1913 // get detector info
1914 path.Form("DetectorInfo/Detector%03d/", redGreenOffsets[i]+j+1);
1915 pathName = path + "Name";
1916 header->Get(pathName, str, ok);
1917 if (ok)
1918 dataSet.SetName(str);
1919 pathName = path + "Time Zero Bin";
1920 header->Get(pathName, dval, ok);
1921 if (ok)
1922 dataSet.SetTimeZeroBin(dval);
1923 pathName = path + "First Good Bin";
1924 header->Get(pathName, ival, ok);
1925 if (ok)
1926 dataSet.SetFirstGoodBin(ival);
1927 pathName = path + "Last Good Bin";
1928 header->Get(pathName, ival, ok);
1929 if (ok)
1930 dataSet.SetLastGoodBin(ival);
1931 dataSet.SetTimeZeroBinEstimated(histo->GetMaximumBin());
1932
1933 // fill data
1934 for (Int_t j=1; j<=histo->GetNbinsX(); j++) {
1935 histoData.push_back(histo->GetBinContent(j));
1936 }
1937 dataSet.SetData(histoData);
1938 runData.SetDataSet(dataSet);
1939
1940 // clear histoData for the next histo
1941 histoData.clear();
1942 }
1943 }
1944 } else { // TDirectory
1945 // get all the data
1946 TH1F *histo;
1947 for (UInt_t i=0; i<redGreenOffsets.size(); i++) {
1948 for (Int_t j=0; j<noOfHistos; j++) {
1949 str.Form("histos/DecayAnaModule/hDecay%03d", redGreenOffsets[i]+j+1);
1950 f.GetObject(str, histo);
1951 if (!histo) {
1952 std::cerr << std::endl << ">> PRunDataHandler::ReadRootFile: **ERROR** Couldn't get histo " << str;
1953 std::cerr << std::endl;
1954 f.Close();
1955 return false;
1956 }
1957
1958 dataSet.Clear();
1959 dataSet.SetTitle(histo->GetTitle());
1960 dataSet.SetHistoNo(redGreenOffsets[i]+j+1);
1961
1962 // get detector info
1963 path.Form("DetectorInfo/Detector%03d/", redGreenOffsets[i]+j+1);
1964 pathName = path + "Name";
1965 header->Get(pathName, str, ok);
1966 if (ok)
1967 dataSet.SetName(str);
1968 pathName = path + "Time Zero Bin";
1969 header->Get(pathName, dval, ok);
1970 if (ok)
1971 dataSet.SetTimeZeroBin(dval);
1972 pathName = path + "First Good Bin";
1973 header->Get(pathName, ival, ok);
1974 if (ok)
1975 dataSet.SetFirstGoodBin(ival);
1976 pathName = path + "Last Good Bin";
1977 header->Get(pathName, ival, ok);
1978 if (ok)
1979 dataSet.SetLastGoodBin(ival);
1980 dataSet.SetTimeZeroBinEstimated(histo->GetMaximumBin());
1981
1982 // fill data
1983 for (Int_t j=1; j<=histo->GetNbinsX(); j++) {
1984 histoData.push_back(histo->GetBinContent(j));
1985 }
1986 dataSet.SetData(histoData);
1987 runData.SetDataSet(dataSet);
1988
1989 // clear histoData for the next histo
1990 histoData.clear();
1991 }
1992 }
1993 }
1994 }
1995
1996 f.Close();
1997
1998 // keep run name
1999 runData.SetRunName(fRunName);
2000
2001 // add run to the run list
2002 fData.push_back(runData);
2003
2004 return true;
2005}
2006
2007//--------------------------------------------------------------------------
2008// ReadNexusFile (private)
2009//--------------------------------------------------------------------------
2018{
2019#ifdef PNEXUS_ENABLED
2020 std::cout << std::endl << ">> PRunDataHandler::ReadNexusFile(): Will read nexus file " << fRunPathName.Data() << " ...";
2021
2023
2024 // check for type errors, missing enabled HDF4
2025 switch (type) {
2026 case nxs::HDFType::HDF4:
2027 std::cout << std::endl << ">> PRunDataHandler::ReadNexusFile(): HDF4 file." << std::endl;
2028#ifndef HAVE_HDF4
2029 std::cerr << std::endl << ">> PRunDataHandler::ReadNexusFile(): **ERROR**, HDF4 is not enabled." << std::endl;
2030 return false;
2031#endif
2032 break;
2033 case nxs::HDFType::HDF5:
2034 std::cout << std::endl << ">> PRunDataHandler::ReadNexusFile(): HDF5 file." << std::endl;
2035 break;
2037 std::cerr << std::endl << ">> PRunDataHandler::ReadNexusFile(): Not a valid NeXus file." << std::endl;
2038 return false;
2039 }
2040
2041 PDoubleVector histoData;
2042 PRawRunData runData;
2043 PRawRunDataSet dataSet;
2044 TString str;
2045 std::string sstr;
2046 Int_t ival, idf{-1};
2047 Double_t dval, factor;
2048 bool ok;
2049
2050 if (type == nxs::HDFType::HDF4) {
2051#ifdef HAVE_HDF4
2052 std::unique_ptr<nxH4::PNeXus> nxs_file = std::make_unique<nxH4::PNeXus>(fRunPathName.Data());
2053 if (nxs_file == nullptr) {
2054 std::cerr << std::endl << "**ERROR** allocation of nxH4::PNeXus object failed." << std::endl;
2055 return true;
2056 }
2057
2058 // check for IDF_version
2059 if (nxs_file->HasDataset("/run/IDF_version")) {
2060 idf = nxs_file->GetDataset<int>("/run/IDF_version").GetData()[0];
2061 std::cout << ">> PRunDataHandler::ReadNexusFile(): IDF V" << idf << std::endl;
2062 }
2063 if (idf == -1) { // IDF_version not found
2064 if (nxs_file->HasDataset("/raw_data_1/IDF_version")) {
2065 idf = nxs_file->GetDataset<int>("/raw_data_1/IDF_version").GetData()[0];
2066 std::cout << ">> PRunDataHandler::ReadNexusFile(): IDF V" << idf << std::endl;
2067 }
2068 }
2069 if ((idf != 1) && (idf != 2)) {
2070 std::cerr << std::endl << ">> PRunDataHandler::ReadNexusFile(): a NeXus file with an invalid IDF V" << idf << std::endl;
2071 return false;
2072 }
2073
2074 if (idf == 1) { // HDF4 IDF V1
2075 if (!ReadNexusFileIdf1(nxs_file))
2076 return false;
2077 } else { // HDF4 IDF V2
2078 // not yet implemented
2079 }
2080#endif
2081 } else { // HDF5
2082 std::unique_ptr<nxH5::PNeXus> nxs_file = std::make_unique<nxH5::PNeXus>(fRunPathName.Data());
2083 if (nxs_file == nullptr) {
2084 std::cerr << std::endl << "**ERROR** allocation of nxH5::PNeXus object failed." << std::endl;
2085 return true;
2086 }
2087
2088 // check for IDF_version
2089 if (nxs_file->HasDataset("/run/IDF_version")) {
2090 idf = nxs_file->GetDataset<int>("/run/IDF_version").GetData()[0];
2091 std::cout << ">> PRunDataHandler::ReadNexusFile(): IDF V" << idf << std::endl;
2092 }
2093 if (idf == -1) { // IDF_version not found
2094 if (nxs_file->HasDataset("/raw_data_1/IDF_version")) {
2095 idf = nxs_file->GetDataset<int>("/raw_data_1/IDF_version").GetData()[0];
2096 std::cout << ">> PRunDataHandler::ReadNexusFile(): IDF V" << idf << std::endl;
2097 }
2098 }
2099 if ((idf != 1) && (idf != 2)) {
2100 std::cerr << std::endl << ">> PRunDataHandler::ReadNexusFile(): a NeXus file with an invalid IDF V" << idf << std::endl;
2101 return false;
2102 }
2103
2104 if (idf == 1) { // HDF5 IDF V1
2105 if (!ReadNexusFileIdf1(nxs_file))
2106 return false;
2107 } else { // HDF5 IDF V2
2108 if (!ReadNexusFileIdf2(nxs_file))
2109 return false;
2110 }
2111 }
2112#else
2113 std::cout << std::endl << ">> PRunDataHandler::ReadNexusFile(): Sorry, not enabled at configuration level, i.e. --enable-NeXus when executing configure" << std::endl << std::endl;
2114#endif
2115 return true;
2116}
2117
2118//--------------------------------------------------------------------------
2119// ReadWkmFile (private)
2120//--------------------------------------------------------------------------
2130{
2131 PDoubleVector histoData;
2132 PRawRunData runData;
2133
2134 // open file
2135 std::ifstream f;
2136
2137 // open wkm-file
2138 f.open(fRunPathName.Data(), std::ifstream::in);
2139 if (!f.is_open()) {
2140 std::cerr << std::endl << ">> PRunDataHandler::ReadWkmFile: **ERROR** Couldn't open run data (" << fRunPathName.Data() << ") file for reading, sorry ...";
2141 std::cerr << std::endl;
2142 return false;
2143 }
2144
2145 // read header
2146 Bool_t headerInfo = true;
2147 Char_t instr[512];
2148 TString line, linecp;
2149 Double_t dval;
2150 Int_t ival;
2151 Bool_t ok;
2152 Int_t groups = 0, channels = 0;
2153
2154 // skip leading empty lines
2155 do {
2156 f.getline(instr, sizeof(instr));
2157 line = TString(instr);
2158 if (!line.IsWhitespace())
2159 break;
2160 } while (!f.eof());
2161
2162 // real header data should start here
2163 Ssiz_t idx;
2164 do {
2165 line = TString(instr);
2166 if (line.IsDigit()) { // end of header reached
2167 headerInfo = false;
2168 } else { // real stuff, hence filter data
2169 if (line.Contains("Title") || line.Contains("Titel")) {
2170 idx = line.Index(":");
2171 line.Replace(0, idx+1, nullptr, 0); // remove 'Title:'
2172 StripWhitespace(line);
2173 runData.SetRunTitle(line);
2174 } else if (line.Contains("Run:")) {
2175 idx = line.Index(":");
2176 line.Replace(0, idx+1, nullptr, 0); // remove 'Run:'
2177 StripWhitespace(line);
2178 ival = ToInt(line, ok);
2179 if (ok)
2180 runData.SetRunNumber(ival);
2181 } else if (line.Contains("Field")) {
2182 idx = line.Index(":");
2183 line.Replace(0, idx+1, nullptr, 0); // remove 'Field:'
2184 StripWhitespace(line);
2185 idx = line.Index("G"); // check if unit is given
2186 if (idx > 0) // unit is indeed given
2187 line.Resize(idx);
2188 dval = ToDouble(line, ok);
2189 if (ok)
2190 runData.SetField(dval);
2191 } else if (line.Contains("Setup")) {
2192 idx = line.Index(":");
2193 line.Replace(0, idx+1, nullptr, 0); // remove 'Setup:'
2194 StripWhitespace(line);
2195 runData.SetSetup(line);
2196 } else if (line.Contains("Temp:") || line.Contains("Temp(meas1):")) {
2197 linecp = line;
2198 idx = line.Index(":");
2199 line.Replace(0, idx+1, nullptr, 0); // remove 'Temp:'
2200 StripWhitespace(line);
2201 idx = line.Index("+/-"); // remove "+/- ..." part
2202 if (idx > 0)
2203 line.Resize(idx);
2204 idx = line.Index("K"); // remove "K ..." part
2205 if (idx > 0)
2206 line.Resize(idx);
2207 dval = ToDouble(line, ok);
2208 if (ok) {
2209 runData.SetTemperature(0, dval, 0.0);
2210 }
2211 idx = linecp.Index("+/-"); // get the error
2212 linecp.Replace(0, idx+3, nullptr, 0);
2213 StripWhitespace(linecp);
2214 dval = ToDouble(linecp, ok);
2215 if (ok) {
2216 runData.SetTempError(0, dval);
2217 }
2218 } else if (line.Contains("Temp(meas2):")) {
2219 linecp = line;
2220 idx = line.Index(":");
2221 line.Replace(0, idx+1, nullptr, 0); // remove 'Temp(meas2):'
2222 StripWhitespace(line);
2223 idx = line.Index("+/-"); // remove "+/- ..." part
2224 if (idx > 0)
2225 line.Resize(idx);
2226 idx = line.Index("K"); // remove "K ..." part
2227 if (idx > 0)
2228 line.Resize(idx);
2229 dval = ToDouble(line, ok);
2230 if (ok) {
2231 runData.SetTemperature(1, dval, 0.0);
2232 }
2233 idx = linecp.Index("+/-"); // get the error
2234 linecp.Replace(0, idx+3, nullptr, 0);
2235 StripWhitespace(linecp);
2236 dval = ToDouble(linecp, ok);
2237 if (ok) {
2238 runData.SetTempError(1, dval);
2239 }
2240 } else if (line.Contains("Groups")) {
2241 idx = line.Index(":");
2242 line.Replace(0, idx+1, nullptr, 0); // remove 'Groups:'
2243 StripWhitespace(line);
2244 ival = ToInt(line, ok);
2245 if (ok)
2246 groups = ival;
2247 } else if (line.Contains("Channels")) {
2248 idx = line.Index(":");
2249 line.Replace(0, idx+1, nullptr, 0); // remove 'Channels:'
2250 StripWhitespace(line);
2251 ival = ToInt(line, ok);
2252 if (ok)
2253 channels = ival;
2254 } else if (line.Contains("Resolution")) {
2255 idx = line.Index(":");
2256 line.Replace(0, idx+1, nullptr, 0); // remove 'Resolution:'
2257 StripWhitespace(line);
2258 dval = ToDouble(line, ok);
2259 if (ok)
2260 runData.SetTimeResolution(dval*1.0e3); // us -> ns
2261 }
2262 }
2263
2264 if (headerInfo)
2265 f.getline(instr, sizeof(instr));
2266 } while (headerInfo && !f.eof());
2267
2268 if ((groups == 0) || (channels == 0) || runData.GetTimeResolution() == 0.0) {
2269 std::cerr << std::endl << ">> PRunDataHandler::ReadWkmFile(): **ERROR** essential header informations are missing!";
2270 std::cerr << std::endl << ">> groups = " << groups;
2271 std::cerr << std::endl << ">> channels = " << channels;
2272 std::cerr << std::endl << ">> time resolution = " << runData.GetTimeResolution();
2273 std::cerr << std::endl;
2274 f.close();
2275 return false;
2276 }
2277
2278 // read data ---------------------------------------------------------
2279 UInt_t group_counter = 0;
2280 Int_t val;
2281 std::vector<std::string> tokens;
2282 TString str;
2283 UInt_t histoNo = 0;
2284 PRawRunDataSet dataSet;
2285 do {
2286 // check if empty line, i.e. new group
2287 if (IsWhitespace(instr)) {
2288 dataSet.Clear();
2289 dataSet.SetHistoNo(++histoNo);
2290 dataSet.SetData(histoData);
2291
2292 // get a T0 estimate
2293 Double_t maxVal = 0.0;
2294 Int_t maxBin = 0;
2295 for (UInt_t i=0; i<histoData.size(); i++) {
2296 if (histoData[i] > maxVal) {
2297 maxVal = histoData[i];
2298 maxBin = i;
2299 }
2300 }
2301 dataSet.SetTimeZeroBinEstimated(maxBin);
2302
2303 runData.SetDataSet(dataSet);
2304
2305 histoData.clear();
2306 group_counter++;
2307 } else {
2308 // extract values
2309 line = TString(instr);
2310 // check if line starts with character. Needed for RAL WKM format
2311 if (!line.IsDigit()) {
2312 f.getline(instr, sizeof(instr));
2313 continue;
2314 }
2315 tokens = PStringUtils::Split(line.Data(), " ");
2316
2317 if (tokens.empty()) { // no tokens found
2318 std::cerr << std::endl << ">> PRunDataHandler::ReadWkmFile(): **ERROR** while reading data: coulnd't tokenize run data.";
2319 return false;
2320 }
2321 for (UInt_t i=0; i<tokens.size(); i++) {
2322 str = tokens[i];
2323 val = ToInt(str, ok);
2324 if (ok) {
2325 histoData.push_back(val);
2326 } else {
2327 std::cerr << std::endl << ">> PRunDataHandler::ReadWkmFile(): **ERROR** while reading data: data line contains non-integer values.";
2328 return false;
2329 }
2330 }
2331 }
2332
2333 f.getline(instr, sizeof(instr));
2334
2335 } while (!f.eof());
2336
2337 // handle last line if present
2338 if (strlen(instr) != 0) {
2339 // extract values
2340 line = TString(instr);
2341 tokens = PStringUtils::Split(line.Data(), " ");
2342 if (tokens.empty()) { // no tokens found
2343 std::cerr << std::endl << ">> PRunDataHandler::ReadWkmFile(): **ERROR** while reading data: coulnd't tokenize run data.";
2344 return false;
2345 }
2346 for (UInt_t i=0; i<tokens.size(); i++) {
2347 str = tokens[i];
2348 val = ToInt(str, ok);
2349 if (ok) {
2350 histoData.push_back(val);
2351 } else {
2352 std::cerr << std::endl << ">> PRunDataHandler::ReadWkmFile(): **ERROR** while reading data: data line contains non-integer values.";
2353 return false;
2354 }
2355 }
2356 }
2357
2358 // save the last histo if not empty
2359 if (histoData.size() > 0) {
2360 dataSet.Clear();
2361 dataSet.SetHistoNo(++histoNo);
2362 dataSet.SetData(histoData);
2363
2364 // get a T0 estimate
2365 Double_t maxVal = 0.0;
2366 Int_t maxBin = 0;
2367 for (UInt_t i=0; i<histoData.size(); i++) {
2368 if (histoData[i] > maxVal) {
2369 maxVal = histoData[i];
2370 maxBin = i;
2371 }
2372 }
2373 dataSet.SetTimeZeroBinEstimated(maxBin);
2374
2375 runData.SetDataSet(dataSet);
2376 histoData.clear();
2377 }
2378
2379 // close file
2380 f.close();
2381
2382 // check if all groups are found
2383 if (static_cast<Int_t>(runData.GetNoOfHistos()) != groups) {
2384 std::cerr << std::endl << ">> PRunDataHandler::ReadWkmFile(): **ERROR**";
2385 std::cerr << std::endl << ">> expected " << groups << " histos, but found " << runData.GetNoOfHistos();
2386 return false;
2387 }
2388
2389 // check if all groups have enough channels
2390 for (UInt_t i=0; i<runData.GetNoOfHistos(); i++) {
2391 if (static_cast<Int_t>(runData.GetDataBin(i+1)->size()) != channels) {
2392 std::cerr << std::endl << ">> PRunDataHandler::ReadWkmFile(): **ERROR**";
2393 std::cerr << std::endl << ">> expected " << channels << " bins in histo " << i+1 << ", but found " << runData.GetDataBin(i)->size();
2394 return false;
2395 }
2396 }
2397
2398 // keep run name
2399 runData.SetRunName(fRunName);
2400
2401 // add run to the run list
2402 fData.push_back(runData);
2403
2404 return true;
2405}
2406
2407//--------------------------------------------------------------------------
2408// ReadPsiBinFile (private)
2409//--------------------------------------------------------------------------
2419{
2420 MuSR_td_PSI_bin psiBin;
2421 Int_t status;
2422 Bool_t success;
2423
2424 // read psi bin file
2425 status = psiBin.Read(fRunPathName.Data());
2426 switch (status) {
2427 case 0: // everything perfect
2428 success = true;
2429 break;
2430 case 1: // couldn't open file, or failed while reading the header
2431 std::cerr << std::endl << ">> **ERROR** couldn't open psi-bin file, or failed while reading the header";
2432 std::cerr << std::endl;
2433 success = false;
2434 break;
2435 case 2: // unsupported version of the data
2436 std::cerr << std::endl << ">> **ERROR** psi-bin file: unsupported version of the data";
2437 std::cerr << std::endl;
2438 success = false;
2439 break;
2440 case 3: // error when allocating data buffer
2441 std::cerr << std::endl << ">> **ERROR** psi-bin file: error when allocating data buffer";
2442 std::cerr << std::endl;
2443 success = false;
2444 break;
2445 case 4: // number of histograms/record not equals 1
2446 std::cerr << std::endl << ">> **ERROR** psi-bin file: number of histograms/record not equals 1";
2447 std::cerr << std::endl;
2448 success = false;
2449 break;
2450 default: // you never should have reached this point
2451 success = false;
2452 break;
2453 }
2454
2455 // if any reading error happend, get out of here
2456 if (!success)
2457 return success;
2458
2459 // fill necessary header informations
2460 PRawRunData runData;
2461 Double_t dval;
2462
2463 // set file name
2464 Ssiz_t pos = fRunPathName.Last('/');
2465 TString fln(fRunPathName);
2466 fln.Remove(0, pos+1);
2467 runData.SetFileName(fln);
2468
2469 // set laboratory
2470 runData.SetLaboratory("PSI");
2471
2472 // filter from the file name the instrument
2473 TString instrument("n/a"), beamline("n/a");
2474 TString muonSource("n/a"), muonSpecies("n/a");
2475 if (fRunPathName.Contains("_gps_", TString::kIgnoreCase)) {
2476 instrument = "GPS";
2477 beamline = "piM3.2";
2478 muonSource = "continuous surface muon source";
2479 muonSpecies = "positive muons";
2480 } else if (fRunPathName.Contains("_ltf_", TString::kIgnoreCase)) {
2481 instrument = "LTF";
2482 beamline = "piM3.3";
2483 muonSource = "continuous surface muon source";
2484 muonSpecies = "positive muons";
2485 } else if (fRunPathName.Contains("_gpd_", TString::kIgnoreCase)) {
2486 instrument = "GPD";
2487 beamline = "muE1";
2488 muonSource = "continuous decay channel muon source";
2489 muonSpecies = "positive muons";
2490 } else if (fRunPathName.Contains("_dolly_", TString::kIgnoreCase)) {
2491 instrument = "DOLLY";
2492 beamline = "piE1";
2493 muonSource = "continuous surface muon source";
2494 muonSpecies = "positive muons";
2495 } else if (fRunPathName.Contains("_alc_", TString::kIgnoreCase)) {
2496 instrument = "ALC";
2497 beamline = "piE3";
2498 muonSource = "continuous surface muon source";
2499 muonSpecies = "positive muons";
2500 } else if (fRunPathName.Contains("_hifi_", TString::kIgnoreCase)) {
2501 instrument = "HIFI";
2502 beamline = "piE3";
2503 muonSource = "continuous surface muon source";
2504 muonSpecies = "positive muons";
2505 }
2506 runData.SetInstrument(instrument);
2507 runData.SetBeamline(beamline);
2508 runData.SetMuonSource(muonSource);
2509 runData.SetMuonSpecies(muonSpecies);
2510
2511 // keep run name
2512 runData.SetRunName(fRunName);
2513 // get run title
2514 runData.SetRunTitle(TString(psiBin.GetComment().c_str())); // run title
2515 // get run number
2516 runData.SetRunNumber(psiBin.GetRunNumberInt());
2517 // get setup
2518 runData.SetSetup(TString(psiBin.GetComment().c_str()));
2519 // get sample
2520 runData.SetSample(TString(psiBin.GetSample().c_str()));
2521 // get orientation
2522 runData.SetOrientation(TString(psiBin.GetOrient().c_str()));
2523 // get comment
2524 runData.SetComment(TString(psiBin.GetComment().c_str()));
2525 // set LEM specific information to default value since it is not in the file and not used...
2526 runData.SetEnergy(PMUSR_UNDEFINED);
2528 // get field
2529 Double_t scale = 0.0;
2530 if (psiBin.GetField().rfind("G") != std::string::npos)
2531 scale = 1.0;
2532 if (psiBin.GetField().rfind("T") != std::string::npos)
2533 scale = 1.0e4;
2534 status = sscanf(psiBin.GetField().c_str(), "%lf", &dval);
2535 if (status == 1)
2536 runData.SetField(scale*dval);
2537 // get temperature
2538 PDoubleVector tempVec(psiBin.GetTemperaturesVector());
2539 PDoubleVector tempDevVec(psiBin.GetDevTemperaturesVector());
2540 if ((tempVec.size() > 1) && (tempDevVec.size() > 1) && tempVec[0] && tempVec[1]) {
2541 // take only the first two values for now...
2542 //maybe that's not enough - e.g. in older GPD data I saw the "correct values in the second and third entry..."
2543 for (UInt_t i(0); i<2; i++) {
2544 runData.SetTemperature(i, tempVec[i], tempDevVec[i]);
2545 }
2546 tempVec.clear();
2547 tempDevVec.clear();
2548 } else {
2549 status = sscanf(psiBin.GetTemp().c_str(), "%lfK", &dval);
2550 if (status == 1)
2551 runData.SetTemperature(0, dval, 0.0);
2552 }
2553
2554 // get time resolution (ns)
2555 runData.SetTimeResolution(psiBin.GetBinWidthNanoSec());
2556
2557 // get start/stop time
2558 std::vector<std::string> sDateTime = psiBin.GetTimeStartVector();
2559 if (sDateTime.size() < 2) {
2560 std::cerr << std::endl << ">> **WARNING** psi-bin file: couldn't obtain run start date/time" << std::endl;
2561 }
2562 std::string date("");
2563 if (DateToISO8601(sDateTime[0], date)) {
2564 runData.SetStartDate(date);
2565 } else {
2566 std::cerr << std::endl << ">> **WARNING** failed to convert start date: " << sDateTime[0] << " into ISO 8601 date." << std::endl;
2567 runData.SetStartDate(sDateTime[0]);
2568 }
2569 runData.SetStartTime(sDateTime[1]);
2570 sDateTime.clear();
2571
2572 sDateTime = psiBin.GetTimeStopVector();
2573 if (sDateTime.size() < 2) {
2574 std::cerr << std::endl << ">> **WARNING** psi-bin file: couldn't obtain run stop date/time" << std::endl;
2575 }
2576 date = std::string("");
2577 if (DateToISO8601(sDateTime[0], date)) {
2578 runData.SetStopDate(date);
2579 } else {
2580 std::cerr << std::endl << ">> **WARNING** failed to convert stop date: " << sDateTime[0] << " into ISO 8601 date." << std::endl;
2581 runData.SetStopDate(sDateTime[0]);
2582 }
2583 runData.SetStopTime(sDateTime[1]);
2584 sDateTime.clear();
2585
2586 // get t0's
2587 PIntVector t0 = psiBin.GetT0Vector();
2588
2589 if (t0.empty()) {
2590 std::cerr << std::endl << ">> **ERROR** psi-bin file: couldn't obtain any t0's";
2591 std::cerr << std::endl;
2592 return false;
2593 }
2594
2595 // get first good bin
2596 PIntVector fgb = psiBin.GetFirstGoodVector();
2597 if (fgb.empty()) {
2598 std::cerr << std::endl << ">> **ERROR** psi-bin file: couldn't obtain any fgb's";
2599 std::cerr << std::endl;
2600 return false;
2601 }
2602
2603 // get last good bin
2604 PIntVector lgb = psiBin.GetLastGoodVector();
2605 if (lgb.empty()) {
2606 std::cerr << std::endl << ">> **ERROR** psi-bin file: couldn't obtain any lgb's";
2607 std::cerr << std::endl;
2608 return false;
2609 }
2610
2611 // fill raw data
2612 PRawRunDataSet dataSet;
2613 PDoubleVector histoData;
2614 std::vector<Int_t> histo;
2615 for (Int_t i=0; i<psiBin.GetNumberHistoInt(); i++) {
2616 histo = psiBin.GetHistoArrayInt(i);
2617 for (Int_t j=0; j<psiBin.GetHistoLengthBin(); j++) {
2618 histoData.push_back(histo[j]);
2619 }
2620
2621 // estimate T0 from maximum of the data
2622 Double_t maxVal = 0.0;
2623 Int_t maxBin = 0;
2624 for (UInt_t j=0; j<histoData.size(); j++) {
2625 if (histoData[j] > maxVal) {
2626 maxVal = histoData[j];
2627 maxBin = j;
2628 }
2629 }
2630
2631 dataSet.Clear();
2632 dataSet.SetName(psiBin.GetNameHisto(i).c_str());
2633 dataSet.SetHistoNo(i+1); // i.e. hist numbering starts at 1
2634 if (i < static_cast<Int_t>(t0.size()))
2635 dataSet.SetTimeZeroBin(t0[i]);
2636 dataSet.SetTimeZeroBinEstimated(maxBin);
2637 if (i < static_cast<Int_t>(fgb.size()))
2638 dataSet.SetFirstGoodBin(fgb[i]);
2639 if (i < static_cast<Int_t>(lgb.size()))
2640 dataSet.SetLastGoodBin(lgb[i]);
2641 dataSet.SetData(histoData);
2642
2643 runData.SetDataSet(dataSet);
2644
2645 histoData.clear();
2646 }
2647
2648 // add run to the run list
2649 fData.push_back(runData);
2650
2651 return success;
2652}
2653
2654//--------------------------------------------------------------------------
2655// ReadMudFile (private)
2656//--------------------------------------------------------------------------
2665{
2666 Int_t fh;
2667 UINT32 type, val;
2668 Int_t success;
2669 Char_t str[1024];
2670 Double_t dval;
2671
2672 PRawRunData runData;
2673
2674 fh = MUD_openRead((char*)fRunPathName.Data(), &type);
2675 if (fh == -1) {
2676 std::cerr << std::endl << ">> **ERROR** Couldn't open mud-file " << fRunPathName.Data() << ", sorry.";
2677 std::cerr << std::endl;
2678 return false;
2679 }
2680
2681 // read necessary header information
2682
2683 // keep run name
2684 runData.SetRunName(fRunName);
2685
2686 // get/set the lab
2687 success = MUD_getLab( fh, str, sizeof(str) );
2688 if ( !success ) {
2689 std::cerr << std::endl << ">> **WARNING** Couldn't obtain the laboratory name of run " << fRunName.Data();
2690 std::cerr << std::endl;
2691 strcpy(str, "n/a");
2692 }
2693 runData.SetLaboratory(TString(str));
2694
2695 // get/set the beamline
2696 success = MUD_getArea( fh, str, sizeof(str) );
2697 if ( !success ) {
2698 std::cerr << std::endl << ">> **WARNING** Couldn't obtain the beamline of run " << fRunName.Data();
2699 std::cerr << std::endl;
2700 strcpy(str, "n/a");
2701 }
2702 runData.SetBeamline(TString(str));
2703
2704 // get/set the instrument
2705 success = MUD_getApparatus( fh, str, sizeof(str) );
2706 if ( !success ) {
2707 std::cerr << std::endl << ">> **WARNING** Couldn't obtain the instrument name of run " << fRunName.Data();
2708 std::cerr << std::endl;
2709 strcpy(str, "n/a");
2710 }
2711 runData.SetInstrument(TString(str));
2712
2713 // get run title
2714 success = MUD_getTitle( fh, str, sizeof(str) );
2715 if ( !success ) {
2716 std::cerr << std::endl << ">> **WARNING** Couldn't obtain the run title of run " << fRunName.Data();
2717 std::cerr << std::endl;
2718 }
2719 runData.SetRunTitle(TString(str));
2720
2721 // get run number
2722 success = MUD_getRunNumber( fh, &val );
2723 if (success) {
2724 runData.SetRunNumber(static_cast<Int_t>(val));
2725 }
2726
2727 // get start/stop time of the run
2728 time_t tval;
2729 struct tm *dt;
2730 TString stime("");
2731 success = MUD_getTimeBegin( fh, (UINT32*)&tval );
2732 if (success) {
2733 runData.SetStartDateTime(static_cast<const time_t>(tval));
2734 dt = localtime((const time_t*)&tval);
2735
2736 if (dt) {
2737 // start date
2738 strftime(str, sizeof(str), "%F", dt);
2739 stime = str;
2740 runData.SetStartDate(stime);
2741 // start time
2742 memset(str, 0, sizeof(str));
2743 strftime(str, sizeof(str), "%T", dt);
2744 stime = str;
2745 runData.SetStartTime(stime);
2746 } else {
2747 std::cerr << "PRunDataHandler::ReadMudFile: **WARNING** run start time readback wrong, will set it to 1900-01-01, 00:00:00" << std::endl;
2748 stime = "1900-01-01";
2749 runData.SetStartDate(stime);
2750 stime = "00:00:00";
2751 runData.SetStartTime(stime);
2752 }
2753 }
2754
2755 stime = TString("");
2756 success = MUD_getTimeEnd( fh, (UINT32*)&tval );
2757 if (success) {
2758 runData.SetStopDateTime((const time_t)tval);
2759 dt = localtime((const time_t*)&tval);
2760
2761 if (dt) {
2762 // stop date
2763 strftime(str, sizeof(str), "%F", dt);
2764 stime = str;
2765 runData.SetStopDate(stime);
2766 // stop time
2767 memset(str, 0, sizeof(str));
2768 strftime(str, sizeof(str), "%T", dt);
2769 stime = str;
2770 runData.SetStopTime(stime);
2771 } else {
2772 std::cerr << "PRunDataHandler::ReadMudFile: **WARNING** run stop time readback wrong, will set it to 1900-01-01, 00:00:00" << std::endl;
2773 stime = "1900-01-01";
2774 runData.SetStopDate(stime);
2775 stime = "00:00:00";
2776 runData.SetStopTime(stime);
2777 }
2778 }
2779
2780 // get setup
2781 TString setup;
2782 REAL64 timeResMultiplier = 1.0e9; // Multiplier time resolution
2783 success = MUD_getLab( fh, str, sizeof(str) );
2784 if (success) {
2785 setup = TString(str) + TString("/");
2786 }
2787 success = MUD_getArea( fh, str, sizeof(str) );
2788 if (success) {
2789 setup += TString(str) + TString("/");
2790 if (TString(str) == "BNQR" || TString(str) == "BNMR") {
2791 std::cerr << "PRunDataHandler::ReadMudFile: **INFORMATION** this run was performed on " << str << std::endl;
2792 std::cerr << "PRunDataHandler::ReadMudFile: **INFORMATION** apply correction to time resolution" << std::endl;
2793 // identified BNMR/BNQR, correct time resolution.
2794 timeResMultiplier = 1.0e9;
2795 }
2796 }
2797 success = MUD_getApparatus( fh, str, sizeof(str) );
2798 if (success) {
2799 setup += TString(str) + TString("/");
2800 }
2801 success = MUD_getSample( fh, str, sizeof(str) );
2802 if (success) {
2803 setup += TString(str);
2804 runData.SetSample(str);
2805 }
2806 runData.SetSetup(setup);
2807
2808 // set LEM specific information to default value since it is not in the file and not used...
2809 runData.SetEnergy(PMUSR_UNDEFINED);
2811
2812 // get field
2813 success = MUD_getField( fh, str, sizeof(str) );
2814 if (success) {
2815 success = sscanf(str, "%lf G", &dval);
2816 if (success == 1) {
2817 runData.SetField(dval);
2818 } else {
2819 runData.SetField(PMUSR_UNDEFINED);
2820 }
2821 } else {
2822 runData.SetField(PMUSR_UNDEFINED);
2823 }
2824
2825 // get temperature
2826 success = MUD_getTemperature( fh, str, sizeof(str) );
2827 if (success) {
2828 success = sscanf(str, "%lf K", &dval);
2829 if (success == 1) {
2830 runData.SetTemperature(0, dval, 0.0);
2831 } else {
2832 runData.SetTemperature(0, PMUSR_UNDEFINED, 0.0);
2833 }
2834 } else {
2835 runData.SetTemperature(0, PMUSR_UNDEFINED, 0.0);
2836 }
2837
2838 // get number of histogramms
2839 success = MUD_getHists(fh, &type, &val);
2840 if ( !success ) {
2841 std::cerr << std::endl << ">> **ERROR** Couldn't obtain the number of histograms of run " << fRunName.Data();
2842 std::cerr << std::endl;
2843 MUD_closeRead(fh);
2844 return false;
2845 }
2846 Int_t noOfHistos = static_cast<Int_t>(val);
2847
2848 // get time resolution (ns)
2849 // check that time resolution is identical for all histograms
2850 // >> currently it is not forseen to handle histos with different time resolutions <<
2851 // >> perhaps this needs to be reconsidered later on <<
2852 REAL64 timeResolution = 0.0; // in seconds!!
2853 REAL64 lrval = 0.0;
2854 for (Int_t i=1; i<=noOfHistos; i++) {
2855 success = MUD_getHistSecondsPerBin( fh, i, &lrval );
2856 if (!success) {
2857 std::cerr << std::endl << ">> **ERROR** Couldn't obtain the time resolution of run " << fRunName.Data();
2858 std::cerr << std::endl << ">> which is fatal, sorry.";
2859 std::cerr << std::endl;
2860 MUD_closeRead(fh);
2861 return false;
2862 }
2863 if (i==1) {
2864 timeResolution = lrval;
2865 } else {
2866 if (lrval != timeResolution) {
2867 std::cerr << std::endl << ">> **ERROR** various time resolutions found in run " << fRunName.Data();
2868 std::cerr << std::endl << ">> this is currently not supported, sorry.";
2869 std::cerr << std::endl;
2870 MUD_closeRead(fh);
2871 return false;
2872 }
2873 }
2874 }
2875
2876 runData.SetTimeResolution(static_cast<Double_t>(timeResolution) * timeResMultiplier); // s -> ns or s -> ms for bNMR
2877 // Other possibility:
2878 // Check if it is a bNMR run and fix it or check if "timeres" line
2879 // was introduced in the msr file
2880
2881
2882 // read histograms
2883 UINT32 *pData; // histo memory
2884 pData = nullptr;
2885 PDoubleVector histoData;
2886 PRawRunDataSet dataSet;
2887 UInt_t noOfBins;
2888
2889 for (Int_t i=1; i<=noOfHistos; i++) {
2890 dataSet.Clear();
2891
2892 dataSet.SetHistoNo(i);
2893
2894 // get t0's
2895 success = MUD_getHistT0_Bin( fh, i, &val );
2896 if ( !success ) {
2897 std::cerr << std::endl << ">> **WARNING** Couldn't get t0 of histo " << i << " of run " << fRunName.Data();
2898 std::cerr << std::endl;
2899 }
2900 dataSet.SetTimeZeroBin(static_cast<Double_t>(val));
2901
2902 // get bkg bins
2903 success = MUD_getHistBkgd1( fh, i, &val );
2904 if ( !success ) {
2905 std::cerr << std::endl << ">> **WARNING** Couldn't get bkg bin 1 of histo " << i << " of run " << fRunName.Data();
2906 std::cerr << std::endl;
2907 val = 0;
2908 }
2909 dataSet.SetFirstBkgBin(static_cast<Int_t>(val));
2910
2911 success = MUD_getHistBkgd2( fh, i, &val );
2912 if ( !success ) {
2913 std::cerr << std::endl << ">> **WARNING** Couldn't get bkg bin 2 of histo " << i << " of run " << fRunName.Data();
2914 std::cerr << std::endl;
2915 val = 0;
2916 }
2917 dataSet.SetLastBkgBin(static_cast<Int_t>(val));
2918
2919 // get good data bins
2920 success = MUD_getHistGoodBin1( fh, i, &val );
2921 if ( !success ) {
2922 std::cerr << std::endl << ">> **WARNING** Couldn't get good bin 1 of histo " << i << " of run " << fRunName.Data();
2923 std::cerr << std::endl;
2924 val = 0;
2925 }
2926 dataSet.SetFirstGoodBin(static_cast<Int_t>(val));
2927
2928 success = MUD_getHistGoodBin2( fh, i, &val );
2929 if ( !success ) {
2930 std::cerr << std::endl << ">> **WARNING** Couldn't get good bin 2 of histo " << i << " of run " << fRunName.Data();
2931 std::cerr << std::endl;
2932 val = 0;
2933 }
2934 dataSet.SetLastGoodBin(static_cast<Int_t>(val));
2935
2936 // get number of bins
2937 success = MUD_getHistNumBins( fh, i, &val );
2938 if ( !success ) {
2939 std::cerr << std::endl << ">> **ERROR** Couldn't get the number of bins of histo " << i << ".";
2940 std::cerr << std::endl << ">> This is fatal, sorry.";
2941 std::cerr << std::endl;
2942 MUD_closeRead( fh );
2943 return false;
2944 }
2945 noOfBins = static_cast<UInt_t>(val);
2946
2947 pData = (UINT32*)malloc(noOfBins*sizeof(pData));
2948 if (pData == nullptr) {
2949 std::cerr << std::endl << ">> **ERROR** Couldn't allocate memory for data.";
2950 std::cerr << std::endl << ">> This is fatal, sorry.";
2951 std::cerr << std::endl;
2952 MUD_closeRead( fh );
2953 return false;
2954 }
2955
2956 // get histogram
2957 success = MUD_getHistData( fh, i, pData );
2958 if ( !success ) {
2959 std::cerr << std::endl << ">> **ERROR** Couldn't get histo no " << i << ".";
2960 std::cerr << std::endl << ">> This is fatal, sorry.";
2961 std::cerr << std::endl;
2962 MUD_closeRead( fh );
2963 return false;
2964 }
2965
2966 for (UInt_t j=0; j<noOfBins; j++) {
2967 histoData.push_back(pData[j]);
2968 }
2969 dataSet.SetData(histoData);
2970
2971 // estimate T0 from maximum of the data
2972 Double_t maxVal = 0.0;
2973 Int_t maxBin = 0;
2974 for (UInt_t j=0; j<histoData.size(); j++) {
2975 if (histoData[j] > maxVal) {
2976 maxVal = histoData[j];
2977 maxBin = j;
2978 }
2979 }
2980 dataSet.SetTimeZeroBinEstimated(maxBin);
2981
2982 runData.SetDataSet(dataSet);
2983
2984 histoData.clear();
2985
2986 free(pData);
2987 }
2988
2989 MUD_closeRead(fh);
2990
2991 // add run to the run list
2992 fData.push_back(runData);
2993
2994 return true;
2995}
2996
2997//--------------------------------------------------------------------------
2998// ReadMduAsciiFile (private)
2999//--------------------------------------------------------------------------
3027{
3028 Bool_t success = true;
3029
3030 // open file
3031 std::ifstream f;
3032
3033 // open data-file
3034 f.open(fRunPathName.Data(), std::ifstream::in);
3035 if (!f.is_open()) {
3036 std::cerr << std::endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** Couldn't open data file (" << fRunPathName.Data() << ") for reading, sorry ...";
3037 std::cerr << std::endl;
3038 return false;
3039 }
3040
3041 PRawRunData runData;
3042
3043 // keep run name
3044 runData.SetRunName(fRunName);
3045
3046 Int_t lineNo = 0;
3047 Char_t instr[512];
3048 TString line, workStr;
3049 Bool_t headerTag = false;
3050 Bool_t dataTag = false;
3051 Int_t dataLineCounter = 0;
3052 std::vector<std::string> tokens;
3053 TString str;
3054 Int_t groups = 0;
3055 Int_t channels = 0;
3056 Double_t dval = 0.0, unitScaling = 0.0;
3057 std::vector<PDoubleVector> data;
3058
3059 while (!f.eof()) {
3060 f.getline(instr, sizeof(instr));
3061 line = TString(instr);
3062 lineNo++;
3063
3064 // ignore comment lines
3065 if (line.BeginsWith("#") || line.BeginsWith("%"))
3066 continue;
3067
3068 // ignore empty lines
3069 if (line.IsWhitespace())
3070 continue;
3071
3072 // check if header tag
3073 workStr = line;
3074 workStr.Remove(TString::kLeading, ' '); // remove spaces from the begining
3075 if (workStr.BeginsWith("header", TString::kIgnoreCase)) {
3076 headerTag = true;
3077 dataTag = false;
3078 continue;
3079 }
3080
3081 // check if data tag
3082 workStr = line;
3083 workStr.Remove(TString::kLeading, ' '); // remove spaces from the beining
3084 if (workStr.BeginsWith("data", TString::kIgnoreCase)) {
3085 headerTag = false;
3086 dataTag = true;
3087 continue;
3088 }
3089
3090 if (headerTag) {
3091 workStr = line;
3092 workStr.Remove(TString::kLeading, ' '); // remove spaces from the beining
3093 if (workStr.BeginsWith("title:", TString::kIgnoreCase)) {
3094 runData.SetRunTitle(TString(workStr.Data()+workStr.First(":")+2));
3095 } else if (workStr.BeginsWith("field:", TString::kIgnoreCase)) {
3096 tokens = PStringUtils::Split(workStr.Data(), ":("); // field: val (units)
3097 // check if expected number of tokens present
3098 if (tokens.size() != 3) {
3099 std::cerr << std::endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** line no " << lineNo << ", invalid field entry in header.";
3100 std::cerr << std::endl << ">> " << line.Data();
3101 std::cerr << std::endl;
3102 success = false;
3103 break;
3104 }
3105 // check if field value is a number
3106 if (TString(tokens[1]).IsFloat()) {
3107 dval = TString(tokens[1]).Atof();
3108 } else {
3109 std::cerr << std::endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** line no " << lineNo << ", field value is not float/doulbe.";
3110 std::cerr << std::endl << ">> " << line.Data();
3111 std::cerr << std::endl;
3112 success = false;
3113 break;
3114 }
3115 // check units, accept (G), (T)
3116 if (TString(tokens[2]).Contains("G"))
3117 unitScaling = 1.0;
3118 else if (TString(tokens[2]).Contains("T"))
3119 unitScaling = 1.0e4;
3120 else {
3121 std::cerr << std::endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** line no " << lineNo << ", unkown field units.";
3122 std::cerr << std::endl << ">> " << line.Data();
3123 std::cerr << std::endl;
3124 success = false;
3125 break;
3126 }
3127 runData.SetField(dval*unitScaling);
3128 } else if (workStr.BeginsWith("temp:", TString::kIgnoreCase)) {
3129 tokens = PStringUtils::Split(workStr.Data(), ":("); // temp: val (units)
3130 // check if expected number of tokens present
3131 if (tokens.size() != 3) {
3132 std::cerr << std::endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** line no " << lineNo << ", invalid temperatue entry in header.";
3133 std::cerr << std::endl << ">> " << line.Data();
3134 std::cerr << std::endl;
3135 success = false;
3136 break;
3137 }
3138 // check if field value is a number
3139 if (TString(tokens[1]).IsFloat()) {
3140 dval = TString(tokens[1]).Atof();
3141 } else {
3142 std::cerr << std::endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** line no " << lineNo << ", temperature value is not float/doulbe.";
3143 std::cerr << std::endl << ">> " << line.Data();
3144 std::cerr << std::endl;
3145 success = false;
3146 break;
3147 }
3148 runData.SetTemperature(0, dval, 0.0);
3149 } else if (workStr.BeginsWith("setup:", TString::kIgnoreCase)) {
3150 runData.SetSetup(TString(workStr.Data()+workStr.First(":")+2));
3151 } else if (workStr.BeginsWith("groups:", TString::kIgnoreCase)) {
3152 workStr = TString(workStr.Data()+workStr.First(":")+2);
3153 groups = workStr.Atoi();
3154 if (groups == 0) {
3155 std::cerr << std::endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** line no " << lineNo << ", groups is not a number or 0.";
3156 std::cerr << std::endl;
3157 success = false;
3158 break;
3159 }
3160 data.resize(groups);
3161 } else if (workStr.BeginsWith("channels:", TString::kIgnoreCase)) {
3162 workStr = TString(workStr.Data()+workStr.First(":")+2);
3163 channels = workStr.Atoi();
3164 if (channels == 0) {
3165 std::cerr << std::endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** line no " << lineNo << ", channels is not a number or 0.";
3166 std::cerr << std::endl;
3167 success = false;
3168 break;
3169 }
3170 } else if (workStr.BeginsWith("resolution:", TString::kIgnoreCase)) {
3171 tokens = PStringUtils::Split(workStr.Data(), ":("); // resolution: val (units)
3172 // check if expected number of tokens present
3173 if (tokens.size() != 3) {
3174 std::cerr << std::endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** line no " << lineNo << ", invalid time resolution entry in header.";
3175 std::cerr << std::endl << line.Data();
3176 std::cerr << std::endl;
3177 success = false;
3178 break;
3179 }
3180 // check if timeresolution value is a number
3181 if (TString(tokens[1]).IsFloat()) {
3182 dval = TString(tokens[1]).Atof();
3183 } else {
3184 std::cerr << std::endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** line no " << lineNo << ", time resolution value is not float/doulbe.";
3185 std::cerr << std::endl << ">> " << line.Data();
3186 std::cerr << std::endl;
3187 success = false;
3188 break;
3189 }
3190 // check units, accept (fs), (ps), (ns), (us)
3191 if (TString(tokens[2]).Contains("fs"))
3192 unitScaling = 1.0e-6;
3193 else if (TString(tokens[2]).Contains("ps"))
3194 unitScaling = 1.0e-3;
3195 else if (TString(tokens[2]).Contains("ns"))
3196 unitScaling = 1.0;
3197 else if (TString(tokens[2]).Contains("us"))
3198 unitScaling = 1.0e3;
3199 else {
3200 std::cerr << std::endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** line no " << lineNo << ", unkown time resolution units.";
3201 std::cerr << std::endl << ">> " << line.Data();
3202 std::cerr << std::endl;
3203 success = false;
3204 break;
3205 }
3206 runData.SetTimeResolution(dval*unitScaling);
3207 } else { // error
3208 std::cerr << std::endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** line no " << lineNo << ", illegal header line.";
3209 std::cerr << std::endl;
3210 success = false;
3211 break;
3212 }
3213 } else if (dataTag) {
3214 dataLineCounter++;
3215 tokens = PStringUtils::Split(line.Data(), " ,\t");
3216 // check if the number of data line entries is correct
3217 if (static_cast<Int_t>(tokens.size()) != groups+1) {
3218 std::cerr << std::endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** found data line with a wrong data format, cannot be handled (line no " << lineNo << ")";
3219 std::cerr << std::endl << ">> line:";
3220 std::cerr << std::endl << ">> " << line.Data();
3221 std::cerr << std::endl;
3222 success = false;
3223 break;
3224 }
3225
3226 for (UInt_t i=1; i<tokens.size(); i++) {
3227 data[i-1].push_back(TString(tokens[i]).Atof());
3228 }
3229 }
3230 }
3231
3232 f.close();
3233
3234 // keep data
3235 PRawRunDataSet dataSet;
3236 for (UInt_t i=0; i<data.size(); i++) {
3237 dataSet.Clear();
3238 dataSet.SetHistoNo(i);
3239 dataSet.SetData(data[i]);
3240
3241 // estimate T0 from maximum of the data
3242 Double_t maxVal = 0.0;
3243 Int_t maxBin = 0;
3244 for (UInt_t j=0; j<data[i].size(); j++) {
3245 if (data[i][j] > maxVal) {
3246 maxVal = data[i][j];
3247 maxBin = j;
3248 }
3249 }
3250 dataSet.SetTimeZeroBinEstimated(maxBin);
3251 runData.SetDataSet(dataSet);
3252 }
3253
3254 // clean up
3255 for (UInt_t i=0; i<data.size(); i++)
3256 data[i].clear();
3257 data.clear();
3258
3259 if (dataLineCounter != channels) {
3260 std::cerr << std::endl << ">> PRunDataHandler::ReadMduAsciiFile **WARNING** found " << dataLineCounter << " data bins,";
3261 std::cerr << std::endl << ">> expected " << channels << " according to the header." << std::endl;
3262 }
3263
3264 fData.push_back(runData);
3265
3266 return success;
3267}
3268
3269//--------------------------------------------------------------------------
3270// ReadAsciiFile (private)
3271//--------------------------------------------------------------------------
3309{
3310 Bool_t success = true;
3311
3312 // open file
3313 std::ifstream f;
3314
3315 // open data-file
3316 f.open(fRunPathName.Data(), std::ifstream::in);
3317 if (!f.is_open()) {
3318 std::cerr << std::endl << ">> PRunDataHandler::ReadAsciiFile **ERROR** Couldn't open data file (" << fRunPathName.Data() << ") for reading, sorry ...";
3319 std::cerr << std::endl;
3320 return false;
3321 }
3322
3323 PRawRunData runData;
3324
3325 // init some stuff
3326 runData.fDataNonMusr.SetFromAscii(true);
3327 runData.fDataNonMusr.AppendLabel("??"); // x default label
3328 runData.fDataNonMusr.AppendLabel("??"); // y default label
3329
3330 runData.SetRunName(fRunName); // keep the run name
3331
3332 Int_t lineNo = 0;
3333 Char_t instr[512];
3334 TString line, workStr;
3335 Bool_t headerTag = false;
3336 Bool_t dataTag = false;
3337 Double_t x, y, ey;
3338 PDoubleVector xVec, exVec, yVec, eyVec;
3339
3340 while (!f.eof()) {
3341 f.getline(instr, sizeof(instr));
3342 line = TString(instr);
3343 lineNo++;
3344
3345 // check if comment line
3346 if (line.BeginsWith("#") || line.BeginsWith("%"))
3347 continue;
3348
3349 // check if header tag
3350 workStr = line;
3351 workStr.Remove(TString::kLeading, ' '); // remove spaces from the begining
3352 if (workStr.BeginsWith("header", TString::kIgnoreCase)) {
3353 headerTag = true;
3354 dataTag = false;
3355 continue;
3356 }
3357
3358 // check if data tag
3359 workStr = line;
3360 workStr.Remove(TString::kLeading, ' '); // remove spaces from the beining
3361 if (workStr.BeginsWith("data", TString::kIgnoreCase)) {
3362 headerTag = false;
3363 dataTag = true;
3364 continue;
3365 }
3366
3367 if (headerTag) {
3368 if (line.IsWhitespace()) // ignore empty lines
3369 continue;
3370 workStr = line;
3371 workStr.Remove(TString::kLeading, ' '); // remove spaces from the beining
3372 if (workStr.BeginsWith("title:", TString::kIgnoreCase)) {
3373 runData.SetRunTitle(TString(workStr.Data()+workStr.First(":")+2));
3374 } else if (workStr.BeginsWith("setup:", TString::kIgnoreCase)) {
3375 runData.SetSetup(TString(workStr.Data()+workStr.First(":")+2));
3376 } else if (workStr.BeginsWith("field:", TString::kIgnoreCase)) {
3377 workStr = TString(workStr.Data()+workStr.First(":")+2);
3378 if (!workStr.IsFloat()) {
3379 std::cerr << std::endl << ">> PRunDataHandler::ReadAsciiFile **ERROR** line no " << lineNo << ", field is not a number.";
3380 std::cerr << std::endl;
3381 success = false;
3382 break;
3383 }
3384 runData.SetField(workStr.Atof());
3385 } else if (workStr.BeginsWith("x-axis-title:", TString::kIgnoreCase)) {
3386 runData.fDataNonMusr.SetLabel(0, TString(workStr.Data()+workStr.First(":")+2));
3387 } else if (workStr.BeginsWith("y-axis-title:", TString::kIgnoreCase)) {
3388 runData.fDataNonMusr.SetLabel(1, TString(workStr.Data()+workStr.First(":")+2));
3389 } else if (workStr.BeginsWith("temp:", TString::kIgnoreCase)) {
3390 workStr = TString(workStr.Data()+workStr.First(":")+2);
3391 if (!workStr.IsFloat()) {
3392 std::cerr << std::endl << ">> PRunDataHandler::ReadAsciiFile **ERROR** line no " << lineNo << ", temperature is not a number.";
3393 std::cerr << std::endl;
3394 success = false;
3395 break;
3396 }
3397 runData.SetTemperature(0, workStr.Atof(), 0.0);
3398 } else if (workStr.BeginsWith("energy:", TString::kIgnoreCase)) {
3399 workStr = TString(workStr.Data()+workStr.First(":")+2);
3400 if (!workStr.IsFloat()) {
3401 std::cerr << std::endl << ">> PRunDataHandler::ReadAsciiFile **ERROR** line no " << lineNo << ", energy is not a number.";
3402 std::cerr << std::endl;
3403 success = false;
3404 break;
3405 }
3406 runData.SetEnergy(workStr.Atof());
3407 runData.SetTransport(PMUSR_UNDEFINED); // just to initialize the variables to some "meaningful" value
3408 } else { // error
3409 std::cerr << std::endl << ">> PRunDataHandler::ReadAsciiFile **ERROR** line no " << lineNo << ", illegal header line.";
3410 std::cerr << std::endl;
3411 success = false;
3412 break;
3413 }
3414 } else if (dataTag) {
3415 if (line.IsWhitespace()) // ignore empty lines
3416 continue;
3417
3418 // Remove trailing end of line
3419 line.Remove(TString::kTrailing, '\r');
3420
3421 // check if data have x, y [, error y] structure, and that x, y, and error y are numbers
3422 std::vector<std::string> tokens = PStringUtils::Split(line.Data(), " ,\t");
3423 // check if the number of data line entries is 2 or 3
3424 if ((tokens.size() != 2) && (tokens.size() != 3)) {
3425 std::cerr << std::endl << ">> PRunDataHandler::ReadAsciiFile **ERROR** found data line with a structure different than \"x, y [, error y]\", cannot be handled (line no " << lineNo << ")";
3426 std::cerr << std::endl;
3427 success = false;
3428 break;
3429 }
3430
3431 // get x
3432 if (!TString(tokens[0]).IsFloat()) {
3433 std::cerr << std::endl << ">> PRunDataHandler::ReadAsciiFile **ERROR** line no " << lineNo << ": x = " << tokens[0] << " is not a number, sorry.";
3434 std::cerr << std::endl;
3435 success = false;
3436 break;
3437 }
3438 x = TString(tokens[0]).Atof();
3439
3440 // get y
3441 if (!TString(tokens[1]).IsFloat()) {
3442 std::cerr << std::endl << ">> PRunDataHandler::ReadAsciiFile **ERROR** line no " << lineNo << ": y = " << tokens[1] << " is not a number, sorry.";
3443 std::cerr << std::endl;
3444 success = false;
3445 break;
3446 }
3447 y = TString(tokens[1]).Atof();
3448
3449 // get error y if present
3450 if (tokens.size() == 3) {
3451 if (!TString(tokens[2]).IsFloat()) {
3452 std::cerr << std::endl << ">> PRunDataHandler::ReadAsciiFile **ERROR** line no " << lineNo << ": error y = " << tokens[2] << " is not a number, sorry.";
3453 std::cerr << std::endl;
3454 success = false;
3455 break;
3456 }
3457 ey = TString(tokens[2]).Atof();
3458 if (ey == 0) {
3459 std::cerr << std::endl << ">> PRunDataHandler::ReadAsciiFile **WARNING** line no " << lineNo << ": error y = 0 which doesn't make sense. Will set it to 1.0. Please check!!";
3460 std::cerr << std::endl;
3461 ey = 1.0;
3462 }
3463 } else {
3464 std::cerr << std::endl << ">> PRunDataHandler::ReadAsciiFile **WARNING** line no " << lineNo << ": error y = 0 which doesn't make sense. Will set it to 1.0. Please check!!";
3465 std::cerr << std::endl;
3466 ey = 1.0;
3467 }
3468
3469 // keep values
3470 xVec.push_back(x);
3471 exVec.push_back(1.0);
3472 yVec.push_back(y);
3473 eyVec.push_back(ey);
3474
3475 } else {
3476 std::cerr << std::endl << ">> PRunDataHandler::ReadAsciiFile **ERROR** line no " << lineNo << " neither header nor data line. No idea how to handle it!";
3477 std::cerr << std::endl;
3478 success = false;
3479 break;
3480 }
3481 }
3482
3483 f.close();
3484
3485 // keep values
3486 runData.fDataNonMusr.AppendData(xVec);
3487 runData.fDataNonMusr.AppendErrData(exVec);
3488 runData.fDataNonMusr.AppendData(yVec);
3489 runData.fDataNonMusr.AppendErrData(eyVec);
3490
3491 fData.push_back(runData);
3492
3493 // clean up
3494 xVec.clear();
3495 exVec.clear();
3496 yVec.clear();
3497 eyVec.clear();
3498
3499 return success;
3500}
3501
3502//--------------------------------------------------------------------------
3503// ReadDBFile (private)
3504//--------------------------------------------------------------------------
3616{
3617 Bool_t success = true;
3618
3619 // open file
3620 std::ifstream f;
3621
3622 // open db-file
3623 f.open(fRunPathName.Data(), std::ifstream::in);
3624 if (!f.is_open()) {
3625 std::cerr << std::endl << ">> PRunDataHandler::ReadDBFile **ERROR** Couldn't open data file (" << fRunPathName.Data() << ") for reading, sorry ...";
3626 std::cerr << std::endl;
3627 return false;
3628 }
3629
3630 PRawRunData runData;
3631
3632 runData.fDataNonMusr.SetFromAscii(false);
3633
3634 Int_t lineNo = 0;
3635 Int_t idx;
3636 Int_t dbTag = -1;
3637 Char_t instr[512];
3638 TString line, workStr;
3639 Double_t val;
3640 Bool_t firstData = true; // needed as a switch to check in which format the data are given.
3641 Bool_t labelledFormat = true; // flag showing if the data are given in row format, or as labelled format (see description above, default is labelled format)
3642 Bool_t dataTagsRead = false; // flag showing if the data tags are alread read
3643
3644 // variables needed to tokenize strings
3645 TString tstr;
3646 std::vector<std::string> tokens;
3647
3648 while (!f.eof()) {
3649 // get next line from file
3650 f.getline(instr, sizeof(instr));
3651 line = TString(instr);
3652 lineNo++;
3653
3654 // check if comment line
3655 if (line.BeginsWith("#") || line.BeginsWith("%"))
3656 continue;
3657
3658 // ignore empty lines
3659 if (line.IsWhitespace())
3660 continue;
3661
3662 // check for db specific tags
3663 workStr = line;
3664 workStr.Remove(TString::kLeading, ' '); // remove spaces from the begining
3665 if (workStr.BeginsWith("title", TString::kIgnoreCase)) {
3666 dbTag = 0;
3667 continue;
3668 } else if (workStr.BeginsWith("abstract", TString::kIgnoreCase)) {
3669 dbTag = 1;
3670 continue;
3671 } else if (workStr.BeginsWith("comments", TString::kIgnoreCase)) {
3672 dbTag = 2;
3673 continue;
3674 } else if (workStr.BeginsWith("label", TString::kIgnoreCase)) {
3675 dbTag = 3;
3676 continue;
3677 } else if (workStr.BeginsWith("data", TString::kIgnoreCase) && !dataTagsRead) {
3678 dataTagsRead = true;
3679 dbTag = 4;
3680
3681 // filter out all data tags
3682 tokens = PStringUtils::Split(workStr.Data(), " ,\t");
3683 for (UInt_t i=1; i<tokens.size(); i++) {
3684 runData.fDataNonMusr.AppendDataTag(TString(tokens[i]));
3685 }
3686 continue;
3687 }
3688
3689 switch (dbTag) {
3690 case 0: // TITLE
3691 runData.SetRunTitle(workStr);
3692 break;
3693 case 1: // ABSTRACT
3694 // nothing to be done for now
3695 break;
3696 case 2: // COMMENTS
3697 // nothing to be done for now
3698 break;
3699 case 3: // LABEL
3700 runData.fDataNonMusr.AppendLabel(workStr);
3701 break;
3702 case 4: // DATA
3703 // filter out potential start data tag
3704 if (workStr.BeginsWith("\\-e", TString::kIgnoreCase) ||
3705 workStr.BeginsWith("\\e", TString::kIgnoreCase) ||
3706 workStr.BeginsWith("/-e", TString::kIgnoreCase) ||
3707 workStr.BeginsWith("/e", TString::kIgnoreCase)) {
3708 continue;
3709 }
3710
3711 // check if first real data line
3712 if (firstData) {
3713 // check if data are given just as rows are as labelled columns (see description above)
3714 tokens = PStringUtils::Split(workStr.Data(), ",");
3715 if (!TString(tokens[0]).IsFloat()) {
3716 labelledFormat = true;
3717 } else {
3718 labelledFormat = false;
3719 }
3720
3721 // prepare data vector for use
3722 PDoubleVector dummy;
3723 for (UInt_t i=0; i<runData.fDataNonMusr.GetDataTags()->size(); i++) {
3724 runData.fDataNonMusr.AppendData(dummy);
3725 runData.fDataNonMusr.AppendErrData(dummy);
3726 }
3727
3728 firstData = false;
3729 }
3730
3731 if (labelledFormat) { // handle labelled formated data
3732 // check if run line
3733 const Char_t *str = workStr.Data();
3734 if (isdigit(str[0])) { // run line
3735 TString run("run");
3736 idx = GetDataTagIndex(run, runData.fDataNonMusr.GetDataTags());
3737 if (idx == -1) {
3738 std::cerr << std::endl << ">> PRunDataHandler::ReadDBFile **ERROR** in line no " << lineNo << ":";
3739 std::cerr << std::endl << ">> " << workStr.Data();
3740 std::cerr << std::endl << ">> found potential run data line without run data tag.";
3741 return false;
3742 }
3743 // split string in tokens
3744 tokens = PStringUtils::Split(workStr.Data(), ","); // line has structure: runNo,,, runTitle
3745 tstr = TString(tokens[0]);
3746 if (!tstr.IsFloat()) {
3747 std::cerr << std::endl << ">> PRunDataHandler::ReadDBFile **ERROR** in line no " << lineNo << ":";
3748 std::cerr << std::endl << ">> " << workStr.Data();
3749 std::cerr << std::endl << ">> Expected db-data line with structure: runNo,,, runTitle";
3750 std::cerr << std::endl << ">> runNo = " << tstr.Data() << ", seems to be not a number.";
3751 return false;
3752 }
3753 val = tstr.Atof();
3754 runData.fDataNonMusr.AppendSubData(idx, val);
3755 runData.fDataNonMusr.AppendSubErrData(idx, 1.0);
3756 } else { // tag = data line
3757 // remove all possible spaces
3758 workStr.ReplaceAll(" ", "");
3759 // split string in tokens
3760 tokens = PStringUtils::Split(workStr.Data(), "=,"); // line has structure: tag = val,err1,err2,
3761 if (tokens.size() < 3) {
3762 std::cerr << std::endl << ">> PRunDataHandler::ReadDBFile **ERROR** in line no " << lineNo << ":";
3763 std::cerr << std::endl << ">> " << workStr.Data();
3764 std::cerr << std::endl << ">> Expected db-data line with structure: tag = val,err1,err2,\\";
3765 return false;
3766 }
3767 tstr = TString(tokens[0]);
3768 idx = GetDataTagIndex(tstr, runData.fDataNonMusr.GetDataTags());
3769 if (idx == -1) {
3770 std::cerr << std::endl << ">> PRunDataHandler::ReadDBFile **ERROR** in line no " << lineNo << ":";
3771 std::cerr << std::endl << ">> " << workStr.Data();
3772 std::cerr << std::endl << ">> data tag error: " << tstr.Data() << " seems not present in the data tag list";
3773 return false;
3774 }
3775
3776 switch (tokens.size()) {
3777 case 3: // tag = val,,,
3778 tstr = TString(tokens[1]);
3779 if (!tstr.IsFloat()) {
3780 std::cerr << std::endl << ">> PRunDataHandler::ReadDBFile **ERROR** in line no " << lineNo << ":";
3781 std::cerr << std::endl << ">> " << workStr.Data();
3782 std::cerr << std::endl << ">> Expected db-data line with structure: tag = val,err1,err2,\\";
3783 std::cerr << std::endl << ">> val = " << tstr.Data() << ", seems to be not a number.";
3784 return false;
3785 }
3786 val = tstr.Atof();
3787 runData.fDataNonMusr.AppendSubData(idx, val);
3788 runData.fDataNonMusr.AppendSubErrData(idx, 1.0);
3789 break;
3790 case 4: // tag = val,err,,
3791 case 5: // tag = val,err1,err2,
3792 // handle val
3793 tstr = TString(tokens[1]);
3794 if (!tstr.IsFloat()) {
3795 std::cerr << std::endl << ">> PRunDataHandler::ReadDBFile **ERROR** in line no " << lineNo << ":";
3796 std::cerr << std::endl << ">> " << workStr.Data();
3797 std::cerr << std::endl << ">> Expected db-data line with structure: tag = val,err1,err2,\\";
3798 std::cerr << std::endl << ">> val = " << tstr.Data() << ", seems to be not a number.";
3799 return false;
3800 }
3801 val = tstr.Atof();
3802 runData.fDataNonMusr.AppendSubData(idx, val);
3803 // handle err1 (err2 will be ignored for the time being)
3804 tstr = TString(tokens[2]);
3805 if (!tstr.IsFloat()) {
3806 std::cerr << std::endl << ">> PRunDataHandler::ReadDBFile **ERROR** in line no " << lineNo << ":";
3807 std::cerr << std::endl << ">> " << workStr.Data();
3808 std::cerr << std::endl << ">> Expected db-data line with structure: tag = val,err1,err2,\\";
3809 std::cerr << std::endl << ">> err1 = " << tstr.Data() << ", seems to be not a number.";
3810 return false;
3811 }
3812 val = tstr.Atof();
3813 runData.fDataNonMusr.AppendSubErrData(idx, val);
3814 break;
3815 default:
3816 std::cerr << std::endl << ">> PRunDataHandler::ReadDBFile **ERROR** in line no " << lineNo << ":";
3817 std::cerr << std::endl << ">> " << workStr.Data();
3818 std::cerr << std::endl << ">> Expected db-data line with structure: tag = val,err1,err2,\\";
3819 return false;
3820 }
3821 }
3822
3823 } else { // handle row formated data
3824 // split string in tokens
3825 tokens = PStringUtils::Split(workStr.Data(), ","); // line has structure: val1, err11, err12, ..., valn, errn1, errn2, runNo, , , , runTitle
3826 if (tokens.size() != 3*runData.fDataNonMusr.GetDataTags()->size()+1) {
3827 std::cerr << std::endl << ">> PRunDataHandler::ReadDBFile **ERROR** in line no " << lineNo << ":";
3828 std::cerr << std::endl << ">> " << workStr.Data();
3829 std::cerr << std::endl << ">> Expected db-data line with structure: val1, err11, err12, ..., valn, errn1, errn2, runNo, , , , runTitle";
3830 std::cerr << std::endl << ">> found = " << tokens.size() << " tokens, however expected " << 3*runData.fDataNonMusr.GetDataTags()->size()+1;
3831 std::cerr << std::endl << ">> Perhaps there are commas without space inbetween, like 12.3,, 3.2,...";
3832 return false;
3833 }
3834 // extract data
3835 Int_t j=0;
3836 for (UInt_t i=0; i+1<tokens.size(); i+=3) {
3837 // handle value
3838 tstr = TString(tokens[i]);
3839 if (!tstr.IsFloat()) {
3840 std::cerr << std::endl << ">> PRunDataHandler::ReadDBFile **ERROR** in line no " << lineNo << ":";
3841 std::cerr << std::endl << ">> " << workStr.Data();
3842 std::cerr << std::endl << ">> Expected db-data line with structure: val1, err11, err12, ..., valn, errn1, errn2, runNo, , , , runTitle";
3843 std::cerr << std::endl << ">> value=" << tstr.Data() << " seems not to be a number";
3844 return false;
3845 }
3846 runData.fDataNonMusr.AppendSubData(j, tstr.Atof());
3847
3848 // handle 1st error if present (2nd will be ignored for now)
3849 tstr = TString(tokens[i+1]);
3850 if (tstr.IsWhitespace()) {
3851 runData.fDataNonMusr.AppendSubErrData(j, 1.0);
3852 } else if (tstr.IsFloat()) {
3853 runData.fDataNonMusr.AppendSubErrData(j, tstr.Atof());
3854 } else {
3855 std::cerr << std::endl << ">> PRunDataHandler::ReadDBFile **ERROR** in line no " << lineNo << ":";
3856 std::cerr << std::endl << ">> " << workStr.Data();
3857 std::cerr << std::endl << ">> Expected db-data line with structure: val1, err11, err12, ..., valn, errn1, errn2, runNo, , , , runTitle";
3858 std::cerr << std::endl << ">> error1=" << tstr.Data() << " seems not to be a number";
3859 return false;
3860 }
3861 j++;
3862 }
3863 }
3864 break;
3865 default:
3866 break;
3867 }
3868 }
3869
3870 f.close();
3871
3872 // check that the number of labels == the number of data tags
3873 if (runData.fDataNonMusr.GetLabels()->size() != runData.fDataNonMusr.GetDataTags()->size()) {
3874 std::cerr << std::endl << ">> PRunDataHandler::ReadDBFile **ERROR**";
3875 std::cerr << std::endl << ">> number of LABELS found = " << runData.fDataNonMusr.GetLabels()->size();
3876 std::cerr << std::endl << ">> number of Data tags found = " << runData.fDataNonMusr.GetDataTags()->size();
3877 std::cerr << std::endl << ">> They have to be equal!!";
3878 return false;
3879 }
3880
3881 // check if all vectors have the same size
3882 for (UInt_t i=1; i<runData.fDataNonMusr.GetData()->size(); i++) {
3883 if (runData.fDataNonMusr.GetData()->at(i).size() != runData.fDataNonMusr.GetData()->at(i-1).size()) {
3884 std::cerr << std::endl << ">> PRunDataHandler::ReadDBFile **ERROR** in line no " << lineNo;
3885 std::cerr << std::endl << ">> label: " << runData.fDataNonMusr.GetDataTags()->at(i-1).Data() << ", number data elements = " << runData.fDataNonMusr.GetData()->at(i-1).size();
3886 std::cerr << std::endl << ">> label: " << runData.fDataNonMusr.GetDataTags()->at(i).Data() << ", number data elements = " << runData.fDataNonMusr.GetData()->at(i).size();
3887 std::cerr << std::endl << ">> They have to be equal!!";
3888 success = false;
3889 break;
3890 }
3891 if (runData.fDataNonMusr.GetErrData()->at(i).size() != runData.fDataNonMusr.GetErrData()->at(i-1).size()) {
3892 std::cerr << std::endl << ">> PRunDataHandler::ReadDBFile **ERROR** in line no " << lineNo;
3893 std::cerr << std::endl << ">> label: " << runData.fDataNonMusr.GetDataTags()->at(i-1).Data() << ", number data elements = " << runData.fDataNonMusr.GetData()->at(i-1).size();
3894 std::cerr << std::endl << ">> label: " << runData.fDataNonMusr.GetDataTags()->at(i).Data() << ", number error data elements = " << runData.fDataNonMusr.GetErrData()->at(i).size();
3895 std::cerr << std::endl << ">> They have to be equal!!";
3896 success = false;
3897 break;
3898 }
3899 }
3900
3901 // keep run name
3902 runData.SetRunName(fRunName);
3903
3904 fData.push_back(runData);
3905
3906 return success;
3907}
3908
3909//--------------------------------------------------------------------------
3910// ReadDatFile (private)
3911//--------------------------------------------------------------------------
3921{
3922 Bool_t success = true;
3923
3924 // open file
3925 std::ifstream f;
3926
3927 // open dat-file
3928 f.open(fRunPathName.Data(), std::ifstream::in);
3929 if (!f.is_open()) {
3930 std::cerr << std::endl << ">> PRunDataHandler::ReadDatFile **ERROR** Couldn't open data file (" << fRunPathName.Data() << ") for reading, sorry ...";
3931 std::cerr << std::endl;
3932 return false;
3933 }
3934
3935 PRawRunData runData;
3936 runData.fDataNonMusr.SetFromAscii(false);
3937
3938 Int_t lineNo = 0;
3939 Char_t instr[4096];
3940 TString line;
3941 Bool_t headerInfo=true;
3942
3943 // variables needed to tokenize strings
3944 TString tstr;
3945 std::vector<std::string> tokens;
3946
3947 UInt_t noOfDataSets = 0, noOfEntries = 0;
3948 PBoolVector isData;
3949 Double_t dval;
3950
3951 while (!f.eof()) {
3952 // get next line from file
3953 f.getline(instr, sizeof(instr));
3954 line = TString(instr);
3955 lineNo++;
3956
3957 // check if comment line
3958 if (line.BeginsWith("#") || line.BeginsWith("%"))
3959 continue;
3960
3961 // ignore empty lines
3962 if (line.IsWhitespace())
3963 continue;
3964
3965 tokens = PStringUtils::Split(line.Data(), " \t");
3966 if (tokens.empty()) { // error
3967 std::cerr << std::endl << ">> PRunDataHandler::ReadDatFile **ERROR** couldn't tokenize the line, in lineNo: " << lineNo;
3968 std::cerr << std::endl << ">> line: '" << line << "'.";
3969 std::cerr << std::endl;
3970 return false;
3971 }
3972
3973 // filter header information
3974 if (headerInfo) {
3975 headerInfo = false;
3976
3977 // filter out all data tags: this labels are used in the msr-file to select the proper data set
3978 // for the dat-files, label and dataTag are the same
3979 noOfEntries = tokens.size();
3980 for (UInt_t i=0; i<noOfEntries; i++) {
3981 tstr = TString(tokens[i]);
3982 if (!tstr.EndsWith("Err", TString::kExact)) {
3983 noOfDataSets++;
3984 isData.push_back(true);
3985 runData.fDataNonMusr.AppendDataTag(tstr);
3986 runData.fDataNonMusr.AppendLabel(tstr);
3987 } else {
3988 isData.push_back(false);
3989 }
3990 }
3991 // set the size for the data
3992 runData.fDataNonMusr.SetSize(noOfDataSets);
3993 } else { // deal with data
3994 if (noOfEntries == 0) {
3995 std::cerr << std::endl << ">> PRunDataHandler::ReadDatFile **ERROR** header information is missing.";
3996 std::cerr << std::endl;
3997 return false;
3998 }
3999 if (tokens.size() != noOfEntries) { // error
4000 std::cerr << std::endl << ">> PRunDataHandler::ReadDatFile **ERROR** data set with wrong number of entries: " << tokens.size() << ", should be " << noOfEntries << ".";
4001 std::cerr << std::endl << ">> in line: " << lineNo;
4002 std::cerr << std::endl << ">> line: '" << line << "'.";
4003 std::cerr << std::endl;
4004 return false;
4005 }
4006 // fill data and dataErr sets
4007 UInt_t idx = 0;
4008 for (UInt_t i=0; i<noOfEntries; i++) {
4009 // 1st: check that entry is indeed a number
4010 tstr = TString(tokens[i]);
4011 if (!tstr.IsFloat()) { // make sure it is a number
4012 std::cerr << std::endl << ">> PRunDataHandler::ReadDatFile **ERROR** data set entry is not a number: " << tstr.Data();
4013 std::cerr << std::endl << ">> in line: " << lineNo;
4014 std::cerr << std::endl;
4015 return false;
4016 }
4017 dval = tstr.Atof();
4018 if (isData[i]) {
4019 runData.fDataNonMusr.AppendSubData(idx, dval);
4020 idx++;
4021 } else { // error value
4022 if (isData[i-1] == 1) { // Err or PosErr hence keep it
4023 if (dval == 0.0) {
4024 std::cout << std::endl << ">> PRunDataHandler::ReadDatFile **WARNING** found Err value = 0. Doesn't make sense! Will set it to 1. Please check!";
4025 std::cerr << std::endl << ">> in line: " << lineNo;
4026 std::cerr << std::endl;
4027 dval = 1.0;
4028 }
4029 runData.fDataNonMusr.AppendSubErrData(idx-1, dval);
4030 }
4031 }
4032 }
4033 }
4034 }
4035
4036 f.close();
4037
4038 // got through all the data sets and if there is NO error vector set it to '1.0'
4039 for (UInt_t i=0; i<noOfDataSets; i++) {
4040 if (runData.fDataNonMusr.GetErrData()->at(i).size() == 0) {
4041 for (UInt_t j=0; j<runData.fDataNonMusr.GetData()->at(i).size(); j++) {
4042 runData.fDataNonMusr.AppendSubErrData(i, 1.0);
4043 }
4044 }
4045 }
4046
4047 // keep run name
4048 runData.SetRunName(fRunName);
4049
4050 fData.push_back(runData);
4051
4052 return success;
4053}
4054
4055//--------------------------------------------------------------------------
4056// WriteMusrRootFile (private)
4057//--------------------------------------------------------------------------
4066Bool_t PRunDataHandler::WriteMusrRootFile(Int_t tag, TString fln)
4067{
4068 Bool_t ok = false;
4069 fln = GenerateOutputFileName(fln, ".root", ok);
4070 if (!ok)
4071 return false;
4072
4073 if (!fAny2ManyInfo->useStandardOutput)
4074 std::cout << std::endl << ">> PRunDataHandler::WriteMusrRootFile(): writing a root data file (" << fln.Data() << ") ... " << std::endl;
4075
4076 // write file
4077 std::unique_ptr<TFile> fout = std::make_unique<TFile>(fln, "RECREATE", fln);
4078 if (fout == nullptr) {
4079 std::cerr << std::endl << "PRunDataHandler::WriteMusrRootFile(): **ERROR** Couldn't create ROOT file '" << fln << "'" << std::endl;
4080 return false;
4081 }
4082 fout->cd();
4083
4084 // generate data file
4085 std::unique_ptr<TMusrRunHeader> header = std::make_unique<TMusrRunHeader>(true);
4086 TFolder *histosFolder, *decayAnaModule, *runHeader;
4087 TDirectory *histosDir, *decayAnaDir, *runHeaderDir;
4088 if (tag == A2M_MUSR_ROOT) { // TFolder
4089 histosFolder = new TFolder("histos", "Histograms");
4090 decayAnaModule = histosFolder->AddFolder("DecayAnaModule", "muSR decay histograms");
4091 runHeader = new TFolder("RunHeader", "MusrRoot Run Header Info");
4092 } else { // TDirectory
4093 histosDir = fout->mkdir("histos");
4094 decayAnaDir = histosDir->mkdir("decayAnaModule");
4095 runHeaderDir = fout->mkdir("RunHeader");
4096 }
4097
4098 // feed header info
4099 TString str, pathName;
4100 Int_t ival;
4101 Double_t dval[2];
4102 time_t start{0}, stop{0};
4103 Bool_t valid{false};
4105
4106 // feed RunInfo
4107 str = fData[0].GetGenericValidatorUrl()->Copy();
4108 header->Set("RunInfo/Generic Validator URL", str);
4109 str = fData[0].GetSpecificValidatorUrl()->Copy();
4110 header->Set("RunInfo/Specific Validator URL", str);
4111 str = fData[0].GetGenerator()->Copy();
4112 header->Set("RunInfo/Generator", str);
4113 str = fData[0].GetFileName()->Copy();
4114 header->Set("RunInfo/File Name", str);
4115 str = fData[0].GetRunTitle()->Copy();
4116 header->Set("RunInfo/Run Title", str);
4117 header->Set("RunInfo/Run Number", fData[0].GetRunNumber());
4118 str = fData[0].GetStartDate()->Copy() + " " + fData[0].GetStartTime()->Copy();
4119 header->Set("RunInfo/Run Start Time", str);
4120 str = fData[0].GetStopDate()->Copy() + " " + fData[0].GetStopTime()->Copy();
4121 header->Set("RunInfo/Run Stop Time", str);
4122 start = fData[0].CalcStartDateTime(valid);
4123 if (valid)
4124 stop = fData[0].CalcStopDateTime(valid);
4125 if (valid)
4126 ival = (int)stop - (int)start;
4127 prop.Set("Run Duration", ival, "sec");
4128 header->Set("RunInfo/Run Duration", prop);
4129 str = fData[0].GetLaboratory()->Copy();
4130 header->Set("RunInfo/Laboratory", str);
4131 str = fData[0].GetInstrument()->Copy();
4132 header->Set("RunInfo/Instrument", str);
4133 dval[0] = fData[0].GetMuonBeamMomentum();
4134 prop.Set("Muon Beam Momentum", dval[0], "MeV/c");
4135 header->Set("RunInfo/Muon Beam Momentum", prop);
4136 str = fData[0].GetMuonSpecies()->Copy();
4137 header->Set("RunInfo/Muon Species", str);
4138 str = fData[0].GetMuonSource()->Copy();
4139 header->Set("RunInfo/Muon Source", str);
4140 str = fData[0].GetSetup()->Copy();
4141 header->Set("RunInfo/Setup", str);
4142 str = fData[0].GetComment()->Copy();
4143 header->Set("RunInfo/Comment", str);
4144 str = fData[0].GetSample()->Copy();
4145 header->Set("RunInfo/Sample Name", str);
4146 dval[0] = fData[0].GetTemperature(0);
4147 dval[1] = fData[0].GetTempError(0);
4148 prop.Set("Sample Temperature", MRH_UNDEFINED, dval[0], dval[1], "K");
4149 header->Set("RunInfo/Sample Temperature", prop);
4150 dval[0] = fData[0].GetField();
4151 prop.Set("Sample Magnetic Field", dval[0], "G");
4152 header->Set("RunInfo/Sample Magnetic Field", prop);
4153 header->Set("RunInfo/No of Histos", static_cast<Int_t>(fData[0].GetNoOfHistos()));
4154 dval[0] = fData[0].GetTimeResolution();
4155 prop.Set("Time Resolution", dval[0], "ns");
4156 header->Set("RunInfo/Time Resolution", prop);
4157 header->Set("RunInfo/RedGreen Offsets", fData[0].GetRedGreenOffset());
4158
4159 // feed DetectorInfo
4160 Int_t histoNo = 0;
4161 PRawRunDataSet *dataSet;
4162 UInt_t size = fData[0].GetNoOfHistos();
4163 for (UInt_t i=0; i<size; i++) {
4164 dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
4165 if (dataSet == nullptr) { // something is really wrong
4166 std::cerr << std::endl << ">> PRunDataHandler::WriteMusrRootFile: **ERROR** Couldn't get data set (idx=" << i << ")";
4167 std::cerr << std::endl << ">> something is really wrong!" << std::endl;
4168 return false;
4169 }
4170 histoNo = dataSet->GetHistoNo();
4171 pathName.Form("DetectorInfo/Detector%03d/Name", histoNo);
4172 str = dataSet->GetName();
4173 if (!str.CompareTo("n/a"))
4174 str.Form("Detector%3d", histoNo);
4175 header->Set(pathName, str);
4176 pathName.Form("DetectorInfo/Detector%03d/Histo Number", histoNo);
4177 header->Set(pathName, histoNo);
4178 pathName.Form("DetectorInfo/Detector%03d/Histo Length", histoNo);
4179 header->Set(pathName, static_cast<Int_t>(dataSet->GetData()->size()/fAny2ManyInfo->rebin));
4180 pathName.Form("DetectorInfo/Detector%03d/Time Zero Bin", histoNo);
4181 header->Set(pathName, dataSet->GetTimeZeroBin()/fAny2ManyInfo->rebin);
4182 pathName.Form("DetectorInfo/Detector%03d/First Good Bin", histoNo);
4183 ival = dataSet->GetFirstGoodBin();
4184 header->Set(pathName, static_cast<Int_t>(ival/fAny2ManyInfo->rebin));
4185 pathName.Form("DetectorInfo/Detector%03d/Last Good Bin", histoNo);
4186 ival = dataSet->GetLastGoodBin();
4187 header->Set(pathName, static_cast<Int_t>(ival/fAny2ManyInfo->rebin));
4188 }
4189
4190 // feed SampleEnvironmentInfo
4191 str = fData[0].GetCryoName()->Copy();
4192 header->Set("SampleEnvironmentInfo/Cryo", str);
4193
4194 // feed MagneticFieldEnvironmentInfo
4195 str = fData[0].GetMagnetName()->Copy();
4196 header->Set("MagneticFieldEnvironmentInfo/Magnet Name", str);
4197
4198 // feed BeamlineInfo
4199 str = fData[0].GetBeamline()->Copy();
4200 header->Set("BeamlineInfo/Name", str);
4201
4202 // feed histos
4203 std::vector<TH1F*> histos;
4204 TH1F *histo = nullptr;
4205 UInt_t length = 0;
4206 if (fAny2ManyInfo->rebin == 1) {
4207 for (UInt_t i=0; i<size; i++) {
4208 dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
4209 if (dataSet == nullptr) { // something is really wrong
4210 std::cerr << std::endl << ">> PRunDataHandler::WriteMusrRootFile: **ERROR** Couldn't get data set (idx=" << i << ")";
4211 std::cerr << std::endl << ">> something is really wrong!" << std::endl;
4212 return false;
4213 }
4214 str.Form("hDecay%03d", dataSet->GetHistoNo());
4215 length = dataSet->GetData()->size();
4216 histo = new TH1F(str.Data(), str.Data(), length+1, -0.5, static_cast<Double_t>(length)+0.5);
4217 Int_t sum=0, entries=0;
4218 for (UInt_t j=0; j<length; j++) {
4219 entries = dataSet->GetData()->at(j);
4220 histo->SetBinContent(j+1, entries);
4221 sum += entries;
4222 }
4223 histo->SetEntries(sum);
4224 histos.push_back(histo);
4225 }
4226 } else { // rebin > 1
4227 UInt_t dataRebin = 0;
4228 UInt_t dataCount = 0;
4229 for (UInt_t i=0; i<size; i++) {
4230 dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
4231 if (dataSet == nullptr) { // something is really wrong
4232 std::cerr << std::endl << ">> PRunDataHandler::WriteMusrRootFile: **ERROR** Couldn't get data set (idx=" << i << ")";
4233 std::cerr << std::endl << ">> something is really wrong!" << std::endl;
4234 return false;
4235 }
4236 str.Form("hDecay%03d", dataSet->GetHistoNo());
4237 length = dataSet->GetData()->size();
4238 histo = new TH1F(str.Data(), str.Data(), static_cast<Int_t>(length/fAny2ManyInfo->rebin)+1, -0.5, static_cast<Double_t>(static_cast<Int_t>(length/fAny2ManyInfo->rebin))+0.5);
4239 dataCount = 0;
4240 Int_t sum=0, entries=0;
4241 for (UInt_t j=0; j<length; j++) {
4242 if ((j > 0) && (j % fAny2ManyInfo->rebin == 0)) {
4243 dataCount++;
4244 histo->SetBinContent(dataCount, dataRebin);
4245 dataRebin = 0;
4246 }
4247 entries = dataSet->GetData()->at(j);
4248 sum += entries;
4249 dataRebin += static_cast<UInt_t>(entries);
4250 }
4251 histo->SetEntries(sum);
4252 histos.push_back(histo);
4253 }
4254 }
4255
4256 if (tag == A2M_MUSR_ROOT) { // TFolder
4257 // add histos to the DecayAnaModule folder
4258 for (UInt_t i=0; i<histos.size(); i++)
4259 decayAnaModule->Add(histos[i]);
4260 } else { // TDirectory
4261 // add histos to the DecayAnaModule directory
4262 for (UInt_t i=0; i<histos.size(); i++)
4263 decayAnaDir->Add(histos[i]);
4264 }
4265
4266 if (tag == A2M_MUSR_ROOT) { // TFolder
4267 if (header->FillFolder(runHeader))
4268 runHeader->Write();
4269 histosFolder->Write();
4270 } else { // TDirectory
4271 if (header->FillDirectory(runHeaderDir)) {
4272 runHeaderDir->Write();
4273 }
4274 histosDir->Write();
4275 }
4276 fout->Close();
4277
4278 // check if root file shall be streamed to stdout
4279 if (fAny2ManyInfo->useStandardOutput && (fAny2ManyInfo->compressionTag == 0)) {
4280 // stream file to stdout
4281 std::ifstream is;
4282 int length=1024;
4283 char *buffer;
4284
4285 is.open(fln.Data(), std::ios::binary);
4286 if (!is.is_open()) {
4287 std::cerr << std::endl << "PRunDataHandler::WriteMusrRootFile(): **ERROR** Couldn't open the root-file for streaming." << std::endl;
4288 remove(fln.Data());
4289 return false;
4290 }
4291
4292 // get length of file
4293 is.seekg(0, std::ios::end);
4294 length = is.tellg();
4295 is.seekg(0, std::ios::beg);
4296
4297 if (length == -1) {
4298 std::cerr << std::endl << "PRunDataHandler::WriteMusrRootFile(): **ERROR** Couldn't determine the root-file size." << std::endl;
4299 remove(fln.Data());
4300 return false;
4301 }
4302
4303 // allocate memory
4304 buffer = new char [length];
4305
4306 // read data as a block
4307 while (!is.eof()) {
4308 is.read(buffer, length);
4309 std::cout.write(buffer, length);
4310 }
4311
4312 is.close();
4313
4314 delete [] buffer;
4315
4316 // delete temporary root file
4317 remove(fln.Data());
4318 }
4319
4320 return true;
4321}
4322
4323//--------------------------------------------------------------------------
4324// WriteRootFile (private)
4325//--------------------------------------------------------------------------
4336{
4337 Bool_t ok = false;
4338 fln = GenerateOutputFileName(fln, ".root", ok);
4339 if (!ok)
4340 return false;
4341
4342
4343 if (!fAny2ManyInfo->useStandardOutput)
4344 std::cout << std::endl << ">> PRunDataHandler::WriteRootFile(): writing a root data file (" << fln.Data() << ") ... " << std::endl;
4345
4346 // generate data file
4347 TFolder *histosFolder;
4348 TFolder *decayAnaModule;
4349 TFolder *runInfo;
4350
4351 histosFolder = gROOT->GetRootFolder()->AddFolder("histos", "Histograms");
4352 gROOT->GetListOfBrowsables()->Add(histosFolder, "histos");
4353 decayAnaModule = histosFolder->AddFolder("DecayAnaModule", "muSR decay histograms");
4354
4355 runInfo = gROOT->GetRootFolder()->AddFolder("RunInfo", "LEM RunInfo");
4356 gROOT->GetListOfBrowsables()->Add(runInfo, "RunInfo");
4357 std::unique_ptr<TLemRunHeader> header = std::make_unique<TLemRunHeader>();
4358 gROOT->GetListOfBrowsables()->Add(runInfo, "RunInfo");
4359
4360 // feed header info
4361 header->SetRunTitle(fData[0].GetRunTitle()->Data());
4362 header->SetLemSetup(fData[0].GetSetup()->Data());
4363 header->SetRunNumber(fData[0].GetRunNumber());
4364 TString dt = *fData[0].GetStartDate() + "/" + *fData[0].GetStartTime();
4365 header->SetStartTimeString(dt.Data());
4366 dt = *fData[0].GetStopDate() + "/" + *fData[0].GetStopTime();
4367 header->SetStopTimeString(dt.Data());
4368 header->SetStartTime(fData[0].GetStartDateTime());
4369 header->SetStopTime(fData[0].GetStopDateTime());
4370 header->SetModeratorHV(-999.9, 0.0);
4371 header->SetSampleHV(-999.9, 0.0);
4372 header->SetImpEnergy(-999.9);
4373 header->SetSampleTemperature(fData[0].GetTemperature(0), fData[0].GetTempError(0));
4374 header->SetSampleBField(fData[0].GetField(), 0.0);
4375 header->SetTimeResolution(fData[0].GetTimeResolution());
4376 PRawRunDataSet *dataSet = fData[0].GetDataSet(0, false); // i.e. the false means, that i is the index and NOT the histo number
4377 header->SetNChannels(static_cast<UInt_t>(dataSet->GetData()->size()/fAny2ManyInfo->rebin));
4378 header->SetNHist(fData[0].GetNoOfHistos());
4379 header->SetCuts("none");
4380 header->SetModerator("none");
4381
4382 // feed t0's if possible
4383 UInt_t NoT0s = fData[0].GetNoOfHistos();
4384 if (fData[0].GetNoOfHistos() > NHIST) {
4385 std::cerr << std::endl << ">> PRunDataHandler::WriteRootFile: **WARNING** found more T0's (" << NoT0s << ") than can be handled (" << NHIST << ").";
4386 std::cerr << std::endl << ">> Will only write the first " << NHIST << " T0s!!" << std::endl;
4387 NoT0s = NHIST;
4388 }
4389 Double_t *tt0 = new Double_t[NoT0s];
4390
4391 for (UInt_t i=0; i<NoT0s; i++) {
4392 dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
4393 tt0[i] = dataSet->GetTimeZeroBin()/fAny2ManyInfo->rebin;
4394 }
4395 header->SetTimeZero(tt0);
4396 runInfo->Add(header.get()); // add header to RunInfo folder
4397
4398 // feed histos
4399 std::vector<TH1F*> histos;
4400 TH1F *histo = nullptr;
4401 Char_t str[32];
4402 UInt_t size = 0;
4403 if (fAny2ManyInfo->rebin == 1) {
4404 for (UInt_t i=0; i<fData[0].GetNoOfHistos(); i++) {
4405 dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
4406 if (dataSet == nullptr) { // something is really wrong
4407 std::cerr << std::endl << ">> PRunDataHandler::WriteRootFile: **ERROR** Couldn't get data set (idx=0" << i << ")";
4408 std::cerr << std::endl << ">> something is really wrong!" << std::endl;
4409 return false;
4410 }
4411 size = dataSet->GetData()->size();
4412 snprintf(str, sizeof(str), "hDecay%02d", static_cast<Int_t>(i));
4413 histo = new TH1F(str, str, size+1, -0.5, static_cast<Double_t>(size)+0.5);
4414 for (UInt_t j=0; j<size; j++) {
4415 histo->SetBinContent(j+1, dataSet->GetData()->at(j));
4416 }
4417 histos.push_back(histo);
4418 }
4419 } else { // rebin > 1
4420 UInt_t dataRebin = 0;
4421 UInt_t dataCount = 0;
4422 for (UInt_t i=0; i<fData[0].GetNoOfHistos(); i++) {
4423 dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
4424 if (dataSet == nullptr) { // something is really wrong
4425 std::cerr << std::endl << ">> PRunDataHandler::WriteRootFile: **ERROR** Couldn't get data set (idx=0" << i << ")";
4426 std::cerr << std::endl << ">> something is really wrong!" << std::endl;
4427 return false;
4428 }
4429 size = dataSet->GetData()->size();
4430 snprintf(str, sizeof(str), "hDecay%02d", static_cast<Int_t>(i));
4431 histo = new TH1F(str, str, static_cast<UInt_t>(size/fAny2ManyInfo->rebin)+1, -0.5, static_cast<Double_t>(size)/static_cast<Double_t>(fAny2ManyInfo->rebin)+0.5);
4432 dataCount = 0;
4433 for (UInt_t j=0; j<size; j++) {
4434 if ((j > 0) && (j % fAny2ManyInfo->rebin == 0)) {
4435 dataCount++;
4436 histo->SetBinContent(dataCount, dataRebin);
4437 dataRebin = 0;
4438 }
4439 dataRebin += static_cast<UInt_t>(dataSet->GetData()->at(j));
4440 }
4441 histos.push_back(histo);
4442 }
4443 }
4444
4445 // add histos to the DecayAnaModule folder
4446 for (UInt_t i=0; i<histos.size(); i++)
4447 decayAnaModule->Add(histos[i]);
4448
4449 // write file
4450 std::unique_ptr<TFile> fout = std::make_unique<TFile>(fln, "RECREATE", fln);
4451 if (fout == nullptr) {
4452 std::cerr << std::endl << "PRunDataHandler::WriteRootFile(): **ERROR** Couldn't create ROOT file '" << fln << "'" << std::endl;
4453 return false;
4454 }
4455
4456 fout->cd();
4457 runInfo->Write();
4458 histosFolder->Write();
4459 fout->Close();
4460
4461 // clean up
4462 for (UInt_t i=0; i<histos.size(); i++) {
4463 delete histos[i];
4464 }
4465 histos.clear();
4466 delete [] tt0;
4467
4468 // check if root file shall be streamed to stdout
4469 if (fAny2ManyInfo->useStandardOutput && (fAny2ManyInfo->compressionTag == 0)) {
4470 // stream file to stdout
4471 std::ifstream is;
4472 int length=1024;
4473 char *buffer;
4474
4475 is.open(fln.Data(), std::ios::binary);
4476 if (!is.is_open()) {
4477 std::cerr << std::endl << "PRunDataHandler::WriteRootFile(): **ERROR** Couldn't open the root-file for streaming." << std::endl;
4478 remove(fln.Data());
4479 return false;
4480 }
4481
4482 // get length of file
4483 is.seekg(0, std::ios::end);
4484 length = is.tellg();
4485 is.seekg(0, std::ios::beg);
4486
4487 if (length == -1) {
4488 std::cerr << std::endl << "PRunDataHandler::WriteRootFile(): **ERROR** Couldn't determine the root-file size." << std::endl;
4489 remove(fln.Data());
4490 return false;
4491 }
4492
4493 // allocate memory
4494 buffer = new char [length];
4495
4496 // read data as a block
4497 while (!is.eof()) {
4498 is.read(buffer, length);
4499 std::cout.write(buffer, length);
4500 }
4501
4502 is.close();
4503
4504 delete [] buffer;
4505
4506 // delete temporary root file
4507 remove(fln.Data());
4508 }
4509
4510 return true;
4511}
4512
4513//--------------------------------------------------------------------------
4514// WriteNexusFile (private)
4515//--------------------------------------------------------------------------
4523Bool_t PRunDataHandler::WriteNexusFile(TString format, TString fln)
4524{
4525#ifdef PNEXUS_ENABLED
4526 std::string str{""};
4527 Bool_t ok = false;
4528 fln = GenerateOutputFileName(fln, ".nxs", ok);
4529 if (!ok)
4530 return false;
4531
4532 if (!fAny2ManyInfo->useStandardOutput)
4533 std::cout << std::endl << ">> PRunDataHandler::WriteNexusFile(): writing a NeXus data file (" << fln.Data() << ") ... " << std::endl;
4534
4535 if (format.Contains("HDF4", TString::kIgnoreCase)) { // HDF4
4536#ifdef HAVE_HDF4
4537 try {
4538 // create NeXus object
4539 std::unique_ptr<nxH4::PNeXus> nxs = std::make_unique<nxH4::PNeXus>();
4540 if (nxs == nullptr) {
4541 std::cerr << std::endl << ">> PRunDataHandler::WriteNexusFile(): **ERROR** couldn't invoke the NeXus object." << std::endl;
4542 return false;
4543 }
4544
4545 // set NeXus version
4546 nxs->AddGroupAttribute("/", "NeXus_version", std::string("4.3.0"));
4547
4548 // set HDF4 version
4549 nxs->AddGroupAttribute("/", "HDF_version", nxs->GetHdf4LibVersion());
4550
4551 // set file name
4552 nxs->AddGroupAttribute("/", "file_name", std::string(fln.Data()));
4553
4554 // set creation time
4555 std::string dt = nxs::getIso8601TimestampLocal();
4556 nxs->AddGroupAttribute("/", "file_time", dt);
4557
4558 if (fAny2ManyInfo->idf == 1) { // IDF V1
4559 // set IDF version
4560 nxs->AddDataset<int>("/run/IDF_version", {(int)fAny2ManyInfo->idf}, {1}, nxH4::H4DataType::kINT32);
4561
4562 // set program name
4563 nxs->AddDataset<std::string>("/run/program_name", {"any2many"}, {1}, nxH4::H4DataType::kCHAR8);
4564 str="n/a";
4565 #ifdef HAVE_CONFIG_H
4566 str = PACKAGE_VERSION;
4567 #endif
4568 nxs->AddDatasetAttribute<std::string>("/run/program_name", "version", str);
4569
4570 // set run number
4571 nxs->AddDataset<int>("/run/number", {fData[0].GetRunNumber()}, {1}, nxH4::H4DataType::kINT32);
4572
4573 // set title
4574 nxs->AddDataset<std::string>("/run/title", {fData[0].GetRunTitle()->Data()}, {1}, nxH4::H4DataType::kCHAR8);
4575
4576 // set notes
4577 nxs->AddDataset<std::string>("/run/notes", {std::string("n/a")}, {1}, nxH4::H4DataType::kCHAR8);
4578
4579 // set analysis
4580 nxs->AddDataset<std::string>("/run/analysis", {std::string("muonTD")}, {1}, nxH4::H4DataType::kCHAR8);
4581
4582 // set lab
4583 str = *fData[0].GetLaboratory();
4584 nxs->AddDataset<std::string>("/run/lab", {str}, {1}, nxH4::H4DataType::kCHAR8);
4585
4586 // set beamline
4587 str = *fData[0].GetBeamline();
4588 nxs->AddDataset<std::string>("/run/beamline", {str}, {1}, nxH4::H4DataType::kCHAR8);
4589
4590 // set start time
4591 str = std::string(fData[0].GetStartDate()->Data()) + std::string("T") + std::string(fData[0].GetStartTime()->Data());
4592 nxs->AddDataset<std::string>("/run/start_time", {str}, {1}, nxH4::H4DataType::kCHAR8);
4593
4594 // set stop time
4595 str = std::string(fData[0].GetStopDate()->Data()) + std::string("T") + std::string(fData[0].GetStopTime()->Data());
4596 nxs->AddDataset<std::string>("/run/stop_time", {str}, {1}, nxH4::H4DataType::kCHAR8);
4597
4598 // set switching state
4599 nxs->AddDataset<int>("/run/switching_states", {1}, {1}, nxH4::H4DataType::kINT32);
4600
4601 // set user name
4602 nxs->AddDataset<std::string>("/run/user/name", {std::string("n/a")}, {1}, nxH4::H4DataType::kCHAR8);
4603
4604 // set user experiment_number
4605 nxs->AddDataset<std::string>("/run/user/experiment_number", {std::string("n/a")}, {1}, nxH4::H4DataType::kCHAR8);
4606
4607 // set sample name
4608 nxs->AddDataset<std::string>("/run/sample/name", {fData[0].GetSample()->Data()}, {1}, nxH4::H4DataType::kCHAR8);
4609
4610 // set sample temperature
4611 nxs->AddDataset<float>("/run/sample/temperature", {(float)fData[0].GetTemperature(0)}, {1}, nxH4::H4DataType::kFLOAT32);
4612 nxs->AddDatasetAttribute<float>("/run/sample/temperature", "units", std::string("Kelvin"));
4613
4614 // set magnetic field
4615 nxs->AddDataset<float>("/run/sample/magnetic_field", {(float)fData[0].GetField()}, {1}, nxH4::H4DataType::kFLOAT32);
4616 nxs->AddDatasetAttribute<float>("/run/sample/magnetic_field", "units", std::string("Gauss"));
4617
4618 // set sample environment
4619 nxs->AddDataset<std::string>("/run/sample/environment", {fData[0].GetSetup()->Data()}, {1}, nxH4::H4DataType::kCHAR8);
4620
4621 // set sample shape
4622 nxs->AddDataset<std::string>("/run/sample/shape", {std::string("n/a")}, {1}, nxH4::H4DataType::kCHAR8);
4623
4624 // set magnetic field vector
4625 nxs->AddDataset<float>("/run/sample/magnetic_field_vector", {1.0f, 1.0f, 1.0f}, {3}, nxH4::H4DataType::kFLOAT32);
4626 nxs->AddDatasetAttribute<float>("/run/sample/magnetic_field_vector", "coordinate_system", std::string("cartesian"));
4627 nxs->AddDatasetAttribute<float>("/run/sample/magnetic_field_vector", "units", std::string("Gauss"));
4628 nxs->AddDatasetAttribute<float>("/run/sample/magnetic_field_vector", "available", 0);
4629
4630 // set instrument name
4631 str = *fData[0].GetInstrument();
4632 nxs->AddDataset<std::string>("/run/instrument/name", {str}, {1}, nxH4::H4DataType::kCHAR8);
4633
4634 // set instrument number of detectors
4635 nxs->AddDataset<int>("/run/instrument/detector/number", {(int)fData[0].GetNoOfHistos()}, {1}, nxH4::H4DataType::kINT32);
4636
4637 // set instrument collimator
4638 nxs->AddDataset<std::string>("/run/instrument/collimator/type", {std::string("n/a")}, {1}, nxH4::H4DataType::kCHAR8);
4639
4640 // set instrument beam total number of counts in Mev
4641 // calculate the total number of counts
4642 double total_counts = 0;
4643 PRawRunDataSet *dataSet = nullptr;
4644 for (unsigned int i=0; i<fData[0].GetNoOfHistos(); i++) {
4645 dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
4646 if (dataSet == nullptr) { // something is really wrong
4647 std::cerr << std::endl << ">> PRunDataHandler::WriteNexusFile: **ERROR** Couldn't get data set (idx=0" << i << ")";
4648 std::cerr << std::endl << ">> something is really wrong!" << std::endl;
4649 return false;
4650 }
4651 for (unsigned int j=0; j<dataSet->GetData()->size(); j++)
4652 total_counts += dataSet->GetData()->at(j);
4653 }
4654 float total_counts_mev = (float) total_counts / 1.0e6;
4655 nxs->AddDataset<float>("/run/instrument/beam/total_counts", {total_counts_mev}, {1}, nxH4::H4DataType::kFLOAT32);
4656 nxs->AddDatasetAttribute<float>("/run/instrument/beam/total_counts", "units", std::string("MEv"));
4657
4658 // set time resolution (use FLOAT instead of INT)
4659 float res = (float)(fData[0].GetTimeResolution()*fAny2ManyInfo->rebin*1.0e3);
4660 nxs->AddDataset<float>("/run/histogram_data_1/resolution", {res}, {1}, nxH4::H4DataType::kFLOAT32);
4661 nxs->AddDatasetAttribute<float>("/run/histogram_data_1/resolution", "units", std::string("picoseconds"));
4662
4663 // set time zero time to 0. see t0_bin attribute of counts!
4664 nxs->AddDataset<int>("/run/histogram_data_1/time_zero", {0}, {1}, nxH4::H4DataType::kINT32);
4665 nxs->AddDatasetAttribute<int>("/run/histogram_data_1/time_zero", "units", std::string("microseconds"));
4666 nxs->AddDatasetAttribute<int>("/run/histogram_data_1/time_zero", "available", 0);
4667
4668 // set raw_time
4669 res = (float)(fData[0].GetTimeResolution()*fAny2ManyInfo->rebin*1.0e-3);
4670 dataSet = fData[0].GetDataSet(0, false); // i.e. the false means, that i is the index and NOT the histo number
4671 unsigned int length = (int)(dataSet->GetData()->size() / fAny2ManyInfo->rebin);
4672 std::vector<float> time;
4673 for (unsigned int i=0; i<length; i++)
4674 time.push_back(((float)i+0.5)*res);
4675 nxs->AddDataset<float>("/run/histogram_data_1/raw_time", time, {length}, nxH4::H4DataType::kFLOAT32);
4676 nxs->AddDatasetAttribute<float>("/run/histogram_data_1/raw_time", "axis", 1);
4677 nxs->AddDatasetAttribute<float>("/run/histogram_data_1/raw_time", "primary", 0);
4678 nxs->AddDatasetAttribute<float>("/run/histogram_data_1/raw_time", "units", std::string("microseconds"));
4679 nxs->AddDatasetAttribute<float>("/run/histogram_data_1/raw_time", "available", 0);
4680
4681 // set corrected_time
4682 nxs->AddDataset<float>("/run/histogram_data_1/corrected_time", time, {length}, nxH4::H4DataType::kFLOAT32);
4683 nxs->AddDatasetAttribute<float>("/run/histogram_data_1/corrected_time", "axis", 1);
4684 nxs->AddDatasetAttribute<float>("/run/histogram_data_1/corrected_time", "units", std::string("microseconds"));
4685 nxs->AddDatasetAttribute<float>("/run/histogram_data_1/corrected_time", "available", 0);
4686
4687 // set grouping
4688 std::vector<int> grouping(fData[0].GetNoOfHistos(), 0);
4689 nxs->AddDataset<int>("/run/histogram_data_1/grouping", grouping, {(uint32_t)grouping.size()}, nxH4::H4DataType::kINT32);
4690 nxs->AddDatasetAttribute<int>("/run/histogram_data_1/grouping", "avaliabe", 0);
4691
4692 // set alpha
4693 int ival=1;
4694 nxs->AddDataset<int>("/run/histogram_data_1/alpha", {ival}, {1}, nxH4::H4DataType::kINT32);
4695 nxs->AddDatasetAttribute<int>("/run/histogram_data_1/alpha", "avaliabe", 0);
4696
4697 // set counts
4698 // feed histos
4699 PIntVector data;
4700 UInt_t size = 0;
4701 int noHisto, histoLength;
4702 if (fAny2ManyInfo->rebin == 1) {
4703 noHisto = fData[0].GetNoOfHistos();
4704 for (UInt_t i=0; i<fData[0].GetNoOfHistos(); i++) {
4705 dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
4706 if (dataSet == nullptr) { // something is really wrong
4707 std::cerr << std::endl << ">> PRunDataHandler::WriteNexusFile: **ERROR** Couldn't get data set (idx=" << i << ")";
4708 std::cerr << std::endl << ">> something is really wrong!" << std::endl;
4709 return false;
4710 }
4711 size = dataSet->GetData()->size();
4712 histoLength = size;
4713 for (UInt_t j=0; j<size; j++) {
4714 data.push_back((UInt_t)dataSet->GetData()->at(j));
4715 }
4716 }
4717 } else { // rebin > 1
4718 UInt_t dataRebin = 0;
4719 UInt_t dataCount = 0;
4720 noHisto = fData[0].GetNoOfHistos();
4721 for (UInt_t i=0; i<fData[0].GetNoOfHistos(); i++) {
4722 dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
4723 if (dataSet == nullptr) { // something is really wrong
4724 std::cerr << std::endl << ">> PRunDataHandler::WriteNexusFile: **ERROR** Couldn't get data set (idx=" << i << ")";
4725 std::cerr << std::endl << ">> something is really wrong!" << std::endl;
4726 return false;
4727 }
4728 size = dataSet->GetData()->size();
4729 dataCount = 0;
4730 for (UInt_t j=0; j<size; j++) {
4731 if ((j > 0) && (j % fAny2ManyInfo->rebin == 0)) {
4732 dataCount++;
4733 data.push_back(dataRebin);
4734 dataRebin = 0;
4735 }
4736 dataRebin += static_cast<UInt_t>(dataSet->GetData()->at(j));
4737 }
4738 }
4739 size = dataCount;
4740 }
4741 nxs->AddDataset<int>("/run/histogram_data_1/counts", data, {(uint32_t)noHisto, (uint32_t)size}, nxH4::H4DataType::kINT32);
4742 nxs->AddDatasetAttribute<int>("/run/histogram_data_1/counts", "units", std::string("counts"));
4743 nxs->AddDatasetAttribute<int>("/run/histogram_data_1/counts", "signal", 1);
4744 nxs->AddDatasetAttribute<int>("/run/histogram_data_1/counts", "number", noHisto);
4745 nxs->AddDatasetAttribute<int>("/run/histogram_data_1/counts", "length", (int)size);
4746 nxs->AddDatasetAttribute<int>("/run/histogram_data_1/counts", "t0_bin", 0);
4747 nxs->AddDatasetAttribute<int>("/run/histogram_data_1/counts", "first_good_bin", 0);
4748 nxs->AddDatasetAttribute<int>("/run/histogram_data_1/counts", "last_good_bin", 0);
4749 res = (float)(fData[0].GetTimeResolution()*fAny2ManyInfo->rebin*1.0e3)/2.0;
4750 nxs->AddDatasetAttribute<int>("/run/histogram_data_1/counts", "offset", res);
4751 } else { // IDF V2
4752 nxs->AddGroupAttribute("/raw_data_1", "NX_class", std::string("NXentry"));
4753
4754 // set IDF version
4755 nxs->AddDataset<int>("/raw_data_1/IDF_version", {(int)fAny2ManyInfo->idf}, {1}, nxH4::H4DataType::kINT32);
4756
4757 // set beamline
4758 str = *fData[0].GetBeamline();
4759 nxs->AddDataset<std::string>("/raw_data_1/beamline", {str}, {1}, nxH4::H4DataType::kCHAR8);
4760
4761 // set definition
4762 nxs->AddDataset<std::string>("/raw_data_1/definition", {std::string("muonTD")}, {1}, nxH4::H4DataType::kCHAR8);
4763
4764 // set run_number
4765 nxs->AddDataset<int>("/raw_data_1/run_number", {fData[0].GetRunNumber()}, {1}, nxH4::H4DataType::kINT32);
4766
4767 // set title
4768 nxs->AddDataset<std::string>("/raw_data_1/title", {fData[0].GetRunTitle()->Data()}, {1}, nxH4::H4DataType::kCHAR8);
4769
4770 // set start time
4771 str = std::string(fData[0].GetStartDate()->Data()) + std::string("T") + std::string(fData[0].GetStartTime()->Data());
4772 nxs->AddDataset<std::string>("/raw_data_1/start_time", {str}, {1}, nxH4::H4DataType::kCHAR8);
4773 nxs->AddDatasetAttribute<std::string>("/raw_data_1/start_time", "units", "ISO8601");
4774
4775 // set end time
4776 str = std::string(fData[0].GetStopDate()->Data()) + std::string("T") + std::string(fData[0].GetStopTime()->Data());
4777 nxs->AddDataset<std::string>("/raw_data_1/end_time", {str}, {1}, nxH4::H4DataType::kCHAR8);
4778 nxs->AddDatasetAttribute<std::string>("/raw_data_1/end_time", "units", "ISO8601");
4779
4780 // set experiment_identifier
4781 str = "n/a";
4782 nxs->AddDataset<std::string>("/raw_data_1/experiment_identifier", {str}, {1}, nxH4::H4DataType::kCHAR8);
4783
4784 // set instrument attribute
4785 nxs->AddGroupAttribute("/raw_data_1/instrument", "NX_class", std::string("NXinstrument"));
4786
4787 // set instrument name
4788 str = *fData[0].GetInstrument();
4789 nxs->AddDataset<std::string>("/raw_data_1/instrument/name", {str}, {1}, nxH4::H4DataType::kCHAR8);
4790
4791 // set instrument/source attribute
4792 nxs->AddGroupAttribute("/raw_data_1/instrument/source", "NX_class", std::string("NXsource"));
4793
4794 // set instrument/source/name
4795 str = fData[0].GetLaboratory()->Data();
4796 nxs->AddDataset<std::string>("/raw_data_1/instrument/source/name", {str}, {1}, nxH4::H4DataType::kCHAR8);
4797
4798 // set instrument/source/type
4799 TString tstr = *fData[0].GetInstrument();
4800 std::string type{"n/a"};
4801 if (tstr.Contains("LEM", TString::kIgnoreCase)) {
4802 type = "low energy muon source";
4803 } else if (tstr.Contains("GPS", TString::kIgnoreCase) || tstr.Contains("GPD", TString::kIgnoreCase) ||
4804 tstr.Contains("LTF", TString::kIgnoreCase) || tstr.Contains("FLAME", TString::kIgnoreCase) ||
4805 tstr.Contains("HAL-9500", TString::kIgnoreCase) || tstr.Contains("DOLLY", TString::kIgnoreCase) ||
4806 tstr.Contains("VMS", TString::kIgnoreCase)) {
4807 type = "quasi-continous muon source";
4808 } else if (tstr.Contains("EMU", TString::kIgnoreCase) || tstr.Contains("MUSR", TString::kIgnoreCase) ||
4809 tstr.Contains("HIFI", TString::kIgnoreCase)) {
4810 type = "pulsed muon source";
4811 }
4812 nxs->AddDataset<std::string>("/raw_data_1/instrument/source/type", {type}, {1}, nxH4::H4DataType::kCHAR8);
4813
4814 // set instrument/source/probe
4815 str = "positive muons";
4816 nxs->AddDataset<std::string>("/raw_data_1/instrument/source/probe", {str}, {1}, nxH4::H4DataType::kCHAR8);
4817
4818 // set instrument/detector info
4819 nxs->AddGroupAttribute("/raw_data_1/instrument/detector_1", "NX_class", std::string("NXdetector"));
4820
4821 // set instrument/detector/spectrum_index
4822 int noHistos = fData[0].GetNoOfHistos();
4823 std::vector<int> spectrum_index(noHistos);
4824 for (unsigned int i=0; i<spectrum_index.size(); i++)
4825 spectrum_index[i] = i+1;
4826 nxs->AddDataset<int>("/raw_data_1/instrument/detector_1/spectrum_index", spectrum_index, {(uint32_t)spectrum_index.size()}, nxH4::H4DataType::kINT32);
4827
4828 // set instrument/detector/raw_time (not useful for quasi-continuous sources)
4829 int ival=0;
4830 nxs->AddDataset<int>("/raw_data_1/instrument/detector_1/raw_time", {ival}, {1}, nxH4::H4DataType::kINT32);
4831 nxs->AddDatasetAttribute<int>("/raw_data_1/instrument/detector_1/raw_time", "available", 0);
4832
4833 // set instrument/detector/counts
4834 // set counts
4835 // feed histos
4836 PRawRunDataSet *dataSet = nullptr;
4837 PIntVector data;
4838 UInt_t size = 0;
4839 int noHisto, histoLength;
4840 if (fAny2ManyInfo->rebin == 1) {
4841 noHisto = fData[0].GetNoOfHistos();
4842 for (UInt_t i=0; i<fData[0].GetNoOfHistos(); i++) {
4843 dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
4844 if (dataSet == nullptr) { // something is really wrong
4845 std::cerr << std::endl << ">> PRunDataHandler::WriteNexusFile: **ERROR** Couldn't get data set (idx=" << i << ")";
4846 std::cerr << std::endl << ">> something is really wrong!" << std::endl;
4847 return false;
4848 }
4849 size = dataSet->GetData()->size();
4850 histoLength = size;
4851 for (UInt_t j=0; j<size; j++) {
4852 data.push_back((UInt_t)dataSet->GetData()->at(j));
4853 }
4854 }
4855 } else { // rebin > 1
4856 UInt_t dataRebin = 0;
4857 UInt_t dataCount = 0;
4858 noHisto = fData[0].GetNoOfHistos();
4859 for (UInt_t i=0; i<fData[0].GetNoOfHistos(); i++) {
4860 dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
4861 if (dataSet == nullptr) { // something is really wrong
4862 std::cerr << std::endl << ">> PRunDataHandler::WriteNexusFile: **ERROR** Couldn't get data set (idx=" << i << ")";
4863 std::cerr << std::endl << ">> something is really wrong!" << std::endl;
4864 return false;
4865 }
4866 size = dataSet->GetData()->size();
4867 dataCount = 0;
4868 for (UInt_t j=0; j<size; j++) {
4869 if ((j > 0) && (j % fAny2ManyInfo->rebin == 0)) {
4870 dataCount++;
4871 data.push_back(dataRebin);
4872 dataRebin = 0;
4873 }
4874 dataRebin += static_cast<UInt_t>(dataSet->GetData()->at(j));
4875 }
4876 }
4877 size = dataCount;
4878 }
4879 nxs->AddDataset<int>("/raw_data_1/instrument/detector_1/counts", data, {(uint32_t)noHisto, (uint32_t)size}, nxH4::H4DataType::kINT32);
4880 nxs->AddDatasetAttribute<int>("/raw_data_1/instrument/detector_1/counts", "axes", std::string("spectrum_index,time_bin"));
4881 nxs->AddDatasetAttribute<int>("/raw_data_1/instrument/detector_1/counts", "long_name", std::string("positon counts"));
4882 nxs->AddDatasetAttribute<int>("/raw_data_1/instrument/detector_1/counts", "signal", 1);
4883 // t0_bin attributes
4884 std::vector<int> t0_bin;
4885 for (unsigned int i=0; i<fData[0].GetNoOfHistos(); i++)
4886 t0_bin.push_back((int)(fData[0].GetT0Bin(i+1)/fAny2ManyInfo->rebin));
4887 nxs->AddDatasetAttribute<int>("/raw_data_1/instrument/detector_1/counts", "t0_bin", {t0_bin});
4888 nxs->AddDatasetAttribute<int>("/raw_data_1/instrument/detector_1/counts", "units", std::string("counts"));
4889
4890 // set raw_data_1/detector info
4891 nxs->AddGroupAttribute("/raw_data_1/detector_1", "NX_class", std::string("NXdata"));
4892
4893 // set detector/counts
4894 nxs->AddDataset<int>("/raw_data_1/detector_1/counts", data, {(uint32_t)noHisto, (uint32_t)size}, nxH4::H4DataType::kINT32);
4895 nxs->AddDatasetAttribute<int>("/raw_data_1/detector_1/counts", "axes", std::string("spectrum_index,time_bin"));
4896 nxs->AddDatasetAttribute<int>("/raw_data_1/detector_1/counts", "long_name", std::string("positon counts"));
4897 nxs->AddDatasetAttribute<int>("/raw_data_1/detector_1/counts", "signal", 1);
4898 }
4899
4900 int result = nxs->WriteNexusFile(fln.Data(), fAny2ManyInfo->idf);
4901 if (result != 0) {
4902 std::cerr << std::endl << "**ERROR** PRunDataHandler::WriteNexusFile, fln=" << fln << std::endl;
4903 return false;
4904 }
4905 } catch (const std::runtime_error& e) {
4906 std::cerr << std::endl << "HDF4 error: " << e.what() << std::endl;
4907 return false;
4908 }
4909#endif
4910 } else { // HDF5
4911 try {
4912 // create NeXus object
4913 std::unique_ptr<nxH5::PNeXus> nxs = std::make_unique<nxH5::PNeXus>();
4914 if (nxs == nullptr) {
4915 std::cerr << std::endl << ">> PRunDataHandler::WriteNexusFile(): **ERROR** couldn't invoke the NeXus object." << std::endl;
4916 return false;
4917 }
4918
4919 // set NeXus version
4920 nxs->AddGroupAttribute("/", "NeXus_version", std::string("4.3.0"));
4921
4922 // set HDF5 version
4923 nxs->AddGroupAttribute("/", "HDF_version", nxs->GetHdf5LibVersion());
4924
4925 // set file name
4926 nxs->AddGroupAttribute("/", "file_name", std::string(fln.Data()));
4927
4928 // set creation time
4929 std::string dt = nxs::getIso8601TimestampLocal();
4930 nxs->AddGroupAttribute("/", "file_time", dt);
4931
4932 if (fAny2ManyInfo->idf == 1) { // IDF V1
4933 // set IDF version
4934 nxs->AddDataset<int>("/run/IDF_version", {(int)fAny2ManyInfo->idf}, {1}, H5::PredType::NATIVE_INT32);
4935
4936 // set program name
4937 nxs->AddDataset<std::string>("/run/program_name", {"any2many"}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE));
4938 str="n/a";
4939 #ifdef HAVE_CONFIG_H
4940 str = PACKAGE_VERSION;
4941 #endif
4942 nxs->AddDatasetAttribute<std::string>("/run/program_name", "version", str);
4943
4944 // set run number
4945 nxs->AddDataset<int>("/run/number", {fData[0].GetRunNumber()}, {1}, H5::PredType::NATIVE_INT32);
4946
4947 // set title
4948 nxs->AddDataset<std::string>("/run/title", {fData[0].GetRunTitle()->Data()}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE));
4949
4950 // set notes
4951 nxs->AddDataset<std::string>("/run/notes", {std::string("n/a")}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE));
4952
4953 // set analysis
4954 nxs->AddDataset<std::string>("/run/analysis", {std::string("muonTD")}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE));
4955
4956 // set lab
4957 str = *fData[0].GetLaboratory();
4958 nxs->AddDataset<std::string>("/run/lab", {str}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE));
4959
4960 // set beamline
4961 str = *fData[0].GetBeamline();
4962 nxs->AddDataset<std::string>("/run/beamline", {str}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE));
4963
4964 // set start time
4965 str = std::string(fData[0].GetStartDate()->Data()) + std::string("T") + std::string(fData[0].GetStartTime()->Data());
4966 nxs->AddDataset<std::string>("/run/start_time", {str}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE));
4967
4968 // set stop time
4969 str = std::string(fData[0].GetStopDate()->Data()) + std::string("T") + std::string(fData[0].GetStopTime()->Data());
4970 nxs->AddDataset<std::string>("/run/stop_time", {str}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE));
4971
4972 // set switching state
4973 nxs->AddDataset<int>("/run/switching_states", {1}, {1}, H5::PredType::NATIVE_INT32);
4974
4975 // set user name
4976 nxs->AddDataset<std::string>("/run/user/name", {std::string("n/a")}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE));
4977
4978 // set user experiment_number
4979 nxs->AddDataset<std::string>("/run/user/experiment_number", {std::string("n/a")}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE));
4980
4981 // set sample name
4982 nxs->AddDataset<std::string>("/run/sample/name", {fData[0].GetSample()->Data()}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE));
4983
4984 // set sample temperature
4985 nxs->AddDataset<float>("/run/sample/temperature", {(float)fData[0].GetTemperature(0)}, {1}, H5::PredType::NATIVE_FLOAT);
4986 nxs->AddDatasetAttribute<float>("/run/sample/temperature", "units", std::string("Kelvin"));
4987
4988 // set magnetic field
4989 nxs->AddDataset<float>("/run/sample/magnetic_field", {(float)fData[0].GetField()}, {1}, H5::PredType::NATIVE_FLOAT);
4990 nxs->AddDatasetAttribute<float>("/run/sample/magnetic_field", "units", std::string("Gauss"));
4991
4992 // set sample environment
4993 nxs->AddDataset<std::string>("/run/sample/environment", {fData[0].GetSetup()->Data()}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE));
4994
4995 // set sample shape
4996 nxs->AddDataset<std::string>("/run/sample/shape", {std::string("n/a")}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE));
4997
4998 // set magnetic field vector
4999 nxs->AddDataset<float>("/run/sample/magnetic_field_vector", {1.0, 1.0, 1.0}, {3}, H5::PredType::NATIVE_FLOAT);
5000 nxs->AddDatasetAttribute<float>("/run/sample/magnetic_field_vector", "coordinate_system", std::string("cartesian"));
5001 nxs->AddDatasetAttribute<float>("/run/sample/magnetic_field_vector", "units", std::string("Gauss"));
5002 nxs->AddDatasetAttribute<float>("/run/sample/magnetic_field_vector", "available", 0);
5003
5004 // set instrument name
5005 str = *fData[0].GetInstrument();
5006 nxs->AddDataset<std::string>("/run/instrument/name", {str}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE));
5007
5008 // set instrument number of detectors
5009 nxs->AddDataset<int>("/run/instrument/detector/number", {(int)fData[0].GetNoOfHistos()}, {1}, H5::PredType::NATIVE_INT32);
5010
5011 // set instrument collimator
5012 nxs->AddDataset<std::string>("/run/instrument/collimator/type", {std::string("n/a")}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE));
5013
5014 // set instrument beam total number of counts in Mev
5015 // calculate the total number of counts
5016 double total_counts = 0;
5017 PRawRunDataSet *dataSet = nullptr;
5018 for (unsigned int i=0; i<fData[0].GetNoOfHistos(); i++) {
5019 dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
5020 if (dataSet == nullptr) { // something is really wrong
5021 std::cerr << std::endl << ">> PRunDataHandler::WriteNexusFile: **ERROR** Couldn't get data set (idx=0" << i << ")";
5022 std::cerr << std::endl << ">> something is really wrong!" << std::endl;
5023 return false;
5024 }
5025 for (unsigned int j=0; j<dataSet->GetData()->size(); j++)
5026 total_counts += dataSet->GetData()->at(j);
5027 }
5028 float total_counts_mev = (float) total_counts / 1.0e6;
5029 nxs->AddDataset<float>("/run/instrument/beam/total_counts", {total_counts_mev}, {1}, H5::PredType::NATIVE_FLOAT);
5030 nxs->AddDatasetAttribute<float>("/run/instrument/beam/total_counts", "units", std::string("MEv"));
5031
5032 // set time resolution (use FLOAT instead of INT)
5033 float res = (float)(fData[0].GetTimeResolution()*fAny2ManyInfo->rebin*1.0e3);
5034 nxs->AddDataset<float>("/run/histogram_data_1/resolution", {res}, {1}, H5::PredType::NATIVE_FLOAT);
5035 nxs->AddDatasetAttribute<float>("/run/histogram_data_1/resolution", "units", std::string("picoseconds"));
5036
5037 // set time zero time to 0. see t0_bin attribute of counts!
5038 nxs->AddDataset<int>("/run/histogram_data_1/time_zero", {0}, {1}, H5::PredType::NATIVE_INT32);
5039 nxs->AddDatasetAttribute<int>("/run/histogram_data_1/time_zero", "units", std::string("microseconds"));
5040 nxs->AddDatasetAttribute<int>("/run/histogram_data_1/time_zero", "available", 0);
5041
5042 // set raw_time
5043 res = (float)(fData[0].GetTimeResolution()*fAny2ManyInfo->rebin*1.0e-3);
5044 dataSet = fData[0].GetDataSet(0, false); // i.e. the false means, that i is the index and NOT the histo number
5045 unsigned int length = (int)(dataSet->GetData()->size() / fAny2ManyInfo->rebin);
5046 std::vector<float> time;
5047 for (unsigned int i=0; i<length; i++)
5048 time.push_back(((float)i+0.5)*res);
5049 nxs->AddDataset<float>("/run/histogram_data_1/raw_time", time, {length}, H5::PredType::NATIVE_FLOAT);
5050 nxs->AddDatasetAttribute<float>("/run/histogram_data_1/raw_time", "axis", 1);
5051 nxs->AddDatasetAttribute<float>("/run/histogram_data_1/raw_time", "primary", 0);
5052 nxs->AddDatasetAttribute<float>("/run/histogram_data_1/raw_time", "units", std::string("microseconds"));
5053 nxs->AddDatasetAttribute<float>("/run/histogram_data_1/raw_time", "available", 0);
5054
5055 // set corrected_time
5056 nxs->AddDataset<float>("/run/histogram_data_1/corrected_time", time, {length}, H5::PredType::NATIVE_FLOAT);
5057 nxs->AddDatasetAttribute<float>("/run/histogram_data_1/corrected_time", "axis", 1);
5058 nxs->AddDatasetAttribute<float>("/run/histogram_data_1/corrected_time", "units", std::string("microseconds"));
5059 nxs->AddDatasetAttribute<float>("/run/histogram_data_1/corrected_time", "available", 0);
5060
5061 // set grouping
5062 std::vector<int> grouping(fData[0].GetNoOfHistos(), 0);
5063 nxs->AddDataset<int>("/run/histogram_data_1/grouping", grouping, {grouping.size()}, H5::PredType::NATIVE_INT32);
5064 nxs->AddDatasetAttribute<int>("/run/histogram_data_1/grouping", "avaliabe", 0);
5065
5066 // set alpha
5067 int ival=1;
5068 nxs->AddDataset<int>("/run/histogram_data_1/alpha", {ival}, {1}, H5::PredType::NATIVE_INT32);
5069 nxs->AddDatasetAttribute<int>("/run/histogram_data_1/alpha", "avaliabe", 0);
5070
5071 // set counts
5072 // feed histos
5073 PIntVector data;
5074 UInt_t size = 0;
5075 int noHisto, histoLength;
5076 if (fAny2ManyInfo->rebin == 1) {
5077 noHisto = fData[0].GetNoOfHistos();
5078 for (UInt_t i=0; i<fData[0].GetNoOfHistos(); i++) {
5079 dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
5080 if (dataSet == nullptr) { // something is really wrong
5081 std::cerr << std::endl << ">> PRunDataHandler::WriteNexusFile: **ERROR** Couldn't get data set (idx=" << i << ")";
5082 std::cerr << std::endl << ">> something is really wrong!" << std::endl;
5083 return false;
5084 }
5085 size = dataSet->GetData()->size();
5086 histoLength = size;
5087 for (UInt_t j=0; j<size; j++) {
5088 data.push_back((UInt_t)dataSet->GetData()->at(j));
5089 }
5090 }
5091 } else { // rebin > 1
5092 UInt_t dataRebin = 0;
5093 UInt_t dataCount = 0;
5094 noHisto = fData[0].GetNoOfHistos();
5095 for (UInt_t i=0; i<fData[0].GetNoOfHistos(); i++) {
5096 dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
5097 if (dataSet == nullptr) { // something is really wrong
5098 std::cerr << std::endl << ">> PRunDataHandler::WriteNexusFile: **ERROR** Couldn't get data set (idx=" << i << ")";
5099 std::cerr << std::endl << ">> something is really wrong!" << std::endl;
5100 return false;
5101 }
5102 size = dataSet->GetData()->size();
5103 dataCount = 0;
5104 for (UInt_t j=0; j<size; j++) {
5105 if ((j > 0) && (j % fAny2ManyInfo->rebin == 0)) {
5106 dataCount++;
5107 data.push_back(dataRebin);
5108 dataRebin = 0;
5109 }
5110 dataRebin += static_cast<UInt_t>(dataSet->GetData()->at(j));
5111 }
5112 }
5113 size = dataCount;
5114 }
5115 nxs->AddDataset<int>("/run/histogram_data_1/counts", data, {(long unsigned int)noHisto, size}, H5::PredType::NATIVE_INT32);
5116 nxs->AddDatasetAttribute<int>("/run/histogram_data_1/counts", "units", std::string("counts"));
5117 nxs->AddDatasetAttribute<int>("/run/histogram_data_1/counts", "signal", 1);
5118 nxs->AddDatasetAttribute<int>("/run/histogram_data_1/counts", "number", noHisto);
5119 nxs->AddDatasetAttribute<int>("/run/histogram_data_1/counts", "length", size);
5120 nxs->AddDatasetAttribute<int>("/run/histogram_data_1/counts", "t0_bin", 0);
5121 nxs->AddDatasetAttribute<int>("/run/histogram_data_1/counts", "first_good_bin", 0);
5122 nxs->AddDatasetAttribute<int>("/run/histogram_data_1/counts", "last_good_bin", 0);
5123 res = (float)(fData[0].GetTimeResolution()*fAny2ManyInfo->rebin*1.0e3)/2.0;
5124 nxs->AddDatasetAttribute<int>("/run/histogram_data_1/counts", "offset", res);
5125 } else { // IDF V2
5126 nxs->AddGroupAttribute("/raw_data_1", "NX_class", std::string("NXentry"));
5127
5128 // set IDF version
5129 nxs->AddDataset<int>("/raw_data_1/IDF_version", {(int)fAny2ManyInfo->idf}, {1}, H5::PredType::NATIVE_INT32);
5130
5131 // set beamline
5132 str = *fData[0].GetBeamline();
5133 nxs->AddDataset<std::string>("/raw_data_1/beamline", {str}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE));
5134
5135 // set definition
5136 nxs->AddDataset<std::string>("/raw_data_1/definition", {std::string("muonTD")}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE));
5137
5138 // set run_number
5139 nxs->AddDataset<int>("/raw_data_1/run_number", {fData[0].GetRunNumber()}, {1}, H5::PredType::NATIVE_INT32);
5140
5141 // set title
5142 nxs->AddDataset<std::string>("/raw_data_1/title", {fData[0].GetRunTitle()->Data()}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE));
5143
5144 // set start time
5145 str = std::string(fData[0].GetStartDate()->Data()) + std::string("T") + std::string(fData[0].GetStartTime()->Data());
5146 nxs->AddDataset<std::string>("/raw_data_1/start_time", {str}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE));
5147 nxs->AddDatasetAttribute<std::string>("/raw_data_1/start_time", "units", "ISO8601");
5148
5149 // set end time
5150 str = std::string(fData[0].GetStopDate()->Data()) + std::string("T") + std::string(fData[0].GetStopTime()->Data());
5151 nxs->AddDataset<std::string>("/raw_data_1/end_time", {str}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE));
5152 nxs->AddDatasetAttribute<std::string>("/raw_data_1/end_time", "units", "ISO8601");
5153
5154 // set experiment_identifier
5155 str = "n/a";
5156 nxs->AddDataset<std::string>("/raw_data_1/experiment_identifier", {str}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE));
5157
5158 // set instrument attribute
5159 nxs->AddGroupAttribute("/raw_data_1/instrument", "NX_class", std::string("NXinstrument"));
5160
5161 // set instrument name
5162 str = *fData[0].GetInstrument();
5163 nxs->AddDataset<std::string>("/raw_data_1/instrument/name", {str}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE));
5164
5165 // set instrument/source attribute
5166 nxs->AddGroupAttribute("/raw_data_1/instrument/source", "NX_class", std::string("NXsource"));
5167
5168 // set instrument/source/name
5169 str = fData[0].GetLaboratory()->Data();
5170 nxs->AddDataset<std::string>("/raw_data_1/instrument/source/name", {str}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE));
5171
5172 // set instrument/source/type
5173 TString tstr = *fData[0].GetInstrument();
5174 std::string type{"n/a"};
5175 if (tstr.Contains("LEM", TString::kIgnoreCase)) {
5176 type = "low energy muon source";
5177 } else if (tstr.Contains("GPS", TString::kIgnoreCase) || tstr.Contains("GPD", TString::kIgnoreCase) ||
5178 tstr.Contains("LTF", TString::kIgnoreCase) || tstr.Contains("FLAME", TString::kIgnoreCase) ||
5179 tstr.Contains("HAL-9500", TString::kIgnoreCase) || tstr.Contains("DOLLY", TString::kIgnoreCase) ||
5180 tstr.Contains("VMS", TString::kIgnoreCase)) {
5181 type = "quasi-continous muon source";
5182 } else if (tstr.Contains("EMU", TString::kIgnoreCase) || tstr.Contains("MUSR", TString::kIgnoreCase) ||
5183 tstr.Contains("HIFI", TString::kIgnoreCase)) {
5184 type = "pulsed muon source";
5185 }
5186 nxs->AddDataset<std::string>("/raw_data_1/instrument/source/type", {type}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE));
5187
5188 // set instrument/source/probe
5189 str = "positive muons";
5190 nxs->AddDataset<std::string>("/raw_data_1/instrument/source/probe", {str}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE));
5191
5192 // set instrument/detector info
5193 nxs->AddGroupAttribute("/raw_data_1/instrument/detector_1", "NX_class", std::string("NXdetector"));
5194
5195 // set instrument/detector/spectrum_index
5196 int noHistos = fData[0].GetNoOfHistos();
5197 std::vector<int> spectrum_index(noHistos);
5198 for (unsigned int i=0; i<spectrum_index.size(); i++)
5199 spectrum_index[i] = i+1;
5200 nxs->AddDataset<int>("/raw_data_1/instrument/detector_1/spectrum_index", spectrum_index, {spectrum_index.size()}, H5::PredType::NATIVE_INT32);
5201
5202 // set instrument/detector/raw_time (not useful for quasi-continuous sources)
5203 int ival=0;
5204 nxs->AddDataset<int>("/raw_data_1/instrument/detector_1/raw_time", {ival}, {1}, H5::PredType::NATIVE_INT32);
5205 nxs->AddDatasetAttribute<int>("/raw_data_1/instrument/detector_1/raw_time", "available", 0);
5206
5207 // set instrument/detector/counts
5208 // set counts
5209 // feed histos
5210 PRawRunDataSet *dataSet = nullptr;
5211 PIntVector data;
5212 UInt_t size = 0;
5213 int noHisto, histoLength;
5214 if (fAny2ManyInfo->rebin == 1) {
5215 noHisto = fData[0].GetNoOfHistos();
5216 for (UInt_t i=0; i<fData[0].GetNoOfHistos(); i++) {
5217 dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
5218 if (dataSet == nullptr) { // something is really wrong
5219 std::cerr << std::endl << ">> PRunDataHandler::WriteNexusFile: **ERROR** Couldn't get data set (idx=" << i << ")";
5220 std::cerr << std::endl << ">> something is really wrong!" << std::endl;
5221 return false;
5222 }
5223 size = dataSet->GetData()->size();
5224 histoLength = size;
5225 for (UInt_t j=0; j<size; j++) {
5226 data.push_back((UInt_t)dataSet->GetData()->at(j));
5227 }
5228 }
5229 } else { // rebin > 1
5230 UInt_t dataRebin = 0;
5231 UInt_t dataCount = 0;
5232 noHisto = fData[0].GetNoOfHistos();
5233 for (UInt_t i=0; i<fData[0].GetNoOfHistos(); i++) {
5234 dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
5235 if (dataSet == nullptr) { // something is really wrong
5236 std::cerr << std::endl << ">> PRunDataHandler::WriteNexusFile: **ERROR** Couldn't get data set (idx=" << i << ")";
5237 std::cerr << std::endl << ">> something is really wrong!" << std::endl;
5238 return false;
5239 }
5240 size = dataSet->GetData()->size();
5241 dataCount = 0;
5242 for (UInt_t j=0; j<size; j++) {
5243 if ((j > 0) && (j % fAny2ManyInfo->rebin == 0)) {
5244 dataCount++;
5245 data.push_back(dataRebin);
5246 dataRebin = 0;
5247 }
5248 dataRebin += static_cast<UInt_t>(dataSet->GetData()->at(j));
5249 }
5250 }
5251 size = dataCount;
5252 }
5253 nxs->AddDataset<int>("/raw_data_1/instrument/detector_1/counts", data, {(long unsigned int)noHisto, size}, H5::PredType::NATIVE_INT32);
5254 nxs->AddDatasetAttribute<int>("/raw_data_1/instrument/detector_1/counts", "axes", std::string("spectrum_index,time_bin"));
5255 nxs->AddDatasetAttribute<int>("/raw_data_1/instrument/detector_1/counts", "long_name", std::string("positon counts"));
5256 nxs->AddDatasetAttribute<int>("/raw_data_1/instrument/detector_1/counts", "signal", 1);
5257 // t0_bin attributes
5258 std::vector<int> t0_bin;
5259 for (unsigned int i=0; i<fData[0].GetNoOfHistos(); i++)
5260 t0_bin.push_back((int)(fData[0].GetT0Bin(i+1)/fAny2ManyInfo->rebin));
5261 nxs->AddDatasetAttribute<int>("/raw_data_1/instrument/detector_1/counts", "t0_bin", {t0_bin});
5262 nxs->AddDatasetAttribute<int>("/raw_data_1/instrument/detector_1/counts", "units", std::string("counts"));
5263
5264 // set raw_data_1/detector info
5265 nxs->AddGroupAttribute("/raw_data_1/detector_1", "NX_class", std::string("NXdata"));
5266
5267 // set detector/counts
5268 nxs->AddDataset<int>("/raw_data_1/detector_1/counts", data, {(long unsigned int)noHisto, size}, H5::PredType::NATIVE_INT32);
5269 nxs->AddDatasetAttribute<int>("/raw_data_1/detector_1/counts", "axes", std::string("spectrum_index,time_bin"));
5270 nxs->AddDatasetAttribute<int>("/raw_data_1/detector_1/counts", "long_name", std::string("positon counts"));
5271 nxs->AddDatasetAttribute<int>("/raw_data_1/detector_1/counts", "signal", 1);
5272 }
5273
5274 int result = nxs->WriteNexusFile(fln.Data(), fAny2ManyInfo->idf);
5275 if (result != 0) {
5276 std::cerr << std::endl << "**ERROR** PRunDataHandler::WriteNexusFile, fln=" << fln << std::endl;
5277 return false;
5278 }
5279 } catch (const H5::Exception& e) {
5280 std::cerr << std::endl << "HDF5 error: " << e.getDetailMsg() << std::endl;
5281 }
5282 }
5283
5284 return true;
5285#else
5286 std::cout << std::endl << ">> PRunDataHandler::WriteNexusFile(): Sorry, not enabled at configuration level, i.e. -Dnexus=1 when executing configure" << std::endl << std::endl;
5287#endif
5288
5289 return true;
5290}
5291
5292//--------------------------------------------------------------------------
5293// WriteWkmFile (private)
5294//--------------------------------------------------------------------------
5305{
5306 // check if a LEM nemu file needs to be written
5307 bool lem_wkm_style = false;
5308 if (!fData[0].GetBeamline()->CompareTo("mue4", TString::kIgnoreCase))
5309 lem_wkm_style = true;
5310
5311 Bool_t ok = false;
5312 if (lem_wkm_style)
5313 fln = GenerateOutputFileName(fln, ".nemu", ok);
5314 else
5315 fln = GenerateOutputFileName(fln, ".wkm", ok);
5316
5317 if (!ok)
5318 return false;
5319
5320 TString fileName = fln;
5321
5322 if (!fAny2ManyInfo->useStandardOutput)
5323 std::cout << std::endl << ">> PRunDataHandler::WriteWkmFile(): writing a wkm data file (" << fln.Data() << ") ... " << std::endl;
5324
5325 // write ascii file
5326 std::ofstream fout;
5327 std::streambuf* strm_buffer = nullptr;
5328
5329 if (!fAny2ManyInfo->useStandardOutput || (fAny2ManyInfo->compressionTag > 0)) {
5330 // open data-file
5331 fout.open(fln.Data(), std::ofstream::out);
5332 if (!fout.is_open()) {
5333 std::cerr << std::endl << ">> PRunDataHandler::WriteWkmFile **ERROR** Couldn't open data file (" << fln.Data() << ") for writing, sorry ...";
5334 std::cerr << std::endl;
5335 return false;
5336 }
5337
5338 // save output buffer of the stream
5339 strm_buffer = std::cout.rdbuf();
5340
5341 // redirect output into the file
5342 std::cout.rdbuf(fout.rdbuf());
5343 }
5344
5345 // write header
5346 std::cout << "- WKM data file converted with any2many";
5347 if (lem_wkm_style) {
5348 std::cout << std::endl << "NEMU_Run: " << fData[0].GetRunNumber();
5349 std::cout << std::endl << "nemu_Run: " << fileName.Data();
5350 } else {
5351 std::cout << std::endl << "Run: " << fData[0].GetRunNumber();
5352 }
5353 std::cout << std::endl << "Date: " << fData[0].GetStartTime()->Data() << " " << fData[0].GetStartDate()->Data() << " / " << fData[0].GetStopTime()->Data() << " " << fData[0].GetStopDate()->Data();
5354 if (fData[0].GetRunTitle()->Length() > 0)
5355 std::cout << std::endl << "Title: " << fData[0].GetRunTitle()->Data();
5356 if (fData[0].GetField() != PMUSR_UNDEFINED) {
5357 std::cout << std::endl << "Field: " << fData[0].GetField();
5358 } else {
5359 std::cout << std::endl << "Field: ??";
5360 }
5361 std::cout << std::endl << "Setup: " << fData[0].GetSetup()->Data();
5362 if (fData[0].GetNoOfTemperatures() == 1) {
5363 std::cout << std::endl << "Temp: " << fData[0].GetTemperature(0);
5364 } else if (fData[0].GetNoOfTemperatures() > 1) {
5365 std::cout << std::endl << "Temp(meas1): " << fData[0].GetTemperature(0) << " +- " << fData[0].GetTempError(0);
5366 std::cout << std::endl << "Temp(meas2): " << fData[0].GetTemperature(1) << " +- " << fData[0].GetTempError(1);
5367 } else {
5368 std::cout << std::endl << "Temp: ??";
5369 }
5370 if (lem_wkm_style)
5371 std::cout << std::endl << "TOF(M3S1): nocut";
5372 std::cout << std::endl << "Groups: " << fData[0].GetNoOfHistos();
5373 UInt_t histo0 = 1;
5374 if (fAny2ManyInfo->groupHistoList.size() != 0) { // red/green list found
5375 histo0 = fAny2ManyInfo->groupHistoList[0]+1; // take the first available red/green entry
5376 }
5377 std::cout << std::endl << "Channels: " << static_cast<UInt_t>(fData[0].GetDataBin(histo0)->size()/fAny2ManyInfo->rebin);
5378 std::cout.precision(10);
5379 std::cout << std::endl << "Resolution: " << fData[0].GetTimeResolution()*fAny2ManyInfo->rebin/1.0e3; // ns->us
5380 std::cout.setf(std::ios::fixed,std::ios::floatfield); // floatfield set to fixed
5381
5382 // write data
5383 UInt_t no_of_bins_per_line = 16;
5384 if (lem_wkm_style)
5385 no_of_bins_per_line = 10;
5386
5387 PRawRunDataSet *dataSet;
5388
5389 if (fAny2ManyInfo->rebin == 1) {
5390 for (UInt_t i=0; i<fData[0].GetNoOfHistos(); i++) {
5391 std::cout << std::endl << std::endl;
5392 dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
5393 for (UInt_t j=0; j<dataSet->GetData()->size(); j++) {
5394 if ((j > 0) && (j % no_of_bins_per_line == 0))
5395 std::cout << std::endl;
5396 if (lem_wkm_style)
5397 std::cout << std::setw(8) << static_cast<Int_t>(dataSet->GetData()->at(j));
5398 else
5399 std::cout << static_cast<Int_t>(dataSet->GetData()->at(j)) << " ";
5400 }
5401 }
5402 } else { // rebin > 1
5403 Int_t dataRebin = 0;
5404 UInt_t count = 0;
5405 for (UInt_t i=0; i<fData[0].GetNoOfHistos(); i++) {
5406 std::cout << std::endl << std::endl;
5407 count = 0;
5408 dataRebin = 0; // reset rebin
5409 dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
5410 for (UInt_t j=0; j<dataSet->GetData()->size(); j++) {
5411 if ((j > 0) && (j % fAny2ManyInfo->rebin == 0)) {
5412 if (lem_wkm_style)
5413 std::cout << std::setw(8) << dataRebin;
5414 else
5415 std::cout << dataRebin << " ";
5416 count++;
5417 dataRebin = 0;
5418 if ((count > 0) && (count % no_of_bins_per_line == 0) && (j != dataSet->GetData()->size()-1))
5419 std::cout << std::endl;
5420 } else {
5421 dataRebin += static_cast<Int_t>(dataSet->GetData()->at(j));
5422 }
5423 }
5424 }
5425 }
5426
5427 if (!fAny2ManyInfo->useStandardOutput || (fAny2ManyInfo->compressionTag > 0)) {
5428 // restore old output buffer
5429 std::cout.rdbuf(strm_buffer);
5430
5431 fout.close();
5432 }
5433
5434 return true;
5435}
5436
5437//--------------------------------------------------------------------------
5438// WritePsiBinFile (private)
5439//--------------------------------------------------------------------------
5450{
5451 Bool_t ok = false;
5452 fln = GenerateOutputFileName(fln, ".bin", ok);
5453 if (!ok)
5454 return false;
5455
5456 if (!fAny2ManyInfo->useStandardOutput)
5457 std::cout << std::endl << ">> PRunDataHandler::WritePsiBinFile(): writing a psi-bin data file (" << fln.Data() << ") ... " << std::endl;
5458
5459 MuSR_td_PSI_bin psibin;
5460 int status = 0;
5461
5462 // fill header information
5463 // run number
5464 psibin.PutRunNumberInt(fData[0].GetRunNumber());
5465 // length of histograms
5466 UInt_t histo0 = 1;
5467 if (fAny2ManyInfo->groupHistoList.size() != 0) { // red/green list found
5468 histo0 = fAny2ManyInfo->groupHistoList[0]+1; // take the first available red/green entry
5469 }
5470 psibin.PutHistoLengthBin(static_cast<int>(fData[0].GetDataBin(histo0)->size()/fAny2ManyInfo->rebin));
5471 // number of histograms
5472 psibin.PutNumberHistoInt(static_cast<int>(fData[0].GetNoOfHistos()));
5473 // run title = sample (10 char) / temp (10 char) / field (10 char) / orientation (10 char)
5474 char cstr[11];
5475 // sample
5476 if (fData[0].GetSample()->Length() > 0)
5477 strncpy(cstr, fData[0].GetSample()->Data(), 10);
5478 else
5479 strcpy(cstr, "??");
5480 cstr[10] = '\0';
5481 psibin.PutSample(cstr);
5482 // temp
5483 if (fData[0].GetNoOfTemperatures() > 0)
5484 snprintf(cstr, 10, "%.1f K", fData[0].GetTemperature(0));
5485 else
5486 strcpy(cstr, "?? K");
5487 cstr[10] = '\0';
5488 psibin.PutTemp(cstr);
5489 // field
5490 if (fData[0].GetField() > 0)
5491 snprintf(cstr, 10, "%.1f G", fData[0].GetField());
5492 else
5493 strcpy(cstr, "?? G");
5494 cstr[10] = '\0';
5495 psibin.PutField(cstr);
5496 // orientation
5497 if (fData[0].GetOrientation()->Length() > 0)
5498 strncpy(cstr, fData[0].GetOrientation()->Data(), 10);
5499 else
5500 strcpy(cstr, "??");
5501 cstr[10] = '\0';
5502 psibin.PutOrient(cstr);
5503 // setup
5504 if (fData[0].GetSetup()->Length() > 0)
5505 strncpy(cstr, fData[0].GetSetup()->Data(), 10);
5506 else
5507 strcpy(cstr, "??");
5508 cstr[10] = '\0';
5509 psibin.PutSetup(cstr);
5510
5511 // handle PSI-BIN start/stop Time/Date. PSI-BIN requires: Time -> HH:MM:SS, and Date -> DD-MMM-YY
5512 // internally given: Time -> HH:MM:SS, and Date -> YYYY-MM-DD
5513 // run start date
5514 std::vector<std::string> svec;
5515 TString str, date;
5516 TDatime dt;
5517 int year, month, day;
5518
5519 // 28-Aug-2014, TP: the following line does not work, it generates the wrong date
5520 //dt.Set(fData[0].GetStartDateTime()); //as35
5521 // the following generates the correct date entry
5522 date.Append(*fData[0].GetStartDate());
5523 sscanf((const char*)date.Data(),"%04d-%02d-%02d", &year, &month, &day);
5524 dt.Set(year, month, day, 0, 0, 0);
5525
5526 date.Form("%02d-", dt.GetDay());
5527 date.Append(GetMonth(dt.GetMonth()));
5528 date.Append("-");
5529 date.Append(GetYear(dt.GetYear()));
5530 strncpy(cstr, date.Data(), 9);
5531 cstr[9] = '\0';
5532 svec.push_back(cstr);
5533 // run start time
5534 strncpy(cstr, fData[0].GetStartTime()->Data(), 8);
5535 cstr[8] = '\0';
5536 svec.push_back(cstr);
5537 psibin.PutTimeStartVector(svec);
5538 svec.clear();
5539
5540 // run stop date
5541 // 28-Aug-2014, TP: the following line does not work, it generates the wrong date
5542 //dt.Set(fData[0].GetStopDateTime());
5543 // the following generates the correct date entry
5544 date.Clear();
5545 date.Append(*fData[0].GetStopDate());
5546 sscanf((const char*)date.Data(),"%04d-%02d-%02d", &year, &month, &day);
5547 dt.Set(year, month, day, 0, 0, 0);
5548
5549 date.Form("%02d-", dt.GetDay());
5550 date.Append(GetMonth(dt.GetMonth()));
5551 date.Append("-");
5552 date.Append(GetYear(dt.GetYear()));
5553 strncpy(cstr, date.Data(), 9);
5554 cstr[9] = '\0';
5555 svec.push_back(cstr);
5556 // run stop time
5557 strncpy(cstr, fData[0].GetStopTime()->Data(), 8);
5558 cstr[8] = '\0';
5559 svec.push_back(cstr);
5560 psibin.PutTimeStopVector(svec);
5561 svec.clear();
5562
5563 // number of measured temperatures
5564 psibin.PutNumberTemperatureInt(fData[0].GetNoOfTemperatures());
5565
5566 // mean temperatures
5567 std::vector<double> dvec;
5568 for (UInt_t i=0; i<fData[0].GetNoOfTemperatures(); i++)
5569 dvec.push_back(fData[0].GetTemperature(i));
5570 psibin.PutTemperaturesVector(dvec);
5571
5572 // standard deviation of temperatures
5573 dvec.clear();
5574 for (UInt_t i=0; i<fData[0].GetNoOfTemperatures(); i++)
5575 dvec.push_back(fData[0].GetTempError(i));
5576 psibin.PutDevTemperaturesVector(dvec);
5577
5578 // write comment
5579 psibin.PutComment(fData[0].GetRunTitle()->Data());
5580
5581 // write time resolution
5582 psibin.PutBinWidthNanoSec(fData[0].GetTimeResolution()*fAny2ManyInfo->rebin);
5583
5584 // write scaler dummies
5585 psibin.PutNumberScalerInt(0);
5586
5587 // feed detector related info like, histogram names, t0, fgb, lgb
5588 Int_t ival = 0;
5589 PRawRunDataSet *dataSet;
5590 UInt_t size = fData[0].GetNoOfHistos();
5591 // collect histo names in order to see if they are still unique after cropping to 4 char.
5592 PStringVector hName, hNCrop;
5593 TString sCrop;
5594 for (UInt_t i=0; i<size; i++) {
5595 dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
5596 // detector name
5597 str = dataSet->GetName();
5598 hName.push_back(str);
5599 sCrop = str;
5600 sCrop.Remove(4);
5601 hNCrop.push_back(sCrop);
5602 }
5603 // check cropped for uniqueness
5604 ival = 1;
5605 for (UInt_t i=0; i<size; i++) {
5606 for (UInt_t j=i+1; j<size; j++) {
5607 if (hNCrop[i] == hNCrop[j]) {
5608 std::string nn = std::to_string(ival);
5609 hNCrop[j][3] = nn[0];
5610 ival++;
5611 }
5612 }
5613 }
5614 // handle rest of the detectors
5615 for (UInt_t i=0; i<size; i++) {
5616 dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
5617 if (dataSet == nullptr) { // something is really wrong
5618 std::cerr << std::endl << ">> PRunDataHandler::WritePsiBinFile: **ERROR** Couldn't get data set (idx=" << i << ")";
5619 std::cerr << std::endl << ">> something is really wrong!" << std::endl;
5620 return false;
5621 }
5622
5623 // detector name
5624 psibin.PutNameHisto(hNCrop[i].Data(), i);
5625 // time zero bin
5626 ival = static_cast<Int_t>(dataSet->GetTimeZeroBin()/fAny2ManyInfo->rebin);
5627 psibin.PutT0Int(i, ival);
5628 // first good bin
5629 ival = static_cast<Int_t>(dataSet->GetFirstGoodBin()/fAny2ManyInfo->rebin);
5630 psibin.PutFirstGoodInt(i, ival);
5631 // last good bin
5632 ival = static_cast<Int_t>(dataSet->GetLastGoodBin()/fAny2ManyInfo->rebin);
5633 psibin.PutLastGoodInt(i, ival);
5634 }
5635
5636 // feed histos
5637 std::vector< std::vector<int> > histos;
5638 histos.resize(fData[0].GetNoOfHistos());
5639 UInt_t length = 0;
5640 if (fAny2ManyInfo->rebin == 1) {
5641 for (UInt_t i=0; i<size; i++) {
5642 dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
5643 if (dataSet == nullptr) { // something is really wrong
5644 std::cerr << std::endl << ">> PRunDataHandler::WritePsiBinFile: **ERROR** Couldn't get data set (idx=" << i << ")";
5645 std::cerr << std::endl << ">> something is really wrong!" << std::endl;
5646 return false;
5647 }
5648 length = dataSet->GetData()->size();
5649 histos[i].resize(length);
5650 for (UInt_t j=0; j<length; j++) {
5651 histos[i][j] = static_cast<Int_t>(dataSet->GetData()->at(j));
5652 }
5653 }
5654 } else { // rebin > 1
5655 UInt_t dataRebin = 0;
5656 UInt_t dataCount = 0;
5657 for (UInt_t i=0; i<size; i++) {
5658 dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
5659 if (dataSet == nullptr) { // something is really wrong
5660 std::cerr << std::endl << ">> PRunDataHandler::WritePsiBinFile: **ERROR** Couldn't get data set (idx=" << i << ")";
5661 std::cerr << std::endl << ">> something is really wrong!" << std::endl;
5662 return false;
5663 }
5664 length = dataSet->GetData()->size();
5665 dataCount = 0;
5666 for (UInt_t j=0; j<length; j++) {
5667 if ((j > 0) && (j % fAny2ManyInfo->rebin == 0)) {
5668 dataCount++;
5669 histos[i].push_back(dataRebin);
5670 dataRebin = 0;
5671 }
5672 dataRebin += static_cast<UInt_t>(dataSet->GetData()->at(j));
5673 }
5674 }
5675 }
5676 status = psibin.PutHistoArrayInt(histos, 2); // tag 2 means: lift histo length restriction on only make sure it is < 32512
5677 if (status != 0) {
5678 std::cerr << std::endl << ">> PRunDataHandler::WritePsiBinFile(): " << psibin.ConsistencyStatus() << std::endl;
5679 return false;
5680 }
5681
5682 if (!psibin.CheckDataConsistency(2)) {
5683 std::cerr << std::endl << ">> PRunDataHandler::WritePsiBinFile(): " << psibin.ConsistencyStatus() << std::endl;
5684 return false;
5685 }
5686
5687 // write data to file
5688 status = psibin.Write(fln.Data());
5689
5690 if (status != 0) {
5691 std::cerr << std::endl << ">> PRunDataHandler::WritePsiBinFile(): " << psibin.WriteStatus() << std::endl;
5692 return false;
5693 }
5694
5695 return true;
5696}
5697
5698//--------------------------------------------------------------------------
5699// WriteMudFile (private)
5700//--------------------------------------------------------------------------
5711{
5712 Bool_t ok = false;
5713 fln = GenerateOutputFileName(fln, ".msr", ok);
5714 if (!ok)
5715 return false;
5716
5717 if (!fAny2ManyInfo->useStandardOutput)
5718 std::cout << std::endl << ">> PRunDataHandler::WriteMudFile(): writing a mud data file (" << fln.Data() << ") ... " << std::endl;
5719
5720 // generate the mud data file
5721 int fd = MUD_openWrite((char*)fln.Data(), MUD_FMT_TRI_TD_ID);
5722 if (fd == -1) {
5723 std::cerr << std::endl << ">> PRunDataHandler::WriteMudFile(): **ERROR** couldn't open mud data file for write ..." << std::endl;
5724 return false;
5725 }
5726
5727 // generate header information
5728 char dummy[32], info[128];
5729 strcpy(dummy, "???");
5731 MUD_setExptNumber(fd, 0);
5732 MUD_setRunNumber(fd, fData[0].GetRunNumber());
5733 Int_t ival = fData[0].GetStopDateTime()-fData[0].GetStartDateTime();
5734 MUD_setElapsedSec(fd, ival);
5735 MUD_setTimeBegin(fd, fData[0].GetStartDateTime());
5736 MUD_setTimeEnd(fd, fData[0].GetStopDateTime());
5737 MUD_setTitle(fd, (char *)fData[0].GetRunTitle()->Data());
5738 MUD_setLab(fd, (char *)fData[0].GetLaboratory()->Data());
5739 MUD_setArea(fd, (char *)fData[0].GetBeamline()->Data());
5740 MUD_setMethod(fd, (char *)fData[0].GetSetup()->Data());
5741 MUD_setApparatus(fd, (char *)fData[0].GetInstrument()->Data());
5742 MUD_setInsert(fd, dummy);
5743 MUD_setSample(fd, (char *)fData[0].GetSample()->Data());
5744 MUD_setOrient(fd, (char *)fData[0].GetOrientation()->Data());
5745 MUD_setDas(fd, dummy);
5746 MUD_setExperimenter(fd, dummy);
5747 snprintf(info, sizeof(info), "%lf+-%lf (K)", fData[0].GetTemperature(0), fData[0].GetTempError(0));
5748 MUD_setTemperature(fd, info);
5749 snprintf(info, sizeof(info), "%lf", fData[0].GetField());
5750 MUD_setField(fd, info);
5751
5752 // generate the histograms
5753 MUD_setHists(fd, MUD_GRP_TRI_TD_HIST_ID, fData[0].GetNoOfHistos());
5754
5755 UInt_t *data, dataSize = fData[0].GetDataSet(0, false)->GetData()->size()/fAny2ManyInfo->rebin + 1;
5756 data = new UInt_t[dataSize];
5757 if (data == nullptr) {
5758 std::cerr << std::endl << ">> PRunDataHandler::WriteMudFile(): **ERROR** couldn't allocate memory for the data ..." << std::endl;
5759 MUD_closeWrite(fd);
5760 return false;
5761 }
5762
5763 UInt_t noOfEvents = 0, k = 0;
5764 ival = 0;
5765 PRawRunDataSet *dataSet;
5766 for (UInt_t i=0; i<fData[0].GetNoOfHistos(); i++) {
5767 dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
5768 if (dataSet == nullptr) { // something is really wrong
5769 std::cerr << std::endl << ">> PRunDataHandler::WriteMudFile: **ERROR** Couldn't get data set (idx=" << i << ")";
5770 std::cerr << std::endl << ">> something is really wrong!" << std::endl;
5771 return false;
5772 }
5773
5774 // fill data
5775 for (UInt_t j=0; j<dataSize; j++)
5776 data[j] = 0;
5777 noOfEvents = 0;
5778 k = 0;
5779 for (UInt_t j=0; j<dataSet->GetData()->size(); j++) {
5780 if ((j > 0) && (j % fAny2ManyInfo->rebin == 0)) {
5781 data[k] = ival;
5782 noOfEvents += ival;
5783 k++;
5784 ival = 0;
5785 }
5786 ival += static_cast<UInt_t>(dataSet->GetData()->at(j));
5787 }
5788
5789 // feed data relevant information
5790 // the numbering of the histograms start from '1', hence i+1 needed!!
5791 MUD_setHistType(fd, i+1, MUD_GRP_TRI_TD_HIST_ID);
5792 MUD_setHistNumBytes(fd, i+1, sizeof(data));
5793 MUD_setHistNumBins(fd, i+1, dataSize);
5794 MUD_setHistBytesPerBin(fd, i+1, 0);
5795 MUD_setHistFsPerBin(fd, i+1, static_cast<UINT32>(1.0e6*fAny2ManyInfo->rebin*fData[0].GetTimeResolution())); // time resolution is given in (ns)
5796 MUD_setHistT0_Ps(fd, i+1, static_cast<UINT32>(1.0e3*fData[0].GetTimeResolution()*((dataSet->GetTimeZeroBin()+fAny2ManyInfo->rebin/2)/fAny2ManyInfo->rebin)));
5797 MUD_setHistT0_Bin(fd, i+1, static_cast<UINT32>(dataSet->GetTimeZeroBin()/fAny2ManyInfo->rebin));
5798 MUD_setHistGoodBin1(fd, i+1, static_cast<UINT32>(dataSet->GetFirstGoodBin()/fAny2ManyInfo->rebin));
5799 MUD_setHistGoodBin2(fd, i+1, static_cast<UINT32>(dataSet->GetLastGoodBin()/fAny2ManyInfo->rebin));
5800 MUD_setHistBkgd1(fd, i+1, 0);
5801 MUD_setHistBkgd2(fd, i+1, 0);
5802 MUD_setHistNumEvents(fd, i+1, (UINT32)noOfEvents);
5803 MUD_setHistTitle(fd, i+1, (char *)dataSet->GetName().Data());
5804 REAL64 timeResolution = (fAny2ManyInfo->rebin*fData[0].GetTimeResolution())/1.0e9; // ns -> s
5805 MUD_setHistSecondsPerBin(fd, i+1, timeResolution);
5806
5807 MUD_setHistData(fd, i+1, data);
5808 }
5809
5810 MUD_closeWrite(fd);
5811
5812 delete [] data;
5813
5814 // check if mud file shall be streamed to stdout
5815 if (fAny2ManyInfo->useStandardOutput && (fAny2ManyInfo->compressionTag == 0)) {
5816 // stream file to stdout
5817 std::ifstream is;
5818 int length=1024;
5819 char *buffer;
5820
5821 is.open(fln.Data(), std::ios::binary);
5822 if (!is.is_open()) {
5823 std::cerr << std::endl << "PRunDataHandler::WriteMudFile(): **ERROR** Couldn't open the mud-file for streaming." << std::endl;
5824 remove(fln.Data());
5825 return false;
5826 }
5827
5828 // get length of file
5829 is.seekg(0, std::ios::end);
5830 length = is.tellg();
5831 is.seekg(0, std::ios::beg);
5832
5833 if (length == -1) {
5834 std::cerr << std::endl << "PRunDataHandler::WriteMudFile(): **ERROR** Couldn't determine the mud-file size." << std::endl;
5835 remove(fln.Data());
5836 return false;
5837 }
5838
5839 // allocate memory
5840 buffer = new char [length];
5841
5842 // read data as a block
5843 while (!is.eof()) {
5844 is.read(buffer, length);
5845 std::cout.write(buffer, length);
5846 }
5847
5848 is.close();
5849
5850 delete [] buffer;
5851
5852 // delete temporary root file
5853 remove(fln.Data());
5854 }
5855 return true;
5856}
5857
5858//--------------------------------------------------------------------------
5859// WriteAsciiFile (private)
5860//--------------------------------------------------------------------------
5871{
5872 Bool_t ok = false;
5873 fln = GenerateOutputFileName(fln, ".ascii", ok);
5874 if (!ok)
5875 return false;
5876
5877 TString fileName = fln;
5878
5879 if (!fAny2ManyInfo->useStandardOutput)
5880 std::cout << std::endl << ">> PRunDataHandler::WriteAsciiFile(): writing an ascii data file (" << fln.Data() << ") ... " << std::endl;
5881
5882 // write ascii file
5883 std::ofstream fout;
5884 std::streambuf* strm_buffer = nullptr;
5885
5886 if (!fAny2ManyInfo->useStandardOutput || (fAny2ManyInfo->compressionTag > 0)) {
5887 // open data-file
5888 fout.open(fln.Data(), std::ofstream::out);
5889 if (!fout.is_open()) {
5890 std::cerr << std::endl << ">> PRunDataHandler::WriteAsciiFile **ERROR** Couldn't open data file (" << fln.Data() << ") for writing, sorry ...";
5891 std::cerr << std::endl;
5892 return false;
5893 }
5894
5895 // save output buffer of the stream
5896 strm_buffer = std::cout.rdbuf();
5897
5898 // redirect output into the file
5899 std::cout.rdbuf(fout.rdbuf());
5900 }
5901
5902 // write header
5903 std::cout << "%*************************************************************************";
5904 std::cout << std::endl << "% file name : " << fileName.Data();
5905 if (fData[0].GetRunTitle()->Length() > 0)
5906 std::cout << std::endl << "% title : " << fData[0].GetRunTitle()->Data();
5907 if (fData[0].GetRunNumber() >= 0)
5908 std::cout << std::endl << "% run number : " << fData[0].GetRunNumber();
5909 if (fData[0].GetSetup()->Length() > 0)
5910 std::cout << std::endl << "% setup : " << fData[0].GetSetup()->Data();
5911 std::cout << std::endl << "% field : " << fData[0].GetField() << " (G)";
5912 if (fData[0].GetStartTime()->Length() > 0)
5913 std::cout << std::endl << "% date : " << fData[0].GetStartTime()->Data() << " " << fData[0].GetStartDate()->Data() << " / " << fData[0].GetStopTime()->Data() << " " << fData[0].GetStopDate()->Data();
5914 if (fData[0].GetNoOfTemperatures() > 0) {
5915 std::cout << std::endl << "% temperature : ";
5916 for (UInt_t i=0; i<fData[0].GetNoOfTemperatures()-1; i++) {
5917 std::cout << fData[0].GetTemperature(i) << "+-" << fData[0].GetTempError(i) << "(K) , ";
5918 }
5919 std::cout << fData[0].GetTemperature(fData[0].GetNoOfTemperatures()-1) << "+-" << fData[0].GetTempError(fData[0].GetNoOfTemperatures()-1) << "(K)";
5920 }
5921 if (fData[0].GetEnergy() != PMUSR_UNDEFINED)
5922 std::cout << std::endl << "% energy : " << fData[0].GetEnergy() << " (keV)";
5923 if (fData[0].GetTransport() != PMUSR_UNDEFINED)
5924 std::cout << std::endl << "% transport : " << fData[0].GetTransport() << " (kV)";
5925 if (fData[0].GetTimeResolution() != PMUSR_UNDEFINED) {
5926 std::cout.precision(10);
5927 std::cout << std::endl << "% time resolution : " << fData[0].GetTimeResolution()*fAny2ManyInfo->rebin << " (ns)";
5928 std::cout.setf(std::ios::fixed,std::ios::floatfield); // floatfield set to fixed
5929 }
5930 PRawRunDataSet *dataSet;
5931 std::cout << std::endl << "% t0 : ";
5932 for (UInt_t i=0; i<fData[0].GetNoOfHistos()-1; i++) {
5933 dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
5934 std::cout << static_cast<UInt_t>(dataSet->GetTimeZeroBin()/fAny2ManyInfo->rebin) << ", ";
5935 }
5936 dataSet = fData[0].GetDataSet(fData[0].GetNoOfHistos()-1, false); // i.e. the false means, that i is the index and NOT the histo number
5937 std::cout << static_cast<UInt_t>(dataSet->GetTimeZeroBin()/fAny2ManyInfo->rebin);
5938
5939 std::cout << std::endl << "% # histos : " << fData[0].GetNoOfHistos();
5940 dataSet = fData[0].GetDataSet(0, false); // i.e. the false means, that i is the index and NOT the histo number
5941 std::cout << std::endl << "% # of bins : " << static_cast<UInt_t>(dataSet->GetData()->size()/fAny2ManyInfo->rebin);
5942 std::cout << std::endl << "%*************************************************************************";
5943
5944 // write data
5945 UInt_t length = fData[0].GetDataSet(0,false)->GetData()->size();
5946 if (fAny2ManyInfo->rebin == 1) {
5947 for (UInt_t i=0; i<length; i++) {
5948 std::cout << std::endl;
5949 for (UInt_t j=0; j<fData[0].GetNoOfHistos(); j++) {
5950 dataSet = fData[0].GetDataSet(j, false); // i.e. the false means, that i is the index and NOT the histo number
5951 std::cout.width(8);
5952 std::cout << static_cast<Int_t>(dataSet->GetData()->at(i));
5953 }
5954 }
5955 } else {
5956 PUIntVector dataRebin(fData[0].GetNoOfHistos());
5957
5958 // initialize the dataRebin vector
5959 for (UInt_t i=0; i<dataRebin.size(); i++) {
5960 dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
5961 dataRebin[i] = static_cast<UInt_t>(dataSet->GetData()->at(0));
5962 }
5963
5964 for (UInt_t i=0; i<length; i++) {
5965 if ((i > 0) && ((i % fAny2ManyInfo->rebin) == 0)) {
5966 std::cout << std::endl;
5967 for (UInt_t j=0; j<dataRebin.size(); j++) {
5968 std::cout.width(8);
5969 std::cout << dataRebin[j];
5970 }
5971 // initialize the dataRebin vector for the next pack
5972 for (UInt_t j=0; j<dataRebin.size(); j++) {
5973 dataSet = fData[0].GetDataSet(j, false); // i.e. the false means, that i is the index and NOT the histo number
5974 dataRebin[j] = static_cast<UInt_t>(dataSet->GetData()->at(i));
5975 }
5976 } else {
5977 for (UInt_t j=0; j<fData[0].GetNoOfHistos(); j++) {
5978 dataSet = fData[0].GetDataSet(j, false); // i.e. the false means, that i is the index and NOT the histo number
5979 dataRebin[j] += static_cast<UInt_t>(dataSet->GetData()->at(i));
5980 }
5981 }
5982 }
5983 }
5984
5985 std::cout << std::endl;
5986
5987 if (!fAny2ManyInfo->useStandardOutput || (fAny2ManyInfo->compressionTag > 0)) {
5988 // restore old output buffer
5989 std::cout.rdbuf(strm_buffer);
5990
5991 fout.close();
5992 }
5993
5994 return true;
5995}
5996
5997
5998//--------------------------------------------------------------------------
5999// StripWhitespace (private)
6000//--------------------------------------------------------------------------
6012{
6013 Char_t *s = nullptr;
6014 Char_t *subs = nullptr;
6015 Int_t i;
6016 Int_t start;
6017 Int_t end;
6018 Int_t size;
6019
6020 size = static_cast<Int_t>(str.Length());
6021 s = new Char_t[size+1];
6022
6023 if (!s)
6024 return false;
6025
6026 for (Int_t i=0; i<size+1; i++)
6027 s[i] = str[i];
6028 s[size] = 0;
6029
6030 // check for whitespaces at the beginning of the string
6031 i = 0;
6032 while (isblank(s[i]) || iscntrl(s[i])) {
6033 i++;
6034 }
6035 start = i;
6036
6037 // check for whitespaces at the end of the string
6038 i = strlen(s);
6039 while (isblank(s[i]) || iscntrl(s[i])) {
6040 i--;
6041 }
6042 end = i;
6043
6044 if (end < start)
6045 return false;
6046
6047 // make substring
6048 subs = new Char_t[end-start+2];
6049 if (!subs)
6050 return false;
6051
6052 strncpy(subs, s+start, end-start+1);
6053 subs[end-start+1] = '\0';
6054
6055 str = TString(subs);
6056
6057 // clean up
6058 if (subs) {
6059 delete [] subs;
6060 subs = nullptr;
6061 }
6062 if (s) {
6063 delete [] s;
6064 s = nullptr;
6065 }
6066
6067 return true;
6068}
6069
6070//--------------------------------------------------------------------------
6071// IsWhitespace (private)
6072//--------------------------------------------------------------------------
6083Bool_t PRunDataHandler::IsWhitespace(const Char_t *str)
6084{
6085 UInt_t i=0;
6086
6087 while (isblank(str[i]) || iscntrl(str[i])) {
6088 if (str[i] == 0)
6089 break;
6090 i++;
6091 }
6092
6093 if (i == strlen(str))
6094 return true;
6095 else
6096 return false;
6097}
6098
6099//--------------------------------------------------------------------------
6100// ToDouble (private)
6101//--------------------------------------------------------------------------
6112Double_t PRunDataHandler::ToDouble(TString &str, Bool_t &ok)
6113{
6114 Char_t *s;
6115 Double_t value;
6116 Int_t size, status;
6117
6118 ok = true;
6119
6120 size = static_cast<Int_t>(str.Length());
6121 s = new Char_t[size+1];
6122
6123 if (!s) {
6124 ok = false;
6125 return 0.0;
6126 }
6127
6128 // copy string; stupid way but it works
6129 for (Int_t i=0; i<size+1; i++)
6130 s[i] = str[i];
6131 s[size] = 0;
6132
6133 // extract value
6134 status = sscanf(s, "%lf", &value);
6135 if (status != 1) {
6136 ok = false;
6137 return 0.0;
6138 }
6139
6140 // clean up
6141 if (s) {
6142 delete [] s;
6143 s = nullptr;
6144 }
6145
6146 return value;
6147}
6148
6149//--------------------------------------------------------------------------
6150// ToInt (private)
6151//--------------------------------------------------------------------------
6162Int_t PRunDataHandler::ToInt(TString &str, Bool_t &ok)
6163{
6164 Char_t *s;
6165 Int_t value;
6166 Int_t size, status;
6167
6168 ok = true;
6169
6170 size = static_cast<Int_t>(str.Length());
6171 s = new Char_t[size+1];
6172
6173 if (!s) {
6174 ok = false;
6175 return 0;
6176 }
6177
6178 // copy string; stupid way but it works
6179 for (Int_t i=0; i<size+1; i++)
6180 s[i] = str[i];
6181 s[size] = 0;
6182
6183 // extract value
6184 status = sscanf(s, "%d", &value);
6185 if (status != 1) {
6186 ok = false;
6187 return 0;
6188 }
6189
6190 // clean up
6191 if (s) {
6192 delete [] s;
6193 s = nullptr;
6194 }
6195
6196 return value;
6197}
6198
6199//--------------------------------------------------------------------------
6200// GetDataTagIndex (private)
6201//--------------------------------------------------------------------------
6212Int_t PRunDataHandler::GetDataTagIndex(TString &str, const PStringVector* dataTags)
6213{
6214 Int_t result = -1;
6215
6216 // check all the other possible data tags
6217 for (UInt_t i=0; i<dataTags->size(); i++) {
6218 if (!dataTags->at(i).CompareTo(str, TString::kIgnoreCase)) {
6219 result = i;
6220 break;
6221 }
6222 }
6223
6224 return result;
6225}
6226
6227
6228//--------------------------------------------------------------------------
6229// GenerateOutputFileName (private)
6230//--------------------------------------------------------------------------
6244TString PRunDataHandler::GenerateOutputFileName(const TString fileName, const TString extension, Bool_t &ok)
6245{
6246 TString fln = fileName;
6247 ok = true;
6248
6249 if (fAny2ManyInfo == nullptr)
6250 return fln;
6251
6252 // generate output file name if needed
6253 if (!fAny2ManyInfo->useStandardOutput || (fAny2ManyInfo->compressionTag > 0)) {
6254 if (fln.Length() == 0) {
6255 ok = false;
6256 fln = GetFileName(extension, ok);
6257 if (!ok) {
6258 fln = "";
6259 return fln;
6260 }
6261 } else {
6262 fln.Prepend(fAny2ManyInfo->outPath);
6263 }
6264
6265 // make sure that the file name doesn't already exist as a real file
6266 if (!gSystem->AccessPathName(fln)) { // file name already exists!!
6267 Int_t count = 1;
6268 TString newFln;
6269 do {
6270 newFln = fln;
6271 newFln.Insert(newFln.Last('.'), TString::Format(".%d", count++));
6272 } while (!gSystem->AccessPathName(newFln));
6273 std::cerr << std::endl << ">> PRunDataHandler::GenerateOutputFileName **WARNING** needed to modify output filename to " << newFln << ",";
6274 std::cerr << std::endl << ">> due to potential conflict with already existing files." << std::endl << std::endl;
6275 fln = newFln;
6276 }
6277
6278 // keep the file name if compression is whished
6279 fAny2ManyInfo->outPathFileName.push_back(fln);
6280 } else {
6281 fln = fAny2ManyInfo->outPath + TString("__tmp.") + extension;
6282 }
6283
6284 return fln;
6285}
6286
6287//--------------------------------------------------------------------------
6288// GetFileName (private)
6289//--------------------------------------------------------------------------
6300TString PRunDataHandler::GetFileName(const TString extension, Bool_t &ok)
6301{
6302 TString fileName = "";
6303 ok = true;
6304
6305 Int_t start = fRunPathName.Last('/');
6306 Int_t end = fRunPathName.Last('.');
6307 if (end == -1) {
6308 std::cerr << std::endl << ">> PRunDataHandler::GetFileName(): **ERROR** couldn't generate the output file name ..." << std::endl;
6309 ok = false;
6310 return fileName;
6311 }
6312 // cut out the filename (get rid of the extension, and the path)
6313 Char_t str1[1024], str2[1024];
6314 strncpy(str1, fRunPathName.Data(), sizeof(str1));
6315 for (Int_t i=0; i<end-start-1; i++) {
6316 str2[i] = str1[i+start+1];
6317 }
6318 str2[end-start-1] = 0;
6319
6320 if (fAny2ManyInfo->inFormat == fAny2ManyInfo->outFormat) { // only rebinning
6321 TString rebinStr;
6322 rebinStr += fAny2ManyInfo->rebin;
6323 fileName = fAny2ManyInfo->outPath + str2 + "_rebin" + rebinStr + extension;
6324 } else { // real conversion
6325 fileName = fAny2ManyInfo->outPath + str2 + extension;
6326 }
6327
6328 return fileName;
6329}
6330
6331//--------------------------------------------------------------------------
6332// FileNameFromTemplate (private)
6333//--------------------------------------------------------------------------
6351TString PRunDataHandler::FileNameFromTemplate(TString &fileNameTemplate, Int_t run, TString &year, Bool_t &ok)
6352{
6353 TString result("");
6354
6355 TString str;
6356
6357 // check year string
6358 if ((year.Length() != 2) && (year.Length() != 4)) {
6359 std::cerr << std::endl << ">> PRunDataHandler::FileNameFromTemplate: **ERROR** year needs to be of the format";
6360 std::cerr << std::endl << ">> 'yy' or 'yyyy', found " << year << std::endl;
6361 return result;
6362 }
6363
6364 // make a short year version 'yy' and a long year version 'yyyy'
6365 TString yearShort="", yearLong="";
6366 if (year.Length() == 2) {
6367 yearShort = year;
6368 yearLong = "20" ;
6369 yearLong += year;
6370 } else {
6371 yearShort = year[2];
6372 yearShort += year[3];
6373 yearLong = year;
6374 }
6375
6376 // tokenize template string
6377 std::vector<std::string> tok = PStringUtils::Split(fileNameTemplate.Data(), "[]");
6378 if (tok.empty()) {
6379 std::cerr << std::endl << ">> PRunDataHandler::FileNameFromTemplate: **ERROR** couldn't tokenize template!" << std::endl;
6380 return result;
6381 }
6382 if (tok.size()==1) {
6383 std::cerr << std::endl << ">> PRunDataHandler::FileNameFromTemplate: **WARNING** template without tags." << std::endl;
6384 }
6385
6386 // go through the tokens and generate the result string
6387 for (UInt_t i=0; i<tok.size(); i++) {
6388 str = TString(tok[i]);
6389
6390 // check tokens
6391 if (!str.CompareTo("yy", TString::kExact)) { // check for 'yy'
6392 result += yearShort;
6393 } else if (!str.CompareTo("yyyy", TString::kExact)) { // check for 'yyyy'
6394 result += yearLong;
6395 } else if (str.Contains("rr")) { // check for run
6396 // make sure ONLY 'r' are present
6397 Int_t idx;
6398 for (idx=0; idx<str.Length(); idx++) {
6399 if (str[idx] != 'r')
6400 break;
6401 }
6402 if (idx == str.Length()) { // 'r' only
6403 TString runStr("");
6404 char fmt[128];
6405 snprintf(fmt, sizeof(fmt), "%%0%dd", str.Length());
6406 runStr.Form(fmt, run);
6407 result += runStr;
6408 } else { // not only 'r'
6409 result += str;
6410 }
6411 } else { // all parts which are NOT tags
6412 result += str;
6413 }
6414 }
6415
6416 // everything fine here
6417 ok = true;
6418
6419 return result;
6420}
6421
6422//--------------------------------------------------------------------------
6423// DateToISO8601 (private)
6424//--------------------------------------------------------------------------
6433bool PRunDataHandler::DateToISO8601(std::string inDate, std::string &iso8601Date)
6434{
6435 iso8601Date = std::string("");
6436
6437 struct tm tm;
6438
6439 // currently only dates like dd-mmm-yy are handled, where dd day of the month, mmm month as abbrivation, e.g. JAN, and yy as the year
6440 if (!strptime(inDate.c_str(), "%d-%b-%y", &tm)) // failed
6441 return false;
6442
6443 TString str("");
6444 str.Form("%04d-%02d-%02d", 1900+tm.tm_year, tm.tm_mon+1, tm.tm_mday);
6445
6446 iso8601Date = str.Data();
6447
6448 return true;
6449}
6450
6451//--------------------------------------------------------------------------
6452// SplitTimeData (private)
6453//--------------------------------------------------------------------------
6463void PRunDataHandler::SplitTimeDate(TString timeData, TString &time, TString &date, Bool_t &ok)
6464{
6465 struct tm tm;
6466 memset(&tm, 0, sizeof(tm));
6467 strptime(timeData.Data(), "%Y-%m-%d %H:%M:S", &tm);
6468 if (tm.tm_year == 0)
6469 strptime(timeData.Data(), "%Y-%m-%dT%H:%M:S", &tm);
6470
6471 if (tm.tm_year == 0) {
6472 ok = false;
6473 return;
6474 }
6475
6476 time = TString::Format("%02d:%02d:%02d", tm.tm_hour, tm.tm_min, tm.tm_sec);
6477 date = TString::Format("%04d-%02d-%02d", tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday);
6478}
6479
6480//--------------------------------------------------------------------------
6481// GetMonth (private)
6482//--------------------------------------------------------------------------
6490TString PRunDataHandler::GetMonth(Int_t month)
6491{
6492 TString monthString = "???";
6493
6494 switch (month) {
6495 case 1:
6496 monthString = "JAN";
6497 break;
6498 case 2:
6499 monthString = "FEB";
6500 break;
6501 case 3:
6502 monthString = "MAR";
6503 break;
6504 case 4:
6505 monthString = "APR";
6506 break;
6507 case 5:
6508 monthString = "MAY";
6509 break;
6510 case 6:
6511 monthString = "JUN";
6512 break;
6513 case 7:
6514 monthString = "JUL";
6515 break;
6516 case 8:
6517 monthString = "AUG";
6518 break;
6519 case 9:
6520 monthString = "SEP";
6521 break;
6522 case 10:
6523 monthString = "OCT";
6524 break;
6525 case 11:
6526 monthString = "NOV";
6527 break;
6528 case 12:
6529 monthString = "DEC";
6530 break;
6531 default:
6532 break;
6533 }
6534
6535 return monthString;
6536}
6537
6538//--------------------------------------------------------------------------
6539// GetYear (private)
6540//--------------------------------------------------------------------------
6548TString PRunDataHandler::GetYear(Int_t year)
6549{
6550 TString yearString = "??";
6551 Int_t yy=0;
6552
6553 if (year < 2000) {
6554 yy = year - 1900;
6555 if (yy > 0)
6556 yearString.Form("%02d", yy);
6557 } else {
6558 yy = year - 2000;
6559 if ((yy >= 0) && (yy <= 99))
6560 yearString.Form("%02d", yy);
6561 }
6562
6563 return yearString;
6564}
#define POST_PILEUP_HISTO_OFFSET
Definition PMusr.h:168
std::vector< UInt_t > PUIntVector
Definition PMusr.h:375
std::vector< PMsrRunBlock > PMsrRunList
Definition PMusr.h:1263
#define PMUSR_UNDEFINED
Definition PMusr.h:177
std::vector< Bool_t > PBoolVector
Definition PMusr.h:369
std::vector< Int_t > PIntVector
Definition PMusr.h:381
std::vector< TString > PStringVector
Definition PMusr.h:417
std::vector< Double_t > PDoubleVector
Definition PMusr.h:399
NeXus HDF4/HDF5 file reader and writer for muon spin rotation data.
#define PRH_MUSR_ROOT_DIR
#define PHR_INIT_ANY2MANY
#define PHR_INIT_ALL
#define PRH_LEM_ROOT
#define PRH_PPC_OFFSET
#define PRH_MUSR_ROOT
#define PHR_INIT_MSR
return status
#define MRH_UNDEFINED
int Write(const char *fileName)
Method to write a PSI-bin or an MDU file.
std::string GetOrient()
Method returning a string containing the orientation specified in the title.
int PutDevTemperaturesVector(std::vector< double > &devTemps)
Method setting a vector of doubles containing standard deviations of the monitored values (usually te...
int PutNameHisto(std::string histoName, int i)
Method setting a string containing the name of the histogram <i>
std::vector< int > GetT0Vector()
Method returning a vector of integer containing the t0 values of the histograms specified in the head...
std::string GetNameHisto(int i)
Method returning a string containing the name of the histogram <i>
int PutNumberTemperatureInt(int noOfTemps)
Method setting an integer representing the number of temperatures.
int PutFirstGoodInt(int i, int j)
Method setting an integer representing the first good bin specified in the header for a specified his...
int PutTemp(std::string temp)
Method setting a string containing the fSample temperature.
bool CheckDataConsistency(int tag=0)
Check if a given set of data is consistent with the PSI-BIN limitations. If false,...
int PutSample(std::string sample)
Method setting a string containing the fSample name.
std::vector< double > GetTemperaturesVector()
Method returning a vector of doubles containing monitored values (usually temperatures)
std::vector< int > GetLastGoodVector()
Method returning a vector of integer containing the last good bin values of the histograms specified ...
std::vector< int > GetHistoArrayInt(int histo_num)
Method to obtain an array of type integer containing the values of the histogram <histo_num>
int PutT0Int(int histoNo, int t0)
Method setting an integer representing the t0 point (from the "integer" t0 in the header) for a speci...
std::string ConsistencyStatus() const
Method to obtain error/success information on data consistency check.
std::string GetField()
Method returning a string containing the field specified in the title.
void PutNumberHistoInt(int val)
int PutField(std::string field)
Method setting a string containing the field.
int PutComment(std::string comment)
Method setting a string containing the comment.
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 ...
int PutHistoArrayInt(std::vector< std::vector< int > > &histo, int tag=0)
Method to set the histograms which is a vector of vector of int's (histogram). There are two differen...
std::vector< int > GetFirstGoodVector()
Method returning a vector of integer containing the first good bin values of the histograms specified...
int PutLastGoodInt(int i, int j)
Method to modify the last good bin (value <j>) of the histogram <i>
std::vector< std::string > GetTimeStopVector()
Method returning a vector of strings containing 1) the date when the run was stopped and 2) the time ...
void PutBinWidthNanoSec(double binWidth)
Method setting a double representing the bin-width in nanoseconds.
std::vector< double > GetDevTemperaturesVector()
Method returning a vector of doubles containing standard deviations of the monitored values (usually ...
std::string WriteStatus() const
Method to obtain error/success information after writing.
int PutTimeStartVector(std::vector< std::string > timeStart)
Method setting a vector of strings containing 1) the date when the run was started and 2) the time wh...
double GetBinWidthNanoSec()
Method returning a double representing the bin-width in nanoseconds.
int PutRunNumberInt(int i)
Method to modify the run number (value <i>)
int Read(const char *fileName)
Method to read a PSI-bin or an MDU file.
int PutSetup(std::string setup)
Method setting a string containing the setup.
int PutNumberScalerInt(int val)
Method seting the number of scalers present.
std::string GetSample()
Method returning a string containing the fSample name.
void PutHistoLengthBin(int val)
std::string GetComment()
Method returning a string containing the comment specified in the title.
int PutTemperaturesVector(std::vector< double > &temps)
Method setting a vector of doubles containing monitored values (usually temperatures)
int PutOrient(std::string orientation)
Method setting a string containing the fSample orientation.
int PutTimeStopVector(std::vector< std::string > timeStop)
Method setting a vector of strings containing 1) the date when the run was started and 2) the time wh...
MSR file parser and manager for the musrfit framework.
virtual TString * GetInstitute(UInt_t idx=0)
Definition PMusr.cpp:1419
virtual TString * GetFileFormat(UInt_t idx=0)
Definition PMusr.cpp:1461
virtual void SetBeamline(TString &str, Int_t idx=-1)
Definition PMusr.cpp:1394
virtual TString * GetBeamline(UInt_t idx=0)
Definition PMusr.cpp:1377
virtual void SetFileFormat(TString &str, Int_t idx=-1)
Definition PMusr.cpp:1478
virtual TString * GetRunName(UInt_t idx=0)
Definition PMusr.cpp:1335
virtual void SetInstitute(TString &str, Int_t idx=-1)
Definition PMusr.cpp:1436
virtual void AppendLabel(const TString str)
Definition PMusr.h:589
virtual void AppendErrData(const PDoubleVector &data)
Definition PMusr.h:607
virtual void AppendSubErrData(const UInt_t idx, const Double_t dval)
Definition PMusr.cpp:229
virtual const PStringVector * GetDataTags()
Returns pointer to vector of data tags (identifiers for each data column)
Definition PMusr.h:570
virtual void AppendDataTag(const TString str)
Definition PMusr.h:601
virtual void AppendSubData(const UInt_t idx, const Double_t dval)
Definition PMusr.cpp:209
virtual void SetFromAscii(const Bool_t bval)
Definition PMusr.h:578
virtual const std::vector< PDoubleVector > * GetData()
Returns pointer to vector of data columns.
Definition PMusr.h:572
virtual const PStringVector * GetLabels()
Returns pointer to vector of axis/column labels.
Definition PMusr.h:568
virtual const std::vector< PDoubleVector > * GetErrData()
Returns pointer to vector of error data columns.
Definition PMusr.h:574
virtual void SetSize(const UInt_t size)
Definition PMusr.cpp:162
virtual void AppendData(const PDoubleVector &data)
Definition PMusr.h:604
virtual void SetLabel(const UInt_t idx, const TString str)
Definition PMusr.cpp:189
virtual Int_t GetFirstGoodBin()
Returns the first bin of good data range (after prompt peak)
Definition PMusr.h:661
virtual PDoubleVector * GetData()
Returns pointer to raw histogram data vector (counts per bin)
Definition PMusr.h:669
virtual void SetLastBkgBin(Int_t lbb)
Definition PMusr.h:699
virtual void Clear()
Clears all data from this histogram set.
Definition PMusr.cpp:261
virtual void SetLastGoodBin(Int_t lgb)
Definition PMusr.h:693
virtual Double_t GetTimeZeroBin()
Returns the time-zero bin (t0) position.
Definition PMusr.h:657
virtual void SetHistoNo(Int_t no)
Definition PMusr.h:681
virtual void SetData(PDoubleVector data)
Definition PMusr.h:702
virtual Int_t GetHistoNo()
Returns the histogram number as stored in the data file.
Definition PMusr.h:655
virtual TString GetName()
Returns the histogram name.
Definition PMusr.h:653
virtual void SetName(TString str)
Definition PMusr.h:678
virtual Int_t GetLastGoodBin()
Returns the last bin of good data range.
Definition PMusr.h:663
virtual void SetTimeZeroBinEstimated(Double_t tzb)
Definition PMusr.h:687
virtual void SetFirstBkgBin(Int_t fbb)
Definition PMusr.h:696
virtual void SetTitle(TString str)
Definition PMusr.h:675
virtual void SetTimeZeroBin(Double_t tzb)
Definition PMusr.h:684
virtual void SetFirstGoodBin(Int_t fgb)
Definition PMusr.h:690
virtual void SetStopDate(const TString str)
Definition PMusr.h:920
virtual void SetRingAnode(const UInt_t idx, const Double_t dval)
Definition PMusr.cpp:784
PNonMusrRawRunData fDataNonMusr
keeps all ascii- or db-file info in case of nonMusr fit
Definition PMusr.h:940
virtual void SetGenerator(const TString &str)
Definition PMusr.h:902
virtual const PDoubleVector * GetDataBin(const UInt_t histoNo)
Definition PMusr.h:896
virtual const Double_t GetTimeResolution()
Definition PMusr.h:882
virtual void SetMuonSource(const TString &str)
Definition PMusr.h:908
virtual void SetTimeResolution(const Double_t dval)
Definition PMusr.h:933
virtual void SetSample(const TString str)
Definition PMusr.h:925
virtual void SetVersion(const TString &str)
Definition PMusr.h:899
virtual void SetEnergy(const Double_t dval)
Definition PMusr.h:930
virtual void SetStartDate(const TString str)
Definition PMusr.h:917
virtual void SetTransport(const Double_t dval)
Definition PMusr.h:931
virtual void SetRunName(const TString &str)
Definition PMusr.h:912
virtual void SetOrientation(const TString str)
Definition PMusr.h:926
virtual void SetRedGreenOffset(PIntVector &ivec)
Definition PMusr.h:934
virtual void SetSetup(const TString str)
Definition PMusr.h:915
virtual void SetStopTime(const TString str)
Definition PMusr.h:919
virtual void SetSpecificValidatorUrl(const TString &str)
Definition PMusr.h:901
virtual void SetStopDateTime(const time_t val)
Definition PMusr.h:921
virtual void SetRunTitle(const TString str)
Definition PMusr.h:914
virtual void SetMuonSpinAngle(const Double_t dval)
Definition PMusr.h:911
virtual void SetTemperature(const UInt_t idx, const Double_t temp, const Double_t errTemp)
Definition PMusr.cpp:801
virtual void SetCryoName(const TString str)
Definition PMusr.h:924
virtual void SetFileName(const TString &str)
Definition PMusr.h:904
virtual void SetComment(const TString &str)
Definition PMusr.h:903
virtual void SetMuonSpecies(const TString &str)
Definition PMusr.h:909
virtual void SetBeamline(const TString &str)
Definition PMusr.h:906
virtual void SetTempError(const UInt_t idx, const Double_t errTemp)
Definition PMusr.cpp:819
virtual void SetRunNumber(const Int_t &val)
Definition PMusr.h:913
virtual void ClearTemperature()
Definition PMusr.h:927
virtual void SetMuonBeamMomentum(const Double_t dval)
Definition PMusr.h:910
virtual void SetInstrument(const TString &str)
Definition PMusr.h:907
virtual void SetStartDateTime(const time_t val)
Definition PMusr.h:918
virtual void SetField(const Double_t dval)
Definition PMusr.h:923
virtual void SetStartTime(const TString str)
Definition PMusr.h:916
virtual const UInt_t GetNoOfHistos()
Definition PMusr.h:893
virtual void SetLaboratory(const TString &str)
Definition PMusr.h:905
virtual void SetMagnetName(const TString str)
Definition PMusr.h:922
virtual void SetDataSet(PRawRunDataSet &dataSet, UInt_t idx=-1)
Definition PMusr.h:938
virtual void SetGenericValidatorUrl(const TString &str)
Definition PMusr.h:900
PRunDataHandler()
Default constructor creating an uninitialized handler.
PMsrHandler * fMsrInfo
Pointer to MSR file handler (not owned, don't delete)
virtual TString FileNameFromTemplate(TString &fileNameTemplate, Int_t run, TString &year, Bool_t &ok)
virtual void SplitTimeDate(TString timeDate, TString &time, TString &date, Bool_t &ok)
virtual Bool_t ReadAsciiFile()
virtual Bool_t ReadWkmFile()
virtual Bool_t ReadRootFile()
Bool_t ReadNexusFileIdf2(T &nxs_file)
virtual Bool_t WriteWkmFile(TString fln="")
TString fRunName
Current run name being processed (used during file reading)
virtual Bool_t ReadDBFile()
virtual void ReadData()
Reads all data files specified in MSR file or configuration.
virtual Bool_t StripWhitespace(TString &str)
virtual Bool_t IsWhitespace(const Char_t *str)
virtual Bool_t ReadFilesMsr()
Bool_t ReadNexusFileIdf1(T &nxs_file)
Bool_t fAllDataAvailable
Flag: true if all requested data files loaded successfully, false if any failed.
virtual Int_t ToInt(TString &str, Bool_t &ok)
PRawRunDataList fData
List of all loaded raw run data (histograms + metadata)
virtual Bool_t WriteData(TString fileName="")
Writes data to file in the specified format.
virtual Bool_t ReadNexusFile()
virtual TString GenerateOutputFileName(const TString fileName, const TString extension, Bool_t &ok)
virtual Bool_t WriteAsciiFile(TString fln="")
virtual Bool_t ReadMudFile()
virtual Bool_t FileExistsCheck(PMsrRunBlock &runInfo, const UInt_t idx)
virtual Bool_t WritePsiBinFile(TString fln="")
virtual PRawRunData * GetRunData(const TString &runName)
Retrieves run data by run name.
virtual TString GetFileName(const TString extension, Bool_t &ok)
virtual Bool_t WriteMudFile(TString fln="")
TString fFileFormat
Explicitly specified file format (overrides auto-detection)
virtual TString GetMonth(Int_t month)
virtual Bool_t WriteMusrRootFile(Int_t tag=A2M_MUSR_ROOT_DIR, TString fln="")
virtual Int_t GetDataTagIndex(TString &str, const PStringVector *fLabels)
virtual Bool_t ReadMduAsciiFile()
virtual Bool_t WriteRootFile(TString fln="")
PStringVector fDataPath
Search paths for data files (checked sequentially until file found)
TString fRunPathName
Full path to current data file being read.
virtual ~PRunDataHandler()
Virtual destructor that frees all loaded data.
virtual void TestFileName(TString &runName, const TString &ext)
virtual Bool_t WriteNexusFile(TString format, TString fln="")
virtual bool DateToISO8601(std::string inDate, std::string &iso8601Date)
virtual Bool_t ReadWriteFilesList()
virtual Bool_t SetRunData(PRawRunData *data, UInt_t idx=0)
Sets or replaces run data at specified index.
virtual void Init(const Int_t tag=0)
PAny2ManyInfo * fAny2ManyInfo
Pointer to any2many conversion configuration (not owned, don't delete)
virtual Bool_t FileAlreadyRead(TString runName)
virtual Bool_t ReadPsiBinFile()
virtual Bool_t ReadDatFile()
virtual TString GetYear(Int_t month)
virtual Double_t ToDouble(TString &str, Bool_t &ok)
virtual void ConvertData()
Performs format conversion (for any2many utility).
virtual Double_t GetError() const
virtual Double_t GetValue() const
virtual void Set(TString label, Double_t demand, Double_t value, Double_t error, TString unit, TString description=TString("n/a"))
virtual TString GetUnit() const
#define A2M_NEXUS
NeXus HDF5 format (ISIS, JPARC standard - self-describing, hierarchical)
#define A2M_MUD
TRIUMF MUD (Muon Data) format (TRIUMF's standard binary format)
#define A2M_ROOT
Generic ROOT file (minimal structure, basic histograms only)
#define A2M_PSIBIN
PSI binary format (legacy PSI format, platform-specific byte ordering)
#define A2M_ASCII
Generic ASCII format (two-column time-value data for non-μSR applications)
#define A2M_MUSR_ROOT
MusrRoot format (PSI-specific ROOT with complete metadata and run info)
#define A2M_WKM
WKM format (older PSI format, deprecated but still supported for legacy data)
#define A2M_UNDEFINED
Undefined or unknown format (used for error indication)
#define A2M_PSIMDU
PSI MDU ASCII format (ASCII variant of PSI format with metadata)
#define A2M_MUSR_ROOT_DIR
MusrRoot with directory structure (organized by run number, year, etc.)
unsigned long UINT32
Definition mud.h:146
#define MUD_SEC_GEN_RUN_DESC_ID
Definition mud.h:73
#define MUD_GRP_TRI_TD_HIST_ID
Definition mud.h:90
#define MUD_FMT_TRI_TD_ID
Definition mud.h:57
double REAL64
Definition mud.h:149
int MUD_getHistSecondsPerBin(int fd, int num, REAL64 *pSecondsPerBin)
int MUD_setHistData(int fd, int num, void *pData)
int MUD_openWrite(char *filename, UINT32 type)
int MUD_setHistSecondsPerBin(int fd, int num, REAL64 secondsPerBin)
int MUD_setHists(int fd, UINT32 type, UINT32 num)
int MUD_closeWrite(int fd)
int MUD_setRunDesc(int fd, UINT32 type)
int MUD_openRead(char *filename, UINT32 *pType)
int MUD_getHistData(int fd, int num, void *pData)
int MUD_closeRead(int fd)
@ kFLOAT32
32-bit floating point (DFNT_FLOAT32)
Definition PNeXus.h:331
@ kCHAR8
8-bit character (DFNT_CHAR8)
Definition PNeXus.h:333
@ kINT32
32-bit signed integer (DFNT_INT32)
Definition PNeXus.h:330
Common utilities for NeXus file handling.
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
std::string getIso8601TimestampLocal()
get the current time and return it as na IOS8601 time stamp.
Definition PNeXus.cpp:139