add HDF4/HDF5 library version information, needed for writing.

This commit is contained in:
2026-02-07 08:05:09 +01:00
parent 4519a0b76e
commit 4dcef1a835
2 changed files with 118 additions and 105 deletions

View File

@@ -302,6 +302,10 @@ void nxH4::PNeXusDeadTime::minimize(const int i)
//=============================================================================
nxH4::PNeXus::PNeXus() : fSdId(-1), fFileId(-1)
{
uint32 major_v, minor_v, release;
char string[256];
Hgetlibversion(&major_v, &minor_v, &release, string);
fHdf4LibVersion = string;
}
//=============================================================================
@@ -310,6 +314,11 @@ nxH4::PNeXus::PNeXus() : fSdId(-1), fFileId(-1)
nxH4::PNeXus::PNeXus(const std::string fln, const bool printDebug)
: fPrintDebug(printDebug), fFileName(fln), fSdId(-1), fFileId(-1)
{
uint32 major_v, minor_v, release;
char string[256];
Hgetlibversion(&major_v, &minor_v, &release, string);
fHdf4LibVersion = string;
if (ReadNexusFile() != 0) {
throw std::runtime_error("Failed to read NeXus file: " + fln);
}
@@ -3231,7 +3240,15 @@ std::string nxH5::PNeXus::findDatasetPath(H5::Group& parent, const std::string&
//=============================================================================
nxH5::PNeXus::PNeXus()
{
// empty
unsigned majnum, minnum, relnum;
herr_t status;
std::stringstream ss;
status = H5get_libversion(&majnum, &minnum, &relnum);
if (status >= 0) {
ss << majnum << "." << minnum << "." << relnum;
}
fHdf5LibVersion = ss.str();
}
//=============================================================================
@@ -3262,6 +3279,16 @@ nxH5::PNeXus::PNeXus()
*/
nxH5::PNeXus::PNeXus(const std::string fln, const bool printDebug) : fFileName(fln), fPrintDebug(printDebug)
{
unsigned majnum, minnum, relnum;
herr_t status;
std::stringstream ss;
status = H5get_libversion(&majnum, &minnum, &relnum);
if (status >= 0) {
ss << majnum << "." << minnum << "." << relnum;
}
fHdf5LibVersion = ss.str();
ReadNexusFile();
}
@@ -5309,84 +5336,6 @@ void nxH5::PNeXus::WriteFileAttributes(H5::H5File& file)
}
}
//=============================================================================
// Write IDF version 2 structure
//=============================================================================
/**
* Writes all datasets from the data map to the HDF5 file following the
* IDF version 2 structure. Iterates through fDataMap and writes each
* dataset based on its type.
*
* @param file HDF5 file object
* @throws H5::Exception if writing fails
*/
void nxH5::PNeXus::WriteIdfV2(H5::H5File& file)
{
if (fPrintDebug) {
std::cout << "debug> Writing IDF v2 structure..." << std::endl;
}
// Iterate through all datasets in fDataMap
for (const auto& [path, anyData] : fDataMap) {
try {
// Try PNXdata<int>
try {
auto intData = std::any_cast<PNXdata<int>>(anyData);
WriteIntDataset(file, path, intData);
continue;
} catch (const std::bad_any_cast&) {}
// Try PNXdata<int32_t> - convert to int
try {
auto int32Data = std::any_cast<PNXdata<int32_t>>(anyData);
// Convert PNXdata<int32_t> to PNXdata<int>
PNXdata<int> intData(int32Data.GetDataType());
intData.SetDimensions(int32Data.GetDimensions());
std::vector<int> convertedData;
for (auto val : int32Data.GetData()) {
convertedData.push_back(static_cast<int>(val));
}
intData.SetData(convertedData);
// Copy attributes
for (const auto& [name, value] : int32Data.GetAttributes()) {
intData.AddAttribute(name, value);
}
WriteIntDataset(file, path, intData);
continue;
} catch (const std::bad_any_cast&) {}
// Try PNXdata<float>
try {
auto floatData = std::any_cast<PNXdata<float>>(anyData);
WriteFloatDataset(file, path, floatData);
continue;
} catch (const std::bad_any_cast&) {}
// Try PNXdata<std::string>
try {
auto strData = std::any_cast<PNXdata<std::string>>(anyData);
WriteStringDataset(file, path, strData);
continue;
} catch (const std::bad_any_cast&) {}
// Unknown type
if (fPrintDebug) {
std::cerr << "Warning: Unknown data type for path " << path
<< std::endl;
}
} catch (const H5::Exception& err) {
std::cerr << "Error writing dataset " << path << ": "
<< err.getDetailMsg() << std::endl;
throw;
}
}
}
//=============================================================================
// Group attribute management methods
//=============================================================================
@@ -5549,13 +5498,70 @@ int nxH5::PNeXus::WriteNexusFile(const std::string& filename, int idfVersion)
WriteFileAttributes(file);
// Write structure based on IDF version
if (idfVersion == 1) {
std::cerr << "Error: IDF version 1 writing not yet implemented"
if ((idfVersion == 1) || (idfVersion == 2)) {
if (fPrintDebug) {
std::cout << "debug> Writing IDF v2 structure..." << std::endl;
}
// Iterate through all datasets in fDataMap
for (const auto& [path, anyData] : fDataMap) {
try {
// Try PNXdata<int>
try {
auto intData = std::any_cast<PNXdata<int>>(anyData);
WriteIntDataset(file, path, intData);
continue;
} catch (const std::bad_any_cast&) {}
// Try PNXdata<int32_t> - convert to int
try {
auto int32Data = std::any_cast<PNXdata<int32_t>>(anyData);
// Convert PNXdata<int32_t> to PNXdata<int>
PNXdata<int> intData(int32Data.GetDataType());
intData.SetDimensions(int32Data.GetDimensions());
std::vector<int> convertedData;
for (auto val : int32Data.GetData()) {
convertedData.push_back(static_cast<int>(val));
}
intData.SetData(convertedData);
// Copy attributes
for (const auto& [name, value] : int32Data.GetAttributes()) {
intData.AddAttribute(name, value);
}
WriteIntDataset(file, path, intData);
continue;
} catch (const std::bad_any_cast&) {}
// Try PNXdata<float>
try {
auto floatData = std::any_cast<PNXdata<float>>(anyData);
WriteFloatDataset(file, path, floatData);
continue;
} catch (const std::bad_any_cast&) {}
// Try PNXdata<std::string>
try {
auto strData = std::any_cast<PNXdata<std::string>>(anyData);
WriteStringDataset(file, path, strData);
continue;
} catch (const std::bad_any_cast&) {}
// Unknown type
if (fPrintDebug) {
std::cerr << "Warning: Unknown data type for path " << path
<< std::endl;
file.close();
return 1;
} else if (idfVersion == 2) {
WriteIdfV2(file);
}
} catch (const H5::Exception& err) {
std::cerr << "Error writing dataset " << path << ": "
<< err.getDetailMsg() << std::endl;
throw;
}
}
} else {
std::cerr << "Error: Unsupported IDF version " << idfVersion
<< std::endl;

View File

@@ -543,6 +543,12 @@ public:
*/
std::string GetFileName() const { return fFileName; }
/**
* @brief Get the hdf4 library version
* @return The hdf4 version as a string
*/
std::string GetHdf4LibVersion() const { return fHdf4LibVersion; }
/**
* @brief Get the hdf4 version of the NeXus file
* @return The hdf4 version as a string
@@ -874,6 +880,7 @@ private:
bool fPrintDebug{false}; ///< if true print additional debug information
std::string fFileName{""}; ///< NeXus HDF4 filename
int fIdfVersion{-1}; ///< IDF version of the NeXus file
std::string fHdf4LibVersion{""}; ///< HDF4 library version used when calling PNeXus
std::string fHdf4Version{""}; ///< HDF4 version of the file
std::string fNeXusVersion{""}; ///< NeXus version of the file
std::string fFileNameNxs{""};
@@ -1488,6 +1495,12 @@ public:
*/
std::string GetFileName() const { return fFileName; }
/**
* @brief Get the HDF5 library version string
* @return The HDF5 version as a string (e.g., "1.10.4")
*/
std::string GetHdf5LibVersion() const { return fHdf5LibVersion; }
/**
* @brief Get the HDF5 version string from the file
* @return The HDF5 version as a string (e.g., "1.10.4")
@@ -1843,6 +1856,7 @@ private:
bool fPrintDebug{false}; ///< if true print additional debug information
std::string fFileName{""}; ///< NeXus HDF5 filename
int fIdfVersion{-1}; ///< IDF version of the NeXus file
std::string fHdf5LibVersion{"n/a"}; ///< HDF5 library version used when calling PNeXus
std::string fHdf5Version{""}; ///< HDF5 version of the file
std::string fNeXusVersion{""}; ///< NeXus version of the file
std::string fFileNameNxs{""};
@@ -1948,13 +1962,6 @@ private:
*/
void WriteFileAttributes(H5::H5File& file);
/**
* @brief Write IDF version 2 structure
* @param file HDF5 file object
* @throws H5::Exception if writing fails
*/
void WriteIdfV2(H5::H5File& file);
// ========================================================================
// Case-insensitive lookup helper methods
// ========================================================================