@@ -1019,7 +1019,7 @@ void Measurement::set_info_from_txt_or_csv( std::istream& istr )
1019
1019
}
1020
1020
1021
1021
int channel = 0 ;
1022
- float energy = 0 .0f , count = 0 .0f ; // , count2 = 0.0f;
1022
+ float energy = 0 .0f , count = 0 .0f ;
1023
1023
for ( size_t col = 0 ; col < fields.size (); ++col )
1024
1024
{
1025
1025
if ( column_map.count (col) )
@@ -1029,7 +1029,6 @@ void Measurement::set_info_from_txt_or_csv( std::istream& istr )
1029
1029
case kChannel : channel = atoi (fields[col].c_str ()); break ;
1030
1030
case kEnergy : energy = static_cast <float >(atof (fields[col].c_str ())); break ;
1031
1031
case kCounts : count = static_cast <float >(atof (fields[col].c_str ())); break ;
1032
- // case kCounts + 1: count2 = static_cast<float>(atof(fields[col].c_str())); break;
1033
1032
default :
1034
1033
// \TODO: Ignoring past the first record...
1035
1034
assert ( column_map[col] > kCounts );
@@ -1040,12 +1039,9 @@ void Measurement::set_info_from_txt_or_csv( std::istream& istr )
1040
1039
1041
1040
if ( IsNan (energy) || IsInf (energy) )
1042
1041
continue ;
1043
- if ( IsNan (count) || IsInf (count) /* || IsNan(count2) || IsInf(count2) */ )
1042
+ if ( IsNan (count) || IsInf (count) )
1044
1043
continue ;
1045
1044
1046
- // if( errno )
1047
- // throw runtime_error( "Error converting to float" );
1048
-
1049
1045
energy *= energy_units;
1050
1046
1051
1047
if ( (energies->size () && (energies->back () > energy) )
@@ -1062,11 +1058,11 @@ void Measurement::set_info_from_txt_or_csv( std::istream& istr )
1062
1058
}while ( SpecUtils::safe_get_line ( istr, line, maxlen ) );
1063
1059
1064
1060
if ( counts->empty () )
1065
- throw runtime_error ( " Didnt find and channel counts" );
1061
+ throw runtime_error ( " Didnt find any channel counts" );
1066
1062
1067
1063
gamma_counts_ = counts;
1068
1064
1069
- if ( (energies->size () >= counts->size ()) && (energies->back ()!= 0 .0f ) )
1065
+ if ( (energies->size () >= counts->size ()) && (energies->back () != 0 .0f ) )
1070
1066
{
1071
1067
try
1072
1068
{
@@ -1082,12 +1078,20 @@ void Measurement::set_info_from_txt_or_csv( std::istream& istr )
1082
1078
1083
1079
break ;
1084
1080
}else if ( column_map.empty ()
1085
- && ( istarts_with ( fields[0 ], " channel" )
1081
+ && (
1082
+ // Let counts header be "Channel", "Counts", "Ch", or similar non-English varients
1083
+ istarts_with ( fields[0 ], " channel" )
1086
1084
|| istarts_with ( fields[0 ], " counts" )
1087
- || istarts_with ( fields[0 ], " data" )
1088
- || istarts_with ( fields[0 ], " energy" )
1089
1085
|| istarts_with ( fields[0 ], " Ch" )
1090
1086
|| istarts_with ( fields[0 ], " Канал" )
1087
+ // For a single column data
1088
+ || istarts_with ( fields[0 ], " data" )
1089
+ // energy header can be like "Energy", "Energy (keV)", "En", or similar, but we dont
1090
+ // want to mistake something like "Energy Calibration, ..." as a column header
1091
+ || istarts_with ( fields[0 ], " energy (" )
1092
+ || iequals_ascii (fields[0 ], " energy" )
1093
+ || iequals_ascii (fields[0 ], " en" )
1094
+ || iequals_ascii (fields[0 ], " en (" )
1091
1095
|| fields[0 ]==" ##" ) )
1092
1096
{
1093
1097
++nlines_used;
@@ -1345,21 +1349,53 @@ void Measurement::set_info_from_txt_or_csv( std::istream& istr )
1345
1349
1346
1350
if ( c > 0 || b > 0 )
1347
1351
poly_calib_coeff = { d, c, b, a };
1352
+ }else if ( poly_calib_coeff.empty ()
1353
+ && starts_with ( fields[0 ], " energy calibration" )
1354
+ && (fields.size () >= 3 )
1355
+ && starts_with ( fields[1 ], " offset:" )
1356
+ && starts_with ( fields[2 ], " slope:" ) )
1357
+ {
1358
+ // Canberra Lynx CSV files get here
1359
+ // fields == {"energy calibration", "offset: -2.69", "slope: 0.37", "quadratic: -2.89e-7"}
1360
+ // Note: because lower channel energies are also provided, this polynomial calibration we are
1361
+ // parsing out here, wont be used.
1362
+ map<string,float > vals_map{ {" offset" , 0 .0f }, {" slope" , 0 .0f }, {" quadratic" , 0 .0f } };
1363
+
1364
+ for ( size_t i = 1 ; i < fields.size (); ++i )
1365
+ {
1366
+ float val;
1367
+ vector<string> parts;
1368
+ SpecUtils::split ( parts, fields[i], " : \t " );
1369
+
1370
+ if ( (parts.size () >= 2 ) && SpecUtils::parse_float (parts[1 ].c_str (), parts[1 ].size (), val) )
1371
+ vals_map[parts[0 ]] = val;
1372
+ }
1373
+
1374
+ poly_calib_coeff = vector<float >{ vals_map[" offset" ], vals_map[" slope" ], vals_map[" quadratic" ] };
1375
+ while ( !poly_calib_coeff.empty () && (poly_calib_coeff.back () == 0.0 ) )
1376
+ poly_calib_coeff.resize ( poly_calib_coeff.size () - 1 );
1377
+ }else
1378
+ {
1379
+ // unidentified line
1348
1380
}
1349
-
1350
1381
}// while( getline( istr, line ) )
1351
1382
1352
- if ( nlines_total < 10 || nlines_used < static_cast <size_t >( ceil (0.25 *nlines_total) ))
1383
+ if ( ( nlines_total < 10 ) || ( nlines_used < static_cast <size_t >( ceil (0.25 *nlines_total) )) )
1353
1384
{
1354
1385
reset ();
1355
1386
istr.seekg ( orig_pos, ios::beg );
1356
1387
istr.clear ( ios::failbit );
1357
1388
throw runtime_error ( " Not enough (useful) lines in the file." );
1358
1389
}//
1359
1390
1391
+ // If we have polynomial energy calibration terms, we will only use them if we dont already
1392
+ // have another energy calibration - this includes when lower channel energies are specified
1393
+ // (perhaps we should check if polynomial and lower channel energies are about the same, and
1394
+ // if so, go with the polynomial)
1360
1395
const size_t nchannel = gamma_counts_ ? gamma_counts_->size () : size_t (0 );
1361
- if ( nchannel>=2 && !poly_calib_coeff.empty ()
1362
- && (energy_calibration_->type () == EnergyCalType::InvalidEquationType) )
1396
+ if ( (nchannel >= 2 )
1397
+ && (poly_calib_coeff.size () >= 2 )
1398
+ && (energy_calibration_->type () == EnergyCalType::InvalidEquationType) )
1363
1399
{
1364
1400
try
1365
1401
{
0 commit comments