Skip to content

Commit 073798a

Browse files
committed
Merge branch 'master' of github.com:sandialabs/InterSpec
2 parents 0a15513 + fc35503 commit 073798a

18 files changed

+623
-91
lines changed

InterSpec/DetectorPeakResponse.h

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,8 +283,27 @@ class DetectorPeakResponse
283283
const float detectorDiameter,
284284
const float energyUnits,
285285
const EffGeometryType geometry_type );
286-
287-
286+
287+
struct EnergyEffPoint
288+
{
289+
float energy, efficiency;
290+
291+
/** Currently unused efficiency uncertainty. */
292+
std::optional<float> efficiencyUncert;
293+
};//struct EnergyEffPoint
294+
295+
/** Sets the detector efficiencies by pairs of energy (in keV) and efficiencies.
296+
297+
@param efficiencies The eneryg/efficiency information - must have at least two entries, and its range defines `m_lowerEnergy` and `m_upperEnergy`.
298+
@param detectorDiameter The detector diameter - set to zero or negative if geometry type is not EffGeometryType::FarField; must be positive if far field
299+
@param geometry_type The efficiency type these points are for.
300+
301+
Throws exception on error.
302+
*/
303+
void setEfficiencyPoints( const std::vector<EnergyEffPoint> &efficiencies,
304+
const float detectorDiameter,
305+
const EffGeometryType geometry_type );
306+
288307
//setIntrinsicEfficiencyFormula(): sets m_efficiencyForm, m_efficiencyFormula,
289308
// and m_efficiencyFcn to correspond to the fucntional form passed in.
290309
// Formula should be in the a general functional form, where energy is

InterSpec/RelActCalc.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -316,10 +316,16 @@ struct PhysicalModelShieldInput
316316
*/
317317
bool fit_areal_density = true;
318318

319-
/** The lower AD for the shielding. Must be in range [0,500] g/cm2, if fitting AD. */
319+
/** The lower AD for the shielding. Must be in range [0,500] g/cm2, if fitting AD.
320+
321+
In units of `PhysicalUnits` - i.e., you need to divide by `PhysicalUnits::g_per_cm2` to printout to g/cm2 human values.
322+
*/
320323
double lower_fit_areal_density = 0.0;
321324

322-
/** The upper AD for the shielding. Must be greater than to lower AD, if fitting, and must be in range [0,500] g/cm2. */
325+
/** The upper AD for the shielding. Must be greater than to lower AD, if fitting, and must be in range [0,500] g/cm2.
326+
327+
In units of `PhysicalUnits` - i.e., you need to divide by `PhysicalUnits::g_per_cm2` to printout to g/cm2 human values.
328+
*/
323329
double upper_fit_areal_density = 0.0;
324330

325331
/** Checks specified constraints are obeyed - throwing an exception if not. */

InterSpec/RelActCalcAuto_imp.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ struct PeakDefImp
110110

111111
/** Gives lower and upper energies that contain `1.0 - missing_frac` of the peak,
112112
113-
For skewed distributions, particularly Crystal Bal, the energy range given by the desired
113+
For skewed distributions, particularly Crystal Ball, the energy range given by the desired
114114
peak coverage can get huge, so you can also specify the max number of FWHM to use, which will
115115
truncate the range in these cases of very large skew.
116116

InterSpec/SpecMeas.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,11 @@ class SpecMeas : public SpecUtils::SpecFile
132132
const std::set<int> &det_nums ) const;
133133
/** Adds reading back in peak information (only from InterSpec exported SPE files though). */
134134
virtual bool load_from_iaea( std::istream &istr );
135-
135+
136+
virtual void load_cnf_using_reader( CAMInputOutput::CAMIO &reader );
137+
136138
virtual std::shared_ptr< ::rapidxml::xml_document<char> > create_2012_N42_xml() const;
137-
139+
138140
/** Same as #SpecFile::set_energy_calibration, but marks this SpecMeas as modified. */
139141
virtual void set_energy_calibration( const std::shared_ptr<const SpecUtils::EnergyCalibration> &cal,
140142
const std::shared_ptr<const SpecUtils::Measurement> &measurement );

InterSpec_resources/SpecMeasManager.css

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,11 @@ button.LinkBtn.NonSpecQrCodeBtn.Wt-btn.with-label
135135
max-width: 85vw;
136136
}
137137

