BornAgain  1.19.79
Simulate and fit neutron and x-ray scattering at grazing incidence
ProjectionsPlot.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file GUI/View/Projection/ProjectionsPlot.cpp
6 //! @brief Defines class ProjectionCanvas
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 "Base/Axis/IAxis.h"
17 #include "Device/Data/Datafield.h"
24 #include <qcustomplot.h>
25 
26 #include <boost/polymorphic_cast.hpp>
27 #include <utility>
28 
29 using boost::polymorphic_downcast;
30 
31 ProjectionsPlot::ProjectionsPlot(QString projectionType, QWidget* parent)
32  : SessionItemWidget(parent)
33  , m_projectionType(std::move(projectionType))
34  , m_customPlot(new QCustomPlot)
35  , m_block_plot_update(false)
36 {
37  auto* vlayout = new QVBoxLayout(this);
38  vlayout->setMargin(0);
39  vlayout->setSpacing(0);
40  vlayout->addWidget(m_customPlot);
41  m_customPlot->setAttribute(Qt::WA_NoMousePropagation, false);
42  setLayout(vlayout);
43 
44  m_customPlot->xAxis->setTickLabelFont(
45  QFont(QFont().family(), GUI::Constants::plot_tick_label_size()));
46  m_customPlot->yAxis->setTickLabelFont(
47  QFont(QFont().family(), GUI::Constants::plot_tick_label_size()));
48 
50 }
51 
53 {
55 }
56 
57 void ProjectionsPlot::onMarginsChanged(double left, double right)
58 {
59  QMargins orig = m_customPlot->axisRect()->margins();
60  m_customPlot->axisRect()->setMargins(QMargins(left, orig.top(), right, orig.bottom()));
61  replot();
62 }
63 
65 {
66  // Update projection plot on new item appearance
68  [this](SessionItem* item) {
69  if (item)
71  },
72  this);
73 
74  // Remove projection plot
76  [this](SessionItem* item) { clearProjection(item); }, this);
77 
78  // Update projection position
80  [this](SessionItem* item, const QString& name) { onProjectionPropertyChanged(item, name); },
81  this);
82 
83  // Values of intensity changed, regenerate everything.
85  [this]() {
88  },
89  this);
90 
91  // IntensityItem property (e.g. interpolation changed)
93  [this](const QString& name) { onIntensityItemPropertyChanged(name); }, this);
94 
95  // Update to changed IntensityDataItem axes
97  [this](SessionItem* item, const QString name) {
98  if (item->modelType() == BasicAxisItem::M_TYPE
101  },
102  this);
103 
106 }
107 
109 {
112 }
113 
114 void ProjectionsPlot::onProjectionPropertyChanged(SessionItem* item, const QString& /*property*/)
115 {
117  return;
118 
119  m_block_plot_update = true;
120 
121  if (auto* graph = graphForItem(item))
122  setGraphFromItem(graph, item);
123  replot();
124 
125  m_block_plot_update = false;
126 }
127 
129 {
130  auto* result = dynamic_cast<IntensityDataItem*>(currentItem());
131  ASSERT(result);
132  return result;
133 }
134 
136 {
138  ASSERT(result);
139  return result;
140 }
141 
142 QVector<SessionItem*> ProjectionsPlot::projectionItems()
143 {
145 }
146 
148 {
149  if (item->modelType() != m_projectionType)
150  return nullptr;
151 
152  QCPGraph* graph = m_item_to_graph[item];
153  if (!graph) {
154  graph = m_customPlot->addGraph();
155  QPen pen;
156  pen.setColor(QColor(0, 0, 255, 200));
157  graph->setLineStyle(intensityItem()->isInterpolated() ? QCPGraph::lsLine
158  : QCPGraph::lsStepCenter);
159  graph->setPen(pen);
160  m_item_to_graph[item] = graph;
161  }
162 
163  return graph;
164 }
165 
167 {
168  if (currentItem())
170 }
171 
172 //! Creates cached 2D histogram for later projection calculations.
173 
175 {
176  m_field.reset(intensityItem()->getDatafield());
177  updateAxesRange();
178  updateAxesTitle();
179  setLogz(intensityItem()->isLogz());
180 }
181 
182 //! Runs through all projection items and generates missed plots.
183 
185 {
187  return;
188 
189  m_block_plot_update = true;
190 
191  for (auto* projItem : projectionItems())
192  setGraphFromItem(graphForItem(projItem), projItem);
193 
194  replot();
195 
196  m_block_plot_update = false;
197 }
198 
199 //! Updates canva's axes to match current zoom level of IntensityDataItem
200 
202 {
203  if (isHorizontalType())
205  else
207 
209 }
210 
212 {
213  if (isHorizontalType())
214  m_customPlot->xAxis->setLabel(intensityItem()->getXaxisTitle());
215  else
216  m_customPlot->xAxis->setLabel(intensityItem()->getYaxisTitle());
217 }
218 
219 //! Clears all graphs corresponding to projection items.
220 
222 {
223  m_block_plot_update = true;
224 
225  m_customPlot->clearPlottables();
226  m_item_to_graph.clear();
227 
228  replot();
229 
230  m_block_plot_update = false;
231 }
232 
233 //! Removes plot corresponding to given projection item.
234 
236 {
237  if (auto* graph = graphForItem(item)) {
238  m_block_plot_update = true;
239  m_customPlot->removePlottable(graph);
240  m_item_to_graph.remove(item);
241  replot();
242  m_block_plot_update = false;
243  }
244 }
245 
246 //! Updates projection appearance (line style, etc)
247 
248 void ProjectionsPlot::onIntensityItemPropertyChanged(const QString& propertyName)
249 {
251  setInterpolate(intensityItem()->isInterpolated());
252  replot();
253  }
254 }
255 
256 //! Updates zoom of projections in accordance with IntensityDataItem.
257 
258 void ProjectionsPlot::onAxisPropertyChanged(const QString& axisName, const QString& propertyName)
259 {
260  Q_UNUSED(axisName);
261 
262  if (BasicAxisItem::isBoundsPropertiesName(propertyName))
263  updateAxesRange();
264  else if (BasicAxisItem::isTitlePropertyName(propertyName))
265  updateAxesTitle();
266  else if (AmplitudeAxisItem::isLogScalePropertyName(propertyName))
267  setLogz(intensityItem()->isLogz());
268 
269  replot();
270 }
271 
272 //! Sets the data to graph from given projection iten.
273 
274 void ProjectionsPlot::setGraphFromItem(QCPGraph* graph, SessionItem* item)
275 {
276  std::unique_ptr<Datafield> field;
277 
278  // TODO: merge with very similar code in SaveProjectionsAssistant::projectionsData
279  if (item->modelType() == HorizontalLineItem::M_TYPE) {
280  double value = polymorphic_downcast<HorizontalLineItem*>(item)->posY();
281  field.reset(m_field->xProjection(value));
282  } else {
283  double value = polymorphic_downcast<VerticalLineItem*>(item)->posX();
284  field.reset(m_field->yProjection(value));
285  }
286 
287 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
288  auto centers = field->axis(0).binCenters();
289  auto values = field->flatVector();
290  graph->setData(QVector<double>(centers.begin(), centers.end()),
291  QVector<double>(values.begin(), values.end()));
292 #else
293  graph->setData(QVector<double>::fromStdVector(hist->binCenters()),
294  QVector<double>::fromStdVector(hist->binValues()));
295 #endif
296 }
297 
298 void ProjectionsPlot::setInterpolate(bool isInterpolated)
299 {
300  for (auto* graph : m_item_to_graph)
301  graph->setLineStyle(isInterpolated ? QCPGraph::lsLine : QCPGraph::lsStepCenter);
302 }
303 
304 void ProjectionsPlot::setLogz(bool isLogz)
305 {
307 }
308 
310 {
311  m_customPlot->replot();
312 }
313 
314 //! Returns true, if widget is intended for horizontal projections.
315 
317 {
319 }
Defines various axis items.
Defines class IntensityDataItem.
Defines MaskItems classes.
Defines various constants for plotting.
Defines items related to projections over color map.
Defines class ProjectionsPlot.
Defines RangeUtils namespace.
static bool isLogScalePropertyName(const QString &name)
Definition: AxesItems.cpp:193
static constexpr auto M_TYPE
Definition: AxesItems.h:81
static bool isBoundsPropertiesName(const QString &name)
either lower bound or upper bound property name
Definition: AxesItems.cpp:75
static bool isTitlePropertyName(const QString &name)
Definition: AxesItems.cpp:95
static constexpr auto M_TYPE
Definition: AxesItems.h:35
static constexpr auto M_TYPE
Definition: MaskItems.h:147
static bool isInterpolatedPropertyName(const QString &name)
ProjectionContainerItem * projectionContainerItem()
void unsubscribe(const void *caller)
Cancels all subscriptions of given caller.
Definition: ModelMapper.cpp:78
void setOnAboutToRemoveChild(std::function< void(SessionItem *)> f, const void *caller=nullptr)
Definition: ModelMapper.cpp:72
void setOnChildrenChange(std::function< void(SessionItem *)> f, const void *caller=nullptr)
Calls back when number of children has changed, reports newChild. newChild == nullptr denotes the cas...
Definition: ModelMapper.cpp:62
void setOnPropertyChange(std::function< void(QString)> f, const void *caller=nullptr)
Definition: ModelMapper.cpp:39
void setOnValueChange(std::function< void(void)> f, const void *caller=nullptr)
Definition: ModelMapper.cpp:34
void setOnChildPropertyChange(std::function< void(SessionItem *, QString)> f, const void *caller=nullptr)
Calls back on child property change, report childItem and property name.
Definition: ModelMapper.cpp:53
A container to hold ProjectionItems, intended to store projections of color map on X,...
~ProjectionsPlot() override
QCustomPlot * m_customPlot
void updateProjectionsData()
Creates cached 2D histogram for later projection calculations.
IntensityDataItem * intensityItem()
std::unique_ptr< Datafield > m_field
void onIntensityItemPropertyChanged(const QString &propertyName)
Updates projection appearance (line style, etc)
QVector< SessionItem * > projectionItems()
void clearProjection(SessionItem *item)
Removes plot corresponding to given projection item.
void setGraphFromItem(QCPGraph *graph, SessionItem *item)
Sets the data to graph from given projection iten.
void onMarginsChanged(double left, double right)
QString m_projectionType
void unsubscribeFromItem() override
void unsubscribeFromChildren()
void updateAxesRange()
Updates canva's axes to match current zoom level of IntensityDataItem.
void setLogz(bool isLogz)
QCPGraph * graphForItem(SessionItem *item)
void subscribeToItem() override
QMap< SessionItem *, QCPGraph * > m_item_to_graph
bool isHorizontalType()
Returns true, if widget is intended for horizontal projections.
void updateProjections()
Runs through all projection items and generates missed plots.
ProjectionContainerItem * projectionContainerItem()
void onAxisPropertyChanged(const QString &axisName, const QString &propertyName)
Updates zoom of projections in accordance with IntensityDataItem.
ProjectionsPlot(QString projectionType, QWidget *parent=nullptr)
void setInterpolate(bool isInterpolated)
void clearProjections()
Clears all graphs corresponding to projection items.
void onProjectionPropertyChanged(SessionItem *item, const QString &property)
The SessionItemWidget class is a base for all widgets representing the content of SessionItem....
SessionItem * currentItem()
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.
QVector< SessionItem * > childrenOfType(const QString &model_type) const
Returns a vector of all children of the given type.
ModelMapper * mapper()
Returns the current model mapper of this item. Creates new one if necessary.
QString modelType() const
Get model type.
int plot_tick_label_size()
Definition: PlotConstants.h:23
QString const & name(EShape k)
Definition: particles.cpp:20
QCPRange itemZoomY(const IntensityDataItem *item)
Returns y-axis vizible range (zoom).
Definition: RangeUtils.cpp:94
void setLogz(QCPColorScale *scale, bool isLogz)
Definition: RangeUtils.cpp:110
void setDefaultMargins(QCustomPlot *customPlot)
Sets default margins for axes rectangle plot.
Definition: RangeUtils.cpp:138
QCPRange itemDataZoom(const IntensityDataItem *item)
Returns z-axis visible range (zoom).
Definition: RangeUtils.cpp:105
QCPRange itemZoomX(const IntensityDataItem *item)
Returns x-axis vizible range (zoom).
Definition: RangeUtils.cpp:84