diff --git a/src/classes/PRunDataHandler.cpp b/src/classes/PRunDataHandler.cpp index df820d00..5159f182 100644 --- a/src/classes/PRunDataHandler.cpp +++ b/src/classes/PRunDataHandler.cpp @@ -4818,8 +4818,378 @@ Bool_t PRunDataHandler::WriteNexusFile(TString format, TString fln) if (format.Contains("HDF4", TString::kIgnoreCase)) { // HDF4 #ifdef HAVE_HDF4 - std::cerr << "**ERROR** not yet implemented!" << std::endl; - return false; + try { + // create NeXus object + std::unique_ptr nxs = std::make_unique(); + if (nxs == nullptr) { + std::cerr << std::endl << ">> PRunDataHandler::WriteNexusFile(): **ERROR** couldn't invoke the NeXus object." << std::endl; + return false; + } + + // set NeXus version + nxs->AddGroupAttribute("/", "NeXus_version", std::string("4.3.0")); + + // set HDF4 version + nxs->AddGroupAttribute("/", "HDF_version", nxs->GetHdf4LibVersion()); + + // set file name + nxs->AddGroupAttribute("/", "file_name", std::string(fln.Data())); + + // set creation time + std::string dt = nxs::getIso8601TimestampLocal(); + nxs->AddGroupAttribute("/", "file_time", dt); + + if (fAny2ManyInfo->idf == 1) { // IDF V1 + // set IDF version + nxs->AddDataset("/run/IDF_version", {(int)fAny2ManyInfo->idf}, {1}, nxH4::H4DataType::INT32); + + // set program name + nxs->AddDataset("/run/program_name", {"any2many"}, {1}, nxH4::H4DataType::CHAR8); + 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}, nxH4::H4DataType::INT32); + + // set title + nxs->AddDataset("/run/title", {fData[0].GetRunTitle()->Data()}, {1}, nxH4::H4DataType::CHAR8); + + // set notes + nxs->AddDataset("/run/notes", {std::string("n/a")}, {1}, nxH4::H4DataType::CHAR8); + + // set analysis + nxs->AddDataset("/run/notes", {std::string("muonTD")}, {1}, nxH4::H4DataType::CHAR8); + + // set lab + str = *fData[0].GetLaboratory(); + nxs->AddDataset("/run/lab", {str}, {1}, nxH4::H4DataType::CHAR8); + + // set beamline + str = *fData[0].GetBeamline(); + nxs->AddDataset("/run/beamline", {str}, {1}, nxH4::H4DataType::CHAR8); + + // 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}, nxH4::H4DataType::CHAR8); + + // 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}, nxH4::H4DataType::CHAR8); + + // set switching state + nxs->AddDataset("/run/switching_states", {1}, {1}, nxH4::H4DataType::INT32); + + // set user name + nxs->AddDataset("/run/user/name", {std::string("n/a")}, {1}, nxH4::H4DataType::CHAR8); + + // set user experiment_number + nxs->AddDataset("/run/user/experiment_number", {std::string("n/a")}, {1}, nxH4::H4DataType::CHAR8); + + // set sample name + nxs->AddDataset("/run/sample/name", {fData[0].GetSample()->Data()}, {1}, nxH4::H4DataType::CHAR8); + + // set sample temperature + nxs->AddDataset("/run/sample/temperature", {(float)fData[0].GetTemperature(0)}, {1}, nxH4::H4DataType::FLOAT32); + nxs->AddDatasetAttribute("/run/sample/temperature", "units", std::string("Kelvin")); + + // set magnetic field + nxs->AddDataset("/run/sample/magnetic_field", {(float)fData[0].GetField()}, {1}, nxH4::H4DataType::FLOAT32); + nxs->AddDatasetAttribute("/run/sample/magnetic_field", "units", std::string("Gauss")); + + // set sample environment + nxs->AddDataset("/run/sample/environment", {fData[0].GetSetup()->Data()}, {1}, nxH4::H4DataType::CHAR8); + + // set sample shape + nxs->AddDataset("/run/sample/shape", {std::string("n/a")}, {1}, nxH4::H4DataType::CHAR8); + + // set magnetic field vector + nxs->AddDataset("/run/sample/magnetic_field_vector", {1.0f, 1.0f, 1.0f}, {3}, nxH4::H4DataType::FLOAT32); + 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}, nxH4::H4DataType::CHAR8); + + // set instrument number of detectors + nxs->AddDataset("/run/instrument/detector/number", {(int)fData[0].GetNoOfHistos()}, {1}, nxH4::H4DataType::INT32); + + // set instrument collimator + nxs->AddDataset("/run/instrument/collimator/type", {std::string("n/a")}, {1}, nxH4::H4DataType::CHAR8); + + // 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}, nxH4::H4DataType::FLOAT32); + 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}, nxH4::H4DataType::FLOAT32); + nxs->AddDatasetAttribute("/run/histogram_data_1/resolution", "units", std::string("picoseconds")); + + // set time zero time to 0. see t0_bin attribute of counts! + nxs->AddDataset("/run/histogram_data_1/time_zero", {0}, {1}, nxH4::H4DataType::INT32); + nxs->AddDatasetAttribute("/run/histogram_data_1/time_zero", "units", std::string("microseconds")); + nxs->AddDatasetAttribute("/run/histogram_data_1/time_zero", "available", 0); + + // set raw_time + res = (float)(fData[0].GetTimeResolution()*fAny2ManyInfo->rebin*1.0e-3); + dataSet = fData[0].GetDataSet(0, false); // i.e. the false means, that i is the index and NOT the histo number + unsigned int length = (int)(dataSet->GetData()->size() / fAny2ManyInfo->rebin); + std::vector time; + for (unsigned int i=0; iAddDataset("/run/histogram_data_1/raw_time", time, {length}, nxH4::H4DataType::FLOAT32); + nxs->AddDatasetAttribute("/run/histogram_data_1/raw_time", "axis", 1); + nxs->AddDatasetAttribute("/run/histogram_data_1/raw_time", "primary", 0); + nxs->AddDatasetAttribute("/run/histogram_data_1/raw_time", "units", std::string("microseconds")); + nxs->AddDatasetAttribute("/run/histogram_data_1/raw_time", "available", 0); + + // set corrected_time + nxs->AddDataset("/run/histogram_data_1/corrected_time", time, {length}, nxH4::H4DataType::FLOAT32); + nxs->AddDatasetAttribute("/run/histogram_data_1/corrected_time", "axis", 1); + nxs->AddDatasetAttribute("/run/histogram_data_1/corrected_time", "units", std::string("microseconds")); + nxs->AddDatasetAttribute("/run/histogram_data_1/corrected_time", "available", 0); + + // set grouping + std::vector grouping(fData[0].GetNoOfHistos(), 0); + nxs->AddDataset("/run/histogram_data_1/grouping", grouping, {(uint32_t)grouping.size()}, nxH4::H4DataType::INT32); + nxs->AddDatasetAttribute("/run/histogram_data_1/grouping", "avaliabe", 0); + + // set alpha + int ival=1; + nxs->AddDataset("/run/histogram_data_1/alpha", {ival}, {1}, nxH4::H4DataType::INT32); + nxs->AddDatasetAttribute("/run/histogram_data_1/alpha", "avaliabe", 0); + + // set counts + // feed histos + PIntVector data; + UInt_t size = 0; + int noHisto, histoLength; + if (fAny2ManyInfo->rebin == 1) { + noHisto = fData[0].GetNoOfHistos(); + for (UInt_t i=0; i> PRunDataHandler::WriteNexusFile: **ERROR** Couldn't get data set (idx=" << i << ")"; + std::cerr << std::endl << ">> something is really wrong!" << std::endl; + return false; + } + size = dataSet->GetData()->size(); + histoLength = size; + for (UInt_t j=0; jGetData()->at(j)); + } + } + } else { // rebin > 1 + UInt_t dataRebin = 0; + UInt_t dataCount = 0; + noHisto = fData[0].GetNoOfHistos(); + for (UInt_t i=0; i> PRunDataHandler::WriteNexusFile: **ERROR** Couldn't get data set (idx=" << i << ")"; + std::cerr << std::endl << ">> something is really wrong!" << std::endl; + return false; + } + size = dataSet->GetData()->size(); + dataCount = 0; + for (UInt_t j=0; j 0) && (j % fAny2ManyInfo->rebin == 0)) { + dataCount++; + data.push_back(dataRebin); + dataRebin = 0; + } + dataRebin += static_cast(dataSet->GetData()->at(j)); + } + } + size = dataCount; + } + nxs->AddDataset("/run/histogram_data_1/counts", data, {(uint32_t)noHisto, (uint32_t)size}, nxH4::H4DataType::INT32); + nxs->AddDatasetAttribute("/run/histogram_data_1/counts", "units", std::string("counts")); + nxs->AddDatasetAttribute("/run/histogram_data_1/counts", "signal", 1); + nxs->AddDatasetAttribute("/run/histogram_data_1/counts", "number", noHisto); + nxs->AddDatasetAttribute("/run/histogram_data_1/counts", "length", (int)size); + nxs->AddDatasetAttribute("/run/histogram_data_1/counts", "t0_bin", 0); + nxs->AddDatasetAttribute("/run/histogram_data_1/counts", "first_good_bin", 0); + nxs->AddDatasetAttribute("/run/histogram_data_1/counts", "last_good_bin", 0); + res = (float)(fData[0].GetTimeResolution()*fAny2ManyInfo->rebin*1.0e3)/2.0; + nxs->AddDatasetAttribute("/run/histogram_data_1/counts", "offset", res); + } else { // IDF V2 + nxs->AddGroupAttribute("/raw_data_1", "NX_class", std::string("NXentry")); + + // set IDF version + nxs->AddDataset("/raw_data_1/IDF_version", {(int)fAny2ManyInfo->idf}, {1}, nxH4::H4DataType::INT32); + + // set beamline + str = *fData[0].GetBeamline(); + nxs->AddDataset("/raw_data_1/beamline", {str}, {1}, nxH4::H4DataType::CHAR8); + + // set definition + nxs->AddDataset("/raw_data_1/definition", {std::string("muonTD")}, {1}, nxH4::H4DataType::CHAR8); + + // set run_number + nxs->AddDataset("/raw_data_1/run_number", {fData[0].GetRunNumber()}, {1}, nxH4::H4DataType::INT32); + + // set title + nxs->AddDataset("/raw_data_1/title", {fData[0].GetRunTitle()->Data()}, {1}, nxH4::H4DataType::CHAR8); + + // set start time + str = std::string(fData[0].GetStartDate()->Data()) + std::string("T") + std::string(fData[0].GetStartTime()->Data()); + nxs->AddDataset("/raw_data_1/start_time", {str}, {1}, nxH4::H4DataType::CHAR8); + nxs->AddDatasetAttribute("/raw_data_1/start_time", "units", "ISO8601"); + + // set end time + str = std::string(fData[0].GetStopDate()->Data()) + std::string("T") + std::string(fData[0].GetStopTime()->Data()); + nxs->AddDataset("/raw_data_1/end_time", {str}, {1}, nxH4::H4DataType::CHAR8); + nxs->AddDatasetAttribute("/raw_data_1/end_time", "units", "ISO8601"); + + // set experiment_identifier + str = "n/a"; + nxs->AddDataset("/raw_data_1/experiment_identifier", {str}, {1}, nxH4::H4DataType::CHAR8); + + // set instrument attribute + nxs->AddGroupAttribute("/raw_data_1/instrument", "NX_class", std::string("NXinstrument")); + + // set instrument name + str = *fData[0].GetInstrument(); + nxs->AddDataset("/raw_data_1/instrument/name", {str}, {1}, nxH4::H4DataType::CHAR8); + + // set instrument/source attribute + nxs->AddGroupAttribute("/raw_data_1/instrument/source", "NX_class", std::string("NXsource")); + + // set instrument/source/name + str = fData[0].GetLaboratory()->Data(); + nxs->AddDataset("/raw_data_1/instrument/source/name", {str}, {1}, nxH4::H4DataType::CHAR8); + + // set instrument/source/type + TString tstr = *fData[0].GetInstrument(); + std::string type{"n/a"}; + if (tstr.Contains("LEM", TString::kIgnoreCase)) { + type = "low energy muon source"; + } else if (tstr.Contains("GPS", TString::kIgnoreCase) || tstr.Contains("GPD", TString::kIgnoreCase) || + tstr.Contains("LTF", TString::kIgnoreCase) || tstr.Contains("FLAME", TString::kIgnoreCase) || + tstr.Contains("HAL-9500", TString::kIgnoreCase) || tstr.Contains("DOLLY", TString::kIgnoreCase) || + tstr.Contains("VMS", TString::kIgnoreCase)) { + type = "quasi-continous muon source"; + } else if (tstr.Contains("EMU", TString::kIgnoreCase) || tstr.Contains("MUSR", TString::kIgnoreCase) || + tstr.Contains("HIFI", TString::kIgnoreCase)) { + type = "pulsed muon source"; + } + nxs->AddDataset("/raw_data_1/instrument/source/type", {type}, {1}, nxH4::H4DataType::CHAR8); + + // set instrument/source/probe + str = "positive muons"; + nxs->AddDataset("/raw_data_1/instrument/source/probe", {str}, {1}, nxH4::H4DataType::CHAR8); + + // set instrument/detector info + nxs->AddGroupAttribute("/raw_data_1/instrument/detector_1", "NX_class", std::string("NXdetector")); + + // set instrument/detector/spectrum_index + int noHistos = fData[0].GetNoOfHistos(); + std::vector spectrum_index(noHistos); + for (unsigned int i=0; iAddDataset("/raw_data_1/instrument/detector_1/spectrum_index", spectrum_index, {(uint32_t)spectrum_index.size()}, nxH4::H4DataType::INT32); + + // set instrument/detector/raw_time (not useful for quasi-continuous sources) + int ival=0; + nxs->AddDataset("/raw_data_1/instrument/detector_1/raw_time", {ival}, {1}, nxH4::H4DataType::INT32); + nxs->AddDatasetAttribute("/raw_data_1/instrument/detector_1/raw_time", "available", 0); + + // set instrument/detector/counts + // set counts + // feed histos + PRawRunDataSet *dataSet = nullptr; + PIntVector data; + UInt_t size = 0; + int noHisto, histoLength; + if (fAny2ManyInfo->rebin == 1) { + noHisto = fData[0].GetNoOfHistos(); + for (UInt_t i=0; i> PRunDataHandler::WriteNexusFile: **ERROR** Couldn't get data set (idx=" << i << ")"; + std::cerr << std::endl << ">> something is really wrong!" << std::endl; + return false; + } + size = dataSet->GetData()->size(); + histoLength = size; + for (UInt_t j=0; jGetData()->at(j)); + } + } + } else { // rebin > 1 + UInt_t dataRebin = 0; + UInt_t dataCount = 0; + noHisto = fData[0].GetNoOfHistos(); + for (UInt_t i=0; i> PRunDataHandler::WriteNexusFile: **ERROR** Couldn't get data set (idx=" << i << ")"; + std::cerr << std::endl << ">> something is really wrong!" << std::endl; + return false; + } + size = dataSet->GetData()->size(); + dataCount = 0; + for (UInt_t j=0; j 0) && (j % fAny2ManyInfo->rebin == 0)) { + dataCount++; + data.push_back(dataRebin); + dataRebin = 0; + } + dataRebin += static_cast(dataSet->GetData()->at(j)); + } + } + size = dataCount; + } + nxs->AddDataset("/raw_data_1/instrument/detector_1/counts", data, {(uint32_t)noHisto, (uint32_t)size}, nxH4::H4DataType::INT32); + nxs->AddDatasetAttribute("/raw_data_1/instrument/detector_1/counts", "axes", std::string("spectrum_index,time_bin")); + nxs->AddDatasetAttribute("/raw_data_1/instrument/detector_1/counts", "long_name", std::string("positon counts")); + nxs->AddDatasetAttribute("/raw_data_1/instrument/detector_1/counts", "signal", 1); + // t0_bin attributes + std::vector t0_bin; + for (unsigned int i=0; irebin)); + nxs->AddDatasetAttribute("/raw_data_1/instrument/detector_1/counts", "t0_bin", {t0_bin}); + nxs->AddDatasetAttribute("/raw_data_1/instrument/detector_1/counts", "units", std::string("counts")); + + // set raw_data_1/detector info + nxs->AddGroupAttribute("/raw_data_1/detector_1", "NX_class", std::string("NXdata")); + + // set detector/counts + nxs->AddDataset("/raw_data_1/detector_1/counts", data, {(uint32_t)noHisto, (uint32_t)size}, nxH4::H4DataType::INT32); + nxs->AddDatasetAttribute("/raw_data_1/detector_1/counts", "axes", std::string("spectrum_index,time_bin")); + nxs->AddDatasetAttribute("/raw_data_1/detector_1/counts", "long_name", std::string("positon counts")); + nxs->AddDatasetAttribute("/raw_data_1/detector_1/counts", "signal", 1); + } + + int result = nxs->WriteNexusFile(fln.Data(), fAny2ManyInfo->idf); + if (result != 0) { + std::cerr << std::endl << "**ERROR** PRunDataHandler::WriteNexusFile, fln=" << fln << std::endl; + return false; + } + } catch (const std::runtime_error& e) { + std::cerr << std::endl << "HDF4 error: " << e.what() << std::endl; + return false; + } #endif } else { // HDF5 try { @@ -5196,190 +5566,6 @@ Bool_t PRunDataHandler::WriteNexusFile(TString format, TString fln) } return true; - -/* //as35 - } else if (fAny2ManyInfo->idf == 2) { - // fill necessary data structures - nxs->SetFileName(fln.Data()); - - // 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); - - // NXroot info - nxs->SetCreator("PSI: any2many"); - - // NXentry info - nxs->GetEntryIdf2()->SetDefinition("muonTD"); - nxs->GetEntryIdf2()->SetProgramName("any2many"); - nxs->GetEntryIdf2()->SetProgramVersion("$Id$"); - nxs->GetEntryIdf2()->SetRunNumber(fData[0].GetRunNumber()); - nxs->GetEntryIdf2()->SetTitle(fData[0].GetRunTitle()->Data()); - str = std::string(fData[0].GetStartDate()->Data()) + std::string("T") + std::string(fData[0].GetStartTime()->Data()); - nxs->GetEntryIdf2()->SetStartTime(str); - str = std::string(fData[0].GetStopDate()->Data()) + std::string("T") + std::string(fData[0].GetStopTime()->Data()); - nxs->GetEntryIdf2()->SetStopTime(str); - - nxs->GetEntryIdf2()->SetExperimentIdentifier("n/a"); - - // NXuser info - nxs->GetEntryIdf2()->GetUser()->SetName("n/a"); - - // NXsample info - nxs->GetEntryIdf2()->GetSample()->SetName(fData[0].GetSample()->Data()); - nxs->GetEntryIdf2()->GetSample()->SetDescription("n/a"); - nxs->GetEntryIdf2()->GetSample()->SetPhysProp("temperature_1", fData[0].GetTemperature(0), "Kelvin"); - nxs->GetEntryIdf2()->GetSample()->SetPhysProp("magnetic_field_1", fData[0].GetField(), "Gauss"); - nxs->GetEntryIdf2()->GetSample()->SetEnvironmentTemp(fData[0].GetSetup()->Data()); - nxs->GetEntryIdf2()->GetSample()->SetEnvironmentField("n/a"); - - // here would be the information for NXinstrument. Currently there are not much information to feed this - nxs->GetEntryIdf2()->GetInstrument()->SetName(fData[0].GetInstrument()->Data()); - - // NXinstrument/NXsource - nxs->GetEntryIdf2()->GetInstrument()->GetSource()->SetName(fData[0].GetLaboratory()->Data()); - nxs->GetEntryIdf2()->GetInstrument()->GetSource()->SetType(fData[0].GetMuonSource()->Data()); - nxs->GetEntryIdf2()->GetInstrument()->GetSource()->SetProbe(fData[0].GetMuonSpecies()->Data()); - - // NXinstrument/NXbeamline - nxs->GetEntryIdf2()->GetInstrument()->GetBeamline()->SetName(fData[0].GetBeamline()->Data()); - - // NXinstrument/NXdetector - nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetDescription(fData[0].GetInstrument()->Data()); // assume that this should be the instrument name - nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetNoOfPeriods(0); // currently red/green is not distinguished - nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetNoOfSpectra(fData[0].GetNoOfHistos()); - PRawRunDataSet *dataSet = fData[0].GetDataSet(0, false); // i.e. the false means, that i is the index and NOT the histo number - if (dataSet == nullptr) { // something is really wrong - std::cerr << std::endl << ">> PRunDataHandler::WriteNeXusFile: **ERROR** Couldn't get data set (idx=0)"; - std::cerr << std::endl << ">> something is really wrong!" << std::endl; - return false; - } - nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetNoOfBins((unsigned int)(dataSet->GetData()->size() / fAny2ManyInfo->rebin)); - nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetTimeResolution(fData[0].GetTimeResolution()*fAny2ManyInfo->rebin, "ns"); - int *histo = nullptr; - int idx = 0; - if (fAny2ManyInfo->rebin == 1) { - histo = new int[fData[0].GetNoOfHistos()*dataSet->GetData()->size()]; - idx = 0; - for (int i=0; iGetEntryIdf2()->GetInstrument()->GetDetector()->GetNoOfSpectra(); i++) { - dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number - if (dataSet == nullptr) { // something is really wrong - std::cerr << std::endl << ">> PRunDataHandler::WriteNeXusFile: **ERROR** Couldn't get data set (idx=" << i << ")"; - std::cerr << std::endl << ">> something is really wrong!" << std::endl; - return false; - } - for (unsigned int j=0; jGetData()->size(); j++) { - *(histo+idx++) = (int) dataSet->GetData()->at(j); - } - } - nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetHistos(histo); - // clean up - if (histo) { - delete [] histo; - histo = nullptr; - } - } else { // rebin > 1 - histo = new int[fData[0].GetNoOfHistos()*(int)(dataSet->GetData()->size()/fAny2ManyInfo->rebin)]; - int counts = 0; - idx = 0; - for (int i=0; iGetEntryIdf2()->GetInstrument()->GetDetector()->GetNoOfSpectra(); i++) { - dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number - if (dataSet == nullptr) { // something is really wrong - std::cerr << std::endl << ">> PRunDataHandler::WriteNeXusFile: **ERROR** Couldn't get data set (idx=" << i << ")"; - std::cerr << std::endl << ">> something is really wrong!" << std::endl; - return false; - } - for (unsigned int j=0; jGetData()->size(); j++) { - if ((j>0) && (j % fAny2ManyInfo->rebin == 0)) { - *(histo+idx++) = counts; - counts = 0; - } - counts += (int) dataSet->GetData()->at(j); - } - } - nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetHistos(histo); - // clean up - if (histo) { - delete [] histo; - histo = nullptr; - } - } - - // handle spectrum index - for (int i=0; iGetEntryIdf2()->GetInstrument()->GetDetector()->GetNoOfSpectra(); i++) - nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetSpectrumIndex(i+1); - - // handle histogram resolution - nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetTimeResolution(fData[0].GetTimeResolution()*fAny2ManyInfo->rebin, "ns"); - - // handle raw time - std::vector raw_time; - UInt_t size = (unsigned int)(dataSet->GetData()->size() / fAny2ManyInfo->rebin); - for (unsigned int i=0; irebin * 1.0e-3); // since time resolution is given in ns, the factor 1.0e-3 is needed to convert to us - } - nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetRawTime(raw_time); - nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetRawTimeUnit("micro.second"); - nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetRawTimeName("time"); - raw_time.clear(); - - // handle t0 - nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetT0Tag(2); // i.e. t0[#histo] format - int *t0 = new int[fData[0].GetNoOfHistos()]; - int *fgb = new int[fData[0].GetNoOfHistos()]; - int *lgb = new int[fData[0].GetNoOfHistos()]; - if ((t0==0) || (fgb==0) || (lgb==0)) { - std::cerr << std::endl << ">> PRunDataHandler::WriteNeXusFile: **ERROR** Couldn't allocate memory for t0, fgb, lgb" << std::endl; - return false; - } - for (unsigned int i=0; i> PRunDataHandler::WriteNeXusFile: **ERROR** Couldn't get data set (idx=0)"; - std::cerr << std::endl << ">> something is really wrong!" << std::endl; - return false; - } - t0[i] = (int)(dataSet->GetTimeZeroBin() / fAny2ManyInfo->rebin); - fgb[i] = (int)(dataSet->GetFirstGoodBin() / fAny2ManyInfo->rebin); - lgb[i] = (int)(dataSet->GetLastGoodBin() / fAny2ManyInfo->rebin); - } - nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetT0(t0); - nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetFirstGoodBin(fgb); - nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetLastGoodBin(lgb); - - // clean up - if (t0) delete [] t0; - if (fgb) delete [] fgb; - if (lgb) delete [] lgb; - } else { - return false; - } - - // filter out the proper file type, i.e. HDF4, HDF5, or XML - char fileType[32]; - memset(fileType, '\0', 32); - if (!fAny2ManyInfo->outFormat.CompareTo("nexus1-hdf4", TString::kIgnoreCase) || !fAny2ManyInfo->outFormat.CompareTo("nexus2-hdf4", TString::kIgnoreCase)) - strncpy(fileType, "hdf4", sizeof(fileType)); - else if (!fAny2ManyInfo->outFormat.CompareTo("nexus1-hdf5", TString::kIgnoreCase) || !fAny2ManyInfo->outFormat.CompareTo("nexus2-hdf5", TString::kIgnoreCase)) - strncpy(fileType, "hdf5", sizeof(fileType)); - else if (!fAny2ManyInfo->outFormat.CompareTo("nexus1-xml", TString::kIgnoreCase) || !fAny2ManyInfo->outFormat.CompareTo("nexus2-xml", TString::kIgnoreCase)) - strncpy(fileType, "xml", sizeof(fileType)); - else { - std::cerr << std::endl << ">> PRunDataHandler::WriteNexusFile(): **ERROR** undefined output NeXus format " << fAny2ManyInfo->outFormat.Data() << " found."; - std::cerr << std::endl << ">> Allowed are: hdf4, hdf5, xml" << std::endl; - return false; - } - - // write file - nxs->WriteFile(fln, fileType, fAny2ManyInfo->idf); -*/ //as35 #else std::cout << std::endl << ">> PRunDataHandler::WriteNexusFile(): Sorry, not enabled at configuration level, i.e. -Dnexus=1 when executing configure" << std::endl << std::endl; #endif diff --git a/src/external/nexus/PNeXus.cpp b/src/external/nexus/PNeXus.cpp index 13e926fb..7678aad2 100644 --- a/src/external/nexus/PNeXus.cpp +++ b/src/external/nexus/PNeXus.cpp @@ -1982,8 +1982,30 @@ int nxH4::PNeXus::WriteNexusFile(const std::string& filename, int idfVersion) WriteFileAttributes(sd_id); // Write datasets based on IDF version - if (idfVersion == 2) { - WriteIdfV2(sd_id); + if ((idfVersion == 1) || (idfVersion == 2)) { + // Write all datasets from data map + for (const auto& [path, data_any] : fDataMap) { + // Try to write as int dataset + try { + auto data = std::any_cast>(data_any); + WriteIntDataset(sd_id, path, data); + continue; + } catch (...) {} + + // Try to write as float dataset + try { + auto data = std::any_cast>(data_any); + WriteFloatDataset(sd_id, path, data); + continue; + } catch (...) {} + + // Try to write as string dataset + try { + auto data = std::any_cast>(data_any); + WriteStringDataset(sd_id, path, data); + continue; + } catch (...) {} + } } else { std::cerr << "**ERROR** Unsupported IDF version for writing: " << idfVersion << std::endl; SDend(sd_id); @@ -2039,36 +2061,6 @@ void nxH4::PNeXus::WriteFileAttributes(int32 sd_id) } } -//============================================================================= -// nxH4::PNeXus::WriteIdfV2 -//============================================================================= -void nxH4::PNeXus::WriteIdfV2(int32 sd_id) -{ - // Write all datasets from data map - for (const auto& [path, data_any] : fDataMap) { - // Try to write as int dataset - try { - auto data = std::any_cast>(data_any); - WriteIntDataset(sd_id, path, data); - continue; - } catch (...) {} - - // Try to write as float dataset - try { - auto data = std::any_cast>(data_any); - WriteFloatDataset(sd_id, path, data); - continue; - } catch (...) {} - - // Try to write as string dataset - try { - auto data = std::any_cast>(data_any); - WriteStringDataset(sd_id, path, data); - continue; - } catch (...) {} - } -} - //============================================================================= // nxH4::PNeXus::WriteIntDataset //============================================================================= diff --git a/src/external/nexus/PNeXus.h b/src/external/nexus/PNeXus.h index 2182022d..6fbc4d95 100644 --- a/src/external/nexus/PNeXus.h +++ b/src/external/nexus/PNeXus.h @@ -989,13 +989,6 @@ private: */ void WriteFileAttributes(int32 sd_id); - /** - * @brief Write IDF version 2 structure - * @param sd_id HDF4 SD interface ID - * @throws std::runtime_error if writing fails - */ - void WriteIdfV2(int32 sd_id); - // ======================================================================== // Case-insensitive lookup helper methods // ========================================================================