Skip to content

Commit 158923f

Browse files
committed
Moved y-axis range checking logic to D3SpectrumDisplayDiv, and also added a explanatory message when setYRange(...) call, from terminal widget, isnt fully obeyed.
In response to issue #33.
1 parent e44b99d commit 158923f

File tree

7 files changed

+115
-94
lines changed

7 files changed

+115
-94
lines changed

InterSpec/D3SpectrumDisplayDiv.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "InterSpec_config.h"
55

66
#include <map>
7+
#include <tuple>
78
#include <chrono>
89
#include <memory>
910
#include <vector>
@@ -324,7 +325,13 @@ class D3SpectrumDisplayDiv : public Wt::WContainerWidget
324325

325326
void setYAxisMinimum( const double minimum );
326327
void setYAxisMaximum( const double maximum );
327-
void setYAxisRange( const double minimum, const double maximum );
328+
329+
/** Set the y-axis range.
330+
331+
Returns the actual set y-range, and if this is different than the requested range, a message as to why it couldnt be set
332+
(e.x., a value less than or equal to 0 was requested for a log axis).
333+
*/
334+
std::tuple<double,double,Wt::WString> setYAxisRange( double minimum, double maximum );
328335

329336
//peakLabel should be of type SpectrumChart::PeakLabels, but I didnt want
330337
// to include the SpectrumChart header for just this

InterSpec/InterSpec.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,20 @@
2727

2828
#include <set>
2929
#include <deque>
30+
#include <tuple>
3031
#include <memory>
3132
#include <vector>
3233

3334
#include <Wt/Dbo/Dbo>
3435
#include <Wt/WContainerWidget>
3536

36-
//#include "SpecUtils/SpecFile.h"
37-
//Without including InterSpecUser.h here, we get some wierd issues with the
38-
// DB optomistic versioning...
37+
//Without including InterSpecUser.h here, we get some weird issues with the
38+
// DB optimistic versioning...
3939
#include "InterSpec/InterSpecUser.h"
4040

4141
class PeakDef;
4242
class PopupDiv;
43+
class SpecMeas;
4344
class AuxWindow;
4445
class GoogleMap;
4546
class PeakModel;
@@ -591,10 +592,10 @@ class InterSpec : public Wt::WContainerWidget
591592

592593
/** Sets the Y-axis range.
593594
594-
Returns true if successful, or false if the request couldnt be fully honored
595+
Returns set range, and empty string if successful, or otherwise a message explaining why the request couldnt be fully honored
595596
(e.g., a negative lower counts was specified, but its currently log-scale)
596597
*/
597-
bool setYAxisRange( double lower_counts, double upper_counts );
598+
std::tuple<double,double,Wt::WString> setYAxisRange( double lower_counts, double upper_counts );
598599

599600
/** When displaying the spectrum in log-y, sets the lower y-axis value to show, if there are channels with zero counts. */
600601
bool setLogYAxisMin( const double lower_value );

