Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
QmitkPlotWidget.cpp
Go to the documentation of this file.
1 /*===================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
17 #include <iostream>
18 #include <qlayout.h>
19 
20 #include <qwt_interval_symbol.h>
21 #include <qwt_point_data.h>
22 
23 #include "QmitkPlotWidget.h"
24 
25 QmitkPlotWidget::QmitkPlotWidget(QWidget *parent, const char *title, const char *, Qt::WindowFlags f)
26  : QWidget(parent, f)
27 {
28  auto boxLayout = new QVBoxLayout(this);
29  m_Plot = new QwtPlot(QwtText(title), this);
30  m_Plot->setCanvasBackground(Qt::white);
31  boxLayout->addWidget(m_Plot);
32 }
33 
35 {
36  this->Clear();
37  delete m_Plot;
38 }
39 
41 {
42  return m_Plot;
43 }
44 
45 void QmitkPlotWidget::SetLegend(QwtLegend *legend, QwtPlot::LegendPosition pos, double ratio)
46 {
47  m_Plot->insertLegend(legend, pos, ratio);
48 }
49 
50 void QmitkPlotWidget::SetLegendAttribute(unsigned int curveId, const QwtPlotCurve::LegendAttribute &attribute)
51 {
52  std::get<0>(m_PlotCurveVector[curveId])->setLegendAttribute(attribute);
53 }
54 
55 unsigned int QmitkPlotWidget::InsertCurve(const char *title, QColor color)
56 {
57  QwtText qwt_title = QwtText(title);
58  qwt_title.setColor(color);
59  qwt_title.setPaintAttribute(QwtText::PaintUsingTextColor);
60 
61  QwtPlotCurve *curve = new QwtPlotCurve(qwt_title);
62  QwtPlotIntervalCurve *xErrors = new QwtPlotIntervalCurve();
63  QwtPlotIntervalCurve *yErrors = new QwtPlotIntervalCurve();
64 
65  auto tuple = std::make_tuple(curve, xErrors, yErrors);
66  m_PlotCurveVector.push_back(tuple);
67 
68  std::get<0>(m_PlotCurveVector.back())->attach(m_Plot);
69  std::get<1>(m_PlotCurveVector.back())->attach(m_Plot);
70  std::get<2>(m_PlotCurveVector.back())->attach(m_Plot);
71 
72  // error curves should not show up on the legend
73  std::get<1>(m_PlotCurveVector.back())->setItemAttribute(QwtPlotItem::Legend, false);
74  std::get<2>(m_PlotCurveVector.back())->setItemAttribute(QwtPlotItem::Legend, false);
75 
76  return static_cast<unsigned int>(m_PlotCurveVector.size() - 1);
77 }
78 
79 void QmitkPlotWidget::SetPlotTitle(const QwtText &qwt_title)
80 {
81  this->m_Plot->setTitle(qwt_title);
82 }
83 
84 void QmitkPlotWidget::SetPlotTitle(const char *title)
85 {
86  QwtText qwt_title_text(title);
87  this->SetPlotTitle(qwt_title_text);
88 }
89 
90 void QmitkPlotWidget::SetAxisTitle(int axis, const char *title)
91 {
92  m_Plot->setAxisTitle(axis, title);
93 }
94 
95 bool QmitkPlotWidget::SetCurveData(unsigned int curveId,
96  const QmitkPlotWidget::DataVector &xValues,
97  const QmitkPlotWidget::DataVector &yValues)
98 {
99  if (xValues.size() != yValues.size())
100  {
101  std::cerr << "Sizes of data arrays don't match." << std::endl;
102  return false;
103  }
104  double *rawDataX = ConvertToRawArray(xValues);
105  double *rawDataY = ConvertToRawArray(yValues);
106  std::get<0>(m_PlotCurveVector[curveId])
107  ->setSamples(new QwtPointArrayData(rawDataX, rawDataY, static_cast<int>(xValues.size())));
108  delete[] rawDataX;
109  delete[] rawDataY;
110  return true;
111 }
112 
113 bool QmitkPlotWidget::SetCurveData(unsigned int curveId,
114  const DataVector &xValues,
115  const DataVector &yValues,
116  const DataVector &yLowerError,
117  const DataVector &yUpperError)
118 {
119  bool success = true;
120  success = success && this->SetCurveData(curveId, xValues, yValues);
121  success = success && this->AddErrorIntervalCurve(curveId, yLowerError, yUpperError, false);
122 
123  return success;
124 }
125 
126 bool QmitkPlotWidget::SetCurveData(unsigned int curveId,
127  const DataVector &xValues,
128  const DataVector &yValues,
129  const DataVector &xLowerError,
130  const DataVector &xUpperError,
131  const DataVector &yLowerError,
132  const DataVector &yUpperError)
133 {
134  bool success = true;
135  success = success && this->SetCurveData(curveId, xValues, yValues);
136  success = success && this->AddErrorIntervalCurve(curveId, xLowerError, xUpperError, true);
137  success = success && this->AddErrorIntervalCurve(curveId, yLowerError, yUpperError, false);
138 
139  return success;
140 }
141 
142 bool QmitkPlotWidget::SetCurveData(unsigned int curveId, const XYDataVector &data)
143 {
144  double *rawDataX = ConvertToRawArray(data, 0);
145  double *rawDataY = ConvertToRawArray(data, 1);
146  std::get<0>(m_PlotCurveVector[curveId])
147  ->setData(new QwtPointArrayData(rawDataX, rawDataY, static_cast<int>(data.size())));
148  delete[] rawDataX;
149  delete[] rawDataY;
150  return true;
151 }
152 
153 void QmitkPlotWidget::SetCurvePen(unsigned int curveId, const QPen &pen)
154 {
155  std::get<0>(m_PlotCurveVector[curveId])->setPen(pen);
156  std::get<0>(m_PlotCurveVector[curveId])->setLegendAttribute(QwtPlotCurve::LegendShowLine);
157 }
158 
159 void QmitkPlotWidget::SetCurveBrush(unsigned int curveId, const QBrush &brush)
160 {
161  std::get<0>(m_PlotCurveVector[curveId])->setBrush(brush);
162  std::get<0>(m_PlotCurveVector[curveId])->setLegendAttribute(QwtPlotCurve::LegendShowBrush);
163 }
164 
165 void QmitkPlotWidget::SetCurveTitle(unsigned int, const char *title)
166 {
167  m_Plot->setTitle(title);
168 }
169 
170 void QmitkPlotWidget::SetCurveStyle(unsigned int curveId, const QwtPlotCurve::CurveStyle style)
171 {
172  std::get<0>(m_PlotCurveVector[curveId])->setStyle(style);
173 }
174 
175 void QmitkPlotWidget::SetCurveSymbol(unsigned int curveId, QwtSymbol *symbol)
176 {
177  std::get<0>(m_PlotCurveVector[curveId])->setSymbol(symbol);
178  std::get<0>(m_PlotCurveVector[curveId])->setLegendAttribute(QwtPlotCurve::LegendShowSymbol);
179 }
180 
181 void QmitkPlotWidget::SetCurveAntialiasingOn(unsigned int curveId)
182 {
183  std::get<0>(m_PlotCurveVector[curveId])->setRenderHint(QwtPlotItem::RenderAntialiased);
184 }
185 
187 {
188  std::get<0>(m_PlotCurveVector[curveId])->setRenderHint(QwtPlotItem::RenderAntialiased, false);
189 }
190 
191 void QmitkPlotWidget::SetErrorPen(unsigned int curveId, const QPen &pen)
192 {
193  std::get<1>(m_PlotCurveVector[curveId])->setPen(pen);
194  QwtIntervalSymbol *errorBar = new QwtIntervalSymbol(QwtIntervalSymbol::Bar);
195  errorBar->setPen(pen);
196  std::get<1>(m_PlotCurveVector[curveId])->setSymbol(errorBar);
197  std::get<2>(m_PlotCurveVector[curveId])->setPen(pen);
198  errorBar = new QwtIntervalSymbol(QwtIntervalSymbol::Bar);
199  errorBar->setPen(pen);
200  std::get<2>(m_PlotCurveVector[curveId])->setSymbol(errorBar);
201 }
202 
203 void QmitkPlotWidget::SetErrorStyleSymbols(unsigned int curveId, bool drawSmybols)
204 {
205  if (drawSmybols)
206  {
207  std::get<1>(m_PlotCurveVector[curveId])->setStyle(QwtPlotIntervalCurve::NoCurve);
208  QwtIntervalSymbol *errorBar = new QwtIntervalSymbol(QwtIntervalSymbol::Bar);
209  errorBar->setPen(std::get<1>(m_PlotCurveVector[curveId])->pen());
210  std::get<1>(m_PlotCurveVector[curveId])->setSymbol(errorBar);
211  std::get<2>(m_PlotCurveVector[curveId])->setStyle(QwtPlotIntervalCurve::NoCurve);
212  errorBar = new QwtIntervalSymbol(QwtIntervalSymbol::Bar);
213  errorBar->setPen(std::get<2>(m_PlotCurveVector[curveId])->pen());
214  std::get<2>(m_PlotCurveVector[curveId])->setSymbol(errorBar);
215  }
216  else
217  {
218  std::get<1>(m_PlotCurveVector[curveId])->setStyle(QwtPlotIntervalCurve::Tube);
219  std::get<1>(m_PlotCurveVector[curveId])->setSymbol(nullptr);
220  std::get<2>(m_PlotCurveVector[curveId])->setStyle(QwtPlotIntervalCurve::Tube);
221  std::get<2>(m_PlotCurveVector[curveId])->setSymbol(nullptr);
222  }
223 }
224 
226 {
227  m_Plot->replot();
228 }
229 
231 {
232  m_Plot->detachItems();
233  m_PlotCurveVector.clear();
234  m_PlotCurveVector.resize(0);
235 }
236 
238 {
239  auto raw = new double[values.size()];
240  for (unsigned int i = 0; i < values.size(); ++i)
241  raw[i] = values[i];
242  return raw;
243 }
244 
245 double *QmitkPlotWidget::ConvertToRawArray(const QmitkPlotWidget::XYDataVector &values, unsigned int component)
246 {
247  auto raw = new double[values.size()];
248  for (unsigned int i = 0; i < values.size(); ++i)
249  {
250  switch (component)
251  {
252  case (0):
253  raw[i] = values[i].first;
254  break;
255  case (1):
256  raw[i] = values[i].second;
257  break;
258  default:
259  std::cout << "Component must be either 0 or 1." << std::endl;
260  }
261  }
262  return raw;
263 }
264 
265 bool QmitkPlotWidget::AddErrorIntervalCurve(unsigned int curveId,
266  const DataVector &lessError,
267  const DataVector &moreError,
268  bool isXError)
269 {
270  const QwtSeriesData<QPointF> *curveSeriesData = std::get<0>(this->m_PlotCurveVector[curveId])->data();
271 
272  size_t size = curveSeriesData->size();
273 
274  if (size != lessError.size() || size != moreError.size())
275  {
276  std::cerr << "Sizes of data arrays don't match." << std::endl;
277  return false;
278  }
279 
280  QVector<QwtIntervalSample> samples;
281  QwtIntervalSample *sample;
282  QwtPlotIntervalCurve *curve;
283 
284  if (isXError)
285  {
286  curve = std::get<1>(m_PlotCurveVector[curveId]);
287  }
288  else
289  {
290  curve = std::get<2>(m_PlotCurveVector[curveId]);
291  }
292 
293  for (unsigned int index = 0; index < size; ++index)
294  {
295  qreal xValue = curveSeriesData->sample(index).x();
296  qreal yValue = curveSeriesData->sample(index).y();
297  if (isXError)
298  {
299  sample = new QwtIntervalSample(xValue, xValue - lessError[index], xValue + moreError[index]);
300  }
301  else
302  {
303  sample = new QwtIntervalSample(xValue, yValue - lessError[index], yValue + moreError[index]);
304  }
305  samples.push_back(*sample);
306  }
307 
308  curve->setSamples(samples);
309  curve->setStyle(QwtPlotIntervalCurve::NoCurve);
310 
311  QwtIntervalSymbol *errorBar = new QwtIntervalSymbol(QwtIntervalSymbol::Bar);
312  errorBar->setPen(QPen(Qt::black));
313  curve->setSymbol(errorBar);
314 
315  if (isXError)
316  {
317  curve->setOrientation(Qt::Horizontal);
318  }
319  else
320  {
321  curve->setOrientation(Qt::Vertical);
322  }
323 
324  return true;
325 }
void SetPlotTitle(const QwtText &qwt_title)
std::vector< ScalarType > DataVector
std::vector< std::pair< double, double > > XYDataVector
void SetCurveAntialiasingOff(unsigned int curveId)
std::vector< std::tuple< QwtPlotCurve *, QwtPlotIntervalCurve *, QwtPlotIntervalCurve * > > m_PlotCurveVector
QwtPlot * GetPlot()
void SetCurveSymbol(unsigned int curveId, QwtSymbol *symbol)
void SetCurveStyle(unsigned int curveId, const QwtPlotCurve::CurveStyle style)
void SetCurveAntialiasingOn(unsigned int curveId)
void SetCurvePen(unsigned int curveId, const QPen &pen)
unsigned int InsertCurve(const char *title, QColor color=QColor(Qt::black))
void SetCurveTitle(unsigned int curveId, const char *title)
bool SetCurveData(unsigned int curveId, const DataVector &xValues, const DataVector &yValues)
QmitkPlotWidget(QWidget *parent=nullptr, const char *title=nullptr, const char *name=nullptr, Qt::WindowFlags f=nullptr)
void SetCurveBrush(unsigned int curveId, const QBrush &brush)
double * ConvertToRawArray(const DataVector &values)
bool AddErrorIntervalCurve(unsigned int curveId, const DataVector &lessError, const DataVector &moreError, bool isXError)
void SetAxisTitle(int axis, const char *title)
void SetLegendAttribute(unsigned int curveId, const QwtPlotCurve::LegendAttribute &attribute)
void SetLegend(QwtLegend *legend, QwtPlot::LegendPosition pos=QwtPlot::RightLegend, double ratio=-1)
void SetErrorStyleSymbols(unsigned int curveId, bool drawSmybols)
virtual ~QmitkPlotWidget()
void SetErrorPen(unsigned int curveId, const QPen &pen)