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 | |||
504 | werner | 20 | #include "saplingout.h" |
21 | #include "model.h" |
||
22 | #include "resourceunit.h" |
||
1162 | werner | 23 | #include "saplings.h" |
504 | werner | 24 | #include "species.h" |
25 | |||
26 | SaplingOut::SaplingOut() |
||
27 | { |
||
28 | |||
29 | setName("Sapling Output", "sapling"); |
||
30 | setDescription("Output of the establishment/sapling layer per resource unit and species.\n" \ |
||
31 | "The output covers trees between a dbh of 1cm and the recruitment threshold (i.e. a height of 4m)." \ |
||
950 | werner | 32 | "Cohorts with a dbh < 1cm are counted in 'cohort_count_ha' but not used for average calculations.\n\n" \ |
33 | "You can specify a 'condition' to limit execution for specific time/ area with the variables 'ru' (resource unit id) and 'year' (the current year)"); |
||
570 | werner | 34 | columns() << OutputColumn::year() << OutputColumn::ru() << OutputColumn::id() << OutputColumn::species() |
1177 | werner | 35 | << OutputColumn("count_ha", "number of represented individuals per ha (tree height >1.3m).", OutInteger) |
36 | << OutputColumn("count_small_ha", "number of represented individuals per ha (with height <=1.3m).", OutInteger) |
||
504 | werner | 37 | << OutputColumn("cohort_count_ha", "number of cohorts per ha.", OutInteger) |
1177 | werner | 38 | << OutputColumn("height_avg_m", "arithmetic average height of the cohorts (m) ", OutDouble) |
39 | << OutputColumn("age_avg", "arithmetic average age of the sapling cohorts (years)", OutDouble); |
||
504 | werner | 40 | } |
41 | |||
42 | void SaplingOut::setup() |
||
43 | { |
||
950 | werner | 44 | // use a condition for to control execuation for the current year |
45 | QString condition = settings().value(".condition", ""); |
||
46 | mCondition.setExpression(condition); |
||
47 | if (!mCondition.isEmpty()) { |
||
48 | mVarRu = mCondition.addVar("ru"); |
||
49 | mVarYear = mCondition.addVar("year"); |
||
50 | } |
||
504 | werner | 51 | } |
52 | |||
53 | void SaplingOut::exec() |
||
54 | { |
||
55 | Model *m = GlobalSettings::instance()->model(); |
||
950 | werner | 56 | |
504 | werner | 57 | double n, avg_dbh, avg_height, avg_age; |
58 | foreach(ResourceUnit *ru, m->ruList()) { |
||
574 | werner | 59 | if (ru->id()==-1) |
60 | continue; // do not include if out of project area |
||
61 | |||
950 | werner | 62 | if (!mCondition.isEmpty()) { |
63 | *mVarRu = ru->id(); |
||
64 | *mVarYear = GlobalSettings::instance()->currentYear(); |
||
65 | if (!mCondition.execute() ) |
||
66 | continue; |
||
67 | } |
||
68 | |||
504 | werner | 69 | foreach(const ResourceUnitSpecies *rus, ru->ruSpecies()) { |
70 | const StandStatistics &stat = rus->constStatistics(); |
||
1162 | werner | 71 | const SaplingStat &sap = const_cast<ResourceUnitSpecies*>(rus)->saplingStat(); |
504 | werner | 72 | |
73 | if (stat.saplingCount()==0) |
||
74 | continue; |
||
570 | werner | 75 | *this << currentYear() << ru->index() << ru->id() << rus->species()->id(); // keys |
504 | werner | 76 | |
77 | // calculate statistics based on the number of represented trees per cohort |
||
1162 | werner | 78 | n = sap.livingStemNumber(rus->species(), avg_dbh, avg_height, avg_age); |
1177 | werner | 79 | *this << sap.livingSaplings() |
80 | << sap.livingSaplingsSmall() |
||
81 | << sap.livingCohorts() |
||
82 | << sap.averageHeight() |
||
83 | << sap.averageAge(); |
||
504 | werner | 84 | writeRow(); |
85 | } |
||
86 | } |
||
87 | } |
||
1182 | werner | 88 | |
89 | SaplingDetailsOut::SaplingDetailsOut() |
||
90 | { |
||
91 | setName("Sapling Details Output", "saplingdetail"); |
||
92 | setDescription("Detailed output on indidvidual sapling cohorts.\n" \ |
||
1183 | werner | 93 | "For each occupied and living 2x2m pixel, a row is generated, unless" \ |
94 | "the tree diameter is below the 'minDbh' threshold (cm). " \ |
||
95 | "You can further specify a 'condition' to limit execution for specific time/ area with the variables 'ru' (resource unit id) and 'year' (the current year)."); |
||
1182 | werner | 96 | columns() << OutputColumn::year() << OutputColumn::ru() << OutputColumn::id() << OutputColumn::species() |
97 | << OutputColumn("n_represented", "number of trees that are represented by the cohort (Reineke function).", OutDouble) |
||
98 | << OutputColumn("dbh", "diameter of the cohort (cm).", OutDouble) |
||
99 | << OutputColumn("height", "height of the cohort (m).", OutDouble) |
||
100 | << OutputColumn("age", "age of the cohort (years) ", OutInteger); |
||
101 | |||
102 | } |
||
103 | |||
104 | void SaplingDetailsOut::exec() |
||
105 | { |
||
106 | Model *m = GlobalSettings::instance()->model(); |
||
107 | |||
108 | foreach(ResourceUnit *ru, m->ruList()) { |
||
109 | if (ru->id()==-1) |
||
110 | continue; // do not include if out of project area |
||
111 | |||
112 | // exclude if a condition is specified and condition is not met |
||
113 | if (!mCondition.isEmpty()) { |
||
114 | *mVarRu = ru->id(); |
||
115 | *mVarYear = GlobalSettings::instance()->currentYear(); |
||
116 | if (!mCondition.execute() ) |
||
117 | continue; |
||
118 | } |
||
119 | SaplingCell *s = ru->saplingCellArray(); |
||
120 | for (int px=0;px<cPxPerHectare;++px, ++s) { |
||
121 | int n_on_px = s->n_occupied(); |
||
122 | if (n_on_px>0) { |
||
123 | for (int i=0;i<NSAPCELLS;++i) { |
||
124 | if (s->saplings[i].is_occupied()) { |
||
125 | ResourceUnitSpecies *rus = s->saplings[i].resourceUnitSpecies(ru); |
||
126 | const Species *species = rus->species(); |
||
1183 | werner | 127 | double dbh = s->saplings[i].height / species->saplingGrowthParameters().hdSapling * 100.; |
128 | // check minimum dbh |
||
129 | if (dbh<mMinDbh) |
||
130 | continue; |
||
131 | |||
1182 | werner | 132 | double n_repr = species->saplingGrowthParameters().representedStemNumberH(s->saplings[i].height) / static_cast<double>(n_on_px); |
133 | |||
134 | *this << currentYear() << ru->index() << ru->id() << rus->species()->id(); |
||
1183 | werner | 135 | *this << n_repr << dbh << s->saplings[i].height << s->saplings[i].age; |
1182 | werner | 136 | writeRow(); |
137 | } |
||
138 | } |
||
139 | } |
||
140 | } |
||
141 | } |
||
142 | } |
||
143 | |||
144 | void SaplingDetailsOut::setup() |
||
145 | { |
||
146 | // use a condition for to control execuation for the current year |
||
147 | QString condition = settings().value(".condition", ""); |
||
148 | mCondition.setExpression(condition); |
||
149 | if (!mCondition.isEmpty()) { |
||
150 | mVarRu = mCondition.addVar("ru"); |
||
151 | mVarYear = mCondition.addVar("year"); |
||
152 | } |
||
1183 | werner | 153 | mMinDbh = settings().valueDouble(".minDbh"); |
1182 | werner | 154 | } |