BornAgain  1.19.79
Simulate and fit neutron and x-ray scattering at grazing incidence
RealDataItem.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file GUI/Model/Data/RealDataItem.cpp
6 //! @brief Implements class RealDataItem
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 
16 #include "Device/Data/DataUtils.h"
28 #include "GUI/Util/Error.h"
29 
31  : SessionItem(M_TYPE)
32 {
33  setItemName("undefined");
34 
35  // Registering this tag even without actual data item to avoid troubles in copying RealDataItem
39 
40  addProperty(P_INSTRUMENT_ID, QString());
41 
45 }
46 
47 QString RealDataItem::dataName() const
48 {
49  return itemName();
50 }
51 
52 void RealDataItem::setDataName(const QString& name)
53 {
55 }
56 
58 {
59  return dynamic_cast<IntensityDataItem*>(dataItem());
60 }
61 
63 {
64  return dynamic_cast<const IntensityDataItem*>(dataItem());
65 }
66 
68 {
69  return dynamic_cast<SpecularDataItem*>(dataItem());
70 }
71 
73 {
74  return dynamic_cast<const SpecularDataItem*>(dataItem());
75 }
76 
78 {
79  return const_cast<DataItem*>(static_cast<const RealDataItem*>(this)->dataItem());
80 }
81 
83 {
84  return dynamic_cast<const DataItem*>(getItem(T_INTENSITY_DATA));
85 }
86 
88 {
89  return const_cast<DataItem*>(static_cast<const RealDataItem*>(this)->nativeData());
90 }
91 
93 {
94  return dynamic_cast<const DataItem*>(getItem(T_NATIVE_DATA));
95 }
96 
98 {
99  const size_t rank = isSpecularData() ? 1 : 2;
101 }
102 
104 {
105  return getItemValue(P_NATIVE_DATA_UNITS).toString();
106 }
107 
108 void RealDataItem::setNativeDataUnits(const QString& units)
109 {
111 }
112 
114 {
115  ASSERT(isSpecularData()); // not implemented for intensityDataItem
116 
117  if (nativeData() != nullptr)
118  nativeData()->setDatafield(nullptr);
119 }
120 
122 {
123  return (nativeData() != nullptr) && (nativeData()->getDatafield() != nullptr);
124 }
125 
126 const Datafield* RealDataItem::nativeDatafield() const
127 {
128  return hasNativeData() ? nativeData()->getDatafield() : nullptr;
129 }
130 
131 //! takes ownership of data
132 
133 void RealDataItem::setNativeDatafield(Datafield* data)
134 {
135  nativeData()->setDatafield(data); // takes ownership of odata
136 }
137 
138 //! Creates and inserts a data item except if such item with same tag already exists.
139 //! Checks for rank compatibility if already existing.
140 //! No further initialization (like clearing the data etc).
141 
142 void RealDataItem::initDataItem(size_t rank, const QString& tag)
143 {
144  ASSERT(rank == 1 || rank == 2);
145 
146  const auto* dataItem = dynamic_cast<const DataItem*>(getItem(tag));
147  if (dataItem != nullptr) {
148  if ((rank == 1 && !dynamic_cast<const SpecularDataItem*>(dataItem))
149  || (rank == 2 && !dynamic_cast<const IntensityDataItem*>(dataItem)))
150  throw Error("Error in RealDataItem::initDataItem: trying to set data "
151  "incompatible with underlying data item");
152  } else {
153  if (rank == 1)
154  model()->insertItem<SpecularDataItem>(this, 0, tag);
155  else
156  model()->insertItem<IntensityDataItem>(this, 0, tag);
157 
158  ASSERT(getItem(tag)
159  && "Assertion failed in RealDataItem::initDataItem: inserting data item failed.");
160  }
161 }
162 
163 //! Sets Datafield to underlying item. Creates it if not existing.
164 
165 void RealDataItem::setDatafield(Datafield* data)
166 {
167  ASSERT(data && "Assertion failed in RealDataItem::setDatafield: passed data is nullptr");
168 
169  initDataItem(data->rank(), T_INTENSITY_DATA);
170 
171  dataItem()->setDatafield(data);
172 }
173 
174 //! Sets imported data to underlying item. Creates it if not existing.
175 //! This is used for 1D import. For 2D import, use setDatafield.
176 
178 {
179  if (!info)
180  return;
181 
182  const size_t data_rank = info.dataRank();
183  initDataItem(data_rank, T_INTENSITY_DATA);
184  initDataItem(data_rank, T_NATIVE_DATA);
185 
186  QString units_name = info.unitsLabel();
187  auto output_data = info.clonedData();
188 
189  dataItem()->reset(std::move(info));
190  setNativeDataUnits(units_name);
191  item<DataItem>(T_NATIVE_DATA)->setDatafield(output_data.release());
192 }
193 
195 {
196  const size_t rank = 1;
198 }
199 
201 {
202  const size_t rank = 2;
204 }
205 
207 {
208  return nativeDataUnits() != "nbins";
209 }
210 
212 {
213  return getItemValue(P_INSTRUMENT_ID).toString();
214 }
215 
217 {
218  setItemValue(P_INSTRUMENT_ID, QString());
219  updateToInstrument(nullptr);
220 }
221 
223 {
224  if (instrument) {
225  setItemValue(P_INSTRUMENT_ID, instrument->id());
226  updateToInstrument(instrument);
227  } else
229 }
230 
231 std::vector<int> RealDataItem::shape() const
232 {
233  const auto* data_item = dataItem();
234  if (!data_item) {
235  ASSERT(data_item);
236  return {};
237  }
238  return data_item->shape();
239 }
240 
242 {
243  return intensityDataItem() != nullptr;
244 }
245 
247 {
248  return specularDataItem() != nullptr;
249 }
250 
252 {
253  return (dataLoader() != nullptr) ? dataLoader()->numErrors() > 0 : false;
254 }
255 
257 {
258  if (auto* intensity_data = intensityDataItem())
259  return intensity_data->maskContainerItem();
260  return nullptr;
261 }
262 
263 void RealDataItem::setNativeFileName(const QString& filename)
264 {
265  m_nativeFileName = filename;
266 }
267 
269 {
270  return m_nativeFileName;
271 }
272 
274 {
275  QByteArray a;
276  QDataStream s(&a, QIODevice::WriteOnly);
277  s.setVersion(QDataStream::Qt_5_12);
278 
279  s << (quint8)1; // version
280  s << m_nativeFileName;
281 
282  if (m_dataLoader) {
283  s << m_dataLoader->persistentClassName();
284  s << *m_dataLoader;
285  } else
286  s << QString(); // empty loader class name => no loader present
287 
288  return a;
289 }
290 
291 void RealDataItem::deserializeBinaryData(const QByteArray& data)
292 {
293  m_nativeFileName.clear();
294  m_importSettings.clear();
295  m_dataLoader.release();
296 
297  QDataStream s(data);
298  s.setVersion(QDataStream::Qt_5_12);
299 
300  quint8 version;
301  s >> version;
302 
303  if (version == 1) {
304  s >> m_nativeFileName;
305  QString persistentLoaderClassName;
306  s >> persistentLoaderClassName;
307  if (!persistentLoaderClassName.isEmpty()) {
309  DataLoaders1D::instance().createFromPersistentName(persistentLoaderClassName));
310  // #baUserDefLoaders ++ implement userdefined loaders (may require new version!)
311  if (!m_dataLoader)
313  s >> *m_dataLoader;
314  m_dataLoader->setRealDataItem(this);
315  }
316  } else
318 
319  if (s.status() != QDataStream::Ok)
321 }
322 
324 {
325  m_dataLoader.reset(loader);
326  if (m_dataLoader)
329 }
330 
332 {
333  return m_dataLoader.get();
334 }
335 
337 {
338  if (!isIntensityData()) // rotation only for 2D items possible
339  return false;
340 
341  const bool hasLinkToInstrument = !instrumentId().isEmpty();
342  if (hasLinkToInstrument)
343  return true;
344 
345  if (intensityDataItem()->hasMasks())
346  return true;
347 
348  if (intensityDataItem()->hasProjections())
349  return true;
350 
351  return false;
352 }
353 
355 {
356  if (!isIntensityData()) // rotation only for 2D items possible
357  return;
358 
359  // -- first break instrument link, clear masks and projections
361 
362  if (MaskContainerItem* maskContainer = intensityDataItem()->maskContainerItem())
363  maskContainer->clear();
364 
365  if (ProjectionContainerItem* projectionsContainer =
366  intensityDataItem()->projectionContainerItem())
367  projectionsContainer->model()->removeRows(0, projectionsContainer->numberOfChildren(),
368  projectionsContainer->index());
369 
370  // -- now rotate data
371  auto* const input = intensityDataItem()->getDatafield();
373  DataUtils::Data::createRearrangedDataSet(*input, 1).release());
375 }
376 
377 //! Updates the name of file to store intensity data.
378 
380 {
381  if (DataItem* item = dataItem())
383  if (DataItem* item = nativeData())
385 }
386 
388 {
389  DataItem* data_item = dataItem();
390  if (!data_item)
391  return;
392 
393  if (instrument) {
395  if (dataItem())
396  dataItem()->updateCoords(instrument);
397  return;
398  }
399 
400  // instrument == nullptr => unlinking => going back to native data
401  if (isSpecularData()) {
402  if (hasNativeData()) {
403  std::unique_ptr<Datafield> native_data(nativeData()->getDatafield()->clone());
404  const QString units_label = nativeDataUnits();
405  data_item->reset(ImportDataInfo(std::move(native_data), units_label));
406  } else {
407  specularDataItem()->setDatafield(nullptr);
408  }
409  } else {
410  auto* native_data_item = nativeData();
411  auto* data_source = native_data_item ? native_data_item : data_item;
412 
413  std::unique_ptr<Datafield> native_data(data_source->getDatafield()->clone());
414  const QString units_label = nativeDataUnits();
415  data_item->reset(ImportDataInfo(std::move(native_data), units_label));
416  }
417 }
Defines class AbstractDataLoader1D.
Defines class DataLoaders1D.
Defines class DeserializationException.
Defines error class.
Defines ImportDataInfo helper struct.
Defines class InstrumentItem and all its children.
Defines class IntensityDataItem.
Defines namespace GUI::Model::FilenameUtils.
Defines namespace GUI::Model::JobItemUtils.
Defines MaskItems classes.
Defines items related to projections over color map.
Defines class RealDataItem.
Defines class SpecularDataItem.
Abstract base class for all data loaders (classes to import real data).
void contentsProcessed()
Emitted whenever contents have been processed.
virtual int numErrors() const
Number of errors found while processing the content. An error means that either a particular content ...
Abstract base class for IntensityDataItem and SpecularDataItem. Owns one simulated data set of type D...
Definition: DataItem.h:34
virtual void setDatafield(Datafield *data)=0
The given pointer becomes owned by this class!!
Definition: DataItem.cpp:20
Datafield * getDatafield()
Definition: DataItem.h:41
virtual void updateCoords(const InstrumentItem *instrument)=0
virtual void reset(ImportDataInfo data)=0
Resets data to the state defined by user (imported) data.
static DataLoaders1D & instance()
The one and only instance.
static DeserializationException streamError()
static DeserializationException tooNew()
Carries information about loaded data.
size_t dataRank() const
Returns number of dimensions.
QString unitsLabel() const
std::unique_ptr< Datafield > clonedData() const &
Abstract base class for instrument-specific item classes.
QString id() const
void setAxesRangeToData() override
set zoom range of x,y axes to axes of input data
static constexpr auto M_TYPE
void setDatafield(Datafield *data) override
The given pointer becomes owned by this class!!
Container holding various masks as children.
Definition: MaskItems.h:202
A container to hold ProjectionItems, intended to store projections of color map on X,...
Provides access to experimental data, for display and fitting. Owns an AbstractDataLoader.
Definition: RealDataItem.h:33
void initDataItem(size_t data_rank, const QString &tag)
Creates and inserts a data item except if such item with same tag already exists. Checks for rank com...
void removeNativeData()
void initAsSpecularItem()
MaskContainerItem * maskContainerItem()
Returns mask container item.
bool hasImportErrors() const
bool holdsDimensionalData() const
QByteArray serializeBinaryData() const override
QString nativeDataUnits() const
void linkToInstrument(const InstrumentItem *instrument)
void unlinkFromInstrument()
static constexpr auto P_INSTRUMENT_ID
Definition: RealDataItem.h:39
void setNativeDatafield(Datafield *data)
takes ownership of data
static constexpr auto T_INTENSITY_DATA
Definition: RealDataItem.h:40
void deserializeBinaryData(const QByteArray &data) override
QByteArray m_importSettings
Definition: RealDataItem.h:122
QString dataName() const
The name which is presented to the user.
void initNativeData()
bool isIntensityData() const
std::vector< int > shape() const
Returns the shape of underlying data item.
std::unique_ptr< AbstractDataLoader > m_dataLoader
Definition: RealDataItem.h:125
bool isSpecularData() const
AbstractDataLoader * dataLoader() const
void setDataName(const QString &name)
void updateToInstrument(const InstrumentItem *instrument)
This does not set the link to the instrument! Use linkToInstrument() if you want to link to this inst...
QString instrumentId() const
void setImportData(ImportDataInfo info)
Sets imported data to underlying item. Creates it if not existing. This is used for 1D import....
QString nativeFileName() const
void setDataLoader(AbstractDataLoader *loader)
Takes ownership of loader.
bool hasNativeData() const
void setNativeFileName(const QString &filename)
The name from where the native data was originally imported.
QString m_nativeFileName
Definition: RealDataItem.h:123
IntensityDataItem * intensityDataItem()
void setNativeDataUnits(const QString &units)
DataItem * nativeData()
static constexpr auto P_NATIVE_DATA_UNITS
Definition: RealDataItem.h:42
SpecularDataItem * specularDataItem()
void initAsIntensityItem()
static constexpr auto T_NATIVE_DATA
Definition: RealDataItem.h:41
const Datafield * nativeDatafield() const
bool rotationAffectsSetup() const
Returns true, if rotation will affect linked instrument or mask presence.
DataItem * dataItem()
void importContentsProcessed()
void updateNonXMLDataFileNames()
Updates the name of file to store intensity data.
void setDatafield(Datafield *data)
Sets Datafield to underlying item. Creates it if not existing.
Base class for a GUI data item.
Definition: SessionItem.h:204
QString itemName() const
Get item name, return display name if no name is set.
void setItemName(const QString &name)
Set item name, add property if necessary.
SessionItem * addProperty(const QString &name, const QVariant &variant)
Add new property item and register new tag. name is the tag name and the display name....
bool registerTag(const QString &name, int min=0, int max=-1, QStringList modelTypes={})
Add new tag to this item with given name, min, max and types. max = -1 -> unlimited,...
bool setValue(QVariant value)
Set value, ensure that variant types match.
QVariant getItemValue(const QString &tag) const
Directly access value of item under given tag.
void setItemValue(const QString &tag, const QVariant &variant) const
Directly set value of item under given tag.
void setDefaultTag(const QString &tag)
Set default tag.
SessionModel * model() const
Returns model of this item.
Definition: SessionItem.cpp:60
T * item(const QString &tag) const
Definition: SessionItem.h:353
SessionItem * getItem(const QString &tag="", int row=0) const
Returns item in given row of given tag.
T * insertItem(SessionItem *parent=nullptr, int row=-1, QString tag="")
Definition: SessionModel.h:137
void setDatafield(Datafield *data) override
The given pointer becomes owned by this class!!
static constexpr auto M_TYPE
QString nativeDataFileName(const QString &dataName)
QString realDataFileName(const QString &dataName)
Constructs the name of the intensity file belonging to real data item.
void setIntensityItemCoords(DataItem *intensityItem, const InstrumentItem *instrumentItem)
Sets axes units suitable for given instrument.
QString const & name(EShape k)
Definition: particles.cpp:20