Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 51 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,48 @@
# GROWTH SIMULATOR
# STAND GROWTH SIMULATOR
### SIMULADOR DE CRECIMIENTO EN RODALES

A timber plantation growth simulator, with stands and management policies options.
This repo contains a timber plantation growth simulator, for stands generating various management policy options. It's entirely made in python with simple dependencies.

Based on !["Modelos de predicción de biomasa a nivel de rodal en plantaciones de Eucalyptus globulus y Pinus radiata en Zona centro sur de en Chile"](Modelos%20de%20predicción%20de%20biomasa%20a%20nivel%20de%20rodal%20en%20plantaciones%20de%20Eucalyptus%20globulus%20en%20Chile.pdf). By: Alejandro Miranda, Blas Mola and Víctor Hinojosa
The code is based on the paper: !["Modelos de predicción de biomasa a nivel de rodal en plantaciones de Eucalyptus globulus y Pinus radiata en Zona centro sur de en Chile"](Modelos%20de%20predicción%20de%20biomasa%20a%20nivel%20de%20rodal%20en%20plantaciones%20de%20Eucalyptus%20globulus%20en%20Chile.pdf). By: Alejandro Miranda, Blas Mola and Víctor Hinojosa

1. For 34 types of eucalyptus and pinus plantations in the central-south of Chile, a statistical study fitted the following power law (tabla.csv):

For 34 types of eucalyptus and pinus plantations in the central-south of Chile, a statistical study fitted the power law found in `tabla.csv`.
The result file of the statistical study includes the following information for each of the 34 combinations of species and rotation type:

|Attribute|Translation description|
|--|--|
|id| model identification representing the type of stand|
|Next| id of the model the stand would turn into if it is thinned. When `null`, the stand can't be thinned (eucalyptus for example).|
|Prev|Previous, opposite of next; the id of the stand before it would've been thinned.|
|Especie|species of the stand (pinus or eucalyptus).|
|Zona de crecimiento|Zone of Chile where the stand is growing. It depends on the species of the stand (pinus and eucalyptus have diferent zones).|
|Edad del rodal|Age of the stand.|
|Densidad Inicial (n init)|Initial density of the stand for ha.|
|Índice de Sitio (SI)|Site index, mean height of the stands of 10 years.|
|Manejo aplicado al rodal|management of the stand (Pulpable, Multiproposito, Intensivo 1, Intensivo 2 or Sin manejo).|
|Condición|Condition of the stand. It can be "posterior Raleo" (post thinning), "posterior a poda y raleo" (post thinning and prunning)|
|$\alpha$,$\beta$, $\gamma$|coeficents for the biomass model|
|stableyear|year when the formula begins to yield stable results (it depends on the type of pinus).|



The managment of the stand, can be anyone of the next:

• ***Pulpable***: pulpwood, case where the stand thinn for disposal.

• ***Multipropósito***: multiporpuse, when the stand is thinned and pruned 2 times.

• ***Intensivo 1***: Intensive 1, when the stand pruned 3 times and thinned 2 times.

• ***Intensivo 2***: Intensive 2, like intensive 1, but with a different site cuality.

• ***Sin manejo***: wihtout any managment.|

1. The equation to get biomass for a stand of age t is:
$$
biomass(t) = \alpha \cdot t^\beta + \gamma
$$

1. To extrapolate to earlier years; due to the formula yielding negative values (for a few types of pinus). A linear adjustment was made:
2. To extrapolate to earlier years; due to the formula yielding negative values (for a few types of pinus). A linear adjustment was made:

$$
\text{biomass}(t) =
Expand All @@ -22,32 +54,34 @@ $$

_Stable year is the year when the formula begins to yield stable results (it depends on the type of pinus)._

1. A template for generating a timber plantation and different management policies was made (config.toml)
3. A template for generating a timber plantation and different management policies was made (config.toml)

