~valavanisalex/ubuntu/maverick/scidavis/fix-604811

« back to all changes in this revision

Viewing changes to scidavis/src/Filter.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Ruben Molina
  • Date: 2009-09-06 11:34:04 UTC
  • Revision ID: james.westby@ubuntu.com-20090906113404-4awaey82l3686w4q
Tags: upstream-0.2.3
ImportĀ upstreamĀ versionĀ 0.2.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
    File                 : Fit.cpp
 
3
    Project              : SciDAVis
 
4
    --------------------------------------------------------------------
 
5
    Copyright            : (C) 2007 by Ion Vasilief
 
6
    Email (use @ for *)  : ion_vasilief*yahoo.fr
 
7
    Description          : Abstract base class for data analysis operations
 
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
#include "Filter.h"
 
30
#include "Legend.h"
 
31
#include "ColorBox.h"
 
32
#include "Table.h"
 
33
#include "FunctionCurve.h"
 
34
#include "PlotCurve.h"
 
35
#include "core/column/Column.h"
 
36
 
 
37
#include <QApplication>
 
38
#include <QMessageBox>
 
39
#include <QLocale>
 
40
 
 
41
#include <gsl/gsl_sort.h>
 
42
 
 
43
Filter::Filter( ApplicationWindow *parent, Graph *g, const char * name)
 
44
: QObject( parent, name)
 
45
{
 
46
        init();
 
47
        d_graph = g;
 
48
}
 
49
 
 
50
Filter::Filter( ApplicationWindow *parent, Table *t, const char * name)
 
51
: QObject( parent, name)
 
52
{
 
53
        init();
 
54
        d_table = t;
 
55
}
 
56
 
 
57
void Filter::init()
 
58
{
 
59
        d_n = 0;
 
60
        d_curveColorIndex = 1;
 
61
        d_tolerance = 1e-4;
 
62
        d_points = 100;
 
63
        d_max_iterations = 1000;
 
64
        d_curve = 0;
 
65
        d_prec = ((ApplicationWindow *)parent())->fit_output_precision;
 
66
        d_init_err = false;
 
67
    d_sort_data = false;
 
68
    d_min_points = 2;
 
69
    d_explanation = QString(name());
 
70
    d_graph = 0;
 
71
    d_table = 0;
 
72
}
 
73
 
 
74
void Filter::setInterval(double from, double to)
 
75
{
 
76
        if (!d_curve)
 
77
        {
 
78
                QMessageBox::critical((ApplicationWindow *)parent(), tr("SciDAVis") + " - " + tr("Error"),
 
79
                                tr("Please assign a curve first!"));
 
80
                return;
 
81
        }
 
82
        setDataFromCurve (d_curve->title().text(), from, to);
 
83
}
 
84
 
 
85
void Filter::setDataCurve(int curve, double start, double end)
 
86
{
 
87
        if (d_n > 0)
 
88
        {//delete previousely allocated memory
 
89
                delete[] d_x;
 
90
                delete[] d_y;
 
91
        }
 
92
 
 
93
        d_init_err = false;
 
94
        d_curve = d_graph->curve(curve);
 
95
    if (d_sort_data)
 
96
        d_n = sortedCurveData(d_curve, start, end, &d_x, &d_y);
 
97
    else
 
98
        d_n = curveData(d_curve, start, end, &d_x, &d_y);
 
99
 
 
100
        if (d_n == -1)
 
101
        {
 
102
                QMessageBox::critical((ApplicationWindow *)parent(), tr("SciDAVis") + " - " + tr("Error"),
 
103
                                tr("Several data points have the same x value causing divisions by zero, operation aborted!"));
 
104
                d_init_err = true;
 
105
        return;
 
106
        }
 
107
    else if (d_n < d_min_points)
 
108
        {
 
109
                QMessageBox::critical((ApplicationWindow *)parent(), tr("SciDAVis") + " - " + tr("Error"),
 
110
                                tr("You need at least %1 points in order to perform this operation!").arg(d_min_points));
 
111
                d_init_err = true;
 
112
        return;
 
113
        }
 
114
 
 
115
    d_from = start;
 
116
    d_to = end;
 
117
}
 
118
 
 
119
int Filter::curveIndex(const QString& curveTitle, Graph *g)
 
