0.1.39
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, check_context_alive
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 (µmol/m²·s PPFD)
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 _check_context_alive(self):
124 """Raise if the owning Context has been destroyed (see Context.check_context_alive)."""
125 check_context_alive(getattr(self, "context", None), "PhotosynthesisModel")
127 def __enter__(self):
128 """Context manager entry."""
129 return self
131 def __exit__(self, exc_type, exc_value, traceback):
132 """Context manager exit with cleanup."""
133 self.cleanup()
135 def cleanup(self):
136 """Clean up native resources."""
137 if hasattr(self, '_native_ptr') and self._native_ptr is not None:
138 try:
139 photosynthesis_wrapper.destroyPhotosynthesisModel(self._native_ptr)
140 except Exception:
141 pass # Ignore cleanup errors
142 finally:
143 self._native_ptr = None
144
145 def get_native_ptr(self):
146 """Get the native C++ pointer for advanced operations."""
147 return self._native_ptr
149 def __del__(self):
150 """Destructor to ensure cleanup."""
151 self.cleanup()
153 # Model Configuration
154 def setModelTypeEmpirical(self):
155 """
156 Set the photosynthesis model type to empirical.
157
158 The empirical model uses light response curves with saturation kinetics.
159 """
161 photosynthesis_wrapper.setModelTypeEmpirical(self._native_ptr)
162
163 def setModelTypeFarquhar(self):
164 """
165 Set the photosynthesis model type to Farquhar-von Caemmerer-Berry.
166
167 The FvCB model is a mechanistic model accounting for biochemical
168 limitations of C3 photosynthesis.
169 """
171 photosynthesis_wrapper.setModelTypeFarquhar(self._native_ptr)
172
173 def setModelTypeC4(self):
174 """
175 Set the photosynthesis model type to the von Caemmerer (2021) steady-state C4 model.
176
177 Pair with :meth:`setC4CoefficientsFromLibrary` (e.g. ``"SetariaViridis_vC2021"``,
178 ``"Maize_Massad2007"``) or :meth:`setC4ModelCoefficients` to populate parameters.
179
180 Note:
181 Requires helios-core v1.3.72 or newer.
182
183 Raises:
184 NotImplementedError: If running against an older helios-core that does not
185 support the C4 bindings — rebuild with ``build_scripts/build_helios --clean``.
186 """
188 photosynthesis_wrapper.setModelTypeC4(self._native_ptr)
189
190 def setFarquharMesophyllConductance(self, gm_at_25c: float,
191 dha: float = -1.0,
192 topt: float = -1.0,
193 dhd: float = -1.0,
194 uuids: Optional[List[int]] = None):
195 """
196 Set Farquhar mesophyll conductance ``gm`` (mol CO2 / m² / s / bar) for selected primitives.
197
198 Pass ``dha`` < 0 (the default) to apply ``gm`` with no temperature response. Pass a
199 positive ``dha`` and leave ``topt``/``dhd`` at -1 to use a monotonic Arrhenius response.
200 Set ``topt`` (in °C) for a peaked Arrhenius response, and ``dhd`` to override the
201 deactivation energy (defaults to ``10*dha``).
202
203 Args:
204 gm_at_25c: ``gm`` at the 25 °C reference, mol CO2 / m² / s / bar.
205 dha: Activation energy (kJ/mol). -1 disables temperature response.
206 topt: Optimum temperature in °C. -1 keeps Arrhenius monotonic.
207 dhd: Deactivation energy (kJ/mol). -1 picks a default.
208 uuids: Primitive UUIDs to update. Must be given explicitly (``None`` is
209 rejected), as for ``setVcmax``.
210
211 Raises:
212 ValueError: If ``uuids`` is None or empty.
213 NotImplementedError: If running against helios-core older than v1.3.72.
214 """
215 if not uuids:
216 raise ValueError(
217 "setFarquharMesophyllConductance requires explicit UUIDs. "
218 "To configure all primitives use setFarquharModelCoefficients() with a populated coefficient set."
219 )
221 photosynthesis_wrapper.setFarquharMesophyllConductance(
222 self._native_ptr, gm_at_25c, dha, topt, dhd, uuids,
223 )
224
225 def setC4CoefficientsFromLibrary(self, species: str, uuids: Optional[List[int]] = None,
226 material_label: Optional[str] = None):
227 """
228 Set C4 model coefficients from the von Caemmerer (2021) species library.
229
230 Args:
231 species: Species name (case-insensitive). See :data:`AVAILABLE_C4_SPECIES`.
232 uuids: Optional list of primitive UUIDs. If None and ``material_label`` is
233 also None, applies to all primitives in the Context.
234 material_label: Optional material label. When set, applies the coefficients
235 to every primitive that references this material at run() time. Mutually
236 exclusive with ``uuids``.
237
238 Raises:
239 ValueError: If both ``uuids`` and ``material_label`` are provided.
240 NotImplementedError: If running against helios-core older than v1.3.72.
241 """
242 if uuids is not None and material_label is not None:
243 raise ValueError("setC4CoefficientsFromLibrary: pass either uuids or material_label, not both.")
244 if material_label is not None:
246 photosynthesis_wrapper.setC4CoefficientsFromLibraryForMaterial(
247 self._native_ptr, species, material_label,
248 )
249 else:
251 photosynthesis_wrapper.setC4CoefficientsFromLibrary(self._native_ptr, species, uuids)
252
253 def getC4CoefficientsFromLibrary(self, species: str) -> List[float]:
254 """
255 Return the 43-float C4 coefficient array for ``species``.
256 """
258 return photosynthesis_wrapper.getC4CoefficientsFromLibrary(self._native_ptr, species)
259
260 def setC4ModelCoefficients(self, coefficients: List[float],
261 uuids: Optional[List[int]] = None,
262 material_label: Optional[str] = None):
263 """
264 Apply a 43-float C4 coefficient array.
265
266 Pair with :meth:`getC4CoefficientsFromLibrary` to round-trip a species' defaults.
267
268 Args:
269 coefficients: 43-float C4 coefficient array.
270 uuids: Optional list of primitive UUIDs. If None and ``material_label`` is
271 also None, applies to all primitives in the Context.
272 material_label: Optional material label. When set, applies the coefficients
273 to every primitive that references this material at run() time. Mutually
274 exclusive with ``uuids``.
275
276 Raises:
277 ValueError: If both ``uuids`` and ``material_label`` are provided.
278 """
279 if uuids is not None and material_label is not None:
280 raise ValueError("setC4ModelCoefficients: pass either uuids or material_label, not both.")
281 if material_label is not None:
283 photosynthesis_wrapper.setC4ModelCoefficientsForMaterial(
284 self._native_ptr, material_label, coefficients,
285 )
286 else:
288 photosynthesis_wrapper.setC4ModelCoefficients(self._native_ptr, coefficients, uuids)
289
290 def getC4ModelCoefficients(self, uuid: int) -> List[float]:
291 """Return the 43-float C4 coefficient array for a single primitive."""
293 return photosynthesis_wrapper.getC4ModelCoefficients(self._native_ptr, uuid)
294
295 def setCm(self, cm: float, uuids: List[int]):
296 """
297 Manually prescribe the mesophyll cytosolic CO2 partial pressure (Cm) for the C4 model.
298
299 Bypasses the ``Cm = Ci - A/gm`` fixed-point iteration and the stomatal balance
300 on Ci. Primarily intended for testing and validation against the von Caemmerer 2021
301 reference spreadsheet.
302
303 Args:
304 cm: Mesophyll cytosolic CO2 partial pressure in ubar.
305 uuids: Primitive UUIDs to set. Must be non-empty.
306
307 Raises:
308 ValueError: If ``uuids`` is empty.
309 NotImplementedError: If running against helios-core older than v1.3.72.
310 """
311 if not uuids:
312 raise ValueError("setCm requires a non-empty list of UUIDs.")
314 photosynthesis_wrapper.setCm(self._native_ptr, cm, uuids)
315
316 # Model Execution
317 def run(self):
318 """
319 Run photosynthesis calculations for all primitives in the context.
320
321 The model must be configured with appropriate coefficients before running.
322 """
324 photosynthesis_wrapper.run(self._native_ptr)
325
326 @validate_photosynthesis_uuid_params
327 def runForPrimitives(self, uuids: Union[List[int], int]):
328 """
329 Run photosynthesis calculations for specific primitives.
330
331 Args:
332 uuids: Single UUID (integer) or list of UUIDs for primitives
333 """
334 if isinstance(uuids, int):
335 uuids = [uuids]
337 photosynthesis_wrapper.runForUUIDs(self._native_ptr, uuids)
338
339 # Species Configuration
340 @validate_photosynthesis_species_params
341 def setSpeciesCoefficients(self, species: str, uuids: Optional[List[int]] = None):
342 """
343 Set Farquhar model coefficients from built-in species library.
344
345 Args:
346 species: Species name from the built-in library
347 uuids: Optional list of primitive UUIDs. If None, applies to all primitives.
348
349 Example:
350 >>> model.setSpeciesCoefficients("APPLE")
351 >>> model.setSpeciesCoefficients("SOYBEAN", [uuid1, uuid2])
352 """
353 if uuids is None:
355 photosynthesis_wrapper.setFarquharCoefficientsFromLibrary(self._native_ptr, species)
356 else:
358 photosynthesis_wrapper.setFarquharCoefficientsFromLibraryForUUIDs(self._native_ptr, species, uuids)
359
360 def setFarquharCoefficientsFromLibrary(self, species: str, uuids: Optional[List[int]] = None):
361 """
362 Set Farquhar model coefficients from built-in species library.
363
364 This method matches the C++ API naming: setFarquharCoefficientsFromLibrary()
365
366 Args:
367 species: Species name from the built-in library
368 uuids: Optional list of primitive UUIDs. If None, applies to all primitives.
369
370 Example:
371 >>> model.setFarquharCoefficientsFromLibrary("APPLE")
372 >>> model.setFarquharCoefficientsFromLibrary("SOYBEAN", [uuid1, uuid2])
373 """
374 if uuids is None:
376 photosynthesis_wrapper.setFarquharCoefficientsFromLibrary(self._native_ptr, species)
377 else:
379 photosynthesis_wrapper.setFarquharCoefficientsFromLibraryForUUIDs(self._native_ptr, species, uuids)
380
381 def getSpeciesCoefficients(self, species: str) -> List[float]:
382 """
383 Get Farquhar model coefficients for a species from the library.
384
385 Args:
386 species: Species name
387
388 Returns:
389 List of Farquhar model coefficients for the species
390 """
391 species = validate_species_name(species)
393 return photosynthesis_wrapper.getFarquharCoefficientsFromLibrary(self._native_ptr, species)
394
395 @staticmethod
396 def get_available_species() -> List[str]:
397 """
398 Static method to get available species without creating a model instance.
399
400 Returns:
401 List of species names available in the photosynthesis library
402 """
403 return get_available_species()
405 @staticmethod
406 def get_species_aliases() -> dict:
407 """
408 Static method to get species aliases mapping.
409
410 Returns:
411 Dictionary mapping aliases to canonical species names
412 """
413 return get_species_aliases()
415 # Model Coefficient Configuration
416 @validate_empirical_model_params
417 def setEmpiricalModelCoefficients(self, coefficients: EmpiricalModelCoefficients,
418 uuids: Optional[List[int]] = None):
419 """
420 Set empirical model coefficients.
421
422 Args:
423 coefficients: EmpiricalModelCoefficients instance with model parameters
424 uuids: Optional list of primitive UUIDs. If None, applies to all primitives.
425 """
426 # Convert to list format expected by C++ interface
427 coeff_list = coefficients.to_array()
428
429 if uuids is None:
431 photosynthesis_wrapper.setEmpiricalModelCoefficients(self._native_ptr, coeff_list)
432 else:
434 photosynthesis_wrapper.setEmpiricalModelCoefficientsForUUIDs(self._native_ptr, coeff_list, uuids)
435
436 @validate_farquhar_model_params
437 def setFarquharModelCoefficients(self, coefficients: FarquharModelCoefficients,
438 uuids: Optional[List[int]] = None):
439 """
440 Set Farquhar model coefficients.
441
442 Args:
443 coefficients: FarquharModelCoefficients instance with FvCB parameters
444 uuids: Optional list of primitive UUIDs. If None, applies to all primitives.
445 """
446 # Convert to list format expected by C++ interface
447 coeff_list = coefficients.to_array()
448
449 if uuids is None:
451 photosynthesis_wrapper.setFarquharModelCoefficients(self._native_ptr, coeff_list)
452 else:
454 photosynthesis_wrapper.setFarquharModelCoefficientsForUUIDs(self._native_ptr, coeff_list, uuids)
455
456 # Individual Farquhar Parameter Setting
457 def setVcmax(self, vcmax: float, uuids: List[int], dha: Optional[float] = None,
458 topt: Optional[float] = None, dhd: Optional[float] = None):
459 """
460 Set maximum carboxylation rate for Farquhar model.
461
462 This method modifies only the Vcmax parameter while preserving all
463 other existing Farquhar model parameters for each primitive.
464
465 Args:
466 vcmax: Maximum carboxylation rate at 25°C (μmol m⁻² s⁻¹)
467 uuids: List of primitive UUIDs to modify (required)
468 dha: Activation energy (optional, kJ/mol)
469 topt: Optimal temperature (optional, °C)
470 dhd: Deactivation energy (optional, kJ/mol)
471
472 Note:
473 Primitives must have existing Farquhar model coefficients set before
474 calling this method. Use setFarquharCoefficientsFromLibrary() first
475 if needed. To modify all primitives, use setFarquharModelCoefficients()
476 with complete coefficient objects.
477 """
479 photosynthesis_wrapper.setFarquharVcmax(
480 self._native_ptr, vcmax,
481 -1.0 if dha is None else dha,
482 -1.0 if topt is None else topt,
483 -1.0 if dhd is None else dhd,
484 uuids,
485 )
486
487 def setJmax(self, jmax: float, uuids: List[int], dha: Optional[float] = None,
488 topt: Optional[float] = None, dhd: Optional[float] = None):
489 """
490 Set maximum electron transport rate for Farquhar model.
491
492 This method modifies only the Jmax parameter while preserving all
493 other existing Farquhar model parameters for each primitive.
494
495 Args:
496 jmax: Maximum electron transport rate at 25°C (μmol m⁻² s⁻¹)
497 uuids: List of primitive UUIDs to modify (required)
498 dha: Activation energy (optional, kJ/mol)
499 topt: Optimal temperature (optional, °C)
500 dhd: Deactivation energy (optional, kJ/mol)
501
502 Note:
503 Primitives must have existing Farquhar model coefficients set before
504 calling this method. Use setFarquharCoefficientsFromLibrary() first
505 if needed. To modify all primitives, use setFarquharModelCoefficients()
506 with complete coefficient objects.
507 """
509 photosynthesis_wrapper.setFarquharJmax(
510 self._native_ptr, jmax,
511 -1.0 if dha is None else dha,
512 -1.0 if topt is None else topt,
513 -1.0 if dhd is None else dhd,
514 uuids,
515 )
516
517 def setDarkRespiration(self, respiration: float, uuids: List[int], dha: Optional[float] = None,
518 topt: Optional[float] = None, dhd: Optional[float] = None):
519 """
520 Set dark respiration rate.
521
522 This method modifies only the Rd parameter while preserving all
523 other existing Farquhar model parameters for each primitive.
524
525 Args:
526 respiration: Dark respiration rate at 25°C (μmol m⁻² s⁻¹)
527 uuids: List of primitive UUIDs to modify (required)
528 dha: Activation energy (optional, kJ/mol)
529 topt: Optimal temperature (optional, °C)
530 dhd: Deactivation energy (optional, kJ/mol)
531
532 Note:
533 Primitives must have existing Farquhar model coefficients set before
534 calling this method. Use setFarquharCoefficientsFromLibrary() first
535 if needed. To modify all primitives, use setFarquharModelCoefficients()
536 with complete coefficient objects.
537 """
539 photosynthesis_wrapper.setFarquharRd(
540 self._native_ptr, respiration,
541 -1.0 if dha is None else dha,
542 -1.0 if topt is None else topt,
543 -1.0 if dhd is None else dhd,
544 uuids,
545 )
546
547 def setQuantumEfficiency(self, efficiency: float, uuids: List[int], dha: Optional[float] = None,
548 topt: Optional[float] = None, dhd: Optional[float] = None):
549 """
550 Set quantum efficiency of photosystem II.
551
552 This method modifies only the alpha parameter while preserving all
553 other existing Farquhar model parameters for each primitive.
554
555 Args:
556 efficiency: Quantum efficiency at 25°C (dimensionless, 0-1)
557 uuids: List of primitive UUIDs to modify (required)
558 dha: Activation energy (optional, kJ/mol)
559 topt: Optimal temperature (optional, °C)
560 dhd: Deactivation energy (optional, kJ/mol)
561
562 Note:
563 Primitives must have existing Farquhar model coefficients set before
564 calling this method. Use setFarquharCoefficientsFromLibrary() first
565 if needed. To modify all primitives, use setFarquharModelCoefficients()
566 with complete coefficient objects.
567 """
569 photosynthesis_wrapper.setFarquharQuantumEfficiency(
570 self._native_ptr, efficiency,
571 -1.0 if dha is None else dha,
572 -1.0 if topt is None else topt,
573 -1.0 if dhd is None else dhd,
574 uuids,
575 )
576
577 def setLightResponseCurvature(self, curvature: float, uuids: List[int], dha: Optional[float] = None,
578 topt: Optional[float] = None, dhd: Optional[float] = None):
579 """
580 Set light response curvature parameter.
581
582 This method modifies only the theta parameter while preserving all
583 other existing Farquhar model parameters for each primitive.
584
585 Args:
586 curvature: Light response curvature at 25°C (dimensionless)
587 uuids: List of primitive UUIDs to modify (required)
588 dha: Activation energy (optional, kJ/mol)
589 topt: Optimal temperature (optional, °C)
590 dhd: Deactivation energy (optional, kJ/mol)
591
592 Note:
593 Primitives must have existing Farquhar model coefficients set before
594 calling this method. Use setFarquharCoefficientsFromLibrary() first
595 if needed. To modify all primitives, use setFarquharModelCoefficients()
596 with complete coefficient objects.
597
598 """
600 photosynthesis_wrapper.setFarquharLightResponseCurvature(
601 self._native_ptr, curvature,
602 -1.0 if dha is None else dha,
603 -1.0 if topt is None else topt,
604 -1.0 if dhd is None else dhd,
605 uuids,
606 )
607
608 def getLightResponseCurvature(self, uuid: int) -> float:
609 """
610 Get the light response curvature (theta) at 25 degrees C for a primitive.
611
612 Args:
613 uuid: Primitive UUID to query
614
615 Returns:
616 Light response curvature at 25 degrees C (dimensionless)
617 """
618 return self.getLightResponseCurvatureTempResponse(uuid).value_at_25C
620 def getLightResponseCurvatureTempResponse(self, uuid: int):
621 """
622 Get the full light response curvature (theta) temperature response for a primitive.
623
624 Args:
625 uuid: Primitive UUID to query
626
627 Returns:
628 PhotosyntheticTemperatureResponseParameters for theta
629 """
630 from .types import FarquharModelCoefficients
632 coefficients = self.getFarquharModelCoefficients(uuid)
633 return FarquharModelCoefficients.from_array(
635
636 # Results and Output
637 def getEmpiricalModelCoefficients(self, uuid: int) -> List[float]:
638 """
639 Get empirical model coefficients for a specific primitive.
640
641 Args:
642 uuid: Primitive UUID
643
644 Returns:
645 List of empirical model coefficients
646 """
648 return photosynthesis_wrapper.getEmpiricalModelCoefficients(self._native_ptr, uuid)
649
650 def getFarquharModelCoefficients(self, uuid: int) -> List[float]:
651 """
652 Get Farquhar model coefficients for a specific primitive.
653
654 Args:
655 uuid: Primitive UUID
656
657 Returns:
658 List of Farquhar model coefficients
659 """
661 return photosynthesis_wrapper.getFarquharModelCoefficients(self._native_ptr, uuid)
662
663 def exportResults(self, label: str):
664 """
665 Request an optional output primitive data label, written on the next :meth:`run`.
666
667 Calls the native ``PhotosynthesisModel::optionalOutputPrimitiveData()``. Labels include
668 ``"Ci"``, ``"limitation_state"`` and ``"electron_transport_ratio"`` (plus ``"Gamma_CO2"``
669 for the Farquhar model and ``"Cm"``/``"Vp"`` for the C4 model).
670 ``electron_transport_ratio`` is the relative light saturation Ja/Je of van der Tol et al.
671 (2014): the electron transport used by carbon metabolism divided by its light-limited
672 potential. It is 1 in the dark, falls as light saturates photosynthesis, is written by
673 the Farquhar and C4 models, and drives the radiation model's SIF fluorescence yield.
674
675 Args:
676 label: Primitive data label to output
677 """
679 photosynthesis_wrapper.optionalOutputPrimitiveData(self._native_ptr, label)
680
681 # Model Information and Utilities
682 def enableMessages(self):
683 """Enable photosynthesis model status messages."""
685 photosynthesis_wrapper.enableMessages(self._native_ptr)
686
687 def disableMessages(self):
688 """Disable photosynthesis model status messages."""
690 photosynthesis_wrapper.disableMessages(self._native_ptr)
691
692 def printModelReport(self, uuids: Optional[List[int]] = None):
693 """
694 Print model configuration report.
695
696 Args:
697 uuids: Optional list of UUIDs. If None, prints report for all primitives.
698 """
699 if uuids is None:
701 photosynthesis_wrapper.printDefaultValueReport(self._native_ptr)
702 else:
704 photosynthesis_wrapper.printDefaultValueReportForUUIDs(self._native_ptr, uuids)
705
706 # Utility Methods
707 def validateConfiguration(self) -> bool:
708 """
709 Basic validation that model has been configured.
710
711 Returns:
712 True if model appears to be configured (has native pointer)
713 """
714 return self._native_ptr is not None
716 def resetModel(self):
717 """
718 Reset the model by recreating it.
719 Note: This will clear all configured parameters.
720 """
721 if self._native_ptr is not None:
722 old_ptr = self._native_ptr
723 try:
724 context_ptr = self.context.getNativePtr()
725 self._native_ptr = photosynthesis_wrapper.createPhotosynthesisModel(context_ptr)
726 finally:
727 # Clean up old pointer
728 try:
729 photosynthesis_wrapper.destroyPhotosynthesisModel(old_ptr)
730 except Exception:
731 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.
float getLightResponseCurvature(self, int uuid)
Get the light response curvature (theta) at 25 degrees C for a primitive.
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)
Request an optional output primitive data label, written on the next :meth:run.
getLightResponseCurvatureTempResponse(self, int uuid)
Get the full light response curvature (theta) temperature response for a primitive.
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.
_check_context_alive(self)
Raise if the owning Context has been destroyed (see Context.check_context_alive).
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.