```toml
horizonte = 10 # number of years to generate
rodales = 36 # number of stands to generate, choosing one model at random
horizon = 10 # number of years to generate


[random]
# random number generator seed: omit or comment for different results each run
seed = 5
# `low` (inclusive) to `high` (exclusive)
# n, n+1 for getting a single value: n
# see np.random.randint
edades = [1, 18] # min, max age of generated stands
ages = [1, 18] # min, max age of generated stands
has = [5, 15] # min, max hectares of generated stands
stands = 36 # number of stands to generate, choosing one model at random

# ranges: start, stop, step
# n, n+1 for getting a single value range: [n]
# see np.arange
[eucalyptus]
cosechas = [10, 20, 3] # for each Eucalyptus stand, generate different biomass histories harvesting in the year 10, 13, 16 and 19 (4 histories)
harvest = [10, 20, 3] # for each Eucalyptus stand, generate different biomass histories harvesting in the year 10, 13, 16 and 19 (4 histories)

[pino]
raleos = [6, 11, 2] # thinning policies in the years 6, 8, 10.
cosechas = [18, 29, 3] # harvesting policies in the years 18, 21, 24, ... (every 3 years)
[pino] #pinus
thinning = [6, 11, 2] # thinning policies in the years 6, 8, 10.
harvest = [18, 29, 3] # harvesting policies in the years 18, 21, 24, ... (every 3 years)
# all feasible histories combining thinning and harvesting policies will be generated
min_ral = 6 #lower bound to tree thinning actions
```
min_thinning = 6 #lower bound to tree thinning actions
```

1. For a real instance, the numbers of stands and its characteristics can be passed instead of generated at random. For this a `.csv` or `.shp` file is used, the data must include the following fields:

Expand All @@ -56,7 +90,7 @@ _Stable year is the year when the formula begins to yield stable results (it dep
- **age**: Age of the stand
- **hectare (ha)**: Area in hectares

See `auxiliary.py` for GIS extraction or creation of this attributes table `bosque_data.csv` using the methods `get_data` and `create_bosque`.
See `auxiliary.py` for GIS extraction or creation of this attributes table `bosque_data.csv` using the methods `get_data` and `create_forest`.

### quick start

Expand Down
17 changes: 8 additions & 9 deletions auxiliary.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,12 @@ def get_data(filepath=".\\test\\data_base\\proto.shp"):
datasource = None"""


def create_forest(gdf, id="fid"):
"""Crea un bosque a partir de un geopandas dataframe"""
def create_forest(gdf, id="fid", mid="growth_mid", outfile="bosque_data.csv"):
if "area_ha" not in gdf.columns:
gdf["area_ha"] = gdf.geometry.area / 1e4
data_rodales = gdf.dropna(subset=["edad"])
data_rodales_2 = data_rodales.loc[data_rodales["area_ha"] > 0]
bos_names = ["rid", "mid", "edad_inicial", "ha"] # aprender hacer formato decente
bos_names = ["rid", "growth_mid", "edad_inicial", "ha"] # aprender hacer formato decente
rodales = []

for idx, r in data_rodales_2.iterrows():
Expand All @@ -61,20 +62,18 @@ def create_forest(gdf, id="fid"):
e0 = r["edad"]
ha = r["area_ha"]
rodal = {
"rid": r[id], # r["fid"] en caso habitual
"mid": r["id"],
"rid": r[id],
"growth_mid": r[mid],
"edad_inicial": e0,
"ha": ha,
}
rodales += [rodal]

bos = np.array(
[tuple(r[k] for k in bos_names) for r in rodales],
dtype=[("rid", "i4"), ("mid", "i4"), ("edad_inicial", "i4"), ("ha", "f4")],
)
np.savetxt(
"bosque_data.csv", bos, delimiter=",", header=",".join(bos_names), comments="", fmt=["%d", "%d", "%d", "%.2f"]
dtype=[("rid", "i4"), ("growth_mid", "i4"), ("edad_inicial", "i4"), ("ha", "f4")],
)
np.savetxt(outfile, bos, delimiter=",", header=",".join(bos_names), comments="", fmt=["%d", "%d", "%d", "%.2f"])


def plot_1_id_model(horizon: int = 40, show=True, save=False, target_id: int = 30):
Expand Down
25 changes: 15 additions & 10 deletions config.toml
Original file line number Diff line number Diff line change
@@ -1,25 +1,30 @@
horizonte = 10
rodales = 36
#
horizon = 10
#tabla de los modelos de crecieminto
models_table="tabla.csv"
study_area = "fdo/instance1_growth_attributes.shp"
id = "fid"



[random]
# random number generator seed: omit or comment for different results each run
seed = 4
# `low` (inclusive) to `high` (exclusive)
# n, n+1 for getting a single value: n
# see np.random.randint
edades = [1, 18]
ages = [1, 18]
has = [5, 15]
stands = 36

# ranges: start, stop, step
# n, n+1 for getting a single value range: [n]
# see np.arange
[pino]
podas = [5, 15, 5] # not implemented
raleos = [6, 11, 1]
cosechas = [18, 29, 1]
min_ral = 6
pruning = [5, 15, 5] # not implemented
thinning = [6, 11, 1]
harvest = [18, 29, 1]
min_thinning = 6

[eucalyptus]
podas = [4, 6, 2] # not implemented
cosechas = [8, 13, 1]

harvest = [8, 13, 1]
Loading