guard all any_cast attribute reads in ReadNexusFileIdf1 against bad_any_cast

Uncaught std::bad_any_cast calls terminated the program when an HDF4
attribute's stored type didn't match the expected type (e.g. vector<int>
instead of int, or a non-string units attribute). Wrap all eight attribute
casts with try/catch so type mismatches produce a warning rather than a crash.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-07-15 10:33:00 +02:00
co-authored by Claude Sonnet 4.6
parent 66ac3757e6
commit c4929ccc4c
+149 -10
View File
@@ -530,16 +530,155 @@ Bool_t PRunDataHandler::ReadNexusFileIdf1(T& nxs_file)
ival = nxs_file->template GetDataset<int>("/run/number").GetData()[0];
runData.SetRunNumber(ival);
// get/set temperature
dval = PMUSR_UNDEFINED;
sstr = "n/a";
if (nxs_file->HasDataset("/run/sample/temperature")) {
auto tmp_ds = nxs_file->template GetDataset<float>("/run/sample/temperature");
dval = tmp_ds.GetData()[0];
if (tmp_ds.HasAttribute("units"))
sstr = std::any_cast<std::string>(tmp_ds.GetAttribute("units"));
if (sstr == "Celcius")
dval += 273.16;
// get/set temperature
dval = PMUSR_UNDEFINED;
sstr = "n/a";
if (nxs_file->HasDataset("/run/sample/temperature")) {
auto tmp_ds = nxs_file->template GetDataset<float>("/run/sample/temperature");
dval = tmp_ds.GetData()[0];
if (tmp_ds.HasAttribute("units")) {
try {
sstr = std::any_cast<std::string>(tmp_ds.GetAttribute("units"));
} catch (const std::bad_any_cast&) {
std::cerr << std::endl << "**WARNING** ReadNexusFileIdf1: temperature 'units' attribute has unexpected type." << std::endl;
}
}
if (sstr == "Celcius")
dval += 273.16;
}
runData.SetTemperature(0, dval, 0.0);
// get/set field
dval = PMUSR_UNDEFINED;
sstr = "n/a";
factor = 1.0;
if (nxs_file->HasDataset("/run/sample/magnetic_field")) {
auto mag_ds = nxs_file->template GetDataset<float>("/run/sample/magnetic_field");
dval = mag_ds.GetData()[0];
if (mag_ds.HasAttribute("units")) {
try {
sstr = std::any_cast<std::string>(mag_ds.GetAttribute("units"));
} catch (const std::bad_any_cast&) {
std::cerr << std::endl << "**WARNING** ReadNexusFileIdf1: magnetic_field 'units' attribute has unexpected type." << std::endl;
}
}
if (sstr == "Tesla")
factor = 1.0e4;
}
runData.SetField(dval*factor);
// get/set implantation energy
runData.SetEnergy(PMUSR_UNDEFINED);
// get/set moderator HV
runData.SetTransport(PMUSR_UNDEFINED);
// get/set RA HV's (LEM specific)
for (UInt_t i=0; i<4; i++)
runData.SetRingAnode(i, PMUSR_UNDEFINED);
// get/set setup
sstr = "n/a";
if (nxs_file->HasDataset("/run/notes"))
sstr = nxs_file->template GetDataset<std::string>("/run/notes").GetData()[0];
runData.SetSetup(sstr);
// get/set sample
sstr = "n/a";
if (nxs_file->HasDataset("/run/sample/name"))
sstr = nxs_file->template GetDataset<std::string>("/run/sample/name").GetData()[0];
runData.SetSample(sstr);
// get/set orientation
runData.SetOrientation("??");
// get/set time resolution (ns)
dval = PMUSR_UNDEFINED;
sstr = "n/a";
factor = 1.0;
if (nxs_file->HasDataset("/run/histogram_data_1/resolution")) {
auto res_ds = nxs_file->template GetDataset<int>("/run/histogram_data_1/resolution");
dval = res_ds.GetData()[0];
if (res_ds.HasAttribute("units")) {
try {
sstr = std::any_cast<std::string>(res_ds.GetAttribute("units"));
} catch (const std::bad_any_cast&) {
std::cerr << std::endl << "**WARNING** ReadNexusFileIdf1: resolution 'units' attribute has unexpected type." << std::endl;
}
}
if ((sstr == "picoseconds") || (sstr == "pico.seconds"))
factor = 1.0e-3; // ps -> ns
}
runData.SetTimeResolution(dval*factor);
// get/set start/stop time
sstr = "n/a";
TString date{"n/a"}, time{"n/a"};
if (nxs_file->HasDataset("/run/start_time"))
sstr = nxs_file->template GetDataset<std::string>("/run/start_time").GetData()[0];
str = sstr;
SplitTimeDate(str, time, date, ok);
if (ok) {
runData.SetStartTime(time);
runData.SetStartDate(date);
}
sstr = "n/a";
date = "n/a";
time = "n/a";
if (nxs_file->HasDataset("/run/stop_time"))
sstr = nxs_file->template GetDataset<std::string>("/run/stop_time").GetData()[0];
str = sstr;
SplitTimeDate(str, time, date, ok);
if (ok) {
runData.SetStopTime(time);
runData.SetStopDate(date);
}
// get/set deadtime relevant parameters
if (nxs_file->HasDataset("/run/instrument/detector/deadtimes")) {
std::vector<float> dt;
dt = nxs_file->template GetDataset<float>("/run/instrument/detector/deadtimes").GetData();
runData.SetDeadTimeParam(dt);
}
if (nxs_file->HasDataset("/run/instrument/beam/frames_good")) {
ival = nxs_file->template GetDataset<int>("/run/instrument/beam/frames_good").GetData()[0];
runData.SetNumberOfGoodFrames(ival);
}
// data with its metadata
if (nxs_file->HasDataset("/run/histogram_data_1/counts")) {
int t0_bin{-1}, fgb{-1}, lgb{-1}, noOfHistos{-1}, histoLength{-1};
auto count_ds = nxs_file->template GetDataset<int>("/run/histogram_data_1/counts");
auto count = count_ds.GetData();
// get all necessary attributes
auto castIntAttr = [](const std::any& val, const std::string& name) -> int {
try {
return std::any_cast<int>(val);
} catch (const std::bad_any_cast&) {
try {
// Attribute may be stored as vector<int> when HDF4 attr_count > 1
return std::any_cast<std::vector<int>>(val)[0];
} catch (const std::bad_any_cast&) {
std::cerr << std::endl << "**WARNING** ReadNexusFileIdf1: counts attribute '" << name
<< "' has unexpected type; defaulting to -1." << std::endl;
return -1;
}
}
};
if (count_ds.HasAttribute("t0_bin"))
t0_bin = castIntAttr(count_ds.GetAttribute("t0_bin"), "t0_bin");
if (count_ds.HasAttribute("first_good_bin"))
fgb = castIntAttr(count_ds.GetAttribute("first_good_bin"), "first_good_bin");
if (count_ds.HasAttribute("last_good_bin"))
lgb = castIntAttr(count_ds.GetAttribute("last_good_bin"), "last_good_bin");
if (count_ds.HasAttribute("number"))
noOfHistos = castIntAttr(count_ds.GetAttribute("number"), "number");
if (count_ds.HasAttribute("length"))
histoLength = castIntAttr(count_ds.GetAttribute("length"), "length");
if (static_cast<int>(count.size()) != noOfHistos*histoLength) {
std::cerr << std::endl << "**ERROR** PNeXus data size error! count.size()=" << count.size() << ", #histos=" << noOfHistos << ", length=" << histoLength << "." << std::endl;
return false;
}
runData.SetTemperature(0, dval, 0.0);