From 3bb004ea2d8203a443d98e7a54f4df86de01cc58 Mon Sep 17 00:00:00 2001 From: Andreas Suter Date: Sat, 7 Feb 2026 11:31:11 +0100 Subject: [PATCH] more work on the NeXus write routines. --- src/classes/PRunDataHandler.cpp | 140 +++++++++++++++++++------------- src/include/PRunDataHandler.h | 2 +- 2 files changed, 83 insertions(+), 59 deletions(-) diff --git a/src/classes/PRunDataHandler.cpp b/src/classes/PRunDataHandler.cpp index 5d88d86a..c5cccdf6 100644 --- a/src/classes/PRunDataHandler.cpp +++ b/src/classes/PRunDataHandler.cpp @@ -4807,7 +4807,7 @@ Bool_t PRunDataHandler::WriteRootFile(TString fln) Bool_t PRunDataHandler::WriteNexusFile(TString format, TString fln) { #ifdef PNEXUS_ENABLED - + std::string str{""}; Bool_t ok = false; fln = GenerateOutputFileName(fln, ".nxs", ok); if (!ok) @@ -4837,8 +4837,89 @@ Bool_t PRunDataHandler::WriteNexusFile(TString format, TString fln) nxs->AddGroupAttribute("/", "HDF_version", nxs->GetHdf5LibVersion()); // set file name nxs->AddGroupAttribute("/", "file_name", std::string(fln.Data())); + // set creation time + std::string dt = nxs::getIso8601TimestampLocal(); + nxs->AddGroupAttribute("/", "file_time", dt); // set IDF version nxs->AddDataset("/run/IDF_version", {(int)fAny2ManyInfo->idf}, {1}, H5::PredType::NATIVE_INT32); + // set program name + nxs->AddDataset("/run/program_name", {"any2many"}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE)); + str="n/a"; + #ifdef HAVE_CONFIG_H + str = PACKAGE_VERSION; + #endif + nxs->AddDatasetAttribute("/run/program_name", "version", str); + // set run number + nxs->AddDataset("/run/number", {fData[0].GetRunNumber()}, {1}, H5::PredType::NATIVE_INT32); + // set title + nxs->AddDataset("/run/title", {fData[0].GetRunTitle()->Data()}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE)); + // set notes + nxs->AddDataset("/run/notes", {std::string("n/a")}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE)); + // set analysis + nxs->AddDataset("/run/notes", {std::string("muonTD")}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE)); + // set lab + str = *fData[0].GetLaboratory(); + nxs->AddDataset("/run/lab", {str}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE)); + // set beamline + str = *fData[0].GetBeamline(); + nxs->AddDataset("/run/beamline", {str}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE)); + // set start time + str = std::string(fData[0].GetStartDate()->Data()) + std::string("T") + std::string(fData[0].GetStartTime()->Data()); + nxs->AddDataset("/run/start_time", {str}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE)); + // set stop time + str = std::string(fData[0].GetStopDate()->Data()) + std::string("T") + std::string(fData[0].GetStopTime()->Data()); + nxs->AddDataset("/run/stop_time", {str}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE)); + // set switching state + nxs->AddDataset("/run/switching_states", {1}, {1}, H5::PredType::NATIVE_INT32); + // set user name + nxs->AddDataset("/run/user/name", {std::string("n/a")}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE)); + // set user experiment_number + nxs->AddDataset("/run/user/experiment_number", {std::string("n/a")}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE)); + // set sample name + nxs->AddDataset("/run/sample/name", {fData[0].GetSample()->Data()}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE)); + // set sample temperature + nxs->AddDataset("/run/sample/temperature", {(float)fData[0].GetTemperature(0)}, {1}, H5::PredType::NATIVE_FLOAT); + nxs->AddDatasetAttribute("/run/sample/temperature", "units", std::string("Kelvin")); + // set magnetic field + nxs->AddDataset("/run/sample/magnetic_field", {(float)fData[0].GetField()}, {1}, H5::PredType::NATIVE_FLOAT); + nxs->AddDatasetAttribute("/run/sample/magnetic_field", "units", std::string("Gauss")); + // set sample environment + nxs->AddDataset("/run/sample/environment", {fData[0].GetSetup()->Data()}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE)); + // set sample shape + nxs->AddDataset("/run/sample/shape", {std::string("n/a")}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE)); + // set magnetic field vector + nxs->AddDataset("/run/sample/magnetic_field_vector", {1.0, 1.0, 1.0}, {3}, H5::PredType::NATIVE_FLOAT); + nxs->AddDatasetAttribute("/run/sample/magnetic_field_vector", "coordinate_system", std::string("cartesian")); + nxs->AddDatasetAttribute("/run/sample/magnetic_field_vector", "units", std::string("Gauss")); + nxs->AddDatasetAttribute("/run/sample/magnetic_field_vector", "available", 0); + // set instrument name + str = *fData[0].GetInstrument(); + nxs->AddDataset("/run/instrument/name", {str}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE)); + // set instrument number of detectors + nxs->AddDataset("/run/instrument/detector/number", {(int)fData[0].GetNoOfHistos()}, {1}, H5::PredType::NATIVE_INT32); + // set instrument collimator + nxs->AddDataset("/run/instrument/collimator/type", {std::string("n/a")}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE)); + // set instrument beam total number of counts in Mev + // calculate the total number of counts + double total_counts = 0; + PRawRunDataSet *dataSet = nullptr; + for (unsigned int i=0; i> PRunDataHandler::WriteNexusFile: **ERROR** Couldn't get data set (idx=0" << i << ")"; + std::cerr << std::endl << ">> something is really wrong!" << std::endl; + return false; + } + for (unsigned int j=0; jGetData()->size(); j++) + total_counts += dataSet->GetData()->at(j); + } + float total_counts_mev = (float) total_counts / 1.0e6; + nxs->AddDataset("/run/instrument/beam/total_counts", {total_counts_mev}, {1}, H5::PredType::NATIVE_FLOAT); + nxs->AddDatasetAttribute("/run/instrument/beam/total_counts", "units", std::string("MEv")); + // set time resolution (use FLOAT instead of INT) + float res = (float)(fData[0].GetTimeResolution()*fAny2ManyInfo->rebin*1.0e3); + nxs->AddDataset("/run/histogram_data_1/resolution", {res}, {1}, H5::PredType::NATIVE_FLOAT); + nxs->AddDatasetAttribute("/run/histogram_data_1/resolution", "units", std::string("picoseconds")); } else { // IDF V2 // set IDF version nxs->AddDataset("/raw_data_1/IDF_version", {(int)fAny2ManyInfo->idf}, {1}, H5::PredType::NATIVE_INT32); @@ -4860,63 +4941,6 @@ Bool_t PRunDataHandler::WriteNexusFile(TString format, TString fln) if (fAny2ManyInfo->idf == 1) { // fill necessary data structures - // set file creating time - time_t now; - struct tm *tm; - time(&now); - tm = localtime(&now); - std::string str(""); - char cstr[128]; - strftime(cstr, sizeof(cstr), "%FT%T", tm); - str = std::string(cstr); - nxs->SetFileTime(str); - - nxs->GetEntryIdf1()->SetProgramName("any2many"); - nxs->GetEntryIdf1()->SetProgramVersion("$Id$"); - nxs->GetEntryIdf1()->SetRunNumber(fData[0].GetRunNumber()); - nxs->GetEntryIdf1()->SetTitle(fData[0].GetRunTitle()->Data()); - nxs->GetEntryIdf1()->SetNotes("n/a"); - nxs->GetEntryIdf1()->SetAnalysis("muonTD"); - if (*fData[0].GetLaboratory() != "n/a") - nxs->GetEntryIdf1()->SetLaboratory(fData[0].GetLaboratory()->Data()); - if (*fData[0].GetBeamline() != "n/a") - nxs->GetEntryIdf1()->SetBeamline(fData[0].GetBeamline()->Data()); - str = std::string(fData[0].GetStartDate()->Data()) + std::string("T") + std::string(fData[0].GetStartTime()->Data()); - nxs->GetEntryIdf1()->SetStartTime(str); - str = std::string(fData[0].GetStopDate()->Data()) + std::string("T") + std::string(fData[0].GetStopTime()->Data()); - nxs->GetEntryIdf1()->SetStopTime(str); - nxs->GetEntryIdf1()->SetSwitchingState(1); - nxs->GetEntryIdf1()->GetUser()->SetName("n/a"); - nxs->GetEntryIdf1()->GetUser()->SetExperimentNumber("n/a"); - nxs->GetEntryIdf1()->GetSample()->SetName(fData[0].GetSample()->Data()); - nxs->GetEntryIdf1()->GetSample()->SetPhysProp("temperature", fData[0].GetTemperature(0), "Kelvin"); - nxs->GetEntryIdf1()->GetSample()->SetPhysProp("magnetic_field", fData[0].GetField(), "Gauss"); - nxs->GetEntryIdf1()->GetSample()->SetEnvironment(fData[0].GetSetup()->Data()); - nxs->GetEntryIdf1()->GetSample()->SetShape("n/a"); - nxs->GetEntryIdf1()->GetSample()->SetMagneticFieldVectorAvailable(0); - if (*fData[0].GetInstrument() != "n/a") - nxs->GetEntryIdf1()->GetInstrument()->SetName(fData[0].GetInstrument()->Data()); - nxs->GetEntryIdf1()->GetInstrument()->GetDetector()->SetNumber(fData[0].GetNoOfHistos()); - nxs->GetEntryIdf1()->GetInstrument()->GetCollimator()->SetType("n/a"); - // calculate the total number of counts - double total_counts = 0; - PRawRunDataSet *dataSet = nullptr; - for (unsigned int i=0; i> PRunDataHandler::WriteNexusFile: **ERROR** Couldn't get data set (idx=0" << i << ")"; - std::cerr << std::endl << ">> something is really wrong!" << std::endl; - return false; - } - for (unsigned int j=0; jGetData()->size(); j++) - total_counts += dataSet->GetData()->at(j); - } - double total_counts_mev = (double) total_counts / 1.0e6; - nxs->GetEntryIdf1()->GetInstrument()->GetBeam()->SetTotalCounts(total_counts_mev); - nxs->GetEntryIdf1()->GetInstrument()->GetBeam()->SetUnits("Mev"); - - nxs->GetEntryIdf1()->GetData()->SetTimeResolution(fData[0].GetTimeResolution()*fAny2ManyInfo->rebin, "ns"); - for (unsigned int i=0; iGetEntryIdf1()->GetData()->SetT0(static_cast(dataSet->GetTimeZeroBin()/fAny2ManyInfo->rebin), i); diff --git a/src/include/PRunDataHandler.h b/src/include/PRunDataHandler.h index efb8401a..8d918b31 100644 --- a/src/include/PRunDataHandler.h +++ b/src/include/PRunDataHandler.h @@ -436,9 +436,9 @@ class PRunDataHandler virtual Bool_t FileExistsCheck(const Bool_t fileName, const Int_t idx); virtual Bool_t FileExistsCheck(const TString fileName); virtual Bool_t ReadRootFile(); - virtual Bool_t ReadNexusFile(); template Bool_t ReadNexusFileIdf1(T& nxs_file); template Bool_t ReadNexusFileIdf2(T& nxs_file); + virtual Bool_t ReadNexusFile(); virtual Bool_t ReadWkmFile(); virtual Bool_t ReadPsiBinFile(); virtual Bool_t ReadMudFile();