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
|
Binary file
|
pyholos/soil.py
ADDED
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
from enum import StrEnum, auto, unique
|
|
2
|
+
|
|
3
|
+
from pyholos import common2
|
|
4
|
+
from pyholos.common import Region, get_region
|
|
5
|
+
from pyholos.config import PathsSlcData
|
|
6
|
+
from pyholos.common2 import CanadianProvince
|
|
7
|
+
from pyholos.utils import AutoNameEnum, keep_alphabetical_characters
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@unique
|
|
11
|
+
class SoilTexture(StrEnum):
|
|
12
|
+
"""Holos Source Code:
|
|
13
|
+
https://github.com/holos-aafc/Holos/blob/main/H.Core/Enumerations/SoilTexture.cs
|
|
14
|
+
"""
|
|
15
|
+
Fine = auto()
|
|
16
|
+
Medium = auto()
|
|
17
|
+
Coarse = auto()
|
|
18
|
+
Unknown = auto()
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class SoilFunctionalCategory(AutoNameEnum):
|
|
22
|
+
NotApplicable = auto()
|
|
23
|
+
Brown = auto()
|
|
24
|
+
BrownChernozem = auto()
|
|
25
|
+
DarkBrown = auto()
|
|
26
|
+
DarkBrownChernozem = auto()
|
|
27
|
+
Black = auto()
|
|
28
|
+
BlackGrayChernozem = auto()
|
|
29
|
+
Organic = auto()
|
|
30
|
+
EasternCanada = auto()
|
|
31
|
+
All = auto()
|
|
32
|
+
Unknown = auto()
|
|
33
|
+
Grey = auto()
|
|
34
|
+
DarkGrey = auto()
|
|
35
|
+
|
|
36
|
+
def get_simplified_soil_category(self):
|
|
37
|
+
if self in [
|
|
38
|
+
self.__class__.Brown,
|
|
39
|
+
self.__class__.DarkBrown,
|
|
40
|
+
self.__class__.BrownChernozem,
|
|
41
|
+
self.__class__.DarkBrownChernozem
|
|
42
|
+
]:
|
|
43
|
+
res = self.__class__.Brown
|
|
44
|
+
elif self in [
|
|
45
|
+
self.__class__.Black,
|
|
46
|
+
self.__class__.BlackGrayChernozem
|
|
47
|
+
]:
|
|
48
|
+
res = SoilFunctionalCategory.Black
|
|
49
|
+
else:
|
|
50
|
+
# Other types cannot be reduced/simplified (i.e. Organic, Eastern Canada, etc.)
|
|
51
|
+
res = self
|
|
52
|
+
|
|
53
|
+
return res
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def convert_soil_texture_name(
|
|
57
|
+
name: str
|
|
58
|
+
) -> SoilTexture:
|
|
59
|
+
"""Returns a SoilTexture member as a function of the soil name.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
name: soil name
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
SoilTexture member
|
|
66
|
+
|
|
67
|
+
Holos source code:
|
|
68
|
+
https://github.com/holos-aafc/Holos/blob/768b3d8fe2565dad0ba01fb8490974f1047a114f/H.Core/Converters/SoilTextureStringConverter.cs#L9
|
|
69
|
+
"""
|
|
70
|
+
match keep_alphabetical_characters(name=name):
|
|
71
|
+
case "fine":
|
|
72
|
+
return SoilTexture.Fine
|
|
73
|
+
case "coarse":
|
|
74
|
+
return SoilTexture.Coarse
|
|
75
|
+
case "medium":
|
|
76
|
+
return SoilTexture.Medium
|
|
77
|
+
case _:
|
|
78
|
+
# throw new Exception(string.Format(Resources.ExceptionUnknownSoilTextureString, input));
|
|
79
|
+
return SoilTexture.Unknown
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def convert_soil_functional_category_name(
|
|
83
|
+
name: str
|
|
84
|
+
) -> SoilFunctionalCategory:
|
|
85
|
+
"""Returns a SoilFunctionalCategory member as a function of the soil functional category name.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
name: soil functional category name
|
|
89
|
+
|
|
90
|
+
Returns:
|
|
91
|
+
SoilFunctionalCategory member
|
|
92
|
+
|
|
93
|
+
Holos source code:
|
|
94
|
+
https://github.com/holos-aafc/Holos/blob/768b3d8fe2565dad0ba01fb8490974f1047a114f/H.Core/Converters/SoilFunctionalCategoryStringConverter.cs#L10
|
|
95
|
+
"""
|
|
96
|
+
match keep_alphabetical_characters(name=name):
|
|
97
|
+
case "brownchernozem":
|
|
98
|
+
return SoilFunctionalCategory.BrownChernozem
|
|
99
|
+
case "darkbrownchernozem":
|
|
100
|
+
return SoilFunctionalCategory.DarkBrownChernozem
|
|
101
|
+
case "blackgraychernozem":
|
|
102
|
+
return SoilFunctionalCategory.BlackGrayChernozem
|
|
103
|
+
case "all":
|
|
104
|
+
return SoilFunctionalCategory.All
|
|
105
|
+
case "brown":
|
|
106
|
+
return SoilFunctionalCategory.Brown
|
|
107
|
+
case "darkbrown":
|
|
108
|
+
return SoilFunctionalCategory.DarkBrown
|
|
109
|
+
case "black":
|
|
110
|
+
return SoilFunctionalCategory.Black
|
|
111
|
+
case "organic":
|
|
112
|
+
return SoilFunctionalCategory.Organic
|
|
113
|
+
case "easterncanada" | "east":
|
|
114
|
+
return SoilFunctionalCategory.EasternCanada
|
|
115
|
+
case _:
|
|
116
|
+
# Trace.TraceError($"{nameof(SoilFunctionalCategoryStringConverter)}: Soil functional category '{input}' not mapped, returning default value.")
|
|
117
|
+
return SoilFunctionalCategory.NotApplicable
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
class SoilGreatGroup:
|
|
121
|
+
def __init__(
|
|
122
|
+
self,
|
|
123
|
+
soil_great_group_type: str,
|
|
124
|
+
region: str,
|
|
125
|
+
soil_functional_category: str
|
|
126
|
+
):
|
|
127
|
+
self.soil_great_group_type = soil_great_group_type
|
|
128
|
+
self.region = region
|
|
129
|
+
self.soil_functional_category = soil_functional_category
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def get_soil_great_group_table() -> list[SoilGreatGroup]:
|
|
133
|
+
return [
|
|
134
|
+
SoilGreatGroup(
|
|
135
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.BrownChernozem.name,
|
|
136
|
+
region=Region.WesternCanada,
|
|
137
|
+
soil_functional_category=SoilFunctionalCategory.Brown),
|
|
138
|
+
SoilGreatGroup(
|
|
139
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.BrownChernozem.name,
|
|
140
|
+
region=Region.EasternCanada,
|
|
141
|
+
soil_functional_category=SoilFunctionalCategory.NotApplicable),
|
|
142
|
+
SoilGreatGroup(
|
|
143
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.DarkBrownChernozem.name,
|
|
144
|
+
region=Region.WesternCanada,
|
|
145
|
+
soil_functional_category=SoilFunctionalCategory.DarkBrown),
|
|
146
|
+
SoilGreatGroup(
|
|
147
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.DarkBrownChernozem.name,
|
|
148
|
+
region=Region.EasternCanada,
|
|
149
|
+
soil_functional_category=SoilFunctionalCategory.NotApplicable),
|
|
150
|
+
SoilGreatGroup(
|
|
151
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.BlackChernozem.name,
|
|
152
|
+
region=Region.WesternCanada,
|
|
153
|
+
soil_functional_category=SoilFunctionalCategory.Black),
|
|
154
|
+
SoilGreatGroup(
|
|
155
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.BlackChernozem.name,
|
|
156
|
+
region=Region.EasternCanada,
|
|
157
|
+
soil_functional_category=SoilFunctionalCategory.NotApplicable),
|
|
158
|
+
SoilGreatGroup(
|
|
159
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.DarkGrayChernozem.name,
|
|
160
|
+
region=Region.WesternCanada,
|
|
161
|
+
soil_functional_category=SoilFunctionalCategory.Black),
|
|
162
|
+
SoilGreatGroup(
|
|
163
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.DarkGrayChernozem.name,
|
|
164
|
+
region=Region.EasternCanada,
|
|
165
|
+
soil_functional_category=SoilFunctionalCategory.NotApplicable),
|
|
166
|
+
SoilGreatGroup(
|
|
167
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.Solonetz.name,
|
|
168
|
+
region=Region.WesternCanada,
|
|
169
|
+
soil_functional_category=SoilFunctionalCategory.Brown),
|
|
170
|
+
SoilGreatGroup(
|
|
171
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.Solonetz.name,
|
|
172
|
+
region=Region.EasternCanada,
|
|
173
|
+
soil_functional_category=SoilFunctionalCategory.EasternCanada),
|
|
174
|
+
SoilGreatGroup(
|
|
175
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.SolodizedSolonetz.name,
|
|
176
|
+
region=Region.WesternCanada,
|
|
177
|
+
soil_functional_category=SoilFunctionalCategory.Brown),
|
|
178
|
+
SoilGreatGroup(
|
|
179
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.SolodizedSolonetz.name,
|
|
180
|
+
region=Region.EasternCanada,
|
|
181
|
+
soil_functional_category=SoilFunctionalCategory.EasternCanada),
|
|
182
|
+
SoilGreatGroup(
|
|
183
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.Solod.name,
|
|
184
|
+
region=Region.WesternCanada,
|
|
185
|
+
soil_functional_category=SoilFunctionalCategory.Brown),
|
|
186
|
+
SoilGreatGroup(
|
|
187
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.Solod.name,
|
|
188
|
+
region=Region.EasternCanada,
|
|
189
|
+
soil_functional_category=SoilFunctionalCategory.EasternCanada),
|
|
190
|
+
SoilGreatGroup(
|
|
191
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.VerticSolonetz.name,
|
|
192
|
+
region=Region.WesternCanada,
|
|
193
|
+
soil_functional_category=SoilFunctionalCategory.Brown),
|
|
194
|
+
SoilGreatGroup(
|
|
195
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.VerticSolonetz.name,
|
|
196
|
+
region=Region.EasternCanada,
|
|
197
|
+
soil_functional_category=SoilFunctionalCategory.EasternCanada),
|
|
198
|
+
SoilGreatGroup(
|
|
199
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.GrayBrownLuvisol.name,
|
|
200
|
+
region=Region.WesternCanada,
|
|
201
|
+
soil_functional_category=SoilFunctionalCategory.NotApplicable),
|
|
202
|
+
SoilGreatGroup(
|
|
203
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.GrayBrownLuvisol.name,
|
|
204
|
+
region=Region.EasternCanada,
|
|
205
|
+
soil_functional_category=SoilFunctionalCategory.EasternCanada),
|
|
206
|
+
SoilGreatGroup(
|
|
207
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.GrayLuvisol.name,
|
|
208
|
+
region=Region.WesternCanada,
|
|
209
|
+
soil_functional_category=SoilFunctionalCategory.Black),
|
|
210
|
+
SoilGreatGroup(
|
|
211
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.GrayLuvisol.name,
|
|
212
|
+
region=Region.EasternCanada,
|
|
213
|
+
soil_functional_category=SoilFunctionalCategory.EasternCanada),
|
|
214
|
+
SoilGreatGroup(
|
|
215
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.FerroHumicPodzol.name,
|
|
216
|
+
region=Region.WesternCanada,
|
|
217
|
+
soil_functional_category=SoilFunctionalCategory.Brown),
|
|
218
|
+
SoilGreatGroup(
|
|
219
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.FerroHumicPodzol.name,
|
|
220
|
+
region=Region.EasternCanada,
|
|
221
|
+
soil_functional_category=SoilFunctionalCategory.EasternCanada),
|
|
222
|
+
SoilGreatGroup(
|
|
223
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.HumicPodzol.name,
|
|
224
|
+
region=Region.WesternCanada,
|
|
225
|
+
soil_functional_category=SoilFunctionalCategory.Brown),
|
|
226
|
+
SoilGreatGroup(
|
|
227
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.HumicPodzol.name,
|
|
228
|
+
region=Region.EasternCanada,
|
|
229
|
+
soil_functional_category=SoilFunctionalCategory.EasternCanada),
|
|
230
|
+
SoilGreatGroup(
|
|
231
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.HumoFerricPodzol.name,
|
|
232
|
+
region=Region.WesternCanada,
|
|
233
|
+
soil_functional_category=SoilFunctionalCategory.Brown),
|
|
234
|
+
SoilGreatGroup(
|
|
235
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.HumoFerricPodzol.name,
|
|
236
|
+
region=Region.EasternCanada,
|
|
237
|
+
soil_functional_category=SoilFunctionalCategory.EasternCanada),
|
|
238
|
+
SoilGreatGroup(
|
|
239
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.MelanicBrunisol.name,
|
|
240
|
+
region=Region.WesternCanada,
|
|
241
|
+
soil_functional_category=SoilFunctionalCategory.Brown),
|
|
242
|
+
SoilGreatGroup(
|
|
243
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.MelanicBrunisol.name,
|
|
244
|
+
region=Region.EasternCanada,
|
|
245
|
+
soil_functional_category=SoilFunctionalCategory.EasternCanada),
|
|
246
|
+
SoilGreatGroup(
|
|
247
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.EutricBrunisol.name,
|
|
248
|
+
region=Region.WesternCanada,
|
|
249
|
+
soil_functional_category=SoilFunctionalCategory.Brown),
|
|
250
|
+
SoilGreatGroup(
|
|
251
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.EutricBrunisol.name,
|
|
252
|
+
region=Region.EasternCanada,
|
|
253
|
+
soil_functional_category=SoilFunctionalCategory.EasternCanada),
|
|
254
|
+
SoilGreatGroup(
|
|
255
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.SombricBrunisol.name,
|
|
256
|
+
region=Region.WesternCanada,
|
|
257
|
+
soil_functional_category=SoilFunctionalCategory.Brown),
|
|
258
|
+
SoilGreatGroup(
|
|
259
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.SombricBrunisol.name,
|
|
260
|
+
region=Region.EasternCanada,
|
|
261
|
+
soil_functional_category=SoilFunctionalCategory.EasternCanada),
|
|
262
|
+
SoilGreatGroup(
|
|
263
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.DystricBrunisol.name,
|
|
264
|
+
region=Region.WesternCanada,
|
|
265
|
+
soil_functional_category=SoilFunctionalCategory.Brown),
|
|
266
|
+
SoilGreatGroup(
|
|
267
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.DystricBrunisol.name,
|
|
268
|
+
region=Region.EasternCanada,
|
|
269
|
+
soil_functional_category=SoilFunctionalCategory.EasternCanada),
|
|
270
|
+
SoilGreatGroup(
|
|
271
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.HumicGleysol.name,
|
|
272
|
+
region=Region.WesternCanada,
|
|
273
|
+
soil_functional_category=SoilFunctionalCategory.Brown),
|
|
274
|
+
SoilGreatGroup(
|
|
275
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.HumicGleysol.name,
|
|
276
|
+
region=Region.EasternCanada,
|
|
277
|
+
soil_functional_category=SoilFunctionalCategory.EasternCanada),
|
|
278
|
+
SoilGreatGroup(
|
|
279
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.Gleysol.name,
|
|
280
|
+
region=Region.WesternCanada,
|
|
281
|
+
soil_functional_category=SoilFunctionalCategory.Brown),
|
|
282
|
+
SoilGreatGroup(
|
|
283
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.Gleysol.name,
|
|
284
|
+
region=Region.EasternCanada,
|
|
285
|
+
soil_functional_category=SoilFunctionalCategory.EasternCanada),
|
|
286
|
+
SoilGreatGroup(
|
|
287
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.LuvicGleysol.name,
|
|
288
|
+
region=Region.WesternCanada,
|
|
289
|
+
soil_functional_category=SoilFunctionalCategory.Black),
|
|
290
|
+
SoilGreatGroup(
|
|
291
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.LuvicGleysol.name,
|
|
292
|
+
region=Region.EasternCanada,
|
|
293
|
+
soil_functional_category=SoilFunctionalCategory.EasternCanada),
|
|
294
|
+
SoilGreatGroup(
|
|
295
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.Fibrisol.name,
|
|
296
|
+
region=Region.WesternCanada,
|
|
297
|
+
soil_functional_category=SoilFunctionalCategory.Organic),
|
|
298
|
+
SoilGreatGroup(
|
|
299
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.Fibrisol.name,
|
|
300
|
+
region=Region.EasternCanada,
|
|
301
|
+
soil_functional_category=SoilFunctionalCategory.Organic),
|
|
302
|
+
SoilGreatGroup(
|
|
303
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.Mesisol.name,
|
|
304
|
+
region=Region.WesternCanada,
|
|
305
|
+
soil_functional_category=SoilFunctionalCategory.Organic),
|
|
306
|
+
SoilGreatGroup(
|
|
307
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.Mesisol.name,
|
|
308
|
+
region=Region.EasternCanada,
|
|
309
|
+
soil_functional_category=SoilFunctionalCategory.Organic),
|
|
310
|
+
SoilGreatGroup(
|
|
311
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.OrganicCryosol.name,
|
|
312
|
+
region=Region.WesternCanada,
|
|
313
|
+
soil_functional_category=SoilFunctionalCategory.Organic),
|
|
314
|
+
SoilGreatGroup(
|
|
315
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.OrganicCryosol.name,
|
|
316
|
+
region=Region.EasternCanada,
|
|
317
|
+
soil_functional_category=SoilFunctionalCategory.Organic),
|
|
318
|
+
SoilGreatGroup(
|
|
319
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.NotApplicable.name,
|
|
320
|
+
region=Region.WesternCanada,
|
|
321
|
+
soil_functional_category=SoilFunctionalCategory.NotApplicable),
|
|
322
|
+
SoilGreatGroup(
|
|
323
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.NotApplicable.name,
|
|
324
|
+
region=Region.EasternCanada,
|
|
325
|
+
soil_functional_category=SoilFunctionalCategory.NotApplicable),
|
|
326
|
+
|
|
327
|
+
SoilGreatGroup(
|
|
328
|
+
soil_great_group_type=common2.SoilGreatGroupNamesSlc.Unknown.name,
|
|
329
|
+
region=Region.EasternCanada,
|
|
330
|
+
soil_functional_category=SoilFunctionalCategory.EasternCanada),
|
|
331
|
+
]
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
def seek_soil_functional_category(
|
|
335
|
+
province: common2.CanadianProvince,
|
|
336
|
+
soil_great_group: str
|
|
337
|
+
) -> str:
|
|
338
|
+
region = get_region(province=province)
|
|
339
|
+
|
|
340
|
+
for v in get_soil_great_group_table():
|
|
341
|
+
if all([v.soil_great_group_type == soil_great_group, v.region == region]):
|
|
342
|
+
return v.soil_functional_category
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
def get_soil_functional_category(
|
|
346
|
+
province: common2.CanadianProvince,
|
|
347
|
+
soil_great_group: str
|
|
348
|
+
) -> str:
|
|
349
|
+
soil_functional_category = seek_soil_functional_category(
|
|
350
|
+
province=province,
|
|
351
|
+
soil_great_group=soil_great_group)
|
|
352
|
+
return soil_functional_category if soil_functional_category is not None else SoilFunctionalCategory.Black
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
def set_soil_texture_according_to_holos(
|
|
356
|
+
soil_texture_abbreviation_from_slc: str
|
|
357
|
+
) -> str:
|
|
358
|
+
soil_name = common2.ParentMaterialTextureNamesSlc.get_name(abbreviation=soil_texture_abbreviation_from_slc)
|
|
359
|
+
if soil_name in ('Very Coarse', 'Coarse', 'Moderately Coarse'):
|
|
360
|
+
res = SoilTexture.Coarse.name
|
|
361
|
+
elif soil_name in ('Medium', 'Medium Skeletal'):
|
|
362
|
+
res = SoilTexture.Medium.name
|
|
363
|
+
elif soil_name in ('Moderately Fine', 'Fine', 'Very Fine', 'Fine Skeletal'):
|
|
364
|
+
res = SoilTexture.Fine.name
|
|
365
|
+
else:
|
|
366
|
+
res = SoilTexture.Medium.name
|
|
367
|
+
return res
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
def set_soil_properties(
|
|
371
|
+
latitude: float,
|
|
372
|
+
longitude: float
|
|
373
|
+
) -> dict:
|
|
374
|
+
"""Calculates the soil properties required by Holos 4.0
|
|
375
|
+
|
|
376
|
+
Args:
|
|
377
|
+
latitude: (decimal degrees) latitude of the simulated site
|
|
378
|
+
longitude: (decimal degrees) longitude of the simulated site
|
|
379
|
+
|
|
380
|
+
Returns:
|
|
381
|
+
The following key-value pairs:
|
|
382
|
+
id_polygon (int): ID of the SLC polygon in which the site is located
|
|
383
|
+
province (str): The Canadian Province in which the site is located
|
|
384
|
+
ecodistrict_id (int): ID of the Ecodistrict within which the farm is located
|
|
385
|
+
soil_great_group (str): soil great group (e.g. "Regosol")
|
|
386
|
+
soil_functional_category (str): soil functional (e.g. "Black")
|
|
387
|
+
bulk_density (float): (g cm-3) soil bulk density
|
|
388
|
+
soil_texture (str): soil texture (e.g. "Fine")
|
|
389
|
+
soil_ph (float): (-) soil pH
|
|
390
|
+
top_layer_thickness (float): (mm) thickness of the soil top layer
|
|
391
|
+
sand_proportion (float): (between 0 and 1) fraction of sand in soil
|
|
392
|
+
clay_proportion (float): (between 0 and 1) fraction of clay in soil
|
|
393
|
+
organic_carbon_proportion (float): (between 0 and 100) percentage of soil organic carbon in soil
|
|
394
|
+
|
|
395
|
+
"""
|
|
396
|
+
polygon_properties = common2.get_slc_polygon_properties(
|
|
397
|
+
latitude=latitude,
|
|
398
|
+
longitude=longitude,
|
|
399
|
+
geojson_data=common2.load_slc_data(
|
|
400
|
+
path_slc_geojson_file=PathsSlcData.geojson_file))
|
|
401
|
+
id_polygon = polygon_properties['POLY_ID']
|
|
402
|
+
dominant_component_properties = common2.get_dominant_component_properties(
|
|
403
|
+
id_polygon=id_polygon,
|
|
404
|
+
slc_components_table=common2.read_slc_csv(
|
|
405
|
+
path_file=PathsSlcData.cmp_file,
|
|
406
|
+
usecols=['POLY_ID', 'PROVINCE', 'PERCENT_', 'SOIL_ID']))
|
|
407
|
+
id_soil = dominant_component_properties['SOIL_ID']
|
|
408
|
+
soil_layer_table = common2.get_soil_layer_table(
|
|
409
|
+
id_soil=id_soil,
|
|
410
|
+
slc_soil_layer_table=common2.read_slc_csv(path_file=PathsSlcData.slt_file))
|
|
411
|
+
first_non_litter_layer = common2.get_first_non_litter_layer(
|
|
412
|
+
soil_layer_table=soil_layer_table)
|
|
413
|
+
soil_name_table = common2.get_soil_name_table(
|
|
414
|
+
soil_name_table=common2.read_slc_csv(
|
|
415
|
+
path_file=PathsSlcData.snt_file, usecols=['SOIL_ID', 'PMTEX1', 'G_GROUP3']),
|
|
416
|
+
id_soil=id_soil)
|
|
417
|
+
|
|
418
|
+
province = common2.CanadianProvince.get_name(abbreviation=dominant_component_properties['PROVINCE'])
|
|
419
|
+
soil_great_group = common2.SoilGreatGroupNamesSlc.get_name(
|
|
420
|
+
abbreviation=soil_name_table['G_GROUP3']).replace(' ', '')
|
|
421
|
+
|
|
422
|
+
return dict(
|
|
423
|
+
id_polygon=id_polygon,
|
|
424
|
+
province=province,
|
|
425
|
+
ecodistrict_id=polygon_properties['ECO_ID'],
|
|
426
|
+
soil_great_group=soil_great_group,
|
|
427
|
+
soil_functional_category=get_soil_functional_category(
|
|
428
|
+
province=getattr(CanadianProvince, province),
|
|
429
|
+
soil_great_group=soil_great_group),
|
|
430
|
+
bulk_density=first_non_litter_layer['BD'],
|
|
431
|
+
soil_texture=set_soil_texture_according_to_holos(
|
|
432
|
+
soil_texture_abbreviation_from_slc=soil_name_table['PMTEX1']),
|
|
433
|
+
soil_ph=round(first_non_litter_layer['PH2'], 1),
|
|
434
|
+
top_layer_thickness=first_non_litter_layer['LDEPTH'] * 10,
|
|
435
|
+
sand_proportion=first_non_litter_layer['TSAND'] / 100.,
|
|
436
|
+
clay_proportion=first_non_litter_layer['TCLAY'] / 100.,
|
|
437
|
+
organic_carbon_proportion=round(first_non_litter_layer['ORGCARB'], 2))
|
|
438
|
+
|
|
439
|
+
pass
|
pyholos/utils.py
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from enum import StrEnum
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Callable, Iterable
|
|
5
|
+
|
|
6
|
+
from pandas import DataFrame, read_csv
|
|
7
|
+
|
|
8
|
+
from pyholos.core_constants import CoreConstants
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class AutoNameEnum(StrEnum):
|
|
12
|
+
"""Allows automatically setting the member value identical to the member name."""
|
|
13
|
+
|
|
14
|
+
def _generate_next_value_(self, start, count, last_values):
|
|
15
|
+
return self
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def read_holos_resource_table(
|
|
19
|
+
path_file: Path | str,
|
|
20
|
+
**kwargs
|
|
21
|
+
) -> DataFrame:
|
|
22
|
+
return read_csv(path_file, sep=',', decimal='.', comment='#', **kwargs
|
|
23
|
+
).replace({
|
|
24
|
+
'NotApplicable': CoreConstants.NotApplicable,
|
|
25
|
+
float('nan'): None})
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def get_local_args(kwargs: dict) -> dict:
|
|
29
|
+
return {k: v for k, v in kwargs.items() if not any([k.startswith('_'), k == 'self'])}
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def convert_camel_case_to_space_delimited(s: str) -> str:
|
|
33
|
+
return re.sub("([a-z])([A-Z])", r"\g<1> \g<2>", s)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def concat_lists(*args) -> list:
|
|
37
|
+
return [v for ls in args for v in ls]
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def keep_alphabetical_characters(name: str) -> str:
|
|
41
|
+
return ''.join(s for s in name if s.isalpha()).lower()
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def calc_average(values: Iterable[int | float]) -> float:
|
|
45
|
+
values = list(values)
|
|
46
|
+
return sum(values) / len(list(values))
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def clean_string(
|
|
50
|
+
input_string: str,
|
|
51
|
+
characters_to_remove: str | list[str] = (',', ' ', ';'),
|
|
52
|
+
is_remove_text_between_parentheses: bool = True,
|
|
53
|
+
is_remove_text_between_brackets: bool = True
|
|
54
|
+
) -> str:
|
|
55
|
+
if not isinstance(characters_to_remove, (str, tuple)):
|
|
56
|
+
characters_to_remove = [characters_to_remove]
|
|
57
|
+
|
|
58
|
+
for s in characters_to_remove:
|
|
59
|
+
input_string = input_string.replace(s, '')
|
|
60
|
+
|
|
61
|
+
if is_remove_text_between_parentheses:
|
|
62
|
+
input_string = re.sub("[(].*?[)]", "", input_string)
|
|
63
|
+
|
|
64
|
+
if is_remove_text_between_brackets:
|
|
65
|
+
input_string = re.sub("[[].*?[]]", "", input_string)
|
|
66
|
+
|
|
67
|
+
return input_string
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def calc_vector_percentage(vector: int | float | Iterable) -> list:
|
|
71
|
+
if not isinstance(vector, Iterable):
|
|
72
|
+
vector = [vector]
|
|
73
|
+
assert all([v >= 0 for v in vector]), "Negative values are not allowed when calculating a vector's percentage"
|
|
74
|
+
assert sum(vector) > 0, "At least on item must be greater than 0 when calculating a vector's percentage"
|
|
75
|
+
|
|
76
|
+
return [v / sum(vector) * 100 for v in vector]
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def print_holos_msg(
|
|
80
|
+
is_print_message: bool,
|
|
81
|
+
holos_message: str
|
|
82
|
+
) -> Callable | None:
|
|
83
|
+
return print(holos_message) if is_print_message else None
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pyholos
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: A Python package for running the HOLOS 4.0 CLI.
|
|
5
|
+
Project-URL: Homepage, https://github.com/Mon-Systeme-Fourrager/pyholos
|
|
6
|
+
Project-URL: Issues, https://github.com/Mon-Systeme-Fourrager/pyholos/issues
|
|
7
|
+
Author-email: Rami ALBASHA <ralbasha@msfourrager.com>
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Requires-Python: >=3.12
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
# Welcome to PyHolos, the Python wrapper for Holos CLI! (and beyond)
|
|
15
|
+
Description in progress
|
|
16
|
+
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
pyholos/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
pyholos/common.py,sha256=JOnsBjlxWAmzyGLkuNoTACEfuVAuCg8EqwnAcFNOQT4,4822
|
|
3
|
+
pyholos/common2.py,sha256=Dy9f1LiCfNCEbHNZ4db25W4n9VyP4HaOsAIO7TfKOAQ,7364
|
|
4
|
+
pyholos/config.py,sha256=BxtTMji7gDFq_aqhMs31MrMd5NUs7i1yScgJZI2oz9A,2521
|
|
5
|
+
pyholos/core_constants.py,sha256=NSrQ0EuZY_riybgHHLLKyvhrCbOKAYLj1sTo6H0aX_8,888
|
|
6
|
+
pyholos/defaults.py,sha256=n0qKQcKv7ey7ze4lONTSwYGfd7y3RogGEmXkyV8WHig,4842
|
|
7
|
+
pyholos/launching.py,sha256=e1Jcu7w2BDMnG5xxXQhxkqL-aqrQ5qQ6e7mw9mHmM4E,2530
|
|
8
|
+
pyholos/soil.py,sha256=JrpnqJQXmnlTes_AbV5049zX2z5ftT8vrxP--wJbc0I,20167
|
|
9
|
+
pyholos/utils.py,sha256=IPb7Sx0jw-w7r46t0MXgVqHZIiJwBbVei8gPqcoHO7s,2571
|
|
10
|
+
pyholos/components/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
|
+
pyholos/components/common.py,sha256=ZEt4GOjJGRN66chjtSPHo2R-u9wnrkpUkV17W0m7BF8,6788
|
|
12
|
+
pyholos/components/animals/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
+
pyholos/components/animals/beef.py,sha256=jxL7Hh0A_zPpUOD1yWv7O9nMMtdLab-qP4KmQmlvlng,34373
|
|
14
|
+
pyholos/components/animals/common.py,sha256=Vv0mztRCEEI39p07avhvnYIj13Z1wYFoSZw3-Pl8P1E,95832
|
|
15
|
+
pyholos/components/animals/dairy.py,sha256=NDqOGRsQTXmYYflwkdhTF8rE2AuSMA8HzXCtNrxB1zA,16846
|
|
16
|
+
pyholos/components/animals/sheep.py,sha256=G0JcPA0enXIES7RC7jqlXOy88GQExEperCjcNn1l1fQ,18689
|
|
17
|
+
pyholos/components/land_management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
18
|
+
pyholos/components/land_management/common.py,sha256=FPfrcIl-gu4RKnC90RLUOpeX85d6jI6cJ0gvQnvpm4s,7639
|
|
19
|
+
pyholos/components/land_management/crop.py,sha256=3NHDLUCwO2LRo56gBT_yHrPKR8whn0dnjtL13Swzms8,42880
|
|
20
|
+
pyholos/components/land_management/field_system.py,sha256=4BGCocdg-LrzleDA8DUx1WngNBGpF3JIJ5JFnT86dvA,24792
|
|
21
|
+
pyholos/components/land_management/utils.py,sha256=KLBIxYtI0sjLMorYDbigtc3Nu4MN6pXKxewMA7ocE0E,2654
|
|
22
|
+
pyholos/components/land_management/carbon/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
23
|
+
pyholos/components/land_management/carbon/climate.py,sha256=1qMnYYJtmoe4yv4x_XrnhDIgrylE_yzrcszOG4XXfoY,34645
|
|
24
|
+
pyholos/components/land_management/carbon/management.py,sha256=_3MfAdAqaTFjkBRvUtKd76ShsYm_U2Jc6JHDOErYSg4,771
|
|
25
|
+
pyholos/components/land_management/carbon/relative_biomass_information.py,sha256=Q9Mh_jS05eEESvvclXsDPEWePLIm9uywi6liSkQSnAk,17808
|
|
26
|
+
pyholos/components/land_management/carbon/tillage.py,sha256=ztpi9Zkze_YD0gZoqeB73M1NvlzHO9Y6fWdyub7bb1U,3110
|
|
27
|
+
pyholos/farm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
28
|
+
pyholos/farm/enums.py,sha256=DEMGOTB-VmILVCcpoNfWV1FViiJ0TeJkG36_HRiLKEY,1978
|
|
29
|
+
pyholos/farm/farm.py,sha256=XiiDtxoIEwu_uGu2f7A_qUMjYO04g6ZPt_MUf275u_4,4056
|
|
30
|
+
pyholos/farm/farm_inputs.py,sha256=Nz8F8cQBhzHMrbdfZNuNQa2Agvx_BBKE46oB6lJxHK0,26749
|
|
31
|
+
pyholos/farm/farm_settings.py,sha256=KJhz39K0zUGt269zBh_E_YXA6JXkzvoGAvQMzCE9Amc,28952
|
|
32
|
+
pyholos/postprocessing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
33
|
+
pyholos/postprocessing/plots.py,sha256=LvucTQQQCO6mjZavSRlECOA7KNtOIhNmsOLkLKoRYCE,5522
|
|
34
|
+
pyholos/postprocessing/postprocessing.py,sha256=Q7r8ceUEJymBztSdFB46YxoZ0Gyik1VwVWZGVvQ8XuE,1400
|
|
35
|
+
pyholos/resources/soil_landscapes_of_canada_v3r2.zip,sha256=I_o0MLq0_1URoQadjpkpn1c9P0tkDJgaE5sheuSS-zM,48732693
|
|
36
|
+
pyholos/resources/holos/Table_16_Livestock_Coefficients_BeefAndDairy_Cattle_Provider.csv,sha256=ettBji-ROISVa6fj_HB59bk2tX9PyZZRiU0hJkE8SVo,1039
|
|
37
|
+
pyholos/resources/holos/Table_21_Average_Milk_Production_For_Dairy_Cows_By_Province.csv,sha256=wkk4BEKJpCs42Y4yFuDR8-SohZQ8tSYzo-8_phf16jQ,1300
|
|
38
|
+
pyholos/resources/holos/Table_22_Livestock_Coefficients_For_Sheep.csv,sha256=fjEgAuEAR9FXBEx5NIUND0YeX3_CWe9LOjZbAk6_Bwk,1305
|
|
39
|
+
pyholos/resources/holos/Table_29_Percentage_Total_Manure_Produced_In_Systems.csv,sha256=JWrBXqL4DrbLDz65b0wmuzEciaPLZV-rdqwGosTHFwY,2626
|
|
40
|
+
pyholos/resources/holos/Table_30_Default_Bedding_Material_Composition_Provider.csv,sha256=1efDbdg9NO9UAkVL3-qm8WJppgrPrlyUk-G4m9iKYGI,1611
|
|
41
|
+
pyholos/resources/holos/Table_50_Fuel_Energy_Requirement_Estimates_By_Region.csv,sha256=uxUk5CVibrfbwLyRfAAKhzfkT9CYP28ISC1tdRlwTZk,17014
|
|
42
|
+
pyholos/resources/holos/Table_51_Herbicide_Energy_Requirement_Estimates_By_Region.csv,sha256=IOoMBOs5MlYocxqG9xXk_wHe5TSpgP0YEByPQZETZXI,17020
|
|
43
|
+
pyholos/resources/holos/Table_61_Fractions_of_dairy_cattle_N_volatilized.csv,sha256=lSsLcjsa6aSuEJT9Pz7uP9sQ34B72lgITaEXeEfDqAI,1501
|
|
44
|
+
pyholos/resources/holos/Table_62_Fractions_of_swine_N_volatilized.csv,sha256=V6KyvwwidfAto0v1mJWSspUxlE2TlUC3GZ_bCxA9AHo,1480
|
|
45
|
+
pyholos/resources/holos/Table_6_Manure_Types_And_Default_Composition.csv,sha256=CjWCph9KpSNXLDHIxX65GUvErDJ0YV5xBPKAxgQeGow,16191
|
|
46
|
+
pyholos/resources/holos/Table_7_Relative_Biomass_Information.csv,sha256=VDcrv38a00btq3VgAEqjqIyfjDVO7iZl97rqUu_RUik,12228
|
|
47
|
+
pyholos/resources/holos/Table_9_Default_Values_For_Nitrogen_Lignin_In_Crops.csv,sha256=2_43S_ekKqOInS72Ft68-MG9GpnP7ojCu8oYd5Agmx0,4570
|
|
48
|
+
pyholos/resources/holos/Table_Tillage_Factor.csv,sha256=zCxujdA7gdmaP-Ss7NDcNiqSVC4kK6zWK9kQfB_WGuQ,467
|
|
49
|
+
pyholos/resources/holos/feeds.csv,sha256=Wc5aqr6N8Z8grfb0M1JueIXUaEP4L4EKS_RRgOiYkLE,44396
|
|
50
|
+
pyholos/resources/holos/main_tables.py,sha256=WZMt22Q_S2EcxWAIczYc-Tje0ALy6bz-n_vTasxD7Q0,24018
|
|
51
|
+
pyholos/resources/holos/small_area_yields.csv,sha256=Cgap0kQkg8d55wzEJP5N2EziMhtnz3DfJzapXQ-8YYw,32729864
|
|
52
|
+
pyholos-0.0.1.dist-info/METADATA,sha256=PBRbZ4HTZU_4t1OiDjQuptLKaymu6Ar5g_eAH-y4umw,587
|
|
53
|
+
pyholos-0.0.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
54
|
+
pyholos-0.0.1.dist-info/licenses/LICENSE,sha256=C8amDSvgy941IWtTFploX0NSyjBHHB0biiEKEX85XM0,35976
|
|
55
|
+
pyholos-0.0.1.dist-info/RECORD,,
|