diff --git a/src/any2many.cpp b/src/any2many.cpp index 50cae0f3e..e91e6de02 100644 --- a/src/any2many.cpp +++ b/src/any2many.cpp @@ -85,7 +85,7 @@ void any2many_syntax() std::cout << std::endl << " : input data file format. Supported formats are:"; std::cout << std::endl << " MusrRoot, PSI-BIN, ROOT (LEM), MUD, NeXus, PSI-MDU, WKM"; std::cout << std::endl << " : ouput data file format. Supported formats are:"; - std::cout << std::endl << " PSI-BIN, MusrRoot, ROOT, MUD, NeXus1-HDF4, NeXus1-HDF5, NeXus1-XML,"; + std::cout << std::endl << " PSI-BIN, MusrRoot, MusrRootDir, ROOT, MUD, NeXus1-HDF4, NeXus1-HDF5, NeXus1-XML,"; std::cout << std::endl << " NeXus2-HDF4, NeXus2-HDF5, NeXus2-XML, WKM, ASCII"; std::cout << std::endl << " Comment: ROOT is superseeded by MusrRoot. If there is not a very good"; std::cout << std::endl << " reason, avoid it!"; @@ -109,6 +109,10 @@ void any2many_syntax() std::cout << std::endl << " generated according to the input data file name, and the output data"; std::cout << std::endl << " format."; std::cout << std::endl; + std::cout << std::endl << "NOTE to MusrRoot and MusrRootDir : MusrRoot will convert to the deprecated TFolder format,"; + std::cout << std::endl << " whereas MusrRootDir will convert to the TDirectory based format. Typically MusrRootDir should be the"; + std::cout << std::endl << " preferred MusrRoot-file-format output format."; + std::cout << std::endl; std::cout << std::endl << "examples:" << std::endl; std::cout << std::endl << " any2many -f 2010/lem10_his_0123.root -c ROOT ASCII -rebin 25"; std::cout << std::endl << " Will take the LEM ROOT file '2010/lem10_his_0123.root' rebin it with 25"; @@ -172,6 +176,7 @@ int main(int argc, char *argv[]) // init outputFormat outputFormat.push_back("psi-bin"); outputFormat.push_back("musrroot"); + outputFormat.push_back("musrrootdir"); outputFormat.push_back("root"); outputFormat.push_back("mud"); outputFormat.push_back("nexus1-hdf4"); diff --git a/src/classes/PMusr.cpp b/src/classes/PMusr.cpp index f0d9a0450..657892f8a 100644 --- a/src/classes/PMusr.cpp +++ b/src/classes/PMusr.cpp @@ -582,6 +582,58 @@ PRawRunData::~PRawRunData() fRedGreenOffset.clear(); } +//-------------------------------------------------------------------------- +// CalcStartDateTime (public) +//-------------------------------------------------------------------------- +/** + *

Calculate time_t of the present fStartDate and fStartTime. + * + * @param ok, true if time_t conversion has been successful + * + * @return time_t of the present fStartDate and fStartTime + */ +const time_t PRawRunData::CalcStartDateTime(bool &ok) +{ + time_t dt=0; + ok = true; + struct tm tmStruct; + char date_time[256]; + snprintf(date_time, sizeof(date_time), "%s %s", fStartDate.Data(), fStartTime.Data()); + char *p_char = strptime(date_time, "%Y-%m-%d %H:%M:%S", &tmStruct); + if (*p_char != '\0') { + ok = false; + return dt; + } + dt = mktime(&tmStruct); + return dt; +} + +//-------------------------------------------------------------------------- +// CalcStopDateTime (public) +//-------------------------------------------------------------------------- +/** + *

