pyholos 0.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyholos might be problematic. Click here for more details.
- pyholos/__init__.py +0 -0
- pyholos/common.py +141 -0
- pyholos/common2.py +157 -0
- pyholos/components/__init__.py +0 -0
- pyholos/components/animals/__init__.py +0 -0
- pyholos/components/animals/beef.py +766 -0
- pyholos/components/animals/common.py +2301 -0
- pyholos/components/animals/dairy.py +341 -0
- pyholos/components/animals/sheep.py +412 -0
- pyholos/components/common.py +170 -0
- pyholos/components/land_management/__init__.py +0 -0
- pyholos/components/land_management/carbon/__init__.py +0 -0
- pyholos/components/land_management/carbon/climate.py +863 -0
- pyholos/components/land_management/carbon/management.py +21 -0
- pyholos/components/land_management/carbon/relative_biomass_information.py +410 -0
- pyholos/components/land_management/carbon/tillage.py +88 -0
- pyholos/components/land_management/common.py +220 -0
- pyholos/components/land_management/crop.py +1233 -0
- pyholos/components/land_management/field_system.py +458 -0
- pyholos/components/land_management/utils.py +66 -0
- pyholos/config.py +49 -0
- pyholos/core_constants.py +20 -0
- pyholos/defaults.py +116 -0
- pyholos/farm/__init__.py +0 -0
- pyholos/farm/enums.py +54 -0
- pyholos/farm/farm.py +101 -0
- pyholos/farm/farm_inputs.py +633 -0
- pyholos/farm/farm_settings.py +542 -0
- pyholos/launching.py +86 -0
- pyholos/postprocessing/__init__.py +0 -0
- pyholos/postprocessing/plots.py +164 -0
- pyholos/postprocessing/postprocessing.py +38 -0
- pyholos/resources/holos/Table_16_Livestock_Coefficients_BeefAndDairy_Cattle_Provider.csv +21 -0
- pyholos/resources/holos/Table_21_Average_Milk_Production_For_Dairy_Cows_By_Province.csv +23 -0
- pyholos/resources/holos/Table_22_Livestock_Coefficients_For_Sheep.csv +28 -0
- pyholos/resources/holos/Table_29_Percentage_Total_Manure_Produced_In_Systems.csv +56 -0
- pyholos/resources/holos/Table_30_Default_Bedding_Material_Composition_Provider.csv +28 -0
- pyholos/resources/holos/Table_50_Fuel_Energy_Requirement_Estimates_By_Region.csv +81 -0
- pyholos/resources/holos/Table_51_Herbicide_Energy_Requirement_Estimates_By_Region.csv +81 -0
- pyholos/resources/holos/Table_61_Fractions_of_dairy_cattle_N_volatilized.csv +25 -0
- pyholos/resources/holos/Table_62_Fractions_of_swine_N_volatilized.csv +25 -0
- pyholos/resources/holos/Table_6_Manure_Types_And_Default_Composition.csv +126 -0
- pyholos/resources/holos/Table_7_Relative_Biomass_Information.csv +112 -0
- pyholos/resources/holos/Table_9_Default_Values_For_Nitrogen_Lignin_In_Crops.csv +72 -0
- pyholos/resources/holos/Table_Tillage_Factor.csv +13 -0
- pyholos/resources/holos/feeds.csv +223 -0
- pyholos/resources/holos/main_tables.py +493 -0
- pyholos/resources/holos/small_area_yields.csv +167159 -0
- pyholos/resources/soil_landscapes_of_canada_v3r2.zip +0 -0
- pyholos/soil.py +439 -0
- pyholos/utils.py +83 -0
- pyholos-0.0.1.dist-info/METADATA +16 -0
- pyholos-0.0.1.dist-info/RECORD +55 -0
- pyholos-0.0.1.dist-info/WHEEL +4 -0
- pyholos-0.0.1.dist-info/licenses/LICENSE +677 -0
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
from uuid import UUID
|
|
2
|
+
|
|
3
|
+
from pyholos.common import Component, HolosVar
|
|
4
|
+
from pyholos.components.animals.common import (ManureAnimalSourceTypes,
|
|
5
|
+
ManureLocationSourceType,
|
|
6
|
+
ManureStateType)
|
|
7
|
+
from pyholos.components.land_management.carbon.climate import \
|
|
8
|
+
calculate_climate_parameter
|
|
9
|
+
from pyholos.components.land_management.carbon.management import \
|
|
10
|
+
calculate_management_factor
|
|
11
|
+
from pyholos.components.land_management.carbon.relative_biomass_information import (
|
|
12
|
+
RelativeBiomassInformationData, get_nitrogen_lignin_content_in_crops_data,
|
|
13
|
+
parse_table_9)
|
|
14
|
+
from pyholos.components.land_management.carbon.tillage import \
|
|
15
|
+
calculate_tillage_factor
|
|
16
|
+
from pyholos.components.land_management.common import (
|
|
17
|
+
FertilizerBlends, HarvestMethod, IrrigationType, ManureApplicationTypes,
|
|
18
|
+
TillageType, TimePeriodCategory, get_fuel_energy_estimate,
|
|
19
|
+
get_herbicide_energy_estimate)
|
|
20
|
+
from pyholos.components.land_management.crop import (CropType,
|
|
21
|
+
get_nitrogen_fixation)
|
|
22
|
+
from pyholos.core_constants import CoreConstants
|
|
23
|
+
from pyholos.defaults import Defaults
|
|
24
|
+
from pyholos.common2 import CanadianProvince
|
|
25
|
+
from pyholos.soil import SoilFunctionalCategory
|
|
26
|
+
|
|
27
|
+
TABLE_9 = parse_table_9()
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class LandManagementBase(Component):
|
|
31
|
+
def __init__(self):
|
|
32
|
+
super().__init__()
|
|
33
|
+
self.phase_number = HolosVar(name='Phase Number', value=0)
|
|
34
|
+
"""deprecated"""
|
|
35
|
+
|
|
36
|
+
self.name = HolosVar(name='Name')
|
|
37
|
+
self.area = HolosVar(name='Area')
|
|
38
|
+
self.current_year = HolosVar(name='Current Year')
|
|
39
|
+
self.crop_year = HolosVar(name='Crop Year')
|
|
40
|
+
self.crop_type = HolosVar(name='Crop Type')
|
|
41
|
+
self.tillage_type = HolosVar(name='Tillage Type')
|
|
42
|
+
self.year_in_perennial_stand = HolosVar(name='Year In Perennial Stand')
|
|
43
|
+
self.perennial_stand_id = HolosVar(name='Perennial Stand ID')
|
|
44
|
+
self.perennial_stand_length = HolosVar(name='Perennial Stand Length')
|
|
45
|
+
self.biomass_coefficient_product = HolosVar(name='Biomass Coefficient Product')
|
|
46
|
+
self.biomass_coefficient_straw = HolosVar(name='Biomass Coefficient Straw')
|
|
47
|
+
self.biomass_coefficient_roots = HolosVar(name='Biomass Coefficient Roots')
|
|
48
|
+
self.biomass_coefficient_extraroot = HolosVar(name='Biomass Coefficient Extraroot')
|
|
49
|
+
self.nitrogen_content_in_product = HolosVar(name='Nitrogen Content In Product')
|
|
50
|
+
self.nitrogen_content_in_straw = HolosVar(name='Nitrogen Content In Straw')
|
|
51
|
+
self.nitrogen_content_in_roots = HolosVar(name='Nitrogen Content In Roots')
|
|
52
|
+
self.nitrogen_content_in_extraroot = HolosVar(name='Nitrogen Content In Extraroot')
|
|
53
|
+
self.nitrogen_fixation = HolosVar(name='Nitrogen Fixation')
|
|
54
|
+
|
|
55
|
+
self.nitrogen_deposit = HolosVar(name='Nitrogen Deposit', value=CoreConstants.NitrogenDepositionAmount)
|
|
56
|
+
"""(kg(N) ha-1 year-1) Atmospheric Nitrogen deposition amount"""
|
|
57
|
+
|
|
58
|
+
self.carbon_concentration = HolosVar(name='Carbon Concentration', value=CoreConstants.CarbonConcentration)
|
|
59
|
+
"""(kg(C)/kg(plant biomass)) carbon concentration in plant biomass"""
|
|
60
|
+
|
|
61
|
+
self.crop_yield = HolosVar(name='Yield')
|
|
62
|
+
self.harvest_method = HolosVar(name='Harvest Method')
|
|
63
|
+
self.nitrogen_fertilizer_rate = HolosVar(name='Nitrogen Fertilizer Rate')
|
|
64
|
+
|
|
65
|
+
self.phosphorous_fertilizer_rate = HolosVar(name='Phosphorous Fertilizer Rate', value=0)
|
|
66
|
+
"""Not used/implemented yet in Holos v.4. Future version will utilize"""
|
|
67
|
+
|
|
68
|
+
self.is_irrigated = HolosVar(name='Is Irrigated', value="No")
|
|
69
|
+
"""Not used/implemented yet in Holos v.4. Future version will utilize"""
|
|
70
|
+
|
|
71
|
+
self.irrigation_type = HolosVar(name='Irrigation Type')
|
|
72
|
+
self.amount_of_irrigation = HolosVar(name='Amount Of Irrigation')
|
|
73
|
+
self.moisture_content_of_crop = HolosVar(name='Moisture Content Of Crop')
|
|
74
|
+
self.moisture_content_of_crop_percentage = HolosVar(name='Moisture Content Of Crop Percentage')
|
|
75
|
+
self.percentage_of_straw_returned_to_soil = HolosVar(name='PercentageOfStrawReturnedToSoil')
|
|
76
|
+
self.percentage_of_roots_returned_to_soil = HolosVar(name='PercentageOfRootsReturnedToSoil')
|
|
77
|
+
self.percentage_of_product_yield_returned_to_soil = HolosVar(name='PercentageOfProductYieldReturnedToSoil')
|
|
78
|
+
self.is_pesticide_used = HolosVar(name='Is Pesticide Used')
|
|
79
|
+
self.number_of_pesticide_passes = HolosVar(name='Number Of Pesticide Passes')
|
|
80
|
+
self.manure_applied = HolosVar(name='Manure Applied')
|
|
81
|
+
self.amount_of_manure_applied = HolosVar(name='Amount Of Manure Applied')
|
|
82
|
+
self.manure_application_type = HolosVar(name='Manure Application Type')
|
|
83
|
+
self.manure_animal_source_type = HolosVar(name='Manure Animal Source Type')
|
|
84
|
+
self.manure_state_type = HolosVar(name='Manure State Type')
|
|
85
|
+
self.manure_location_source_type = HolosVar(name='Manure Location Source Type')
|
|
86
|
+
self.under_sown_crops_used = HolosVar(name='Under Sown Crops Used')
|
|
87
|
+
|
|
88
|
+
self.crop_is_grazed = HolosVar(name='Crop Is Grazed', value="False")
|
|
89
|
+
"""Not used/implemented yet in Holos v.4. Future version will utilize"""
|
|
90
|
+
|
|
91
|
+
self.field_system_component_guid = HolosVar(name='Field System Component Guid')
|
|
92
|
+
|
|
93
|
+
self.time_period_category = HolosVar(name='Time Period Category String', value=TimePeriodCategory.Current)
|
|
94
|
+
"""Used to indicate time period in field history. Leave as "Current" if not sure"""
|
|
95
|
+
|
|
96
|
+
self.climate_parameter = HolosVar(name='Climate Parameter')
|
|
97
|
+
self.tillage_factor = HolosVar(name='Tillage Factor')
|
|
98
|
+
self.management_factor = HolosVar(name='Management Factor')
|
|
99
|
+
|
|
100
|
+
self.plant_carbon_in_agricultural_product = HolosVar(name='Plant Carbon In Agricultural Product', value=0)
|
|
101
|
+
"""deprecated"""
|
|
102
|
+
|
|
103
|
+
self.carbon_input_from_product = HolosVar(name='Carbon Input From Product', value=0)
|
|
104
|
+
"""(kg(C)/ha) carbon input from product (C_ptoSoil)"""
|
|
105
|
+
|
|
106
|
+
self.carbon_input_from_straw = HolosVar(name='Carbon Input From Straw', value=0)
|
|
107
|
+
"""deprecated"""
|
|
108
|
+
|
|
109
|
+
self.carbon_input_from_roots = HolosVar(name='Carbon Input From Roots', value=0)
|
|
110
|
+
"""deprecated"""
|
|
111
|
+
|
|
112
|
+
self.carbon_input_from_extraroots = HolosVar(name='Carbon Input From Extraroots', value=0)
|
|
113
|
+
"""deprecated"""
|
|
114
|
+
|
|
115
|
+
self.size_of_first_rotation_for_field = HolosVar(name='Size Of First Rotation For Field', value=1)
|
|
116
|
+
"""deprecated"""
|
|
117
|
+
|
|
118
|
+
self.above_ground_carbon_input = HolosVar(name='Above Ground Carbon Input', value=0)
|
|
119
|
+
"""(kg(C)/ha) above-ground carbon input(C_ag)"""
|
|
120
|
+
|
|
121
|
+
self.below_ground_carbon_input = HolosVar(name='Below Ground Carbon Input', value=0)
|
|
122
|
+
"""deprecated"""
|
|
123
|
+
|
|
124
|
+
self.manure_carbon_inputs_per_hectare = HolosVar(name='Manure Carbon Inputs Per Hectare', value=0)
|
|
125
|
+
"""deprecated"""
|
|
126
|
+
|
|
127
|
+
self.digestate_carbon_inputs_per_hectare = HolosVar(name='Digestate Carbon Inputs Per Hectare', value=0)
|
|
128
|
+
"""deprecated"""
|
|
129
|
+
|
|
130
|
+
self.total_carbon_inputs = HolosVar(name='Total Carbon Inputs', value=0)
|
|
131
|
+
"""deprecated"""
|
|
132
|
+
|
|
133
|
+
self.sand = HolosVar(name='Sand')
|
|
134
|
+
"""(-) Fraction of 0-30 cm soil mass that is sand (0.050 – 2mm particles) (between 0 and 1)"""
|
|
135
|
+
|
|
136
|
+
self.lignin = HolosVar(name='Lignin')
|
|
137
|
+
"""(-) fraction of lignin content in the carbon input (on dry basis, between 0 and 1)"""
|
|
138
|
+
|
|
139
|
+
self.w_fac = HolosVar(name='WFac', value=0)
|
|
140
|
+
"""(deprecated) Annual water effect on decomposition."""
|
|
141
|
+
|
|
142
|
+
self.t_fac = HolosVar(name='TFac', value=0)
|
|
143
|
+
"""(deprecated) Annual average air temperature effect on decomposition"""
|
|
144
|
+
|
|
145
|
+
self.total_nitrogen_inputs_for_ipcc_tier2 = HolosVar(name='Total Nitrogen Inputs For Ipcc Tier 2', value=0)
|
|
146
|
+
"""deprecated"""
|
|
147
|
+
|
|
148
|
+
self.nitrogen_content = HolosVar(name='Nitrogen Content')
|
|
149
|
+
"""(-) Nitrogen fraction of the carbon input (from IPCC Tier 2, between 0 and 1)"""
|
|
150
|
+
|
|
151
|
+
self.above_ground_residue_dry_matter = HolosVar(name='Above Ground Residue Dry Matter', value=0)
|
|
152
|
+
"""deprecated"""
|
|
153
|
+
|
|
154
|
+
self.below_ground_residue_dry_matter = HolosVar(name='Below Ground Residue Dry Matter', value=0)
|
|
155
|
+
"""deprecated"""
|
|
156
|
+
|
|
157
|
+
self.fuel_energy = HolosVar(name='Fuel Energy')
|
|
158
|
+
self.herbicide_energy = HolosVar(name='Herbicide Energy')
|
|
159
|
+
self.fertilizer_blend = HolosVar(name='Fertilizer Blend')
|
|
160
|
+
|
|
161
|
+
def get_default_harvest_method(self) -> HarvestMethod:
|
|
162
|
+
"""Returns default harvest method based on the cultivated crop.
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
HarvestMethod class member
|
|
166
|
+
|
|
167
|
+
Holos source code:
|
|
168
|
+
https://github.com/holos-aafc/Holos/blob/b183dab99d211158d1fed9da5370ce599ac7c914/H.Core/Services/Initialization/Crops/CropInitializationService.Harvest.cs#L19
|
|
169
|
+
"""
|
|
170
|
+
return HarvestMethod.Silage if self.crop_type.value.is_silage_crop() else HarvestMethod.CashCrop
|
|
171
|
+
|
|
172
|
+
def set_irrigation_type(self):
|
|
173
|
+
"""Sets the irrigation type, irrigated or rainfed, based on the presence or absence of irrigation amount, resp.
|
|
174
|
+
|
|
175
|
+
Holos source code:
|
|
176
|
+
https://github.com/holos-aafc/Holos/blob/23a53f1fe6796145cc3ac43c005dbcc560421deb/H.Core/Models/LandManagement/Fields/CropViewItem.cs#L1289
|
|
177
|
+
"""
|
|
178
|
+
self.irrigation_type.value = IrrigationType.Irrigated if self.amount_of_irrigation.value > 0 else IrrigationType.RainFed
|
|
179
|
+
|
|
180
|
+
def set_moisture_content(self):
|
|
181
|
+
if any([
|
|
182
|
+
self.harvest_method == HarvestMethod.GreenManure,
|
|
183
|
+
self.harvest_method == HarvestMethod.Silage,
|
|
184
|
+
self.harvest_method == HarvestMethod.Swathing,
|
|
185
|
+
self.crop_type.value.is_silage_crop()
|
|
186
|
+
]):
|
|
187
|
+
"""Sets the moisture percentage of the harvested biomass.
|
|
188
|
+
|
|
189
|
+
Holos source code:
|
|
190
|
+
https://github.com/holos-aafc/Holos/blob/23a53f1fe6796145cc3ac43c005dbcc560421deb/H.Core/Services/Initialization/Crops/CropInitializationService.Water.cs#L60
|
|
191
|
+
"""
|
|
192
|
+
moisture_content_of_crop_percentage = 65
|
|
193
|
+
|
|
194
|
+
else:
|
|
195
|
+
if self.moisture_content_of_crop.value != 0:
|
|
196
|
+
moisture_content_of_crop_percentage = self.moisture_content_of_crop.value * 100.
|
|
197
|
+
else:
|
|
198
|
+
moisture_content_of_crop_percentage = 12
|
|
199
|
+
|
|
200
|
+
self.moisture_content_of_crop_percentage.value = moisture_content_of_crop_percentage
|
|
201
|
+
|
|
202
|
+
def set_percentage_returns(self):
|
|
203
|
+
"""
|
|
204
|
+
Holos source code:
|
|
205
|
+
https://github.com/holos-aafc/Holos/blob/bf38e27113cd965442cafb118f7ce156c8065701/H.Core/Services/Initialization/Crops/CropInitializationService.Returns.cs#L24
|
|
206
|
+
"""
|
|
207
|
+
percentage_of_product_yield_returned_to_soil = 0
|
|
208
|
+
percentage_of_straw_returned_to_soil = 0
|
|
209
|
+
percentage_of_roots_returned_to_soil = 0
|
|
210
|
+
|
|
211
|
+
# Initialize the view item by checking the crop type
|
|
212
|
+
crop_type: CropType = self.crop_type.value
|
|
213
|
+
if crop_type.is_perennial():
|
|
214
|
+
percentage_of_product_yield_returned_to_soil = Defaults.PercentageOfProductReturnedToSoilForPerennials
|
|
215
|
+
percentage_of_straw_returned_to_soil = 0
|
|
216
|
+
percentage_of_roots_returned_to_soil = Defaults.PercentageOfRootsReturnedToSoilForPerennials
|
|
217
|
+
elif crop_type.is_annual():
|
|
218
|
+
percentage_of_product_yield_returned_to_soil = Defaults.PercentageOfProductReturnedToSoilForAnnuals
|
|
219
|
+
percentage_of_straw_returned_to_soil = Defaults.PercentageOfStrawReturnedToSoilForAnnuals
|
|
220
|
+
percentage_of_roots_returned_to_soil = Defaults.PercentageOfRootsReturnedToSoilForAnnuals
|
|
221
|
+
|
|
222
|
+
if crop_type.is_root_crop():
|
|
223
|
+
percentage_of_product_yield_returned_to_soil = Defaults.PercentageOfProductReturnedToSoilForRootCrops
|
|
224
|
+
percentage_of_straw_returned_to_soil = Defaults.PercentageOfStrawReturnedToSoilForRootCrops
|
|
225
|
+
percentage_of_roots_returned_to_soil = 0 # different from original code
|
|
226
|
+
|
|
227
|
+
if crop_type.is_cover_crop():
|
|
228
|
+
percentage_of_product_yield_returned_to_soil = 100
|
|
229
|
+
percentage_of_straw_returned_to_soil = 100
|
|
230
|
+
percentage_of_roots_returned_to_soil = 100
|
|
231
|
+
|
|
232
|
+
# Initialize the view item by checking the harvest method (override any setting based on crop type)
|
|
233
|
+
harvest_method = self.harvest_method.value
|
|
234
|
+
if any([
|
|
235
|
+
crop_type.is_silage_crop(),
|
|
236
|
+
harvest_method == HarvestMethod.Silage
|
|
237
|
+
]):
|
|
238
|
+
percentage_of_product_yield_returned_to_soil = 2
|
|
239
|
+
percentage_of_straw_returned_to_soil = 0
|
|
240
|
+
percentage_of_roots_returned_to_soil = 100
|
|
241
|
+
elif harvest_method == HarvestMethod.Swathing:
|
|
242
|
+
percentage_of_product_yield_returned_to_soil = 30
|
|
243
|
+
percentage_of_straw_returned_to_soil = 0
|
|
244
|
+
percentage_of_roots_returned_to_soil = 100
|
|
245
|
+
elif harvest_method == HarvestMethod.GreenManure:
|
|
246
|
+
percentage_of_product_yield_returned_to_soil = 100
|
|
247
|
+
percentage_of_straw_returned_to_soil = 0
|
|
248
|
+
percentage_of_roots_returned_to_soil = 100
|
|
249
|
+
|
|
250
|
+
self.percentage_of_product_yield_returned_to_soil.value = percentage_of_product_yield_returned_to_soil
|
|
251
|
+
self.percentage_of_straw_returned_to_soil.value = percentage_of_straw_returned_to_soil
|
|
252
|
+
self.percentage_of_roots_returned_to_soil.value = percentage_of_roots_returned_to_soil
|
|
253
|
+
|
|
254
|
+
pass
|
|
255
|
+
|
|
256
|
+
def initialize_biomass_coefficients(
|
|
257
|
+
self,
|
|
258
|
+
residue_data: RelativeBiomassInformationData
|
|
259
|
+
):
|
|
260
|
+
self.biomass_coefficient_product.value = residue_data.relative_biomass_product
|
|
261
|
+
self.biomass_coefficient_straw.value = residue_data.relative_biomass_straw
|
|
262
|
+
self.biomass_coefficient_roots.value = residue_data.relative_biomass_root
|
|
263
|
+
self.biomass_coefficient_extraroot.value = residue_data.relative_biomass_extraroot
|
|
264
|
+
|
|
265
|
+
if self.harvest_method.value in [
|
|
266
|
+
HarvestMethod.Swathing,
|
|
267
|
+
HarvestMethod.GreenManure,
|
|
268
|
+
HarvestMethod.Silage
|
|
269
|
+
]:
|
|
270
|
+
self.biomass_coefficient_product.value = residue_data.relative_biomass_product + residue_data.relative_biomass_straw
|
|
271
|
+
self.biomass_coefficient_straw.value = 0
|
|
272
|
+
self.biomass_coefficient_roots.value = residue_data.relative_biomass_root
|
|
273
|
+
self.biomass_coefficient_extraroot.value = residue_data.relative_biomass_extraroot
|
|
274
|
+
|
|
275
|
+
def initialize_nitrogen_content(
|
|
276
|
+
self,
|
|
277
|
+
residue_data: RelativeBiomassInformationData
|
|
278
|
+
):
|
|
279
|
+
"""
|
|
280
|
+
|
|
281
|
+
Args:
|
|
282
|
+
residue_data: RelativeBiomassInformationData instance
|
|
283
|
+
|
|
284
|
+
Holos source code:
|
|
285
|
+
https://github.com/holos-aafc/Holos/blob/71638efd97c84c6ded45e342ce664477df6f803f/H.Core/Services/Initialization/Crops/CropInitializationService.Nitrogen.cs#L42
|
|
286
|
+
"""
|
|
287
|
+
# Assign N content values used for the ICBM methodology
|
|
288
|
+
|
|
289
|
+
# Table has values in grams but unit of display is kg
|
|
290
|
+
self.nitrogen_content_in_product.value = residue_data.nitrogen_content_product / 1000
|
|
291
|
+
self.nitrogen_content_in_straw.value = residue_data.nitrogen_content_straw / 1000
|
|
292
|
+
self.nitrogen_content_in_roots.value = residue_data.nitrogen_content_root / 1000
|
|
293
|
+
self.nitrogen_content_in_extraroot.value = residue_data.nitrogen_content_extraroot / 1000
|
|
294
|
+
|
|
295
|
+
if self.crop_type.value.is_perennial():
|
|
296
|
+
self.nitrogen_content_in_straw.value = 0
|
|
297
|
+
|
|
298
|
+
# Assign N content values used for IPCC Tier 2
|
|
299
|
+
crop_data = get_nitrogen_lignin_content_in_crops_data(
|
|
300
|
+
crop_type=self.crop_type.value,
|
|
301
|
+
table_9=TABLE_9)
|
|
302
|
+
|
|
303
|
+
self.nitrogen_content.value = crop_data.NitrogenContentResidues
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
class CropViewItem(LandManagementBase):
|
|
307
|
+
def __init__(
|
|
308
|
+
self,
|
|
309
|
+
name: str,
|
|
310
|
+
field_area: float,
|
|
311
|
+
current_year: int,
|
|
312
|
+
crop_year: int,
|
|
313
|
+
year_in_perennial_stand: int,
|
|
314
|
+
crop_type: CropType,
|
|
315
|
+
tillage_type: TillageType,
|
|
316
|
+
perennial_stand_id: UUID,
|
|
317
|
+
perennial_stand_length: int,
|
|
318
|
+
relative_biomass_information_data: RelativeBiomassInformationData,
|
|
319
|
+
crop_yield: float,
|
|
320
|
+
harvest_method: HarvestMethod,
|
|
321
|
+
nitrogen_fertilizer_rate: float,
|
|
322
|
+
under_sown_crops_used: bool,
|
|
323
|
+
field_system_component_guid: UUID,
|
|
324
|
+
province: CanadianProvince,
|
|
325
|
+
clay_content: float,
|
|
326
|
+
sand_content: float,
|
|
327
|
+
organic_carbon_percentage: float,
|
|
328
|
+
soil_top_layer_thickness: float,
|
|
329
|
+
soil_functional_category: SoilFunctionalCategory,
|
|
330
|
+
fertilizer_blend: FertilizerBlends,
|
|
331
|
+
evapotranspiration: list[float],
|
|
332
|
+
precipitation: list[float],
|
|
333
|
+
temperature: list[float],
|
|
334
|
+
|
|
335
|
+
amount_of_irrigation: float = 0,
|
|
336
|
+
number_of_pesticide_passes: int = 0,
|
|
337
|
+
amount_of_manure_applied: float = 0,
|
|
338
|
+
manure_application_type: ManureApplicationTypes = ManureApplicationTypes.NotSelected,
|
|
339
|
+
manure_animal_source_type: ManureAnimalSourceTypes = ManureAnimalSourceTypes.NotSelected,
|
|
340
|
+
manure_state_type: ManureStateType = ManureStateType.not_selected,
|
|
341
|
+
manure_location_source_type: ManureLocationSourceType = ManureLocationSourceType.NotSelected
|
|
342
|
+
|
|
343
|
+
):
|
|
344
|
+
"""
|
|
345
|
+
|
|
346
|
+
Args:
|
|
347
|
+
name: field name
|
|
348
|
+
field_area: (ha) area of the field
|
|
349
|
+
current_year: current year of simulation (constant for all years of a crop rotation)
|
|
350
|
+
crop_year: simulated year (each row in input file must correspond to a certain year)
|
|
351
|
+
year_in_perennial_stand: year within the perennial stand (if any). Each year of a perennial stand must have the year identified in the row of the input file. E.g. a six year perennial stand would have one row with this value set 1 for the first year, 2 for the second year, etc
|
|
352
|
+
crop_type: CropType instance
|
|
353
|
+
tillage_type: TillageType instance
|
|
354
|
+
perennial_stand_id: Used to group all years of a perennial stand together. Each year in a distinct perennial stand must have this value set. All years in the same perennial stand must have this same ID/value. Can be thought of as a 'group' ID
|
|
355
|
+
perennial_stand_length: (-) number of years a perennial crop is grown
|
|
356
|
+
relative_biomass_information_data: RelativeBiomassInformationData instance
|
|
357
|
+
crop_yield: (kg(DM)/ha) crop yield
|
|
358
|
+
harvest_method: HarvestMethod
|
|
359
|
+
nitrogen_fertilizer_rate: (kg(N)/ha) applied nitrogen
|
|
360
|
+
under_sown_crops_used: Set to True when this view item is a perennial crop and the previous year is an annual crop and the user wants to indicate that this year's crop (the perennial) is undersown into the previous year's crop (the annual)
|
|
361
|
+
field_system_component_guid: Unique ID for each field component on the farm
|
|
362
|
+
province: CanadianProvince instance
|
|
363
|
+
clay_content: (-) fraction of clay in soil (between 0 and 1)
|
|
364
|
+
sand_content: (-) fraction of sand in soil (between 0 and 1)
|
|
365
|
+
organic_carbon_percentage: (%) percentage of organic C in soil (between 0 and 100)
|
|
366
|
+
soil_top_layer_thickness: (mm) thickness of the soil top layer
|
|
367
|
+
soil_functional_category: SoilFunctionalCategory instance
|
|
368
|
+
fertilizer_blend: FertilizerBlends instance
|
|
369
|
+
evapotranspiration: (mm/d) all-year daily values of reference crop evapotranspiration
|
|
370
|
+
precipitation: (mm/d) all-year values of precipitation
|
|
371
|
+
temperature: (degrees Celsius) all-year values of air temperature
|
|
372
|
+
amount_of_irrigation: (mm/ha) total amount of irrigation
|
|
373
|
+
number_of_pesticide_passes: number of pesticide passes
|
|
374
|
+
amount_of_manure_applied: (kg/ha) amount of manure applied to the field
|
|
375
|
+
manure_application_type: ManureApplicationTypes instance
|
|
376
|
+
manure_animal_source_type: ManureAnimalSourceTypes instance
|
|
377
|
+
manure_state_type: ManureStateType instance
|
|
378
|
+
manure_location_source_type: ManureLocationSourceType instance
|
|
379
|
+
"""
|
|
380
|
+
super().__init__()
|
|
381
|
+
|
|
382
|
+
self.name.value = name
|
|
383
|
+
self.area.value = field_area
|
|
384
|
+
self.current_year.value = current_year
|
|
385
|
+
self.crop_year.value = crop_year
|
|
386
|
+
self.crop_type.value = crop_type
|
|
387
|
+
self.tillage_type.value = tillage_type
|
|
388
|
+
self.year_in_perennial_stand.value = year_in_perennial_stand
|
|
389
|
+
self.perennial_stand_id.value = str(perennial_stand_id)
|
|
390
|
+
self.perennial_stand_length.value = perennial_stand_length
|
|
391
|
+
|
|
392
|
+
self.initialize_biomass_coefficients(residue_data=relative_biomass_information_data)
|
|
393
|
+
self.initialize_nitrogen_content(residue_data=relative_biomass_information_data)
|
|
394
|
+
|
|
395
|
+
self.nitrogen_fixation.value = get_nitrogen_fixation(crop_type=crop_type)
|
|
396
|
+
self.crop_yield.value = crop_yield
|
|
397
|
+
self.harvest_method.value = harvest_method if harvest_method is not None else self.get_default_harvest_method()
|
|
398
|
+
self.nitrogen_fertilizer_rate.value = nitrogen_fertilizer_rate
|
|
399
|
+
|
|
400
|
+
self.amount_of_irrigation.value = amount_of_irrigation
|
|
401
|
+
self.set_irrigation_type()
|
|
402
|
+
|
|
403
|
+
self.moisture_content_of_crop.value = relative_biomass_information_data.moisture_content_of_product / 100
|
|
404
|
+
self.set_moisture_content()
|
|
405
|
+
self.set_percentage_returns()
|
|
406
|
+
self.number_of_pesticide_passes.value = number_of_pesticide_passes
|
|
407
|
+
self.is_pesticide_used.value = "Yes" if number_of_pesticide_passes > 0 else "No"
|
|
408
|
+
|
|
409
|
+
self.amount_of_manure_applied.value = amount_of_manure_applied
|
|
410
|
+
self.manure_applied.value = amount_of_manure_applied > 0
|
|
411
|
+
self.manure_application_type.value = manure_application_type
|
|
412
|
+
self.manure_animal_source_type.value = manure_animal_source_type
|
|
413
|
+
self.manure_state_type.value = manure_state_type.value
|
|
414
|
+
self.manure_location_source_type.value = manure_location_source_type
|
|
415
|
+
self.under_sown_crops_used.value = str(under_sown_crops_used)
|
|
416
|
+
self.field_system_component_guid.value = str(field_system_component_guid)
|
|
417
|
+
|
|
418
|
+
self.fuel_energy.value = get_fuel_energy_estimate(
|
|
419
|
+
province=province,
|
|
420
|
+
soil_category=soil_functional_category,
|
|
421
|
+
tillage_type=tillage_type,
|
|
422
|
+
crop_type=crop_type)
|
|
423
|
+
self.herbicide_energy.value = get_herbicide_energy_estimate(
|
|
424
|
+
province=province,
|
|
425
|
+
soil_category=soil_functional_category,
|
|
426
|
+
tillage_type=tillage_type,
|
|
427
|
+
crop_type=crop_type)
|
|
428
|
+
self.fertilizer_blend.value = fertilizer_blend
|
|
429
|
+
|
|
430
|
+
is_perennial = crop_type.is_perennial()
|
|
431
|
+
self.climate_parameter.value = calculate_climate_parameter(
|
|
432
|
+
emergence_day=Defaults.EmergenceDayForPerennials if is_perennial else Defaults.EmergenceDay,
|
|
433
|
+
ripening_day=Defaults.RipeningDayForPerennials if is_perennial else Defaults.RipeningDay,
|
|
434
|
+
crop_yield=crop_yield,
|
|
435
|
+
clay=clay_content,
|
|
436
|
+
sand=sand_content,
|
|
437
|
+
layer_thickness_in_millimeters=soil_top_layer_thickness,
|
|
438
|
+
percentage_soil_organic_carbon=organic_carbon_percentage,
|
|
439
|
+
variance=Defaults.VarianceForPerennials if is_perennial else Defaults.Variance,
|
|
440
|
+
alfa=Defaults.Alfa,
|
|
441
|
+
decomposition_minimum_temperature=Defaults.DecompositionMinimumTemperature,
|
|
442
|
+
decomposition_maximum_temperature=Defaults.DecompositionMaximumTemperature,
|
|
443
|
+
moisture_response_function_at_wilting_point=Defaults.MoistureResponseFunctionAtWiltingPoint,
|
|
444
|
+
moisture_response_function_at_saturation=Defaults.MoistureResponseFunctionAtSaturation,
|
|
445
|
+
evapotranspirations=evapotranspiration,
|
|
446
|
+
precipitations=precipitation,
|
|
447
|
+
temperatures=temperature)
|
|
448
|
+
self.tillage_factor.value = calculate_tillage_factor(
|
|
449
|
+
province=province,
|
|
450
|
+
soil_functional_category=soil_functional_category,
|
|
451
|
+
tillage_type=tillage_type,
|
|
452
|
+
crop_type=crop_type)
|
|
453
|
+
self.management_factor.value = calculate_management_factor(
|
|
454
|
+
climate_parameter=self.climate_parameter.value,
|
|
455
|
+
tillage_factor=self.tillage_factor.value)
|
|
456
|
+
|
|
457
|
+
self.sand.value = sand_content
|
|
458
|
+
self.lignin.value = relative_biomass_information_data.lignin_content
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
from pyholos.components.common import convert_province_name
|
|
2
|
+
from pyholos.components.land_management.crop import (CropType,
|
|
3
|
+
convert_crop_type_name)
|
|
4
|
+
from pyholos.config import PathsHolosResources
|
|
5
|
+
from pyholos.common2 import CanadianProvince
|
|
6
|
+
from pyholos.utils import read_holos_resource_table
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class LoadedData:
|
|
10
|
+
def __init__(self):
|
|
11
|
+
self.table_small_yield_area = self.read_small_yield_area_data()
|
|
12
|
+
|
|
13
|
+
@staticmethod
|
|
14
|
+
def read_small_yield_area_data():
|
|
15
|
+
"""Loads default yield data table.
|
|
16
|
+
|
|
17
|
+
Holos source code:
|
|
18
|
+
https://github.com/holos-aafc/Holos/blob/d6dba2d07413fd2d23439b60a6bb9217c8ebb048/H.Core/Providers/Soil/SmallAreaYieldProvider.cs#L113
|
|
19
|
+
"""
|
|
20
|
+
excluded_cols = [4, 14, 15, 19, 20, 37, 38, 40]
|
|
21
|
+
df = read_holos_resource_table(
|
|
22
|
+
path_file=PathsHolosResources.Table_small_area_yields,
|
|
23
|
+
usecols=[v for v in range(41) if v not in excluded_cols])
|
|
24
|
+
|
|
25
|
+
columns = list(df.columns[:4]) + [convert_crop_type_name(name=v).value for v in df.columns[4:]]
|
|
26
|
+
|
|
27
|
+
for crop, replacing_crop in [
|
|
28
|
+
(CropType.MustardSeed, CropType.Mustard),
|
|
29
|
+
(CropType.DryFieldPeas, CropType.DryPeas),
|
|
30
|
+
(CropType.TimothyHay, CropType.TamePasture)
|
|
31
|
+
]:
|
|
32
|
+
columns[columns.index(crop)] = replacing_crop
|
|
33
|
+
|
|
34
|
+
df.columns = columns
|
|
35
|
+
df['PROVINCE'] = df['PROVINCE'].apply(lambda x: convert_province_name(name=x).name)
|
|
36
|
+
|
|
37
|
+
return df.set_index(['YEAR', 'PROVINCE', 'POLY_ID'])
|
|
38
|
+
|
|
39
|
+
def get_yield(
|
|
40
|
+
self,
|
|
41
|
+
year: int,
|
|
42
|
+
polygon_id: int,
|
|
43
|
+
crop_type: CropType,
|
|
44
|
+
province: CanadianProvince
|
|
45
|
+
) -> float:
|
|
46
|
+
if crop_type.is_perennial():
|
|
47
|
+
# Small area yield table only has one perennial type 'tame hay'. Had discussion with team on 8/17/2021 and it was agreed
|
|
48
|
+
# that we would use tame hay yields as the default for all perennial types until better numbers were found
|
|
49
|
+
lookup_crop_type = CropType.TamePasture
|
|
50
|
+
|
|
51
|
+
elif crop_type == CropType.GrassSilage:
|
|
52
|
+
lookup_crop_type = CropType.TamePasture
|
|
53
|
+
|
|
54
|
+
elif crop_type == CropType.Flax:
|
|
55
|
+
lookup_crop_type = CropType.FlaxSeed
|
|
56
|
+
|
|
57
|
+
elif crop_type == CropType.FieldPeas:
|
|
58
|
+
lookup_crop_type = CropType.DryPeas
|
|
59
|
+
else:
|
|
60
|
+
lookup_crop_type = crop_type
|
|
61
|
+
|
|
62
|
+
try:
|
|
63
|
+
res = self.table_small_yield_area.loc[(year, province.name, polygon_id), lookup_crop_type]
|
|
64
|
+
except KeyError:
|
|
65
|
+
res = None
|
|
66
|
+
return res
|
pyholos/config.py
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
from os import environ
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
PATH_HOLOS_CLI = Path(environ['PATH_HOLOS_CLI'])
|
|
5
|
+
DATE_FMT = "%Y-%m-%d"
|
|
6
|
+
|
|
7
|
+
_PATH_HOLOS_SERVICE_RESOURCES = Path(__file__).parent / 'resources'
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class PathsHolosResources:
|
|
11
|
+
_path_root = _PATH_HOLOS_SERVICE_RESOURCES / 'holos'
|
|
12
|
+
Table_Tillage_Factor = _path_root / (
|
|
13
|
+
'Table_Tillage_Factor.csv')
|
|
14
|
+
Table_6_Manure_Types_And_Default_Composition = _path_root / (
|
|
15
|
+
'Table_6_Manure_Types_And_Default_Composition.csv')
|
|
16
|
+
Table_7_Relative_Biomass_Information = _path_root / (
|
|
17
|
+
'Table_7_Relative_Biomass_Information.csv')
|
|
18
|
+
Table_9_Default_Values_For_Nitrogen_Lignin_In_Crops = _path_root / (
|
|
19
|
+
'Table_9_Default_Values_For_Nitrogen_Lignin_In_Crops.csv')
|
|
20
|
+
Table_16_Livestock_Coefficients_BeefAndDairy_Cattle_Provider = _path_root / (
|
|
21
|
+
'Table_16_Livestock_Coefficients_BeefAndDairy_Cattle_Provider.csv')
|
|
22
|
+
Table_21_Average_Milk_Production_For_Dairy_Cows_By_Province = _path_root / (
|
|
23
|
+
'Table_21_Average_Milk_Production_For_Dairy_Cows_By_Province.csv')
|
|
24
|
+
Table_22_Livestock_Coefficients_For_Sheep = _path_root / (
|
|
25
|
+
"Table_22_Livestock_Coefficients_For_Sheep.csv")
|
|
26
|
+
Table_29_Percentage_Total_Manure_Produced_In_Systems = _path_root / (
|
|
27
|
+
"Table_29_Percentage_Total_Manure_Produced_In_Systems.csv")
|
|
28
|
+
Table_30_Default_Bedding_Material_Composition_Provider = _path_root / (
|
|
29
|
+
'Table_30_Default_Bedding_Material_Composition_Provider.csv')
|
|
30
|
+
Table_50_Fuel_Energy_Requirement_Estimates_By_Region = _path_root / (
|
|
31
|
+
'Table_50_Fuel_Energy_Requirement_Estimates_By_Region.csv')
|
|
32
|
+
Table_51_Herbicide_Energy_Requirement_Estimates_By_Region = _path_root / (
|
|
33
|
+
'Table_51_Herbicide_Energy_Requirement_Estimates_By_Region.csv')
|
|
34
|
+
Table_61_Fractions_of_dairy_cattle_N_volatilized = _path_root / (
|
|
35
|
+
'Table_61_Fractions_of_dairy_cattle_N_volatilized.csv')
|
|
36
|
+
Table_62_Fractions_of_swine_N_volatilized = _path_root / (
|
|
37
|
+
'Table_62_Fractions_of_swine_N_volatilized.csv')
|
|
38
|
+
|
|
39
|
+
Table_small_area_yields = _path_root / (
|
|
40
|
+
'small_area_yields.csv')
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class PathsSlcData:
|
|
44
|
+
_path_root = _PATH_HOLOS_SERVICE_RESOURCES / 'soil_landscapes_of_canada_v3r2'
|
|
45
|
+
geojson_file = _path_root / 'soil_landscapes_of_canada_v3r2.geojson'
|
|
46
|
+
csv_dir = _path_root / 'soil_landscapes_of_canada_v3r2_csv'
|
|
47
|
+
cmp_file = csv_dir / 'ca_all_slc_v3r2_cmp.csv'
|
|
48
|
+
slt_file = csv_dir / 'ca_all_slc_v3r2_slt.csv'
|
|
49
|
+
snt_file = csv_dir / 'ca_all_slc_v3r2_snt.csv'
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
class CoreConstants:
|
|
2
|
+
DefaultNumberOfDecimalPlaces: int = 3
|
|
3
|
+
|
|
4
|
+
DaysInYear: int = 365
|
|
5
|
+
|
|
6
|
+
ValueNotDetermined = 0
|
|
7
|
+
NotApplicable = -100000
|
|
8
|
+
|
|
9
|
+
NitrogenDepositionAmount = 5
|
|
10
|
+
"""(kg(N)/ha/year) Atmospheric Nitrogen deposition amount
|
|
11
|
+
Holos source doc: page 74 in https://github.com/holos-aafc/Holos/raw/refs/heads/main/AAFC_Technical_Report_Holos_V4.0_Algorithm_Document_DRAFTVersion_18Nov2024.docx
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
CarbonConcentration = 0.45
|
|
15
|
+
"""(kg(C)/kg(plant biomass)) carbon concentration in plant biomass
|
|
16
|
+
Holos source code: https://github.com/holos-aafc/Holos/blob/b183dab99d211158d1fed9da5370ce599ac7c914/H.Core/CoreConstants.cs#L90
|
|
17
|
+
Holos source doc: footnote in page 37 in https://github.com/holos-aafc/Holos/raw/refs/heads/main/AAFC_Technical_Report_Holos_V4.0_Algorithm_Document_DRAFTVersion_18Nov2024.docx
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
MinimumYear = 1970
|