2Validation for PyHelios plugin parameters.
4Provides comprehensive validation for plugin operations,
5ensuring parameters are valid before reaching C++ plugin code.
8from typing
import Any, List, Union
9from .core
import is_finite_numeric, validate_positive_value, validate_non_negative_value
10from .datatypes
import validate_vec3
11from .exceptions
import ValidationError, create_validation_error
15 param_name_min: str =
"wavelength_min",
16 param_name_max: str =
"wavelength_max",
17 function_name: str =
None):
18 """Validate wavelength range for radiation modeling."""
19 if not is_finite_numeric(wavelength_min)
or not is_finite_numeric(wavelength_max):
20 raise create_validation_error(
21 f
"Wavelength bounds must be finite numbers, got min={wavelength_min}, max={wavelength_max}",
22 param_name=f
"{param_name_min}, {param_name_max}",
23 function_name=function_name,
24 expected_type=
"finite numbers",
25 actual_value=f
"min={wavelength_min}, max={wavelength_max}",
26 suggestion=
"Use finite numeric values for wavelength bounds."
29 if wavelength_min <= 0
or wavelength_max <= 0:
30 raise create_validation_error(
31 f
"Wavelength values must be positive, got min={wavelength_min}, max={wavelength_max}",
32 param_name=f
"{param_name_min}, {param_name_max}",
33 function_name=function_name,
34 expected_type=
"positive numbers",
35 actual_value=f
"min={wavelength_min}, max={wavelength_max}",
36 suggestion=
"Wavelengths must be greater than 0."
39 if wavelength_min >= wavelength_max:
40 raise create_validation_error(
41 f
"Wavelength minimum ({wavelength_min}) must be less than maximum ({wavelength_max})",
42 param_name=f
"{param_name_min}, {param_name_max}",
43 function_name=function_name,
44 expected_type=
"min < max",
45 actual_value=(wavelength_min, wavelength_max),
46 suggestion=
"Ensure wavelength_min < wavelength_max."
50 if wavelength_min < 100
or wavelength_max > 100000:
51 raise create_validation_error(
52 f
"Wavelength range [{wavelength_min}, {wavelength_max}] nm seems unrealistic",
53 param_name=f
"{param_name_min}, {param_name_max}",
54 function_name=function_name,
55 expected_type=
"wavelengths in range 100-100000 nm",
56 actual_value=f
"min={wavelength_min}, max={wavelength_max}",
57 suggestion=
"Typical wavelength range is 100-100000 nm (UV to far-IR). "
58 "Provide wavelength values in nanometers (e.g., PAR: 400-700 nm)."
63 """Validate radiation flux value."""
64 if not is_finite_numeric(flux):
65 raise create_validation_error(
66 f
"Parameter must be a finite number, got {flux} ({type(flux).__name__})",
67 param_name=param_name,
68 function_name=function_name,
69 expected_type=
"finite number",
71 suggestion=
"Flux values must be finite numbers (not NaN or infinity)."
75 raise create_validation_error(
76 f
"Parameter must be non-negative, got {flux}",
77 param_name=param_name,
78 function_name=function_name,
79 expected_type=
"non-negative number",
81 suggestion=
"Flux values cannot be negative."
85def validate_ray_count(count: int, param_name: str =
"ray_count", function_name: str =
None):
86 """Validate ray count for radiation simulations."""
87 if not isinstance(count, int):
88 raise create_validation_error(
89 f
"Parameter must be an integer, got {type(count).__name__}",
90 param_name=param_name,
91 function_name=function_name,
92 expected_type=
"integer",
94 suggestion=
"Ray count must be a positive integer."
98 raise create_validation_error(
99 f
"Parameter must be positive, got {count}",
100 param_name=param_name,
101 function_name=function_name,
102 expected_type=
"positive integer",
104 suggestion=
"Ray count must be greater than 0."
107 if count > 10_000_000:
108 raise create_validation_error(
109 f
"Parameter {count:,} is very large and may cause memory issues",
110 param_name=param_name,
111 function_name=function_name,
112 expected_type=
"integer <= 10,000,000",
114 suggestion=
"Consider using fewer rays (< 10,000,000) for practical simulations."
119 """Validate direction vector for radiation sources."""
120 validate_vec3(direction, param_name, function_name)
123 if hasattr(direction,
'x')
and hasattr(direction,
'y')
and hasattr(direction,
'z'):
124 magnitude_squared = direction.x**2 + direction.y**2 + direction.z**2
125 if magnitude_squared == 0:
126 raise create_validation_error(
127 f
"Direction vector cannot be zero vector (0,0,0)",
128 param_name=param_name,
129 function_name=function_name,
130 expected_type=
"non-zero vec3",
131 actual_value=direction,
132 suggestion=
"Provide a direction vector with non-zero magnitude."
136def validate_band_label(label: str, param_name: str =
"band_label", function_name: str =
None):
137 """Validate radiation band label."""
138 if not isinstance(label, str):
139 raise create_validation_error(
140 f
"Parameter must be a string, got {type(label).__name__}",
141 param_name=param_name,
142 function_name=function_name,
143 expected_type=
"string",
145 suggestion=
"Band labels must be strings."
148 if not label.strip():
149 raise create_validation_error(
150 f
"Parameter cannot be empty or whitespace-only",
151 param_name=param_name,
152 function_name=function_name,
153 expected_type=
"non-empty string",
154 actual_value=repr(label),
155 suggestion=
"Provide a non-empty band label."
159def validate_source_id(source_id: int, param_name: str =
"source_id", function_name: str =
None):
160 """Validate radiation source ID."""
161 if not isinstance(source_id, int):
162 raise create_validation_error(
163 f
"Parameter must be an integer, got {type(source_id).__name__}",
164 param_name=param_name,
165 function_name=function_name,
166 expected_type=
"integer",
167 actual_value=source_id,
168 suggestion=
"Source IDs are integers returned by add*RadiationSource methods."
172 raise create_validation_error(
173 f
"Parameter must be non-negative, got {source_id}",
174 param_name=param_name,
175 function_name=function_name,
176 expected_type=
"non-negative integer",
177 actual_value=source_id,
178 suggestion=
"Source IDs are non-negative integers."
183 """Validate list of radiation source IDs."""
184 if not isinstance(source_ids, list):
185 raise create_validation_error(
186 f
"Parameter must be a list, got {type(source_ids).__name__}",
187 param_name=param_name,
188 function_name=function_name,
189 expected_type=
"list of integers",
190 actual_value=source_ids,
191 suggestion=
"Provide a list of source IDs."
195 raise create_validation_error(
196 f
"Parameter cannot be empty",
197 param_name=param_name,
198 function_name=function_name,
199 expected_type=
"non-empty list",
200 actual_value=source_ids,
201 suggestion=
"Provide at least one source ID."
204 for i, source_id
in enumerate(source_ids):
209 segment_resolution: int = 10, param_prefix: str =
"WPT"):
210 """Validate WeberPennTree generation parameters."""
211 if not is_finite_numeric(scale_factor):
212 raise create_validation_error(
213 f
"Scale factor must be a finite number, got {scale_factor} ({type(scale_factor).__name__})",
214 param_name=f
"{param_prefix}_scale_factor",
215 expected_type=
"finite number",
216 actual_value=scale_factor,
217 suggestion=
"Scale factor must be a finite number."
220 if scale_factor <= 0:
221 raise create_validation_error(
222 f
"Scale factor must be positive, got {scale_factor}",
223 param_name=f
"{param_prefix}_scale_factor",
224 expected_type=
"positive number",
225 actual_value=scale_factor,
226 suggestion=
"Scale factor must be greater than 0."
229 if scale_factor > 100:
230 raise create_validation_error(
231 f
"Scale factor {scale_factor} is very large and may cause issues",
232 param_name=f
"{param_prefix}_scale_factor",
233 expected_type=
"reasonable scale factor (0.1-10)",
234 actual_value=scale_factor,
235 suggestion=
"Typical scale factors are 0.1-10. Large values may cause performance issues."
238 if not isinstance(recursion_level, int):
239 raise create_validation_error(
240 f
"Recursion level must be an integer, got {type(recursion_level).__name__}",
241 param_name=f
"{param_prefix}_recursion_level",
242 expected_type=
"integer",
243 actual_value=recursion_level,
244 suggestion=
"Recursion level must be an integer."
247 if recursion_level < 1
or recursion_level > 10:
248 raise create_validation_error(
249 f
"Recursion level must be between 1-10, got {recursion_level}",
250 param_name=f
"{param_prefix}_recursion_level",
251 expected_type=
"integer in range 1-10",
252 actual_value=recursion_level,
253 suggestion=
"Use recursion level between 1-10 for realistic tree generation."
256 if not isinstance(segment_resolution, int):
257 raise create_validation_error(
258 f
"Segment resolution must be an integer, got {type(segment_resolution).__name__}",
259 param_name=f
"{param_prefix}_segment_resolution",
260 expected_type=
"integer",
261 actual_value=segment_resolution,
262 suggestion=
"Segment resolution must be an integer."
265 if segment_resolution < 3
or segment_resolution > 50:
266 raise create_validation_error(
267 f
"Segment resolution must be between 3-50, got {segment_resolution}",
268 param_name=f
"{param_prefix}_segment_resolution",
269 expected_type=
"integer in range 3-50",
270 actual_value=segment_resolution,
271 suggestion=
"Use segment resolution between 3-50 for good performance and quality."
275def validate_time_value(time_val: Any, param_name: str =
"time", function_name: str =
None):
276 """Validate time values for energy balance calculations."""
277 if not is_finite_numeric(time_val):
278 raise create_validation_error(
279 f
"Parameter must be a finite number, got {time_val} ({type(time_val).__name__})",
280 param_name=param_name,
281 function_name=function_name,
282 expected_type=
"finite number",
283 actual_value=time_val,
284 suggestion=
"Time values must be finite numbers (not NaN or infinity)."
288 raise create_validation_error(
289 f
"Parameter cannot be negative, got {time_val}",
290 param_name=param_name,
291 function_name=function_name,
292 expected_type=
"non-negative number",
293 actual_value=time_val,
294 suggestion=
"Time values must be >= 0."
299 expected_units: str =
None, min_val: float =
None,
300 max_val: float =
None, param_name: str =
None,
301 function_name: str =
None):
302 """Validate physical quantity values with optional range checking."""
303 param_name = param_name
or quantity_name.lower().replace(
' ',
'_')
305 if not is_finite_numeric(value):
306 units_info = f
" ({expected_units})" if expected_units
else ""
307 raise create_validation_error(
308 f
"{quantity_name}{units_info} must be a finite number, got {value} ({type(value).__name__})",
309 param_name=param_name,
310 function_name=function_name,
311 expected_type=
"finite number",
313 suggestion=f
"Provide a finite numeric value for {quantity_name}."
316 if min_val
is not None and value < min_val:
317 units_info = f
" {expected_units}" if expected_units
else ""
318 raise create_validation_error(
319 f
"{quantity_name} must be >= {min_val}{units_info}, got {value}",
320 param_name=param_name,
321 function_name=function_name,
322 expected_type=f
"number >= {min_val}",
324 suggestion=f
"Use a value >= {min_val} for {quantity_name}."
327 if max_val
is not None and value > max_val:
328 units_info = f
" {expected_units}" if expected_units
else ""
329 raise create_validation_error(
330 f
"{quantity_name} must be <= {max_val}{units_info}, got {value}",
331 param_name=param_name,
332 function_name=function_name,
333 expected_type=f
"number <= {max_val}",
335 suggestion=f
"Use a value <= {max_val} for {quantity_name}."
339def validate_tree_id(tree_id: Any, param_name: str =
"tree_id", function_name: str =
None):
340 """Validate WeberPennTree tree ID."""
341 if not isinstance(tree_id, int):
342 raise create_validation_error(
343 f
"Parameter must be an integer, got {type(tree_id).__name__}",
344 param_name=param_name,
345 function_name=function_name,
346 expected_type=
"integer",
347 actual_value=tree_id,
348 suggestion=
"Tree IDs are integers returned by buildTree()."
352 raise create_validation_error(
353 f
"Parameter must be non-negative, got {tree_id}",
354 param_name=param_name,
355 function_name=function_name,
356 expected_type=
"non-negative integer",
357 actual_value=tree_id,
358 suggestion=
"Tree IDs are non-negative integers."
363 param_name: str =
"resolution", function_name: str =
None):
364 """Validate segment resolution parameters for tree generation."""
365 if not isinstance(resolution, int):
366 raise create_validation_error(
367 f
"Parameter must be an integer, got {type(resolution).__name__}",
368 param_name=param_name,
369 function_name=function_name,
370 expected_type=
"integer",
371 actual_value=resolution,
372 suggestion=
"Segment resolution must be an integer."
375 if resolution < min_val
or resolution > max_val:
376 raise create_validation_error(
377 f
"Parameter must be between {min_val}-{max_val}, got {resolution}",
378 param_name=param_name,
379 function_name=function_name,
380 expected_type=f
"integer in range {min_val}-{max_val}",
381 actual_value=resolution,
382 suggestion=f
"Use resolution between {min_val}-{max_val} for good performance and quality."
387 """Validate angle values in degrees."""
388 if not is_finite_numeric(angle):
389 raise create_validation_error(
390 f
"Parameter must be a finite number, got {angle} ({type(angle).__name__})",
391 param_name=param_name,
392 function_name=function_name,
393 expected_type=
"finite number",
395 suggestion=
"Angle values must be finite numbers (not NaN or infinity)."
403 param_name: str =
"scaling_factor", function_name: str =
None):
404 """Validate scaling factor parameters."""
405 if not is_finite_numeric(scale):
406 raise create_validation_error(
407 f
"Parameter must be a finite number, got {scale} ({type(scale).__name__})",
408 param_name=param_name,
409 function_name=function_name,
410 expected_type=
"finite number",
412 suggestion=
"Scaling factors must be finite numbers."
416 raise create_validation_error(
417 f
"Parameter must be positive, got {scale}",
418 param_name=param_name,
419 function_name=function_name,
420 expected_type=
"positive number",
422 suggestion=
"Scaling factors must be greater than 0."
425 if scale < min_val
or scale > max_val:
426 raise create_validation_error(
427 f
"Parameter {scale} is outside reasonable range [{min_val}, {max_val}]",
428 param_name=param_name,
429 function_name=function_name,
430 expected_type=f
"number in range [{min_val}, {max_val}]",
432 suggestion=f
"Use scaling factors between {min_val} and {max_val} to avoid numerical issues."
436def validate_filename(filename: Any, param_name: str =
"filename", function_name: str =
None,
437 allowed_extensions: List[str] =
None):
438 """Validate filename parameters for file operations."""
439 if not isinstance(filename, str):
440 raise create_validation_error(
441 f
"Parameter must be a string, got {type(filename).__name__}",
442 param_name=param_name,
443 function_name=function_name,
444 expected_type=
"string",
445 actual_value=filename,
446 suggestion=
"Filename must be a string."
449 if not filename.strip():
450 raise create_validation_error(
451 f
"Parameter cannot be empty or whitespace-only",
452 param_name=param_name,
453 function_name=function_name,
454 expected_type=
"non-empty string",
455 actual_value=repr(filename),
456 suggestion=
"Provide a non-empty filename."
465 if '\\' in filename
or (len(filename) >= 2
and filename[1] ==
':'):
466 basename = ntpath.basename(filename)
468 basename = os.path.basename(filename)
471 invalid_chars = [
'<',
'>',
'"',
'|',
'?',
'*']
474 invalid_chars.append(
':')
475 if any(char
in basename
for char
in invalid_chars):
476 raise create_validation_error(
477 f
"Filename contains invalid characters: {basename}",
478 param_name=param_name,
479 function_name=function_name,
480 expected_type=
"valid filename",
481 actual_value=filename,
482 suggestion=
"Avoid characters: < > : \" | ? * in filename"
486 if allowed_extensions:
487 ext = os.path.splitext(filename)[1].lower()
488 if ext
not in allowed_extensions:
489 raise create_validation_error(
490 f
"File extension '{ext}' not allowed. Must be one of: {', '.join(allowed_extensions)}",
491 param_name=param_name,
492 function_name=function_name,
493 expected_type=f
"filename with extension {allowed_extensions}",
494 actual_value=filename,
495 suggestion=f
"Use a filename ending with one of: {', '.join(allowed_extensions)}"
499def validate_uuid_list(uuids: Any, param_name: str =
"uuids", function_name: str =
None,
500 allow_empty: bool =
False):
501 """Validate UUID list parameters."""
502 if not isinstance(uuids, list):
503 raise create_validation_error(
504 f
"Parameter must be a list, got {type(uuids).__name__}",
505 param_name=param_name,
506 function_name=function_name,
507 expected_type=
"list of integers",
509 suggestion=
"Provide a list of UUID integers."
512 if not allow_empty
and not uuids:
513 raise create_validation_error(
514 f
"Parameter cannot be empty",
515 param_name=param_name,
516 function_name=function_name,
517 expected_type=
"non-empty list",
519 suggestion=
"Provide at least one UUID."
522 for i, uuid
in enumerate(uuids):
523 if not isinstance(uuid, int):
524 raise create_validation_error(
525 f
"UUID at index {i} must be an integer, got {type(uuid).__name__}",
526 param_name=f
"{param_name}[{i}]",
527 function_name=function_name,
528 expected_type=
"integer",
530 suggestion=
"UUIDs are integers returned by geometry creation methods."
534 raise create_validation_error(
535 f
"UUID at index {i} must be non-negative, got {uuid}",
536 param_name=f
"{param_name}[{i}]",
537 function_name=function_name,
538 expected_type=
"non-negative integer",
540 suggestion=
"UUIDs are non-negative integers."
545 param_name: str =
"value", function_name: str =
None):
546 """Validate positive integer within a specified range."""
547 if not isinstance(value, int):
548 raise create_validation_error(
549 f
"Parameter must be an integer, got {type(value).__name__}",
550 param_name=param_name,
551 function_name=function_name,
552 expected_type=
"integer",
554 suggestion=
"Provide an integer value."
557 if value < min_val
or value > max_val:
558 raise create_validation_error(
559 f
"Parameter must be between {min_val}-{max_val}, got {value}",
560 param_name=param_name,
561 function_name=function_name,
562 expected_type=f
"integer in range {min_val}-{max_val}",
564 suggestion=f
"Use a value between {min_val} and {max_val}."
569 """Validate recursion level for tree generation."""
574 """Validate subdivision count parameters."""
583 """Validate species name for photosynthesis library."""
584 from ..types.photosynthesis
import validate_species_name
as _validate_species
586 if not isinstance(species, str):
587 raise create_validation_error(
588 f
"Parameter must be a string, got {type(species).__name__}",
589 param_name=param_name,
590 function_name=function_name,
591 expected_type=
"string",
592 actual_value=species,
593 suggestion=
"Species names must be strings."
597 return _validate_species(species)
598 except ValueError
as e:
599 raise create_validation_error(
601 param_name=param_name,
602 function_name=function_name,
603 expected_type=
"valid species name",
604 actual_value=species,
605 suggestion=
"Use one of the available species or aliases. See get_available_species()."
609def validate_temperature(temperature: Any, param_name: str =
"temperature", function_name: str =
None):
610 """Validate temperature values for photosynthesis calculations."""
613 quantity_name=
"Temperature",
617 param_name=param_name,
618 function_name=function_name
623 """Validate CO2 concentration values for photosynthesis calculations."""
626 quantity_name=
"CO2 concentration",
627 expected_units=
"ppm",
630 param_name=param_name,
631 function_name=function_name
636 """Validate photosynthetic rate values."""
639 quantity_name=
"Photosynthetic rate",
640 expected_units=
"μmol/m²/s",
643 param_name=param_name,
644 function_name=function_name
648def validate_conductance(conductance: Any, param_name: str =
"conductance", function_name: str =
None):
649 """Validate conductance values for photosynthesis calculations."""
652 quantity_name=
"Conductance",
653 expected_units=
"mol/m²/s",
656 param_name=param_name,
657 function_name=function_name
661def validate_par_flux(par_flux: Any, param_name: str =
"PAR_flux", function_name: str =
None):
662 """Validate PAR flux values for photosynthesis calculations."""
665 quantity_name=
"PAR flux",
666 expected_units=
"μmol/m²/s",
669 param_name=param_name,
670 function_name=function_name
675 """Validate empirical model coefficients array or dataclass."""
677 if hasattr(coefficients,
'to_array')
and callable(getattr(coefficients,
'to_array')):
680 if not isinstance(coefficients, (list, tuple)):
681 raise create_validation_error(
682 f
"Parameter must be a list or tuple, got {type(coefficients).__name__}",
683 param_name=param_name,
684 function_name=function_name,
685 expected_type=
"list or tuple of numbers",
686 actual_value=coefficients,
687 suggestion=
"Provide coefficients as a list or tuple of numbers."
690 if len(coefficients) < 10:
691 raise create_validation_error(
692 f
"Empirical model coefficients need at least 10 elements, got {len(coefficients)}",
693 param_name=param_name,
694 function_name=function_name,
695 expected_type=
"list with >= 10 elements",
696 actual_value=f
"length {len(coefficients)}",
697 suggestion=
"Provide all 10 empirical model coefficients: [Tref, Ci_ref, Asat, theta, Tmin, Topt, q, R, ER, kC]."
700 for i, coeff
in enumerate(coefficients[:10]):
701 if not is_finite_numeric(coeff):
702 raise create_validation_error(
703 f
"Coefficient at index {i} must be a finite number, got {coeff} ({type(coeff).__name__})",
704 param_name=f
"{param_name}[{i}]",
705 function_name=function_name,
706 expected_type=
"finite number",
708 suggestion=
"All coefficients must be finite numbers (not NaN or infinity)."
713 """Validate Farquhar model coefficients array or dataclass."""
715 if hasattr(coefficients,
'to_array')
and callable(getattr(coefficients,
'to_array')):
718 if not isinstance(coefficients, (list, tuple)):
719 raise create_validation_error(
720 f
"Parameter must be a list or tuple, got {type(coefficients).__name__}",
721 param_name=param_name,
722 function_name=function_name,
723 expected_type=
"list or tuple of numbers",
724 actual_value=coefficients,
725 suggestion=
"Provide coefficients as a list or tuple of numbers."
728 if len(coefficients) < 18:
729 raise create_validation_error(
730 f
"Farquhar model coefficients need at least 18 elements, got {len(coefficients)}",
731 param_name=param_name,
732 function_name=function_name,
733 expected_type=
"list with >= 18 elements",
734 actual_value=f
"length {len(coefficients)}",
735 suggestion=
"Provide all 18 Farquhar model coefficients including temperature response parameters."
738 for i, coeff
in enumerate(coefficients[:18]):
739 if not is_finite_numeric(coeff):
740 raise create_validation_error(
741 f
"Coefficient at index {i} must be a finite number, got {coeff} ({type(coeff).__name__})",
742 param_name=f
"{param_name}[{i}]",
743 function_name=function_name,
744 expected_type=
"finite number",
746 suggestion=
"All coefficients must be finite numbers (not NaN or infinity)."
750def validate_vcmax(vcmax: Any, param_name: str =
"Vcmax", function_name: str =
None):
751 """Validate maximum carboxylation rate (Vcmax) parameter."""
758 quantity_name=
"Maximum carboxylation rate (Vcmax)",
759 expected_units=
"μmol/m²/s",
762 param_name=param_name,
763 function_name=function_name
767def validate_jmax(jmax: Any, param_name: str =
"Jmax", function_name: str =
None):
768 """Validate maximum electron transport rate (Jmax) parameter."""
775 quantity_name=
"Maximum electron transport rate (Jmax)",
776 expected_units=
"μmol/m²/s",
779 param_name=param_name,
780 function_name=function_name
785 """Validate quantum efficiency (alpha) parameter."""
792 quantity_name=
"Quantum efficiency (alpha)",
793 expected_units=
"unitless",
796 param_name=param_name,
797 function_name=function_name
802 """Validate dark respiration rate (Rd) parameter."""
809 quantity_name=
"Dark respiration rate (Rd)",
810 expected_units=
"μmol/m²/s",
813 param_name=param_name,
814 function_name=function_name
819 """Validate oxygen concentration for photosynthesis calculations."""
822 quantity_name=
"Oxygen concentration",
823 expected_units=
"mmol/mol",
826 param_name=param_name,
827 function_name=function_name
832 param_prefix: str =
"", function_name: str =
None):
833 """Validate temperature response parameters for photosynthetic processes."""
837 quantity_name=f
"{param_prefix} value at 25°C",
839 param_name=f
"{param_prefix}_at_25C",
840 function_name=function_name
844 if dha
is not None and dha >= 0:
847 quantity_name=f
"{param_prefix} activation energy (dHa)",
848 expected_units=
"kJ/mol",
851 param_name=f
"{param_prefix}_dHa",
852 function_name=function_name
855 if topt
is not None and topt >= 0:
858 quantity_name=f
"{param_prefix} optimum temperature",
862 param_name=f
"{param_prefix}_Topt",
863 function_name=function_name
866 if dhd
is not None and dhd >= 0:
869 quantity_name=f
"{param_prefix} deactivation energy (dHd)",
870 expected_units=
"kJ/mol",
873 param_name=f
"{param_prefix}_dHd",
874 function_name=function_name
878def validate_camera_label(label: str, param_name: str =
"camera_label", function_name: str =
None) -> str:
879 """Validate camera label for radiation camera operations."""
880 if not isinstance(label, str):
881 raise create_validation_error(
882 f
"Camera label must be a string, got {type(label).__name__}",
883 param_name=param_name,
884 function_name=function_name,
887 suggestion=
"Use a string label for the camera."
890 if not label
or label.strip() ==
"":
891 raise create_validation_error(
892 "Camera label cannot be empty",
893 param_name=param_name,
894 function_name=function_name,
895 expected_type=
"non-empty string",
897 suggestion=
"Provide a non-empty string label for the camera."
903def validate_band_labels_list(band_labels: List[str], param_name: str =
"band_labels", function_name: str =
None) -> List[str]:
904 """Validate list of band labels for camera operations."""
905 if not isinstance(band_labels, (list, tuple)):
906 raise create_validation_error(
907 f
"Band labels must be a list or tuple, got {type(band_labels).__name__}",
908 param_name=param_name,
909 function_name=function_name,
910 expected_type=
"List[str]",
911 actual_value=band_labels,
912 suggestion=
"Provide a list of string band labels."
915 if len(band_labels) == 0:
916 raise create_validation_error(
917 "Band labels list cannot be empty",
918 param_name=param_name,
919 function_name=function_name,
920 expected_type=
"non-empty list",
921 actual_value=band_labels,
922 suggestion=
"Provide at least one band label."
925 validated_labels = []
926 for i, label
in enumerate(band_labels):
927 if not isinstance(label, str):
928 raise create_validation_error(
929 f
"Band label at index {i} must be a string, got {type(label).__name__}",
930 param_name=f
"{param_name}[{i}]",
931 function_name=function_name,
934 suggestion=
"All band labels must be strings."
937 if not label
or label.strip() ==
"":
938 raise create_validation_error(
939 f
"Band label at index {i} cannot be empty",
940 param_name=f
"{param_name}[{i}]",
941 function_name=function_name,
942 expected_type=
"non-empty string",
944 suggestion=
"All band labels must be non-empty strings."
947 validated_labels.append(label.strip())
949 return validated_labels
953 """Validate antialiasing samples count."""
954 if not isinstance(samples, int):
955 raise create_validation_error(
956 f
"Antialiasing samples must be an integer, got {type(samples).__name__}",
957 param_name=param_name,
958 function_name=function_name,
960 actual_value=samples,
961 suggestion=
"Provide an integer number of antialiasing samples."
965 raise create_validation_error(
966 f
"Antialiasing samples must be positive, got {samples}",
967 param_name=param_name,
968 function_name=function_name,
969 expected_type=
"positive integer",
970 actual_value=samples,
971 suggestion=
"Use a positive number of antialiasing samples (typically 1-1000)."
976 raise create_validation_error(
977 f
"Antialiasing samples ({samples}) is very high and may cause performance issues",
978 param_name=param_name,
979 function_name=function_name,
980 expected_type=
"reasonable integer (1-10000)",
981 actual_value=samples,
982 suggestion=
"Consider using fewer antialiasing samples for better performance."
validate_recursion_level(Any level, str param_name="recursion_level", str function_name=None)
Validate recursion level for tree generation.
validate_temperature_response_params(Any value_at_25c, Any dha=None, Any topt=None, Any dhd=None, str param_prefix="", str function_name=None)
Validate temperature response parameters for photosynthetic processes.
validate_empirical_coefficients(Any coefficients, str param_name="coefficients", str function_name=None)
Validate empirical model coefficients array or dataclass.
validate_source_id_list(List[int] source_ids, str param_name="source_ids", str function_name=None)
Validate list of radiation source IDs.
validate_positive_integer_range(Any value, int min_val=1, int max_val=50, str param_name="value", str function_name=None)
Validate positive integer within a specified range.
validate_direction_vector(Any direction, str param_name="direction", str function_name=None)
Validate direction vector for radiation sources.
str validate_camera_label(str label, str param_name="camera_label", str function_name=None)
Validate camera label for radiation camera operations.
validate_filename(Any filename, str param_name="filename", str function_name=None, List[str] allowed_extensions=None)
Validate filename parameters for file operations.
validate_uuid_list(Any uuids, str param_name="uuids", str function_name=None, bool allow_empty=False)
Validate UUID list parameters.
validate_subdivision_count(Any count, str param_name="subdivision_count", str function_name=None)
Validate subdivision count parameters.
validate_wpt_parameters(float scale_factor=1.0, int recursion_level=5, int segment_resolution=10, str param_prefix="WPT")
Validate WeberPennTree generation parameters.
validate_conductance(Any conductance, str param_name="conductance", str function_name=None)
Validate conductance values for photosynthesis calculations.
validate_quantum_efficiency(Any alpha, str param_name="alpha", str function_name=None)
Validate quantum efficiency (alpha) parameter.
validate_flux_value(float flux, str param_name="flux", str function_name=None)
Validate radiation flux value.
validate_farquhar_coefficients(Any coefficients, str param_name="coefficients", str function_name=None)
Validate Farquhar model coefficients array or dataclass.
validate_segment_resolution(Any resolution, int min_val=3, int max_val=100, str param_name="resolution", str function_name=None)
Validate segment resolution parameters for tree generation.
validate_jmax(Any jmax, str param_name="Jmax", str function_name=None)
Validate maximum electron transport rate (Jmax) parameter.
validate_scaling_factor(Any scale, float min_val=0.001, float max_val=1000.0, str param_name="scaling_factor", str function_name=None)
Validate scaling factor parameters.
List[str] validate_band_labels_list(List[str] band_labels, str param_name="band_labels", str function_name=None)
Validate list of band labels for camera operations.
validate_tree_id(Any tree_id, str param_name="tree_id", str function_name=None)
Validate WeberPennTree tree ID.
validate_species_name(Any species, str param_name="species", str function_name=None)
Validate species name for photosynthesis library.
validate_band_label(str label, str param_name="band_label", str function_name=None)
Validate radiation band label.
validate_time_value(Any time_val, str param_name="time", str function_name=None)
Validate time values for energy balance calculations.
validate_temperature(Any temperature, str param_name="temperature", str function_name=None)
Validate temperature values for photosynthesis calculations.
validate_wavelength_range(float wavelength_min, float wavelength_max, str param_name_min="wavelength_min", str param_name_max="wavelength_max", str function_name=None)
Validate wavelength range for radiation modeling.
validate_physical_quantity(Any value, str quantity_name, str expected_units=None, float min_val=None, float max_val=None, str param_name=None, str function_name=None)
Validate physical quantity values with optional range checking.
validate_co2_concentration(Any co2, str param_name="co2_concentration", str function_name=None)
Validate CO2 concentration values for photosynthesis calculations.
validate_dark_respiration(Any rd, str param_name="Rd", str function_name=None)
Validate dark respiration rate (Rd) parameter.
validate_par_flux(Any par_flux, str param_name="PAR_flux", str function_name=None)
Validate PAR flux values for photosynthesis calculations.
validate_ray_count(int count, str param_name="ray_count", str function_name=None)
Validate ray count for radiation simulations.
validate_photosynthetic_rate(Any rate, str param_name="photosynthetic_rate", str function_name=None)
Validate photosynthetic rate values.
int validate_antialiasing_samples(int samples, str param_name="antialiasing_samples", str function_name=None)
Validate antialiasing samples count.
validate_oxygen_concentration(Any o2, str param_name="oxygen", str function_name=None)
Validate oxygen concentration for photosynthesis calculations.
validate_angle_degrees(Any angle, str param_name="angle", str function_name=None)
Validate angle values in degrees.
validate_vcmax(Any vcmax, str param_name="Vcmax", str function_name=None)
Validate maximum carboxylation rate (Vcmax) parameter.
validate_source_id(int source_id, str param_name="source_id", str function_name=None)
Validate radiation source ID.