InterSpec/InterSpecUser.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ namespace Wt
7878
// to avoid "Stale object" exceptions when the same user has multiple
7979
// sessions of the app open. A related issue not dealt with is that
8080
// one session will overwrite whats saved in another one, and stuff wont be
81-
// propogated between them
81+
// propagated between them
8282
template<>
8383
struct dbo_traits<UserOption> : public dbo_default_traits
8484
{

InterSpec_resources/app_text/D3SpectrumDisplayDiv.xml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,10 @@
4141
<message id="d3sdd-recalFromTo">Recalibrate data from {1} to {2} keV</message>
4242
<message id="d3sdd-sumFromTo">{1} to {2} keV</message>
4343
<message id="d3sdd-comptonPeakAngle">{1}° Compton Peak</message>
44-
</messages>
44+
45+
<message id="d3sdd-yaxis-lower-upper-equal">Lower and upper counts equal.</message>
46+
<message id="d3sdd-yaxis-no-spectrum">No spectrum displayed.</message>
47+
<message id="d3sdd-yaxis-upper-counts-below-zero">Upper range equal or below zero.</message>
48+
<message id="d3sdd-yaxis-lower-counts-below-zero">Lower range equal or below zero.</message>
49+
<message id="d3sdd-yaxis-below-min-non-zero">Upper range less than minimum displayed, non-zero value.</message>
50+
</messages>

src/D3SpectrumDisplayDiv.cpp

Lines changed: 84 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -996,19 +996,97 @@ void D3SpectrumDisplayDiv::setXAxisRange( const double minimum, const double max
996996
}//void setXAxisRange( const double minimum, const double maximum );
997997

998998

999-
void D3SpectrumDisplayDiv::setYAxisRange( const double minimum,
1000-
const double maximum )
999+
std::tuple<double,double,Wt::WString> D3SpectrumDisplayDiv::setYAxisRange( double lower_counts,
1000+
double upper_counts )
10011001
{
1002-
const string minimumStr = SpecUtils::printCompact(minimum, 8);
1003-
const string maximumStr = SpecUtils::printCompact(maximum, 8);
1004-
m_yAxisMinimum = minimum;
1005-
m_yAxisMaximum = maximum;
1002+
if( upper_counts < lower_counts )
1003+
std::swap( lower_counts, upper_counts );
1004+
1005+
if( upper_counts == lower_counts )
1006+
return {m_yAxisMinimum, m_yAxisMaximum, WString::tr("d3sdd-yaxis-lower-upper-equal")};
1007+
1008+
WString errmsg;
1009+
const bool isLogY = yAxisIsLog();
1010+
if( isLogY )
1011+
{
1012+
const auto hist = m_foreground;
1013+
if( !hist || !hist->gamma_counts() || (hist->gamma_counts()->size() < 2) )
1014+
return {m_yAxisMinimum, m_yAxisMaximum, WString::tr("d3sdd-yaxis-no-spectrum")};
1015+
1016+
const shared_ptr<const vector<float>> &channels = hist->gamma_counts();
1017+
assert( channels );
1018+
1019+
// Lets check the y-range - ignoring we may be showing multiple channels per display-bin,
1020+
// to see if the requested range is reasonable
1021+
double xmin, xmax, ymin, ymax;
1022+
visibleRange( xmin, xmax, ymin, ymax );
1023+
1024+
const size_t lower_channel = hist->find_gamma_channel(xmin);
1025+
const size_t upper_channel = hist->find_gamma_channel(xmax);
1026+
float min_nonzero_value = std::numeric_limits<float>::max();
1027+
float max_value = -std::numeric_limits<float>::max();
1028+
1029+
for( size_t channel = lower_channel; channel <= upper_channel; ++channel )
1030+
{
1031+
if( channel < channels->size() )
1032+
{
1033+
const float val = (*channels)[channel];
1034+
max_value = std::max( max_value, val );
1035+
if( val > 0.0f )
1036+
min_nonzero_value = std::min( min_nonzero_value, val );
1037+
}//if( channel < channels->size() )
1038+
}//for( loop over visible channels )
1039+
1040+
if( (max_value <= 0.0f) || IsInf(max_value) || IsNan(max_value) )
1041+
max_value = 1.0f;
1042+
1043+
if( (min_nonzero_value == std::numeric_limits<float>::max())
1044+
|| IsInf(min_nonzero_value)
1045+
|| IsNan(min_nonzero_value) )
1046+
{
1047+
min_nonzero_value = 0.1f*max_value;
1048+
}
1049+
1050+
if( upper_counts <= 0.0f )
1051+
{
1052+
errmsg = WString::tr("d3sdd-yaxis-upper-counts-below-zero");
1053+
upper_counts = (max_value > 0.0f) ? 2.0f*max_value : 1.0f;
1054+
}
1055+
1056+
if( upper_counts <= min_nonzero_value )
1057+
{
1058+
errmsg = WString::tr("d3sdd-yaxis-below-min-non-zero");
1059+
upper_counts = 2.0f*min_nonzero_value;
1060+
}
1061+
1062+
if( (lower_counts <= 0.0) || (lower_counts > max_value) )
1063+
{
1064+
errmsg = WString::tr("d3sdd-yaxis-lower-counts-below-zero");
1065+
lower_counts = min_nonzero_value;
1066+
}
1067+
}//if( isLogY && (lower_counts <= 0.0f) )
1068+
1069+
1070+
if( isLogY )
1071+
{
1072+
const double prevMinLogY = logYAxisMin();
1073+
if( lower_counts < prevMinLogY )
1074+
setLogYAxisMin( lower_counts );
1075+
}//if( isLogY )
1076+
1077+
1078+
const string minimumStr = SpecUtils::printCompact(lower_counts, 8);
1079+
const string maximumStr = SpecUtils::printCompact(upper_counts, 8);
1080+
m_yAxisMinimum = lower_counts;
1081+
m_yAxisMaximum = upper_counts;
10061082

10071083
string js = m_jsgraph + ".setYAxisRange(" + minimumStr + "," + maximumStr + ");";
10081084
if( isRendered() )
10091085
doJavaScript( js );
10101086
else
10111087
m_pendingJs.push_back( js );
1088+
1089+
return {m_yAxisMinimum, m_yAxisMaximum, errmsg};
10121090
}//void setYAxisRange( const double minimum, const double maximum );
10131091

10141092

src/InterSpec.cpp

Lines changed: 2 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -12237,83 +12237,9 @@ void InterSpec::setDisplayedEnergyRange( float lowerEnergy, float upperEnergy )
1223712237
}//void setDisplayedEnergyRange()
1223812238

1223912239

