0.1.26
Loading...
Searching...
No Matches
LeafOptics.py
Go to the documentation of this file.
1"""
2High-level LeafOptics interface for PyHelios.
3
4This module provides a user-friendly interface to the PROSPECT leaf optical model
5for computing spectral reflectance and transmittance of plant leaves.
6"""
7
8import logging
9import os
10from contextlib import contextmanager
11from dataclasses import dataclass, field
12from pathlib import Path
13from typing import List, Optional, Tuple
14
15from .plugins.registry import get_plugin_registry
16from .wrappers import ULeafOpticsWrapper as leafoptics_wrapper
17from .Context import Context, check_context_alive
18from .exceptions import HeliosError
19from .assets import get_asset_manager
20
21logger = logging.getLogger(__name__)
22
23
25 """Exception raised for LeafOptics-specific errors."""
26 pass
27
28
29# Available species in the built-in library
30AVAILABLE_SPECIES = [
31 "default",
32 "garden_lettuce",
33 "alfalfa",
34 "corn",
35 "sunflower",
36 "english_walnut",
37 "rice",
38 "soybean",
39 "wine_grape",
40 "tomato",
41 "common_bean",
42 "cowpea"
43]
44
45
46@dataclass
48 """
49 Data class for PROSPECT leaf optical model parameters.
50
51 These parameters define the physical and biochemical properties of a leaf
52 that determine its spectral reflectance and transmittance.
53
54 Attributes:
55 numberlayers: Number of mesophyll layers in the leaf (typically 1-3)
56 brownpigments: Brown pigment content (arbitrary units, typically 0)
57 chlorophyllcontent: Chlorophyll a+b content in micrograms per square cm
58 carotenoidcontent: Carotenoid content in micrograms per square cm
59 anthocyancontent: Anthocyanin content in micrograms per square cm
60 watermass: Equivalent water thickness in grams per square cm
61 drymass: Dry matter content (leaf mass per area) in grams per square cm
62 protein: Protein content in grams per square cm (PROSPECT-PRO mode)
63 carbonconstituents: Carbon-based constituents in grams per square cm (PROSPECT-PRO mode)
64 V2Z: Violaxanthin-to-zeaxanthin de-epoxidation state, [0, 1]. Used by the
65 radiation plugin's solar-induced fluorescence (SIF) pipeline; ignored by
66 the pure PROSPECT reflectance/transmittance calculation. Default 0
67 (dark-adapted, all violaxanthin).
68 fqe: Intrinsic fluorescence quantum efficiency scalar applied on top of the
69 per-leaf Phi_F at SIF emission time (radiation plugin only). Ignored by
70 PROSPECT. Default 1.0.
71
72 Note:
73 - If protein > 0 OR carbonconstituents > 0, the model uses PROSPECT-PRO mode
74 which ignores drymass and uses protein + carbonconstituents instead.
75 - Otherwise, the model uses PROSPECT-D mode which uses drymass.
76 - V2Z and fqe are inert unless the radiation plugin's SIF camera is in use.
77 """
78 numberlayers: float = 1.5
79 brownpigments: float = 0.0
80 chlorophyllcontent: float = 30.0 # micrograms/cm^2
81 carotenoidcontent: float = 7.0 # micrograms/cm^2
82 anthocyancontent: float = 1.0 # micrograms/cm^2
83 watermass: float = 0.015 # g/cm^2
84 drymass: float = 0.09 # g/cm^2
85 protein: float = 0.0 # g/cm^2 (PROSPECT-PRO mode)
86 carbonconstituents: float = 0.0 # g/cm^2 (PROSPECT-PRO mode)
87 V2Z: float = 0.0 # SIF: violaxanthin↔zeaxanthin state, [0, 1]
88 fqe: float = 1.0 # SIF: intrinsic fluorescence quantum efficiency scalar
89
90 def to_list(self) -> List[float]:
91 """Convert properties to a list in the order expected by the C++ interface."""
92 return [
93 self.numberlayers,
94 self.brownpigments,
98 self.watermass,
99 self.drymass,
100 self.protein,
102 self.V2Z,
103 self.fqe,
106 @classmethod
107 def from_list(cls, values: List[float]) -> 'LeafOpticsProperties':
108 """Create LeafOpticsProperties from a list of values.
110 Accepts the legacy 9-float layout (without V2Z/fqe) for backward
111 compatibility with serialized data; missing fields fall back to
112 defaults and a ``DeprecationWarning`` is emitted so callers can
113 migrate to the 11-element layout.
114 """
115 if len(values) not in (9, 11):
116 raise ValueError(f"Expected 9 or 11 values, got {len(values)}")
117 if len(values) == 9:
118 import warnings
119 warnings.warn(
120 "LeafOpticsProperties.from_list received a 9-element legacy "
121 "array (pre-helios-core 1.3.72). V2Z and fqe will default to "
122 "0.0 and 1.0 respectively. Migrate serialized data to the "
123 "11-element layout to silence this warning.",
124 DeprecationWarning,
125 stacklevel=2,
126 )
127 return cls(
128 numberlayers=values[0],
129 brownpigments=values[1],
130 chlorophyllcontent=values[2],
131 carotenoidcontent=values[3],
132 anthocyancontent=values[4],
133 watermass=values[5],
134 drymass=values[6],
135 protein=values[7],
136 carbonconstituents=values[8],
137 V2Z=values[9] if len(values) > 9 else 0.0,
138 fqe=values[10] if len(values) > 10 else 1.0,
140
141
142@contextmanager
144 """
145 Context manager that temporarily changes working directory to where LeafOptics assets are located.
146
147 LeafOptics C++ code uses relative paths like "plugins/leafoptics/spectral_data/"
148 expecting assets relative to working directory. This manager temporarily changes to the build
149 directory where assets are actually located.
150 """
151 # Find the build directory containing LeafOptics assets
152 asset_manager = get_asset_manager()
153 working_dir = asset_manager._get_helios_build_path()
154
155 if working_dir and working_dir.exists():
156 leafoptics_assets = working_dir / 'plugins' / 'leafoptics' / 'spectral_data'
157 else:
158 # Fallback to development paths
159 current_dir = Path(__file__).parent
160 repo_root = current_dir.parent
161 build_lib_dir = repo_root / 'pyhelios_build' / 'build' / 'lib'
162 working_dir = build_lib_dir.parent
163 leafoptics_assets = working_dir / 'plugins' / 'leafoptics' / 'spectral_data'
164
165 if not build_lib_dir.exists():
166 raise LeafOpticsError(
167 f"PyHelios build directory not found at {build_lib_dir}. "
168 f"LeafOptics requires native libraries to be built. "
169 f"Run: build_scripts/build_helios --plugins leafoptics"
170 )
171
172 # Validate spectral data file exists
173 spectral_file = leafoptics_assets / 'prospect_spectral_library.xml'
174 if not spectral_file.exists():
175 raise LeafOpticsError(
176 f"LeafOptics spectral data not found at {spectral_file}. "
177 f"Build system failed to copy LeafOptics assets. "
178 f"Run: build_scripts/build_helios --clean --plugins leafoptics"
179 )
180
181 # Validate file size (should be ~475KB)
182 file_size = spectral_file.stat().st_size
183 if file_size < 400000: # Less than 400KB indicates corruption
184 raise LeafOpticsError(
185 f"LeafOptics spectral data file appears corrupted (size: {file_size} bytes, expected ~475KB). "
186 f"Run: build_scripts/build_helios --clean --plugins leafoptics"
187 )
188
189 # Change to the build directory temporarily
190 original_dir = os.getcwd()
191 try:
192 os.chdir(working_dir)
193 logger.debug(f"Changed working directory to {working_dir} for LeafOptics asset access")
194 yield working_dir
195 finally:
196 os.chdir(original_dir)
197 logger.debug(f"Restored working directory to {original_dir}")
198
199
200class LeafOptics:
201 """
202 High-level interface for PROSPECT leaf optical model.
203
204 This class provides a user-friendly wrapper around the native Helios
205 LeafOptics plugin for computing spectral reflectance and transmittance
206 of plant leaves based on their biochemical properties.
207
208 The PROSPECT model computes spectral optical properties for wavelengths
209 from 400 nm to 2500 nm at 1 nm resolution (2101 data points).
210
211 System requirements:
212 - Cross-platform support (Windows, Linux, macOS)
213 - No GPU required
214 - Requires spectral_data assets (~475KB XML file)
215 - LeafOptics plugin compiled into PyHelios
216
217 Example:
218 >>> from pyhelios import Context, LeafOptics, LeafOpticsProperties
219 >>>
220 >>> with Context() as context:
221 ... with LeafOptics(context) as leafoptics:
222 ... # Get properties for a known species
223 ... props = leafoptics.getPropertiesFromLibrary("sunflower")
224 ... print(f"Sunflower chlorophyll: {props.chlorophyllcontent} ug/cm^2")
225 ...
226 ... # Compute spectra
227 ... wavelengths, reflectance, transmittance = leafoptics.getLeafSpectra(props)
228 ... print(f"Spectral range: {wavelengths[0]}-{wavelengths[-1]} nm")
229 ...
230 ... # Apply to geometry
231 ... leaf_uuid = context.addPatch(center=[0, 0, 1], size=[0.1, 0.1])
232 ... leafoptics.run([leaf_uuid], props, "sunflower_leaf")
233 """
234
235 def __init__(self, context: Context):
236 """
237 Initialize LeafOptics with graceful plugin handling.
238
239 Args:
240 context: Helios Context instance
241
242 Raises:
243 TypeError: If context is not a Context instance
244 LeafOpticsError: If LeafOptics plugin is not available or spectral data missing
245 """
246 # Validate context type - use duck typing to handle import state issues during testing
247 if not (hasattr(context, '__class__') and
248 (isinstance(context, Context) or
249 context.__class__.__name__ == 'Context')):
250 raise TypeError(f"LeafOptics requires a Context instance, got {type(context).__name__}")
251
252 self.context = context
253 self._leafoptics_ptr = None
254
255 # Check plugin availability using registry
256 registry = get_plugin_registry()
257
258 if not registry.is_plugin_available('leafoptics'):
259 # Get helpful information about the missing plugin
260 available_plugins = registry.get_available_plugins()
261
262 error_msg = (
263 "LeafOptics requires the 'leafoptics' plugin which is not available.\n\n"
264 "The LeafOptics plugin implements the PROSPECT leaf optical model which computes:\n"
265 "- Spectral reflectance (400-2500 nm at 1 nm resolution)\n"
266 "- Spectral transmittance\n"
267 "- Based on leaf biochemical properties (chlorophyll, water, dry matter, etc.)\n\n"
268 "Features:\n"
269 "- Cross-platform support (Windows, Linux, macOS)\n"
270 "- No GPU required\n"
271 "- Built-in species library with 12 plant species\n"
272 "- Supports both PROSPECT-D and PROSPECT-PRO modes\n\n"
273 "To enable LeafOptics modeling:\n"
274 "1. Build PyHelios with LeafOptics plugin:\n"
275 " build_scripts/build_helios --plugins leafoptics\n"
276 "2. Or build with radiation plugins for full spectral modeling:\n"
277 " build_scripts/build_helios --plugins leafoptics,radiation\n"
278 f"\nCurrently available plugins: {available_plugins}"
281 raise LeafOpticsError(error_msg)
282
283 # Plugin is available - create LeafOptics with asset-aware working directory
284 try:
286 self._leafoptics_ptr = leafoptics_wrapper.createLeafOptics(context.getNativePtr())
287 if self._leafoptics_ptr is None:
288 raise LeafOpticsError(
289 "Failed to create LeafOptics instance. "
290 "This may indicate a problem with the spectral data files."
291 )
292 logger.info("LeafOptics created successfully")
293
294 except LeafOpticsError:
295 raise
296 except Exception as e:
297 raise LeafOpticsError(f"Failed to initialize LeafOptics: {e}")
298
299 def _check_context_alive(self):
300 """Raise if the owning Context has been destroyed (see Context.check_context_alive)."""
301 check_context_alive(getattr(self, "context", None), "LeafOptics")
302
303 def __enter__(self):
304 """Context manager entry."""
305 return self
306
307 def __exit__(self, exc_type, exc_value, traceback):
308 """Context manager exit with proper cleanup."""
309 if self._leafoptics_ptr is not None:
310 try:
311 leafoptics_wrapper.destroyLeafOptics(self._leafoptics_ptr)
312 logger.debug("LeafOptics destroyed successfully")
313 except Exception as e:
314 logger.warning(f"Error destroying LeafOptics: {e}")
315 finally:
316 self._leafoptics_ptr = None
317
318 def __del__(self):
319 """Destructor to ensure C++ resources freed even without 'with' statement."""
320 if hasattr(self, '_leafoptics_ptr') and self._leafoptics_ptr is not None:
321 try:
322 leafoptics_wrapper.destroyLeafOptics(self._leafoptics_ptr)
323 self._leafoptics_ptr = None
324 except Exception as e:
325 import warnings
326 warnings.warn(f"Error in LeafOptics.__del__: {e}")
327
328 def run(self, UUIDs: List[int], leafproperties: LeafOpticsProperties, label: str) -> None:
329 """
330 Run the LeafOptics model to generate spectra and assign to primitives.
331
332 This method computes reflectance and transmittance spectra based on the given
333 leaf properties, creates global data entries, and assigns them to the specified
334 primitives.
335
336 Args:
337 UUIDs: List of primitive UUIDs to assign spectra to
338 leafproperties: LeafOpticsProperties with biochemical parameters
339 label: Label for the spectra (appended to "leaf_reflectivity_" and "leaf_transmissivity_")
340
341 Raises:
342 ValueError: If parameters are invalid
343 LeafOpticsError: If computation fails
344
345 Example:
346 >>> props = LeafOpticsProperties(chlorophyllcontent=40.0, watermass=0.02)
347 >>> leafoptics.run([leaf_uuid], props, "my_leaf")
348 >>> # Creates: "leaf_reflectivity_my_leaf" and "leaf_transmissivity_my_leaf"
349 """
350 if not UUIDs:
351 raise ValueError("UUIDs list cannot be empty")
352 if not isinstance(leafproperties, LeafOpticsProperties):
353 raise ValueError("leafproperties must be a LeafOpticsProperties instance")
354 if not label:
355 raise ValueError("Label cannot be empty")
356
358 try:
359 leafoptics_wrapper.leafOpticsRun(
360 self._leafoptics_ptr,
361 UUIDs,
362 leafproperties.to_list(),
363 label
364 )
365 except Exception as e:
366 raise LeafOpticsError(f"Failed to run LeafOptics model: {e}")
367
368 def runNoUUIDs(self, leafproperties: LeafOpticsProperties, label: str) -> None:
369 """
370 Run the LeafOptics model without assigning to primitives.
371
372 This method computes reflectance and transmittance spectra based on the given
373 leaf properties and creates global data entries, but does not assign them to
374 any primitives.
375
376 Args:
377 leafproperties: LeafOpticsProperties with biochemical parameters
378 label: Label for the spectra (appended to "leaf_reflectivity_" and "leaf_transmissivity_")
379
380 Raises:
381 ValueError: If parameters are invalid
382 LeafOpticsError: If computation fails
383 """
384 if not isinstance(leafproperties, LeafOpticsProperties):
385 raise ValueError("leafproperties must be a LeafOpticsProperties instance")
386 if not label:
387 raise ValueError("Label cannot be empty")
388
390 try:
391 leafoptics_wrapper.leafOpticsRunNoUUIDs(
392 self._leafoptics_ptr,
393 leafproperties.to_list(),
394 label
395 )
396 except Exception as e:
397 raise LeafOpticsError(f"Failed to run LeafOptics model: {e}")
398
399 def getLeafSpectra(self, leafproperties: LeafOpticsProperties) -> Tuple[List[float], List[float], List[float]]:
400 """
401 Compute leaf reflectance and transmittance spectra.
402
403 This method computes spectral properties without creating global data entries
404 or assigning to primitives.
405
406 Args:
407 leafproperties: LeafOpticsProperties with biochemical parameters
408
409 Returns:
410 Tuple of (wavelengths, reflectivities, transmissivities):
411 - wavelengths: List of wavelengths in nm (400-2500 at 1nm resolution, 2101 points)
412 - reflectivities: List of reflectance values (0-1) at each wavelength
413 - transmissivities: List of transmittance values (0-1) at each wavelength
414
415 Raises:
416 ValueError: If parameters are invalid
417 LeafOpticsError: If computation fails
418
419 Example:
420 >>> props = LeafOpticsProperties(chlorophyllcontent=40.0)
421 >>> wavelengths, refl, trans = leafoptics.getLeafSpectra(props)
422 >>> # Find reflectance at 550 nm (green peak)
423 >>> idx_550 = wavelengths.index(550.0)
424 >>> print(f"Reflectance at 550 nm: {refl[idx_550]:.3f}")
425 """
426 if not isinstance(leafproperties, LeafOpticsProperties):
427 raise ValueError("leafproperties must be a LeafOpticsProperties instance")
428
430 try:
431 return leafoptics_wrapper.leafOpticsGetLeafSpectra(
432 self._leafoptics_ptr,
433 leafproperties.to_list()
434 )
435 except Exception as e:
436 raise LeafOpticsError(f"Failed to get leaf spectra: {e}")
437
438 def setProperties(self, UUIDs: List[int], leafproperties: LeafOpticsProperties) -> None:
439 """
440 Set leaf optical properties for primitives as Context primitive data.
441
442 This assigns the biochemical properties as primitive data using labels:
443 "chlorophyll", "carotenoid", "anthocyanin", "brown", "water", "drymass"
444 (or "protein" + "cellulose" in PROSPECT-PRO mode).
445
446 Args:
447 UUIDs: List of primitive UUIDs
448 leafproperties: LeafOpticsProperties with biochemical parameters
449
450 Raises:
451 ValueError: If parameters are invalid
452 LeafOpticsError: If operation fails
453 """
454 if not UUIDs:
455 raise ValueError("UUIDs list cannot be empty")
456 if not isinstance(leafproperties, LeafOpticsProperties):
457 raise ValueError("leafproperties must be a LeafOpticsProperties instance")
458
460 try:
461 leafoptics_wrapper.leafOpticsSetProperties(
462 self._leafoptics_ptr,
463 UUIDs,
464 leafproperties.to_list()
465 )
466 except Exception as e:
467 raise LeafOpticsError(f"Failed to set properties: {e}")
468
469 def getPropertiesFromSpectrum(self, UUIDs: List[int]) -> None:
470 """
471 Get PROSPECT parameters from reflectivity spectrum for primitives.
472
473 This method retrieves the "reflectivity_spectrum" primitive data for each
474 primitive and checks if it matches a spectrum generated by this LeafOptics
475 instance. If a match is found, the corresponding PROSPECT model parameters
476 are assigned as primitive data.
477
478 Args:
479 UUIDs: List of primitive UUIDs to query
480
481 Note:
482 Primitives without matching spectra are silently skipped.
483 """
484 if not UUIDs:
485 raise ValueError("UUIDs list cannot be empty")
486
488 try:
489 leafoptics_wrapper.leafOpticsGetPropertiesFromSpectrum(
490 self._leafoptics_ptr,
491 UUIDs
492 )
493 except Exception as e:
494 raise LeafOpticsError(f"Failed to get properties from spectrum: {e}")
495
496 def getPropertiesFromLibrary(self, species: str) -> LeafOpticsProperties:
497 """
498 Get leaf optical properties from the built-in species library.
499
500 The library contains PROSPECT-D parameters fitted from the LOPEX93 dataset
501 for common plant species.
502
503 Args:
504 species: Name of the species (case-insensitive). Available species:
505 "default", "garden_lettuce", "alfalfa", "corn", "sunflower",
506 "english_walnut", "rice", "soybean", "wine_grape", "tomato",
507 "common_bean", "cowpea"
508
509 Returns:
510 LeafOpticsProperties populated with the species-specific parameters
511
512 Raises:
513 ValueError: If species name is empty
514
515 Note:
516 If species is not found, default properties are used and a warning is issued.
517
518 Example:
519 >>> props = leafoptics.getPropertiesFromLibrary("sunflower")
520 >>> print(f"Chlorophyll: {props.chlorophyllcontent} ug/cm^2")
521 """
522 if not species:
523 raise ValueError("Species name cannot be empty")
524
526 try:
527 properties_list = leafoptics_wrapper.leafOpticsGetPropertiesFromLibrary(
528 self._leafoptics_ptr,
529 species
530 )
531 return LeafOpticsProperties.from_list(properties_list)
532 except Exception as e:
533 raise LeafOpticsError(f"Failed to get properties from library: {e}")
534
535 def disableMessages(self) -> None:
536 """Disable command-line output messages from LeafOptics."""
538 try:
539 leafoptics_wrapper.leafOpticsDisableMessages(self._leafoptics_ptr)
540 except Exception as e:
541 raise LeafOpticsError(f"Failed to disable messages: {e}")
542
543 def enableMessages(self) -> None:
544 """Enable command-line output messages from LeafOptics."""
546 try:
547 leafoptics_wrapper.leafOpticsEnableMessages(self._leafoptics_ptr)
548 except Exception as e:
549 raise LeafOpticsError(f"Failed to enable messages: {e}")
551 def optionalOutputPrimitiveData(self, label: str) -> None:
552 """
553 Selectively output specific biochemical properties as primitive data.
554
555 By default, LeafOptics writes all biochemical properties to primitive data.
556 Use this method to specify only the properties you need for improved performance.
557
558 Args:
559 label: Biochemical property to output. Valid values:
560 - "chlorophyll": Chlorophyll content
561 - "carotenoid": Carotenoid content
562 - "anthocyanin": Anthocyanin content
563 - "brown": Brown pigment content
564 - "water": Water content
565 - "drymass": Dry mass content
566 - "protein": Protein content
567 - "cellulose": Cellulose content
568
569 Raises:
570 ValueError: If label is empty or invalid
571 LeafOpticsError: If operation fails
572
573 Note:
574 Added in helios-core v1.3.59 for performance optimization when only
575 specific biochemical properties are needed for analysis.
576
577 Example:
578 >>> with LeafOptics(context) as leaf:
579 ... # Only output chlorophyll and water content
580 ... leaf.optionalOutputPrimitiveData("chlorophyll")
581 ... leaf.optionalOutputPrimitiveData("water")
582 ... leaf.run(uuids, properties, "leaf_spectra")
583 """
584 if not label:
585 raise ValueError("Label cannot be empty")
586
587 valid_labels = ["chlorophyll", "carotenoid", "anthocyanin", "brown",
588 "water", "drymass", "protein", "cellulose"]
589 if label not in valid_labels:
590 raise ValueError(f"Invalid label '{label}'. Must be one of: {', '.join(valid_labels)}")
591
593 try:
594 leafoptics_wrapper.leafOpticsOptionalOutputPrimitiveData(self._leafoptics_ptr, label)
595 except Exception as e:
596 raise LeafOpticsError(f"Failed to set optional output for '{label}': {e}")
597
598 @staticmethod
599 def getAvailableSpecies() -> List[str]:
600 """
601 Get list of available species in the built-in library.
602
603 Returns:
604 List of species names that can be used with getPropertiesFromLibrary()
605 """
606 return AVAILABLE_SPECIES.copy()
607
608 @staticmethod
609 def isAvailable() -> bool:
610 """
611 Check if LeafOptics plugin is available in the current build.
613 Returns:
614 True if LeafOptics is available, False otherwise
615 """
616 return leafoptics_wrapper.is_leafoptics_available()
Exception raised for LeafOptics-specific errors.
Definition LeafOptics.py:25
Data class for PROSPECT leaf optical model parameters.
Definition LeafOptics.py:63
float anthocyancontent
Anthocyanin content in micrograms per square cm.
float watermass
Equivalent water thickness in grams per square cm.
float drymass
Dry matter content (leaf mass per area) in grams per square cm.
float numberlayers
Number of mesophyll layers in the leaf (typically 1-3)
float carbonconstituents
Carbon-based constituents in grams per square cm (PROSPECT-PRO mode)
float protein
Protein content in grams per square cm (PROSPECT-PRO mode)
float carotenoidcontent
Carotenoid content in micrograms per square cm.
'LeafOpticsProperties' from_list(cls, List[float] values)
Create LeafOpticsProperties from a list of values.
float brownpigments
Brown pigment content (arbitrary units, typically 0)
float chlorophyllcontent
Chlorophyll a+b content in micrograms per square cm.
List[float] to_list(self)
Convert properties to a list in the order expected by the C++ interface.
float V2Z
Violaxanthin-to-zeaxanthin de-epoxidation state, [0, 1].
float fqe
Intrinsic fluorescence quantum efficiency scalar applied on top of the.
High-level interface for PROSPECT leaf optical model.
None setProperties(self, List[int] UUIDs, LeafOpticsProperties leafproperties)
Set leaf optical properties for primitives as Context primitive data.
__del__(self)
Destructor to ensure C++ resources freed even without 'with' statement.
List[str] getAvailableSpecies()
Get list of available species in the built-in library.
LeafOpticsProperties getPropertiesFromLibrary(self, str species)
Get leaf optical properties from the built-in species library.
__exit__(self, exc_type, exc_value, traceback)
Context manager exit with proper cleanup.
None run(self, List[int] UUIDs, LeafOpticsProperties leafproperties, str label)
Run the LeafOptics model to generate spectra and assign to primitives.
Tuple[List[float], List[float], List[float]] getLeafSpectra(self, LeafOpticsProperties leafproperties)
Compute leaf reflectance and transmittance spectra.
None disableMessages(self)
Disable command-line output messages from LeafOptics.
None optionalOutputPrimitiveData(self, str label)
Selectively output specific biochemical properties as primitive data.
bool isAvailable()
Check if LeafOptics plugin is available in the current build.
None runNoUUIDs(self, LeafOpticsProperties leafproperties, str label)
Run the LeafOptics model without assigning to primitives.
None enableMessages(self)
Enable command-line output messages from LeafOptics.
__enter__(self)
Context manager entry.
None getPropertiesFromSpectrum(self, List[int] UUIDs)
Get PROSPECT parameters from reflectivity spectrum for primitives.
_check_context_alive(self)
Raise if the owning Context has been destroyed (see Context.check_context_alive).
Exception classes for PyHelios library.
Definition exceptions.py:10
_leafoptics_working_directory()
Context manager that temporarily changes working directory to where LeafOptics assets are located.