add HDF4/HDF5 library version information, needed for writing.
This commit is contained in:
190
src/external/nexus/PNeXus.cpp
vendored
190
src/external/nexus/PNeXus.cpp
vendored
@@ -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
|
||||
//=============================================================================
|
||||
@@ -5533,29 +5482,86 @@ int nxH5::PNeXus::WriteNexusFile(const std::string& filename, int idfVersion)
|
||||
std::cout << "debug> Creating NeXus file: " << filename << std::endl;
|
||||
}
|
||||
|
||||
// Validate that we have data to write
|
||||
// Validate that we have data to write
|
||||
if (fDataMap.empty()) {
|
||||
std::cerr << "Error: No data to write (data map is empty)" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Create new HDF5 file (truncate if exists)
|
||||
// Create new HDF5 file (truncate if exists)
|
||||
H5::H5File file(filename, H5F_ACC_TRUNC);
|
||||
|
||||
// Turn off auto-printing for exceptions
|
||||
// Turn off auto-printing for exceptions
|
||||
H5::Exception::dontPrint();
|
||||
|
||||
// Write root-level file attributes
|
||||
// Write root-level file attributes
|
||||
WriteFileAttributes(file);
|
||||
|
||||
// Write structure based on IDF version
|
||||
if (idfVersion == 1) {
|
||||
std::cerr << "Error: IDF version 1 writing not yet implemented"
|
||||
<< std::endl;
|
||||
file.close();
|
||||
return 1;
|
||||
} else if (idfVersion == 2) {
|
||||
WriteIdfV2(file);
|
||||
// Write structure based on IDF version
|
||||
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;
|
||||
}
|
||||
|
||||
} 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;
|
||||
@@ -5563,7 +5569,7 @@ int nxH5::PNeXus::WriteNexusFile(const std::string& filename, int idfVersion)
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Close file
|
||||
// Close file
|
||||
file.close();
|
||||
|
||||
if (fPrintDebug) {
|
||||
|
||||
33
src/external/nexus/PNeXus.h
vendored
33
src/external/nexus/PNeXus.h
vendored
@@ -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{""};
|
||||
@@ -981,9 +988,9 @@ private:
|
||||
*/
|
||||
void WriteIdfV2(int32 sd_id);
|
||||
|
||||
// ========================================================================
|
||||
// Case-insensitive lookup helper methods
|
||||
// ========================================================================
|
||||
// ========================================================================
|
||||
// Case-insensitive lookup helper methods
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* @brief Compare two strings case-insensitively
|
||||
@@ -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,16 +1962,9 @@ 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
|
||||
// ========================================================================
|
||||
// ========================================================================
|
||||
// Case-insensitive lookup helper methods
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* @brief Compare two strings case-insensitively
|
||||
|
||||
Reference in New Issue
Block a user