120
{
 
121
        if (curveTitle.isEmpty())
 
122
        {
 
123
                QMessageBox::critical((ApplicationWindow *)parent(), tr("Filter Error"),
 
124
                                tr("Please enter a valid curve name!"));
 
125
                d_init_err = true;
 
126
                return -1;
 
127
        }
 
128
 
 
129
        if (g)
 
130
                d_graph = g;
 
131
 
 
132
        if (!d_graph)
 
133
        {
 
134
                d_init_err = true;
 
135
                return -1;
 
136
        }
 
137
 
 
138
        return d_graph->curveIndex(curveTitle);
 
139
}
 
140
 
 
141
bool Filter::setDataFromCurve(const QString& curveTitle, Graph *g)
 
142
{
 
143
        int index = curveIndex(curveTitle, g);
 
144
        if (index < 0)
 
145
        {
 
146
                d_init_err = true;
 
147
                return false;
 
148
        }
 
149
 
 
150
        d_graph->range(index, &d_from, &d_to);
 
151
    setDataCurve(index, d_from, d_to);
 
152
        return true;
 
153
}
 
154
 
 
155
bool Filter::setDataFromCurve(const QString& curveTitle, double from, double to, Graph *g)
 
156
{
 
157
        int index = curveIndex(curveTitle, g);
 
158
        if (index < 0)
 
159
        {
 
160
                d_init_err = true;
 
161
                return false;
 
162
        }
 
163
 
 
164
        setDataCurve(index, from, to);
 
165
        return true;
 
166
}
 
167
 
 
168
void Filter::setColor(const QString& colorName)
 
169
{
 
170
    QColor c = QColor(colorName);
 
171
    if (colorName == "green")
 
172
        c = QColor(Qt::green);
 
173
    else if (colorName == "darkYellow")
 
174
        c = QColor(Qt::darkYellow);
 
175
    if (!ColorBox::isValidColor(c))
 
176
    {
 
177
        QMessageBox::critical((ApplicationWindow *)parent(), tr("Color Name Error"),
 
178
                                tr("The color name '%1' is not valid, a default color (red) will be used instead!").arg(colorName));
 
179
        d_curveColorIndex = 1;
 
180
        return;
 
181
    }
 
182
 
 
183
        d_curveColorIndex = ColorBox::colorIndex(c);
 
184
}
 
185
 
 
186
void Filter::showLegend()
 
187
{
 
188
        Legend* mrk = d_graph->newLegend(legendInfo());
 
189
        if (d_graph->hasLegend())
 
190
        {
 
191
                Legend* legend = d_graph->legend();
 
192
                QPoint p = legend->rect().bottomLeft();
 
193
                mrk->setOrigin(QPoint(p.x(), p.y()+20));
 
194
        }
 
195
        d_graph->replot();
 
196
}
 
197
 
 
198
bool Filter::run()
 
199
{
 
200
        if (d_init_err)
 
201
                return false;
 
202
 
 
203
        if (d_n < 0)
 
204
        {
 
205
                QMessageBox::critical((ApplicationWindow *)parent(), tr("SciDAVis") + " - " + tr("Error"),
 
206
                                tr("You didn't specify a valid data set for this operation!"));
 
207
                return false;
 
208
        }
 
209
 
 
210
        QApplication::setOverrideCursor(Qt::WaitCursor);
 
211
 
 
212
    output();//data analysis and output
 
213
    ((ApplicationWindow *)parent())->updateLog(logInfo());
 
214
 
 
215
        QApplication::restoreOverrideCursor();
 
216
    return true;
 
217
}
 
218
 
 
219
void Filter::output()
 
220
{
 
221
    double *X = new double[d_points];
 
222
    double *Y = new double[d_points];
 
223
 
 
224
    //do the data analysis
 
225
    calculateOutputData(X, Y);
 
226
 
 
227
        addResultCurve(X, Y);
 
228
}
 
229
 
 
230
int Filter::sortedCurveData(QwtPlotCurve *c, double start, double end, double **x, double **y)
 
