WOFOST crop database¶
There is a GitHub repository containing calibtated parameters for a range of varieties of crops. These parameters were used, e.g., in the Hupselbrook test case provided with the SWAP model for potato variety. As these are reusable, it made sense to tap into that database to make creation of valid crop files for pySWAP easier.
In this notebook, we will create a .crp file for potato variety used in the hupselbrook test case.
import pyswap as psp
Exploring the database¶
pySWAP contains a simple wrapper around A. Wit's crop database. We can use built in classes to get an overview of available data. Then we can check which crop types are available in the database.
cropdb = psp.db.WOFOSTCropDB()
cropdb.croptypes
['barley', 'cassava', 'chickpea', 'cotton', 'cowpea', 'fababean', 'groundnut', 'maize', 'millet', 'mungbean', 'pigeonpea', 'potato', 'rapeseed', 'rice', 'sorghum', 'soybean', 'sugarbeet', 'sugarcane', 'sunflower', 'sweetpotato', 'tobacco', 'wheat', 'seed_onion']
When we call load_crop_file
on the database object with the name of a specific crop type, we will get a WOFOSTCropFile object. We can then inspect that object to see the file's metadata, parameters in individual sections, available ecotypes and varieties.
cropfile = cropdb.load_crop_file("rice")
cropfile.metadata
{'Creator': 'Allard de Wit', 'Contributor': None, 'Contact': 'allard.dewit@wur.nl', 'Publisher': 'Wageningen Environmental Research', 'Title': 'Parameter sets for the WOFOST7.2/WOFOST8.0 model for simulating rice', 'Date': datetime.date(2022, 2, 13), 'Language': 'EN', 'Format': 'YAML', 'Subject': 'WOFOST parameters for rice', 'Description': 'This file provides parameters for several rice varieties. Mostly calibrated based on observations done at the International Rice Research Institute, but also based on observations from Europe and earlier work.', 'Identifier': None, 'Relation': None, 'Source': None, 'Type': None, 'Coverage': {'Region': 'Selected locations in Europe (France, Spain, Greece, Italy, Portugal), tropical regions'}, 'Rights': 'European Union Public License (EUPL)', 'Keyword': 'rice; Oryza sativa'}
print(cropfile.ecotypes)
print(cropfile.varieties)
['rice_eu', 'rice_irri'] ['Rice_501', 'Rice_HYV_IR8', 'Rice_IR64616H_DS', 'Rice_IR64616H_WS', 'Rice_IR64', 'Rice_IR72', 'Rice_IR72_DS', 'Rice_IR72_WS', 'Rice_IR8A']
rice_501 = cropfile.get_variety("Rice_501")
The new object is CropVariety
object. From here you can view the metadata of the particular variety or obtain just the parameters as a dictionary. Mind that at this stage, all tables are just arrays of numbers, the same way as it is formatted in the .yaml files. pySWAP automatically converts them in tables when they are used to populate the parameters of crop settings classes.
Using the CropVariety object to populate the crop settings class¶
The point of having this database integration is to enable populating some of the wofost crop parameters used by swap directly from the files. A lot of the parameters we still have to set manually, namely Preparation, ScheduledIrrigation, Interception, OxygenStress, DroughtStress, etc.
potato_prep = psp.components.crop.Preparation(
swprep=0,
swsow=0,
swgerm=2,
tsumemeopt=170.0,
tbasem=3.0,
teffmx=18.0,
hdrygerm=-500.0,
hwetgerm=-100.0,
zgerm=-10.0,
agerm=203.0,
dvsend=2.0,
swharv=0,
)
scheduled_irrigation = psp.components.irrigation.ScheduledIrrigation(schedule=0)
interception = psp.components.crop.Interception(swinter=1, cofab=0.25)
potato_chtb = psp.components.crop.CHTB.create({
"DVS": [0.0, 1.0, 2.0],
"CH": [
1.0,
40.0,
50.0,
],
})
potato_rdctb = psp.components.crop.RDCTB.create({
"RRD": [0.0, 1.0],
"RDENS": [1.0, 0.0],
})
potato_ox_stress = psp.components.crop.OxygenStress(
swoxygen=1,
swwrtnonox=1,
aeratecrit=0.5,
hlim1=-10.0,
hlim2u=-25.0,
hlim2l=-25.0,
swrootradius=2,
root_radiuso2=0.00015,
)
potato_dr_stress = psp.components.crop.DroughtStress(
swdrought=1,
hlim3h=-300.0,
hlim3l=-500.0,
hlim4=-10000.0,
adcrh=0.5,
adcrl=0.1,
)
--------------------------------------------------------------------------- AttributeError Traceback (most recent call last) Cell In[7], line 19 16 scheduled_irrigation = psp.components.irrigation.ScheduledIrrigation(schedule=0) 17 interception = psp.components.crop.Interception(swinter=1, cofab=0.25) ---> 19 potato_chtb = psp.components.crop.CHTB.create({ 20 "DVS": [0.0, 1.0, 2.0], 21 "CH": [ 22 1.0, 23 40.0, 24 50.0, 25 ], 26 }) 28 potato_rdctb = psp.components.crop.RDCTB.create({ 29 "RRD": [0.0, 1.0], 30 "RDENS": [1.0, 0.0], 31 }) 33 potato_ox_stress = psp.components.crop.OxygenStress( 34 swoxygen=1, 35 swwrtnonox=1, (...) 41 root_radiuso2=0.00015, 42 ) AttributeError: module 'pyswap.components.crop' has no attribute 'CHTB'
Then, we can load the potato_701 variety from the WOFOST database and create the CropDevelopmentSettings object like so:
db = psp.db.WOFOSTCropDB()
potato = db.load_crop_file("potato")
potato_params = potato.get_variety("Potato_701")
potato_cropdev_settings = psp.components.crop.CropDevelopmentSettingsWOFOST(
wofost_variety=potato_params,
swcf=2,
dvs_ch=potato_chtb,
albedo=0.19,
laiem=0.0589,
ssa=0.0,
kdif=1.0,
rsc=207.0,
rsw=0.0,
kdir=0.75,
eff=0.45,
swrd=2,
rdc=50.0,
swdmi2rd=1,
rdctb=potato_rdctb,
)
# By calling the `update_from_wofost method`, the CropDevelopmentSettingsWOFOST object
# will be updated with the values from the WOFOST crop file and the model will be evaluated,
# to make sure that some of the required settings are not missing.
potato_cropdev_settings.update_from_wofost()
--------------------------------------------------------------------------- NameError Traceback (most recent call last) Cell In[8], line 8 2 potato = db.load_crop_file("potato") 3 potato_params = potato.get_variety("Potato_701") 5 potato_cropdev_settings = psp.components.crop.CropDevelopmentSettingsWOFOST( 6 wofost_variety=potato_params, 7 swcf=2, ----> 8 dvs_ch=potato_chtb, 9 albedo=0.19, 10 laiem=0.0589, 11 ssa=0.0, 12 kdif=1.0, 13 rsc=207.0, 14 rsw=0.0, 15 kdir=0.75, 16 eff=0.45, 17 swrd=2, 18 rdc=50.0, 19 swdmi2rd=1, 20 rdctb=potato_rdctb, 21 ) 23 # By calling the `update_from_wofost method`, the CropDevelopmentSettingsWOFOST object 24 # will be updated with the values from the WOFOST crop file and the model will be evaluated, 25 # to make sure that some of the required settings are not missing. 26 potato_cropdev_settings.update_from_wofost() NameError: name 'potato_chtb' is not defined
Further we proceed with creation of the CropFile
object, which goes directly to the Model
. You can observe the content of the crop file by calling CropFile.crp
property.
crppotato = psp.components.crop.CropFile(
name="potatod",
prep=potato_prep,
cropdev_settings=potato_cropdev_settings,
oxygenstress=potato_ox_stress,
droughtstress=potato_dr_stress,
interception=interception,
scheduledirrigation=scheduled_irrigation,
)
--------------------------------------------------------------------------- NameError Traceback (most recent call last) Cell In[9], line 4 1 crppotato = psp.components.crop.CropFile( 2 name="potatod", 3 prep=potato_prep, ----> 4 cropdev_settings=potato_cropdev_settings, 5 oxygenstress=potato_ox_stress, 6 droughtstress=potato_dr_stress, 7 interception=interception, 8 scheduledirrigation=scheduled_irrigation, 9 ) NameError: name 'potato_cropdev_settings' is not defined
print(crppotato.crp)
--------------------------------------------------------------------------- NameError Traceback (most recent call last) Cell In[10], line 1 ----> 1 print(crppotato.crp) NameError: name 'crppotato' is not defined
The WOFOST database integration allows you draw calibrated settings from the database into pySWAP. If you wish to change some of the settings, you should do it by updating the base pySWAP classes (e.g., CropDevalopmentSettings), like so:
potato_cropdev_settings_tsum1_up = potato_cropdev_settings.update({"tsum1": 900})
--------------------------------------------------------------------------- NameError Traceback (most recent call last) Cell In[11], line 1 ----> 1 potato_cropdev_settings_tsum1_up = potato_cropdev_settings.update({"tsum1": 900}) NameError: name 'potato_cropdev_settings' is not defined
crppotato_tsum1_up = crppotato.update({
"cropdev_settings": potato_cropdev_settings_tsum1_up
})
--------------------------------------------------------------------------- NameError Traceback (most recent call last) Cell In[12], line 1 ----> 1 crppotato_tsum1_up = crppotato.update({ 2 "cropdev_settings": potato_cropdev_settings_tsum1_up 3 }) NameError: name 'crppotato' is not defined
print(crppotato_tsum1_up.cropdev_settings.tsum1)
--------------------------------------------------------------------------- NameError Traceback (most recent call last) Cell In[13], line 1 ----> 1 print(crppotato_tsum1_up.cropdev_settings.tsum1) NameError: name 'crppotato_tsum1_up' is not defined