BornAgain  1.19.79
Simulate and fit neutron and x-ray scattering at grazing incidence
SimulationView.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file GUI/View/Toplevel/SimulationView.cpp
6 //! @brief Implements class SimulationView
7 //!
8 //! @homepage http://www.bornagainproject.org
9 //! @license GNU General Public License v3 or higher (see COPYING)
10 //! @copyright Forschungszentrum Jülich GmbH 2021
11 //! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************************************
14 
18 #include "GUI/Model/Job/JobItem.h"
29 #include "ui_SimulationView.h"
30 #include <QButtonGroup>
31 #include <QMessageBox>
32 #include <thread>
33 
35  : QWidget(parent)
36  , m_ui(new Ui::SimulationView)
37  , m_document(document)
38 {
39  m_ui->setupUi(this);
40 
41  setAttribute(Qt::WA_StyledBackground, true);
42  setProperty("stylable", true); // for stylesheet addressing
43 
47 
48  auto* buttonGroup = new QButtonGroup(this);
49  buttonGroup->addButton(m_ui->runPolicyImmediatelyRadio);
50  buttonGroup->addButton(m_ui->runPolicyBackgroundRadio);
51 
52  auto* computationButtonGroup = new QButtonGroup(this);
53  computationButtonGroup->addButton(m_ui->analyticalRadio);
54  computationButtonGroup->addButton(m_ui->monteCarloRadio);
55 
56  buttonGroup = new QButtonGroup(this);
57  buttonGroup->addButton(m_ui->ambientLayerRadio);
58  buttonGroup->addButton(m_ui->averageLayerRadio);
59 
60  // -- fill combo for "number of threads"
61  const int nthreads = static_cast<int>(std::thread::hardware_concurrency());
62  m_ui->numberOfThreadsCombo->addItem(QString("Max (%1 threads)").arg(nthreads), nthreads);
63  for (int i = nthreads - 1; i > 1; i--)
64  m_ui->numberOfThreadsCombo->addItem(QString("%1 threads").arg(i), i);
65  m_ui->numberOfThreadsCombo->addItem("1 thread", 1);
66 
68 
69  connect(m_ui->simulateButton, &QPushButton::clicked, this, &SimulationView::simulate);
70  connect(m_ui->exportToPyScriptButton, &QPushButton::clicked, this,
72  connect(computationButtonGroup, QOverload<int>::of(&QButtonGroup::buttonClicked), this,
74 
75  connect(m_ui->runPolicyImmediatelyRadio, &QRadioButton::toggled,
76  [=]() { document->setModified(); });
77 
78  connect(m_ui->analyticalRadio, &QRadioButton::toggled, [=]() { document->setModified(); });
79 
80  connect(m_ui->averageLayerRadio, &QRadioButton::toggled, [=]() { document->setModified(); });
81 
82  connect(m_ui->numberOfThreadsCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
83  [=]() { document->setModified(); });
84 
85  connect(m_ui->numberOfMonteCarloPoints, QOverload<int>::of(&QSpinBox::valueChanged),
86  [=]() { document->setModified(); });
87 
88  connect(m_ui->includeSpecularCheck, &QCheckBox::toggled, [=]() { document->setModified(); });
89 
90  connect(m_document, &ProjectDocument::modified, this,
92 }
93 
94 void SimulationView::showEvent(QShowEvent*)
95 {
97 }
98 
100 {
101  QSignalBlocker b1(m_ui->runPolicyImmediatelyRadio);
102  QSignalBlocker b2(m_ui->analyticalRadio);
103  QSignalBlocker b3(m_ui->averageLayerRadio);
104  QSignalBlocker b4(m_ui->numberOfThreadsCombo);
105  QSignalBlocker b5(m_ui->numberOfMonteCarloPoints);
106  QSignalBlocker b6(m_ui->includeSpecularCheck);
107 
108  // -- selection group
111  updateSelection(m_ui->realDataCombo, m_document->realDataModel()->realDataNames(), true);
112 
113  // -- options group
114  optionsItem()->runImmediately() ? m_ui->runPolicyImmediatelyRadio->setChecked(true)
115  : m_ui->runPolicyBackgroundRadio->setChecked(true);
116 
117  optionsItem()->useAnalytical() ? m_ui->analyticalRadio->setChecked(true)
118  : m_ui->monteCarloRadio->setChecked(true);
119 
120  optionsItem()->useAverageMaterials() ? m_ui->averageLayerRadio->setChecked(true)
121  : m_ui->ambientLayerRadio->setChecked(true);
122 
123  m_ui->numberOfThreadsCombo->setCurrentIndex(
124  m_ui->numberOfThreadsCombo->findData(optionsItem()->numberOfThreads()));
125  m_ui->numberOfMonteCarloPoints->setValue(optionsItem()->numberOfMonteCarloPoints());
126  m_ui->includeSpecularCheck->setChecked(optionsItem()->includeSpecularPeak());
127 
128  updateEnabling();
129 }
130 
131 void SimulationView::hideEvent(QHideEvent*)
132 {
133  // Storing the options has do be done here because on a showEvent the values are set again from
134  // the SimulationOptionsItem (=> keep values when switching views)
136 }
137 
139 {
141  if (const QString msg = validateSimulationSetup(true); !msg.isEmpty()) {
142  QMessageBox::warning(this, "Can't run the job",
143  "Can't run the job with current settings\n\n" + msg);
144  return;
145  }
146  JobModel* jobModel = m_document->jobModel();
147  JobItem* jobItem = jobModel->addJob(selectedSample(), selectedInstrument(), selectedRealData(),
148  *optionsItem());
149  jobModel->runJob(jobItem);
150 }
151 
153 {
155  if (const QString msg = validateSimulationSetup(false); !msg.isEmpty()) {
156  QMessageBox::warning(this, "Can't export to Python",
157  "Can't export to Python with current settings\n\n" + msg);
158  return;
159  }
160  auto* pythonWidget = new PythonScriptWidget(GUI::Global::mainWindow);
161  pythonWidget->show();
162  pythonWidget->raise();
163  pythonWidget->generatePythonScript(selectedSample(), selectedInstrument(), *optionsItem(),
165 }
166 
168 {
169  optionsItem()->setRunImmediately(m_ui->runPolicyImmediatelyRadio->isChecked());
170  optionsItem()->setNumberOfThreads(m_ui->numberOfThreadsCombo->currentData().toInt());
171  if (m_ui->analyticalRadio->isChecked())
173  else
174  optionsItem()->setUseMonteCarloIntegration(m_ui->numberOfMonteCarloPoints->value());
175  optionsItem()->setUseAverageMaterials(m_ui->averageLayerRadio->isChecked());
176  optionsItem()->setIncludeSpecularPeak(m_ui->includeSpecularCheck->isChecked());
177 }
178 
180 {
181  m_ui->numberOfMonteCarloPoints->setEnabled(m_ui->monteCarloRadio->isChecked());
182 }
183 
184 void SimulationView::updateSelection(QComboBox* comboBox, QStringList itemList, bool allowNone)
185 {
186  const QString previousItem = comboBox->currentText();
187 
188  comboBox->clear();
189  comboBox->setEnabled(!itemList.isEmpty());
190 
191  if (itemList.isEmpty()) {
192  comboBox->addItem("Not yet defined");
193  return;
194  }
195 
196  if (allowNone)
197  itemList.insert(-1, "None");
198  comboBox->addItems(itemList);
199  if (itemList.contains(previousItem))
200  comboBox->setCurrentIndex(itemList.indexOf(previousItem));
201 }
202 
203 QString SimulationView::validateSimulationSetup(bool validateRealData) const
204 {
205  QString messages;
206  const auto append = [&](const QString& m) { messages.append("- " + m + "\n"); };
207 
208  if (!selectedSample())
209  append("No sample selected");
210  else {
211  SampleValidator sampleValidator;
212  if (!sampleValidator.isValidMultiLayer(selectedSample()))
213  append(sampleValidator.getValidationMessage());
214  }
215 
216  if (!selectedInstrument())
217  append("No instrument selected");
218 
219  if (validateRealData && selectedRealData() && selectedInstrument()
221  append("The experimental data does not fit in the selected instrument. Try linking "
222  "them in Import Tab.");
223 
224  return messages;
225 }
226 
228 {
229  m_ui->instrumentCombo->setVisible(!m_document->singleInstrumentMode());
230  m_ui->instrumentLabel->setVisible(!m_document->singleInstrumentMode());
231 }
232 
233 QVector<MultiLayerItem*> SimulationView::sampleItems() const
234 {
235  return m_document->sampleItems()->sampleItems();
236 }
237 
238 QVector<InstrumentItem*> SimulationView::collectedItems() const
239 {
241 }
242 
243 QVector<RealDataItem*> SimulationView::realDataItems() const
244 {
246 }
247 
249 {
251 }
252 
254 {
255  return sampleItems().value(m_ui->sampleCombo->currentIndex(), nullptr);
256 }
257 
259 {
260  return collectedItems().value(m_ui->instrumentCombo->currentIndex(), nullptr);
261 }
262 
264 {
265  return realDataItems().value(m_ui->realDataCombo->currentIndex() - 1, nullptr); // -1: "None"
266 }
Defines global pointers.
Defines class GroupBoxCollapser.
Defines class InstrumentItem and all its children.
Defines class JobItem.
Defines class JobModel.
Defines class MultiLayerItem.
Defines class ProjectDocument.
Defines class ProjectManager.
Defines class PythonScriptWidget.
Defines class RealDataItem.
Defines class RealDataModel.
Defines class SampleValidator.
Defines class SimulationOptionsItem.
Defines class SimulationView.
static GroupBoxCollapser * installIntoGroupBox(QGroupBox *groupBox, bool expanded=true)
QVector< InstrumentItem * > collectedItems() const
QStringList instrumentNames() const
Abstract base class for instrument-specific item classes.
virtual bool alignedWith(const RealDataItem *item) const
void runJob(JobItem *jobItem)
Definition: JobModel.cpp:142
JobItem * addJob(const MultiLayerItem *sampleItem, const InstrumentItem *instrumentItem, const RealDataItem *realDataItem, const SimulationOptionsItem &optionItem)
Main method to add a job.
Definition: JobModel.cpp:52
QStringList sampleNames() const
QVector< MultiLayerItem * > sampleItems() const
Project document class handles all data related to the opened project (sample, job,...
JobModel * jobModel() const
RealDataModel * realDataModel() const
InstrumentCollection * collectedItems() const
MultiLayerItems * sampleItems()
bool singleInstrumentMode() const
void modified()
Emitted for any modifications in the document.
SimulationOptionsItem * simulationOptionsItem()
static ProjectManager * instance()
The PythonScriptWidget displays a python script which represents full simulation. Part of SimulationS...
Provides access to experimental data, for display and fitting. Owns an AbstractDataLoader.
Definition: RealDataItem.h:33
QVector< RealDataItem * > realDataItems() const
QStringList realDataNames() const
Validates whether MultiLayerItem is suitable for simulation.
bool isValidMultiLayer(const MultiLayerItem *sample)
QString getValidationMessage() const
The SimulationOptionsItem class holds simulation status (run policy, number of threads,...
void setRunImmediately(bool runImmediately)
void setUseAverageMaterials(bool useAverageMaterials)
void setNumberOfThreads(unsigned n)
void setIncludeSpecularPeak(bool includeSpecularPeak)
void setUseMonteCarloIntegration(unsigned numberOfPoints)
Widget to define a simulation. Contains:
SimulationOptionsItem * optionsItem() const
QVector< MultiLayerItem * > sampleItems() const
QVector< RealDataItem * > realDataItems() const
Ui::SimulationView * m_ui
const RealDataItem * selectedRealData() const
Returns selected real data item taking into account that there might be several items with the same n...
const InstrumentItem * selectedInstrument() const
Returns selected InstrumentItem taking into account that there might be several instruments with the ...
const MultiLayerItem * selectedSample() const
Returns selected sample (MultiLayerItem) taking into account that there might be several samples with...
QVector< InstrumentItem * > collectedItems() const
void updateFunctionalityNarrowing()
Show/hide UI elements according to settings in current project.
ProjectDocument * m_document
void showEvent(QShowEvent *) override
void updateSelection(QComboBox *comboBox, QStringList itemList, bool allowNone=false)
Updates selection combo with string list while preserving previous selection. If allowNone == true,...
void writeOptionsToUI()
Write entries in OptionsItem to UI.
void hideEvent(QHideEvent *) override
SimulationView(QWidget *parent, ProjectDocument *document)
QString validateSimulationSetup(bool validateRealData) const
Checks whether selection is correct for running a simulation. Returns empty string if valid,...
void readOptionsFromUI()
Read the entries in the UI and store in OptionsItem.
void updateEnabling()
Update enabling of elements depending on other elements.
static QMainWindow * mainWindow
Definition: Globals.h:22
QString projectDir(const QString &projectFileName)
Returns project directory deduced from project file name.
void warning(QWidget *parent, const QString &title, const QString &text, const QString &detailedText)
Definition: MessageBox.cpp:37