SampleTransmission.cpp 7.3 KB
Newer Older
1
2
3
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4
5
//   NScD Oak Ridge National Laboratory, European Spallation Source,
//   Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6
// SPDX - License - Identifier: GPL - 3.0 +
7
8
9
//----------------------
// Includes
//----------------------
Roman Tolchenov's avatar
Roman Tolchenov committed
10
#include "SampleTransmission.h"
11
12

#include "MantidAPI/AlgorithmManager.h"
Dan Nixon's avatar
Dan Nixon committed
13
#include "MantidKernel/Statistics.h"
Roman Tolchenov's avatar
Roman Tolchenov committed
14
#include "MantidQtWidgets/Common/HelpWindow.h"
15
#include "MantidQtWidgets/Common/UserInputValidator.h"
16

17
18
namespace {
Mantid::Kernel::Logger g_log("SampleTransmission");
19
20
}

21
22
23
24
// Add this class to the list of specialised dialogs in this namespace
namespace MantidQt {
namespace CustomInterfaces {
DECLARE_SUBWINDOW(SampleTransmission)
25
}
LamarMoore's avatar
LamarMoore committed
26
} // namespace MantidQt
27
28
29
30
31
32
33

using namespace MantidQt::CustomInterfaces;
using namespace Mantid::API;

//----------------------
// Public member functions
//----------------------
34
35
36
37
38
/// Constructor
SampleTransmission::SampleTransmission(QWidget *parent)
    : UserSubWindow(parent), m_algRunner(new API::AlgorithmRunner(this)) {
  connect(m_algRunner, SIGNAL(algorithmComplete(bool)), this,
          SLOT(algorithmComplete(bool)));
39
40
41
42
43
}

/**
 * Set up the dialog layout.
 */
44
void SampleTransmission::initLayout() {
45
  m_uiForm.setupUi(this);
46
  m_uiForm.ppTransmission->disableYAxisMenu();
47
  connect(m_uiForm.pbCalculate, SIGNAL(clicked()), this, SLOT(calculate()));
48
  connect(m_uiForm.pbHelp, SIGNAL(clicked()), this, SLOT(showHelp()));
49
50

  validate(true);
51
52
}

53
54
55
/**
 * Opens the Qt help page for the interface.
 */
56
57
void SampleTransmission::showHelp() {
  MantidQt::API::HelpWindow::showCustomInterface(
58
      nullptr, QString("Sample Transmission Calculator"), QString("general"));
59
60
}

61
62
63
64
/**
 * Validate user input.
 * Outputs any warnings to the results log at warning level.
 *
65
 * @param silent If the results should not be logged
66
67
 * @return Result of validation
 */
68
bool SampleTransmission::validate(bool silent) {
69
70
71
72
  UserInputValidator uiv;

  // Valudate input binning
  int wavelengthBinning = m_uiForm.cbBinningType->currentIndex();
73
74
75
76
77
78
79
80
81
82
83
84
  switch (wavelengthBinning) {
  // Single
  case 0:
    uiv.checkBins(m_uiForm.spSingleLow->value(),
                  m_uiForm.spSingleWidth->value(),
                  m_uiForm.spSingleHigh->value());
    break;

  // Multiple
  case 1:
    uiv.checkFieldIsNotEmpty("Multiple binning", m_uiForm.leMultiple,
                             m_uiForm.valMultiple);
85

86
87
88
89
    // Checks that the first number in the list is not negative.
    // Only the first number needs to be checked because if it isn't negative
    // then the rest can't be.
    // The Rebin algorithm takes care of the rest of the checks.
90
    if (m_uiForm.leMultiple->text().trimmed().at(0) == '-') {
91
92
93
94
      uiv.setErrorLabel(m_uiForm.valMultiple, false);
      uiv.addErrorMessage("Wavelength cannot be negative.");
    }

95
    break;
96
97
98
  }

  // Validate chemical formula
99
  uiv.checkFieldIsNotEmpty("Chemical Formula", m_uiForm.leChemicalFormula,
100
101
                           m_uiForm.valChemicalFormula);

102
  // Ensure number density is not zero
103
104
  uiv.setErrorLabel(m_uiForm.valDensity,
                    uiv.checkNotEqual("Density", m_uiForm.spDensity->value()));
105
106

  // Ensure thickness is not zero
107
108
109
  uiv.setErrorLabel(
      m_uiForm.valThickness,
      uiv.checkNotEqual("Thickness", m_uiForm.spThickness->value()));
110

111
  // Give error message
112
  if (!silent && !uiv.isAllInputValid())
113
    showInformationBox(uiv.generateErrorMessage());
114
115

  return uiv.isAllInputValid();
116
117
118
119
120
}

/**
 * Performs a calculation with the current settings
 */
