labplot  2.8.2
About: LabPlot is an application for plotting and analysis of 2D and 3D functions and data. It is a complete rewrite of LabPlot1 and lacks in the first release a lot of features available in the predecessor. On the other hand, the GUI and the usability is more superior.
  Fossies Dox: labplot-2.8.2.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

XYIntegrationCurve.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  File : XYIntegrationCurve.cpp
3  Project : LabPlot
4  Description : A xy-curve defined by an integration
5  --------------------------------------------------------------------
6  Copyright : (C) 2016 Stefan Gerlach (stefan.gerlach@uni.kn)
7  Copyright : (C) 2017 Alexander Semke (alexander.semke@web.de)
8 
9  ***************************************************************************/
10 
11 /***************************************************************************
12  * *
13  * This program is free software; you can redistribute it and/or modify *
14  * it under the terms of the GNU General Public License as published by *
15  * the Free Software Foundation; either version 2 of the License, or *
16  * (at your option) any later version. *
17  * *
18  * This program is distributed in the hope that it will be useful, *
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
21  * GNU General Public License for more details. *
22  * *
23  * You should have received a copy of the GNU General Public License *
24  * along with this program; if not, write to the Free Software *
25  * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
26  * Boston, MA 02110-1301 USA *
27  * *
28  ***************************************************************************/
29 
30 /*!
31  \class XYIntegrationCurve
32  \brief A xy-curve defined by an integration
33 
34  \ingroup worksheet
35 */
36 
37 #include "XYIntegrationCurve.h"
42 #include "backend/lib/macros.h"
43 
44 extern "C" {
45 #include <gsl/gsl_errno.h>
46 }
47 
48 #include <KLocalizedString>
49 #include <QIcon>
50 #include <QElapsedTimer>
51 #include <QThreadPool>
52 
55 }
56 
59 }
60 
61 //no need to delete the d-pointer here - it inherits from QGraphicsItem
62 //and is deleted during the cleanup in QGraphicsScene
64 
66  Q_D(XYIntegrationCurve);
67  d->recalculate();
68 }
69 
70 /*!
71  Returns an icon to be used in the project explorer.
72 */
73 QIcon XYIntegrationCurve::icon() const {
74  return QIcon::fromTheme("labplot-xy-curve");
75 }
76 
77 //##############################################################################
78 //########################## getter methods ##################################
79 //##############################################################################
81 
82 const XYIntegrationCurve::IntegrationResult& XYIntegrationCurve::integrationResult() const {
83  Q_D(const XYIntegrationCurve);
84  return d->integrationResult;
85 }
86 
87 //##############################################################################
88 //################# setter methods and undo commands ##########################
89 //##############################################################################
90 STD_SETTER_CMD_IMPL_F_S(XYIntegrationCurve, SetIntegrationData, XYIntegrationCurve::IntegrationData, integrationData, recalculate);
91 void XYIntegrationCurve::setIntegrationData(const XYIntegrationCurve::IntegrationData& integrationData) {
92  Q_D(XYIntegrationCurve);
93  exec(new XYIntegrationCurveSetIntegrationDataCmd(d, integrationData, ki18n("%1: set options and perform the integration")));
94 }
95 
96 //##############################################################################
97 //######################### Private implementation #############################
98 //##############################################################################
100 }
101 
102 //no need to delete xColumn and yColumn, they are deleted
103 //when the parent aspect is removed
105 
107  QElapsedTimer timer;
108  timer.start();
109 
110  //create integration result columns if not available yet, clear them otherwise
111  if (!xColumn) {
114  xVector = static_cast<QVector<double>* >(xColumn->data());
115  yVector = static_cast<QVector<double>* >(yColumn->data());
116 
117  xColumn->setHidden(true);
118  q->addChild(xColumn);
119  yColumn->setHidden(true);
120  q->addChild(yColumn);
121 
122  q->setUndoAware(false);
123  q->setXColumn(xColumn);
124  q->setYColumn(yColumn);
125  q->setUndoAware(true);
126  } else {
127  xVector->clear();
128  yVector->clear();
129  }
130 
131  // clear the previous result
133 
134  //determine the data source columns
135  const AbstractColumn* tmpXDataColumn = nullptr;
136  const AbstractColumn* tmpYDataColumn = nullptr;
138  //spreadsheet columns as data source
139  tmpXDataColumn = xDataColumn;
140  tmpYDataColumn = yDataColumn;
141  } else {
142  //curve columns as data source
143  tmpXDataColumn = dataSourceCurve->xColumn();
144  tmpYDataColumn = dataSourceCurve->yColumn();
145  }
146 
147  if (!tmpXDataColumn || !tmpYDataColumn) {
149  emit q->dataChanged();
151  return;
152  }
153 
154  //copy all valid data point for the integration to temporary vectors
155  QVector<double> xdataVector;
156  QVector<double> ydataVector;
157 
158  double xmin;
159  double xmax;
161  xmin = tmpXDataColumn->minimum();
162  xmax = tmpXDataColumn->maximum();
163  } else {
164  xmin = integrationData.xRange.first();
165  xmax = integrationData.xRange.last();
166  }
167 
168  XYAnalysisCurve::copyData(xdataVector, ydataVector, tmpXDataColumn, tmpYDataColumn, xmin, xmax);
169 
170  const size_t n = (size_t)xdataVector.size(); // number of data points to integrate
171  if (n < 2) {
173  integrationResult.valid = false;
174  integrationResult.status = i18n("Not enough data points available.");
176  emit q->dataChanged();
178  return;
179  }
180 
181  double* xdata = xdataVector.data();
182  double* ydata = ydataVector.data();
183 
184  // integration settings
186  const bool absolute = integrationData.absolute;
187 
188  DEBUG("method:"<<nsl_int_method_name[method]);
189  DEBUG("absolute area:"<<absolute);
190 
191 ///////////////////////////////////////////////////////////
192  int status = 0;
193  size_t np = n;
194 
195  switch (method) {
197  status = nsl_int_rectangle(xdata, ydata, n, absolute);
198  break;
200  status = nsl_int_trapezoid(xdata, ydata, n, absolute);
201  break;
203  np = nsl_int_simpson(xdata, ydata, n, absolute);
204  break;
206  np = nsl_int_simpson_3_8(xdata, ydata, n, absolute);
207  break;
208  }
209 
210  xVector->resize((int)np);
211  yVector->resize((int)np);
212  memcpy(xVector->data(), xdata, np * sizeof(double));
213  memcpy(yVector->data(), ydata, np * sizeof(double));
214 ///////////////////////////////////////////////////////////
215 
216  //write the result
218  integrationResult.valid = true;
219  integrationResult.status = QString::number(status);
220  integrationResult.elapsedTime = timer.elapsed();
221  integrationResult.value = ydata[np-1];
222 
223  //redraw the curve
225  emit q->dataChanged();
227 }
228 
229 //##############################################################################
230 //################## Serialization/Deserialization ###########################
231 //##############################################################################
232 //! Save as XML
233 void XYIntegrationCurve::save(QXmlStreamWriter* writer) const{
234  Q_D(const XYIntegrationCurve);
235 
236  writer->writeStartElement("xyIntegrationCurve");
237 
238  //write the base class
239  XYAnalysisCurve::save(writer);
240 
241  //write xy-integration-curve specific information
242  // integration data
243  writer->writeStartElement("integrationData");
244  writer->writeAttribute( "autoRange", QString::number(d->integrationData.autoRange) );
245  writer->writeAttribute( "xRangeMin", QString::number(d->integrationData.xRange.first()) );
246  writer->writeAttribute( "xRangeMax", QString::number(d->integrationData.xRange.last()) );
247  writer->writeAttribute( "method", QString::number(d->integrationData.method) );
248  writer->writeAttribute( "absolute", QString::number(d->integrationData.absolute) );
249  writer->writeEndElement();// integrationData
250 
251  // integration results (generated columns)
252  writer->writeStartElement("integrationResult");
253  writer->writeAttribute( "available", QString::number(d->integrationResult.available) );
254  writer->writeAttribute( "valid", QString::number(d->integrationResult.valid) );
255  writer->writeAttribute( "status", d->integrationResult.status );
256  writer->writeAttribute( "time", QString::number(d->integrationResult.elapsedTime) );
257  writer->writeAttribute( "value", QString::number(d->integrationResult.value) );
258 
259  //save calculated columns if available
260  if (d->xColumn) {
261  d->xColumn->save(writer);
262  d->yColumn->save(writer);
263  }
264  writer->writeEndElement(); //"integrationResult"
265 
266  writer->writeEndElement(); //"xyIntegrationCurve"
267 }
268 
269 //! Load from XML
270 bool XYIntegrationCurve::load(XmlStreamReader* reader, bool preview) {
271  Q_D(XYIntegrationCurve);
272 
273  KLocalizedString attributeWarning = ki18n("Attribute '%1' missing or empty, default value is used");
274  QXmlStreamAttributes attribs;
275  QString str;
276 
277  while (!reader->atEnd()) {
278  reader->readNext();
279  if (reader->isEndElement() && reader->name() == "xyIntegrationCurve")
280  break;
281 
282  if (!reader->isStartElement())
283  continue;
284 
285  if (reader->name() == "xyAnalysisCurve") {
286  if ( !XYAnalysisCurve::load(reader, preview) )
287  return false;
288  } else if (!preview && reader->name() == "integrationData") {
289  attribs = reader->attributes();
290  READ_INT_VALUE("autoRange", integrationData.autoRange, bool);
291  READ_DOUBLE_VALUE("xRangeMin", integrationData.xRange.first());
292  READ_DOUBLE_VALUE("xRangeMax", integrationData.xRange.last());
293  READ_INT_VALUE("method", integrationData.method, nsl_int_method_type);
294  READ_INT_VALUE("absolute", integrationData.absolute, bool);
295  } else if (!preview && reader->name() == "integrationResult") {
296  attribs = reader->attributes();
297  READ_INT_VALUE("available", integrationResult.available, int);
298  READ_INT_VALUE("valid", integrationResult.valid, int);
302  } else if (!preview && reader->name() == "column") {
303  Column* column = new Column(QString(), AbstractColumn::ColumnMode::Numeric);
304  if (!column->load(reader, preview)) {
305  delete column;
306  return false;
307  }
308  if (column->name() == "x")
309  d->xColumn = column;
310  else if (column->name() == "y")
311  d->yColumn = column;
312  }
313  }
314 
315  if (preview)
316  return true;
317 
318  // wait for data to be read before using the pointers
319  QThreadPool::globalInstance()->waitForDone();
320 
321  if (d->xColumn && d->yColumn) {
322  d->xColumn->setHidden(true);
323  addChild(d->xColumn);
324 
325  d->yColumn->setHidden(true);
326  addChild(d->yColumn);
327 
328  d->xVector = static_cast<QVector<double>* >(d->xColumn->data());
329  d->yVector = static_cast<QVector<double>* >(d->yColumn->data());
330 
331  XYCurve::d_ptr->xColumn = d->xColumn;
332  XYCurve::d_ptr->yColumn = d->yColumn;
333 
335  }
336 
337  return true;
338 }
AspectType
STD_SETTER_CMD_IMPL_F_S(XYIntegrationCurve, SetIntegrationData, XYIntegrationCurve::IntegrationData, integrationData, recalculate)
void setUndoAware(bool)
void addChild(AbstractAspect *)
Add the given Aspect to my list of children.
QString name() const
void exec(QUndoCommand *)
Execute the given command, pushing it on the undoStack() if available.
AbstractAspectPrivate * d
void setHidden(bool)
Set "hidden" property, i.e. whether to exclude this aspect from being shown in the explorer.
Interface definition for data with column logic.
virtual double maximum(int count=0) const
virtual double minimum(int count=0) const
Aspect that manages a column.
Definition: Column.h:42
void * data() const
Definition: Column.cpp:852
bool load(XmlStreamReader *, bool preview) override
Load the column from XML.
Definition: Column.cpp:1152
XYAnalysisCurve::DataSourceType dataSourceType
const AbstractColumn * yDataColumn
QVector< double > * xVector
const AbstractColumn * xDataColumn
QVector< double > * yVector
Base class for all analysis curves.
static void copyData(QVector< double > &xData, QVector< double > &yData, const AbstractColumn *xDataColumn, const AbstractColumn *yDataColumn, double xMin, double xMax)
void save(QXmlStreamWriter *) const override
Save as XML.
bool load(XmlStreamReader *, bool preview) override
Load from XML.
bool sourceDataChangedSinceLastRecalc
const AbstractColumn * xColumn
void recalcLogicalPoints()
Definition: XYCurve.cpp:1090
const AbstractColumn * yColumn
void dataChanged()
XYCurvePrivate *const d_ptr
Definition: XYCurve.h:186
void recalcLogicalPoints()
Definition: XYCurve.cpp:765
XYIntegrationCurve::IntegrationData integrationData
XYIntegrationCurve *const q
~XYIntegrationCurvePrivate() override
XYIntegrationCurvePrivate(XYIntegrationCurve *)
XYIntegrationCurve::IntegrationResult integrationResult
A xy-curve defined by an integration.
bool load(XmlStreamReader *, bool preview) override
Load from XML.
QIcon icon() const override
void recalculate() override
const IntegrationResult & integrationResult() const
XYIntegrationCurve(const QString &name)
~XYIntegrationCurve() override
void save(QXmlStreamWriter *) const override
Save as XML.
XML stream parser that supports errors as well as warnings. This class also adds line and column numb...
#define READ_DOUBLE_VALUE(name, var)
Definition: macros.h:475
#define DEBUG(x)
Definition: macros.h:50
#define READ_INT_VALUE(name, var, type)
Definition: macros.h:468
#define BASIC_SHARED_D_READER_IMPL(classname, type, method, var)
Definition: macros.h:127
#define READ_STRING_VALUE(name, var)
Definition: macros.h:482
#define i18n(m)
Definition: nsl_common.h:38
size_t nsl_int_simpson(double *x, double *y, const size_t n, int abs)
Definition: nsl_int.c:79
int nsl_int_rectangle(const double *x, double *y, const size_t n, int abs)
Definition: nsl_int.c:39
const char * nsl_int_method_name[]
Definition: nsl_int.c:37
int nsl_int_trapezoid(const double *x, double *y, const size_t n, int abs)
Definition: nsl_int.c:59
size_t nsl_int_simpson_3_8(double *x, double *y, const size_t n, int abs)
Definition: nsl_int.c:114
nsl_int_method_type
Definition: nsl_int.h:35
@ nsl_int_method_simpson_3_8
Definition: nsl_int.h:35
@ nsl_int_method_rectangle
Definition: nsl_int.h:35
@ nsl_int_method_simpson
Definition: nsl_int.h:35
@ nsl_int_method_trapezoid
Definition: nsl_int.h:35