12240-
bool InterSpec::setYAxisRange( double lower_counts, double upper_counts )
12240+
tuple<double,double,Wt::WString> InterSpec::setYAxisRange( double lower_counts, double upper_counts )
1224112241
{
12242-
bool success = true;
12243-
if( upper_counts < lower_counts )
12244-
std::swap( lower_counts, upper_counts );
12245-
12246-
if( upper_counts == lower_counts )
12247-
return false;
12248-
12249-
const bool isLogY = m_spectrum->yAxisIsLog();
12250-
if( isLogY )
12251-
{
12252-
const auto hist = displayedHistogram(SpecUtils::SpectrumType::Foreground);
12253-
if( !hist || !hist->gamma_counts() || (hist->gamma_counts()->size() < 2) )
12254-
return false;
12255-
12256-
const shared_ptr<const vector<float>> &channels = hist->gamma_counts();
12257-
assert( channels );
12258-
12259-
// Lets check the y-range - ignoring we may be showing multiple channels per display-bin,
12260-
// to see if the requested range is reasonable
12261-
double xmin, xmax, ymin, ymax;
12262-
m_spectrum->visibleRange( xmin, xmax, ymin, ymax );
12263-
12264-
const size_t lower_channel = hist->find_gamma_channel(xmin);
12265-
const size_t upper_channel = hist->find_gamma_channel(xmax);
12266-
float min_nonzero_value = std::numeric_limits<float>::max();
12267-
float max_value = -std::numeric_limits<float>::max();
12268-
12269-
for( size_t channel = lower_channel; channel <= upper_channel; ++channel )
12270-
{
12271-
if( channel < channels->size() )
12272-
{
12273-
const float val = (*channels)[channel];
12274-
max_value = std::max( max_value, val );
12275-
if( val > 0.0f )
12276-
min_nonzero_value = std::min( min_nonzero_value, val );
12277-
}//if( channel < channels->size() )
12278-
}//for( loop over visible channels )
12279-
12280-
if( (max_value <= 0.0f) || IsInf(max_value) || IsNan(max_value) )
12281-
max_value = 1.0f;
12282-
12283-
if( (min_nonzero_value == std::numeric_limits<float>::max())
12284-
|| IsInf(min_nonzero_value)
12285-
|| IsNan(min_nonzero_value) )
12286-
{
12287-
min_nonzero_value = 0.1f*max_value;
12288-
}
12289-
12290-
if( upper_counts <= 0.0f )
12291-
{
12292-
success = false;
12293-
upper_counts = (max_value > 0.0f) ? 2.0f*max_value : 1.0f;
12294-
}
12295-
12296-
if( upper_counts <= min_nonzero_value )
12297-
{
12298-
success = false;
12299-
upper_counts = 2.0f*min_nonzero_value;
12300-
}
12301-
12302-
if( (lower_counts <= 0.0) || (lower_counts > max_value) )
12303-
lower_counts = min_nonzero_value;
12304-
}//if( isLogY && (lower_counts <= 0.0f) )
12305-
12306-
12307-
if( isLogY )
12308-
{
12309-
const double prevMinLogY = m_spectrum->logYAxisMin();
12310-
if( lower_counts < prevMinLogY )
12311-
m_spectrum->setLogYAxisMin( lower_counts );
12312-
}//if( isLogY )
12313-
12314-
m_spectrum->setYAxisRange( lower_counts, upper_counts );
12315-
12316-
return success;
12242+
return m_spectrum->setYAxisRange( lower_counts, upper_counts );
1231712243
}//bool setYAxisRange(...)
1231812244

1231912245

src/TerminalModel.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "InterSpec_config.h"
3535

3636
#include <regex>
37+
#include <tuple>
3738
#include <vector>
3839
#include <memory>
3940
#include <stdio.h>
@@ -1914,12 +1915,14 @@ std::string TerminalModel::setYRange( const std::string& arguments )
19141915
// throw mup::ParserError( "Invalid arguments for function (setYRange). Lower and upper bound"
19151916
// " must not have difference less than or equal to 0.01." );
19161917

1917-
const bool success = m_viewer->setYAxisRange(lower, upper);
1918+
const std::tuple<double,double,Wt::WString> result = m_viewer->setYAxisRange(lower, upper);
19181919

1919-
if( success )
1920-
os << "Now setting count range to [" << lower << ", " << upper << "] counts.";
1920+
if( std::get<2>(result).empty() )
1921+
os << "Setting y-range to [" << lower << ", " << upper << "].";
19211922
else
1922-
os << "Setting to count range [" << lower << ", " << upper << "] not fully be fulfilled.";
1923+
os << "Setting y-range to [" << lower << ", " << upper << "] not fully be fulfilled; set to ["
1924+
<< std::get<0>(result) << ", " << std::get<1>(result) << "]: "
1925+
<< std::get<2>(result).toUTF8();
19231926
} catch ( const mup::ParserError& e ) {
19241927
os << "Error code " << e.GetCode() << ": " << e.GetMsg();
19251928

0 commit comments

Comments
 (0)