Subversion Repositories public iLand

Rev

Rev 802 | Rev 835 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 802 Rev 808
1
Redirecting to URL 'https://iland.boku.ac.at/svn/iland/tags/release_1.0/src/core/modelcontroller.cpp':
1
Redirecting to URL 'https://iland.boku.ac.at/svn/iland/tags/release_1.0/src/core/modelcontroller.cpp':
2
/********************************************************************************************
2
/********************************************************************************************
3
**    iLand - an individual based forest landscape and disturbance model
3
**    iLand - an individual based forest landscape and disturbance model
4
**    http://iland.boku.ac.at
4
**    http://iland.boku.ac.at
5
**    Copyright (C) 2009-  Werner Rammer, Rupert Seidl
5
**    Copyright (C) 2009-  Werner Rammer, Rupert Seidl
6
**
6
**
7
**    This program is free software: you can redistribute it and/or modify
7
**    This program is free software: you can redistribute it and/or modify
8
**    it under the terms of the GNU General Public License as published by
8
**    it under the terms of the GNU General Public License as published by
9
**    the Free Software Foundation, either version 3 of the License, or
9
**    the Free Software Foundation, either version 3 of the License, or
10
**    (at your option) any later version.
10
**    (at your option) any later version.
11
**
11
**
12
**    This program is distributed in the hope that it will be useful,
12
**    This program is distributed in the hope that it will be useful,
13
**    but WITHOUT ANY WARRANTY; without even the implied warranty of
13
**    but WITHOUT ANY WARRANTY; without even the implied warranty of
14
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
**    GNU General Public License for more details.
15
**    GNU General Public License for more details.
16
**
16
**
17
**    You should have received a copy of the GNU General Public License
17
**    You should have received a copy of the GNU General Public License
18
**    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
**    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
********************************************************************************************/
19
********************************************************************************************/
20
20
21
/** ModelController is a helper class used to control the flow of operations during a model run.
21
/** ModelController is a helper class used to control the flow of operations during a model run.
22
  The ModelController encapsulates the Model class and is the main control unit. It is used by the
22
  The ModelController encapsulates the Model class and is the main control unit. It is used by the
23
  iLand GUI as well as the command line version (ilandc).
23
  iLand GUI as well as the command line version (ilandc).
24

24

25
  */
25
  */
26
26
27
#include "global.h"
27
#include "global.h"
28
#include "modelcontroller.h"
28
#include "modelcontroller.h"
29
#include <QObject>
29
#include <QObject>
30
30
31
#include "model.h"
31
#include "model.h"
-
 
32
#include "debugtimer.h"
32
#include "helper.h"
33
#include "helper.h"
33
#include "expression.h"
34
#include "expression.h"
34
#include "expressionwrapper.h"
35
#include "expressionwrapper.h"
35
#include "../output/outputmanager.h"
36
#include "../output/outputmanager.h"
36
37
37
#include "species.h"
38
#include "species.h"
38
#include "speciesset.h"
39
#include "speciesset.h"
39
#include "mapgrid.h"
40
#include "mapgrid.h"
-
 