138+
.simple-dialog.EccDrfDialog .body.NonSpecDialogBody
139+
{
140+
padding-bottom: 8px;
141+
}
142+
138143
.simple-dialog.EccDrfDialog .HowToUseGrp
139144
{
140145
display: flex;
@@ -146,12 +151,15 @@ button.LinkBtn.NonSpecQrCodeBtn.Wt-btn.with-label
146151
{
147152
margin-left: 40px;
148153
margin-top: 10px;
154+
149155
}
150156

151157
.simple-dialog.EccDrfDialog table.FarFieldOptTbl td
152158
{
153159
vertical-align: middle;
154-
padding-left: 5px
160+
padding-left: 5px;
161+
padding-bottom: 2px;
162+
padding-top: 2px;
155163
}
156164

157165
.simple-dialog.EccDrfDialog .EccDrfTypeBtn

InterSpec_resources/app_text/RefSpectraWidget.xml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
<messages>
33
<!-- rs- is short for Reference Spectra -->
44
<message id="rs-dialog-title">Reference Spectra</message>
5-
<message id="rs-show-foreground">Show Foreground</message>
6-
<message id="rs-show-background">Background</message>
5+
<message id="rs-show-foreground">Compare Foreground</message>
6+
<message id="rs-show-foreground-portrait">Compare</message>
7+
<message id="rs-show-background">Show Background</message>
8+
<message id="rs-show-background-portrait">Background</message>
79
<message id="rs-tt-add-dir-btn">Add directory to open reference spectra from.</message>
810
<message id="rs-tt-delete-dir-btn">Removes the currently selected directory from the list of places to show reference spectra from.</message>
911
<message id="rs-no-dir-selected-desktop">

InterSpec_resources/app_text/SpecMeasManager.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@
133133
<message id="smm-ecc-fix-geom-act-m2">Fixed Geometry - activity per m2</message>
134134
<message id="smm-ecc-fix-geom-act-gram">Fixed Geometry - activity per gram</message>
135135
<message id="smm-ecc-det-diam">Detector diam.</message>
136-
<message id="smm-ecc-dist">Distance.</message>
136+
<message id="smm-ecc-dist">Distance</message>
137137
<message id="smm-ecc-use-drf">Use DRF</message>
138138
<message id="smm-ecc-error">Error creating DRF from ECC: {1}</message>
139139

src/DetectorPeakResponse.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -898,6 +898,46 @@ void DetectorPeakResponse::fromEnergyEfficiencyCsv( std::istream &input,
898898
}//void fromEnergyEfficiencyCsv(...)
899899

900900

901+
void DetectorPeakResponse::setEfficiencyPoints( const std::vector<DetectorPeakResponse::EnergyEffPoint> &efficiencies,
902+
const float detectorDiameter,
903+
const EffGeometryType geometry_type )
904+
{
905+
if( (geometry_type == EffGeometryType::FarField)
906+
&& ((detectorDiameter <= 0.0) || IsInf(detectorDiameter) || IsNan(detectorDiameter)) )
907+
throw runtime_error( "Detector diameter must be greater than 0.0" );
908+
909+
if( efficiencies.size() < 2 )
910+
throw runtime_error( "DetectorPeakResponse::setEfficiencyPoints(): need at least two efficiency points." );
911+
912+
m_energyEfficiencies.clear();
913+
for( const EnergyEffPoint &p : efficiencies )
914+
{
915+
if( p.energy < 0.0 || p.efficiency < 0.0 )
916+
throw runtime_error( "Energy and efficiency musst be >= 0" );
917+
918+
EnergyEfficiencyPair eep;
919+
eep.energy = p.energy;
920+
eep.efficiency = p.efficiency;
921+
922+
m_energyEfficiencies.push_back( std::move(eep) );
923+
}//for( const EnergyEffPoint &p : efficiencies )
924+
925+
std::sort( begin(m_energyEfficiencies), end(m_energyEfficiencies) );
926+
927+
m_detectorDiameter = detectorDiameter;
928+
m_efficiencyEnergyUnits = static_cast<float>(PhysicalUnits::keV);
929+
930+
m_flags = 0;
931+
932+
m_lowerEnergy = m_energyEfficiencies.front().energy;
933+
m_upperEnergy = m_energyEfficiencies.back().energy;
934+
935+
m_lastUsedUtc = m_createdUtc = std::time(nullptr);
936+
m_geomType = geometry_type;
937+
938+
computeHash();
939+
}//void setEfficiencyPoints(...)
940+
901941

902942
void DetectorPeakResponse::setIntrinsicEfficiencyFormula( const string &fcnstr,
903943
const float diameter,

src/PeakFitLM.cpp

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1509,11 +1509,20 @@ vector<shared_ptr<const PeakDef>> fit_peaks_in_roi_LM( const vector<shared_ptr<c
15091509
options.min_trust_region_radius = 1e-32;
15101510
// Lower bound for the relative decrease before a step is accepted.
15111511
options.min_relative_decrease = 1e-3; //pseudo optimized based on success rate of fitting peaks - but unknown effect on accuracy of fits.
1512-
options.max_num_iterations = 50000;
1512+
1513+
// It looks like it usually takes well below 100 calls to solve most problems, but a tail up to ~500, and then rare
1514+
// (pathelogical?) cases that can take >50k
1515+
// However, for these pathological cases, if we just try again starting from where it left off, it will solve
1516+
// it super quick - I guess because there will be more "momentum" to find the minimum, or something, not totally
1517+
// sure.
1518+
// We could probably reduce this number of iterations to ~100 - but the effects or impact of this hasnt been
1519+
// evaluated.
1520+
// Also, have not checked dependence on number of peaks at all
1521+
options.max_num_iterations = (coFitPeaks.size() > 2) ? 1000 : 500;
15131522
#ifndef NDEBUG
1514-
options.max_solver_time_in_seconds = 300.0;
1523+
options.max_solver_time_in_seconds = (coFitPeaks.size() > 2) ? 180.0 : 120;
15151524
#else
1516-
options.max_solver_time_in_seconds = 30.0;
1525+
options.max_solver_time_in_seconds = (coFitPeaks.size() > 2) ? 30.0 : 150.0;
15171526
#endif
15181527

15191528
#if( PRINT_VERBOSE_PEAK_FIT_LM_INFO )
@@ -1546,18 +1555,48 @@ vector<shared_ptr<const PeakDef>> fit_peaks_in_roi_LM( const vector<shared_ptr<c
15461555
std::cout << summary.FullReport() << "\n";
15471556
cout << "Took " << cost_functor->m_ncalls.load() << " calls to solve." << endl;
15481557
#endif
1549-
1558+
15501559
switch( summary.termination_type )
15511560
{
15521561
case ceres::CONVERGENCE:
15531562
case ceres::USER_SUCCESS:
15541563
break;
15551564

15561565
case ceres::NO_CONVERGENCE:
1566+
{
15571567
#if( PRINT_VERBOSE_PEAK_FIT_LM_INFO )
15581568
cerr << "The L-M ceres::Solver solving failed - NO_CONVERGENCE:\n" << summary.FullReport() << endl;
15591569
#endif
1570+
// We will give it another go - for most cases it seems the solution will now be succesffuly found really
1571+
// quickly. The guess is this is from momentum, or whatever, but not really sure.
1572+
//cerr << "Initial L-M ceres::Solver failed with " << cost_functor->m_ncalls.load() << " calls and "
1573+
// << summary.num_successful_steps << " steps - will try again" << endl;
1574+
1575+
options.max_num_iterations = 5000;
1576+
// TODO: see if we should loosed any of the following up.
1577+
//options.function_tolerance = 1e-6;
1578+
//options.parameter_tolerance = 1e-9;
1579+
//options.initial_trust_region_radius = 35*(cost_functor->number_parameters() - prob_setup.m_constant_parameters.size());
1580+
cost_functor->m_ncalls = 0;
1581+
1582+
summary = ceres::Solver::Summary();
1583+
1584+
ceres::Solve(options, &problem, &summary);
1585+
1586+
if( (summary.termination_type == ceres::CONVERGENCE)
1587+
|| (summary.termination_type == ceres::USER_SUCCESS) )
1588+
{
1589+
//cerr << "Retry of L-M ceres::Solver worked with "
1590+
//<< cost_functor->m_ncalls.load() << " fcn additional calls in "
1591+
//<< summary.num_successful_steps << " succesfull steps"
1592+
//<< endl;
1593+
break;
1594+
}
1595+
1596+
cerr << "Retry of L-M ceres::Solver Failed with " << cost_functor->m_ncalls.load() << " additional calls" << endl;
1597+
15601598
throw runtime_error( "The L-M ceres::Solver solving failed - NO_CONVERGENCE." );
1599+
}
15611600

15621601
case ceres::FAILURE:
15631602
#if( PRINT_VERBOSE_PEAK_FIT_LM_INFO )

0 commit comments

Comments
 (0)