Calculate time_t of the present fStopDate and fStopTime. + * + * @param ok, true if time_t conversion has been successful + * + * @return time_t of the present fStopDate and fStopTime + */ +const time_t PRawRunData::CalcStopDateTime(bool &ok) +{ + time_t dt=0; + ok = true; + struct tm tmStruct; + char date_time[256]; + snprintf(date_time, sizeof(date_time), "%s %s", fStopDate.Data(), fStopTime.Data()); + char *p_char = strptime(date_time, "%Y-%m-%d %H:%M:%S", &tmStruct); + if (*p_char != '\0') { + ok = false; + return dt; + } + dt = mktime(&tmStruct); + return dt; +} + //-------------------------------------------------------------------------- // GetTemperature (public) //-------------------------------------------------------------------------- diff --git a/src/classes/PRunDataHandler.cpp b/src/classes/PRunDataHandler.cpp index 6f0736b74..039ece7c8 100644 --- a/src/classes/PRunDataHandler.cpp +++ b/src/classes/PRunDataHandler.cpp @@ -72,16 +72,6 @@ #define PRH_NPP_OFFSET 0 #define PRH_PPC_OFFSET 20 -#define A2M_UNDEFINED 0 -#define A2M_ROOT 1 -#define A2M_MUSR_ROOT 2 -#define A2M_PSIBIN 3 -#define A2M_PSIMDU 4 -#define A2M_MUD 5 -#define A2M_NEXUS 6 -#define A2M_WKM 7 -#define A2M_ASCII 8 - #define PHR_INIT_ALL 0 #define PHR_INIT_MSR 1 #define PHR_INIT_ANY2MANY 2 @@ -373,6 +363,8 @@ Bool_t PRunDataHandler::WriteData(TString fileName) if (fAny2ManyInfo != nullptr) { if (!fAny2ManyInfo->outFormat.CompareTo("musrroot", TString::kIgnoreCase)) outTag = A2M_MUSR_ROOT; + else if (!fAny2ManyInfo->outFormat.CompareTo("musrrootdir", TString::kIgnoreCase)) + outTag = A2M_MUSR_ROOT_DIR; else if (!fAny2ManyInfo->outFormat.CompareTo("psibin", TString::kIgnoreCase)) outTag = A2M_PSIBIN; else if (!fAny2ManyInfo->outFormat.CompareTo("psimdu", TString::kIgnoreCase)) @@ -395,10 +387,11 @@ Bool_t PRunDataHandler::WriteData(TString fileName) Bool_t success{true}; switch (outTag) { case A2M_MUSR_ROOT: + case A2M_MUSR_ROOT_DIR: if (fAny2ManyInfo->outFileName.Length() == 0) - success = WriteMusrRootFile(fileName); + success = WriteMusrRootFile(outTag, fileName); else - success = WriteMusrRootFile(fAny2ManyInfo->outFileName); + success = WriteMusrRootFile(outTag, fAny2ManyInfo->outFileName); break; case A2M_PSIBIN: case A2M_PSIMDU: @@ -603,6 +596,8 @@ Bool_t PRunDataHandler::ReadWriteFilesList() outTag = A2M_ROOT; else if (!fAny2ManyInfo->outFormat.CompareTo("musrroot", TString::kIgnoreCase)) outTag = A2M_MUSR_ROOT; + else if (!fAny2ManyInfo->outFormat.CompareTo("musrrootdir", TString::kIgnoreCase)) + outTag = A2M_MUSR_ROOT_DIR; else if (!fAny2ManyInfo->outFormat.CompareTo("psi-bin", TString::kIgnoreCase)) outTag = A2M_PSIBIN; else if (!fAny2ManyInfo->outFormat.CompareTo("mud",TString::kIgnoreCase)) @@ -669,10 +664,11 @@ Bool_t PRunDataHandler::ReadWriteFilesList() success = WriteRootFile(fAny2ManyInfo->outFileName); break; case A2M_MUSR_ROOT: + case A2M_MUSR_ROOT_DIR: if (fAny2ManyInfo->outFileName.Length() == 0) - success = WriteMusrRootFile(); + success = WriteMusrRootFile(outTag); else - success = WriteMusrRootFile(fAny2ManyInfo->outFileName); + success = WriteMusrRootFile(outTag, fAny2ManyInfo->outFileName); break; case A2M_PSIBIN: if (fAny2ManyInfo->outFileName.Length() == 0) @@ -781,7 +777,8 @@ Bool_t PRunDataHandler::ReadWriteFilesList() success = WriteRootFile(fln); break; case A2M_MUSR_ROOT: - success = WriteMusrRootFile(fln); + case A2M_MUSR_ROOT_DIR: + success = WriteMusrRootFile(outTag, fln); break; case A2M_PSIBIN: success = WritePsiBinFile(fln); @@ -3730,8 +3727,6 @@ Bool_t PRunDataHandler::ReadAsciiFile() { Bool_t success = true; -std::cout << "as35> in ReadAsciiFile() ..." << std::endl; - // open file std::ifstream f; @@ -4541,13 +4536,12 @@ Bool_t PRunDataHandler::ReadDatFile() /** *

