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) 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) nxH4::PNeXus::PNeXus(const std::string fln, const bool printDebug)
: fPrintDebug(printDebug), fFileName(fln), fSdId(-1), fFileId(-1) : 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) { if (ReadNexusFile() != 0) {
throw std::runtime_error("Failed to read NeXus file: " + fln); 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() 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) 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(); 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 // Group attribute management methods
//============================================================================= //=============================================================================
@@ -5549,13 +5498,70 @@ int nxH5::PNeXus::WriteNexusFile(const std::string& filename, int idfVersion)
WriteFileAttributes(file); WriteFileAttributes(file);
// Write structure based on IDF version // Write structure based on IDF version
if (idfVersion == 1) { if ((idfVersion == 1) || (idfVersion == 2)) {
std::cerr << "Error: IDF version 1 writing not yet implemented" 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; << std::endl;
file.close(); }
return 1;
} else if (idfVersion == 2) { } catch (const H5::Exception& err) {
WriteIdfV2(file); std::cerr << "Error writing dataset " << path << ": "
<< err.getDetailMsg() << std::endl;
throw;
}
}
} else { } else {
std::cerr << "Error: Unsupported IDF version " << idfVersion std::cerr << "Error: Unsupported IDF version " << idfVersion
<< std::endl; << std::endl;

View File

@@ -543,6 +543,12 @@ public:
*/ */
std::string GetFileName() const { return fFileName; } 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 * @brief Get the hdf4 version of the NeXus file
* @return The hdf4 version as a string * @return The hdf4 version as a string
@@ -874,6 +880,7 @@ private:
bool fPrintDebug{false}; ///< if true print additional debug information bool fPrintDebug{false}; ///< if true print additional debug information
std::string fFileName{""}; ///< NeXus HDF4 filename std::string fFileName{""}; ///< NeXus HDF4 filename
int fIdfVersion{-1}; ///< IDF version of the NeXus file 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 fHdf4Version{""}; ///< HDF4 version of the file
std::string fNeXusVersion{""}; ///< NeXus version of the file std::string fNeXusVersion{""}; ///< NeXus version of the file
std::string fFileNameNxs{""}; std::string fFileNameNxs{""};
@@ -1488,6 +1495,12 @@ public:
*/ */
std::string GetFileName() const { return fFileName; } 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 * @brief Get the HDF5 version string from the file
* @return The HDF5 version as a string (e.g., "1.10.4") * @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 bool fPrintDebug{false}; ///< if true print additional debug information
std::string fFileName{""}; ///< NeXus HDF5 filename std::string fFileName{""}; ///< NeXus HDF5 filename
int fIdfVersion{-1}; ///< IDF version of the NeXus file 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 fHdf5Version{""}; ///< HDF5 version of the file
std::string fNeXusVersion{""}; ///< NeXus version of the file std::string fNeXusVersion{""}; ///< NeXus version of the file
std::string fFileNameNxs{""}; std::string fFileNameNxs{""};
@@ -1948,13 +1962,6 @@ private:
*/ */
void WriteFileAttributes(H5::H5File& file); 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 // Case-insensitive lookup helper methods
// ======================================================================== // ========================================================================