add TDirectory option to any2many.

This commit is contained in:
2025-10-03 15:42:44 +02:00
parent 0eb36fc48a
commit 71fb4c9435
6 changed files with 136 additions and 56 deletions

View File

@@ -85,7 +85,7 @@ void any2many_syntax()
std::cout << std::endl << " <inFormat> : input data file format. Supported formats are:"; std::cout << std::endl << " <inFormat> : 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 << " MusrRoot, PSI-BIN, ROOT (LEM), MUD, NeXus, PSI-MDU, WKM";
std::cout << std::endl << " <outFormat> : ouput data file format. Supported formats are:"; std::cout << std::endl << " <outFormat> : 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 << " 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 << " Comment: ROOT is superseeded by MusrRoot. If there is not a very good";
std::cout << std::endl << " reason, avoid it!"; 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 << " generated according to the input data file name, and the output data";
std::cout << std::endl << " format."; std::cout << std::endl << " format.";
std::cout << std::endl; std::cout << std::endl;
std::cout << std::endl << "NOTE to MusrRoot and MusrRootDir <outFormat>: 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 << "examples:" << std::endl;
std::cout << std::endl << " any2many -f 2010/lem10_his_0123.root -c ROOT ASCII -rebin 25"; 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"; 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 // init outputFormat
outputFormat.push_back("psi-bin"); outputFormat.push_back("psi-bin");
outputFormat.push_back("musrroot"); outputFormat.push_back("musrroot");
outputFormat.push_back("musrrootdir");
outputFormat.push_back("root"); outputFormat.push_back("root");
outputFormat.push_back("mud"); outputFormat.push_back("mud");
outputFormat.push_back("nexus1-hdf4"); outputFormat.push_back("nexus1-hdf4");

View File