Write the MusrRoot file format. Only the required entries will be handled. * - * return: - * - true on successful writting, - * - otherwise false. - * + * \param tag = A2M_MUSR_ROOT (TFolder MusrRoot, deprecated), = A2M_MUSR_ROOT_DIR (TDirectory MusrRoot). * \param fln file name. If empty, the routine will try to construct one + * + * \return true on successful writting, false otherwise. */ -Bool_t PRunDataHandler::WriteMusrRootFile(TString fln) +Bool_t PRunDataHandler::WriteMusrRootFile(Int_t tag, TString fln) { Bool_t ok = false; fln = GenerateOutputFileName(fln, ".root", ok); @@ -4557,24 +4551,34 @@ Bool_t PRunDataHandler::WriteMusrRootFile(TString fln) if (!fAny2ManyInfo->useStandardOutput) std::cout << std::endl << ">> PRunDataHandler::WriteMusrRootFile(): writing a root data file (" << fln.Data() << ") ... " << std::endl; + // write file + std::unique_ptr fout = std::make_unique(fln, "RECREATE", fln); + if (fout == nullptr) { + std::cerr << std::endl << "PRunDataHandler::WriteMusrRootFile(): **ERROR** Couldn't create ROOT file '" << fln << "'" << std::endl; + return false; + } + fout->cd(); + // generate data file - TFolder *histosFolder; - TFolder *decayAnaModule; - TFolder *runHeader; - - histosFolder = gROOT->GetRootFolder()->AddFolder("histos", "Histograms"); - gROOT->GetListOfBrowsables()->Add(histosFolder, "histos"); - decayAnaModule = histosFolder->AddFolder("DecayAnaModule", "muSR decay histograms"); - - runHeader = gROOT->GetRootFolder()->AddFolder("RunHeader", "MusrRoot Run Header Info"); - gROOT->GetListOfBrowsables()->Add(runHeader, "RunHeader"); std::unique_ptr header = std::make_unique(true); - gROOT->GetListOfBrowsables()->Add(runHeader, "RunHeader"); + TFolder *histosFolder, *decayAnaModule, *runHeader; + TDirectory *histosDir, *decayAnaDir, *runHeaderDir; + if (tag == A2M_MUSR_ROOT) { // TFolder + histosFolder = new TFolder("histos", "Histograms"); + decayAnaModule = histosFolder->AddFolder("DecayAnaModule", "muSR decay histograms"); + runHeader = new TFolder("RunHeader", "MusrRoot Run Header Info"); + } else { // TDirectory + histosDir = fout->mkdir("histos"); + decayAnaDir = histosDir->mkdir("decayAnaModule"); + runHeaderDir = fout->mkdir("RunHeader"); + } // feed header info TString str, pathName; Int_t ival; Double_t dval[2]; + time_t start{0}, stop{0}; + Bool_t valid{false}; TMusrRunPhysicalQuantity prop; // feed RunInfo @@ -4593,7 +4597,11 @@ Bool_t PRunDataHandler::WriteMusrRootFile(TString fln) header->Set("RunInfo/Run Start Time", str); str = fData[0].GetStopDate()->Copy() + " " + fData[0].GetStopTime()->Copy(); header->Set("RunInfo/Run Stop Time", str); - ival = fData[0].GetStopDateTime() - fData[0].GetStartDateTime(); + start = fData[0].CalcStartDateTime(valid); + if (valid) + stop = fData[0].CalcStopDateTime(valid); + if (valid) + ival = (int)stop - (int)start; prop.Set("Run Duration", ival, "sec"); header->Set("RunInfo/Run Duration", prop); str = fData[0].GetLaboratory()->Copy(); @@ -4723,29 +4731,28 @@ Bool_t PRunDataHandler::WriteMusrRootFile(TString fln) } } - // add histos to the DecayAnaModule folder - for (UInt_t i=0; iAdd(histos[i]); - - // write file - std::unique_ptr fout = std::make_unique(fln, "RECREATE", fln); - if (fout == nullptr) { - std::cerr << std::endl << "PRunDataHandler::WriteMusrRootFile(): **ERROR** Couldn't create ROOT file '" << fln << "'" << std::endl; - return false; + if (tag == A2M_MUSR_ROOT) { // TFolder + // add histos to the DecayAnaModule folder + for (UInt_t i=0; iAdd(histos[i]); + } else { // TDirectory + // add histos to the DecayAnaModule directory + for (UInt_t i=0; iAdd(histos[i]); } - fout->cd(); - if (header->FillFolder(runHeader)) - runHeader->Write(); - histosFolder->Write(); + if (tag == A2M_MUSR_ROOT) { // TFolder + if (header->FillFolder(runHeader)) + runHeader->Write(); + histosFolder->Write(); + } else { // TDirectory + if (header->FillDirectory(runHeaderDir)) { + runHeaderDir->Write(); + } + histosDir->Write(); + } fout->Close(); - // cleanup - for (UInt_t i=0; iuseStandardOutput && (fAny2ManyInfo->compressionTag == 0)) { // stream file to stdout diff --git a/src/external/MusrRoot/TMusrRunHeader.cpp b/src/external/MusrRoot/TMusrRunHeader.cpp index 5d782e95b..478990895 100644 --- a/src/external/MusrRoot/TMusrRunHeader.cpp +++ b/src/external/MusrRoot/TMusrRunHeader.cpp @@ -1326,7 +1326,7 @@ void TMusrRunHeader::DumpHeader() fmt.Form("%%s: %%.%dlf %%s; SP: %%.%dlf", digit, digit_d); tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetUnit().Data(), prop.GetDemand()); } - } else if (prop.GetDemand() == MRH_UNDEFINED) { // = n/a + } else if (prop.GetValue() == MRH_UNDEFINED) { // = n/a fmt.Form("%%s: %%s %%s"); if ((prop.GetUnit() != "n/a")) tstr.Form(fmt, prop.GetLabel().Data(), "n/a", prop.GetUnit().Data()); @@ -1827,6 +1827,9 @@ TObjString TMusrRunHeader::GetHeaderString(UInt_t idx) fmt.Form("%%s: %%.%dlf %%s; SP: %%.%dlf", digit, digit_d); tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetUnit().Data(), prop.GetDemand()); } + } else if (prop.GetValue() == MRH_UNDEFINED) { + fmt.Form("%%s: %%.1e %%s"); + tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetUnit().Data()); } str.Form("%03d - %s -@%d", idx, tstr.Data(), MRH_TMUSR_RUN_PHYSICAL_QUANTITY); tostr.SetString(str); diff --git a/src/include/PMusr.h b/src/include/PMusr.h index f4a5b5c1c..a5f9f743e 100644 --- a/src/include/PMusr.h +++ b/src/include/PMusr.h @@ -421,9 +421,11 @@ class PRawRunData { virtual const TString* GetStartTime() { return &fStartTime; } virtual const TString* GetStartDate() { return &fStartDate; } virtual const time_t GetStartDateTime() { return fStartDateTimeSec; } + virtual const time_t CalcStartDateTime(bool &ok); virtual const TString* GetStopTime() { return &fStopTime; } virtual const TString* GetStopDate() { return &fStopDate; } virtual const time_t GetStopDateTime() { return fStopDateTimeSec; } + virtual const time_t CalcStopDateTime(bool &ok); virtual const TString* GetCryoName() { return &fCryo; } virtual const TString* GetSample() { return &fSample; } virtual const TString* GetOrientation() { return &fOrientation; } diff --git a/src/include/PRunDataHandler.h b/src/include/PRunDataHandler.h index b7a3a963f..f56620eff 100644 --- a/src/include/PRunDataHandler.h +++ b/src/include/PRunDataHandler.h @@ -35,6 +35,17 @@ #include "PMusr.h" #include "PMsrHandler.h" +#define A2M_UNDEFINED 0 +#define A2M_ROOT 1 +#define A2M_MUSR_ROOT 2 +#define A2M_MUSR_ROOT_DIR 3 +#define A2M_PSIBIN 4 +#define A2M_PSIMDU 5 +#define A2M_MUD 6 +#define A2M_NEXUS 7 +#define A2M_WKM 8 +#define A2M_ASCII 9 + /** *

Handler class needed to read/handle raw data files. */ @@ -91,7 +102,7 @@ class PRunDataHandler virtual Bool_t ReadDBFile(); virtual Bool_t ReadDatFile(); - virtual Bool_t WriteMusrRootFile(TString fln=""); + virtual Bool_t WriteMusrRootFile(Int_t tag=A2M_MUSR_ROOT_DIR, TString fln=""); virtual Bool_t WriteRootFile(TString fln=""); virtual Bool_t WriteNexusFile(TString fln=""); virtual Bool_t WriteWkmFile(TString fln="");