BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
SpecularPlot.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file GUI/coregui/Views/SpecularDataWidgets/SpecularPlot.cpp
6 //! @brief Implements class SpecularPlot
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/Math/Constants.h"
23 
24 namespace {
25 const int replot_update_interval = 10;
26 
27 int bin(double x, const QCPGraph* graph);
28 } // namespace
29 
31  : ScientificPlot(parent, PLOT_TYPE::Plot1D)
32  , m_custom_plot(new QCustomPlot)
33  , m_update_timer(new UpdateTimer(replot_update_interval, this))
34  , m_block_update(true)
35 {
36  initPlot();
37 
38  QVBoxLayout* vlayout = new QVBoxLayout(this);
39  vlayout->setContentsMargins(0, 0, 0, 0);
40  vlayout->setSpacing(0);
41  vlayout->addWidget(m_custom_plot);
42  setLayout(vlayout);
43 
45 }
46 
47 PlotEventInfo SpecularPlot::eventInfo(double xpos, double ypos) const
48 {
49  PlotEventInfo result(plotType());
50  if (!specularItem())
51  return result;
52 
53  result.setX(xpos);
54  result.setValue(ypos);
55 
56  result.setInAxesRange(axesRangeContains(xpos, ypos));
57  result.setNx(bin(result.x(), m_custom_plot->graph()));
58 
59  return result;
60 }
61 
62 void SpecularPlot::setLog(bool log)
63 {
66 }
67 
69 {
71 }
72 
73 void SpecularPlot::onPropertyChanged(const QString& property_name)
74 {
75  if (m_block_update)
76  return;
77 
78  if (property_name == DataItem::P_AXES_UNITS) {
80  replot();
81  }
82 }
83 
84 void SpecularPlot::onXaxisRangeChanged(QCPRange newRange)
85 {
86  m_block_update = true;
87  specularItem()->setLowerX(newRange.lower);
88  specularItem()->setUpperX(newRange.upper);
89  m_block_update = false;
90 }
91 
92 void SpecularPlot::onYaxisRangeChanged(QCPRange newRange)
93 {
94  m_block_update = true;
95  specularItem()->setLowerY(newRange.lower);
96  specularItem()->setUpperY(newRange.upper);
97  m_block_update = false;
98 }
99 
101 {
102  m_custom_plot->replot();
103 }
104 
106 {
108 
110  [this](const QString& name) { onPropertyChanged(name); }, this);
111 
113  [this](SessionItem* item, const QString name) {
114  if (item->modelType() == "BasicAxis" || item->modelType() == "AmplitudeAxis")
116  },
117  this);
118 
119  specularItem()->mapper()->setOnValueChange([this]() { setPlotFromItem(this->specularItem()); },
120  this);
121 
122  setConnected(true);
123 }
124 
126 {
127  setConnected(false);
128 }
129 
131 {
132  m_custom_plot->addGraph();
133 
134  QPen pen(QColor(0, 0, 255, 200));
135  m_custom_plot->graph()->setLineStyle(QCPGraph::lsLine);
136  m_custom_plot->graph()->setPen(pen);
137 
138  m_custom_plot->xAxis->setTickLabelFont(
139  QFont(QFont().family(), Constants::plot_tick_label_size()));
140  m_custom_plot->yAxis->setTickLabelFont(
141  QFont(QFont().family(), Constants::plot_tick_label_size()));
142 }
143 
144 void SpecularPlot::setConnected(bool isConnected)
145 {
146  setAxesRangeConnected(isConnected);
147  setUpdateTimerConnected(isConnected);
148 }
149 
151 {
152  if (isConnected) {
153  connect(m_custom_plot->xAxis,
154  static_cast<void (QCPAxis::*)(const QCPRange&)>(&QCPAxis::rangeChanged), this,
155  &SpecularPlot::onXaxisRangeChanged, Qt::UniqueConnection);
156 
157  connect(m_custom_plot->yAxis,
158  static_cast<void (QCPAxis::*)(const QCPRange&)>(&QCPAxis::rangeChanged), this,
159  &SpecularPlot::onYaxisRangeChanged, Qt::UniqueConnection);
160 
161  } else {
162  disconnect(m_custom_plot->xAxis,
163  static_cast<void (QCPAxis::*)(const QCPRange&)>(&QCPAxis::rangeChanged), this,
165 
166  disconnect(m_custom_plot->yAxis,
167  static_cast<void (QCPAxis::*)(const QCPRange&)>(&QCPAxis::rangeChanged), this,
169  }
170 }
171 
173 {
174  if (isConnected)
176  Qt::UniqueConnection);
177  else
179 }
180 
182 {
184 
185  m_block_update = true;
186 
187  m_custom_plot->graph(0)->data()->clear();
191 
192  replot();
193 
194  m_block_update = false;
195 }
196 
198 {
199  m_custom_plot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
200  m_custom_plot->axisRect()->setupFullAxesBox(true);
201 
202  setAxesRangeConnected(false);
203  m_custom_plot->xAxis->setRange(item->getLowerX(), item->getUpperX());
204  m_custom_plot->yAxis->setRange(item->getLowerY(), item->getUpperY());
205  setLog(item->isLog());
206  setAxesRangeConnected(true);
207 }
208 
210 {
211  setLabel(item->xAxisItem(), m_custom_plot->xAxis, item->getXaxisTitle());
212  setLabel(item->yAxisItem(), m_custom_plot->yAxis, item->getYaxisTitle());
213 }
214 
215 void SpecularPlot::setLabel(const BasicAxisItem* item, QCPAxis* axis, QString label)
216 {
217  ASSERT(item && axis);
219  axis->setLabel(std::move(label));
220  else
221  axis->setLabel(QString());
222 }
223 
225 {
226  ASSERT(item);
227  auto data = item->getOutputData();
228  if (!data)
229  return;
230 
231  for (size_t i = 0, size = data->getAllocatedSize(); i < size; ++i) {
232  double x = data->getAxisValue(i, 0);
233  double y = data->operator[](i);
234  m_custom_plot->graph()->addData(x, y);
235  }
236 }
237 
239 {
240  return const_cast<SpecularDataItem*>(static_cast<const SpecularPlot*>(this)->specularItem());
241 }
242 
244 {
245  const auto result = dynamic_cast<const SpecularDataItem*>(currentItem());
246  return result;
247 }
248 
249 void SpecularPlot::modifyAxesProperties(const QString& axisName, const QString& propertyName)
250 {
251  if (m_block_update)
252  return;
253 
254  if (propertyName == BasicAxisItem::P_TITLE
255  || propertyName == BasicAxisItem::P_TITLE_IS_VISIBLE) {
257  replot();
258  }
259 
260  if (axisName == SpecularDataItem::P_XAXIS) {
261  if (propertyName == BasicAxisItem::P_MIN_DEG || propertyName == BasicAxisItem::P_MAX_DEG) {
262  setAxesRangeConnected(false);
263  m_custom_plot->xAxis->setRange(specularItem()->getLowerX(),
264  specularItem()->getUpperX());
265  setAxesRangeConnected(true);
266  replot();
267  }
268  } else if (axisName == SpecularDataItem::P_YAXIS) {
269  if (propertyName == BasicAxisItem::P_MIN_DEG || propertyName == BasicAxisItem::P_MAX_DEG) {
270  setAxesRangeConnected(false);
271  m_custom_plot->yAxis->setRange(specularItem()->getLowerY(),
272  specularItem()->getUpperY());
273  setAxesRangeConnected(true);
274  replot();
275  } else if (propertyName == AmplitudeAxisItem::P_IS_LOGSCALE) {
276  setLog(specularItem()->isLog());
277  replot();
278  }
279  }
280 }
281 
283 {
285 }
286 
287 namespace {
288 int bin(double x, const QCPGraph* graph)
289 {
290  const int key_start = graph->findBegin(x);
291  const int key_end = graph->findBegin(x, false); // false = do not expand range
292  if (key_end == key_start || key_end == graph->dataCount())
293  return key_start;
294  return (x - graph->dataSortKey(key_start)) <= (graph->dataSortKey(key_end) - x) ? key_start
295  : key_end;
296 }
297 } // namespace
#define ASSERT(condition)
Definition: Assert.h:31
Defines various axis items.
Defines ColorMapUtils namespace.
Defines M_PI and some more mathematical constants.
Defines the class PlotEventInfo.
Defines class SpecularDataItem.
Defines class SpecularPlot.
Defines class UpdateTimer.
static const QString P_IS_LOGSCALE
Definition: AxesItems.h:55
static const QString P_MAX_DEG
Definition: AxesItems.h:28
static const QString P_TITLE
Definition: AxesItems.h:29
static const QString P_TITLE_IS_VISIBLE
Definition: AxesItems.h:30
static const QString P_MIN_DEG
Definition: AxesItems.h:27
OutputData< double > * getOutputData()
Definition: DataItem.h:36
static const QString P_AXES_UNITS
Definition: DataItem.h:34
void setOnValueChange(std::function< void(void)> f, const void *caller=0)
Definition: ModelMapper.cpp:30
void setOnChildPropertyChange(std::function< void(SessionItem *, QString)> f, const void *caller=0)
Calls back on child property change, report childItem and property name.
Definition: ModelMapper.cpp:49
void setOnPropertyChange(std::function< void(QString)> f, const void *caller=0)
Definition: ModelMapper.cpp:35
double getAxisValue(size_t global_index, size_t i_selected_axis) const
Returns the value of selected axis for given global_index.
Definition: OutputData.h:430
The Plot1D class presents data of several 1D DataItems contained in a Data1DViewItem.
Definition: Plot1D.h:32
Contains parameters of mouse position in 1D or 2D plot.
Definition: PlotEventInfo.h:26
double x() const
Definition: PlotEventInfo.h:42
void setNx(int nx)
Definition: PlotEventInfo.h:49
void setInAxesRange(bool flag)
Definition: PlotEventInfo.h:35
void setX(double x)
Definition: PlotEventInfo.h:41
void setValue(double value)
Definition: PlotEventInfo.h:46
Common interface for plot-descriptor interaction.
PLOT_TYPE plotType() const
Returns the type of current plot.
bool axesRangeContains(double xpos, double ypos) const
Returns true if axes rectangle contains given in axes coordinates.
void setMouseTrackingEnabled(bool enable)
Tracks move events (used when showing profile histograms and printing status string)
SessionItem * currentItem()
QString itemName() const
Get item name, return display name if no name is set.
QVariant getItemValue(const QString &tag) const
Directly access value of item under given tag.
ModelMapper * mapper()
Returns the current model mapper of this item. Creates new one if necessary.
QString modelType() const
Get model type.
double getLowerY() const
returns lower and upper zoom ranges of y-axis
QString getXaxisTitle() const
void setUpperY(double value)
void setUpperX(double value)
void setLowerX(double value)
static const QString P_YAXIS
static const QString P_XAXIS
void setLowerY(double value)
double getUpperY() const
double getLowerX() const
returns lower and upper zoom ranges of x-axis
QString getYaxisTitle() const
void resetView()
Set axes viewport to original data.
double getUpperX() const
const AmplitudeAxisItem * yAxisItem() const
const BasicAxisItem * xAxisItem() const
The SpecularPlot class presents 1D intensity data from SpecularDataItem.
Definition: SpecularPlot.h:32
bool m_block_update
Definition: SpecularPlot.h:108
void initPlot()
creates and initializes the color map
void setAxesRangeConnected(bool isConnected)
Connects/disconnects signals related to SpecularPlot's X,Y axes rectangle change.
void setConnected(bool isConnected)
void setPlotFromItem(SpecularDataItem *intensityItem)
Sets initial state of SpecularPlot to match given intensity item.
void setAxesLabelsFromItem(SpecularDataItem *item)
Sets X,Y axes labels from item.
SpecularPlot(QWidget *parent=nullptr)
void setLog(bool log)
sets logarithmic scale
PlotEventInfo eventInfo(double xpos, double ypos) const override
Returns PlotEventInfo corresponding to given axes coordinates.
UpdateTimer * m_update_timer
Definition: SpecularPlot.h:106
void setUpdateTimerConnected(bool isConnected)
void onXaxisRangeChanged(QCPRange newRange)
Propagate xmin, xmax back to IntensityDataItem.
void setAxesRangeFromItem(SpecularDataItem *item)
Sets (xmin,xmax) and (ymin,ymax) of SpecularPlot from specular item.
void modifyAxesProperties(const QString &axisName, const QString &propertyName)
void onTimeToReplot()
Replots SpecularPlot.
void setLabel(const BasicAxisItem *item, QCPAxis *axis, QString label)
Sets label to axis.
void onPropertyChanged(const QString &property_name)
updates plot depending on IntensityDataItem properties
QCustomPlot * m_custom_plot
Definition: SpecularPlot.h:105
void setDataFromItem(SpecularDataItem *item)
Sets the intensity values to SpecularPlot.
void subscribeToItem() override
SpecularDataItem * specularItem()
void replot()
Schedule replot for later execution by onTimeReplot() slot.
void unsubscribeFromItem() override
void onYaxisRangeChanged(QCPRange newRange)
Propagate ymin, ymax back to IntensityDataItem.
void resetView()
reset all axes min,max to initial value
The UpdateTimer class accumulates update requests during certain period of time, and at the end of th...
Definition: UpdateTimer.h:27
void scheduleUpdate()
Definition: UpdateTimer.cpp:42
void timeToUpdate()
void setLogz(QCPColorScale *scale, bool isLogz)
int plot_tick_label_size()
QString const & name(EShape k)
Definition: particles.cpp:21
Defines various constants for plotting.