Unverified Commit d883d9e5 authored by Gagik Vardanyan's avatar Gagik Vardanyan Committed by GitHub
Browse files

Merge pull request #28792 from mantidproject/28788_instrument_view_negative_values

Instrument view handle invalid values better
parents 8fbcb579 90b401f5
......@@ -43,6 +43,8 @@ Improvements
- We have neatened up the the slice viewer user interface, to reduce the amount of wasted space and devote more to the data view itself.
- Surface plots no longer spill over the axes when their limits are reduced.
- The instrument view now ignores non-finite (infinity and NaN) values and should now display workspaces containing those values.
If there are no valid values for that detector the value will appear as invalid (grayed out).
It can also now display negative values in workspaces correctly.
- The gray and plasma colormaps have been added to the instrument view.
- Slow running algorithms will now display an estimated time to completion in their progress bars.
- The x-axis tick labels on colorfill plots are now horizontal.
......@@ -67,7 +69,7 @@ Bugfixes
- Fixed the default axis scale settings applying to the wrong axis.
- Performing an overplot by dragging workspaces onto colorfill plots now correctly replaces the workspace.
- Removed gridlines from the colorbar on colorfill plots.
- The Instrument View now passes through useful error messages to the workbench if it fails to start, for example if your data contains NaN or infinite values.
- The Instrument View now passes through useful error messages to the workbench if it fails to start.
- The correct interpolation now appears in the plot figure options for colorfill plots.
- Changing the axis scale on a colourfill plot now has the same result if it is done from either the context menu or figure options.
- `plt.show()` now shows the most recently created figure.
......
......@@ -18,6 +18,7 @@
#include <QObject>
#include <limits>
#include <memory>
#include <vector>
......@@ -57,7 +58,10 @@ class EXPORT_OPT_MANTIDQT_INSTRUMENTVIEW InstrumentActor : public QObject {
Q_OBJECT
public:
/// Invalid workspace index in detector index to workspace index lookup
static const size_t INVALID_INDEX;
static constexpr size_t INVALID_INDEX = std::numeric_limits<size_t>::max();
/// Value that indicates this pixel data is invalid
static constexpr double INVALID_VALUE = -std::numeric_limits<double>::max();
/// Constructor
InstrumentActor(const QString &wsName, bool autoscaling = true,
double scaleMin = 0.0, double scaleMax = 0.0);
......@@ -214,6 +218,8 @@ signals:
void colorMapChanged() const;
private:
static constexpr double TOLERANCE = 0.00001;
void setUpWorkspace(const std::shared_ptr<const Mantid::API::MatrixWorkspace>
&sharedWorkspace,
double scaleMin, double scaleMax);
......@@ -273,9 +279,6 @@ private:
/// Colors in order of component info
std::vector<size_t> m_monitors;
std::vector<size_t> m_components;
static double m_tolerance;
std::vector<bool> m_isCompVisible;
std::vector<size_t> m_detIndex2WsIndex;
......
......@@ -36,7 +36,6 @@
#include <QMessageBox>
#include <QSettings>
#include <limits>
#include <numeric>
#include <utility>
......@@ -57,10 +56,6 @@ bool isPhysicalView() {
} // namespace
const size_t InstrumentActor::INVALID_INDEX =
std::numeric_limits<size_t>::max();
double InstrumentActor::m_tolerance = 0.00001;
/**
* Constructor. Creates a tree of GLActors. Each actor is responsible for
* displaying insrument components in 3D.
......@@ -436,7 +431,7 @@ void InstrumentActor::setIntegrationRange(const double &xmin,
double InstrumentActor::getIntegratedCounts(size_t index) const {
auto i = getWorkspaceIndex(index);
if (i == INVALID_INDEX)
return -1.0;
return InstrumentActor::INVALID_VALUE;
return m_specIntegrs.at(i);
}
......@@ -850,21 +845,21 @@ void InstrumentActor::BasisRotation(const Mantid::Kernel::V3D &Xfrom,
// std::cerr<<"To "<<Xto<<Yto<<Zto<<'\n';
double sZ = Zfrom.scalar_prod(Zto);
if (fabs(sZ - 1) < m_tolerance) // vectors the same
if (fabs(sZ - 1) < TOLERANCE) // vectors the same
{
double sX = Xfrom.scalar_prod(Xto);
if (fabs(sX - 1) < m_tolerance) {
if (fabs(sX - 1) < TOLERANCE) {
R = Mantid::Kernel::Quat();
} else if (fabs(sX + 1) < m_tolerance) {
} else if (fabs(sX + 1) < TOLERANCE) {
R = Mantid::Kernel::Quat(180, Zfrom);
} else {
R = Mantid::Kernel::Quat(Xfrom, Xto);
}
} else if (fabs(sZ + 1) < m_tolerance) // rotated by 180 degrees
} else if (fabs(sZ + 1) < TOLERANCE) // rotated by 180 degrees
{
if (fabs(Xfrom.scalar_prod(Xto) - 1) < m_tolerance) {
if (fabs(Xfrom.scalar_prod(Xto) - 1) < TOLERANCE) {
R = Mantid::Kernel::Quat(180., Xfrom);
} else if (fabs(Yfrom.scalar_prod(Yto) - 1) < m_tolerance) {
} else if (fabs(Yfrom.scalar_prod(Yto) - 1) < TOLERANCE) {
R = Mantid::Kernel::Quat(180., Yfrom);
} else {
R = Mantid::Kernel::Quat(180., Xto) * Mantid::Kernel::Quat(Xfrom, Xto);
......@@ -876,15 +871,15 @@ void InstrumentActor::BasisRotation(const Mantid::Kernel::V3D &Xfrom,
const auto X1 = normalize(Zfrom.cross_prod(Zto));
double sX = Xfrom.scalar_prod(Xto);
if (fabs(sX - 1) < m_tolerance) {
if (fabs(sX - 1) < TOLERANCE) {
R = Mantid::Kernel::Quat(Zfrom, Zto);
return;
}
sX = Xfrom.scalar_prod(X1);
if (fabs(sX - 1) < m_tolerance) {
if (fabs(sX - 1) < TOLERANCE) {
R1 = Mantid::Kernel::Quat();
} else if (fabs(sX + 1) < m_tolerance) // 180 degree rotation
} else if (fabs(sX + 1) < TOLERANCE) // 180 degree rotation
{
R1 = Mantid::Kernel::Quat(180., Zfrom);
} else {
......@@ -901,9 +896,9 @@ void InstrumentActor::BasisRotation(const Mantid::Kernel::V3D &Xfrom,
// Rotation R3 around ZZ by gamma
Mantid::Kernel::Quat R3;
sX = Xto.scalar_prod(X1);
if (fabs(sX - 1) < m_tolerance) {
if (fabs(sX - 1) < TOLERANCE) {
R3 = Mantid::Kernel::Quat();
} else if (fabs(sX + 1) < m_tolerance) // 180 degree rotation
} else if (fabs(sX + 1) < TOLERANCE) // 180 degree rotation
{
R3 = Mantid::Kernel::Quat(180., Zto);
} else {
......@@ -1017,6 +1012,11 @@ void InstrumentActor::calculateIntegratedSpectra(
// Use the workspace function to get the integrated spectra
workspace.getIntegratedSpectra(m_specIntegrs, m_BinMinValue, m_BinMaxValue,
wholeRange());
// replace any values that are not finite
std::replace_if(m_specIntegrs.begin(), m_specIntegrs.end(),
[](double x) { return !std::isfinite(x); },
InstrumentActor::INVALID_VALUE);
m_maskBinsData.subtractIntegratedSpectra(workspace, m_specIntegrs);
}
......@@ -1050,17 +1050,9 @@ void InstrumentActor::setDataIntegrationRange(const double &xmin,
m_DataMinValue = DBL_MAX;
m_DataMaxValue = -DBL_MAX;
if (std::any_of(m_specIntegrs.begin(), m_specIntegrs.end(),
[](double val) { return !std::isfinite(val); }))
throw std::runtime_error(
"The workspace contains values that cannot be displayed (infinite "
"or NaN).\n"
"Please run ReplaceSpecialValues algorithm for correction.");
const auto &spectrumInfo = workspace->spectrumInfo();
// Ignore monitors if multiple detectors aren't grouped.
// PARALLEL_FOR_NO_WSP_CHECK()
for (size_t i = 0; i < m_specIntegrs.size(); i++) {
const auto &spectrumDefinition = spectrumInfo.spectrumDefinition(i);
if (spectrumDefinition.size() == 1 &&
......@@ -1070,6 +1062,8 @@ void InstrumentActor::setDataIntegrationRange(const double &xmin,
auto sum = m_specIntegrs[i];
if (sum == InstrumentActor::INVALID_VALUE)
continue;
if (sum < m_DataMinValue)
m_DataMinValue = sum;
if (sum > m_DataMaxValue)
......
......@@ -366,13 +366,14 @@ void InstrumentRenderer::resetColors() {
for (size_t det = 0; det < counts.size(); ++det) {
if (!isMasked(det)) {
const double integratedValue(counts[det]);
if (integratedValue > -1) {
if (integratedValue == InstrumentActor::INVALID_VALUE) {
m_colors[det] = invalidColor;
} else {
const auto &color = rgba[det];
m_colors[det] =
GLColor(qRed(color), qGreen(color), qBlue(color),
static_cast<int>(255 * (integratedValue / vmax)));
} else
m_colors[det] = invalidColor;
}
} else {
m_colors[det] = maskedColor;
}
......
......@@ -933,8 +933,9 @@ QString ComponentInfoController::displayDetectorInfo(size_t index) {
QString::fromStdString(componentInfo.name(index)) + '\n';
const double integrated = actor.getIntegratedCounts(index);
const QString counts =
integrated == -1.0 ? "N/A" : QString::number(integrated);
const QString counts = integrated == InstrumentActor::INVALID_VALUE
? "N/A"
: QString::number(integrated);
text += "Counts: " + counts + '\n';
// display info about peak overlays
text += actor.getParameterInfo(index);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment