BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
JobModelFunctions.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file GUI/coregui/Models/JobModelFunctions.cpp
6 //! @brief Implements auxiliary functions in JobModelFunctions namespace.
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 
42 #include <map>
43 
44 namespace {
45 //! Links RealDataItem to the JobItem's instrument.
46 // (re-)Linking is necessary because of following reason
47 // 1) Copying of RealDataItem from RealDataModel on board of JobItem requires relink to the copied
48 // insturment
49 // 2) During relink all masks (if exists) will be converted to the default units of current detector
50 void processInstrumentLink(JobItem* jobItem);
51 
52 //! Copies masks and ROI from RealDataItem on board of instrument.
53 void copyMasksToInstrument(JobItem* jobItem);
54 
55 //! Crops RealDataItem to the region of interest.
56 void cropRealData(JobItem* jobItem);
57 
58 //! Creates necessary fit containers for jobItem intended for fitting.
59 void createFitContainers(JobItem* jobItem);
60 
61 PointwiseAxisItem* getPointwiseAxisItem(const SpecularInstrumentItem* instrument);
62 } // namespace
63 
65 {
66  ASSERT(job_item && job_item->isValidForFitting());
67  ASSERT(job_item->instrumentItem() && job_item->instrumentItem()->is<SpecularInstrumentItem>());
68  ASSERT(!job_item->getItem(JobItem::T_DATAVIEW));
69 
70  SessionModel* model = job_item->model();
71  auto view_item = model->insertItem<Data1DViewItem>(job_item, -1, JobItem::T_DATAVIEW);
72 
73  auto property_container =
75 
76  property_container->addItem(job_item->realDataItem()->dataItem());
77  property_container->addItem(job_item->dataItem());
78 
79  // also triggers Data1DViewItem::setAxesRangeToData and DataViewUtils::updateAxesTitle by
80  // setting new value of P_AXES_UNITS.
81  auto converter = DomainObjectBuilder::createUnitConverter(job_item->instrumentItem());
84 }
85 
87 {
88  auto model = jobItem->model();
89  auto multilayer = model->copyItem(sampleItem, jobItem, JobItem::T_SAMPLE);
90  multilayer->setItemName("MultiLayer");
91 
92  // copying materials
93  auto container = jobItem->model()->insertItem<MaterialItemContainer>(
94  jobItem, -1, JobItem::T_MATERIAL_CONTAINER);
95 
96  std::map<MaterialItem*, QString> materials;
97  for (auto property_item : multilayer->materialPropertyItems()) {
98  auto material_property = property_item->value().value<ExternalProperty>();
99  auto material = MaterialItemUtils::findMaterial(material_property);
100 
101  auto iter = materials.find(material);
102  if (iter == materials.end()) {
103  auto material_copy = container->insertCopy(material);
104  materials.insert({material, material_copy->identifier()});
105  material_property.setIdentifier(material_copy->identifier());
106  } else
107  material_property.setIdentifier(iter->second);
108  property_item->setValue(material_property.variant());
109  }
110 }
111 
113 {
114  auto model = jobItem->model();
115  auto copiedInstrument = model->copyItem(from, jobItem, JobItem::T_INSTRUMENT);
116  copiedInstrument->setItemName(from->modelType());
117  copiedInstrument->setId(GUIHelpers::createUuid());
119 
120  auto spec_to = dynamic_cast<SpecularInstrumentItem*>(copiedInstrument);
121  if (!spec_to)
122  return;
123 
124  // updating filename
126  spec_to->beamItem()->updateFileName(filename);
127 
128  // copying axis data
129  auto spec_from = static_cast<const SpecularInstrumentItem*>(from);
130  auto axis_origin = getPointwiseAxisItem(spec_from);
131  const QString current_axis_type = spec_from->beamItem()->inclinationAxisGroup()->currentType();
132  if (current_axis_type == "PointwiseAxis")
133  spec_to->beamItem()->updateToData(*axis_origin->axis(), axis_origin->getUnitsLabel());
134  else if (axis_origin->containsNonXMLData())
135  getPointwiseAxisItem(spec_to)->init(*axis_origin->axis(), axis_origin->getUnitsLabel());
136 }
137 
138 //! Setup items intended for storing results of the job.
139 
141 {
142  const bool isSpecularInstrument = jobItem->instrumentItem()->is<SpecularInstrumentItem>();
143  const bool isIntensityInstrument = jobItem->instrumentItem()->is<GISASInstrumentItem>()
145  || jobItem->instrumentItem()->is<DepthProbeInstrumentItem>();
146 
147  ASSERT(isSpecularInstrument || isIntensityInstrument);
148 
149  if (isSpecularInstrument)
150  jobItem->model()->insertItem<SpecularDataItem>(jobItem, -1, JobItem::T_OUTPUT);
151  else if (isIntensityInstrument)
152  jobItem->model()->insertItem<IntensityDataItem>(jobItem, -1, JobItem::T_OUTPUT);
153  else
154  throw GUIHelpers::Error("JobModelFunctions::setupJobItemOutput() -> Error. "
155  "Unsupported instrument type");
156 }
157 
158 //! Setups JobItem for fit.
159 
160 void JobModelFunctions::setupJobItemForFit(JobItem* jobItem, const RealDataItem* realDataItem)
161 {
162  if (!jobItem->instrumentItem())
163  throw GUIHelpers::Error("JobModelFunctions::processInstrumentLink() -> Error. "
164  "No instrument.");
165 
166  copyRealDataItem(jobItem, realDataItem);
167  processInstrumentLink(jobItem);
168  copyMasksToInstrument(jobItem);
169 
170  // TODO: remove if when other simulation types are ready for roi & masks
171  if (jobItem->instrumentItem()->is<GISASInstrumentItem>())
172  cropRealData(jobItem);
173  if (jobItem->instrumentItem()->is<SpecularInstrumentItem>())
174  initDataView(jobItem);
175 
176  createFitContainers(jobItem);
177 }
178 
180 {
181  auto container =
183  for (auto item : container->getItems(MaterialItemContainer::T_MATERIALS))
185 
186  auto sample = static_cast<MultiLayerItem*>(jobItem->getItem(JobItem::T_SAMPLE));
188 }
189 
190 void JobModelFunctions::copyRealDataItem(JobItem* jobItem, const RealDataItem* realDataItem)
191 {
192  if (!realDataItem)
193  return;
194 
195  SessionModel* model = jobItem->model();
196 
197  RealDataItem* realDataItemCopy = model->copyItem(realDataItem, jobItem, JobItem::T_REALDATA);
198  ASSERT(realDataItemCopy);
199 
200  realDataItemCopy->dataItem()->setOutputData(realDataItem->dataItem()->getOutputData()->clone());
201 
202  // adapting the name to job name
203  realDataItemCopy->dataItem()->setFileName(ItemFileNameUtils::jobReferenceFileName(*jobItem));
204 
205  // #baimport ++ copy members of realDataItem?
206 
207  if (!realDataItem->hasNativeData())
208  return;
209 
210  realDataItemCopy->setNativeOutputData(realDataItem->nativeOutputData()->clone());
211  realDataItemCopy->nativeData()->setFileName(ItemFileNameUtils::jobNativeDataFileName(*jobItem));
212 }
213 
215 {
216  while (item && item->modelType() != "JobItem")
217  item = item->parent();
218  return static_cast<const JobItem*>(item);
219 }
220 
221 namespace {
222 void processInstrumentLink(JobItem* jobItem)
223 {
224  RealDataItem* realData = jobItem->realDataItem();
225  if (!realData)
226  throw GUIHelpers::Error("JobModelFunctions::processInstrumentLink() -> Error. No data.");
227 
228  realData->setInstrumentId(jobItem->instrumentItem()->id());
229  realData->updateToInstrument(jobItem->instrumentItem());
230 }
231 
232 void copyMasksToInstrument(JobItem* jobItem)
233 {
234  auto mask_container = jobItem->realDataItem()->maskContainerItem();
235  jobItem->instrumentItem()->importMasks(mask_container);
236 }
237 
238 void cropRealData(JobItem* jobItem)
239 {
240  RealDataItem* realData = jobItem->realDataItem();
241 
242  // adjusting real data to the size of region of interest
243  IntensityDataItem* intensityItem = realData->intensityDataItem();
244 
245  std::unique_ptr<OutputData<double>> origData(intensityItem->getOutputData()->clone());
246 
247  JobItemUtils::createDefaultDetectorMap(intensityItem, jobItem->instrumentItem());
248 
249  auto instrument = jobItem->instrumentItem()->createInstrument();
250  instrument->getDetector()->iterate(
251  [&](IDetector::const_iterator it) {
252  auto cropped_data = intensityItem->getOutputData();
253  (*cropped_data)[it.roiIndex()] = (*origData)[it.detectorIndex()];
254  },
255  /*visit_masked*/ false);
256 
257  intensityItem->updateDataRange();
258 }
259 
260 void createFitContainers(JobItem* jobItem)
261 {
262  SessionModel* model = jobItem->model();
263 
264  SessionItem* fitSuiteItem = jobItem->getItem(JobItem::T_FIT_SUITE);
265  if (fitSuiteItem != nullptr) {
266  throw GUIHelpers::Error("JobModel::createFitContainers() -> Error. Attempt to create "
267  "a second FitSuiteItem.");
268  }
269 
270  fitSuiteItem = model->insertItem<FitSuiteItem>(jobItem, -1, JobItem::T_FIT_SUITE);
271 
272  SessionItem* parsContainerItem =
274  if (parsContainerItem != nullptr) {
275  throw GUIHelpers::Error("JobModel::createFitContainers() -> Error. Attempt to create "
276  "a second FitParameterContainer.");
277  }
278 
279  model->insertItem<FitParameterContainerItem>(fitSuiteItem, -1,
281 
282  // Minimizer settings
283  SessionItem* minimizerContainerItem = fitSuiteItem->getItem(FitSuiteItem::T_MINIMIZER);
284  if (minimizerContainerItem != nullptr) {
285  throw GUIHelpers::Error("JobModel::createFitContainers() -> Error. Attempt to create "
286  "a second MinimizerContainer.");
287  }
288 
290 }
291 
292 PointwiseAxisItem* getPointwiseAxisItem(const SpecularInstrumentItem* instrument)
293 {
294  return dynamic_cast<PointwiseAxisItem*>(
295  instrument->beamItem()->inclinationAxisGroup()->getChildOfType("PointwiseAxis"));
296 }
297 } // namespace
#define ASSERT(condition)
Definition: Assert.h:31
Defines class Data1DViewItem.
Defines class DataPropertyContainer.
Defines DepthProbeInstrumentItem class.
Defines classes DetectorItems.
Defines DomainObjectBuilder namespace.
Defines FitParameterItems family of classes.
Defines class FitSuiteItem.
Defines class GUIHelpers functions.
Defines class GroupItem.
Defines interface IDetector2D.
Defines InstrumentItems classes.
Defines class Instrument.
Defines class IntensityDataItem.
Defines auxiliary functions in ItemFileNameUtils namespace.
Defines class JobItemUtils.
Defines class JobItem.
Defines auxiliary functions in JobModelFunctions namespace.
Defines class JobModel.
Defines MaskItems classes.
Defines class MaskUnitsConverter.
Defines class MaterialItemContainer.
Defines class MaterialItemUtils.
Defines MinimizerItem class.
Defines class MultiLayerItem.
Defines pointwise axis item.
Defines class RealDataItem.
Defines class SpecularDataItem.
QVariant variant() const
Constructs variant enclosing given ComboProperty.
View model for 1D DataItem.
static const QString P_AXES_UNITS
static const QString T_DATA_PROPERTIES
OutputData< double > * getOutputData()
Definition: DataItem.h:36
virtual void setOutputData(OutputData< double > *data)=0
The given pointer becomes owned by this class!!
Definition: DataItem.cpp:24
void setFileName(const QString &filename)
Definition: DataItem.cpp:45
The ExternalProperty class defines custom QVariant property to carry the text, color and an identifie...
QString identifier() const
static const QString T_FIT_PARAMETERS_CONTAINER
Definition: FitSuiteItem.h:29
static const QString T_MINIMIZER
Definition: FitSuiteItem.h:30
QString id() const
virtual std::unique_ptr< Instrument > createInstrument() const =0
virtual void importMasks(const MaskContainerItem *)
void updateDataRange()
Sets min,max values for z-axis, if axes is not locked, and ranges are not yet set.
static const QString T_DATAVIEW
Definition: JobItem.h:52
static const QString T_SAMPLE
Definition: JobItem.h:47
static const QString T_OUTPUT
Definition: JobItem.h:50
InstrumentItem * instrumentItem()
Definition: JobItem.cpp:224
static const QString T_FIT_SUITE
Definition: JobItem.h:55
static const QString T_INSTRUMENT
Definition: JobItem.h:49
DataItem * dataItem()
Definition: JobItem.cpp:118
RealDataItem * realDataItem()
Definition: JobItem.cpp:259
bool isValidForFitting()
Definition: JobItem.cpp:165
static const QString T_REALDATA
Definition: JobItem.h:51
static const QString T_MATERIAL_CONTAINER
Definition: JobItem.h:48
static const QString P_INSTRUMENT_NAME
Definition: JobItem.h:38
static const QString T_MATERIALS
static const QString P_MAGNETIZATION
Definition: MaterialItem.h:26
The MinimizerContainerItem class holds collection of minimizers.
Definition: MinimizerItem.h:33
static const QString P_EXTERNAL_FIELD
OutputData * clone() const
Definition: OutputData.h:259
Item for non-uniform axis with specified coordinates.
The RealDataItem class represents intensity data imported from file and intended for fitting.
Definition: RealDataItem.h:35
MaskContainerItem * maskContainerItem()
Returns mask container item.
void setInstrumentId(const QString &id)
const OutputData< double > * nativeOutputData() const
void updateToInstrument(const InstrumentItem *instrument)
bool hasNativeData() const
void setNativeOutputData(OutputData< double > *data)
takes ownership of data
IntensityDataItem * intensityDataItem()
DataItem * nativeData()
DataItem * dataItem()
QString itemName() const
Get item name, return display name if no name is set.
bool is() const
Definition: SessionItem.h:175
QVariant value() const
Get value.
void setVisible(bool enabled)
Flags accessors.
bool setValue(QVariant value)
Set value, ensure that variant types match.
SessionItem * parent() const
Returns parent of this item.
Definition: SessionItem.cpp:73
SessionModel * model() const
Returns model of this item.
Definition: SessionItem.cpp:66
void setItemValue(const QString &tag, const QVariant &variant)
Directly set value of item under given tag.
QString modelType() const
Get model type.
SessionItem * getItem(const QString &tag="", int row=0) const
Returns item in given row of given tag.
SessionItem * getChildOfType(const QString &type) const
Returns the first child of the given type.
T * copyItem(const T *item_to_copy, SessionItem *new_parent=0, const QString &tag="")
Definition: SessionModel.h:136
T * insertItem(SessionItem *parent=nullptr, int row=-1, QString tag="")
Definition: SessionModel.h:125
An iterator for SimulationArea.
GroupItem * inclinationAxisGroup()
Definition: BeamItems.cpp:155
SpecularBeamItem * beamItem() const override
std::unique_ptr< IUnitConverter > createUnitConverter(const InstrumentItem *instrumentItem)
Creates a unit converter corresponding to the given instrument item.
std::string filename(const std::string &path)
Returns path without directory part ("Foo/Bar/Doz.int.gz" -> "Doz.int.gz")
QString createUuid()
Definition: GUIHelpers.cpp:242
QString instrumentDataFileName(const InstrumentItem &instrumentItem)
QString jobReferenceFileName(const JobItem &jobItem)
Constructs the name of the file with reference data.
QString jobNativeDataFileName(const JobItem &jobItem)
ComboProperty availableUnits(const IUnitConverter &converter)
void createDefaultDetectorMap(DataItem *intensityItem, const InstrumentItem *instrumentItem)
void setupJobItemForFit(JobItem *jobItem, const RealDataItem *realDataItem)
Setups JobItem for fit.
void setupJobItemInstrument(JobItem *jobItem, const InstrumentItem *from)
Properly copies instrument into job item.
void setupJobItemSampleData(JobItem *jobItem, const MultiLayerItem *sampleItem)
Properly copies sample and materials into JobItem.
const JobItem * findJobItem(const SessionItem *item)
Determines parenting JobItem of a given SessionItem.
void muteMagnetizationData(JobItem *jobItem)
void copyRealDataItem(JobItem *jobItem, const RealDataItem *realDataItem)
Copy RealDataItem to jobItem intended for fitting.
void initDataView(JobItem *jobItem)
Initializes Data1DViewItem and assigns it to the passed JobItem.
void setupJobItemOutput(JobItem *jobItem)
Setup items intended for storing results of the job.
MaterialItem * findMaterial(const ExternalProperty &material_property)