Rev 1221 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
671 | werner | 1 | /******************************************************************************************** |
2 | ** iLand - an individual based forest landscape and disturbance model |
||
3 | ** http://iland.boku.ac.at |
||
4 | ** Copyright (C) 2009- Werner Rammer, Rupert Seidl |
||
5 | ** |
||
6 | ** This program is free software: you can redistribute it and/or modify |
||
7 | ** it under the terms of the GNU General Public License as published by |
||
8 | ** the Free Software Foundation, either version 3 of the License, or |
||
9 | ** (at your option) any later version. |
||
10 | ** |
||
11 | ** This program is distributed in the hope that it will be useful, |
||
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
14 | ** GNU General Public License for more details. |
||
15 | ** |
||
16 | ** You should have received a copy of the GNU General Public License |
||
17 | ** along with this program. If not, see <http://www.gnu.org/licenses/>. |
||
18 | ********************************************************************************************/ |
||
19 | |||
243 | werner | 20 | #include "global.h" |
242 | werner | 21 | #include "climateconverter.h" |
243 | werner | 22 | #include "csvfile.h" |
23 | |||
793 | werner | 24 | #include <QJSEngine> |
25 | #include <QJSValue> |
||
243 | werner | 26 | #include <QtSql> |
242 | werner | 27 | |
248 | werner | 28 | /** @class ClimateConverter |
29 | Converts text-file-based data into the iLand climate data format. |
||
243 | werner | 30 | For the iLand format see the wiki (ClimateFormat). For each column (i.e. year,month, day, |
31 | temp, prec, rad, vpd), an expression providing access to the columns of the input file calculates |
||
32 | the respective output value. Propertes tableName and fileName define the input file and the |
||
33 | name of the output table (located in the "climate"-database of iLand) respectively. |
||
34 | */ |
||
247 | werner | 35 | /** @group script |
36 | @class ClimateConverter |
||
37 | This is the Scripting related documentation for the ClimateConverter tool. |
||
38 | */ |
||
793 | werner | 39 | //Q_SCRIPT_DECLARE_QMETAOBJECT(ClimateConverter, QObject*) |
40 | void ClimateConverter::addToScriptEngine(QJSEngine &engine) |
||
242 | werner | 41 | { |
42 | // about this kind of scripting magic see: http://qt.nokia.com/developer/faqs/faq.2007-06-25.9557303148 |
||
793 | werner | 43 | //QJSValue cc_class = engine.scriptValueFromQMetaObject<ClimateConverter>(); |
242 | werner | 44 | // the script name for the object is "ClimateConverter". |
793 | werner | 45 | QObject *cc = new ClimateConverter(); |
46 | QJSValue cc_class = engine.newQObject(cc); |
||
242 | werner | 47 | engine.globalObject().setProperty("ClimateConverter", cc_class); |
48 | } |
||
49 | |||
766 | werner | 50 | ClimateConverter::ClimateConverter(QObject *) |
242 | werner | 51 | { |
244 | werner | 52 | mCaptions = true; |
242 | werner | 53 | bindExpression(mExpYear, 0); |
54 | bindExpression(mExpMonth, 1); |
||
55 | bindExpression(mExpDay, 2); |
||
56 | |||
57 | bindExpression(mExpTemp, 3); |
||
414 | werner | 58 | bindExpression(mExpMinTemp, 4); |
242 | werner | 59 | |
414 | werner | 60 | bindExpression(mExpPrec, 5); |
61 | bindExpression(mExpRad, 6); |
||
62 | bindExpression(mExpVpd, 7); |
||
242 | werner | 63 | } |
64 | |||
414 | werner | 65 | |
66 | |||
242 | werner | 67 | void ClimateConverter::bindExpression(Expression &expr, int index) |
68 | { |
||
243 | werner | 69 | expr.setExpression(QString("c%1").arg(index) ); // "cX" is the default expression |
242 | werner | 70 | for (int i=0;i<10;i++) |
71 | mVars[index*10 + i] = expr.addVar( QString("c%1").arg(i) ); |
||
72 | } |
||
73 | |||
74 | void ClimateConverter::run() |
||
75 | { |
||
76 | mExpYear.setExpression(mYear); |
||
77 | mExpMonth.setExpression(mMonth); |
||
78 | mExpDay.setExpression(mDay); |
||
79 | |||
80 | mExpTemp.setExpression(mTemp); |
||
414 | werner | 81 | mExpMinTemp.setExpression(mMinTemp); |
242 | werner | 82 | mExpPrec.setExpression(mPrec); |
83 | mExpRad.setExpression(mRad); |
||
84 | mExpVpd.setExpression(mVpd); |
||
243 | werner | 85 | // prepare output database |
244 | werner | 86 | if (mDatabase.isEmpty()) { |
87 | qDebug() << "ClimateConverter: database is empty!"; |
||
88 | return; |
||
89 | } |
||
90 | QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE","cctemp"); |
||
91 | db.setDatabaseName(mDatabase); |
||
92 | if (!db.open()) { |
||
93 | qDebug() << "ClimateConverter: invalid database: " << db.lastError().text(); |
||
94 | return; |
||
95 | } |
||
96 | |||
97 | QSqlQuery creator(db); |
||
243 | werner | 98 | if (mTableName.isEmpty()) { |
99 | qDebug() << "ClimateConverter::run: invalid climate database or table name."; |
||
100 | } |
||
244 | werner | 101 | QString sql=QString("CREATE TABLE %1 ( " \ |
102 | "year INTEGER, month INTEGER, day INTEGER, " \ |
||
414 | werner | 103 | "temp REAL, min_temp REAL, prec REAL, rad REAL, vpd REAL)").arg(mTableName); |
242 | werner | 104 | |
243 | werner | 105 | QString drop=QString("drop table if exists %1").arg(mTableName); |
244 | werner | 106 | |
243 | werner | 107 | creator.exec(drop); // drop table (if exists) |
244 | werner | 108 | if (creator.lastError().isValid()) { |
109 | qDebug() << "ClimateConverter: Sql-Error (drop):" << creator.lastError().text(); |
||
110 | return; |
||
111 | } |
||
243 | werner | 112 | creator.exec(sql); // (re-)create table |
244 | werner | 113 | if (creator.lastError().isValid()) { |
114 | qDebug() << "ClimateConverter: Sql-Error (create table):" << creator.lastError().text(); |
||
115 | return; |
||
116 | } |
||
117 | |||
243 | werner | 118 | // prepare insert statement |
414 | werner | 119 | sql = QString("insert into %1 (year, month, day, temp, min_temp, prec, rad, vpd) values (?,?,?, ?,?,?,?,?)").arg(mTableName); |
243 | werner | 120 | creator.prepare(sql); |
244 | werner | 121 | if (creator.lastError().isValid()) { |
122 | qDebug() << "ClimateConverter: Sql-Error (prepare):" << creator.lastError().text(); |
||
123 | return; |
||
124 | } |
||
243 | werner | 125 | // load file |
126 | if (mFileName.isEmpty()) { |
||
127 | qDebug() << "ClimateConverter::run: empty filename."; |
||
128 | return; |
||
129 | } |
||
244 | werner | 130 | CSVFile file; |
131 | file.setHasCaptions(mCaptions); |
||
132 | file.loadFile(mFileName); |
||
243 | werner | 133 | if (!file.rowCount()) { |
134 | qDebug() << "ClimateConverter::run: cannot load file:" << mFileName; |
||
135 | return; |
||
136 | } |
||
244 | werner | 137 | |
243 | werner | 138 | // do this for each row |
139 | double value; |
||
140 | int year, month, day; |
||
414 | werner | 141 | double temp, min_temp, prec, rad, vpd; |
243 | werner | 142 | int rows=0; |
244 | werner | 143 | db.transaction(); |
243 | werner | 144 | for (int row=0;row<file.rowCount(); row++) { |
145 | // fetch values from input file |
||
146 | for (int col=0;col<file.colCount(); col++) { |
||
245 | werner | 147 | value = file.value(row, col).toDouble(); |
243 | werner | 148 | // store value in each of the expression variables |
414 | werner | 149 | for (int j=0;j<8;j++) |
243 | werner | 150 | *(mVars[j*10 + col]) = value; // store in the locataion mVars[x] points to. |
242 | werner | 151 | } |
243 | werner | 152 | // calculate new values.... |
153 | year = (int)mExpYear.execute(); |
||
154 | month = (int)mExpMonth.execute(); |
||
155 | day = (int)mExpDay.execute(); |
||
156 | temp = mExpTemp.execute(); |
||
414 | werner | 157 | min_temp = mExpMinTemp.execute(); |
243 | werner | 158 | prec = mExpPrec.execute(); |
159 | rad = mExpRad.execute(); |
||
160 | vpd = mExpVpd.execute(); |
||
244 | werner | 161 | //qDebug() << year << month << day << temp << prec << rad << vpd; |
243 | werner | 162 | // bind values |
163 | creator.bindValue(0,year); |
||
164 | creator.bindValue(1,month); |
||
165 | creator.bindValue(2,day); |
||
166 | creator.bindValue(3,temp); |
||
414 | werner | 167 | creator.bindValue(4,min_temp); |
168 | creator.bindValue(5,prec); |
||
169 | creator.bindValue(6,rad); |
||
170 | creator.bindValue(7,vpd); |
||
243 | werner | 171 | creator.exec(); |
172 | rows++; |
||
173 | if (creator.lastError().isValid()) { |
||
174 | qDebug() << "ClimateConverter: Sql-Error:" << creator.lastError().text(); |
||
244 | werner | 175 | return; |
243 | werner | 176 | } |
242 | werner | 177 | } |
244 | werner | 178 | db.commit(); |
179 | creator.clear(); |
||
180 | db.close(); |
||
181 | QSqlDatabase::removeDatabase("cctemp"); |
||
243 | werner | 182 | qDebug() << "ClimateConverter::run: processing complete." << rows << "rows inserted."; |
244 | werner | 183 | |
242 | werner | 184 | } |