BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
LinkInstrumentManager.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file GUI/coregui/Views/ImportDataWidgets/LinkInstrumentManager.cpp
6 //! @brief Implements class LinkInstrumentManager
7 //!
8 //! @homepage http://www.bornagainproject.org
9 //! @license GNU General Public License v3 or higher (see COPYING)
10 //! @copyright Forschungszentrum Jülich GmbH 2018
11 //! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************************************
14 
26 #include <QMessageBox>
27 #include <QPushButton>
28 
29 namespace {
30 bool QuestionOnInstrumentReshaping(const QString& message);
31 } // namespace
32 
34  : QObject(parent), m_instrumentModel(nullptr), m_realDataModel(nullptr)
35 {
36 }
37 
38 //! Sets models and builds initial links.
39 
41  RealDataModel* realDataModel)
42 {
43  ASSERT(instrumentModel != nullptr);
44  ASSERT(realDataModel != nullptr);
45 
47  m_instrumentModel->disconnect(this);
48 
49  if (m_realDataModel)
50  m_realDataModel->disconnect(this);
51 
52  m_instrumentModel = instrumentModel;
53  m_realDataModel = realDataModel;
54 
57 
59 }
60 
61 //! Returns true if RealDataItem can be linked to the instrument (same number of bins).
62 //! Also offers dialog to adjust instrument to match shape of real data.
63 
65  const QString& identifier,
66  bool quiet /*= false*/)
67 {
68  auto instrumentItem = m_instrumentModel->findInstrumentById(identifier);
69 
70  // linking to null instrument is possible, it means unlinking from currently linked
71  if (!instrumentItem)
72  return true;
73 
74  const bool isCompatible = ImportDataUtils::Compatible(*instrumentItem, *realDataItem);
75  if (!isCompatible) {
76  if (!quiet)
77  QMessageBox::warning(MainWindow::instance(), "Can't link to instrument",
78  "Can't link, data is incompatible with the instrument.");
79  return false;
80  }
81 
82  if (realDataItem->isSpecularData() && !realDataItem->hasNativeData()) {
83  if (!quiet)
84  QMessageBox::warning(MainWindow::instance(), "Can't link to instrument",
85  "Can't link, data is empty.");
86  return false;
87  }
88 
89  if (instrumentItem->alignedWith(realDataItem))
90  return true;
91 
92  QString message =
93  realDataItem->holdsDimensionalData()
94  ? "Experimental data carries information on the range/points of measurement."
95  : ImportDataUtils::printShapeMessage(instrumentItem->shape(), realDataItem->shape());
96  if (!QuestionOnInstrumentReshaping(message))
97  return false;
98 
99  instrumentItem->updateToRealData(realDataItem);
100  return true;
101 }
102 
103 //! Perform actions on instrument children change.
104 
106 {
107  if (child == nullptr)
108  return;
109 
110  ASSERT(instrument != nullptr);
111 
112  // Run through all RealDataItem and refresh linking to match possible change in detector
113  // axes definition.
114  for (auto realDataItem : linkedRealDataItems(instrument))
115  if (!instrument->alignedWith(realDataItem))
116  realDataItem->clearInstrumentId();
117  else
118  realDataItem->updateToInstrument(instrument);
119 }
120 
121 //! Updates map of instruments on insert/remove InstrumentItem event.
122 
124 {
125  // remove links in realDataItems (in case of a linked instrument was removed)
126  for (auto realDataItem : m_realDataModel->realDataItems()) {
127  if (!m_instrumentModel->instrumentExists(realDataItem->instrumentId()))
128  realDataItem->clearInstrumentId();
129  }
130 
132 }
133 
134 //! Set up callbacks to all instrument items
135 
137 {
138  for (auto instrumentItem : m_instrumentModel->instrumentItems()) {
139  instrumentItem->mapper()->unsubscribe(this);
140 
141  instrumentItem->mapper()->setOnAnyChildChange(
142  [this, instrumentItem](SessionItem* child) {
143  onInstrumentChildChange(instrumentItem, child);
144  },
145  this);
146  }
147 }
148 
149 //! Returns list of RealDataItem's linked to given instrument.
150 
151 QList<RealDataItem*> LinkInstrumentManager::linkedRealDataItems(InstrumentItem* instrumentItem)
152 {
153  ASSERT(instrumentItem != nullptr);
154 
155  QList<RealDataItem*> result;
156  for (auto realDataItem : m_realDataModel->realDataItems()) {
157  const QString linkedIdentifier = realDataItem->instrumentId();
158  const QString instrumentIdentifier = instrumentItem->id();
159 
160  if (linkedIdentifier == instrumentIdentifier)
161  result.append(realDataItem);
162  }
163  return result;
164 }
165 
166 namespace {
167 bool QuestionOnInstrumentReshaping(const QString& message)
168 {
169  QMessageBox msgBox;
170  msgBox.setText("Instrument description conflicts with the experimental data.");
171 
172  QString informative;
173  informative.append(message);
174  informative.append("\n\nDo you want to adjust the instrument to the experimental data?\n\n");
175  msgBox.setInformativeText(informative);
176 
177  QPushButton* modifyInstrumentButton =
178  msgBox.addButton("Yes, please modify instrument", QMessageBox::YesRole);
179  msgBox.addButton("No, leave as it is", QMessageBox::NoRole);
180 
181  msgBox.exec();
182 
183  return msgBox.clickedButton() == modifyInstrumentButton;
184 }
185 } // namespace
#define ASSERT(condition)
Definition: Assert.h:31
Defines various axis items.
Declares class DataItem.
Defines classes DetectorItems.
Defines class MainWindow.
Defines ImportDataUtils namespace.
Defines InstrumentItems classes.
Defines class InstrumentModel.
Defines class LinkInstrumentManager.
Defines MaskItems classes.
Defines class RealDataItem.
Defines class RealDataModel.
QString id() const
virtual bool alignedWith(const RealDataItem *item) const
bool instrumentExists(const QString &instrumentId) const
InstrumentItem * findInstrumentById(const QString &instrumentId) const
QVector< InstrumentItem * > instrumentItems() const
void instrumentAddedOrRemoved()
void onInstrumentAddedOrRemoved()
Updates map of instruments on insert/remove InstrumentItem event.
bool canLinkDataToInstrument(const RealDataItem *realDataItem, const QString &identifier, bool quiet=false)
quiet defines whether a "not possible" message box is shown if link is not possible.
LinkInstrumentManager(QObject *parent=nullptr)
QList< RealDataItem * > linkedRealDataItems(InstrumentItem *instrumentItem)
Returns list of RealDataItem's linked to given instrument.
void setModels(InstrumentModel *instrumentModel, RealDataModel *realDataModel)
Sets models and builds initial links.
void onInstrumentChildChange(InstrumentItem *instrument, SessionItem *child)
Perform actions on instrument children change.
void updateInstrumentSubscriptions()
Set up callbacks to all instrument items.
InstrumentModel * m_instrumentModel
RealDataModel * m_realDataModel
static MainWindow * instance()
Returns the one and only instance of this class.
Definition: mainwindow.cpp:129
The RealDataItem class represents intensity data imported from file and intended for fitting.
Definition: RealDataItem.h:35
bool holdsDimensionalData() const
std::vector< int > shape() const
Returns the shape of underlying data item.
bool isSpecularData() const
bool hasNativeData() const
The RealDataModel class is a model to store all imported RealDataItem's.
Definition: RealDataModel.h:26
QVector< RealDataItem * > realDataItems() const
void warning(QWidget *parent, const QString &title, const QString &text, const QString &detailedText)
Definition: GUIHelpers.cpp:74
QString printShapeMessage(const std::vector< int > &instrument_shape, const std::vector< int > &data_shape)
Composes a message with the shapes of InstrumentItem and RealDataItem.
bool Compatible(const InstrumentItem &instrumentItem, const RealDataItem &realDataItem)
Check whether data item is compatible with instrument (same rank)