0.1.22
Loading...
Searching...
No Matches
PhotosynthesisModel.py
Go to the documentation of this file.
1"""
2PhotosynthesisModel Plugin for PyHelios.
3
4This module provides a high-level interface to the Helios photosynthesis modeling
5plugin, enabling simulation of plant photosynthesis processes using both empirical
6and mechanistic models.
7"""
8
9from typing import List, Optional, Union
10from .Context import Context
11from .wrappers import UPhotosynthesisWrapper as photosynthesis_wrapper
12from .types.photosynthesis import (
13 PhotosyntheticTemperatureResponseParameters,
14 EmpiricalModelCoefficients,
15 FarquharModelCoefficients,
16 PHOTOSYNTHESIS_SPECIES,
17 validate_species_name,
18 get_available_species,
19 get_species_aliases
20)
21from .validation.plugin_decorators import (
22 validate_photosynthesis_species_params,
23 validate_empirical_model_params,
24 validate_farquhar_model_params,
25 validate_photosynthesis_uuid_params
26)
27
28
29class PhotosynthesisModelError(Exception):
30 """Exception raised by PhotosynthesisModel operations."""
31 pass
32
33
34#: Species available in the helios-core C4 photosynthesis library (von Caemmerer 2021).
35#: Lookups via :meth:`PhotosynthesisModel.setC4CoefficientsFromLibrary` are case-insensitive
36#: but otherwise exact — unknown species raise ``helios_runtime_error`` from the C++ side.
37AVAILABLE_C4_SPECIES = [
38 "SetariaViridis_vC2021",
39 "GenericC4_vC2000",
40 "Maize_Massad2007",
41]
42
43
45 """
46 High-level interface for Helios photosynthesis modeling.
47
48 The PhotosynthesisModel provides methods for configuring and running
49 photosynthesis simulations using various models including empirical
50 and mechanistic (Farquhar-von Caemmerer-Berry) approaches.
51
52 Features:
53 - Support for empirical and FvCB photosynthesis models
54 - Built-in species library with 21+ plant species
55 - Comprehensive parameter validation
56 - Context manager support for proper cleanup
57
58 Example:
59 >>> from pyhelios import Context, PhotosynthesisModel
60 >>> from pyhelios.types import EmpiricalModelCoefficients
61 >>> context = Context()
62 >>> with PhotosynthesisModel(context) as photosynthesis:
63 ... # Configure empirical model
64 ... coeffs = EmpiricalModelCoefficients(
65 ... Tref=298.0, # Reference temperature (K)
66 ... Ci_ref=290.0, # Reference CO2 concentration (μmol/mol)
67 ... Asat=20.0, # Light-saturated photosynthesis rate (μmol/m²/s)
68 ... theta=65.0 # Light response curvature (W/m²)
69 ... )
70 ... photosynthesis.setEmpiricalModelCoefficients(coeffs)
71 ... photosynthesis.run()
72
73 Available species can be queried using:
74 >>> PhotosynthesisModel.get_available_species()
75 ['ALMOND', 'APPLE', 'AVOCADO', ...]
76 """
77
78 def __init__(self, context: Context):
79 """
80 Initialize PhotosynthesisModel.
81
82 Args:
83 context: PyHelios Context instance containing the 3D geometry
84
85 Raises:
86 PhotosynthesisModelError: If plugin is not available or initialization fails
87 """
88 if not isinstance(context, Context):
90 f"Context parameter must be a Context instance, got {type(context).__name__}"
91 )
92
93 self.context = context
94 self._native_ptr = None
95
96 try:
97 # Get the native context pointer
98 context_ptr = self.context.getNativePtr()
99 if context_ptr is None:
100 raise PhotosynthesisModelError("Context has no native pointer - context may not be properly initialized")
101
102 # Create the photosynthesis model
103 self._native_ptr = photosynthesis_wrapper.createPhotosynthesisModel(context_ptr)
104 if self._native_ptr is None:
105 raise PhotosynthesisModelError("Failed to create photosynthesis model")
106
107 except Exception as e:
108 if "photosynthesis plugin is not available" in str(e).lower():
110 "Photosynthesis plugin is not available. "
111 "Please rebuild PyHelios with photosynthesis plugin enabled:\n"
112 " build_scripts/build_helios --plugins photosynthesis"
113 ) from e
114 elif "mock mode" in str(e).lower():
116 "PhotosynthesisModel requires native Helios libraries. "
117 "Currently running in mock mode. Please build native libraries:\n"
118 " build_scripts/build_helios --plugins photosynthesis"
119 ) from e
120 else:
121 raise PhotosynthesisModelError(f"Failed to initialize PhotosynthesisModel: {e}") from e
122
123 def __enter__(self):
124 """Context manager entry."""
125 return self
126
127 def __exit__(self, exc_type, exc_value, traceback):
128 """Context manager exit with cleanup."""
129 self.cleanup()
130
131 def cleanup(self):
132 """Clean up native resources."""
133 if hasattr(self, '_native_ptr') and self._native_ptr is not None:
134 try:
135 photosynthesis_wrapper.destroyPhotosynthesisModel(self._native_ptr)
136 except Exception:
137 pass # Ignore cleanup errors
138 finally:
139 self._native_ptr = None
140
141 def get_native_ptr(self):
142 """Get the native C++ pointer for advanced operations."""
143 return self._native_ptr
144
145 def __del__(self):
146 """Destructor to ensure cleanup."""
147 self.cleanup()
148
149 # Model Configuration
150 def setModelTypeEmpirical(self):
151 """
152 Set the photosynthesis model type to empirical.
153
154 The empirical model uses light response curves with saturation kinetics.
155 """
156 photosynthesis_wrapper.setModelTypeEmpirical(self._native_ptr)
157
158 def setModelTypeFarquhar(self):
159 """
160 Set the photosynthesis model type to Farquhar-von Caemmerer-Berry.
161
162 The FvCB model is a mechanistic model accounting for biochemical
163 limitations of C3 photosynthesis.
164 """
165 photosynthesis_wrapper.setModelTypeFarquhar(self._native_ptr)
166
167 def setModelTypeC4(self):
168 """
169 Set the photosynthesis model type to the von Caemmerer (2021) steady-state C4 model.
170
171 Pair with :meth:`setC4CoefficientsFromLibrary` (e.g. ``"SetariaViridis_vC2021"``,
172 ``"Maize_Massad2007"``) or :meth:`setC4ModelCoefficients` to populate parameters.
173
174 Note:
175 Requires helios-core v1.3.72 or newer.
176
177 Raises:
178 NotImplementedError: If running against an older helios-core that does not
179 support the C4 bindings — rebuild with ``build_scripts/build_helios --clean``.
180 """
181 photosynthesis_wrapper.setModelTypeC4(self._native_ptr)
182
183 def setFarquharMesophyllConductance(self, gm_at_25c: float,
184 dha: float = -1.0,
185 topt: float = -1.0,
186 dhd: float = -1.0,
187 uuids: Optional[List[int]] = None):
188 """
189 Set Farquhar mesophyll conductance ``gm`` (mol CO2 / m² / s / bar) for selected primitives.
190
191 Pass ``dha`` < 0 (the default) to apply ``gm`` with no temperature response. Pass a
192 positive ``dha`` and leave ``topt``/``dhd`` at -1 to use a monotonic Arrhenius response.
193 Set ``topt`` (in °C) for a peaked Arrhenius response, and ``dhd`` to override the
194 deactivation energy (defaults to ``10*dha``).
195
196 Args:
197 gm_at_25c: ``gm`` at the 25 °C reference, mol CO2 / m² / s / bar.
198 dha: Activation energy (kJ/mol). -1 disables temperature response.
199 topt: Optimum temperature in °C. -1 keeps Arrhenius monotonic.
200 dhd: Deactivation energy (kJ/mol). -1 picks a default.
201 uuids: Primitive UUIDs to update. ``None`` is rejected; the underlying
202 wrapper requires explicit UUIDs (matching ``setVcmax`` etc.).
204 Raises:
205 ValueError: If ``uuids`` is None or empty.
206 NotImplementedError: If running against helios-core older than v1.3.72.
207 """
208 if not uuids:
209 raise ValueError(
210 "setFarquharMesophyllConductance requires explicit UUIDs. "
211 "To configure all primitives use setFarquharModelCoefficients() with a populated coefficient set."
212 )
213 photosynthesis_wrapper.setFarquharMesophyllConductance(
214 self._native_ptr, gm_at_25c, dha, topt, dhd, uuids,
215 )
216
217 def setC4CoefficientsFromLibrary(self, species: str, uuids: Optional[List[int]] = None,
218 material_label: Optional[str] = None):
219 """
220 Set C4 model coefficients from the von Caemmerer (2021) species library.
221
222 Args:
223 species: Species name (case-insensitive). See :data:`AVAILABLE_C4_SPECIES`.
224 uuids: Optional list of primitive UUIDs. If None and ``material_label`` is
225 also None, applies to all primitives in the Context.
226 material_label: Optional material label. When set, applies the coefficients
227 to every primitive that references this material at run() time. Mutually
228 exclusive with ``uuids``.
229
230 Raises:
231 ValueError: If both ``uuids`` and ``material_label`` are provided.
232 NotImplementedError: If running against helios-core older than v1.3.72.
233 """
234 if uuids is not None and material_label is not None:
235 raise ValueError("setC4CoefficientsFromLibrary: pass either uuids or material_label, not both.")
236 if material_label is not None:
237 photosynthesis_wrapper.setC4CoefficientsFromLibraryForMaterial(
238 self._native_ptr, species, material_label,
239 )
240 else:
241 photosynthesis_wrapper.setC4CoefficientsFromLibrary(self._native_ptr, species, uuids)
242
243 def getC4CoefficientsFromLibrary(self, species: str) -> List[float]:
244 """
245 Return the 43-float C4 coefficient array for ``species``.
246
247 See ``native/include/pyhelios_wrapper_photosynthesis.h`` for the per-index meaning.
248 """
249 return photosynthesis_wrapper.getC4CoefficientsFromLibrary(self._native_ptr, species)
250
251 def setC4ModelCoefficients(self, coefficients: List[float],
252 uuids: Optional[List[int]] = None,
253 material_label: Optional[str] = None):
254 """
255 Apply a 43-float C4 coefficient array.
256
257 Pair with :meth:`getC4CoefficientsFromLibrary` to round-trip a species' defaults.
258
259 Args:
260 coefficients: 43-float C4 coefficient array.
261 uuids: Optional list of primitive UUIDs. If None and ``material_label`` is
262 also None, applies to all primitives in the Context.
263 material_label: Optional material label. When set, applies the coefficients
264 to every primitive that references this material at run() time. Mutually
265 exclusive with ``uuids``.
266
267 Raises:
268 ValueError: If both ``uuids`` and ``material_label`` are provided.
269 """
270 if uuids is not None and material_label is not None:
271 raise ValueError("setC4ModelCoefficients: pass either uuids or material_label, not both.")
272 if material_label is not None:
273 photosynthesis_wrapper.setC4ModelCoefficientsForMaterial(
274 self._native_ptr, material_label, coefficients,
275 )
276 else:
277 photosynthesis_wrapper.setC4ModelCoefficients(self._native_ptr, coefficients, uuids)
278
279 def getC4ModelCoefficients(self, uuid: int) -> List[float]:
280 """Return the 43-float C4 coefficient array for a single primitive."""
281 return photosynthesis_wrapper.getC4ModelCoefficients(self._native_ptr, uuid)
282
283 def setCm(self, cm: float, uuids: List[int]):
284 """
285 Manually prescribe the mesophyll cytosolic CO2 partial pressure (Cm) for the C4 model.
286
287 Bypasses the ``Cm = Ci - A/gm`` fixed-point iteration and the stomatal balance
288 on Ci. Primarily intended for testing and validation against the von Caemmerer 2021
289 reference spreadsheet.
290
291 Args:
292 cm: Mesophyll cytosolic CO2 partial pressure in ubar.
293 uuids: Primitive UUIDs to set. Must be non-empty.
294
295 Raises:
296 ValueError: If ``uuids`` is empty.
297 NotImplementedError: If running against helios-core older than v1.3.72.
298 """
299 if not uuids:
300 raise ValueError("setCm requires a non-empty list of UUIDs.")
301 photosynthesis_wrapper.setCm(self._native_ptr, cm, uuids)
302
303 # Model Execution
304 def run(self):
305 """
306 Run photosynthesis calculations for all primitives in the context.
307
308 The model must be configured with appropriate coefficients before running.
309 """
310 photosynthesis_wrapper.run(self._native_ptr)
311
312 @validate_photosynthesis_uuid_params
313 def runForPrimitives(self, uuids: Union[List[int], int]):
314 """
315 Run photosynthesis calculations for specific primitives.
316
317 Args:
318 uuids: Single UUID (integer) or list of UUIDs for primitives
319 """
320 if isinstance(uuids, int):
321 uuids = [uuids]
322 photosynthesis_wrapper.runForUUIDs(self._native_ptr, uuids)
323
324 # Species Configuration
325 @validate_photosynthesis_species_params
326 def setSpeciesCoefficients(self, species: str, uuids: Optional[List[int]] = None):
327 """
328 Set Farquhar model coefficients from built-in species library.
329
330 Args:
331 species: Species name from the built-in library
332 uuids: Optional list of primitive UUIDs. If None, applies to all primitives.
333
334 Example:
335 >>> model.setSpeciesCoefficients("APPLE")
336 >>> model.setSpeciesCoefficients("SOYBEAN", [uuid1, uuid2])
337 """
338 if uuids is None:
339 photosynthesis_wrapper.setFarquharCoefficientsFromLibrary(self._native_ptr, species)
340 else:
341 photosynthesis_wrapper.setFarquharCoefficientsFromLibraryForUUIDs(self._native_ptr, species, uuids)
342
343 def setFarquharCoefficientsFromLibrary(self, species: str, uuids: Optional[List[int]] = None):
344 """
345 Set Farquhar model coefficients from built-in species library.
346
347 This method matches the C++ API naming: setFarquharCoefficientsFromLibrary()
348
349 Args:
350 species: Species name from the built-in library
351 uuids: Optional list of primitive UUIDs. If None, applies to all primitives.
352
353 Example:
354 >>> model.setFarquharCoefficientsFromLibrary("APPLE")
355 >>> model.setFarquharCoefficientsFromLibrary("SOYBEAN", [uuid1, uuid2])
356 """
357 if uuids is None:
358 photosynthesis_wrapper.setFarquharCoefficientsFromLibrary(self._native_ptr, species)
359 else:
360 photosynthesis_wrapper.setFarquharCoefficientsFromLibraryForUUIDs(self._native_ptr, species, uuids)
361
362 def getSpeciesCoefficients(self, species: str) -> List[float]:
363 """
364 Get Farquhar model coefficients for a species from the library.
365
366 Args:
367 species: Species name
368
369 Returns:
370 List of Farquhar model coefficients for the species
371 """
372 species = validate_species_name(species)
373 return photosynthesis_wrapper.getFarquharCoefficientsFromLibrary(self._native_ptr, species)
374
375 @staticmethod
376 def get_available_species() -> List[str]:
377 """
378 Static method to get available species without creating a model instance.
379
380 Returns:
381 List of species names available in the photosynthesis library
382 """
383 return get_available_species()
384
385 @staticmethod
386 def get_species_aliases() -> dict:
387 """
388 Static method to get species aliases mapping.
389
390 Returns:
391 Dictionary mapping aliases to canonical species names
392 """
393 return get_species_aliases()
394
395 # Model Coefficient Configuration
396 @validate_empirical_model_params
397 def setEmpiricalModelCoefficients(self, coefficients: EmpiricalModelCoefficients,
398 uuids: Optional[List[int]] = None):
399 """
400 Set empirical model coefficients.
401
402 Args:
403 coefficients: EmpiricalModelCoefficients instance with model parameters
404 uuids: Optional list of primitive UUIDs. If None, applies to all primitives.
405 """
406 # Convert to list format expected by C++ interface
407 coeff_list = coefficients.to_array()
408
409 if uuids is None:
410 photosynthesis_wrapper.setEmpiricalModelCoefficients(self._native_ptr, coeff_list)
411 else:
412 photosynthesis_wrapper.setEmpiricalModelCoefficientsForUUIDs(self._native_ptr, coeff_list, uuids)
413
414 @validate_farquhar_model_params
415 def setFarquharModelCoefficients(self, coefficients: FarquharModelCoefficients,
416 uuids: Optional[List[int]] = None):
417 """
418 Set Farquhar model coefficients.
419
420 Args:
421 coefficients: FarquharModelCoefficients instance with FvCB parameters
422 uuids: Optional list of primitive UUIDs. If None, applies to all primitives.
423 """
424 # Convert to list format expected by C++ interface
425 coeff_list = coefficients.to_array()
426
427 if uuids is None:
428 photosynthesis_wrapper.setFarquharModelCoefficients(self._native_ptr, coeff_list)
429 else:
430 photosynthesis_wrapper.setFarquharModelCoefficientsForUUIDs(self._native_ptr, coeff_list, uuids)
431
432 # Individual Farquhar Parameter Setting
433 def setVcmax(self, vcmax: float, uuids: List[int], dha: Optional[float] = None,
434 topt: Optional[float] = None, dhd: Optional[float] = None):
435 """
436 Set maximum carboxylation rate for Farquhar model.
437
438 This method modifies only the Vcmax parameter while preserving all
439 other existing Farquhar model parameters for each primitive.
440
441 Args:
442 vcmax: Maximum carboxylation rate at 25°C (μmol m⁻² s⁻¹)
443 uuids: List of primitive UUIDs to modify (required)
444 dha: Activation energy (optional, kJ/mol)
445 topt: Optimal temperature (optional, °C)
446 dhd: Deactivation energy (optional, kJ/mol)
447
448 Note:
449 Primitives must have existing Farquhar model coefficients set before
450 calling this method. Use setFarquharCoefficientsFromLibrary() first
451 if needed. To modify all primitives, use setFarquharModelCoefficients()
452 with complete coefficient objects.
453 """
454 from .types import FarquharModelCoefficients
455
456 # For each UUID, get existing coefficients, modify Vcmax, then set back
457 for uuid in uuids:
458 # Get existing coefficients as raw array
459 existing_array = self.getFarquharModelCoefficients(uuid)
460
461 # Create new coefficient object from existing values
462 existing_coeffs = FarquharModelCoefficients.from_array(existing_array)
463
464 # Modify only Vcmax parameter using the temperature response
465 if dha is None:
466 existing_coeffs.Vcmax = vcmax
467 else:
468 # Create temperature response object and set it
469 from .types import PhotosyntheticTemperatureResponseParameters
470 if dhd is None and topt is None:
471 temp_response = PhotosyntheticTemperatureResponseParameters(vcmax, dha)
472 elif dhd is None:
473 temp_response = PhotosyntheticTemperatureResponseParameters(vcmax, dha, topt)
474 else:
475 temp_response = PhotosyntheticTemperatureResponseParameters(vcmax, dha, topt, dhd)
476
477 # Set the temperature response values
478 existing_coeffs.Vcmax = temp_response.value_at_25C
479 # Note: Temperature response parameters would need to be stored separately
480 # For now, just set the basic value
481 existing_coeffs.Vcmax = vcmax
482
483 # Set the modified coefficients back for this UUID
484 self.setFarquharModelCoefficients(existing_coeffs, [uuid])
485
486 def setJmax(self, jmax: float, uuids: List[int], dha: Optional[float] = None,
487 topt: Optional[float] = None, dhd: Optional[float] = None):
488 """
489 Set maximum electron transport rate for Farquhar model.
490
491 This method modifies only the Jmax parameter while preserving all
492 other existing Farquhar model parameters for each primitive.
493
494 Args:
495 jmax: Maximum electron transport rate at 25°C (μmol m⁻² s⁻¹)
496 uuids: List of primitive UUIDs to modify (required)
497 dha: Activation energy (optional, kJ/mol)
498 topt: Optimal temperature (optional, °C)
499 dhd: Deactivation energy (optional, kJ/mol)
500
501 Note:
502 Primitives must have existing Farquhar model coefficients set before
503 calling this method. Use setFarquharCoefficientsFromLibrary() first
504 if needed. To modify all primitives, use setFarquharModelCoefficients()
505 with complete coefficient objects.
506 """
507 from .types import FarquharModelCoefficients
508
509 # For each UUID, get existing coefficients, modify Jmax, then set back
510 for uuid in uuids:
511 # Get existing coefficients as raw array
512 existing_array = self.getFarquharModelCoefficients(uuid)
513
514 # Create new coefficient object from existing values
515 existing_coeffs = FarquharModelCoefficients.from_array(existing_array)
516
517 # Modify only Jmax parameter
518 existing_coeffs.Jmax = jmax
519
520 # Set the modified coefficients back for this UUID
521 self.setFarquharModelCoefficients(existing_coeffs, [uuid])
522
523 def setDarkRespiration(self, respiration: float, uuids: List[int], dha: Optional[float] = None,
524 topt: Optional[float] = None, dhd: Optional[float] = None):
525 """
526 Set dark respiration rate.
527
528 This method modifies only the Rd parameter while preserving all
529 other existing Farquhar model parameters for each primitive.
530
531 Args:
532 respiration: Dark respiration rate at 25°C (μmol m⁻² s⁻¹)
533 uuids: List of primitive UUIDs to modify (required)
534 dha: Activation energy (optional, kJ/mol)
535 topt: Optimal temperature (optional, °C)
536 dhd: Deactivation energy (optional, kJ/mol)
537
538 Note:
539 Primitives must have existing Farquhar model coefficients set before
540 calling this method. Use setFarquharCoefficientsFromLibrary() first
541 if needed. To modify all primitives, use setFarquharModelCoefficients()
542 with complete coefficient objects.
543 """
544 from .types import FarquharModelCoefficients
545
546 # For each UUID, get existing coefficients, modify Rd, then set back
547 for uuid in uuids:
548 # Get existing coefficients as raw array
549 existing_array = self.getFarquharModelCoefficients(uuid)
550
551 # Create new coefficient object from existing values
552 existing_coeffs = FarquharModelCoefficients.from_array(existing_array)
553
554 # Modify only Rd parameter
555 existing_coeffs.Rd = respiration
556
557 # Set the modified coefficients back for this UUID
558 self.setFarquharModelCoefficients(existing_coeffs, [uuid])
559
560 def setQuantumEfficiency(self, efficiency: float, uuids: List[int], dha: Optional[float] = None,
561 topt: Optional[float] = None, dhd: Optional[float] = None):
562 """
563 Set quantum efficiency of photosystem II.
564
565 This method modifies only the alpha parameter while preserving all
566 other existing Farquhar model parameters for each primitive.
567
568 Args:
569 efficiency: Quantum efficiency at 25°C (dimensionless, 0-1)
570 uuids: List of primitive UUIDs to modify (required)
571 dha: Activation energy (optional, kJ/mol)
572 topt: Optimal temperature (optional, °C)
573 dhd: Deactivation energy (optional, kJ/mol)
574
575 Note:
576 Primitives must have existing Farquhar model coefficients set before
577 calling this method. Use setFarquharCoefficientsFromLibrary() first
578 if needed. To modify all primitives, use setFarquharModelCoefficients()
579 with complete coefficient objects.
580 """
581 from .types import FarquharModelCoefficients
582
583 # For each UUID, get existing coefficients, modify alpha, then set back
584 for uuid in uuids:
585 # Get existing coefficients as raw array
586 existing_array = self.getFarquharModelCoefficients(uuid)
587
588 # Create new coefficient object from existing values
589 existing_coeffs = FarquharModelCoefficients.from_array(existing_array)
590
591 # Modify only alpha parameter
592 existing_coeffs.alpha = efficiency
593
594 # Set the modified coefficients back for this UUID
595 self.setFarquharModelCoefficients(existing_coeffs, [uuid])
596
597 def setLightResponseCurvature(self, curvature: float, uuids: List[int], dha: Optional[float] = None,
598 topt: Optional[float] = None, dhd: Optional[float] = None):
599 """
600 Set light response curvature parameter.
601
602 This method modifies only the theta parameter while preserving all
603 other existing Farquhar model parameters for each primitive.
604
605 Args:
606 curvature: Light response curvature at 25°C (dimensionless)
607 uuids: List of primitive UUIDs to modify (required)
608 dha: Activation energy (optional, kJ/mol)
609 topt: Optimal temperature (optional, °C)
610 dhd: Deactivation energy (optional, kJ/mol)
611
612 Note:
613 Primitives must have existing Farquhar model coefficients set before
614 calling this method. Use setFarquharCoefficientsFromLibrary() first
615 if needed. To modify all primitives, use setFarquharModelCoefficients()
616 with complete coefficient objects.
617
618 Note:
619 The theta parameter is stored in the coefficient array but may not be
620 directly exposed in the current FarquharModelCoefficients structure.
621 This method sets the basic curvature value.
622 """
623 from .types import FarquharModelCoefficients
624
625 # For each UUID, get existing coefficients, modify theta/curvature, then set back
626 for uuid in uuids:
627 # Get existing coefficients as raw array
628 existing_array = self.getFarquharModelCoefficients(uuid)
629
630 # Create new coefficient object from existing values
631 existing_coeffs = FarquharModelCoefficients.from_array(existing_array)
632
633 # Note: theta/curvature parameter mapping would need to be checked
634 # For now, this is a placeholder - the actual field mapping needs verification
635 # existing_coeffs.theta = curvature # This field may not exist
636
637 # Set the modified coefficients back for this UUID
638 self.setFarquharModelCoefficients(existing_coeffs, [uuid])
639
640 # Results and Output
641 def getEmpiricalModelCoefficients(self, uuid: int) -> List[float]:
642 """
643 Get empirical model coefficients for a specific primitive.
644
645 Args:
646 uuid: Primitive UUID
647
648 Returns:
649 List of empirical model coefficients
650 """
651 return photosynthesis_wrapper.getEmpiricalModelCoefficients(self._native_ptr, uuid)
652
653 def getFarquharModelCoefficients(self, uuid: int) -> List[float]:
654 """
655 Get Farquhar model coefficients for a specific primitive.
656
657 Args:
658 uuid: Primitive UUID
659
660 Returns:
661 List of Farquhar model coefficients
662 """
663 return photosynthesis_wrapper.getFarquharModelCoefficients(self._native_ptr, uuid)
664
665 def exportResults(self, label: str):
666 """
667 Export photosynthesis results with optional label.
668
669 Args:
670 label: Data label for export
671 """
672 photosynthesis_wrapper.optionalOutputPrimitiveData(self._native_ptr, label)
673
674 # Model Information and Utilities
675 def enableMessages(self):
676 """Enable photosynthesis model status messages."""
677 photosynthesis_wrapper.enableMessages(self._native_ptr)
678
679 def disableMessages(self):
680 """Disable photosynthesis model status messages."""
681 photosynthesis_wrapper.disableMessages(self._native_ptr)
682
683 def printModelReport(self, uuids: Optional[List[int]] = None):
684 """
685 Print model configuration report.
686
687 Args:
688 uuids: Optional list of UUIDs. If None, prints report for all primitives.
689 """
690 if uuids is None:
691 photosynthesis_wrapper.printDefaultValueReport(self._native_ptr)
692 else:
693 photosynthesis_wrapper.printDefaultValueReportForUUIDs(self._native_ptr, uuids)
694
695 # Utility Methods
696 def validateConfiguration(self) -> bool:
697 """
698 Basic validation that model has been configured.
699
700 Returns:
701 True if model appears to be configured (has native pointer)
702 """
703 return self._native_ptr is not None
704
705 def resetModel(self):
706 """
707 Reset the model by recreating it.
708 Note: This will clear all configured parameters.
709 """
710 if self._native_ptr is not None:
711 old_ptr = self._native_ptr
712 try:
713 context_ptr = self.context.getNativePtr()
714 self._native_ptr = photosynthesis_wrapper.createPhotosynthesisModel(context_ptr)
715 finally:
716 # Clean up old pointer
717 try:
718 photosynthesis_wrapper.destroyPhotosynthesisModel(old_ptr)
719 except Exception:
720 pass
Exception raised by PhotosynthesisModel operations.
High-level interface for Helios photosynthesis modeling.
setC4CoefficientsFromLibrary(self, str species, Optional[List[int]] uuids=None, Optional[str] material_label=None)
Set C4 model coefficients from the von Caemmerer (2021) species library.
disableMessages(self)
Disable photosynthesis model status messages.
printModelReport(self, Optional[List[int]] uuids=None)
Print model configuration report.
enableMessages(self)
Enable photosynthesis model status messages.
bool validateConfiguration(self)
Basic validation that model has been configured.
List[float] getC4ModelCoefficients(self, int uuid)
Return the 43-float C4 coefficient array for a single primitive.
setFarquharMesophyllConductance(self, float gm_at_25c, float dha=-1.0, float topt=-1.0, float dhd=-1.0, Optional[List[int]] uuids=None)
Set Farquhar mesophyll conductance gm (mol CO2 / m² / s / bar) for selected primitives.
setFarquharCoefficientsFromLibrary(self, str species, Optional[List[int]] uuids=None)
Set Farquhar model coefficients from built-in species library.
setJmax(self, float jmax, List[int] uuids, Optional[float] dha=None, Optional[float] topt=None, Optional[float] dhd=None)
Set maximum electron transport rate for Farquhar model.
List[float] getFarquharModelCoefficients(self, int uuid)
Get Farquhar model coefficients for a specific primitive.
get_native_ptr(self)
Get the native C++ pointer for advanced operations.
setDarkRespiration(self, float respiration, List[int] uuids, Optional[float] dha=None, Optional[float] topt=None, Optional[float] dhd=None)
Set dark respiration rate.
setModelTypeFarquhar(self)
Set the photosynthesis model type to Farquhar-von Caemmerer-Berry.
List[float] getC4CoefficientsFromLibrary(self, str species)
Return the 43-float C4 coefficient array for species.
setVcmax(self, float vcmax, List[int] uuids, Optional[float] dha=None, Optional[float] topt=None, Optional[float] dhd=None)
Set maximum carboxylation rate for Farquhar model.
setModelTypeC4(self)
Set the photosynthesis model type to the von Caemmerer (2021) steady-state C4 model.
setModelTypeEmpirical(self)
Set the photosynthesis model type to empirical.
exportResults(self, str label)
Export photosynthesis results with optional label.
resetModel(self)
Reset the model by recreating it.
setQuantumEfficiency(self, float efficiency, List[int] uuids, Optional[float] dha=None, Optional[float] topt=None, Optional[float] dhd=None)
Set quantum efficiency of photosystem II.
setCm(self, float cm, List[int] uuids)
Manually prescribe the mesophyll cytosolic CO2 partial pressure (Cm) for the C4 model.
setEmpiricalModelCoefficients(self, EmpiricalModelCoefficients coefficients, Optional[List[int]] uuids=None)
Set empirical model coefficients.
dict get_species_aliases()
Static method to get species aliases mapping.
run(self)
Run photosynthesis calculations for all primitives in the context.
__init__(self, Context context)
Initialize PhotosynthesisModel.
runForPrimitives(self, Union[List[int], int] uuids)
Run photosynthesis calculations for specific primitives.
setFarquharModelCoefficients(self, FarquharModelCoefficients coefficients, Optional[List[int]] uuids=None)
Set Farquhar model coefficients.
List[str] get_available_species()
Static method to get available species without creating a model instance.
List[float] getEmpiricalModelCoefficients(self, int uuid)
Get empirical model coefficients for a specific primitive.
setC4ModelCoefficients(self, List[float] coefficients, Optional[List[int]] uuids=None, Optional[str] material_label=None)
Apply a 43-float C4 coefficient array.
List[float] getSpeciesCoefficients(self, str species)
Get Farquhar model coefficients for a species from the library.
setSpeciesCoefficients(self, str species, Optional[List[int]] uuids=None)
Set Farquhar model coefficients from built-in species library.
__exit__(self, exc_type, exc_value, traceback)
Context manager exit with cleanup.
setLightResponseCurvature(self, float curvature, List[int] uuids, Optional[float] dha=None, Optional[float] topt=None, Optional[float] dhd=None)
Set light response curvature parameter.
Temperature response parameters for photosynthetic processes.