22import pathlib
33import typing
44import types
5- from datetime import datetime
5+ import datetime
66from .types import ParameterModel , ParameterBoundedModel
77
88
@@ -11,7 +11,7 @@ def _variable_origin_static_type(
1111 vars_values : dict [str , typing .Any ]
1212) -> None :
1313 '''
14- Validates input variables against their expected types.
14+ Checks that input variables match their expected origin types.
1515 '''
1616
1717 # iterate name and type of method variables
@@ -55,7 +55,7 @@ def _path_directory(
5555 path : pathlib .Path
5656) -> None :
5757 '''
58- Validates path of the direcotry .
58+ Ensures the input path refers to a valid directory .
5959 '''
6060
6161 if not path .is_dir ():
@@ -66,20 +66,40 @@ def _path_directory(
6666 return None
6767
6868
69+ def _date_begin_earlier_end (
70+ begin_date : datetime .date ,
71+ end_date : datetime .date
72+ ) -> None :
73+ '''
74+ Checks that begin date is earlier than end date.
75+ '''
76+
77+ date_fmt = '%d-%b-%Y'
78+
79+ if begin_date >= end_date :
80+ raise ValueError (
81+ f'begin_date { begin_date .strftime (date_fmt )} must be earlier than end_date { end_date .strftime (date_fmt )} '
82+ )
83+
84+
6985def _validate_date_str (
7086 date_str : str
7187) -> None :
7288 '''
7389 Validates a date string in 'YYYY-MM-DD' format.
7490 Raises ValueError if invalid.
7591 '''
92+
7693 try :
77- datetime .strptime (date_str , '%Y-%m-%d' ).date ()
94+ datetime .datetime . strptime (date_str , '%Y-%m-%d' ).date ()
7895 except ValueError :
7996 raise ValueError (f'Invalid date format: "{ date_str } ". Expected YYYY-MM-DD.' )
8097
8198
82- def _validate_units (param_change : ParameterModel , txtinout_path : pathlib .Path ) -> None :
99+ def _calibration_units (
100+ txtinout_path : pathlib .Path ,
101+ param_change : ParameterModel
102+ ) -> None :
83103 '''
84104 Validate units for a given parameter change against calibration parameters.
85105 '''
@@ -98,26 +118,19 @@ def _validate_units(param_change: ParameterModel, txtinout_path: pathlib.Path) -
98118
99119 # Get the object type for the parameter
100120 row = cal_parms_df .loc [cal_parms_df ['name' ] == name , 'obj_typ' ]
101- if row .empty :
102- raise ValueError (f"Parameter '{ name } ' not found in file 'cal_parms.cal'." )
103-
104121 obj_type = row .iloc [0 ]
105- if not obj_type :
106- raise ValueError ("Missing 'obj_typ' column in 'cal_parms.cal' file." )
107122
108- # Supported mapping of obj_type → file
123+ # Supported mapping of obj_type
109124 obj_type_files = {
110125 'hru' : 'hru-data.hru' ,
111126 'sol' : 'hru-data.hru' ,
112127 'res' : 'reservoir.res' ,
113- 'aqu' : 'aquifer.aqu' ,
128+ 'aqu' : 'aquifer.aqu'
114129 }
115-
116130 if obj_type not in obj_type_files :
117- supported = ", " .join (obj_type_files .keys ())
118131 raise ValueError (
119- f" Parameter ' { name } ' does not support units. "
120- f"Only parameters of type [ { supported } ] support units."
132+ f' Parameter " { name } " with obj_type " { obj_type } " in "cal_parms.cal" does not support " units" key. '
133+ f'Supported obj_type: [ { ', ' . join ( obj_type_files . keys ()) } ].'
121134 )
122135
123136 file = obj_type_files [obj_type ]
@@ -135,13 +148,16 @@ def _validate_units(param_change: ParameterModel, txtinout_path: pathlib.Path) -
135148 max_unit = max (units )
136149 if len (df ) < max_unit :
137150 raise ValueError (
138- f" Invalid units for parameter ' { name } '. "
139- f" Some ids exceed the maximum available in { file } "
140- f" (requested up to { max_unit } , available { len (df )} )."
151+ f' Invalid units for parameter " { name } ". '
152+ f' Some ids exceed the maximum available in { file } '
153+ f' (requested up to { max_unit } , available { len (df )} ).'
141154 )
142155
143156
144- def _validate_conditions (param_change : ParameterModel , txtinout_path : pathlib .Path ) -> None :
157+ def _calibration_conditions (
158+ txtinout_path : pathlib .Path ,
159+ param_change : ParameterModel
160+ ) -> None :
145161 '''
146162 Validate conditions for a given parameter change against calibration parameters.
147163 '''
@@ -172,59 +188,69 @@ def _validate_conditions(param_change: ParameterModel, txtinout_path: pathlib.Pa
172188 for cond_name , cond_values in conditions .items ():
173189 if cond_name not in supported_conditions :
174190 raise ValueError (
175- f" Condition ' { cond_name } ' for parameter ' { name } ' is not supported. "
176- f" Available conditions are: { ', ' .join (sorted (supported_conditions ))} ."
191+ f' Condition " { cond_name } " for parameter " { name } " is not supported. '
192+ f' Available conditions are: { ', ' .join (sorted (supported_conditions ))} .'
177193 )
178194
179195 valid_values = validators .get (cond_name , set ())
180196 for val in cond_values :
181197 if val not in valid_values :
182198 raise ValueError (
183- f"Condition '{ cond_name } ' for parameter '{ name } ' "
184- f"has invalid value '{ val } '. "
185- f"Valid values are: { sorted (valid_values )} ."
199+ f'Condition "{ cond_name } " for parameter "{ name } " has invalid value "{ val } ". '
200+ f'Expected are: { sorted (valid_values )} .'
186201 )
187202
188203
189- def _validate_conditions_and_units (parameters : list [ParameterModel ], txtinout_path : pathlib .Path ) -> None :
204+ def _calibration_conditions_and_units (
205+ txtinout_path : pathlib .Path ,
206+ parameters : list [ParameterModel ]
207+ ) -> None :
190208 '''
191209 This function checks:
192210 - That the parameter exists in the calibration parameters.
193211 - That the parameter supports units/conditions (based on 'obj_typ').
194212 - That specified units correspond to valid IDs in the relevant SWAT+ input files.
195213 - That conditions (if applicable) exist and are valid.
196214 '''
215+
197216 for param_change in parameters :
198217 try :
199- _validate_conditions (param_change , txtinout_path )
200- _validate_units (param_change , txtinout_path )
218+ _calibration_conditions (
219+ txtinout_path = txtinout_path ,
220+ param_change = param_change
221+ )
222+ _calibration_units (
223+ txtinout_path = txtinout_path ,
224+ param_change = param_change
225+ )
201226 except ValueError as e :
202227 raise ValueError (
203- f"{ e } \n \n "
204- f"If you want to ignore the validation, set "
205- f"'skip_units_and_conditions_validation=True'"
228+ f'{ e } \n \n '
229+ f'If you want to ignore the validation, set "skip_validation=True"'
206230 ) from e
207231
208232
209- def _validate_cal_parameters (
210- txtinout_folder : pathlib .Path ,
233+ def _calibration_parameters (
234+ txtinout_path : pathlib .Path ,
211235 parameters : list [ParameterBoundedModel ] | list [ParameterModel ]
212236) -> None :
213237 '''
214238 Check if parameters exists in cal_parms.cal
215239 '''
216240
217- file_path = txtinout_folder / "cal_parms.cal"
218-
219- if not file_path .exists ():
220- raise FileNotFoundError ("cal_parms.cal file does not exist in the TxtInOut folder" )
241+ # Path of cal_parms.cal
242+ file_path = txtinout_path / 'cal_parms.cal'
221243
222- cal_parms_df = pandas .read_csv (
244+ # DataFrame from cal_parms.cal file
245+ parms_df = pandas .read_csv (
223246 filepath_or_buffer = file_path ,
224247 skiprows = 2 ,
225248 sep = r'\s+'
226249 )
227250
251+ # Check validity of input calibration parameter name
228252 for param in parameters :
229- if param .name not in cal_parms_df ['name' ].values :
230- raise ValueError (f"The parameter '{ param .name } ' is not in cal_parms.cal" )
253+ if param .name not in parms_df ['name' ].values :
254+ raise ValueError (
255+ f'Calibration parameter "{ param .name } " not found in cal_parms.cal file'
256+ )
0 commit comments