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.

Files changed (55) hide show
  1. pyholos/__init__.py +0 -0
  2. pyholos/common.py +141 -0
  3. pyholos/common2.py +157 -0
  4. pyholos/components/__init__.py +0 -0
  5. pyholos/components/animals/__init__.py +0 -0
  6. pyholos/components/animals/beef.py +766 -0
  7. pyholos/components/animals/common.py +2301 -0
  8. pyholos/components/animals/dairy.py +341 -0
  9. pyholos/components/animals/sheep.py +412 -0
  10. pyholos/components/common.py +170 -0
  11. pyholos/components/land_management/__init__.py +0 -0
  12. pyholos/components/land_management/carbon/__init__.py +0 -0
  13. pyholos/components/land_management/carbon/climate.py +863 -0
  14. pyholos/components/land_management/carbon/management.py +21 -0
  15. pyholos/components/land_management/carbon/relative_biomass_information.py +410 -0
  16. pyholos/components/land_management/carbon/tillage.py +88 -0
  17. pyholos/components/land_management/common.py +220 -0
  18. pyholos/components/land_management/crop.py +1233 -0
  19. pyholos/components/land_management/field_system.py +458 -0
  20. pyholos/components/land_management/utils.py +66 -0
  21. pyholos/config.py +49 -0
  22. pyholos/core_constants.py +20 -0
  23. pyholos/defaults.py +116 -0
  24. pyholos/farm/__init__.py +0 -0
  25. pyholos/farm/enums.py +54 -0
  26. pyholos/farm/farm.py +101 -0
  27. pyholos/farm/farm_inputs.py +633 -0
  28. pyholos/farm/farm_settings.py +542 -0
  29. pyholos/launching.py +86 -0
  30. pyholos/postprocessing/__init__.py +0 -0
  31. pyholos/postprocessing/plots.py +164 -0
  32. pyholos/postprocessing/postprocessing.py +38 -0
  33. pyholos/resources/holos/Table_16_Livestock_Coefficients_BeefAndDairy_Cattle_Provider.csv +21 -0
  34. pyholos/resources/holos/Table_21_Average_Milk_Production_For_Dairy_Cows_By_Province.csv +23 -0
  35. pyholos/resources/holos/Table_22_Livestock_Coefficients_For_Sheep.csv +28 -0
  36. pyholos/resources/holos/Table_29_Percentage_Total_Manure_Produced_In_Systems.csv +56 -0
  37. pyholos/resources/holos/Table_30_Default_Bedding_Material_Composition_Provider.csv +28 -0
  38. pyholos/resources/holos/Table_50_Fuel_Energy_Requirement_Estimates_By_Region.csv +81 -0
  39. pyholos/resources/holos/Table_51_Herbicide_Energy_Requirement_Estimates_By_Region.csv +81 -0
  40. pyholos/resources/holos/Table_61_Fractions_of_dairy_cattle_N_volatilized.csv +25 -0
  41. pyholos/resources/holos/Table_62_Fractions_of_swine_N_volatilized.csv +25 -0
  42. pyholos/resources/holos/Table_6_Manure_Types_And_Default_Composition.csv +126 -0
  43. pyholos/resources/holos/Table_7_Relative_Biomass_Information.csv +112 -0
  44. pyholos/resources/holos/Table_9_Default_Values_For_Nitrogen_Lignin_In_Crops.csv +72 -0
  45. pyholos/resources/holos/Table_Tillage_Factor.csv +13 -0
  46. pyholos/resources/holos/feeds.csv +223 -0
  47. pyholos/resources/holos/main_tables.py +493 -0
  48. pyholos/resources/holos/small_area_yields.csv +167159 -0
  49. pyholos/resources/soil_landscapes_of_canada_v3r2.zip +0 -0
  50. pyholos/soil.py +439 -0
  51. pyholos/utils.py +83 -0
  52. pyholos-0.0.1.dist-info/METADATA +16 -0
  53. pyholos-0.0.1.dist-info/RECORD +55 -0
  54. pyholos-0.0.1.dist-info/WHEEL +4 -0
  55. 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