Skip to content

Commit 2d7b78d

Browse files
committed
Module docstrings updated
1 parent 4e146ad commit 2d7b78d

11 files changed

Lines changed: 276 additions & 61 deletions

File tree

DSSATTools/__init__.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,12 @@
3333
>>> insi='UNCU', lat=4.34, long=-74.40, elev=1800,
3434
>>> table=df_with_data
3535
>>> )
36-
>>> soil = SoilProfile.from_file('IBSG910085')
36+
>>> soil = SoilProfile.from_file('IBSG910085', 'SOIL.SOL')
3737
>>> field = Field(
3838
>>> id_field='ITHY0001', wsta=weather_station, flob=0,
3939
>>> fldd=0, flds=0, id_soil=soil, fldt='DR000'
4040
>>> )
41-
>>> planting = planting = Planting(
41+
>>> planting = Planting(
4242
>>> pdate=date(1980, 6, 17), ppop=18, ppoe=18,
4343
>>> plme='S', plds='R', plrs=45, plrd=0, pldp=5
4444
>>> )
@@ -91,11 +91,11 @@
9191
VERSION = '048'
9292

9393
from DSSATTools import crop
94-
from DSSATTools.soil import SoilProfile
95-
from DSSATTools.weather import WeatherStation
94+
from DSSATTools.soil import SoilProfile, SoilLayer
95+
from DSSATTools.weather import WeatherStation, WeatherRecord
9696
from DSSATTools.run import DSSAT
9797
from DSSATTools import filex
9898

9999
__all__ = [
100-
'crop', 'SoilProfile', 'WeatherStation', 'DSSAT',
100+
'crop', 'SoilProfile', 'WeatherStation', 'DSSAT', 'filex'
101101
]

DSSATTools/crop.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,20 @@
11
'''
2-
2+
This module hosts the classes that represent each crop. Not all crops are
3+
implemented. Each crop class is child of a generic Crop class. A crop is
4+
instantiated by passing the cultivar code:
5+
>>> crop = Sorghum('IB0026')
6+
This will create a dictionary-like object with keys as the cultivar parameters'
7+
names. Then, the cultivar parameters can be modified
8+
by assigning values:
9+
>>> crop['p1'] = 450.
10+
>>> crop['g1'] = 0.1
11+
The ecotype parameter is itself a dictionary-like object with the ecotype
12+
parameters' names as keys. Then, the ecotype parameters are modified in the same
13+
way as the cultivar parameters:
14+
>>> crop['eco#']['topt'] = 35.5
15+
The cultivar_list class function will return a list of all the cultivars availble
16+
for a crop:
17+
>>> available_cultivars = Sorghum.cultivar_list()
318
'''
419
import os
520
from . import VERSION

DSSATTools/filex.py

Lines changed: 88 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,90 @@
11
"""
2-
File X module.
3-
4-
5-
6-
SimulationOptions and Treatment:
7-
They are only to represent those sections.
2+
This module implement the sections of the DSSAT FileX as python objects. All
3+
sections are implemented, excepting the enviromental modifications section.
4+
Environmental modifications can be easily implemented by modifying the Weather
5+
component of each experiment. One section object represents a single factor
6+
level in the experiment.
7+
8+
Each section is defined using the same parameter names (lowercase) of the DSSAT
9+
FileX. For example, planting date is defined as follow:
10+
>>> planting = Planting(
11+
>>> pdate=date(1980, 6, 17), ppop=18, ppoe=18,
12+
>>> plme='S', plds='R', plrs=45, plrd=0, pldp=5
13+
>>> )
14+
15+
Sections that include a schedule or soil profile (i.e. Initial conditions), are
16+
defined as a list of individual events or soil layers. For example, a fertilizer
17+
section with two fertilizer events is defined as follows:
18+
>>> fertilizer = Fertilizer(table=[
19+
>>> FertilizerEvent(
20+
>>> fdate=date(1980, 7, 4), fmcd='FE005', fdep=5,
21+
>>> famn=80, facd='AP002'
22+
>>> ),
23+
>>> FertilizerEvent(
24+
>>> fdate=date(1980, 8, 7), fmcd='FE005', fdep=5,
25+
>>> famn=80, facd='AP002'
26+
>>> )
27+
>>> ])
28+
Other sections based on events are irrigation, residue, chemical, and tillage.
29+
30+
Note that the Fertilizer object is initialized by passing a list of FertilizerEvent
31+
objects in the 'table' parameter. The table parameter also accepts DataFrames,
32+
only if the column names of that DataFrame match the parameters for the individual
33+
event or layer object. Next is an example of this for the initial conditions section:
34+
>>> initial_conditions = InitialConditions(
35+
>>> pcr='SG', icdat=date(1980, 6, 1), icrt=500, icnd=0,
36+
>>> icrn=1, icre=1, icres=1300, icren=.5, icrep=0, icrip=100, icrid=10,
37+
>>> table=pd.DataFrame([
38+
>>> (10, .06, 2.5, 1.8),
39+
>>> (22, .06, 2.5, 1.8),
40+
>>> (52, .195, 3., 4.5),
41+
>>> (82, .21, 3.5, 5.0),
42+
>>> (112, 0.2, 2., 2.0),
43+
>>> (142, 0.2, 1., 0.7),
44+
>>> (172, 0.2, 1., 0.6),
45+
>>> ], columns=['icbl', 'sh2o', 'snh4', 'sno3'])
46+
>>> )
47+
Note that InitialConditions have more parameters besides the table parameter. The
48+
column names of the passed DataFrame are the same as the parameters for the
49+
InitialConditionsLayer class. The soil analysis section is the other section based
50+
on soil layers.
51+
52+
The field and cultivar sections are the only sections that need other DSSATTools
53+
objects as input parameters. In this section, the 'wsta' must be a WeatherStation
54+
object, and the 'id_soil' must be a SoilProfile object.
55+
>>> field = Field(
56+
>>> id_field='ITHY0001', wsta=weather_station, flob=0, fldt='DR000',
57+
>>> fldd=0, flds=0, id_soil=soil
58+
>>> )
59+
'wsta' and 'id_soil' also receives weather station and soil profile ids as strings.
60+
However, this wouldn't make sense in the context of running DSSAT using this package.
61+
62+
The cultivar can be defined either using the Cultivar class, or by directly using the
63+
one of the classes defined in DSSATTools.crop.
64+
>>> cultivar = Sorghum('IB0026')
65+
>>> cultivar = Cultivar(cr='SG', ingeno='IB0026', cname='CSH-1')
66+
These two definitions will yield the same result. However, when the cultivar is
67+
defined using the crop class it is posible to modify the cultivar and ecotype
68+
coefficients. More information is found at the DSSATTools.crop module documentation.
69+
70+
Finally, the simulations controls is created by using the SimulationsControls
71+
class. Each sub-section of the simulation controls sections is created using its
72+
own class. Next example shows how to create the simulations controls defining only
73+
the general options.
74+
>>> simulation_controls = SimulationControls(
75+
>>> general=SCGeneral(sdate=date(1980, 6, 1))
76+
>>> )
77+
78+
The sections can be created from an existing FileX using the read_filex function.
79+
That function will return a dictionary, mapping each treatment to its correspondent
80+
section definitions. The next example reads an existing FileX, and then assigns
81+
the first treatment to the treatment variable. In this case, treatment is a
82+
dictionary mapping each section name to its python object.
83+
>>> treatments = read_filex("Maize/BRPI0202.MZX")
84+
>>> treatment = treatments[1]
85+
86+
The create_filex function returns the string of the FileX for for the passed
87+
sections defined as their python objects.
888
"""
989
from datetime import date
1090
from .base.partypes import (
@@ -1709,14 +1789,14 @@ def read_filex(filexpath):
17091789
)
17101790
return treatments
17111791

1712-
def write_filex(field:Field, cultivar:Cultivar, planting:Planting,
1792+
def create_filex(field:Field, cultivar:Cultivar, planting:Planting,
17131793
simulation_controls:SimulationControls, harvest:Harvest=None,
17141794
initial_conditions:InitialConditions=None,
17151795
fertilizer:Fertilizer=None, soil_analysis:SoilAnalysis=None,
17161796
irrigation:Irrigation=None, residue:Residue=None,
17171797
chemical:Chemical=None, tillage:Tillage=None):
17181798
"""
1719-
Returns the FileX string
1799+
Returns the FileX as a string
17201800
"""
17211801
experiment_name = field["id_field"][:4] +\
17221802
simulation_controls["general"]["sdate"].strftime('%y01') + cultivar.code

DSSATTools/run.py

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,24 @@
33
so per each DSSAT instance there's a directory where all the necesary files to
44
run the model are allocated. To run the model there are 2 basic steps:
55
6-
1. Create a new DSSAT instance.
7-
2. Run the model by calling the run() method.
8-
You can close the simulation environment by calling the close() method.
9-
10-
The model outputs are storage in the `output` attribute. Up to date the next output
11-
are available: PlantGro, Weather, SoilWat, SoilOrg.
6+
1. Create a new DSSAT instance. When DSSAT is instantiated, a simulation environment
7+
is set. That enviroment is set at the path passed during the call:
8+
>>> dssat = DSSAT("/tmp/dssat_test")
9+
2. Run the model by calling the run_treatment() method. This method receives as
10+
parameters the FileX sections' objects:
11+
>>> results = dssat.run_treatment(
12+
>>> field=field, cultivar=crop, planting=planting,
13+
>>> initial_conditions=initial_conditions, fertilizer=fertilizer,
14+
>>> simulation_controls=simulation_controls
15+
>>> )
16+
This call returns a dictionary that contains the values of the standard output
17+
of the model: FLO, MAT, TOPWT, HARWT, RAIN, etc. After running, the DSSAT instance
18+
will have all the output files as strings in the output_files attribute, and the
19+
output timeseries tables in the output_tables attribute:
20+
>>> overview = dssat.output_files['OVERVIEW'] # Gets the overview file as a str
21+
>>> plantgro = dssat.output_tables['PlantGro'] # Gets the plant growth table
22+
3. You can close the simulation environment by calling the close() method.
23+
>>> dssat.close
1224
'''
1325

1426
import subprocess
@@ -32,7 +44,7 @@
3244
from .filex import(
3345
Planting, Cultivar, Harvest, InitialConditions, Fertilizer,
3446
SoilAnalysis, Irrigation, Residue, Chemical, Tillage, Field,
35-
SimulationControls, Mow, write_filex
47+
SimulationControls, Mow, create_filex
3648
)
3749
from .base.utils import detect_encoding
3850

@@ -203,7 +215,7 @@ def run_treatment(self, field:Field, cultivar:Cultivar, planting:Planting,
203215
f'.{cultivar.code}X'
204216
filex_name = os.path.join(self.run_path, filex_name.upper())
205217
with open(filex_name, "w") as f:
206-
lines = write_filex(
218+
lines = create_filex(
207219
field, cultivar, planting, simulation_controls, harvest,
208220
initial_conditions, fertilizer, soil_analysis, irrigation,
209221
residue, chemical, tillage
@@ -282,13 +294,11 @@ def run_treatment(self, field:Field, cultivar:Cultivar, planting:Planting,
282294
continue
283295
table_start = -1
284296
init_lines = []
285-
for line in file_lines:
297+
for line in file_lines.split('\n'):
286298
table_start += 1
287299
init_lines.append(line)
288-
289300
if "@" in init_lines[-1][:10]:
290301
break
291-
292302
try:
293303
df = pd.read_csv(
294304
io.StringIO("".join(file_lines)),
@@ -338,7 +348,7 @@ def close(self):
338348
sys.stdout.write(f'{self.run_path} and its content has been removed.\n')
339349

340350
@property
341-
def output(self):
351+
def output_tables(self):
342352
if len(self._output) < 1:
343353
warnings.warn("No output has been saved")
344354
return None

DSSATTools/soil.py

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,71 @@
11
"""
2-
Contains the SoilProfile and SoilLayer classes. It also has some functions
3-
to estimate missing soil properties. Specifically, a function to estimate
4-
soil organic carbon from soil color, and a function to estimate soil hydraulic
5-
properties using soil texture.
2+
This module contains the classes and functions that handle the soil definition.
3+
The soil profile object is created using the SoilProfile class. One way of
4+
doing that is just loading soil profile from an existing DSSAT Soil file. For
5+
that, the from_file soil profile class function is used:
6+
>>> soil = SoilProfile.from_file("IBMZ910214", "SOIL.SOL")
7+
The soil profile can also be created from scratch using the SoilProfile and
8+
SoilLayer classes similar to the layer-based sections of the FileX:
9+
>>> soil = SoilProfile(
10+
>>> name='IBMZ910214', soil_series_name='Millhopper Fine Sand',
11+
>>> site='Gainesville', country='USA', lat=29.6, long=-82.37,
12+
>>> soil_data_source='Gainesville', soil_clasification='S',
13+
>>> scs_family='Loamy,silic,hyperth Arnic Paleudult', scom='', salb=0.18,
14+
>>> slu1=2.0, sldr=0.65, slro=60.0, slnf=1.0, slpf=0.92, smhb='IB001',
15+
>>> smpx='IB001', smke='IB001',
16+
>>> table = [
17+
>>> SoilLayer(
18+
>>> slb=5.0, slmh='', slll=0.026, sdul=0.096, ssat=0.345, srgf=1.0,
19+
>>> ssks=7.4, sbdm=1.66, sloc=0.67, slcl=1.7, slsi=0.9, slcf=0.0,
20+
>>> slhw=7.0, scec=20.0
21+
>>> ),
22+
>>> SoilLayer(
23+
>>> slb=15.0, slmh='', slll=0.025, sdul=0.105, ssat=0.345, srgf=1.0,
24+
>>> ssks=7.4, sbdm=1.66, sloc=0.67, slcl=1.7, slsi=0.9, slcf=0.0,
25+
>>> slhw=7.0
26+
>>> ),
27+
>>> SoilLayer(
28+
>>> slb=30.0, slmh='', slll=0.075, sdul=0.12, ssat=0.345, srgf=0.7,
29+
>>> ssks=14.8, sbdm=1.66, sloc=0.17, slcl=2.4, slsi=2.6, slcf=0.0,
30+
>>> slhw=7.0
31+
>>> ),
32+
>>> SoilLayer(
33+
>>> slb=45.0, slmh='', slll=0.025, sdul=0.086, ssat=0.345, srgf=0.3,
34+
>>> ssks=3.7, sbdm=1.66, sloc=0.17, slcl=2.4, slsi=2.6, slcf=0.0,
35+
>>> slhw=7.0
36+
>>> ),
37+
>>> SoilLayer(
38+
>>> slb=60.0, slmh='', slll=0.025, sdul=0.072, ssat=0.345, srgf=0.3,
39+
>>> ssks=3.7, sbdm=1.66, sloc=0.17, slcl=2.4, slsi=2.6, slcf=0.0,
40+
>>> slhw=7.0
41+
>>> ),
42+
>>> SoilLayer(
43+
>>> slb=90.0, slmh='', slll=0.028, sdul=0.072, ssat=0.345, srgf=0.1,
44+
>>> ssks=3.7, sbdm=1.66, sloc=0.17, slcl=2.4, slsi=2.6, slcf=0.0,
45+
>>> slhw=7.0
46+
>>> ),
47+
>>> SoilLayer(
48+
>>> slb=120.0, slmh='', slll=0.028, sdul=0.08, ssat=0.345, srgf=0.1,
49+
>>> ssks=0.1, sbdm=1.66, sloc=0.18, slcl=7.7, slsi=3.1, slcf=0.0,
50+
>>> slhw=7.0,
51+
>>> ),
52+
>>> SoilLayer(
53+
>>> slb=150.0, slmh='', slll=0.029, sdul=0.09, ssat=0.345, srgf=0.05,
54+
>>> ssks=0.1, sbdm=1.66, sloc=0.15, slcl=7.7, slsi=3.1, slcf=0.0,
55+
>>> slhw=7.0
56+
>>> ),
57+
>>> SoilLayer(
58+
>>> slb=180.0, slmh='', slll=0.029, sdul=0.09, ssat=0.345, srgf=0.05,
59+
>>> ssks=0.1, sbdm=1.66, sloc=0.1, slcl=7.7, slsi=3.1, slcf=0.0,
60+
>>> slhw=7.0
61+
>>> )
62+
>>> ]
63+
>>> )
64+
65+
This module also contains some functions to estimate missing soil properties. The
66+
estimate_from_texture function estimates the soil hydro-dynamic properties based
67+
on soil texture. The sloc_from_color estimates the soil organic carbon based on
68+
the soil color.
669
"""
770

871
from .base.partypes import (

DSSATTools/weather.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,19 @@
11
'''
2-
3-
2+
This module contains the classes that handle the weather definition. The
3+
WeatherStation class represents the DSSAT weather station. The weather station
4+
object can be created by reading the data from existing DSSAT wheater files:
5+
>>> weather = WeatherStation.from_files(["UAFD9001.WTH", "UAFD9101.WTH",])
6+
Note that the input parameter is a list of files, as DSSAT can have multiple files
7+
for the same station. The list of files must correspond to the same station. The
8+
weather station can also be created using the data from a DataFrame:
9+
>>> weather_station = WeatherStation(
10+
>>> insi='UNCU', lat=4.34, long=-74.40, elev=1800,
11+
>>> table=df_with_data
12+
>>> )
13+
where the df_with_data contains the weather data and its column names match the
14+
DSSAT weather parameters' names. As with the event-based sections of the FileX,
15+
the table is a list of events (daily weather records). In this case the
16+
WeatherRecord class is the class representing each daily weather record.
417
'''
518
import os
619
import pandas as pd

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ DSSATTools library allows the user to create low-code scripts to run simulations
3232

3333
DSSATTools implements an object-based approach to define DSSAT simulation input. This aims to mimic the process of creating the DSSAT input files (SOL, WTH, FileX) using the DSSAT GUI Tools. Then, the same way that XBuild has one menu for each FileX section (e.g. Cultivar, Soil Analysis, Planting Date, etc.), there is one DSSATTools class for each section of the FileX. Also, there is one class for the WTH file, and one class for the SOL file.
3434

35-
The filex module contains all the classes that represent each of the FileX sections. The crop module contains the Crop classes, one per crop. Such classes represent the crop and their cultivar and ecotype parameters. The soil module contains the SoilProfile class, which represents a single soil profile. The weather module hosts the WeatherStation class, which represents the Weather Station file (WTH).
35+
The filex module contains all the classes that represent each of the FileX sections. All the FileX sections are implemented excepting enviromental modifications. The crop module contains the Crop classes, one per crop. Such classes represent the crop and their cultivar and ecotype parameters. The soil module contains the SoilProfile class, which represents a single soil profile. The weather module hosts the WeatherStation class, which represents the Weather Station file (WTH).
3636

3737
Here is one example on how the package is used to run a simple simulation:
3838

@@ -48,12 +48,12 @@ Here is one example on how the package is used to run a simple simulation:
4848
>>> insi='UNCU', lat=4.34, long=-74.40, elev=1800,
4949
>>> table=df_with_data
5050
>>> )
51-
>>> soil = SoilProfile.from_file('IBSG910085')
51+
>>> soil = SoilProfile.from_file('IBSG910085', 'SOIL.SOL')
5252
>>> field = Field(
5353
>>> id_field='ITHY0001', wsta=weather_station, flob=0,
5454
>>> fldd=0, flds=0, id_soil=soil, fldt='DR000'
5555
>>> )
56-
>>> planting = planting = Planting(
56+
>>> planting = Planting(
5757
>>> pdate=date(1980, 6, 17), ppop=18, ppoe=18,
5858
>>> plme='S', plds='R', plrs=45, plrd=0, pldp=5
5959
>>> )

debug_filex.py

Lines changed: 0 additions & 21 deletions
This file was deleted.

docs/conf.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
1414

1515
project = 'DSSATTools'
16-
copyright = '2023, Diego Quintero'
16+
copyright = '2025, Diego Quintero'
1717
author = 'Diego Quintero'
18-
exclude_patterns = ['base', 'models']
18+
exclude_patterns = ['base']
1919

2020
# -- General configuration ---------------------------------------------------
2121
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration

future_features.md

Lines changed: 0 additions & 2 deletions
This file was deleted.

0 commit comments

Comments
 (0)