diff --git a/InterSpec/DetectionLimitSimple.h b/InterSpec/DetectionLimitSimple.h
index f0500d35..a6802a20 100644
--- a/InterSpec/DetectionLimitSimple.h
+++ b/InterSpec/DetectionLimitSimple.h
@@ -156,6 +156,8 @@ class DetectionLimitSimple : public Wt::WContainerWidget
void handleFitFwhmRequested();
+ void handleSelectDetectorRequested();
+
void handleSpectrumChanged();
void handleUserChangedRoi();
@@ -250,6 +252,7 @@ class DetectionLimitSimple : public Wt::WContainerWidget
NativeFloatSpinBox *m_fwhm;
Wt::WText *m_fwhmSuggestTxt;
Wt::WPushButton *m_addFwhmBtn;
+ Wt::WPushButton *m_selectDetectorBtn;
Wt::WLabel *m_continuumPriorLabel;
Wt::WComboBox *m_continuumPrior;
diff --git a/InterSpec_resources/app_text/DetectionLimitSimple.xml b/InterSpec_resources/app_text/DetectionLimitSimple.xml
index 27bbab3b..bcca056e 100644
--- a/InterSpec_resources/app_text/DetectionLimitSimple.xml
+++ b/InterSpec_resources/app_text/DetectionLimitSimple.xml
@@ -3,6 +3,7 @@
Fit FWHM...
+ Select detector...
further details...
Confidence Level:
ROI Lower:
@@ -57,7 +58,21 @@
Limit
Cont. Area
DOF
-
+ Upper
+ Lower
+ Best
+ ROI Range (keV)
+ ROI Channels
+ ROI Width
+ Det. Intrinsic Eff.
+ Solid angle frac.
+ Air transmission
+ Gamma Intensity
+ Error computing limit...
+ Error computing limit information: {1}
+ Please select a detector efficiency function.
+ Distance can't be negative.
+ Detector efficiency function does not have FWHM info - please fit for FWHM, or change detector.
diff --git a/src/DetectionLimitSimple.cpp b/src/DetectionLimitSimple.cpp
index fd8881fb..b161276f 100644
--- a/src/DetectionLimitSimple.cpp
+++ b/src/DetectionLimitSimple.cpp
@@ -210,6 +210,7 @@ DetectionLimitSimple::DetectionLimitSimple( MaterialDB *materialDB,
m_fwhm( nullptr ),
m_fwhmSuggestTxt( nullptr ),
m_addFwhmBtn( nullptr ),
+ m_selectDetectorBtn( nullptr ),
m_continuumPriorLabel( nullptr ),
m_continuumPrior( nullptr ),
m_continuumTypeLabel( nullptr ),
@@ -450,10 +451,18 @@ void DetectionLimitSimple::init()
m_fwhmSuggestTxt = new WText( generalInput );
m_fwhmSuggestTxt->addStyleClass( "FwhmSuggest GridThirdCol GridSixthRow GridVertCenter GridSpanTwoCol" );
+
m_addFwhmBtn = new WPushButton( WString::tr("dls-fit-fwhm-btn"), generalInput );
m_addFwhmBtn->clicked().connect( this, &DetectionLimitSimple::handleFitFwhmRequested );
m_addFwhmBtn->addStyleClass( "MdaFitFwhm LightButton GridFifthCol GridSixthRow" );
+ m_selectDetectorBtn = new WPushButton( WString::tr("dls-select-drf-btn"), generalInput );
+ m_selectDetectorBtn->clicked().connect( this, &DetectionLimitSimple::handleSelectDetectorRequested );
+ m_selectDetectorBtn->addStyleClass( "MdaFitFwhm LightButton GridFifthCol GridSixthRow" );
+
+ const shared_ptr drf = m_detectorDisplay->detector();
+ m_addFwhmBtn->setHidden( !drf || !drf->isValid() || drf->hasResolutionInfo() );
+ m_selectDetectorBtn->setHidden( drf && drf->isValid() );
m_continuumPriorLabel = new WLabel( WString::tr("dls-deon-cont-norm-label"), generalInput );
m_continuumPriorLabel->addStyleClass( "GridFirstCol GridSeventhRow GridVertCenter" );
@@ -631,13 +640,15 @@ void DetectionLimitSimple::setFwhmFromEstimate()
float fwhm = 0.1f;
const shared_ptr drf = m_detectorDisplay->detector();
+
+ m_addFwhmBtn->setHidden( !drf || !drf->isValid() || drf->hasResolutionInfo() );
+ m_selectDetectorBtn->setHidden( drf && drf->isValid() );
+
if( drf && drf->hasResolutionInfo() )
{
- m_addFwhmBtn->hide();
fwhm = drf->peakResolutionFWHM( energy );
}else
{
- m_addFwhmBtn->show();
fwhm = std::max( 0.1f, PeakSearchGuiUtils::estimate_FWHM_of_foreground(energy) );
}
@@ -665,11 +676,11 @@ void DetectionLimitSimple::handleUserChangedFwhm()
m_fwhm->setValue( fwhm );
}//if( invalid FWHM )
+ m_addFwhmBtn->setHidden( !drf || !drf->isValid() || drf->hasResolutionInfo() );
+ m_selectDetectorBtn->setHidden( drf && drf->isValid() );
if( drf && drf->hasResolutionInfo() )
{
- m_addFwhmBtn->hide();
-
const double drf_fwhm = drf->peakResolutionFWHM( energy );
if( fabs(fwhm - drf_fwhm) > 0.1 )
{
@@ -683,7 +694,6 @@ void DetectionLimitSimple::handleUserChangedFwhm()
}
}else
{
- m_addFwhmBtn->show();
const float est_fwhm = std::max( 0.1f, PeakSearchGuiUtils::estimate_FWHM_of_foreground(energy) );
char text[32] = { '\0' };
@@ -1084,6 +1094,9 @@ void DetectionLimitSimple::handleDetectorChanged( std::shared_ptrsetDetector( new_drf );
+ m_addFwhmBtn->setHidden( !new_drf || !new_drf->isValid() || new_drf->hasResolutionInfo() );
+ m_selectDetectorBtn->setHidden( new_drf && new_drf->isValid() );
+
handleUserChangedFwhm();
m_renderFlags |= DetectionLimitSimple::RenderActions::UpdateLimit;
@@ -1102,6 +1115,12 @@ void DetectionLimitSimple::handleFitFwhmRequested()
}//void handleFitFwhmRequested()
+void DetectionLimitSimple::handleSelectDetectorRequested()
+{
+ m_detectorDisplay->editDetector();
+}//void handleSelectDetectorRequested()
+
+
void DetectionLimitSimple::handleSpectrumChanged()
{
m_renderFlags |= DetectionLimitSimple::RenderActions::UpdateLimit;
@@ -1578,13 +1597,10 @@ SimpleDialog *DetectionLimitSimple::createDeconvolutionLimitMoreInfo()
WTable *table = new WTable( contents );
table->addStyleClass( "DeconvoMoreInfoTable" );
-
-
-
const auto print_result = [table, use_curie, measurement, roi_start, roi_end](
const DetectionLimitCalc::DeconComputeResults &result,
const bool is_best, const WString typestr ){
- WString label = WString("{1} {2}").arg(typestr).arg( WString::tr("dls-Limit") );
+ WString label = WString("{1} {2}").arg(typestr).arg( WString::tr( (is_best ? "Activity" : "dls-Limit") ) );
WString value = PhysicalUnits::printToBestActivityUnits( result.input.activity, 3, use_curie );
WTableCell *cell = table->elementAt( table->rowCount(), 0 );
@@ -1593,7 +1609,7 @@ SimpleDialog *DetectionLimitSimple::createDeconvolutionLimitMoreInfo()
new WText( value, cell );
- label = WString("{1} {2}").arg(typestr).arg( WString::tr("dls-Limit") );
+ label = WString("{1} {2}").arg(typestr).arg( WString::tr( (is_best ? "Counts" : "dls-Limit") ) );
double counts = 0.0, uncert = 0.0;
for( const auto peak : result.fit_peaks )
{
@@ -1762,6 +1778,8 @@ SimpleDialog *DetectionLimitSimple::createDeconvolutionLimitMoreInfo()
// " source before any shielding, but accounting for nuclide age,"
// " per decay of the parent nuclide." );
}//if( branch_ratio > 0.0 )
+
+ return dialog;
}//void createDeconvolutionLimitMoreInfo()
diff --git a/src/DetectionLimitTool.cpp b/src/DetectionLimitTool.cpp
index 42b33590..c0a5b75d 100644
--- a/src/DetectionLimitTool.cpp
+++ b/src/DetectionLimitTool.cpp
@@ -2045,6 +2045,51 @@ SimpleDialog *DetectionLimitTool::createCurrieRoiMoreInfoWindow( const SandiaDec
" expected to lead to detection." );
+ switch( limitType )
+ {
+ case DetectionLimitTool::LimitType::Activity:
+ {
+ if( result.source_counts <= result.decision_threshold )
+ {
+ // There is NOT enough excess counts that we would reliably detect this activity, so we
+ // didnt give nominal activity above, so we'll do that here
+ WString obs_label;
+ string lowerstr, upperstr, nomstr;
+ if( drf && (distance >= 0.0) && (gammas_per_bq > 0.0) )
+ {
+ obs_label = "Activity";
+ const float nominal_act = result.source_counts / gammas_per_bq;
+
+ nomstr = PhysicalUnits::printToBestActivityUnits( nominal_act, 2, useCuries )
+ + DetectorPeakResponse::det_eff_geom_type_postfix( det_geom );
+ if( nominal_act < 0 )
+ nomstr = "< " + PhysicalUnits::printToBestActivityUnits( 0.0, 2, useCuries )
+ + DetectorPeakResponse::det_eff_geom_type_postfix( det_geom );
+ }else
+ {
+ obs_label = "Observed counts";
+ nomstr = SpecUtils::printCompact(result.source_counts, 4);
+
+ if( result.source_counts < 0 )
+ nomstr = "< 0 counts";
+ }//if( drf ) / else
+
+ nomstr += " (below Lc)";
+
+ cell = table->elementAt( table->rowCount(), 0 );
+ new WText( obs_label, cell );
+ cell = table->elementAt( table->rowCount() - 1, 1 );
+ new WText( nomstr, cell );
+ addTooltipToRow( "The observed signal counts is less than the "critical level", Lc,"
+ " so a detection can not be declared, but this is the excess over expected counts/activity." );
+ }//if( result.source_counts <= result.decision_threshold )
+ }//case DetectionLimitTool::LimitType::Activity:
+
+ case DetectionLimitTool::LimitType::Distance:
+ break;
+ }//switch( limitType )
+
+
// Add a blank row
cell = table->elementAt( table->rowCount(), 0 );
txt = new WText( " ", TextFormat::XHTMLText, cell );
diff --git a/src/PeakSearchGuiUtils.cpp b/src/PeakSearchGuiUtils.cpp
index cd3b0010..933e63e1 100644
--- a/src/PeakSearchGuiUtils.cpp
+++ b/src/PeakSearchGuiUtils.cpp
@@ -3131,7 +3131,7 @@ std::pair,int> reference_line_near_peak( Inte
const double dist = fabs( l.m_energy - mean );
const double w = l.m_normalized_intensity / (0.25*sigma + dist);
- if( (w > largest_w) && (l.m_energy < ux) && (l.m_energy > lx) && (dist < 4*sigma) )
+ if( (w > largest_w) && (l.m_energy < ux) && (l.m_energy > lx) && (dist < 5*sigma) )
{
largest_w = w;
best_energy = l.m_energy;
@@ -3183,8 +3183,30 @@ float reference_line_energy_near_peak( InterSpec * const interspec, const PeakDe
tuple
nuclide_reference_line_near( InterSpec *viewer, const float energy )
{
- const double sigma = estimate_FWHM_of_foreground( energy );
-
+ double sigma = estimate_FWHM_of_foreground( energy );
+
+ // For HPGe zoomed out, its really hard to be within the 5-peak-sigmas of the reference
+ // line that `reference_line_near_peak(...)` requires, so we'll also take into account
+ // the number of pixels a peak would show up as.
+ // Note: `SpectrumChartD3.prototype.updateMouseCoordText(...)` basically requires within 10px
+ const shared_ptr hist
+ = viewer->displayedHistogram(SpecUtils::SpectrumType::Foreground);
+ if( PeakFitUtils::is_high_res(hist) )
+ {
+ double xmin, xmax, ymin, ymax;
+ viewer->displayedSpectrumRange( xmin, xmax, ymin, ymax );
+
+ const int ww = viewer->renderedWidth();
+
+ if( (xmin < xmax) && ((xmax - xmin) > 50.0) && (ww > 200) )
+ {
+ // Will assume chart plot-area is 100px narrower than total window (unchecked).
+ const double keV_per_pixel = (xmax - xmin) / (ww - 100);
+ // set peak-sigma to be 2 pixels, giving us to require 10 pixels of accuracy from the user
+ sigma = std::max( sigma, 2.0*keV_per_pixel );
+ }//if( x-range and render size seem reasonable )
+ }//if( PeakFitUtils::is_high_res(hist) )
+
PeakDef tmppeak( energy, std::max(sigma,0.1), 100.0 );
const pair,int> refline