41
#include "statdata.h"
40
42
41
#ifdef ILAND_GUI
43
#ifdef ILAND_GUI
42
#include "mainwindow.h" // for the debug message buffering
44
#include "mainwindow.h" // for the debug message buffering
43
#endif
45
#endif
44
46
45
ModelController::ModelController()
47
ModelController::ModelController()
46
{
48
{
47
    mModel = NULL;
49
    mModel = NULL;
48
    mPaused = false;
50
    mPaused = false;
49
    mRunning = false;
51
    mRunning = false;
50
    mYearsToRun = 0;
52
    mYearsToRun = 0;
51
    mViewerWindow = 0;
53
    mViewerWindow = 0;
52
    mDynamicOutputEnabled = false;
54
    mDynamicOutputEnabled = false;
53
}
55
}
54
56
55
ModelController::~ModelController()
57
ModelController::~ModelController()
56
{
58
{
57
    destroy();
59
    destroy();
58
}
60
}
59
61
60
void ModelController::connectSignals()
62
void ModelController::connectSignals()
61
{
63
{
62
    if (!mViewerWindow)
64
    if (!mViewerWindow)
63
        return;
65
        return;
64
#ifdef ILAND_GUI
66
#ifdef ILAND_GUI
65
    connect(this,SIGNAL(bufferLogs(bool)), mViewerWindow, SLOT(bufferedLog(bool)));
67
    connect(this,SIGNAL(bufferLogs(bool)), mViewerWindow, SLOT(bufferedLog(bool)));
66
#endif
68
#endif
67
}
69
}
68
70
69
/// prepare a list of all (active) species
71
/// prepare a list of all (active) species
70
QHash<QString, QString> ModelController::availableSpecies()
72
QHash<QString, QString> ModelController::availableSpecies()
71
{
73
{
72
    QHash<QString, QString> list;
74
    QHash<QString, QString> list;
73
    if (mModel) {
75
    if (mModel) {
74
        SpeciesSet *set = mModel->speciesSet();
76
        SpeciesSet *set = mModel->speciesSet();
75
        if (!set)
77
        if (!set)
76
            throw IException("there are 0 or more than one species sets.");
78
            throw IException("there are 0 or more than one species sets.");
77
        foreach (const Species *s, set->activeSpecies()) {
79
        foreach (const Species *s, set->activeSpecies()) {
78
            list[s->id()] = s->name();
80
            list[s->id()] = s->name();
79
        }
81
        }
80
    }
82
    }
81
    return list;
83
    return list;
82
}
84
}
83
85
84
bool ModelController::canCreate()
86
bool ModelController::canCreate()
85
{
87
{
86
    if (mModel)
88
    if (mModel)
87
        return false;
89
        return false;
88
    return true;
90
    return true;
89
}
91
}
90
92
91
bool ModelController::canDestroy()
93
bool ModelController::canDestroy()
92
{
94
{
93
    return mModel != NULL;
95
    return mModel != NULL;
94
}
96
}
95
97
96
bool ModelController::canRun()
98
bool ModelController::canRun()
97
{
99
{
98
    if (mModel && mModel->isSetup())
100
    if (mModel && mModel->isSetup())
99
        return true;
101
        return true;
100
    return false;
102
    return false;
101
}
103
}
102
104
103
bool ModelController::isRunning()
105
bool ModelController::isRunning()
104
{
106
{
105
    return mRunning;
107
    return mRunning;
106
}
108
}
107
109
108
bool ModelController::isFinished()
110
bool ModelController::isFinished()
109
{
111
{
110
    if (!mModel)
112
    if (!mModel)
111
        return false;
113
        return false;
112
    return canRun() && !isRunning()  && mFinished;
114
    return canRun() && !isRunning()  && mFinished;
113
}
115
}
114
116
115
bool ModelController::isPaused()
117
bool ModelController::isPaused()
116
{
118
{
117
    return mPaused;
119
    return mPaused;
118
}
120
}
119
121
120
int ModelController::currentYear() const
122
int ModelController::currentYear() const
121
{
123
{
122
    return GlobalSettings::instance()->currentYear();
124
    return GlobalSettings::instance()->currentYear();
123
}
125
}
124
126
125
void ModelController::setFileName(QString initFileName)
127
void ModelController::setFileName(QString initFileName)
126
{
128
{
127
    mInitFile = initFileName;
129
    mInitFile = initFileName;
128
    try {
130
    try {
129
        GlobalSettings::instance()->loadProjectFile(mInitFile);
131
        GlobalSettings::instance()->loadProjectFile(mInitFile);
130
    } catch(const IException &e) {
132
    } catch(const IException &e) {
131
        QString error_msg = e.message();
133
        QString error_msg = e.message();
132
        Helper::msg(error_msg);
134
        Helper::msg(error_msg);
133
        qDebug() << error_msg;
135
        qDebug() << error_msg;
134
    }
136
    }
135
}
137
}
136
138
137
void ModelController::create()
139
void ModelController::create()
138
{
140
{
139
    if (!canCreate())
141
    if (!canCreate())
140
        return;
142
        return;
141
    emit bufferLogs(true);
143
    emit bufferLogs(true);
142
144
143
    try {
145
    try {
144
        DebugTimer::clearAllTimers();
146
        DebugTimer::clearAllTimers();
145
        mModel = new Model();
147
        mModel = new Model();
146
        mModel->loadProject();
148
        mModel->loadProject();
147
        if (!mModel->isSetup())
149
        if (!mModel->isSetup())
148
            return;
150
            return;
149
151
150
        // reset clock...
152
        // reset clock...
151
        GlobalSettings::instance()->setCurrentYear(1); // reset clock
153
        GlobalSettings::instance()->setCurrentYear(1); // reset clock
152
        // initialization of trees, output on startup
154
        // initialization of trees, output on startup
153
        mModel->beforeRun();
155
        mModel->beforeRun();
154
    } catch(const IException &e) {
156
    } catch(const IException &e) {
155
        QString error_msg = e.message();
157
        QString error_msg = e.message();
156
        Helper::msg(error_msg);
158
        Helper::msg(error_msg);
157
        qDebug() << error_msg;
159
        qDebug() << error_msg;
158
    }
160
    }
159
    emit bufferLogs(false);
161
    emit bufferLogs(false);
160
162
161
    qDebug() << "Model created.";
163
    qDebug() << "Model created.";
162
}
164
}
163
165
164
void ModelController::destroy()
166
void ModelController::destroy()
165
{
167
{
166
    if (canDestroy()) {
168
    if (canDestroy()) {
167
        delete mModel;
169
        delete mModel;
168
        mModel = 0;
170
        mModel = 0;
169
        GlobalSettings::instance()->setCurrentYear(0);
171
        GlobalSettings::instance()->setCurrentYear(0);
170
        qDebug() << "ModelController: Model destroyed.";
172
        qDebug() << "ModelController: Model destroyed.";
171
    }
173
    }
172
}
174
}
173
175
174
void ModelController::runloop()
176
void ModelController::runloop()
175
{
177
{
176
    static QTime sLastTime = QTime::currentTime();
178
    static QTime sLastTime = QTime::currentTime();
177
#ifdef ILAND_GUI
179
#ifdef ILAND_GUI
178
 //   QApplication::processEvents();
180
 //   QApplication::processEvents();
179
#else
181
#else
180
 //   QCoreApplication::processEvents();
182
 //   QCoreApplication::processEvents();
181
#endif
183
#endif
182
    if (mPaused)
184
    if (mPaused)
183
        return;
185
        return;
184
    bool doStop = false;
186
    bool doStop = false;
185
    bool hasError = false;
187
    bool hasError = false;
186
    if (GlobalSettings::instance()->currentYear()<=1) {
188
    if (GlobalSettings::instance()->currentYear()<=1) {
187
        sLastTime = QTime::currentTime(); // reset clock at the beginning of the simulation
189
        sLastTime = QTime::currentTime(); // reset clock at the beginning of the simulation
188
    }
190
    }
189
191
190
    if (!mCanceled && GlobalSettings::instance()->currentYear() < mYearsToRun) {
192
    if (!mCanceled && GlobalSettings::instance()->currentYear() < mYearsToRun) {
191
        emit bufferLogs(true);
193
        emit bufferLogs(true);
192
194
193
        hasError = runYear(); // do the work!
195
        hasError = runYear(); // do the work!
194
196
195
        mRunning = true;
197
        mRunning = true;
196
        emit year(GlobalSettings::instance()->currentYear());
198
        emit year(GlobalSettings::instance()->currentYear());
197
        if (!hasError) {
199
        if (!hasError) {
198
            int elapsed = sLastTime.msecsTo(QTime::currentTime());
200
            int elapsed = sLastTime.msecsTo(QTime::currentTime());
199
            int time=0;
201
            int time=0;
200
            if (currentYear()%50==0 && elapsed>10000)
202
            if (currentYear()%50==0 && elapsed>10000)
201
                time = 100; // a 100ms pause...
203
                time = 100; // a 100ms pause...
202
            if (currentYear()%100==0 && elapsed>10000) {
204
            if (currentYear()%100==0 && elapsed>10000) {
203
                time = 500; // a 500ms pause...
205
                time = 500; // a 500ms pause...
204
            }
206
            }
205
            if (time>0) {
207
            if (time>0) {
206
                sLastTime = QTime::currentTime(); // reset clock
208
                sLastTime = QTime::currentTime(); // reset clock
207
                qDebug() << "--- little break ---- (after " << elapsed << "ms).";
209
                qDebug() << "--- little break ---- (after " << elapsed << "ms).";
208
                //QTimer::singleShot(time,this, SLOT(runloop()));
210
                //QTimer::singleShot(time,this, SLOT(runloop()));
209
            }
211
            }
210
212
211
        }
213
        }
212
        else
214
        else
213
           doStop = true; // an error occured
215
           doStop = true; // an error occured
214
216
215
    } else {
217
    } else {
216
        doStop = true; // all years simulated
218
        doStop = true; // all years simulated
217
    }
219
    }
218
220
219
    if (doStop || mCanceled) {
221
    if (doStop || mCanceled) {
220
                // finished
222
                // finished
221
        internalStop();
223
        internalStop();
222
    }
224
    }
223
225
224
#ifdef ILAND_GUI
226
#ifdef ILAND_GUI
225
    QApplication::processEvents();
227
    QApplication::processEvents();
226
#else
228
#else
227
    QCoreApplication::processEvents();
229
    QCoreApplication::processEvents();
228
#endif
230
#endif
229
}
231
}
230
232
231
bool ModelController::internalRun()
233
bool ModelController::internalRun()
232
{
234
{
233
    // main loop
235
    // main loop
234
236
235
    while (mRunning && !mPaused &&  !mFinished) {
237
    while (mRunning && !mPaused &&  !mFinished) {
236
        runloop(); // start the running loop
238
        runloop(); // start the running loop
237
    }
239
    }
238
    return isFinished();
240
    return isFinished();
239
}
241
}
240
242
241
void ModelController::internalStop()
243
void ModelController::internalStop()
242
{
244
{
243
    if (mRunning) {
245
    if (mRunning) {
244
        GlobalSettings::instance()->outputManager()->save();
246
        GlobalSettings::instance()->outputManager()->save();
245
        DebugTimer::printAllTimers();
247
        DebugTimer::printAllTimers();
246
        mFinished = true;
248
        mFinished = true;
247
    }
249
    }
248
    mRunning = false;
250
    mRunning = false;
249
    emit bufferLogs(false); // stop buffering
251
    emit bufferLogs(false); // stop buffering
250
    emit finished(QString());
252
    emit finished(QString());
251
    emit stateChanged();
253
    emit stateChanged();
252
254
253
}
255
}
254
256
255
void ModelController::run(int years)
257
void ModelController::run(int years)
256
{
258
{
257
    if (!canRun())
259
    if (!canRun())
258
        return;
260
        return;
259
    emit bufferLogs(true); // start buffering
261
    emit bufferLogs(true); // start buffering
260
262
261
    DebugTimer many_runs(QString("Timer for %1 runs").arg(years));
263
    DebugTimer many_runs(QString("Timer for %1 runs").arg(years));
262
    mPaused = false;
264
    mPaused = false;
263
    mFinished = false;
265
    mFinished = false;
264
    mCanceled = false;
266
    mCanceled = false;
265
    mYearsToRun = years;
267
    mYearsToRun = years;
266
    //GlobalSettings::instance()->setCurrentYear(1); // reset clock
268
    //GlobalSettings::instance()->setCurrentYear(1); // reset clock
267
269
268
    DebugTimer::clearAllTimers();
270
    DebugTimer::clearAllTimers();
269
271
270
    mRunning = true;
272
    mRunning = true;
271
    emit stateChanged();
273
    emit stateChanged();
272
274
273
    qDebug() << "ModelControler: runloop started.";
275
    qDebug() << "ModelControler: runloop started.";
274
    internalRun();
276
    internalRun();
275
    emit stateChanged();
277
    emit stateChanged();
276
}
278
}
277
279
278
bool ModelController::runYear()
280
bool ModelController::runYear()
279
{
281
{
280
    if (!canRun()) return false;
282
    if (!canRun()) return false;
281
    DebugTimer t("ModelController:runYear");
283
    DebugTimer t("ModelController:runYear");
282
    qDebug() << "ModelController: run year" << currentYear();
284
    qDebug() << "ModelController: run year" << currentYear();
283
285
284
    if (GlobalSettings::instance()->settings().paramValueBool("debug_clear"))
286
    if (GlobalSettings::instance()->settings().paramValueBool("debug_clear"))
285
        GlobalSettings::instance()->clearDebugLists();  // clear debug data
287
        GlobalSettings::instance()->clearDebugLists();  // clear debug data
286
    bool err=false;
288
    bool err=false;
287
    try {
289
    try {
288
        emit bufferLogs(true);
290
        emit bufferLogs(true);
289
        mModel->runYear();
291
        mModel->runYear();
290
        fetchDynamicOutput();
292
        fetchDynamicOutput();
291
    } catch(const IException &e) {
293
    } catch(const IException &e) {
292
        QString error_msg = e.message();
294
        QString error_msg = e.message();
293
#ifdef ILAND_GUI
295
#ifdef ILAND_GUI
294
        Helper::msg(error_msg);
296
        Helper::msg(error_msg);
295
#endif
297
#endif
296
        qDebug() << error_msg;
298
        qDebug() << error_msg;
297
        err=true;
299
        err=true;
298
    }
300
    }
299
    emit bufferLogs(false);
301
    emit bufferLogs(false);
300
    return err;
302
    return err;
301
}
303
}
302
304
303
bool ModelController::pause()
305
bool ModelController::pause()
304
{
306
{
305
    if(!isRunning())
307
    if(!isRunning())
306
        return mPaused;
308
        return mPaused;
307
309
308
    if (mPaused) {
310
    if (mPaused) {
309
        // currently in pause - mode -> continue
311
        // currently in pause - mode -> continue
310
        mPaused = false;
312
        mPaused = false;
311
313
312
    } else {
314
    } else {
313
        // currently running -> set to pause mode
315
        // currently running -> set to pause mode
314
        GlobalSettings::instance()->outputManager()->save();
316
        GlobalSettings::instance()->outputManager()->save();
315
        mPaused = true;
317
        mPaused = true;
316
        emit bufferLogs(false);
318
        emit bufferLogs(false);
317
    }
319
    }
318
    emit stateChanged();
320
    emit stateChanged();
319
    return mPaused;
321
    return mPaused;
320
}
322
}
321
323
322
bool ModelController::continueRun()
324
bool ModelController::continueRun()
323
{
325
{
324
    mRunning = true;
326
    mRunning = true;
325
    emit stateChanged();
327
    emit stateChanged();
326
    return internalRun();
328
    return internalRun();
327
}
329
}
328
330
329
void ModelController::cancel()
331
void ModelController::cancel()
330
{
332
{
331
    mCanceled = true;
333
    mCanceled = true;
332
    internalStop();
334
    internalStop();
333
    emit stateChanged();
335
    emit stateChanged();
334
}
336
}
335
337
336
QMutex error_mutex;
338
QMutex error_mutex;
337
void ModelController::throwError(const QString msg)
339
void ModelController::throwError(const QString msg)
338
{
340
{
339
    QMutexLocker lock(&error_mutex); // serialize access
341
    QMutexLocker lock(&error_mutex); // serialize access
340
    qDebug() << "ModelController: throwError reached:";
342
    qDebug() << "ModelController: throwError reached:";
341
    qDebug() << msg;
343
    qDebug() << msg;
342
    emit bufferLogs(false);
344
    emit bufferLogs(false);
343
    emit bufferLogs(true); // start buffering again
345
    emit bufferLogs(true); // start buffering again
344
346
345
    throw IException(msg); // raise error again
347
    throw IException(msg); // raise error again
346
348
347
}
349
}
348
//////////////////////////////////////
350
//////////////////////////////////////
349
// dynamic outut
351
// dynamic outut
350
//////////////////////////////////////
352
//////////////////////////////////////
351
//////////////////////////////////////
353
//////////////////////////////////////
352
void ModelController::setupDynamicOutput(QString fieldList)
354
void ModelController::setupDynamicOutput(QString fieldList)
353
{
355
{
354
    mDynFieldList.clear();
356
    mDynFieldList.clear();
355
    if (!fieldList.isEmpty()) {
357
    if (!fieldList.isEmpty()) {
356
        QRegExp rx("((?:\\[.+\\]|\\w+)\\.\\w+)");
358
        QRegExp rx("((?:\\[.+\\]|\\w+)\\.\\w+)");
357
        int pos=0;
359
        int pos=0;
358
        while ((pos = rx.indexIn(fieldList, pos)) != -1) {
360
        while ((pos = rx.indexIn(fieldList, pos)) != -1) {
359
            mDynFieldList.append(rx.cap(1));
361
            mDynFieldList.append(rx.cap(1));
360
            pos += rx.matchedLength();
362
            pos += rx.matchedLength();
361
        }
363
        }
362
364
363
        //mDynFieldList = fieldList.split(QRegExp("(?:\\[.+\\]|\\w+)\\.\\w+"), QString::SkipEmptyParts);
365
        //mDynFieldList = fieldList.split(QRegExp("(?:\\[.+\\]|\\w+)\\.\\w+"), QString::SkipEmptyParts);
364
        mDynFieldList.prepend("count");
366
        mDynFieldList.prepend("count");
365
        mDynFieldList.prepend("year"); // fixed fields.
367
        mDynFieldList.prepend("year"); // fixed fields.
366
    }
368
    }
367
    mDynData.clear();
369
    mDynData.clear();
368
    mDynData.append(mDynFieldList.join(";"));
370
    mDynData.append(mDynFieldList.join(";"));
369
    mDynamicOutputEnabled = true;
371
    mDynamicOutputEnabled = true;
370
}
372
}
371
373
372
QString ModelController::dynamicOutput()
374
QString ModelController::dynamicOutput()
373
{
375
{
374
    return mDynData.join("\n");
376
    return mDynData.join("\n");
375
}
377
}
376
378
377
const QStringList aggList = QStringList() << "mean" << "sum" << "min" << "max" << "p25" << "p50" << "p75" << "p5"<< "p10" << "p90" << "p95";
379
const QStringList aggList = QStringList() << "mean" << "sum" << "min" << "max" << "p25" << "p50" << "p75" << "p5"<< "p10" << "p90" << "p95";
378
void ModelController::fetchDynamicOutput()
380
void ModelController::fetchDynamicOutput()
379
{
381
{
380
    if (!mDynamicOutputEnabled || mDynFieldList.isEmpty())
382
    if (!mDynamicOutputEnabled || mDynFieldList.isEmpty())
381
        return;
383
        return;
382
    DebugTimer t("dynamic output");
384
    DebugTimer t("dynamic output");
383
    QStringList var;
385
    QStringList var;
384
    QString lastVar = "";
386
    QString lastVar = "";
385
    QVector<double> data;
387
    QVector<double> data;
386
    AllTreeIterator at(mModel);
388
    AllTreeIterator at(mModel);
387
    TreeWrapper tw;
389
    TreeWrapper tw;
388
    int var_index;
390
    int var_index;
389
    StatData stat;
391
    StatData stat;
390
    double value;
392
    double value;
391
    QStringList line;
393
    QStringList line;
392
    Expression custom_expr;
394
    Expression custom_expr;
393
    bool simple_expression;
395
    bool simple_expression;
394
    foreach (QString field, mDynFieldList) {
396
    foreach (QString field, mDynFieldList) {
395
        if (field=="count" || field=="year")
397
        if (field=="count" || field=="year")
396
            continue;
398
            continue;
397
        if (field.count()>0 && field.at(0)=='[') {
399
        if (field.count()>0 && field.at(0)=='[') {
398
            QRegExp rex("\\[(.+)\\]\\.(\\w+)");
400
            QRegExp rex("\\[(.+)\\]\\.(\\w+)");
399
            rex.indexIn(field);
401
            rex.indexIn(field);
400
            var = rex.capturedTexts();
402
            var = rex.capturedTexts();
401
            var.pop_front(); // drop first element (contains the full string)
403
            var.pop_front(); // drop first element (contains the full string)
402
            simple_expression = false;
404
            simple_expression = false;
403
        } else {
405
        } else {
404
            var = field.split(QRegExp("\\W+"), QString::SkipEmptyParts);
406
            var = field.split(QRegExp("\\W+"), QString::SkipEmptyParts);
405
            simple_expression = true;
407
            simple_expression = true;
406
        }
408
        }
407
        if (var.count()!=2)
409
        if (var.count()!=2)
408
                throw IException(QString("Invalid variable name for dynamic output:") + field);
410
                throw IException(QString("Invalid variable name for dynamic output:") + field);
409
        if (var.first()!=lastVar) {
411
        if (var.first()!=lastVar) {
410
            // load new field
412
            // load new field
411
            data.clear();
413
            data.clear();
412
            at.reset(); var_index = 0;
414
            at.reset(); var_index = 0;
413
            if (simple_expression) {
415
            if (simple_expression) {
414
                var_index = tw.variableIndex(var.first());
416
                var_index = tw.variableIndex(var.first());
415
                if (var_index<0)
417
                if (var_index<0)
416
                    throw IException(QString("Invalid variable name for dynamic output:") + var.first());
418
                    throw IException(QString("Invalid variable name for dynamic output:") + var.first());
417
419
418
            } else {
420
            } else {
419
                custom_expr.setExpression(var.first());
421
                custom_expr.setExpression(var.first());
420
                custom_expr.setModelObject(&tw);
422
                custom_expr.setModelObject(&tw);
421
            }
423
            }
422
            while (Tree *t = at.next()) {
424
            while (Tree *t = at.next()) {
423
                tw.setTree(t);
425
                tw.setTree(t);
424
                if (simple_expression)
426
                if (simple_expression)
425
                    value = tw.value(var_index);
427
                    value = tw.value(var_index);
426
                else
428
                else
427
                    value = custom_expr.execute();
429
                    value = custom_expr.execute();
428
                data.push_back(value);
430
                data.push_back(value);
429
            }
431
            }
430
            stat.setData(data);
432
            stat.setData(data);
431
        }
433
        }
432
        // fetch data
434
        // fetch data
433
        var_index = aggList.indexOf(var[1]);
435
        var_index = aggList.indexOf(var[1]);
434
        switch (var_index) {
436
        switch (var_index) {
435
            case 0: value = stat.mean(); break;
437
            case 0: value = stat.mean(); break;
436
            case 1: value = stat.sum(); break;
438
            case 1: value = stat.sum(); break;
437
            case 2: value = stat.min(); break;
439
            case 2: value = stat.min(); break;
438
            case 3: value = stat.max(); break;
440
            case 3: value = stat.max(); break;
439
            case 4: value = stat.percentile25(); break;
441
            case 4: value = stat.percentile25(); break;
440
            case 5: value = stat.median(); break;
442
            case 5: value = stat.median(); break;
441
            case 6: value = stat.percentile75(); break;
443
            case 6: value = stat.percentile75(); break;
442
            case 7: value = stat.percentile(5); break;
444
            case 7: value = stat.percentile(5); break;
443
            case 8: value = stat.percentile(10); break;
445
            case 8: value = stat.percentile(10); break;
444
            case 9: value = stat.percentile(90); break;
446
            case 9: value = stat.percentile(90); break;
445
            case 10: value = stat.percentile(95); break;
447
            case 10: value = stat.percentile(95); break;
446
            default: throw IException(QString("Invalid aggregate expression for dynamic output: %1\nallowed:%2")
448
            default: throw IException(QString("Invalid aggregate expression for dynamic output: %1\nallowed:%2")
447
                                  .arg(var[1]).arg(aggList.join(" ")));
449
                                  .arg(var[1]).arg(aggList.join(" ")));
448
        }
450
        }
449
        line+=QString::number(value);
451
        line+=QString::number(value);
450
    }
452
    }
451
    line.prepend( QString::number(data.size()) );
453
    line.prepend( QString::number(data.size()) );
452
    line.prepend( QString::number(GlobalSettings::instance()->currentYear()) );
454
    line.prepend( QString::number(GlobalSettings::instance()->currentYear()) );
453
    mDynData.append(line.join(";"));
455
    mDynData.append(line.join(";"));
454
}
456
}
455
457
456
void ModelController::saveScreenshot(QString file_name)
458
void ModelController::saveScreenshot(QString file_name)
457
{
459
{
458
#ifdef ILAND_GUI
460
#ifdef ILAND_GUI
459
    if (!mViewerWindow)
461
    if (!mViewerWindow)
460
        return;
462
        return;
461
    QImage img = mViewerWindow->screenshot();
463
    QImage img = mViewerWindow->screenshot();
462
    img.save(file_name);
464
    img.save(file_name);
463
#endif
465
#endif
464
}
466
}
465
467
466
void ModelController::paintMap(MapGrid *map, double min_value, double max_value)
468
void ModelController::paintMap(MapGrid *map, double min_value, double max_value)
467
{
469
{
468
#ifdef ILAND_GUI
470
#ifdef ILAND_GUI
469
    if (mViewerWindow) {
471
    if (mViewerWindow) {
470
        mViewerWindow->paintGrid(map, "", GridViewRainbow, min_value, max_value);
472
        mViewerWindow->paintGrid(map, "", GridViewRainbow, min_value, max_value);
471
        qDebug() << "painted map grid" << map->name() << "min-value (blue):" << min_value << "max-value(red):" << max_value;
473
        qDebug() << "painted map grid" << map->name() << "min-value (blue):" << min_value << "max-value(red):" << max_value;
472
    }
474
    }
473
#else
475
#else
474
    Q_UNUSED(map);Q_UNUSED(min_value);Q_UNUSED(max_value);
476
    Q_UNUSED(map);Q_UNUSED(min_value);Q_UNUSED(max_value);
475
#endif
477
#endif
476
}
478
}
477
479
478
void ModelController::addGrid(const FloatGrid *grid, const QString &name, const GridViewType view_type, double min_value, double max_value)
480
void ModelController::addGrid(const FloatGrid *grid, const QString &name, const GridViewType view_type, double min_value, double max_value)
479
{
481
{
480
#ifdef ILAND_GUI
482
#ifdef ILAND_GUI
481
483
482
    if (mViewerWindow) {
484
    if (mViewerWindow) {
483
        mViewerWindow->paintGrid(grid, name, view_type, min_value, max_value);
485
        mViewerWindow->paintGrid(grid, name, view_type, min_value, max_value);
484
        qDebug() << "painted grid min-value (blue):" << min_value << "max-value(red):" << max_value;
486
        qDebug() << "painted grid min-value (blue):" << min_value << "max-value(red):" << max_value;
485
    }
487
    }
486
#else
488
#else
487
    Q_UNUSED(grid); Q_UNUSED(name); Q_UNUSED(view_type); Q_UNUSED(min_value);Q_UNUSED(max_value);
489
    Q_UNUSED(grid); Q_UNUSED(name); Q_UNUSED(view_type); Q_UNUSED(min_value);Q_UNUSED(max_value);
488
#endif
490
#endif
489
}
491
}
490
492
491
void ModelController::addLayers(const LayeredGridBase *layers, const QString &name)
493
void ModelController::addLayers(const LayeredGridBase *layers, const QString &name)
492
{
494
{
493
#ifdef ILAND_GUI
495
#ifdef ILAND_GUI
494
    if (mViewerWindow)
496
    if (mViewerWindow)
495
        mViewerWindow->addLayers(layers, name);
497
        mViewerWindow->addLayers(layers, name);
496
    //qDebug() << layers->names();
498
    //qDebug() << layers->names();
497
#else
499
#else
498
    Q_UNUSED(layers); Q_UNUSED(name);
500
    Q_UNUSED(layers); Q_UNUSED(name);
499
#endif
501
#endif
500
}
502
}
501
503
502
void ModelController::setViewport(QPointF center_point, double scale_px_per_m)
504
void ModelController::setViewport(QPointF center_point, double scale_px_per_m)
503
{
505
{
504
#ifdef ILAND_GUI
506
#ifdef ILAND_GUI
505
    if (mViewerWindow)
507
    if (mViewerWindow)
506
        mViewerWindow->setViewport(center_point, scale_px_per_m);
508
        mViewerWindow->setViewport(center_point, scale_px_per_m);
507
#else
509
#else
508
    Q_UNUSED(center_point);Q_UNUSED(scale_px_per_m);
510
    Q_UNUSED(center_point);Q_UNUSED(scale_px_per_m);
509
#endif
511
#endif
510
}
512
}
511
513
512
void ModelController::repaint()
514
void ModelController::repaint()
513
{
515
{
514
#ifdef ILAND_GUI
516
#ifdef ILAND_GUI
515
    if (mViewerWindow)
517
    if (mViewerWindow)
516
        mViewerWindow->repaint();
518
        mViewerWindow->repaint();
517
#endif
519
#endif
518
}
520
}
519
521
520
522
521
523
522
 
524