231
{
 
232
    if (!c)
 
233
        return 0;
 
234
 
 
235
    int i_start = 0, i_end = c->dataSize();
 
236
    for (int i = 0; i < i_end; i++)
 
237
            if (c->x(i) >= start)
 
238
        {
 
239
              i_start = i;
 
240
          break;
 
241
        }
 
242
    for (int i = i_end-1; i >= 0; i--)
 
243
            if (c->x(i) <= end)
 
244
        {
 
245
              i_end = i;
 
246
          break;
 
247
        }
 
248
    int n = i_end - i_start + 1;
 
249
    (*x) = new double[n];
 
250
    (*y) = new double[n];
 
251
    double *xtemp = new double[n];
 
252
    double *ytemp = new double[n];
 
253
 
 
254
        int j=0;
 
255
    for (int i = i_start; i <= i_end; i++)
 
256
    {
 
257
        xtemp[j] = c->x(i);
 
258
        ytemp[j++] = c->y(i);
 
259
    }
 
260
    size_t *p = new size_t[n];
 
261
    gsl_sort_index(p, xtemp, 1, n);
 
262
    for (int i=0; i<n; i++)
 
263
    {
 
264
        (*x)[i] = xtemp[p[i]];
 
265
            (*y)[i] = ytemp[p[i]];
 
266
    }
 
267
    delete[] xtemp;
 
268
    delete[] ytemp;
 
269
    delete[] p;
 
270
    return n;
 
271
}
 
272
 
 
273
int Filter::curveData(QwtPlotCurve *c, double start, double end, double **x, double **y)
 
274
{
 
275
    if (!c)
 
276
        return 0;
 
277
 
 
278
    int i_start = 0, i_end = c->dataSize();
 
279
    for (int i = 0; i < i_end; i++)
 
280
            if (c->x(i) >= start)
 
281
        {
 
282
              i_start = i;
 
283
          break;
 
284
        }
 
285
    for (int i = i_end-1; i >= 0; i--)
 
286
            if (c->x(i) <= end)
 
287
        {
 
288
              i_end = i;
 
289
          break;
 
290
        }
 
291
    int n = i_end - i_start + 1;
 
292
    (*x) = new double[n];
 
293
    (*y) = new double[n];
 
294
 
 
295
    int j=0;
 
296
    for (int i = i_start; i <= i_end; i++)
 
297
    {
 
298
        (*x)[j] = c->x(i);
 
299
        (*y)[j++] = c->y(i);
 
300
    }
 
301
    return n;
 
302
}
 
303
 
 
304
QwtPlotCurve* Filter::addResultCurve(double *x, double *y)
 
305
{
 
306
    ApplicationWindow *app = (ApplicationWindow *)parent();
 
307
    const QString tableName = app->generateUniqueName(QString(this->name()));
 
308
        Column *xCol = new Column(tr("1", "filter table x column name"), SciDAVis::Numeric);
 
309
        Column *yCol = new Column(tr("2", "filter table y column name"), SciDAVis::Numeric);
 
310
        xCol->setPlotDesignation(SciDAVis::X);
 
311
        yCol->setPlotDesignation(SciDAVis::Y);
 
312
        for (int i=0; i<d_points; i++)
 
313
        {
 
314
                xCol->setValueAt(i, x[i]);
 
315
                yCol->setValueAt(i, y[i]);
 
316
        }
 
317
        // first set the values, then add the columns to the table, otherwise, we generate too many undo commands
 
318
    Table *t = app->newHiddenTable(tableName, d_explanation + " " + tr("of") + " " + d_curve->title().text(), 
 
319
                QList<Column *>() << xCol << yCol);
 
320
 
 
321
        DataCurve *c = new DataCurve(t, tableName + "_" + xCol->name(), tableName + "_" + yCol->name());
 
322
        c->setData(x, y, d_points);
 
323
    c->setPen(QPen(ColorBox::color(d_curveColorIndex), 1));
 
324
        d_graph->insertPlotItem(c, Graph::Line);
 
325
    d_graph->updatePlot();
 
326
 
 
327
    delete[] x;
 
328
        delete[] y;
 
329
        return (QwtPlotCurve*)c;
 
330
}
 
331
 
 
332
Filter::~Filter()
 
333
{
 
334
        if (d_n > 0)
 
335
        {//delete the memory allocated for the data
 
336
                delete[] d_x;
 
337
                delete[] d_y;
 
338
        }
 
339
}