121
void SampleTransmission::calculate() {
122
  // Do not try to run with invalid input
123
  if (!validate())
124
125
    return;

126
  // Create the transmission calculation algorithm
127
128
  IAlgorithm_sptr transCalcAlg =
      AlgorithmManager::Instance().create("CalculateSampleTransmission");
129
130
131
132
  transCalcAlg->initialize();

  // Set the wavelength binning based on type set in UI
  int wavelengthBinning = m_uiForm.cbBinningType->currentIndex();
133
134
135
  switch (wavelengthBinning) {
  // Single
  case 0: {
136
137
138
    // Convert values to binning params using the 'C' locale.
    std::ostringstream binning;
    binning.imbue(std::locale::classic());
Antti Soininen's avatar
Antti Soininen committed
139
140
141
    binning << m_uiForm.spSingleLow->value() << ','
            << m_uiForm.spSingleWidth->value() << ','
            << m_uiForm.spSingleHigh->value();
142
    transCalcAlg->setProperty("WavelengthRange", binning.str());
143
144
145
146
147
148
149
150
    break;
  }

  // Multiple
  case 1:
    transCalcAlg->setProperty("WavelengthRange",
                              m_uiForm.leMultiple->text().toStdString());
    break;
151
152
153
  }

  // Set sample material properties
154
155
  transCalcAlg->setProperty("ChemicalFormula",
                            m_uiForm.leChemicalFormula->text().toStdString());
156

157
158
  transCalcAlg->setProperty("DensityType",
                            m_uiForm.cbDensity->currentText().toStdString());
159
160
  transCalcAlg->setProperty("Density", m_uiForm.spDensity->value());

161
162
163
164
  transCalcAlg->setProperty("Thickness", m_uiForm.spThickness->value());

  transCalcAlg->setProperty("OutputWorkspace", "CalculatedSampleTransmission");

165
166
167
168
  // Clear the previous results
  m_uiForm.twResults->clear();
  m_uiForm.ppTransmission->clear();

169
170
171
172
173
174
175
176
177
  // Run algorithm
  m_algRunner->startAlgorithm(transCalcAlg);
}

/**
 * Handles completion of the calculation algorithm.
 *
 * @param error If the algorithm exited with an error
 */
178
void SampleTransmission::algorithmComplete(bool error) {
Dan Nixon's avatar
Dan Nixon committed
179
180
  using namespace Mantid::Kernel;

181
  // Ignore errors
182
183
184
  if (error) {
    showInformationBox(
        "Transmission calculation failed.\nSee Results Log for details.");
185
    return;
186
  }
187

Dan Nixon's avatar
Dan Nixon committed
188
  MatrixWorkspace_sptr ws =
189
190
      AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(
          "CalculatedSampleTransmission");
Dan Nixon's avatar
Dan Nixon committed
191
192

  // Fill the output table
LamarMoore's avatar
LamarMoore committed
193
  double scattering = ws->y(1)[0];
194
  auto *scatteringItem = new QTreeWidgetItem();
Dan Nixon's avatar
Dan Nixon committed
195
196
197
198
  scatteringItem->setText(0, "Scattering");
  scatteringItem->setText(1, QString::number(scattering));
  m_uiForm.twResults->addTopLevelItem(scatteringItem);

199
  auto *transmissionItem = new QTreeWidgetItem();
Dan Nixon's avatar
Dan Nixon committed
200
201
202
203
  transmissionItem->setText(0, "Transmission");
  m_uiForm.twResults->addTopLevelItem(transmissionItem);
  transmissionItem->setExpanded(true);

204
  Statistics stats = getStatistics(ws->y(0).rawData());
Dan Nixon's avatar
Dan Nixon committed
205
206
207
208
209
210
211
212

  QMap<QString, double> transmissionStats;
  transmissionStats["Min"] = stats.minimum;
  transmissionStats["Max"] = stats.maximum;
  transmissionStats["Mean"] = stats.mean;
  transmissionStats["Median"] = stats.median;
  transmissionStats["Std. Dev."] = stats.standard_deviation;

213
214
  for (auto it = transmissionStats.begin(); it != transmissionStats.end();
       ++it) {
Dan Nixon's avatar
Dan Nixon committed
215
216
217
218
219
220
    QTreeWidgetItem *item = new QTreeWidgetItem();
    item->setText(0, it.key());
    item->setText(1, QString::number(it.value()));
    transmissionItem->addChild(item);
  }

221
222
  m_uiForm.twResults->resizeColumnToContents(0);

223
224
225
226
227
228
229
230
231
232
233
234
  try {
    // Plot transmission curve on preview plot
    m_uiForm.ppTransmission->addSpectrum("Transmission",
                                         "CalculatedSampleTransmission", 0);
    m_uiForm.ppTransmission->resizeX();
  } catch (std::runtime_error &e) {
    // PreviewPlot may throw an exception if our workspace has less than two X
    // values
    showInformationBox(
        QString::fromStdString("Unable to plot CalculatedSampleTransmission: " +
                               std::string(e.what())));
  }
235
}