@@ -582,6 +582,58 @@ PRawRunData::~PRawRunData()
fRedGreenOffset.clear(); fRedGreenOffset.clear();
} }
//--------------------------------------------------------------------------
// CalcStartDateTime (public)
//--------------------------------------------------------------------------
/**
* <p>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)
//--------------------------------------------------------------------------
/**
* <p>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) // GetTemperature (public)
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------

View File

@@ -72,16 +72,6 @@
#define PRH_NPP_OFFSET 0 #define PRH_NPP_OFFSET 0
#define PRH_PPC_OFFSET 20 #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_ALL 0
#define PHR_INIT_MSR 1 #define PHR_INIT_MSR 1
#define PHR_INIT_ANY2MANY 2 #define PHR_INIT_ANY2MANY 2
@@ -373,6 +363,8 @@ Bool_t PRunDataHandler::WriteData(TString fileName)
if (fAny2ManyInfo != nullptr) { if (fAny2ManyInfo != nullptr) {
if (!fAny2ManyInfo->outFormat.CompareTo("musrroot", TString::kIgnoreCase)) if (!fAny2ManyInfo->outFormat.CompareTo("musrroot", TString::kIgnoreCase))
outTag = A2M_MUSR_ROOT; 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)) else if (!fAny2ManyInfo->outFormat.CompareTo("psibin", TString::kIgnoreCase))
outTag = A2M_PSIBIN; outTag = A2M_PSIBIN;
else if (!fAny2ManyInfo->outFormat.CompareTo("psimdu", TString::kIgnoreCase)) else if (!fAny2ManyInfo->outFormat.CompareTo("psimdu", TString::kIgnoreCase))
@@ -395,10 +387,11 @@ Bool_t PRunDataHandler::WriteData(TString fileName)
Bool_t success{true}; Bool_t success{true};
switch (outTag) { switch (outTag) {
case A2M_MUSR_ROOT: case A2M_MUSR_ROOT:
case A2M_MUSR_ROOT_DIR:
if (fAny2ManyInfo->outFileName.Length() == 0) if (fAny2ManyInfo->outFileName.Length() == 0)
success = WriteMusrRootFile(fileName); success = WriteMusrRootFile(outTag, fileName);
else else
success = WriteMusrRootFile(fAny2ManyInfo->outFileName); success = WriteMusrRootFile(outTag, fAny2ManyInfo->outFileName);
break; break;
case A2M_PSIBIN: case A2M_PSIBIN:
case A2M_PSIMDU: case A2M_PSIMDU:
@@ -603,6 +596,8 @@ Bool_t PRunDataHandler::ReadWriteFilesList()
outTag = A2M_ROOT; outTag = A2M_ROOT;
else if (!fAny2ManyInfo->outFormat.CompareTo("musrroot", TString::kIgnoreCase)) else if (!fAny2ManyInfo->outFormat.CompareTo("musrroot", TString::kIgnoreCase))
outTag = A2M_MUSR_ROOT; 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)) else if (!fAny2ManyInfo->outFormat.CompareTo("psi-bin", TString::kIgnoreCase))
outTag = A2M_PSIBIN; outTag = A2M_PSIBIN;
else if (!fAny2ManyInfo->outFormat.CompareTo("mud",TString::kIgnoreCase)) else if (!fAny2ManyInfo->outFormat.CompareTo("mud",TString::kIgnoreCase))
@@ -669,10 +664,11 @@ Bool_t PRunDataHandler::ReadWriteFilesList()
success = WriteRootFile(fAny2ManyInfo->outFileName); success = WriteRootFile(fAny2ManyInfo->outFileName);
break; break;
case A2M_MUSR_ROOT: case A2M_MUSR_ROOT:
case A2M_MUSR_ROOT_DIR:
if (fAny2ManyInfo->outFileName.Length() == 0) if (fAny2ManyInfo->outFileName.Length() == 0)
success = WriteMusrRootFile(); success = WriteMusrRootFile(outTag);
else else
success = WriteMusrRootFile(fAny2ManyInfo->outFileName); success = WriteMusrRootFile(outTag, fAny2ManyInfo->outFileName);
break; break;
case A2M_PSIBIN: case A2M_PSIBIN:
if (fAny2ManyInfo->outFileName.Length() == 0) if (fAny2ManyInfo->outFileName.Length() == 0)
@@ -781,7 +777,8 @@ Bool_t PRunDataHandler::ReadWriteFilesList()
success = WriteRootFile(fln); success = WriteRootFile(fln);
break; break;
case A2M_MUSR_ROOT: case A2M_MUSR_ROOT:
success = WriteMusrRootFile(fln); case A2M_MUSR_ROOT_DIR:
success = WriteMusrRootFile(outTag, fln);
break; break;
case A2M_PSIBIN: case A2M_PSIBIN:
success = WritePsiBinFile(fln); success = WritePsiBinFile(fln);
@@ -3730,8 +3727,6 @@ Bool_t PRunDataHandler::ReadAsciiFile()
{ {
Bool_t success = true; Bool_t success = true;
std::cout << "as35> in ReadAsciiFile() ..." << std::endl;
// open file // open file
std::ifstream f; std::ifstream f;
@@ -4541,13 +4536,12 @@ Bool_t PRunDataHandler::ReadDatFile()
/** /**
* <p> Write the MusrRoot file format. Only the required entries will be handled. * <p> Write the MusrRoot file format. Only the required entries will be handled.
* *
* <b>return:</b> * \param tag = A2M_MUSR_ROOT (TFolder MusrRoot, deprecated), = A2M_MUSR_ROOT_DIR (TDirectory MusrRoot).
* - true on successful writting,
* - otherwise false.
*
* \param fln file name. If empty, the routine will try to construct one * \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; Bool_t ok = false;
fln = GenerateOutputFileName(fln, ".root", ok); fln = GenerateOutputFileName(fln, ".root", ok);
@@ -4557,24 +4551,34 @@ Bool_t PRunDataHandler::WriteMusrRootFile(TString fln)
if (!fAny2ManyInfo->useStandardOutput) if (!fAny2ManyInfo->useStandardOutput)
std::cout << std::endl << ">> PRunDataHandler::WriteMusrRootFile(): writing a root data file (" << fln.Data() << ") ... " << std::endl; std::cout << std::endl << ">> PRunDataHandler::WriteMusrRootFile(): writing a root data file (" << fln.Data() << ") ... " << std::endl;
// write file
std::unique_ptr<TFile> fout = std::make_unique<TFile>(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 // 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<TMusrRunHeader> header = std::make_unique<TMusrRunHeader>(true); std::unique_ptr<TMusrRunHeader> header = std::make_unique<TMusrRunHeader>(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 // feed header info
TString str, pathName; TString str, pathName;
Int_t ival; Int_t ival;
Double_t dval[2]; Double_t dval[2];
time_t start{0}, stop{0};
Bool_t valid{false};
TMusrRunPhysicalQuantity prop; TMusrRunPhysicalQuantity prop;
// feed RunInfo // feed RunInfo
@@ -4593,7 +4597,11 @@ Bool_t PRunDataHandler::WriteMusrRootFile(TString fln)
header->Set("RunInfo/Run Start Time", str); header->Set("RunInfo/Run Start Time", str);
str = fData[0].GetStopDate()->Copy() + " " + fData[0].GetStopTime()->Copy(); str = fData[0].GetStopDate()->Copy() + " " + fData[0].GetStopTime()->Copy();
header->Set("RunInfo/Run Stop Time", str); 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"); prop.Set("Run Duration", ival, "sec");
header->Set("RunInfo/Run Duration", prop); header->Set("RunInfo/Run Duration", prop);
str = fData[0].GetLaboratory()->Copy(); str = fData[0].GetLaboratory()->Copy();
@@ -4723,28 +4731,27 @@ Bool_t PRunDataHandler::WriteMusrRootFile(TString fln)
} }
} }
if (tag == A2M_MUSR_ROOT) { // TFolder
// add histos to the DecayAnaModule folder // add histos to the DecayAnaModule folder
for (UInt_t i=0; i<histos.size(); i++) for (UInt_t i=0; i<histos.size(); i++)
decayAnaModule->Add(histos[i]); decayAnaModule->Add(histos[i]);
} else { // TDirectory
// write file // add histos to the DecayAnaModule directory
std::unique_ptr<TFile> fout = std::make_unique<TFile>(fln, "RECREATE", fln); for (UInt_t i=0; i<histos.size(); i++)
if (fout == nullptr) { decayAnaDir->Add(histos[i]);
std::cerr << std::endl << "PRunDataHandler::WriteMusrRootFile(): **ERROR** Couldn't create ROOT file '" << fln << "'" << std::endl;
return false;
} }
fout->cd(); if (tag == A2M_MUSR_ROOT) { // TFolder
if (header->FillFolder(runHeader)) if (header->FillFolder(runHeader))
runHeader->Write(); runHeader->Write();
histosFolder->Write(); histosFolder->Write();
fout->Close(); } else { // TDirectory
if (header->FillDirectory(runHeaderDir)) {
// cleanup runHeaderDir->Write();
for (UInt_t i=0; i<histos.size(); i++) {
if (histos[i])
delete histos[i];
} }
histosDir->Write();
}
fout->Close();
// check if root file shall be streamed to stdout // check if root file shall be streamed to stdout
if (fAny2ManyInfo->useStandardOutput && (fAny2ManyInfo->compressionTag == 0)) { if (fAny2ManyInfo->useStandardOutput && (fAny2ManyInfo->compressionTag == 0)) {

View File

@@ -1326,7 +1326,7 @@ void TMusrRunHeader::DumpHeader()
fmt.Form("%%s: %%.%dlf %%s; SP: %%.%dlf", digit, digit_d); fmt.Form("%%s: %%.%dlf %%s; SP: %%.%dlf", digit, digit_d);
tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetUnit().Data(), prop.GetDemand()); tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetUnit().Data(), prop.GetDemand());
} }
} else if (prop.GetDemand() == MRH_UNDEFINED) { // <value> = n/a } else if (prop.GetValue() == MRH_UNDEFINED) { // <value> = n/a
fmt.Form("%%s: %%s %%s"); fmt.Form("%%s: %%s %%s");
if ((prop.GetUnit() != "n/a")) if ((prop.GetUnit() != "n/a"))
tstr.Form(fmt, prop.GetLabel().Data(), "n/a", prop.GetUnit().Data()); 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); fmt.Form("%%s: %%.%dlf %%s; SP: %%.%dlf", digit, digit_d);
tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetUnit().Data(), prop.GetDemand()); 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); str.Form("%03d - %s -@%d", idx, tstr.Data(), MRH_TMUSR_RUN_PHYSICAL_QUANTITY);
tostr.SetString(str); tostr.SetString(str);

View File

@@ -421,9 +421,11 @@ class PRawRunData {
virtual const TString* GetStartTime() { return &fStartTime; } virtual const TString* GetStartTime() { return &fStartTime; }
virtual const TString* GetStartDate() { return &fStartDate; } virtual const TString* GetStartDate() { return &fStartDate; }
virtual const time_t GetStartDateTime() { return fStartDateTimeSec; } virtual const time_t GetStartDateTime() { return fStartDateTimeSec; }
virtual const time_t CalcStartDateTime(bool &ok);
virtual const TString* GetStopTime() { return &fStopTime; } virtual const TString* GetStopTime() { return &fStopTime; }
virtual const TString* GetStopDate() { return &fStopDate; } virtual const TString* GetStopDate() { return &fStopDate; }
virtual const time_t GetStopDateTime() { return fStopDateTimeSec; } virtual const time_t GetStopDateTime() { return fStopDateTimeSec; }
virtual const time_t CalcStopDateTime(bool &ok);
virtual const TString* GetCryoName() { return &fCryo; } virtual const TString* GetCryoName() { return &fCryo; }
virtual const TString* GetSample() { return &fSample; } virtual const TString* GetSample() { return &fSample; }
virtual const TString* GetOrientation() { return &fOrientation; } virtual const TString* GetOrientation() { return &fOrientation; }

View File

@@ -35,6 +35,17 @@
#include "PMusr.h" #include "PMusr.h"
#include "PMsrHandler.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
/** /**
* <p>Handler class needed to read/handle raw data files. * <p>Handler class needed to read/handle raw data files.
*/ */
@@ -91,7 +102,7 @@ class PRunDataHandler
virtual Bool_t ReadDBFile(); virtual Bool_t ReadDBFile();
virtual Bool_t ReadDatFile(); 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 WriteRootFile(TString fln="");
virtual Bool_t WriteNexusFile(TString fln=""); virtual Bool_t WriteNexusFile(TString fln="");
virtual Bool_t WriteWkmFile(TString fln=""); virtual Bool_t WriteWkmFile(TString fln="");