0.1.33
Loading...
Searching...
No Matches
pyhelios.PlantArchitecture.PlantArchitecture Class Reference

High-level interface for plant architecture modeling and procedural plant generation. More...

Detailed Description

High-level interface for plant architecture modeling and procedural plant generation.

PlantArchitecture provides access to the comprehensive plant library with 25+ plant models including trees (almond, apple, olive, walnut), crops (bean, cowpea, maize, rice, soybean), and other plants. This class enables procedural plant generation, time-based growth simulation, and plant community modeling.

This class requires the native Helios library built with PlantArchitecture support. Use context managers for proper resource cleanup.

Example
>>> with Context() as context: ... with PlantArchitecture(context) as plantarch: ... plantarch.loadPlantModelFromLibrary("bean") ... plant_id = plantarch.buildPlantInstanceFromLibrary(base_position=vec3(0, 0, 0), age=30) ... plantarch.advanceTime(10.0) # Grow for 10 days

Definition at line 281 of file PlantArchitecture.py.

Public Member Functions

 __new__ (cls, context=None)
 Create PlantArchitecture instance.
 
 __init__ (self, Context context)
 Initialize PlantArchitecture with a Helios context.
 
 __enter__ (self)
 Context manager entry.
 
 __exit__ (self, exc_type, exc_val, exc_tb)
 Context manager exit - cleanup resources.
 
 __del__ (self)
 Destructor to ensure C++ resources freed even without 'with' statement.
 
None loadPlantModelFromLibrary (self, str plant_label)
 Load a plant model from the built-in library.
 
int buildPlantInstanceFromLibrary (self, vec3 base_position, float age, Optional[dict] build_parameters=None)
 Build a plant instance from the currently loaded library model.
 
List[int] buildPlantCanopyFromLibrary (self, vec3 canopy_center, vec2 plant_spacing, int2 plant_count, float age, float germination_rate=1.0, Optional[dict] build_parameters=None)
 Build a canopy of regularly spaced plants from the currently loaded library model.
 
None advanceTime (self, float dt, Optional[int] plant_id=None, Optional[List[int]] plant_ids=None, Optional[int] years=None)
 Advance time for plant growth and development.
 
None enableAttractionPoints (self, List[vec3] points, Optional[int] plant_id=None, Optional[float] view_half_angle_deg=None, float look_ahead_distance=0.1, float attraction_weight=0.6)
 Steer shoot growth toward a set of target points.
 
None disableAttractionPoints (self, Optional[int] plant_id=None)
 Stop steering growth toward attraction points.
 
None updateAttractionPoints (self, List[vec3] points, Optional[int] plant_id=None)
 Replace the current attraction point set.
 
None appendAttractionPoints (self, List[vec3] points, Optional[int] plant_id=None)
 Add to the current attraction point set.
 
None setAttractionParameters (self, float view_half_angle_deg, float look_ahead_distance, float attraction_weight, float obstacle_reduction_factor=0.75, Optional[int] plant_id=None)
 Tune how strongly attraction points steer growth.
 
 setProgressCallback (self, callback)
 Set a callback to receive progress updates during long-running operations.
 
 setCancelFlag (self, cancel_flag)
 Register an external cancellation flag polled during long plant builds.
 
 getCurrentShootParameters (self, str shoot_type_label, bool return_typed=False)
 Get current shoot parameters for a shoot type.
 
None defineShootType (self, str shoot_type_label, Union[dict, ShootParameters] parameters)
 Define a custom shoot type with specified parameters.
 
 getDefaultCarbohydrateParameters (self, bool return_typed=False)
 Get a default-constructed set of carbohydrate-model parameters.
 
None setPlantCarbohydrateParameters (self, int plant_id, Union[dict, CarbohydrateParameters] parameters)
 Set carbohydrate-model parameters for a plant.
 
 getDefaultNitrogenParameters (self, bool return_typed=False)
 Get a default-constructed set of nitrogen-model parameters.
 
None setPlantNitrogenParameters (self, int plant_id, Union[dict, NitrogenParameters] parameters)
 Set nitrogen-model parameters for a plant.
 
List[str] getAvailablePlantModels (self)
 Get list of all available plant models in the library.
 
List[str] listShootTypeLabels (self, Optional[str] plant_model=None, Optional[int] plant_id=None)
 Get the shoot type labels defined for a plant model.
 
List[int] getAllUUIDs (self)
 Get UUIDs of every plant primitive in the model.
 
List[int] getAllLeafUUIDs (self)
 Get UUIDs of every leaf primitive in the model.
 
List[int] getAllInternodeUUIDs (self)
 Get UUIDs of every internode primitive in the model.
 
List[int] getAllPetioleUUIDs (self)
 Get UUIDs of every petiole primitive in the model.
 
List[int] getAllPeduncleUUIDs (self)
 Get UUIDs of every peduncle primitive in the model.
 
List[int] getAllFlowerUUIDs (self)
 Get UUIDs of every flower primitive in the model.
 
List[int] getAllFruitUUIDs (self)
 Get UUIDs of every fruit primitive in the model.
 
List[int] getAllObjectIDs (self)
 Get object IDs of every plant compound object in the model.
 
List[int] getAllPlantIDs (self)
 Get IDs of every plant instance in the model.
 
List[int] getAllPlantObjectIDs (self, int plant_id)
 Get all object IDs for a specific plant.
 
List[int] getPlantLeafObjectIDs (self, int plant_id)
 Get object IDs for all leaf objects on a specific plant.
 
List[int] getPlantPetioleObjectIDs (self, int plant_id)
 Get object IDs for all petiole objects on a specific plant.
 
List[int] getPlantPeduncleObjectIDs (self, int plant_id)
 Get object IDs for all peduncle objects on a specific plant.
 
List[int] getPlantFlowerObjectIDs (self, int plant_id)
 Get object IDs for all flower (inflorescence) objects on a specific plant.
 
List[int] getPlantFruitObjectIDs (self, int plant_id)
 Get object IDs for all fruit objects on a specific plant.
 
List[vec3getPlantLeafBases (self, int plant_id)
 Get the attachment base position of every leaf on a specific plant.
 
List[int] getAllPlantUUIDs (self, int plant_id, bool include_hidden=False)
 Get all primitive UUIDs for a specific plant.
 
List[int] getAllShootIDs (self, int plant_id)
 Get the IDs of all shoots belonging to a plant.
 
Dict[str, Any] getShoot (self, int plant_id, int shoot_id)
 Get a read-only view of a shoot's topology.
 
List[int] getShootChildIDs (self, int plant_id, int shoot_id)
 Get the child shoot IDs of a shoot (flattened across parent node indices).
 
int getParentShootID (self, int plant_id, int shoot_id)
 Get the ID of the shoot a shoot grew from.
 
int getShootRank (self, int plant_id, int shoot_id)
 Get the branching rank of a shoot.
 
int getShootDepth (self, int plant_id, int shoot_id)
 Get the number of shoots between a shoot and the base stem shoot.
 
bool isShootPruned (self, int plant_id, int shoot_id)
 Report whether a shoot has been pruned away entirely.
 
List[int] getPathToRoot (self, int plant_id, int shoot_id)
 Get the chain of shoots connecting a shoot to the base stem shoot.
 
List[int] getChildShootIDs (self, int plant_id, int shoot_id)
 Get the shoots that grew directly out of a shoot.
 
List[int] getAllDescendantShootIDs (self, int plant_id, int shoot_id)
 Get every shoot descending from a shoot.
 
Dict[int, List[int]] getShootHierarchyMap (self, int plant_id)
 Get the parent-to-children structure of a plant.
 
List[tuple] getShootInternodeVertices (self, int plant_id, int shoot_id)
 Get the woody internode polyline vertices of a shoot as a list of (x, y, z) tuples.
 
List[float] getShootInternodeRadii (self, int plant_id, int shoot_id)
 Get the per-vertex woody internode radii of a shoot.
 
List[float] getPlantLeafAreas (self, int plant_id)
 Get the built one-sided surface area of every leaf on a plant.
 
List[float] getPlantInternodeLengths (self, int plant_id)
 Get the built length of every internode on a plant.
 
List[float] getPlantLeafInclinations (self, int plant_id)
 Get the inclination angle of every leaf on a plant.
 
bool isShootGeometryPrescribed (self, int plant_id, int shoot_id)
 Report whether a shoot's existing geometry was prescribed by the caller rather than generated.
 
float getPlantAge (self, int plant_id)
 Get the current age of a plant in days.
 
float getPlantMaxAge (self, int plant_id)
 Get the maximum age of a plant, beyond which it stops growing.
 
None setPlantMaxAge (self, int plant_id, float max_age)
 Set the maximum age of a plant, beyond which it stops growing.
 
float getPlantHeight (self, int plant_id)
 Get the height of a plant in meters.
 
float getPlantLeafArea (self, int plant_id)
 Get the total leaf area of a plant in m².
 
None optionalOutputObjectData (self, Union[str, List[str]] object_data_labels)
 Enable optional output object data to be written to the Context.
 
None setPlantPhenologicalThresholds (self, int plant_id, float time_to_dormancy_break, float time_to_flower_initiation, float time_to_flower_opening, float time_to_fruit_set, float time_to_fruit_maturity, float time_to_dormancy, float max_leaf_lifespan=1e6, bool is_evergreen=False)
 Set phenological timing thresholds for plant developmental stages.
 
None disablePlantPhenology (self, int plant_id)
 Disable phenological progression for a plant.
 
None makePlantDormant (self, int plant_id)
 Force a plant into a dormant state immediately.
 
None breakPlantDormancy (self, int plant_id)
 Break dormancy for all shoots on a plant, returning it to an active state.
 
bool isPlantDormant (self, int plant_id)
 Check whether a plant is dormant.
 
None pruneBranch (self, int plant_id, int shoot_id, int node_index)
 Prune a shoot at a node, removing that node and everything distal to it.
 
None harvestPlant (self, int plant_id)
 Harvest a plant by removing its flowers and fruit.
 
None removePlantLeaves (self, int plant_id)
 Remove all leaves from every shoot on a plant.
 
None removeShootLeaves (self, int plant_id, int shoot_id)
 Remove all leaves from a single shoot.
 
None removeShootVegetativeBuds (self, int plant_id, int shoot_id)
 Mark every vegetative bud on a single shoot as dead.
 
None removeShootFloralBuds (self, int plant_id, int shoot_id)
 Kill all floral buds on a single shoot.
 
Dict[int, List[int]] getShootIDsByRank (self, int plant_id)
 Group a plant's shoot IDs by branching rank.
 
List[int] getTerminalShootIDs (self, int plant_id)
 Get the plant's terminal shoots – those carrying no child shoots.
 
List[int] pruneShootsByRank (self, int plant_id, int min_rank)
 Prune every shoot at or above a given branching rank.
 
List[int] pruneShootSubtree (self, int plant_id, int shoot_id, bool include_self=True)
 Prune a shoot and everything growing off it.
 
List[int] pruneTerminalShoots (self, int plant_id, int stride=2)
 Thin a plant by pruning every stride-th terminal shoot.
 
None enableSoftCollisionAvoidance (self, Optional[List[int]] target_object_UUIDs=None, Optional[List[int]] target_object_IDs=None, bool enable_petiole_collision=False, bool enable_fruit_collision=False)
 Enable soft collision avoidance for procedural plant growth.
 
None enableGroundClipping (self, float ground_height=0.0)
 Enable automatic removal of plant organs that fall below the ground plane.
 
None disableMessages (self)
 Suppress standard output from the plantarchitecture plugin.
 
None enableMessages (self)
 Re-enable standard output from the plantarchitecture plugin.
 
None disableCollisionDetection (self)
 Disable collision detection for plant growth.
 
None setSoftCollisionAvoidanceParameters (self, float view_half_angle_deg=80.0, float look_ahead_distance=0.1, int sample_count=256, float inertia_weight=0.4)
 Configure parameters for soft collision avoidance algorithm.
 
None setCollisionRelevantOrgans (self, bool include_internodes=False, bool include_leaves=True, bool include_petioles=False, bool include_flowers=False, bool include_fruit=False)
 Specify which plant organs participate in collision detection.
 
None enableSolidObstacleAvoidance (self, List[int] obstacle_UUIDs, float avoidance_distance=0.5, bool enable_fruit_adjustment=False, bool enable_obstacle_pruning=False)
 Enable hard obstacle avoidance for specified geometry.
 
None setStaticObstacles (self, List[int] target_UUIDs)
 Mark geometry as static obstacles for collision detection optimization.
 
List[int] getPlantCollisionRelevantObjectIDs (self, int plant_id)
 Get object IDs of collision-relevant geometry for a specific plant.
 
None writePlantMeshVertices (self, int plant_id, Union[str, Path] filename)
 Write all plant mesh vertices to file for external processing.
 
None writePlantStructureXML (self, int plant_id, Union[str, Path] filename)
 Save plant structure to XML file for later loading.
 
None writeQSMCylinderFile (self, int plant_id, Union[str, Path] filename)
 Export plant structure in TreeQSM cylinder format.
 
None writePlantStructureUSD (self, int plant_id, Union[str, Path] filename, float elastic_modulus=5e9, float wood_density=800.0, float damping_ratio=0.1, float static_friction=0.5, float dynamic_friction=0.3, float restitution=0.1, float organ_spring_stiffness=10.0, float organ_spring_damping=1.0, float leaf_mass_per_area=0.05, float fruit_mass=0.01, float flower_mass=0.002, int solver_position_iterations=32, float min_segment_length=0.001)
 Export plant structure as a USD articulated rigid body for NVIDIA IsaacSim physics.
 
None registerGrowthFrame (self, int plant_id, float min_segment_length=0.001)
 Capture a snapshot of the plant's geometry as a growth animation frame.
 
None writePlantGrowthUSD (self, int plant_id, Union[str, Path] filename, float seconds_per_frame=1.0)
 Export all registered growth frames as a time-sampled USD animation file.
 
None clearGrowthFrames (self, int plant_id)
 Clear stored growth animation frames for a plant.
 
int getGrowthFrameCount (self, int plant_id)
 Get the number of registered growth frames for a plant.
 
List[int] readPlantStructureXML (self, Union[str, Path] filename, bool quiet=False)
 Load plant structure from XML file.
 
int addPlantInstance (self, vec3 base_position, float current_age)
 Create an empty plant instance for custom plant building.
 
None deletePlantInstance (self, int plant_id)
 Delete a plant instance and all associated geometry.
 
int addBaseStemShoot (self, int plant_id, int current_node_number, AxisRotation base_rotation, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, float radius_taper, str shoot_type_label)
 Add a base stem shoot to a plant instance (main trunk/stem).
 
int appendShoot (self, int plant_id, int parent_shoot_id, int current_node_number, AxisRotation base_rotation, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, float radius_taper, str shoot_type_label)
 Append a shoot to the end of an existing shoot.
 
int addChildShoot (self, int plant_id, int parent_shoot_id, int parent_node_index, int current_node_number, AxisRotation shoot_base_rotation, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, float radius_taper, str shoot_type_label, int petiole_index=0)
 Add a child shoot at an axillary bud position on a parent shoot.
 
int addShootFromNodePositions (self, int plant_id, int parent_shoot_id, int parent_node_index, List[vec3] node_positions, List[float] node_radii, str shoot_type_label, Optional[str] growth_shoot_type_label=None, int petiole_index=0)
 Add a shoot whose internode geometry is prescribed by measured node positions.
 
None setPetioleNodePositions (self, int plant_id, int shoot_id, int node_index, int petiole_index, List[vec3] node_positions, List[float] node_radii)
 Prescribe the path of a petiole on an existing phytomer from measured node positions.
 
None setPetioleLeafGeometry (self, int plant_id, int shoot_id, int node_index, int petiole_index, List[vec3] leaf_bases, List[AxisRotation] leaf_rotations, List[float] leaf_sizes)
 Prescribe the base position, orientation and size of every leaf on a petiole.
 
None setPetioleLeafCount (self, int plant_id, int shoot_id, int node_index, int petiole_index, int leaf_count)
 Change the number of leaves (leaflets) on one petiole of an existing phytomer.
 
None setShootInternodeLengthMax (self, int plant_id, int shoot_id, float internode_length_max)
 Set the target length of internodes grown at the apex of an existing shoot.
 
None terminateApicalBud (self, int plant_id, int shoot_id)
 Stop a shoot's apex from adding any further phytomers.
 
int getShootVegetativeBudCount (self, int plant_id, int shoot_id, Optional[BudState] state=None)
 Count a shoot's axillary vegetative buds, summed over all phytomers and petioles.
 
int getPlantLeafCount (self, int plant_id)
 Get the number of leaf objects on a plant.
 
None enableLeafAngleDistributionTracking (self, plant_ids, float beta_mu_inclination, float beta_nu_inclination, float eccentricity, float ellipse_rotation_degrees, float lambda_degrees)
 Steer leaf inclination and azimuth toward a prescribed distribution as the plant grows.
 
None enableLeafElevationAngleDistributionTracking (self, int plant_id, float beta_mu_inclination, float beta_nu_inclination, float lambda_degrees)
 Steer leaf inclination toward a Beta distribution as the plant grows, leaving azimuth to the procedural model.
 
None enableLeafAzimuthAngleDistributionTracking (self, int plant_id, float eccentricity, float ellipse_rotation_degrees, float lambda_degrees)
 Steer leaf azimuth toward an ellipsoidal distribution as the plant grows, leaving inclination to the procedural model.
 
None disableLeafAngleDistributionTracking (self, int plant_id)
 Stop steering a plant's leaf angles toward a prescribed distribution.
 
bool isLeafAngleDistributionTrackingEnabled (self, int plant_id)
 Whether a plant's leaf angles are being steered toward a prescribed distribution.
 
float getPetioleLength (self, int plant_id, int shoot_id, int node_index, Optional[int] petiole_index=None)
 Current length of a phytomer's petioles, measured along the centerline.
 
None scalePetioleMaxLength (self, int plant_id, int shoot_id, int node_index, float scale_factor)
 Scale the fully-elongated length every petiole on a phytomer is growing toward.
 
None setPetioleScaleFraction (self, int plant_id, int shoot_id, int node_index, int petiole_index, float petiole_scale_factor_fraction)
 Set one petiole's current length as a fraction of its fully-elongated length, leaving the leaves it carries at the size they are.
 
None setPetioleAndLeafScaleFraction (self, int plant_id, int shoot_id, int node_index, int petiole_index, float petiole_scale_factor_fraction, float leaf_scale_factor_fraction)
 Set a petiole's length and its leaves' size together, each as a fraction of its own fully-elongated value.
 
None scaleLeafSizeMax (self, int plant_id, int shoot_id, int node_index, float scale_factor)
 Scale the size every leaf on a phytomer is expanding toward, leaving the blades where they are.
 
None setLeafNormal (self, int plant_id, int shoot_id, int node_index, int petiole_index, int leaf_index, vec3 target_normal)
 Re-aim one leaf so its blade faces a given direction.
 
None bendPetioleUnderLeafWeight (self, int plant_id, int shoot_id, int node_index, int petiole_index)
 Bend one petiole, and the leaves it carries, under the weight of its leaflets.
 
None recordPetioleRestShape (self, int plant_id, int shoot_id, int node_index, int petiole_index)
 Record one petiole's current centerline as its undeformed rest shape.
 
bool is_available (self)
 Check if PlantArchitecture is available in current build.
 

Public Attributes

 context = context
 

Protected Member Functions

 _check_context_alive (self)
 Raise if the owning Context has been destroyed (see Context.check_context_alive).
 
 _shootScalarQuery (self, str wrapper_fn_name, int plant_id, int shoot_id, str description)
 Shared body for the per-shoot hierarchy accessors.
 
List[float] _plantFloatVector (self, str wrapper_fn_name, int plant_id, str description)
 Shared body for the per-organ built-geometry queries.
 
None _removeShootOrgans (self, str wrapper_fn_name, int plant_id, int shoot_id, str organ_description)
 Shared body for the three shoot-level organ removal methods.
 
List[int] _childShootIDsOrEmpty (self, int plant_id, int shoot_id)
 Return a shoot's child IDs, or an empty list if it no longer resolves.
 
List[int] _liveChildShootIDs (self, int plant_id, int shoot_id)
 Child shoot IDs that have not been pruned away, ascending.
 
List[int] _pruneShallowest (self, int plant_id, target_shoot_ids)
 Prune every target that something shallower has not already removed.
 
bool _isPrunedOrGone (self, int plant_id, int shoot_id)
 Whether a shoot has been pruned away or no longer resolves at all.
 
List[int] _validatePlantIdList (cls, plant_ids)
 Coerce a sequence of plant IDs, rejecting an empty or malformed one.
 
int _validatePetioleIndex (cls, petiole_index, str name="Petiole index")
 Reject a non-int or negative petiole/leaf index.
 

Static Protected Member Functions

None _validate_attraction_points (points)
 Reject point sets the native layer would misread or silently ignore.
 
 _validateNodesAndRadii (node_positions, node_radii, str positions_name, str radii_name)
 Validate a measured node path and return it as plain lists for the ctypes layer.
 
None _validateShootIdentifiers (int plant_id, int shoot_id)
 Reject non-int and negative plant/shoot identifiers.
 
BudState _validateBudState (state)
 Coerce a BudState (or its int value) and reject anything else.
 
int _validatePlantIdentifier (plant_id)
 Reject a non-int or negative plant ID, returning it as a plain int.
 
int _validateNodeIndex (node_index, str name="Node index")
 Reject a non-int or negative phytomer index.
 
float _validateScaleFactor (scale_factor, str name="Scale factor")
 Reject a non-numeric or non-positive scale factor.
 

Protected Attributes

 _plantarch_ptr = None
 
 _current_plant_model = None
 
 _progress_callback_ref = plantarch_wrapper.PROGRESS_CALLBACK(_c_callback)
 

Constructor & Destructor Documentation

◆ __init__()

pyhelios.PlantArchitecture.PlantArchitecture.__init__ ( self,
Context context )

Initialize PlantArchitecture with a Helios context.

Parameters
contextActive Helios Context instance
Exceptions
PlantArchitectureErrorIf plugin not available in current build
RuntimeErrorIf plugin initialization fails

Definition at line 300 of file PlantArchitecture.py.

◆ __del__()

pyhelios.PlantArchitecture.PlantArchitecture.__del__ ( self)

Destructor to ensure C++ resources freed even without 'with' statement.

Definition at line 348 of file PlantArchitecture.py.

Member Function Documentation

◆ __enter__()

pyhelios.PlantArchitecture.PlantArchitecture.__enter__ ( self)

Context manager entry.

Definition at line 338 of file PlantArchitecture.py.

◆ __exit__()

pyhelios.PlantArchitecture.PlantArchitecture.__exit__ ( self,
exc_type,
exc_val,
exc_tb )

Context manager exit - cleanup resources.

Definition at line 342 of file PlantArchitecture.py.

◆ __new__()

pyhelios.PlantArchitecture.PlantArchitecture.__new__ ( cls,
context = None )

Create PlantArchitecture instance.

Explicit new to prevent ctypes contamination on Windows.

Definition at line 287 of file PlantArchitecture.py.

◆ _check_context_alive()

pyhelios.PlantArchitecture.PlantArchitecture._check_context_alive ( self)
protected

Raise if the owning Context has been destroyed (see Context.check_context_alive).

Definition at line 334 of file PlantArchitecture.py.

◆ _childShootIDsOrEmpty()

List[int] pyhelios.PlantArchitecture.PlantArchitecture._childShootIDsOrEmpty ( self,
int plant_id,
int shoot_id )
protected

Return a shoot's child IDs, or an empty list if it no longer resolves.

Definition at line 2719 of file PlantArchitecture.py.

◆ _isPrunedOrGone()

bool pyhelios.PlantArchitecture.PlantArchitecture._isPrunedOrGone ( self,
int plant_id,
int shoot_id )
protected

Whether a shoot has been pruned away or no longer resolves at all.

Definition at line 2756 of file PlantArchitecture.py.

◆ _liveChildShootIDs()

List[int] pyhelios.PlantArchitecture.PlantArchitecture._liveChildShootIDs ( self,
int plant_id,
int shoot_id )
protected

Child shoot IDs that have not been pruned away, ascending.

Definition at line 2728 of file PlantArchitecture.py.

◆ _plantFloatVector()

List[float] pyhelios.PlantArchitecture.PlantArchitecture._plantFloatVector ( self,
str wrapper_fn_name,
int plant_id,
str description )
protected

Shared body for the per-organ built-geometry queries.

Definition at line 1822 of file PlantArchitecture.py.

◆ _pruneShallowest()

List[int] pyhelios.PlantArchitecture.PlantArchitecture._pruneShallowest ( self,
int plant_id,
target_shoot_ids )
protected

Prune every target that something shallower has not already removed.

   pruneBranch() recurses into child shoots, so cutting a shoot also empties
   every shoot descended from it. Targets are therefore visited in ascending
   shoot ID order -- a child shoot is always created after its parent and so
   always has the higher ID -- which puts each shoot after its ancestors. By
   the time a descendant of an already-cut shoot comes up it has nothing left
   on it and is skipped, so no shoot is cut twice and the returned list holds
   only the cuts that actually did something.

Definition at line 2744 of file PlantArchitecture.py.

◆ _removeShootOrgans()

None pyhelios.PlantArchitecture.PlantArchitecture._removeShootOrgans ( self,
str wrapper_fn_name,
int plant_id,
int shoot_id,
str organ_description )
protected

Shared body for the three shoot-level organ removal methods.

Definition at line 2521 of file PlantArchitecture.py.

◆ _shootScalarQuery()

pyhelios.PlantArchitecture.PlantArchitecture._shootScalarQuery ( self,
str wrapper_fn_name,
int plant_id,
int shoot_id,
str description )
protected

Shared body for the per-shoot hierarchy accessors.

Definition at line 1781 of file PlantArchitecture.py.

◆ _validate_attraction_points()

None pyhelios.PlantArchitecture.PlantArchitecture._validate_attraction_points ( points)
staticprotected

Reject point sets the native layer would misread or silently ignore.

Definition at line 753 of file PlantArchitecture.py.

◆ _validateBudState()

BudState pyhelios.PlantArchitecture.PlantArchitecture._validateBudState ( state)
staticprotected

Coerce a BudState (or its int value) and reject anything else.

   A bare int is accepted because BudState is an IntEnum, but it still has to name a
real    an out-of-range value would be cast onto the C++ enum, which is
   undefined behavior.

Definition at line 4439 of file PlantArchitecture.py.

◆ _validateNodeIndex()

int pyhelios.PlantArchitecture.PlantArchitecture._validateNodeIndex ( node_index,
str name = "Node index" )
staticprotected

Reject a non-int or negative phytomer index.

Definition at line 4982 of file PlantArchitecture.py.

◆ _validateNodesAndRadii()

pyhelios.PlantArchitecture.PlantArchitecture._validateNodesAndRadii ( node_positions,
node_radii,
str positions_name,
str radii_name )
staticprotected

Validate a measured node path and return it as plain lists for the ctypes layer.

Definition at line 3902 of file PlantArchitecture.py.

◆ _validatePetioleIndex()

int pyhelios.PlantArchitecture.PlantArchitecture._validatePetioleIndex ( cls,
petiole_index,
str name = "Petiole index" )
protected

Reject a non-int or negative petiole/leaf index.

Definition at line 4994 of file PlantArchitecture.py.

◆ _validatePlantIdentifier()

int pyhelios.PlantArchitecture.PlantArchitecture._validatePlantIdentifier ( plant_id)
staticprotected

Reject a non-int or negative plant ID, returning it as a plain int.

Definition at line 4956 of file PlantArchitecture.py.

◆ _validatePlantIdList()

List[int] pyhelios.PlantArchitecture.PlantArchitecture._validatePlantIdList ( cls,
plant_ids )
protected

Coerce a sequence of plant IDs, rejecting an empty or malformed one.

Definition at line 4968 of file PlantArchitecture.py.

◆ _validateScaleFactor()

float pyhelios.PlantArchitecture.PlantArchitecture._validateScaleFactor ( scale_factor,
str name = "Scale factor" )
staticprotected

Reject a non-numeric or non-positive scale factor.

Definition at line 5001 of file PlantArchitecture.py.

◆ _validateShootIdentifiers()

None pyhelios.PlantArchitecture.PlantArchitecture._validateShootIdentifiers ( int plant_id,
int shoot_id )
staticprotected

Reject non-int and negative plant/shoot identifiers.

   bool is excluded explicitly: it is an int subclass, so True would otherwise pass
   as shoot 1.

Definition at line 4422 of file PlantArchitecture.py.

◆ addBaseStemShoot()

int pyhelios.PlantArchitecture.PlantArchitecture.addBaseStemShoot ( self,
int plant_id,
int current_node_number,
AxisRotation base_rotation,
float internode_radius,
float internode_length_max,
float internode_length_scale_factor_fraction,
float leaf_scale_factor_fraction,
float radius_taper,
str shoot_type_label )

Add a base stem shoot to a plant instance (main trunk/stem).

   This method creates the primary shoot originating from the plant base. The base stem
   is typically the main trunk or primary stem from which all other shoots branch.
   Specify growth parameters to control the shoot's morphology and development.

   **IMPORTANT - Shoot Type Requirement**: Shoot types must be defined before use. The standard
   workflow is to load a plant model first using loadPlantModelFromLibrary(), which defines
   shoot types that can then be used for custom building. The shoot_type_label must match a
   shoot type defined in the loaded model.
Parameters
plant_idID of the plant instance
current_node_numberStarting node number for this shoot (typically 1)
base_rotationOrientation as AxisRotation(pitch, yaw, roll) in radians (use math.radians() to convert)
internode_radiusBase radius of internodes in meters (must be > 0)
internode_length_maxMaximum internode length in meters (must be > 0)
internode_length_scale_factor_fractionScale factor for internode length (0-1 typically)
leaf_scale_factor_fractionScale factor for leaf size (0-1 typically)
radius_taperRate of radius decrease along shoot (0-1, where 1=no taper)
shoot_type_labelLabel identifying shoot type - must match a type from loaded model
Returns
Shoot ID for the created shoot
Exceptions
ValueErrorIf parameters are invalid (negative IDs, non-positive dimensions, empty label)
PlantArchitectureErrorIf shoot creation fails or shoot type doesn't exist
Example
>>> from pyhelios.types import vec3, AxisRotation >>> >>> # REQUIRED: Load a plant model to define shoot types >>> plantarch.loadPlantModelFromLibrary("bean") >>> >>> # Create empty plant for custom building >>> plant_id = plantarch.addPlantInstance(vec3(0, 0, 0), 0.0) >>> >>> # Add base stem using a shoot type from the loaded model. Labels are >>> # species-specific: bean defines "unifoliate"/"trifoliate", almond >>> # defines "trunk"/"scaffold"/"proleptic"/"sylleptic". There is no >>> # generic "stem" type. >>> shoot_id = plantarch.addBaseStemShoot( ... plant_id=plant_id, ... current_node_number=1, ... base_rotation=AxisRotation(0, 0, 0), # Upright ... internode_radius=0.01, # 1cm radius ... internode_length_max=0.1, # 10cm max length ... internode_length_scale_factor_fraction=1.0, ... leaf_scale_factor_fraction=1.0, ... radius_taper=0.9, # Gradual taper ... shoot_type_label="trifoliate" # Must match loaded model ... )

Definition at line 3642 of file PlantArchitecture.py.

◆ addChildShoot()

int pyhelios.PlantArchitecture.PlantArchitecture.addChildShoot ( self,
int plant_id,
int parent_shoot_id,
int parent_node_index,
int current_node_number,
AxisRotation shoot_base_rotation,
float internode_radius,
float internode_length_max,
float internode_length_scale_factor_fraction,
float leaf_scale_factor_fraction,
float radius_taper,
str shoot_type_label,
int petiole_index = 0 )

Add a child shoot at an axillary bud position on a parent shoot.

   This method creates a lateral branch shoot emerging from a specific node on the
   parent shoot. Child shoots enable creation of branching architectures, with control
   over branch angle, size, and which petiole position the branch emerges from (for
   plants with multiple petioles per node).

   **IMPORTANT - Shoot Type Requirement**: The shoot_type_label must match a shoot type
   defined in a loaded plant model. Load a model with loadPlantModelFromLibrary() before
   calling this method.
Parameters
plant_idID of the plant instance
parent_shoot_idID of the parent shoot
parent_node_indexIndex of the parent node where child emerges (0-based)
current_node_numberStarting node number for this child shoot
shoot_base_rotationOrientation as AxisRotation(pitch, yaw, roll) in radians (use math.radians() to convert)
internode_radiusBase radius of child shoot internodes in meters (must be > 0)
internode_length_maxMaximum internode length in meters (must be > 0)
internode_length_scale_factor_fractionScale factor for internode length (0-1 typically)
leaf_scale_factor_fractionScale factor for leaf size (0-1 typically)
radius_taperRate of radius decrease along shoot (0-1, where 1=no taper)
shoot_type_labelLabel identifying shoot type - must match loaded model
petiole_indexWhich petiole at the node to branch from (default: 0)
Returns
Shoot ID for the created child shoot
Exceptions
ValueErrorIf parameters are invalid (negative values, non-positive dimensions, empty label)
PlantArchitectureErrorIf child shoot creation fails, parent doesn't exist, or shoot type not defined
Example
>>> import math >>> # Load model to define shoot types >>> plantarch.loadPlantModelFromLibrary("bean") >>> >>> # Add lateral branch at 45-degree angle from node 3 >>> branch_id = plantarch.addChildShoot( ... plant_id=plant_id, ... parent_shoot_id=main_shoot_id, ... parent_node_index=3, ... current_node_number=1, ... shoot_base_rotation=AxisRotation(math.radians(45), math.radians(90), 0), # 45° out, 90° around ... internode_radius=0.005, # Thinner than main stem ... internode_length_max=0.06, # Shorter internodes ... internode_length_scale_factor_fraction=1.0, ... leaf_scale_factor_fraction=0.9, ... radius_taper=0.8, ... shoot_type_label="trifoliate" ... ) >>> >>> # Add second branch from opposite petiole >>> branch_id2 = plantarch.addChildShoot( ... plant_id, main_shoot_id, 3, 1, AxisRotation(math.radians(45), math.radians(270), 0), ... 0.005, 0.06, 1.0, 0.9, 0.8, "trifoliate", petiole_index=1 ... )

Definition at line 3840 of file PlantArchitecture.py.

◆ addPlantInstance()

int pyhelios.PlantArchitecture.PlantArchitecture.addPlantInstance ( self,
vec3 base_position,
float current_age )

Create an empty plant instance for custom plant building.

   This method creates a new plant instance at the specified location without any
   shoots or organs. Use addBaseStemShoot(), appendShoot(), and addChildShoot() to
   manually construct the plant structure. This provides low-level control over
   plant architecture, enabling custom morphologies not available in the plant library.
Parameters
base_positionCartesian (x,y,z) coordinates of plant base as vec3
current_ageCurrent age of the plant in days (must be >= 0)
Returns
Plant ID for the created plant instance
Exceptions
ValueErrorIf age is negative
PlantArchitectureErrorIf plant creation fails
Example
>>> # Create empty plant at origin >>> plant_id = plantarch.addPlantInstance(vec3(0, 0, 0), 0.0) >>> >>> # Now add shoots to build custom plant structure >>> shoot_id = plantarch.addBaseStemShoot( ... plant_id, 1, AxisRotation(0, 0, 0), 0.01, 0.1, 1.0, 1.0, 0.8, "mainstem" ... )

Definition at line 3533 of file PlantArchitecture.py.

◆ addShootFromNodePositions()

int pyhelios.PlantArchitecture.PlantArchitecture.addShootFromNodePositions ( self,
int plant_id,
int parent_shoot_id,
int parent_node_index,
List[vec3] node_positions,
List[float] node_radii,
str shoot_type_label,
Optional[str] growth_shoot_type_label = None,
int petiole_index = 0 )

Add a shoot whose internode geometry is prescribed by measured node positions.

   This builds a single shoot, rendered as one continuous internode tube, that
   follows a path given by the caller rather than one generated from the shoot
   type's curvature and tortuosity parameters. It is intended for reconstructing a
   plant from measured geometry such as a QSM, a digitized skeleton or
   photogrammetry. A shoot built through :meth:`addBaseStemShoot`,
   :meth:`appendShoot` or :meth:`addChildShoot` is an extrapolation from its base
   rotation and cannot follow a measured curve; approximating one by chaining many
   short shoots produces a separate tube object per link, which leaves visible gaps
   at every bend.

   The supplied positions are the phytomer endpoints: N+1 positions define N
   internodes and therefore N phytomers. The shoot type's ``internode.length_segments``
   still controls how finely each internode is subdivided, with the intermediate
   nodes interpolated along the straight segment between the two prescribed
   endpoints. The caller controls internode length by choosing how many nodes to
   supply.

   The prescribed phytomers are created fully elongated and are therefore not
   re-scaled or re-curved by subsequent calls to :meth:`advanceTime`. New phytomers
   added at the shoot apex as the plant grows are generated normally, continuing from
   the direction of the final prescribed internode, and use the mean of the
   prescribed internode lengths as their target length. Prescribed radii act as a
lower   a shoot type with a non-zero ``girth_area_factor`` may thicken an
   internode during growth but never thins one, so a girth area factor of zero
   preserves the prescribed radii exactly.

   When ``parent_shoot_id`` is non-negative the base of the shoot is seated on the
   parent as :meth:`addChildShoot` does (offset from the attachment node to the
   surface of the parent internode) and the whole path is translated onto that
   point. All relative geometry is preserved; only the absolute position changes,
   and an error is raised if the discrepancy is large enough that the shoot would
   not be connected to its parent.

   **Separate growth type.** Building measured wood calls for curvature and
   tortuosity of zero so the measured path is not fought, a node cap at least as
   large as the longest measured branch, and often a girth area factor of zero so
   the measured radii are preserved. None of those describe how the plant should
grow    a shoot inheriting them extends perfectly straight and never reaches its
   node cap. Pass ``growth_shoot_type_label`` to take the node caps, the gravitropic
   curvature of phytomers added at the apex, and the type of the shoots this shoot's
   vegetative buds produce from a different shoot type. ``girth_area_factor`` and
   bud-break probability are deliberately still taken from the build type, and the
   build type remains the label reported by the shoot. A measured branch longer
   than the growth type's ``max_nodes`` is accepted and simply stops extending.

   Requires helios-core v1.3.85 or newer.
Parameters
plant_idID of the plant instance
parent_shoot_idID of the shoot to attach to, or -1 to create a base stem shoot at the start of a new plant
parent_node_indexNode of the parent shoot at which the new shoot is added. Ignored when parent_shoot_id is -1
node_positionsInternode node positions in world coordinates, ordered from the base of the shoot to its tip. At least two are required, and no two consecutive positions may be coincident
node_radiiRadius of the shoot at each node, one per position. All must be > 0
shoot_type_labelShoot type whose parameters build the measured geometry. Must already be defined (by :meth:loadPlantModelFromLibrary or :meth:defineShootType)
growth_shoot_type_labelOptional shoot type whose parameters govern the shoot's future growth. None grows the shoot with shoot_type_label
petiole_indexPetiole within the parent node to attach to (default 0)
Returns
ID of the newly created shoot
Exceptions
ValueErrorIf any ID is out of range, a position is not a vec3, a radius is not positive, fewer than two nodes are given, or the counts differ
PlantArchitectureErrorIf the native build fails (undefined shoot type, coincident consecutive nodes, base too far from the parent, ...) or the library predates v1.3.85
Note
Like every other manually added shoot, the new shoot is created dormant. Call :meth:breakPlantDormancy before :meth:advanceTime if it is to grow.
Example
>>> plantarch.loadPlantModelFromLibrary("bean") >>> plant_id = plantarch.addPlantInstance(vec3(0, 0, 0), 0.0) >>> path = [vec3(0, 0, 0), vec3(0.01, 0, 0.1), vec3(0.03, 0.01, 0.2), vec3(0.04, 0.01, 0.3)] >>> radii = [0.006, 0.005, 0.004, 0.003] >>> stem = plantarch.addShootFromNodePositions(plant_id, -1, 0, path, radii, "unifoliate") >>> assert plantarch.isShootGeometryPrescribed(plant_id, stem)

Definition at line 4016 of file PlantArchitecture.py.

◆ advanceTime()

None pyhelios.PlantArchitecture.PlantArchitecture.advanceTime ( self,
float dt,
Optional[int] plant_id = None,
Optional[List[int]] plant_ids = None,
Optional[int] years = None )

Advance time for plant growth and development.

   Updates plants in the simulation, potentially adding new phytomers, growing
   existing organs, transitioning phenological stages, and updating plant geometry.

   By default every plant advances together. Pass plant_id or plant_ids to advance a
   subset, which is what staggered planting dates and mixed-age stands require.
Parameters
dtTime step to advance in days (must be >= 0)
plant_idAdvance only this plant. Mutually exclusive with plant_ids.
plant_idsAdvance only these plants. Mutually exclusive with plant_id.
yearsAdvance this many whole years in addition to dt days. Applies to all plants and cannot be combined with plant_id or plant_ids.
Exceptions
ValueErrorIf dt or years is negative, or selectors are combined
PlantArchitectureErrorIf time advancement fails
Note
Large time steps are more efficient than many small steps. The timestep value can be larger than the phyllochron, allowing multiple phytomers to be produced in a single call.
Example
>>> plantarch.advanceTime(10.0) # all plants, 10 days >>> plantarch.advanceTime(10.0, plant_id=early) # one plant only >>> plantarch.advanceTime(10.0, plant_ids=[a, b]) # a subset >>> plantarch.advanceTime(0.0, years=4) # all plants, 4 years

Definition at line 566 of file PlantArchitecture.py.

◆ appendAttractionPoints()

None pyhelios.PlantArchitecture.PlantArchitecture.appendAttractionPoints ( self,
List[vec3] points,
Optional[int] plant_id = None )

Add to the current attraction point set.

Parameters
pointsAdditional target locations as a list of vec3
plant_idAppend for this plant only. Appends globally when None.
Exceptions
ValueErrorIf points is empty or contains a non-vec3, or plant_id is negative
PlantArchitectureErrorIf the operation fails

Definition at line 704 of file PlantArchitecture.py.

◆ appendShoot()

int pyhelios.PlantArchitecture.PlantArchitecture.appendShoot ( self,
int plant_id,
int parent_shoot_id,
int current_node_number,
AxisRotation base_rotation,
float internode_radius,
float internode_length_max,
float internode_length_scale_factor_fraction,
float leaf_scale_factor_fraction,
float radius_taper,
str shoot_type_label )

Append a shoot to the end of an existing shoot.

   This method extends an existing shoot by appending a new shoot at its terminal bud.
   Useful for creating multi-segmented shoots with varying properties along their length,
   such as shoots with different growth phases or developmental stages.

   **IMPORTANT - Shoot Type Requirement**: The shoot_type_label must match a shoot type
   defined in a loaded plant model. Load a model with loadPlantModelFromLibrary() before
   calling this method.
Parameters
plant_idID of the plant instance
parent_shoot_idID of the parent shoot to extend
current_node_numberStarting node number for this shoot
base_rotationOrientation as AxisRotation(pitch, yaw, roll) in radians (use math.radians() to convert)
internode_radiusBase radius of internodes in meters (must be > 0)
internode_length_maxMaximum internode length in meters (must be > 0)
internode_length_scale_factor_fractionScale factor for internode length (0-1 typically)
leaf_scale_factor_fractionScale factor for leaf size (0-1 typically)
radius_taperRate of radius decrease along shoot (0-1, where 1=no taper)
shoot_type_labelLabel identifying shoot type - must match loaded model
Returns
Shoot ID for the appended shoot
Exceptions
ValueErrorIf parameters are invalid (negative IDs, non-positive dimensions, empty label)
PlantArchitectureErrorIf shoot appending fails, parent doesn't exist, or shoot type not defined
Example
>>> # Load model to define shoot types >>> plantarch.loadPlantModelFromLibrary("bean") >>> >>> # Append shoot with reduced size to simulate apical growth >>> new_shoot_id = plantarch.appendShoot( ... plant_id=plant_id, ... parent_shoot_id=base_shoot_id, ... current_node_number=10, ... base_rotation=AxisRotation(0, 0, 0), ... internode_radius=0.008, # Smaller than base ... internode_length_max=0.08, # Shorter internodes ... internode_length_scale_factor_fraction=1.0, ... leaf_scale_factor_fraction=0.8, # Smaller leaves ... radius_taper=0.85, ... shoot_type_label="trifoliate" ... )

Definition at line 3734 of file PlantArchitecture.py.

◆ bendPetioleUnderLeafWeight()

None pyhelios.PlantArchitecture.PlantArchitecture.bendPetioleUnderLeafWeight ( self,
int plant_id,
int shoot_id,
int node_index,
int petiole_index )

Bend one petiole, and the leaves it carries, under the weight of its leaflets.

   The petiole is bent as a tapered cantilever clamped at its insertion, for the leaf's
   current size and the petiole's age. The bent shape is always computed from the
   recorded undeformed rest shape rather than the current shape, so repeated calls do
   not accumulate and creep the petiole downward. The insertion stays clamped, so the
   petiole keeps leaving the stem at its generated pitch and the droop appears beyond it
   as curvature along the length.

   This is normally driven by the growth model from
   ``PhytomerParameters.petiole.flexibility``; call it directly only to re-bend a petiole
   after changing its geometry yourself. It does nothing for a rigid petiole (flexibility
   left at zero), a petiole whose centerline was prescribed, one carrying a prescribed
   leaf, or when neither the load nor the compliance has changed since the last call.
Parameters
plant_idID of the plant instance
shoot_idShoot index within the plant
node_indexPhytomer index within the shoot
petiole_indexPetiole within the phytomer
Exceptions
ValueErrorIf any identifier is not a non-negative int
PlantArchitectureErrorIf the plant, shoot, node or petiole does not exist
RuntimeErrorIf the native library predates helios-core v1.3.87

Definition at line 4902 of file PlantArchitecture.py.

◆ breakPlantDormancy()

None pyhelios.PlantArchitecture.PlantArchitecture.breakPlantDormancy ( self,
int plant_id )

Break dormancy for all shoots on a plant, returning it to an active state.

   This is the counterpart to :meth:`makePlantDormant`. Note that it only revives buds that
   are not dead, so a plant that was repeatedly made dormant may not recover every bud.
Parameters
plant_idIdentifier of the plant whose dormancy should be broken
Exceptions
ValueErrorIf plant_id is negative
PlantArchitectureErrorIf the plant does not exist or the call fails
Example
>>> plantarch.makePlantDormant(plant_id) >>> plantarch.breakPlantDormancy(plant_id) # resume growth in spring

Definition at line 2298 of file PlantArchitecture.py.

◆ buildPlantCanopyFromLibrary()

List[int] pyhelios.PlantArchitecture.PlantArchitecture.buildPlantCanopyFromLibrary ( self,
vec3 canopy_center,
vec2 plant_spacing,
int2 plant_count,
float age,
float germination_rate = 1.0,
Optional[dict] build_parameters = None )

Build a canopy of regularly spaced plants from the currently loaded library model.

Parameters
canopy_centerCartesian (x,y,z) coordinates of canopy center as vec3
plant_spacingSpacing between plants in x- and y-directions (meters) as vec2
plant_countNumber of plants in x- and y-directions as int2
ageAge of all plants in days (must be >= 0)
germination_rateProbability that each plant position will be occupied (0 to 1). A value of 1.0 means all positions are filled; 0.5 means roughly half the positions will have plants. Default is 1.0.
build_parametersOptional dict of parameter overrides for training system parameters, applied to every plant in the canopy. Only some models read them, and a key the model does not accept raises ValueError rather than being ignored. See buildPlantInstanceFromLibrary() for the per-model list.
Returns
List of plant IDs for the created plant instances
Exceptions
ValueErrorIf age is negative, germination_rate is not in [0, 1], plant count values are not positive, or build_parameters is invalid
PlantArchitectureErrorIf canopy building fails
Example
>>> # 3x3 canopy with 0.5m spacing, 30-day-old plants >>> plant_ids = plantarch.buildPlantCanopyFromLibrary( ... canopy_center=vec3(0, 0, 0), ... plant_spacing=vec2(0.5, 0.5), ... plant_count=int2(3, 3), ... age=30.0 ... ) >>> # With 80% germination rate and custom parameters >>> plant_ids = plantarch.buildPlantCanopyFromLibrary( ... canopy_center=vec3(0, 0, 0), ... plant_spacing=vec2(1.5, 2.0), ... plant_count=int2(5, 3), ... age=45.0, ... germination_rate=0.8, ... build_parameters={'trunk_height': 1.8} ... )

Definition at line 491 of file PlantArchitecture.py.

◆ buildPlantInstanceFromLibrary()

int pyhelios.PlantArchitecture.PlantArchitecture.buildPlantInstanceFromLibrary ( self,
vec3 base_position,
float age,
Optional[dict] build_parameters = None )

Build a plant instance from the currently loaded library model.

Parameters
base_positionCartesian (x,y,z) coordinates of plant base as vec3
ageAge of the plant in days (must be >= 0)
build_parametersOptional dict of parameter overrides for training system parameters. Only some models read them, and a key the model does not accept raises ValueError rather than being ignored:
  • almond, almond_aldrich, almond_wood_colony, apple, pistachio,
walnuttrunk_height, num_scaffolds, scaffold_angle
  • grapevine_VSP: trunk_height, vine_spacing
  • grapevine_wye: trunk_height, vine_spacing, cordon_spacing,
catch_wire_heightAll other models read no build parameters.
Returns
Plant ID for the created plant instance
Exceptions
ValueErrorIf age is negative or build_parameters is invalid
PlantArchitectureErrorIf plant building fails
RuntimeErrorIf no model has been loaded
Example
>>> plant_id = plantarch.buildPlantInstanceFromLibrary(base_position=vec3(2.0, 3.0, 0.0), age=45.0) >>> # With custom parameters >>> plant_id = plantarch.buildPlantInstanceFromLibrary( ... base_position=vec3(0, 0, 0), ... age=30.0, ... build_parameters={'trunk_height': 2.0} ... )

Definition at line 424 of file PlantArchitecture.py.

◆ clearGrowthFrames()

None pyhelios.PlantArchitecture.PlantArchitecture.clearGrowthFrames ( self,
int plant_id )

Clear stored growth animation frames for a plant.

Parameters
plant_idID of the plant instance whose frames should be cleared
Exceptions
ValueErrorIf plant_id is negative

Definition at line 3422 of file PlantArchitecture.py.

◆ defineShootType()

None pyhelios.PlantArchitecture.PlantArchitecture.defineShootType ( self,
str shoot_type_label,
Union[dict, ShootParameters] parameters )

Define a custom shoot type with specified parameters.

   Allows creating new shoot types or modifying existing ones. Pass either a
   nested parameter ``dict`` (use :meth:`getCurrentShootParameters` as a
   template) or a typed
   :class:`pyhelios.plant_architecture_params.ShootParameters` object.

   Redefining an existing library shoot type preserves that species' built-in
   phytomer creation and callback functions, so species-specific organ behavior
   (such as maize forming ears rather than a tassel at every node) is retained.
Parameters
shoot_type_labelUnique name for this shoot type
parametersA nested dict matching the ShootParameters structure, or a ShootParameters object.
Exceptions
ValueErrorIf shoot_type_label is empty, or parameters is not a dict or ShootParameters
PlantArchitectureErrorIf shoot type definition fails
Example
>>> from pyhelios.plant_architecture_params import ShootParameters, RandomParameterFloat >>> plantarch.loadPlantModelFromLibrary("bean") >>> sp = plantarch.getCurrentShootParameters("trifoliate", return_typed=True) >>> sp.max_nodes = RandomParameterFloat.constant(20) >>> sp.phytomer_parameters.leaf.pitch = RandomParameterFloat.uniform(40, 50) >>> plantarch.defineShootType("TallStem", sp)

Definition at line 902 of file PlantArchitecture.py.

◆ deletePlantInstance()

None pyhelios.PlantArchitecture.PlantArchitecture.deletePlantInstance ( self,
int plant_id )

Delete a plant instance and all associated geometry.

   This method removes a plant from the simulation, deleting all shoots, organs,
   and associated primitives from the context. The plant ID becomes invalid after
   deletion and should not be used in subsequent operations.
Parameters
plant_idID of the plant instance to delete
Exceptions
ValueErrorIf plant_id is negative
PlantArchitectureErrorIf plant deletion fails or plant doesn't exist
Example
>>> # Delete a plant >>> plantarch.deletePlantInstance(plant_id) >>> >>> # Delete multiple plants >>> for pid in plant_ids_to_remove: ... plantarch.deletePlantInstance(pid)

Definition at line 3576 of file PlantArchitecture.py.

◆ disableAttractionPoints()

None pyhelios.PlantArchitecture.PlantArchitecture.disableAttractionPoints ( self,
Optional[int] plant_id = None )

Stop steering growth toward attraction points.

Parameters
plant_idDisable for this plant only. Disables globally when None.
Exceptions
ValueErrorIf plant_id is negative
PlantArchitectureErrorIf the operation fails

Definition at line 658 of file PlantArchitecture.py.

◆ disableCollisionDetection()

None pyhelios.PlantArchitecture.PlantArchitecture.disableCollisionDetection ( self)

Disable collision detection for plant growth.

   This method turns off the collision detection system, allowing plants to grow
   without checking for obstacles. This improves performance but plants may grow
   through obstacles and other geometry.
Exceptions
PlantArchitectureErrorIf disabling fails
Example
>>> plantarch.disableCollisionDetection()

Definition at line 2896 of file PlantArchitecture.py.

◆ disableLeafAngleDistributionTracking()

None pyhelios.PlantArchitecture.PlantArchitecture.disableLeafAngleDistributionTracking ( self,
int plant_id )

Stop steering a plant's leaf angles toward a prescribed distribution.

   Leaves already steered keep the orientation they have reached; leaves emerging
   afterward are left where the procedural model puts them.
Parameters
plant_idID of the plant instance
Exceptions
ValueErrorIf ``plant_id`` is not a non-negative int
PlantArchitectureErrorIf the plant does not exist
RuntimeErrorIf the native library predates helios-core v1.3.87

Definition at line 4588 of file PlantArchitecture.py.

◆ disableMessages()

None pyhelios.PlantArchitecture.PlantArchitecture.disableMessages ( self)

Suppress standard output from the plantarchitecture plugin.

   This silences progress bars and informational messages the C++ plugin
   writes to stdout, including the "BVH not cached" warning emitted during
   the first growth steps of a collision-enabled canopy (before any plant
   geometry exists for the BVH to contain).
Exceptions
PlantArchitectureErrorIf the call fails
Example
>>> plantarch.disableMessages() >>> plantarch.advanceTime(30.0) # runs quietly

Definition at line 2860 of file PlantArchitecture.py.

◆ disablePlantPhenology()

None pyhelios.PlantArchitecture.PlantArchitecture.disablePlantPhenology ( self,
int plant_id )

Disable phenological progression for a plant.

   The plant continues to grow, but no phenological stage is ever scheduled: it does not
   enter dormancy, and flower and fruit stages are skipped. This is the explicit form of the
   state a plant is already in when :meth:`setPlantPhenologicalThresholds` has never been
   called on it, so it is mainly useful for turning phenology back off on a plant that had
   thresholds set earlier.
Parameters
plant_idIdentifier of the plant whose phenology is to be disabled
Warning
helios-core's disablePlantPhenology() sets dd_to_fruit_maturity to -1, whereas the "no phenology scheduled" default for that field is 1e6. The field is used as a divisor in the fruit-growth branch of advanceTime(), which is gated only on a bud being in the BUD_FRUITING state, and appendPhytomerToShoot() can set that state from shoot structure alone. On a plant that already has a fruiting bud, a subsequent advanceTime() can therefore compute a negative fruit scale factor. Avoid calling this on a plant with fruiting buds until it is fixed upstream; a plant that never had thresholds set is already in the no-phenology state and does not need it.
Exceptions
ValueErrorIf plant_id is negative
PlantArchitectureErrorIf disabling phenology fails
Example
>>> plantarch.setPlantPhenologicalThresholds(plant_id, 60, 90, 105, 120, 200, 280) >>> plantarch.disablePlantPhenology(plant_id) # growth only, no dormancy or fruiting

Definition at line 2233 of file PlantArchitecture.py.

◆ enableAttractionPoints()

None pyhelios.PlantArchitecture.PlantArchitecture.enableAttractionPoints ( self,
List[vec3] points,
Optional[int] plant_id = None,
Optional[float] view_half_angle_deg = None,
float look_ahead_distance = 0.1,
float attraction_weight = 0.6 )

Steer shoot growth toward a set of target points.

   Attraction points are the counterpart to collision avoidance: collision tells a
   plant what to grow around, attraction tells it what to grow toward. This is how
   trellis wires, espalier targets and greenhouse supports are modelled.

   Steering applies to growth that happens after this call, since the direction is
   chosen as each phytomer is constructed. Enable the points before advanceTime().
Parameters
pointsTarget locations as a list of vec3
plant_idApply to this plant only. Applies to every plant when None.
view_half_angle_degHalf-angle of the search cone in degrees. Defaults to 45 for the global form and 80 for the per-plant form, matching the native defaults, which differ between the two.
look_ahead_distanceHow far ahead a shoot tip looks, in meters
attraction_weightStrength of the steering, 0 to 1
Exceptions
ValueErrorIf points is empty or contains a non-vec3, or plant_id is negative
PlantArchitectureErrorIf the operation fails
Example
>>> wires = [vec3(x, 0, 2.1) for x in range(0, 10)] >>> plantarch.enableAttractionPoints(wires)

Definition at line 626 of file PlantArchitecture.py.

◆ enableGroundClipping()

None pyhelios.PlantArchitecture.PlantArchitecture.enableGroundClipping ( self,
float ground_height = 0.0 )

Enable automatic removal of plant organs that fall below the ground plane.

   Organ vertices below `ground_height` are clipped as plant geometry is
   built, which prevents drooping leaves and low branches from poking
   through a ground tile.
Parameters
ground_heightHeight of the ground plane (default 0.0)
Exceptions
ValueErrorIf ground_height is not a number
PlantArchitectureErrorIf the call fails
Example
>>> plantarch.enableGroundClipping(0.0) >>> plantarch.advanceTime(30.0)

Definition at line 2834 of file PlantArchitecture.py.

◆ enableLeafAngleDistributionTracking()

None pyhelios.PlantArchitecture.PlantArchitecture.enableLeafAngleDistributionTracking ( self,
plant_ids,
float beta_mu_inclination,
float beta_nu_inclination,
float eccentricity,
float ellipse_rotation_degrees,
float lambda_degrees )

Steer leaf inclination and azimuth toward a prescribed distribution as the plant grows.

   Each leaf is given a target angle as it emerges and turns onto it while it expands,
   so a fully grown leaf never moves again: the plant matches the distribution at every
   stage without leaves shifting from one timestep to the next. Targets are not drawn
   independently per leaf, which would reproduce the distribution while destroying the
   arrangement the model generated -- each emerging leaf takes the bin that best trades
   closeness to the angle the model gave it against how far that bin is below its share
   of the plant's leaf area.

   Pass a list of plant IDs to realize the distribution over a canopy as a whole, in
   which case an individual plant need not follow the distribution on its own.

   Enabling tracking on an already-tracked plant replaces its target, so the target may
   be varied over the plant's life.
Parameters
plant_idsA single plant ID, or a sequence of plant IDs to steer together
beta_mu_inclinationMean parameter of the Beta inclination distribution
beta_nu_inclinationShape parameter of the Beta inclination distribution
eccentricityEccentricity of the ellipse defining the azimuth distribution
ellipse_rotation_degreesRotation of that ellipse (degrees)
lambda_degreesHow strongly to favour filling the distribution over keeping each leaf near the angle the model gave it. Zero leaves the plant unchanged; values of order 180 match the distribution as closely as the growing plant allows.
Exceptions
ValueErrorIf any plant ID is not a non-negative int, or the list is empty
PlantArchitectureErrorIf a plant does not exist
RuntimeErrorIf the native library predates helios-core v1.3.87
Example
>>> plantarch.enableLeafAngleDistributionTracking( ... plant_id, 2.0, 1.5, 0.5, 0.0, 180.0) >>> plantarch.advanceTime(plant_id, 20)

Definition at line 4485 of file PlantArchitecture.py.

◆ enableLeafAzimuthAngleDistributionTracking()

None pyhelios.PlantArchitecture.PlantArchitecture.enableLeafAzimuthAngleDistributionTracking ( self,
int plant_id,
float eccentricity,
float ellipse_rotation_degrees,
float lambda_degrees )

Steer leaf azimuth toward an ellipsoidal distribution as the plant grows, leaving inclination to the procedural model.

The azimuth-only counterpart of :meth:enableLeafAngleDistributionTracking.

Parameters
plant_idID of the plant instance
eccentricityEccentricity of the ellipse defining the azimuth distribution
ellipse_rotation_degreesRotation of that ellipse (degrees)
lambda_degreesHow strongly to favour filling the distribution over keeping each leaf near the angle the model gave it
Exceptions
ValueErrorIf ``plant_id`` is not a non-negative int
PlantArchitectureErrorIf the plant does not exist
RuntimeErrorIf the native library predates helios-core v1.3.87

Definition at line 4559 of file PlantArchitecture.py.

◆ enableLeafElevationAngleDistributionTracking()

None pyhelios.PlantArchitecture.PlantArchitecture.enableLeafElevationAngleDistributionTracking ( self,
int plant_id,
float beta_mu_inclination,
float beta_nu_inclination,
float lambda_degrees )

Steer leaf inclination toward a Beta distribution as the plant grows, leaving azimuth to the procedural model.

The inclination-only counterpart of :meth:enableLeafAngleDistributionTracking.

Parameters
plant_idID of the plant instance
beta_mu_inclinationMean parameter of the Beta inclination distribution
beta_nu_inclinationShape parameter of the Beta inclination distribution
lambda_degreesHow strongly to favour filling the distribution over keeping each leaf near the angle the model gave it
Exceptions
ValueErrorIf ``plant_id`` is not a non-negative int
PlantArchitectureErrorIf the plant does not exist
RuntimeErrorIf the native library predates helios-core v1.3.87

Definition at line 4525 of file PlantArchitecture.py.

◆ enableMessages()

None pyhelios.PlantArchitecture.PlantArchitecture.enableMessages ( self)

Re-enable standard output from the plantarchitecture plugin.

Exceptions
PlantArchitectureErrorIf the call fails
Example
>>> plantarch.enableMessages()

Definition at line 2876 of file PlantArchitecture.py.

◆ enableSoftCollisionAvoidance()

None pyhelios.PlantArchitecture.PlantArchitecture.enableSoftCollisionAvoidance ( self,
Optional[List[int]] target_object_UUIDs = None,
Optional[List[int]] target_object_IDs = None,
bool enable_petiole_collision = False,
bool enable_fruit_collision = False )

Enable soft collision avoidance for procedural plant growth.

   This method enables the collision detection system that guides plant growth away from
   obstacles and other plants. The system uses cone-based gap detection to find optimal
   growth directions that minimize collisions while maintaining natural plant architecture.
Parameters
target_object_UUIDsList of primitive UUIDs to avoid collisions with. If empty, avoids all geometry in the context.
target_object_IDsList of compound object IDs to avoid collisions with.
enable_petiole_collisionEnable collision detection for leaf petioles
enable_fruit_collisionEnable collision detection for fruit organs
Exceptions
PlantArchitectureErrorIf collision detection activation fails
Note
Collision detection adds computational overhead. Use setStaticObstacles() to mark static geometry for BVH optimization and improved performance.
Example
>>> # Avoid all geometry >>> plantarch.enableSoftCollisionAvoidance() >>> >>> # Avoid specific obstacles >>> obstacle_uuids = context.getAllUUIDs() >>> plantarch.enableSoftCollisionAvoidance(target_object_UUIDs=obstacle_uuids) >>> >>> # Enable collision detection for petioles and fruit >>> plantarch.enableSoftCollisionAvoidance( ... enable_petiole_collision=True, ... enable_fruit_collision=True ... )

Definition at line 2798 of file PlantArchitecture.py.

◆ enableSolidObstacleAvoidance()

None pyhelios.PlantArchitecture.PlantArchitecture.enableSolidObstacleAvoidance ( self,
List[int] obstacle_UUIDs,
float avoidance_distance = 0.5,
bool enable_fruit_adjustment = False,
bool enable_obstacle_pruning = False )

Enable hard obstacle avoidance for specified geometry.

   This method configures solid obstacles that plants cannot grow through. Unlike soft
   collision avoidance (which guides growth), solid obstacles cause complete growth
   termination when encountered within the avoidance distance.
Parameters
obstacle_UUIDsList of primitive UUIDs representing solid obstacles
avoidance_distanceMinimum distance to maintain from obstacles (meters). Growth stops if obstacles are closer. Default 0.5m.
enable_fruit_adjustmentAdjust fruit positions away from obstacles
enable_obstacle_pruningRemove plant organs that penetrate obstacles
Exceptions
ValueErrorIf obstacle_UUIDs is empty or avoidance_distance is non-positive
PlantArchitectureErrorIf solid obstacle configuration fails
Example
>>> # Simple solid obstacle avoidance >>> wall_uuids = [1, 2, 3, 4] # UUIDs of wall primitives >>> plantarch.enableSolidObstacleAvoidance(wall_uuids) >>> >>> # Close avoidance with fruit adjustment >>> plantarch.enableSolidObstacleAvoidance( ... obstacle_UUIDs=wall_uuids, ... avoidance_distance=0.1, ... enable_fruit_adjustment=True ... )

Definition at line 3044 of file PlantArchitecture.py.

◆ getAllDescendantShootIDs()

List[int] pyhelios.PlantArchitecture.PlantArchitecture.getAllDescendantShootIDs ( self,
int plant_id,
int shoot_id )

Get every shoot descending from a shoot.

   Collected depth-first, so a shoot is always listed before its own descendants.
   The shoot itself is not included, and pruned shoots are omitted.
Parameters
plant_idID of the plant instance
shoot_idShoot whose descendants to collect
Returns
IDs of all descendants of the shoot, empty if it has none.
Example
>>> descendants = plantarch.getAllDescendantShootIDs(plant_id, shoot_id=1) >>> print(f"Branch carries {len(descendants)} sub-shoots")

Definition at line 1748 of file PlantArchitecture.py.

◆ getAllFlowerUUIDs()

List[int] pyhelios.PlantArchitecture.PlantArchitecture.getAllFlowerUUIDs ( self)

Get UUIDs of every flower primitive in the model.

   Spans every plant, unlike the per-plant getters, which is what canopy-wide work
   such as assigning optical properties or reading flux by organ type needs.

   An empty list means no plant has reached the corresponding growth stage,
   which is a legitimate result rather than a failure.
Returns
List of flower primitive UUIDs
Exceptions
PlantArchitectureErrorIf retrieval fails
Example
>>> ids = plantarch.getAllFlowerUUIDs()

Definition at line 1230 of file PlantArchitecture.py.

◆ getAllFruitUUIDs()

List[int] pyhelios.PlantArchitecture.PlantArchitecture.getAllFruitUUIDs ( self)

Get UUIDs of every fruit primitive in the model.

   Spans every plant, unlike the per-plant getters, which is what canopy-wide work
   such as assigning optical properties or reading flux by organ type needs.

   An empty list means no plant has reached the corresponding growth stage,
   which is a legitimate result rather than a failure.
Returns
List of fruit primitive UUIDs
Exceptions
PlantArchitectureErrorIf retrieval fails
Example
>>> ids = plantarch.getAllFruitUUIDs()

Definition at line 1256 of file PlantArchitecture.py.

◆ getAllInternodeUUIDs()

List[int] pyhelios.PlantArchitecture.PlantArchitecture.getAllInternodeUUIDs ( self)

Get UUIDs of every internode primitive in the model.

   Spans every plant, unlike the per-plant getters, which is what canopy-wide work
   such as assigning optical properties or reading flux by organ type needs.
Returns
List of internode primitive UUIDs
Exceptions
PlantArchitectureErrorIf retrieval fails
Example
>>> ids = plantarch.getAllInternodeUUIDs()

Definition at line 1155 of file PlantArchitecture.py.

◆ getAllLeafUUIDs()

List[int] pyhelios.PlantArchitecture.PlantArchitecture.getAllLeafUUIDs ( self)

Get UUIDs of every leaf primitive in the model.

   Spans every plant, unlike the per-plant getters, which is what canopy-wide work
   such as assigning optical properties or reading flux by organ type needs.
Returns
List of leaf primitive UUIDs
Exceptions
PlantArchitectureErrorIf retrieval fails
Example
>>> ids = plantarch.getAllLeafUUIDs()

Definition at line 1132 of file PlantArchitecture.py.

◆ getAllObjectIDs()

List[int] pyhelios.PlantArchitecture.PlantArchitecture.getAllObjectIDs ( self)

Get object IDs of every plant compound object in the model.

   Spans every plant, unlike the per-plant getters, which is what canopy-wide work
   such as assigning optical properties or reading flux by organ type needs.
Returns
List of object IDs
Exceptions
PlantArchitectureErrorIf retrieval fails
Example
>>> ids = plantarch.getAllObjectIDs()

Definition at line 1279 of file PlantArchitecture.py.

◆ getAllPeduncleUUIDs()

List[int] pyhelios.PlantArchitecture.PlantArchitecture.getAllPeduncleUUIDs ( self)

Get UUIDs of every peduncle primitive in the model.

   Spans every plant, unlike the per-plant getters, which is what canopy-wide work
   such as assigning optical properties or reading flux by organ type needs.

   An empty list means no plant has reached the corresponding growth stage,
   which is a legitimate result rather than a failure.
Returns
List of peduncle primitive UUIDs
Exceptions
PlantArchitectureErrorIf retrieval fails
Example
>>> ids = plantarch.getAllPeduncleUUIDs()

Definition at line 1204 of file PlantArchitecture.py.

◆ getAllPetioleUUIDs()

List[int] pyhelios.PlantArchitecture.PlantArchitecture.getAllPetioleUUIDs ( self)

Get UUIDs of every petiole primitive in the model.

   Spans every plant, unlike the per-plant getters, which is what canopy-wide work
   such as assigning optical properties or reading flux by organ type needs.
Returns
List of petiole primitive UUIDs
Exceptions
PlantArchitectureErrorIf retrieval fails
Example
>>> ids = plantarch.getAllPetioleUUIDs()

Definition at line 1178 of file PlantArchitecture.py.

◆ getAllPlantIDs()

List[int] pyhelios.PlantArchitecture.PlantArchitecture.getAllPlantIDs ( self)

Get IDs of every plant instance in the model.

   Spans every plant, unlike the per-plant getters, which is what canopy-wide work
   such as assigning optical properties or reading flux by organ type needs.
Returns
List of plant IDs
Exceptions
PlantArchitectureErrorIf retrieval fails
Example
>>> ids = plantarch.getAllPlantIDs()

Definition at line 1302 of file PlantArchitecture.py.

◆ getAllPlantObjectIDs()

List[int] pyhelios.PlantArchitecture.PlantArchitecture.getAllPlantObjectIDs ( self,
int plant_id )

Get all object IDs for a specific plant.

Parameters
plant_idID of the plant instance
Returns
List of object IDs comprising the plant
Exceptions
ValueErrorIf plant_id is negative
PlantArchitectureErrorIf retrieval fails
Example
>>> object_ids = plantarch.getAllPlantObjectIDs(plant_id) >>> print(f"Plant has {len(object_ids)} objects")

Definition at line 1327 of file PlantArchitecture.py.

◆ getAllPlantUUIDs()

List[int] pyhelios.PlantArchitecture.PlantArchitecture.getAllPlantUUIDs ( self,
int plant_id,
bool include_hidden = False )

Get all primitive UUIDs for a specific plant.

Parameters
plant_idID of the plant instance
include_hiddenIf True, also include UUIDs of hidden prototype primitives managed by this PlantArchitecture instance.
Returns
List of primitive UUIDs comprising the plant (and optionally hidden prototypes)
Exceptions
ValueErrorIf plant_id is negative
PlantArchitectureErrorIf retrieval fails
Example
>>> uuids = plantarch.getAllPlantUUIDs(plant_id) >>> print(f"Plant has {len(uuids)} primitives")

Definition at line 1551 of file PlantArchitecture.py.

◆ getAllShootIDs()

List[int] pyhelios.PlantArchitecture.PlantArchitecture.getAllShootIDs ( self,
int plant_id )

Get the IDs of all shoots belonging to a plant.

   Shoot IDs are contiguous 0-based indices into the plant's shoot tree, in creation
   order; shoot 0 is always the base stem. The returned IDs can be passed to
   :meth:`getShoot`, :meth:`getShootChildIDs`, etc.
Parameters
plant_idID of the plant instance
Returns
List of shoot IDs for the plant

Definition at line 1574 of file PlantArchitecture.py.

◆ getAllUUIDs()

List[int] pyhelios.PlantArchitecture.PlantArchitecture.getAllUUIDs ( self)

Get UUIDs of every plant primitive in the model.

   Spans every plant, unlike the per-plant getters, which is what canopy-wide work
   such as assigning optical properties or reading flux by organ type needs.
Returns
List of primitive UUIDs
Exceptions
PlantArchitectureErrorIf retrieval fails
Example
>>> ids = plantarch.getAllUUIDs()

Definition at line 1109 of file PlantArchitecture.py.

◆ getAvailablePlantModels()

List[str] pyhelios.PlantArchitecture.PlantArchitecture.getAvailablePlantModels ( self)

Get list of all available plant models in the library.

Returns
List of plant model names available for loading
Exceptions
PlantArchitectureErrorIf retrieval fails
Example
>>> models = plantarch.getAvailablePlantModels() >>> print(f"Available models: {', '.join(models)}") Available almond, apple, bean, cowpea, maize, rice, soybean, tomato, wheat, ...

Definition at line 1035 of file PlantArchitecture.py.

◆ getChildShootIDs()

List[int] pyhelios.PlantArchitecture.PlantArchitecture.getChildShootIDs ( self,
int plant_id,
int shoot_id )

Get the shoots that grew directly out of a shoot.

   Ordered by the node they attach to. This includes shoots created by
   :meth:`appendShoot`, which continue the parent's axis rather than branching from
   it; compare their :meth:`getShootRank` with the parent's to tell the two apart.
   Pruned shoots are not included.
Parameters
plant_idID of the plant instance
shoot_idShoot index within the plant
Returns
IDs of the direct children of the shoot, empty if it has none.

Definition at line 1728 of file PlantArchitecture.py.

◆ getCurrentShootParameters()

pyhelios.PlantArchitecture.PlantArchitecture.getCurrentShootParameters ( self,
str shoot_type_label,
bool return_typed = False )

Get current shoot parameters for a shoot type.

   Returns the full nested shoot and phytomer parameter set, including the
   internode/petiole/leaf/peduncle/inflorescence sub-structures and the leaf
   prototype. Every numeric field is a RandomParameter spec with a
   'distribution' and 'parameters'.
Parameters
shoot_type_labelLabel for the shoot type. Labels are species-specific, e.g. "trifoliate" (bean), "trunk"/"scaffold" (almond).
return_typedIf True, return a typed :class:pyhelios.plant_architecture_params.ShootParameters object instead of a plain nested dict.
Returns
A nested dict (default) or a ShootParameters object containing:
  • Geometric parameters (max_nodes, insertion_angle_tip, etc.)
  • Growth parameters (phyllochron_min, elongation_rate_max, etc.)
  • Boolean flags (flowers_require_dormancy, etc.)
  • phytomer_parameters with nested internode/petiole/leaf/peduncle/ inflorescence parameters and the leaf prototype
Exceptions
ValueErrorIf shoot_type_label is empty
PlantArchitectureErrorIf parameter retrieval fails
Example
>>> plantarch.loadPlantModelFromLibrary("bean") >>> params = plantarch.getCurrentShootParameters("trifoliate") >>> print(params['max_nodes']) {'distribution': 'constant', 'parameters': [25.0]} >>> print(params['phytomer_parameters']['leaf']['pitch']) {'distribution': 'normal', 'parameters': [0.0, 20.0]}

Definition at line 845 of file PlantArchitecture.py.

◆ getDefaultCarbohydrateParameters()

pyhelios.PlantArchitecture.PlantArchitecture.getDefaultCarbohydrateParameters ( self,
bool return_typed = False )

Get a default-constructed set of carbohydrate-model parameters.

   The native API exposes no per-plant getter for carbohydrate parameters, so
   this returns the C++ defaults as a template to modify and apply via
   :meth:`setPlantCarbohydrateParameters`.
Parameters
return_typedIf True, return a typed :class:pyhelios.plant_architecture_params.CarbohydrateParameters.
Returns
A flat dict (default) or CarbohydrateParameters object.

Definition at line 939 of file PlantArchitecture.py.

◆ getDefaultNitrogenParameters()

pyhelios.PlantArchitecture.PlantArchitecture.getDefaultNitrogenParameters ( self,
bool return_typed = False )

Get a default-constructed set of nitrogen-model parameters.

   The native API exposes no per-plant getter for nitrogen parameters, so this
   returns the C++ defaults as a template to modify and apply via
   :meth:`setPlantNitrogenParameters`.
Parameters
return_typedIf True, return a typed :class:pyhelios.plant_architecture_params.NitrogenParameters.
Returns
A flat dict (default) or NitrogenParameters object.

Definition at line 987 of file PlantArchitecture.py.

◆ getGrowthFrameCount()

int pyhelios.PlantArchitecture.PlantArchitecture.getGrowthFrameCount ( self,
int plant_id )

Get the number of registered growth frames for a plant.

Parameters
plant_idID of the plant instance to query
Returns
Number of frames registered via :meth:registerGrowthFrame
Exceptions
ValueErrorIf plant_id is negative

Definition at line 3444 of file PlantArchitecture.py.

◆ getParentShootID()

int pyhelios.PlantArchitecture.PlantArchitecture.getParentShootID ( self,
int plant_id,
int shoot_id )

Get the ID of the shoot a shoot grew from.

Parameters
plant_idID of the plant instance
shoot_idShoot index within the plant (see :meth:getAllShootIDs)
Returns
ID of the parent shoot, or -1 if this is the base stem shoot.
Note
A pruned shoot still reports the parent it grew from, even though it is no longer listed among that parent's children.
Example
>>> parent = plantarch.getParentShootID(plant_id, shoot_id=3)

Definition at line 1632 of file PlantArchitecture.py.

◆ getPathToRoot()

List[int] pyhelios.PlantArchitecture.PlantArchitecture.getPathToRoot ( self,
int plant_id,
int shoot_id )

Get the chain of shoots connecting a shoot to the base stem shoot.

Parameters
plant_idID of the plant instance
shoot_idShoot index within the plant
Returns
Shoot IDs ordered from the given shoot to the base stem shoot, including both. For the base stem shoot this is a single element.
Example
>>> path = plantarch.getPathToRoot(plant_id, shoot_id=5)

Definition at line 1710 of file PlantArchitecture.py.

◆ getPetioleLength()

float pyhelios.PlantArchitecture.PlantArchitecture.getPetioleLength ( self,
int plant_id,
int shoot_id,
int node_index,
Optional[int] petiole_index = None )

Current length of a phytomer's petioles, measured along the centerline.

   This is the length right now, not the mature length the petiole is growing toward,
   so it rises as the petiole elongates. Contrast the leaf readers, which report the
   size a leaf is expanding toward. The length is an arclength rather than a
   base-to-tip distance, so a petiole drooping under its leaves reports the same
   length as a rigid one of the same age.

   With ``petiole_index`` omitted, returns the mean over every petiole on the
   phytomer. Petioles at one node are parallel structures rather than segments in
   series, so their lengths are not additive and the mean is the meaningful summary.
   A phytomer with no petiole -- a leafless woody type, or one whose leaf has been
shed    reports 0.0.
Parameters
plant_idID of the plant instance
shoot_idShoot index within the plant
node_indexPhytomer index within the shoot
petiole_indexPetiole within the phytomer; None for the phytomer mean
Returns
Current petiole arclength in meters
Exceptions
ValueErrorIf any identifier is not a non-negative int
PlantArchitectureErrorIf the plant, shoot, node or petiole does not exist
RuntimeErrorIf the native library predates helios-core v1.3.87

Definition at line 4655 of file PlantArchitecture.py.

◆ getPlantAge()

float pyhelios.PlantArchitecture.PlantArchitecture.getPlantAge ( self,
int plant_id )

Get the current age of a plant in days.

Parameters
plant_idID of the plant instance
Returns
Plant age in days
Exceptions
ValueErrorIf plant_id is negative
PlantArchitectureErrorIf retrieval fails
Example
>>> age = plantarch.getPlantAge(plant_id) >>> print(f"Plant is {age} days old")

Definition at line 1966 of file PlantArchitecture.py.

◆ getPlantCollisionRelevantObjectIDs()

List[int] pyhelios.PlantArchitecture.PlantArchitecture.getPlantCollisionRelevantObjectIDs ( self,
int plant_id )

Get object IDs of collision-relevant geometry for a specific plant.

   This method returns the subset of plant geometry that participates in collision
   detection, as filtered by setCollisionRelevantOrgans(). Useful for visualization
   and debugging collision detection behavior.
Parameters
plant_idID of the plant instance
Returns
List of object IDs for collision-relevant plant geometry
Exceptions
ValueErrorIf plant_id is negative
PlantArchitectureErrorIf retrieval fails
Example
>>> # Get collision-relevant geometry >>> collision_obj_ids = plantarch.getPlantCollisionRelevantObjectIDs(plant_id) >>> print(f"Plant has {len(collision_obj_ids)} collision-relevant objects") >>> >>> # Highlight collision geometry in visualization >>> for obj_id in collision_obj_ids: ... context.setObjectColor(obj_id, RGBcolor(1, 0, 0)) # Red

Definition at line 3132 of file PlantArchitecture.py.

◆ getPlantFlowerObjectIDs()

List[int] pyhelios.PlantArchitecture.PlantArchitecture.getPlantFlowerObjectIDs ( self,
int plant_id )

Get object IDs for all flower (inflorescence) objects on a specific plant.

Parameters
plant_idID of the plant instance
Returns
List of object IDs, one per flower. Empty if the plant has not
flowered or has already flowered and set fruit, since flowers are replaced by fruit as growth proceeds. Both are normal results rather than errors.
Exceptions
ValueErrorIf plant_id is negative
PlantArchitectureErrorIf retrieval fails
Example
>>> flower_ids = plantarch.getPlantFlowerObjectIDs(plant_id) >>> print(f"Plant has {len(flower_ids)} flowers")

Definition at line 1450 of file PlantArchitecture.py.

◆ getPlantFruitObjectIDs()

List[int] pyhelios.PlantArchitecture.PlantArchitecture.getPlantFruitObjectIDs ( self,
int plant_id )

Get object IDs for all fruit objects on a specific plant.

Parameters
plant_idID of the plant instance
Returns
List of object IDs, one per fruit. Empty if the plant has not fruited, which is a normal result rather than an error – fruit appear only once a plant reaches the reproductive stage, so a plant built at a young age or from a model with no fruit yields [].
Exceptions
ValueErrorIf plant_id is negative
PlantArchitectureErrorIf retrieval fails
Example
>>> fruit_ids = plantarch.getPlantFruitObjectIDs(plant_id) >>> print(f"Plant has {len(fruit_ids)} fruit") >>> # Object IDs are Context object IDs, so the usual queries apply: >>> uuids = context.getObjectPrimitiveUUIDs(fruit_ids[0])

Definition at line 1482 of file PlantArchitecture.py.

◆ getPlantHeight()

float pyhelios.PlantArchitecture.PlantArchitecture.getPlantHeight ( self,
int plant_id )

Get the height of a plant in meters.

Parameters
plant_idID of the plant instance
Returns
Plant height in meters (vertical extent)
Exceptions
ValueErrorIf plant_id is negative
PlantArchitectureErrorIf retrieval fails
Example
>>> height = plantarch.getPlantHeight(plant_id) >>> print(f"Plant is {height:.2f}m tall")

Definition at line 2055 of file PlantArchitecture.py.

◆ getPlantInternodeLengths()

List[float] pyhelios.PlantArchitecture.PlantArchitecture.getPlantInternodeLengths ( self,
int plant_id )

Get the built length of every internode on a plant.

   Measured along the internode's node positions as they were built, so a shoot
   whose geometry was prescribed by :meth:`addShootFromNodePositions` reports its
   measured lengths and a grown shoot reports what growth produced. See
   :meth:`getPlantLeafAreas` for why this differs from reading the shoot type's
   ``internode_length_max``.

   Internodes are visited shoot by shoot and then phytomer by phytomer, so the
   result has one entry per phytomer on the plant.

   Requires helios-core v1.3.85 or newer.
Parameters
plant_idID of the plant instance
Returns
Length (m) of each internode on the plant
Exceptions
ValueErrorIf plant_id is negative
PlantArchitectureErrorIf the query fails or the library predates v1.3.85

Definition at line 1891 of file PlantArchitecture.py.

◆ getPlantLeafArea()

float pyhelios.PlantArchitecture.PlantArchitecture.getPlantLeafArea ( self,
int plant_id )

Get the total leaf area of a plant in m².

Parameters
plant_idID of the plant instance
Returns
Total leaf area in square meters
Exceptions
ValueErrorIf plant_id is negative
PlantArchitectureErrorIf retrieval fails
Example
>>> leaf_area = plantarch.getPlantLeafArea(plant_id) >>> print(f"Total leaf area: {leaf_area:.3f} m²")

Definition at line 2083 of file PlantArchitecture.py.

◆ getPlantLeafAreas()

List[float] pyhelios.PlantArchitecture.PlantArchitecture.getPlantLeafAreas ( self,
int plant_id )

Get the built one-sided surface area of every leaf on a plant.

   Measured from the geometry that was actually built, rather than reported from
   the shoot type's parameters. The two answer different questions: the shoot type
   gives the distribution a parameter was drawn from, while this gives what the
   plant ended up with. A plant whose leaf parameters carry a wide spread can still
   deliver leaves of a single size (a random parameter caches its first draw, and a
   shoot holds a copy of its type's parameters), and nothing in the parameters
   themselves would reveal that.

   This reports present area, so a leaf part-way through its growth is counted at
   its current size. Leaves are visited shoot by shoot and then phytomer by phytomer,
   the same order as :meth:`getPlantLeafObjectIDs`. Leaves whose geometry does not
   exist (removed, senesced, or never built) are omitted rather than reported as
   zero, so the result can be shorter than the list from :meth:`getPlantLeafObjectIDs`.

   Requires helios-core v1.3.85 or newer.
Parameters
plant_idID of the plant instance
Returns
One-sided surface area (m^2) of each leaf on the plant
Exceptions
ValueErrorIf plant_id is negative
PlantArchitectureErrorIf the query fails or the library predates v1.3.85
Example
>>> areas = plantarch.getPlantLeafAreas(plant_id) >>> print(f"{len(areas)} leaves, mean {sum(areas)/len(areas):.4f} m^2")

Definition at line 1864 of file PlantArchitecture.py.

◆ getPlantLeafBases()

List[vec3] pyhelios.PlantArchitecture.PlantArchitecture.getPlantLeafBases ( self,
int plant_id )

Get the attachment base position of every leaf on a specific plant.

   The base is where the leaf attaches to its petiole, not the leaf centroid.
Parameters
plant_idID of the plant instance
Returns
List of vec3 base positions, one per leaf
Exceptions
ValueErrorIf plant_id is negative
PlantArchitectureErrorIf retrieval fails
Warning
Do not pair this result positionally with :meth:getPlantLeafObjectIDs. The two are built by independent traversals of the shoot tree, so their index correspondence is not guaranteed by the native API. (helios-core has an internal getPlantLeafObjectIDsAndBases() that gathers both in one traversal for exactly this reason, but it is protected and not callable from here.)
Example
>>> bases = plantarch.getPlantLeafBases(plant_id) >>> print(f"First leaf attaches at {bases[0]}")

Definition at line 1519 of file PlantArchitecture.py.

◆ getPlantLeafCount()

int pyhelios.PlantArchitecture.PlantArchitecture.getPlantLeafCount ( self,
int plant_id )

Get the number of leaf objects on a plant.

   Counts compound leaf objects, not primitives -- a leaf built from many triangles
   counts once, and a compound leaf contributes one per leaflet. Equivalent to
   ``len(getPlantLeafObjectIDs(plant_id))`` without materializing the ID list.
Parameters
plant_idID of the plant instance
Returns
The number of leaf objects.
Exceptions
ValueErrorIf plant_id is not a non-negative int
PlantArchitectureErrorIf the plant does not exist
Example
>>> print(f"{plantarch.getPlantLeafCount(plant_id)} leaves")

Definition at line 4401 of file PlantArchitecture.py.

◆ getPlantLeafInclinations()

List[float] pyhelios.PlantArchitecture.PlantArchitecture.getPlantLeafInclinations ( self,
int plant_id )

Get the inclination angle of every leaf on a plant.

   The angle between each leaf blade and the horizontal, computed from its
   area-weighted normal so that a curved or folded blade is summarized by the
   direction it mostly faces. 0 degrees is a horizontal blade and 90 degrees a
   vertical one; because a blade is a surface, a normal pointing down describes the
   same inclination as its opposite pointing up, so the angle is folded about the
   horizontal and never exceeds 90 degrees.

   Ordering and the treatment of missing geometry match :meth:`getPlantLeafAreas`.
   A blade whose facet normals cancel exactly is additionally omitted, since it
   faces no single direction.

   Requires helios-core v1.3.85 or newer.
Parameters
plant_idID of the plant instance
Returns
Inclination angle (degrees, in [0, 90]) of each leaf on the plant
Exceptions
ValueErrorIf plant_id is negative
PlantArchitectureErrorIf the query fails or the library predates v1.3.85

Definition at line 1920 of file PlantArchitecture.py.

◆ getPlantLeafObjectIDs()

List[int] pyhelios.PlantArchitecture.PlantArchitecture.getPlantLeafObjectIDs ( self,
int plant_id )

Get object IDs for all leaf objects on a specific plant.

Parameters
plant_idID of the plant instance
Returns
List of object IDs, one per leaf
Exceptions
ValueErrorIf plant_id is negative
PlantArchitectureErrorIf retrieval fails
Warning
Do not pair this result positionally with :meth:getPlantLeafBases. The two are built by independent traversals of the shoot tree, so their index correspondence is not guaranteed by the native API.
Example
>>> leaf_ids = plantarch.getPlantLeafObjectIDs(plant_id) >>> print(f"Plant has {len(leaf_ids)} leaves")

Definition at line 1359 of file PlantArchitecture.py.

◆ getPlantMaxAge()

float pyhelios.PlantArchitecture.PlantArchitecture.getPlantMaxAge ( self,
int plant_id )

Get the maximum age of a plant, beyond which it stops growing.

Parameters
plant_idID of the plant instance
Returns
Maximum plant age in days. See :meth:setPlantMaxAge.
Exceptions
ValueErrorIf plant_id is negative
PlantArchitectureErrorIf retrieval fails
Example
>>> max_age = plantarch.getPlantMaxAge(plant_id)

Definition at line 1993 of file PlantArchitecture.py.

◆ getPlantPeduncleObjectIDs()

List[int] pyhelios.PlantArchitecture.PlantArchitecture.getPlantPeduncleObjectIDs ( self,
int plant_id )

Get object IDs for all peduncle objects on a specific plant.

   Peduncles are the stalks bearing flowers and fruit.
Parameters
plant_idID of the plant instance
Returns
List of object IDs, one per peduncle. Empty if the plant has not reached its reproductive stage, which is a normal result rather than an error.
Exceptions
ValueErrorIf plant_id is negative
PlantArchitectureErrorIf retrieval fails
Example
>>> peduncle_ids = plantarch.getPlantPeduncleObjectIDs(plant_id) >>> print(f"Plant has {len(peduncle_ids)} peduncles")

Definition at line 1420 of file PlantArchitecture.py.

◆ getPlantPetioleObjectIDs()

List[int] pyhelios.PlantArchitecture.PlantArchitecture.getPlantPetioleObjectIDs ( self,
int plant_id )

Get object IDs for all petiole objects on a specific plant.

   Petioles are the stalks attaching leaves to the stem, so this is the
   structural counterpart to :meth:`getPlantLeafObjectIDs`.
Parameters
plant_idID of the plant instance
Returns
List of object IDs, one per petiole
Exceptions
ValueErrorIf plant_id is negative
PlantArchitectureErrorIf retrieval fails
Example
>>> petiole_ids = plantarch.getPlantPetioleObjectIDs(plant_id) >>> print(f"Plant has {len(petiole_ids)} petioles")

Definition at line 1389 of file PlantArchitecture.py.

◆ getShoot()

Dict[str, Any] pyhelios.PlantArchitecture.PlantArchitecture.getShoot ( self,
int plant_id,
int shoot_id )

Get a read-only view of a shoot's topology.

Parameters
plant_idID of the plant instance
shoot_idShoot index within the plant (see :meth:getAllShootIDs)
Returns
A dict with keys rank, parent_shoot_id (-1 for the base stem), parent_node_index, and node_count.

Definition at line 1594 of file PlantArchitecture.py.

◆ getShootChildIDs()

List[int] pyhelios.PlantArchitecture.PlantArchitecture.getShootChildIDs ( self,
int plant_id,
int shoot_id )

Get the child shoot IDs of a shoot (flattened across parent node indices).

Definition at line 1605 of file PlantArchitecture.py.

◆ getShootDepth()

int pyhelios.PlantArchitecture.PlantArchitecture.getShootDepth ( self,
int plant_id,
int shoot_id )

Get the number of shoots between a shoot and the base stem shoot.

   The base stem has depth 0, its children depth 1, and so on. Unlike
   :meth:`getShootRank` this counts every step in the shoot tree, including axis
   continuations created by :meth:`appendShoot`.
Parameters
plant_idID of the plant instance
shoot_idShoot index within the plant
Returns
Number of steps from this shoot to the base stem shoot.

Definition at line 1670 of file PlantArchitecture.py.

◆ getShootHierarchyMap()

Dict[int, List[int]] pyhelios.PlantArchitecture.PlantArchitecture.getShootHierarchyMap ( self,
int plant_id )

Get the parent-to-children structure of a plant.

   Only shoots that actually have children appear as keys. Pruned shoots appear
   neither as keys nor among the children.
Parameters
plant_idID of the plant instance
Returns
Dict mapping shoot ID to the IDs of its direct children.
Example
>>> hierarchy = plantarch.getShootHierarchyMap(plant_id) >>> print(f"{len(hierarchy)} shoots carry branches")

Definition at line 1768 of file PlantArchitecture.py.

◆ getShootIDsByRank()

Dict[int, List[int]] pyhelios.PlantArchitecture.PlantArchitecture.getShootIDsByRank ( self,
int plant_id )

Group a plant's shoot IDs by branching rank.

   Rank 0 is the base stem, rank 1 its direct branches, and so on. Shoots that have
   been pruned away are not included.
Parameters
plant_idID of the plant instance
Returns
Dict mapping rank to the list of shoot IDs at that rank. Ranks with no live shoots are omitted from the dict.
Exceptions
ValueErrorIf plant_id is negative
PlantArchitectureErrorIf the plant does not exist
Example
>>> by_rank = plantarch.getShootIDsByRank(plant_id) >>> print(f"{len(by_rank.get(1, []))} primary branches")

Definition at line 2556 of file PlantArchitecture.py.

◆ getShootInternodeRadii()

List[float] pyhelios.PlantArchitecture.PlantArchitecture.getShootInternodeRadii ( self,
int plant_id,
int shoot_id )

Get the per-vertex woody internode radii of a shoot.

Definition at line 1805 of file PlantArchitecture.py.

◆ getShootInternodeVertices()

List[tuple] pyhelios.PlantArchitecture.PlantArchitecture.getShootInternodeVertices ( self,
int plant_id,
int shoot_id )

Get the woody internode polyline vertices of a shoot as a list of (x, y, z) tuples.

Definition at line 1794 of file PlantArchitecture.py.

◆ getShootRank()

int pyhelios.PlantArchitecture.PlantArchitecture.getShootRank ( self,
int plant_id,
int shoot_id )

Get the branching rank of a shoot.

   Rank is the botanical branching order: the base stem is rank 0, a branch off it
   is rank 1, and so on. A shoot created by :meth:`appendShoot` continues its
   parent's axis rather than branching from it, so it keeps the parent's rank.
   Rank is therefore not the same as :meth:`getShootDepth`.
Parameters
plant_idID of the plant instance
shoot_idShoot index within the plant
Returns
Branching rank of the shoot.
Example
>>> rank = plantarch.getShootRank(plant_id, shoot_id=3)

Definition at line 1653 of file PlantArchitecture.py.

◆ getShootVegetativeBudCount()

int pyhelios.PlantArchitecture.PlantArchitecture.getShootVegetativeBudCount ( self,
int plant_id,
int shoot_id,
Optional[BudState] state = None )

Count a shoot's axillary vegetative buds, summed over all phytomers and petioles.

   Buds are never removed from a shoot -- only their state changes -- so the
   unfiltered count is stable over the shoot's life and makes a useful denominator.
Parameters
plant_idID of the plant instance
shoot_idShoot index within the plant (see :meth:getAllShootIDs)
stateCount only buds in this :class:~pyhelios.BudState. None (the default) counts buds in every state.
Returns
The number of matching vegetative buds.
Exceptions
ValueErrorIf an identifier is negative, or ``state`` is not a BudState
PlantArchitectureErrorIf the plant or shoot does not exist
Note
BudState.DEAD means "will produce nothing further", which covers both buds that were killed and buds that have already broken into a child shoot. A dead-bud count is therefore not a count of killed buds. To test whether a shoot can still grow, count the live states instead – for example the unfiltered total minus the dead count.
Example
>>> from pyhelios import BudState >>> total = plantarch.getShootVegetativeBudCount(plant_id, 0) >>> dead = plantarch.getShootVegetativeBudCount(plant_id, 0, BudState.DEAD) >>> print(f"{total - dead} buds can still break")

Definition at line 4367 of file PlantArchitecture.py.

◆ getTerminalShootIDs()

List[int] pyhelios.PlantArchitecture.PlantArchitecture.getTerminalShootIDs ( self,
int plant_id )

Get the plant's terminal shoots – those carrying no child shoots.

   These are the tips of the shoot tree. Note that this is a topological test rather
   than a botanical one: a shoot whose axis is continued by :meth:`appendShoot` has
   that continuation as a child and so is not terminal. Pruned shoots are omitted.
Parameters
plant_idID of the plant instance
Returns
List of terminal shoot IDs.
Exceptions
ValueErrorIf plant_id is negative
PlantArchitectureErrorIf the plant does not exist
Example
>>> tips = plantarch.getTerminalShootIDs(plant_id)

Definition at line 2590 of file PlantArchitecture.py.

◆ harvestPlant()

None pyhelios.PlantArchitecture.PlantArchitecture.harvestPlant ( self,
int plant_id )

Harvest a plant by removing its flowers and fruit.

   Every non-dormant floral bud on the plant is killed, which deletes the
   associated flower, fruit and peduncle geometry from the Context. Vegetative
   structure is untouched and the plant continues to grow afterwards.
Parameters
plant_idID of the plant instance to harvest
Exceptions
ValueErrorIf plant_id is negative
PlantArchitectureErrorIf the plant does not exist or the call fails
Note
Leaves are not removed, despite what the upstream Helios documentation for harvestPlant states. Use :meth:removePlantLeaves to defoliate.
Example
>>> before = len(plantarch.getPlantFruitObjectIDs(plant_id)) >>> plantarch.harvestPlant(plant_id) >>> len(plantarch.getPlantFruitObjectIDs(plant_id)) < before True

Definition at line 2408 of file PlantArchitecture.py.

◆ is_available()

bool pyhelios.PlantArchitecture.PlantArchitecture.is_available ( self)

Check if PlantArchitecture is available in current build.

Returns
True if plugin is available, False otherwise

Definition at line 5015 of file PlantArchitecture.py.

◆ isLeafAngleDistributionTrackingEnabled()

bool pyhelios.PlantArchitecture.PlantArchitecture.isLeafAngleDistributionTrackingEnabled ( self,
int plant_id )

Whether a plant's leaf angles are being steered toward a prescribed distribution.

Parameters
plant_idID of the plant instance
Returns
True if tracking is in effect for this plant
Exceptions
ValueErrorIf ``plant_id`` is not a non-negative int
PlantArchitectureErrorIf the plant does not exist
RuntimeErrorIf the native library predates helios-core v1.3.87

Definition at line 4614 of file PlantArchitecture.py.

◆ isPlantDormant()

bool pyhelios.PlantArchitecture.PlantArchitecture.isPlantDormant ( self,
int plant_id )

Check whether a plant is dormant.

Parameters
plant_idIdentifier of the plant to check
Returns
True if all shoots on the plant are dormant, False otherwise
Exceptions
ValueErrorIf plant_id is negative
PlantArchitectureErrorIf the plant does not exist or the query fails
Example
>>> plantarch.makePlantDormant(plant_id) >>> plantarch.isPlantDormant(plant_id) True

Definition at line 2327 of file PlantArchitecture.py.

◆ isShootGeometryPrescribed()

bool pyhelios.PlantArchitecture.PlantArchitecture.isShootGeometryPrescribed ( self,
int plant_id,
int shoot_id )

Report whether a shoot's existing geometry was prescribed by the caller rather than generated.

   True for a shoot built by :meth:`addShootFromNodePositions`, whose internode path
   follows measured node positions. Such a shoot's existing phytomers are exempt
   from the re-scaling and re-curving performed by :meth:`advanceTime`, so a caller
   reading geometry back can tell which parts of a plant are measurement and which
   are model output.

   Requires helios-core v1.3.85 or newer.
Parameters
plant_idID of the plant instance
shoot_idShoot index within the plant
Returns
True if the shoot was built from prescribed node positions
Exceptions
ValueErrorIf either ID is negative
PlantArchitectureErrorIf the query fails or the library predates v1.3.85

Definition at line 1945 of file PlantArchitecture.py.

◆ isShootPruned()

bool pyhelios.PlantArchitecture.PlantArchitecture.isShootPruned ( self,
int plant_id,
int shoot_id )

Report whether a shoot has been pruned away entirely.

   :meth:`pruneBranch` called with ``node_index=0`` removes all of a shoot's
   phytomers and geometry but keeps the shoot in the plant's tree so that shoot IDs
   stay stable. Such a shoot is still returned by :meth:`getAllShootIDs` but is
inert   it has zero nodes, contributes no leaf area, and cannot be queried for
   geometry. Use this to skip those shoots when walking :meth:`getAllShootIDs`.
Parameters
plant_idID of the plant instance
shoot_idShoot index within the plant
Returns
True if the shoot was pruned away and no longer forms part of the plant.
Example
>>> live = [s for s in plantarch.getAllShootIDs(plant_id) ... if not plantarch.isShootPruned(plant_id, s)]

Definition at line 1693 of file PlantArchitecture.py.

◆ listShootTypeLabels()

List[str] pyhelios.PlantArchitecture.PlantArchitecture.listShootTypeLabels ( self,
Optional[str] plant_model = None,
Optional[int] plant_id = None )

Get the shoot type labels defined for a plant model.

   Shoot type labels are species-specific strings such as "trunk" or "scaffold", and
   every shoot-parameter call takes one. Use this to discover the valid labels rather
   than guessing them.
Parameters
plant_modelQuery this library model without changing the currently loaded one. Use getAvailablePlantModels() for valid names. Mutually exclusive with plant_id.
plant_idQuery the shoot types captured by this plant instance when it was created. Mutually exclusive with plant_model.

With neither argument, queries the currently loaded model, which requires a prior call to loadPlantModelFromLibrary().

Returns
List of shoot type label strings.
Exceptions
ValueErrorIf both plant_model and plant_id are given, or plant_id is negative
PlantArchitectureErrorIf no model is loaded, or the model or plant is unknown
Example
>>> plantarch.loadPlantModelFromLibrary("almond") >>> plantarch.listShootTypeLabels() ['proleptic', 'scaffold', 'sylleptic', 'trunk'] >>> plantarch.listShootTypeLabels(plant_model="bean") ['trifoliate', 'unifoliate']

Definition at line 1074 of file PlantArchitecture.py.

◆ loadPlantModelFromLibrary()

None pyhelios.PlantArchitecture.PlantArchitecture.loadPlantModelFromLibrary ( self,
str plant_label )

Load a plant model from the built-in library.

Parameters
plant_labelPlant model identifier from library. Available models include: "almond", "apple", "bean", "bindweed", "butterlettuce", "capsicum", "cheeseweed", "cowpea", "easternredbud", "grapevine_VSP", "maize", "olive", "pistachio", "puncturevine", "rice", "sorghum", "soybean", "strawberry", "sugarbeet", "tomato", "cherrytomato", "walnut", "wheat"
Exceptions
ValueErrorIf plant_label is empty or invalid
PlantArchitectureErrorIf model loading fails
Example
>>> plantarch.loadPlantModelFromLibrary("bean") >>> plantarch.loadPlantModelFromLibrary("almond")

Definition at line 375 of file PlantArchitecture.py.

◆ makePlantDormant()

None pyhelios.PlantArchitecture.PlantArchitecture.makePlantDormant ( self,
int plant_id )

Force a plant into a dormant state immediately.

   This is the direct equivalent of ``makePlantDormant()`` in helios-core, as called by the
   library builders such as ``buildAppleTree()``. It is the counterpart to scheduling dormancy
through this forces the state now, rather than
   waiting for a degree-day threshold to be crossed.

   Dormancy strips the plant's leaves and marks its non-dormant buds dormant, so a
   custom-built plant can be put into the same over-winter state that a library-built
   perennial reaches through phenology.
Parameters
plant_idIdentifier of the plant to make dormant
Exceptions
ValueErrorIf plant_id is negative
PlantArchitectureErrorIf the plant does not exist or the call fails
Example
>>> plant_id = plantarch.addPlantInstance(vec3(0, 0, 0), 0.0) >>> plantarch.addBaseStemShoot(plant_id, 3, AxisRotation(0, 0, 0), ... 0.01, 0.1, 1.0, 1.0, 0.9, "trifoliate") >>> plantarch.makePlantDormant(plant_id)

Definition at line 2270 of file PlantArchitecture.py.

◆ optionalOutputObjectData()

None pyhelios.PlantArchitecture.PlantArchitecture.optionalOutputObjectData ( self,
Union[str, List[str]] object_data_labels )

Enable optional output object data to be written to the Context.

   By default, the plant architecture model only writes a minimal set of
   object data. This method enables additional object data fields so that
   they are available on the Context's compound objects after building.
Parameters
object_data_labelsA single label or a list of labels to enable. Valid labels include: "age", "rank", "plantID", "plant_name", "plant_height", "plant_type", "phenology_stage", "leafID", "peduncleID", "closedflowerID", "openflowerID", "fruitID", "carbohydrate_concentration". The special label "all" enables every available field.
Exceptions
ValueErrorIf a label is empty or not a string
PlantArchitectureErrorIf an invalid label is supplied or the operation otherwise fails
Example
>>> plantarch.optionalOutputObjectData("age") >>> plantarch.optionalOutputObjectData(["rank", "plant_height"]) >>> plantarch.optionalOutputObjectData("all")

Definition at line 2119 of file PlantArchitecture.py.

◆ pruneBranch()

None pyhelios.PlantArchitecture.PlantArchitecture.pruneBranch ( self,
int plant_id,
int shoot_id,
int node_index )

Prune a shoot at a node, removing that node and everything distal to it.

   The phytomer at ``node_index`` is deleted along with every phytomer above it
   on the same shoot, and the cut recurses into every child shoot attached at or
   above that node. The shoot's woody internode tube is trimmed back to the cut
   and its apical bud is terminated, so the pruned axis will not resume growing.
   Pruning at ``node_index=0`` therefore removes the entire shoot and its whole
   branch system.
Parameters
plant_idID of the plant instance
shoot_idShoot index within the plant (see :meth:getAllShootIDs)
node_indexNode on the shoot to cut at, in [0, node_count)
Exceptions
ValueErrorIf any identifier is negative
PlantArchitectureErrorIf the plant or shoot does not exist, if node_index is beyond the shoot's current node count, or if the native call fails
Note
A pruned shoot currently keeps its ID in :meth:getAllShootIDs with a node_count of 0 rather than disappearing. Do not rely on either behavior; traverse with :meth:getShoot and treat node_count == 0 as "nothing left here".
Example
>>> # Remove a whole branch and everything growing off it >>> plantarch.pruneBranch(plant_id, shoot_id=3, node_index=0) >>> # Head back a leader, keeping its lowest 5 nodes >>> plantarch.pruneBranch(plant_id, shoot_id=0, node_index=5)

Definition at line 2372 of file PlantArchitecture.py.

◆ pruneShootsByRank()

List[int] pyhelios.PlantArchitecture.PlantArchitecture.pruneShootsByRank ( self,
int plant_id,
int min_rank )

Prune every shoot at or above a given branching rank.

   This is the "remove higher-order branches" thinning operation: passing
   ``min_rank=3`` leaves the base stem and its first two orders of branching
   intact and cuts everything finer. Because :meth:`pruneBranch` already
   recurses into child shoots, only the shallowest shoot on each pruned axis is
   cut and the rest follow.
Parameters
plant_idID of the plant instance
min_rankLowest rank to prune. Must be at least 1 – rank 0 is the base stem, and pruning it would destroy the plant.
Returns
Ascending list of the shoot IDs actually cut. Shoots removed as a side effect of a shallower cut are not listed.
Exceptions
ValueErrorIf plant_id is negative or min_rank is less than 1
PlantArchitectureErrorIf the plant does not exist
Note
To remove a whole plant use :meth:deletePlantInstance; to cut the base stem itself call :meth:pruneBranch directly.
Example
>>> pruned = plantarch.pruneShootsByRank(plant_id, min_rank=3) >>> print(f"Cut {len(pruned)} higher-order branches")

Definition at line 2631 of file PlantArchitecture.py.

◆ pruneShootSubtree()

List[int] pyhelios.PlantArchitecture.PlantArchitecture.pruneShootSubtree ( self,
int plant_id,
int shoot_id,
bool include_self = True )

Prune a shoot and everything growing off it.

Parameters
plant_idID of the plant instance
shoot_idRoot of the branch system to remove
include_selfIf True (default) the shoot itself is cut at node 0. If False the shoot is kept and only its child shoots are cut.
Returns
Ascending list of the shoot IDs actually cut. Shoots removed as a side effect of a shallower cut are not listed.
Exceptions
ValueErrorIf either identifier is negative
PlantArchitectureErrorIf the plant or shoot does not exist
Example
>>> # Remove a whole branch system >>> plantarch.pruneShootSubtree(plant_id, shoot_id=2) >>> # Keep the cane but strip everything growing off it >>> plantarch.pruneShootSubtree(plant_id, shoot_id=2, include_self=False)

Definition at line 2669 of file PlantArchitecture.py.

◆ pruneTerminalShoots()

List[int] pyhelios.PlantArchitecture.PlantArchitecture.pruneTerminalShoots ( self,
int plant_id,
int stride = 2 )

Thin a plant by pruning every stride-th terminal shoot.

   Terminal shoots are taken in ascending ID order and every ``stride``-th one
   starting from the first is cut, so ``stride=2`` removes about half the tips
   and ``stride=3`` about a third. The base stem is never cut.
Parameters
plant_idID of the plant instance
strideSpacing between pruned tips. Must be at least 1; stride=1 prunes every terminal shoot.
Returns
Ascending list of the shoot IDs actually cut.
Exceptions
ValueErrorIf plant_id is negative or stride is less than 1
PlantArchitectureErrorIf the plant does not exist
Example
>>> pruned = plantarch.pruneTerminalShoots(plant_id, stride=2) >>> print(f"Thinned {len(pruned)} tips")

Definition at line 2701 of file PlantArchitecture.py.

◆ readPlantStructureXML()

List[int] pyhelios.PlantArchitecture.PlantArchitecture.readPlantStructureXML ( self,
Union[str, Path] filename,
bool quiet = False )

Load plant structure from XML file.

   This method reads plant architecture data from an XML file previously saved with
   writePlantStructureXML(). The loaded plants are added to the current context
   and can be grown, modified, or analyzed like any other plants.
Parameters
filenamePath to XML file to load (absolute or relative to current working directory)
quietIf True, suppress console output during loading (default: False)
Returns
List of plant IDs for the loaded plant instances
Exceptions
ValueErrorIf filename is empty
PlantArchitectureErrorIf file doesn't exist, cannot be parsed, or loading fails
Note
The XML file can contain multiple plant instances. All plants in the file will be loaded and their IDs returned in a list. Plant models referenced in the XML must be available in the plant library.
Example
>>> # Load previously saved plants >>> plant_ids = plantarch.readPlantStructureXML("saved_canopy.xml") >>> print(f"Loaded {len(plant_ids)} plants") >>> >>> # Continue growing the loaded plants >>> plantarch.advanceTime(10.0) >>> >>> # Load quietly without console messages >>> plant_ids = plantarch.readPlantStructureXML("bean_day45.xml", quiet=True)

Definition at line 3488 of file PlantArchitecture.py.

◆ recordPetioleRestShape()

None pyhelios.PlantArchitecture.PlantArchitecture.recordPetioleRestShape ( self,
int plant_id,
int shoot_id,
int node_index,
int petiole_index )

Record one petiole's current centerline as its undeformed rest shape.

   :meth:`bendPetioleUnderLeafWeight` always bends from the recorded rest shape, so a
   petiole whose centerline has been replaced wholesale -- by
   :meth:`setPetioleNodePositions`, for instance -- must have its new shape recorded
   before it will droop from it. This also marks the petiole as needing to be bent
   again, so the next bend is not skipped as redundant.
Parameters
plant_idID of the plant instance
shoot_idShoot index within the plant
node_indexPhytomer index within the shoot
petiole_indexPetiole within the phytomer
Exceptions
ValueErrorIf any identifier is not a non-negative int
PlantArchitectureErrorIf the plant, shoot, node or petiole does not exist
RuntimeErrorIf the native library predates helios-core v1.3.87

Definition at line 4937 of file PlantArchitecture.py.

◆ registerGrowthFrame()

None pyhelios.PlantArchitecture.PlantArchitecture.registerGrowthFrame ( self,
int plant_id,
float min_segment_length = 0.001 )

Capture a snapshot of the plant's geometry as a growth animation frame.

   Call this after each :meth:`advanceTime` step to record the plant state for later
   animation export via :meth:`writePlantGrowthUSD`.
Parameters
plant_idID of the plant instance to capture
min_segment_lengthMinimum segment length (m); shorter segments are skipped
Exceptions
ValueErrorIf plant_id is negative
PlantArchitectureErrorIf plant doesn't exist

Definition at line 3370 of file PlantArchitecture.py.

◆ removePlantLeaves()

None pyhelios.PlantArchitecture.PlantArchitecture.removePlantLeaves ( self,
int plant_id )

Remove all leaves from every shoot on a plant.

   Leaf and petiole geometry is deleted from the Context. Buds are left alive,
   so the plant can produce new leaves as it continues to grow.
Parameters
plant_idID of the plant instance to defoliate
Exceptions
ValueErrorIf plant_id is negative
PlantArchitectureErrorIf the plant does not exist or the call fails
Example
>>> plantarch.removePlantLeaves(plant_id) >>> plantarch.getPlantLeafObjectIDs(plant_id) []

Definition at line 2436 of file PlantArchitecture.py.

◆ removeShootFloralBuds()

None pyhelios.PlantArchitecture.PlantArchitecture.removeShootFloralBuds ( self,
int plant_id,
int shoot_id )

Kill all floral buds on a single shoot.

   Existing flower, fruit and peduncle geometry on the shoot is deleted and no
   new flowers will form there.
Parameters
plant_idID of the plant instance
shoot_idShoot index within the plant (see :meth:getAllShootIDs)
Exceptions
ValueErrorIf either identifier is negative
PlantArchitectureErrorIf the plant or shoot does not exist
Example
>>> plantarch.removeShootFloralBuds(plant_id, shoot_id=1)

Definition at line 2515 of file PlantArchitecture.py.

◆ removeShootLeaves()

None pyhelios.PlantArchitecture.PlantArchitecture.removeShootLeaves ( self,
int plant_id,
int shoot_id )

Remove all leaves from a single shoot.

Parameters
plant_idID of the plant instance
shoot_idShoot index within the plant (see :meth:getAllShootIDs)
Exceptions
ValueErrorIf either identifier is negative
PlantArchitectureErrorIf the plant or shoot does not exist
Example
>>> # Strip the leaves off a grapevine trunk, as in a trained architecture >>> plantarch.removeShootLeaves(plant_id, shoot_id=0)

Definition at line 2461 of file PlantArchitecture.py.

◆ removeShootVegetativeBuds()

None pyhelios.PlantArchitecture.PlantArchitecture.removeShootVegetativeBuds ( self,
int plant_id,
int shoot_id )

Mark every vegetative bud on a single shoot as dead.

   Despite the name, nothing is removed: each axillary vegetative bud on the shoot
   is set to ``BudState.DEAD`` and the bud entries themselves stay in place, so
   :meth:`getShootVegetativeBudCount` still sees them and the unfiltered count is
   unchanged. Dead buds are skipped when dormancy breaks, so the shoot keeps its
   existing structure but produces no new lateral shoots -- the standard way to stop
   a trained axis from throwing new canes, and to stop the old wood of a
   reconstructed tree re-growing.

   This is exactly equivalent to setting every bud on the shoot to
   ``BudState.DEAD``; the shoot's own apex is unaffected, so pair it with
   :meth:`terminateApicalBud` to stop the shoot extending as well.
Parameters
plant_idID of the plant instance
shoot_idShoot index within the plant (see :meth:getAllShootIDs)
Exceptions
ValueErrorIf either identifier is negative
PlantArchitectureErrorIf the plant or shoot does not exist
       :meth:`getShootVegetativeBudCount`, to confirm the buds are dead rather than
       gone, and :meth:`terminateApicalBud`, for the shoot's apex.
Example
>>> plantarch.removeShootVegetativeBuds(plant_id, shoot_id=1)

Definition at line 2494 of file PlantArchitecture.py.

◆ scaleLeafSizeMax()

None pyhelios.PlantArchitecture.PlantArchitecture.scaleLeafSizeMax ( self,
int plant_id,
int shoot_id,
int node_index,
float scale_factor )

Scale the size every leaf on a phytomer is expanding toward, leaving the blades where they are.

The blade's present size is untouched and only its target changes, so the expansion fraction moves the other way: a fully-expanded leaf given a larger target becomes a partly-expanded leaf of the same size and goes on growing on the next :meth:advanceTime. This is what hands a leaf built from measured geometry back to the growth model still the size it was measured.

A factor small enough to put the target below the leaf's present size is the one case in which the blade does move: the leaf is taken down to the new target, and the leaflets of a compound leaf are then re-seated along the petiole, discarding a placement prescribed by :meth:setPetioleLeafGeometry.

Parameters
plant_idID of the plant instance
shoot_idShoot index within the plant
node_indexPhytomer index within the shoot
scale_factorFactor to scale the mature leaf size by; must be positive
Exceptions
ValueErrorIf an identifier is invalid or ``scale_factor`` is not positive
PlantArchitectureErrorIf the plant, shoot or node does not exist
RuntimeErrorIf the native library predates helios-core v1.3.87

Definition at line 4809 of file PlantArchitecture.py.

◆ scalePetioleMaxLength()

None pyhelios.PlantArchitecture.PlantArchitecture.scalePetioleMaxLength ( self,
int plant_id,
int shoot_id,
int node_index,
float scale_factor )

Scale the fully-elongated length every petiole on a phytomer is growing toward.

   The petiole counterpart of internode max-length scaling. The petiole's present
   length is left where it is and only its target changes, so a phytomer creation
   function can give a leaf born on a young plant a shorter final petiole without
   moving the petiole that is already there.
Parameters
plant_idID of the plant instance
shoot_idShoot index within the plant
node_indexPhytomer index within the shoot
scale_factorFactor to scale the fully-elongated length by; must be positive
Exceptions
ValueErrorIf an identifier is invalid or ``scale_factor`` is not positive
PlantArchitectureErrorIf the plant, shoot or node does not exist
RuntimeErrorIf the native library predates helios-core v1.3.87

Definition at line 4690 of file PlantArchitecture.py.

◆ setAttractionParameters()

None pyhelios.PlantArchitecture.PlantArchitecture.setAttractionParameters ( self,
float view_half_angle_deg,
float look_ahead_distance,
float attraction_weight,
float obstacle_reduction_factor = 0.75,
Optional[int] plant_id = None )

Tune how strongly attraction points steer growth.

Parameters
view_half_angle_degHalf-angle of the search cone in degrees
look_ahead_distanceHow far ahead a shoot tip looks, in meters
attraction_weightStrength of the steering, 0 to 1
obstacle_reduction_factorScales attraction where an obstacle intervenes
plant_idApply to this plant only. Applies globally when None.
Exceptions
ValueErrorIf plant_id is negative
PlantArchitectureErrorIf the operation fails

Definition at line 731 of file PlantArchitecture.py.

◆ setCancelFlag()

pyhelios.PlantArchitecture.PlantArchitecture.setCancelFlag ( self,
cancel_flag )

Register an external cancellation flag polled during long plant builds.

   ``cancel_flag`` is a ctypes.c_int that, when set non-zero from another
   thread, stops the canopy build loop and the advanceTime() growth loop
   between plants/timesteps — so a long generation can be aborted mid-build
   (returning whatever was built so far). Set it before the build call; pass
   None to clear. The flag is caller-owned and must outlive the build.

Definition at line 806 of file PlantArchitecture.py.

◆ setCollisionRelevantOrgans()

None pyhelios.PlantArchitecture.PlantArchitecture.setCollisionRelevantOrgans ( self,
bool include_internodes = False,
bool include_leaves = True,
bool include_petioles = False,
bool include_flowers = False,
bool include_fruit = False )

Specify which plant organs participate in collision detection.

   This method allows filtering which organs are considered during collision detection,
   enabling optimization by excluding organs unlikely to cause problematic collisions.
Parameters
include_internodesInclude stem internodes in collision detection
include_leavesInclude leaf blades in collision detection
include_petiolesInclude leaf petioles in collision detection
include_flowersInclude flowers in collision detection
include_fruitInclude fruit in collision detection
Exceptions
PlantArchitectureErrorIf organ filtering fails
Example
>>> # Only detect collisions for stems and leaves (default behavior) >>> plantarch.setCollisionRelevantOrgans( ... include_internodes=True, ... include_leaves=True ... ) >>> >>> # Include all organs >>> plantarch.setCollisionRelevantOrgans( ... include_internodes=True, ... include_leaves=True, ... include_petioles=True, ... include_flowers=True, ... include_fruit=True ... )

Definition at line 2995 of file PlantArchitecture.py.

◆ setLeafNormal()

None pyhelios.PlantArchitecture.PlantArchitecture.setLeafNormal ( self,
int plant_id,
int shoot_id,
int node_index,
int petiole_index,
int leaf_index,
vec3 target_normal )

Re-aim one leaf so its blade faces a given direction.

   The roll and pitch that carry the blade onto ``target_normal`` are applied as a
   single rotation about the leaf's own base, so the leaf stays attached to its petiole
   and keeps the azimuth of the petiole it hangs from. The angles are recorded on the
   phytomer, which is what makes the new orientation survive a
   :meth:`writePlantStructureXML` / :meth:`readPlantStructureXML` round trip --
   rotating the leaf object directly through the Context changes the geometry without
   changing the record and is silently lost on reload.
Parameters
plant_idID of the plant instance
shoot_idShoot index within the plant
node_indexPhytomer index within the shoot
petiole_indexPetiole within the phytomer
leaf_indexLeaf within the petiole
target_normalDirection the blade should face, in world coordinates. Need not be normalized.
Exceptions
ValueErrorIf an identifier is invalid, or ``target_normal`` is not a vec3
PlantArchitectureErrorIf the leaf has no geometry, the blade's facet normals cancel, or the target cannot be reached by a roll-pitch pair
RuntimeErrorIf the native library predates helios-core v1.3.87
Example
>>> from pyhelios.types import vec3 >>> plantarch.setLeafNormal(plant_id, 0, 3, 0, 0, vec3(0, 0, 1))

Definition at line 4854 of file PlantArchitecture.py.

◆ setPetioleAndLeafScaleFraction()

None pyhelios.PlantArchitecture.PlantArchitecture.setPetioleAndLeafScaleFraction ( self,
int plant_id,
int shoot_id,
int node_index,
int petiole_index,
float petiole_scale_factor_fraction,
float leaf_scale_factor_fraction )

Set a petiole's length and its leaves' size together, each as a fraction of its own fully-elongated value.

The two fractions are applied in one pass, so the leaves are scaled, re-seated along the rescaled petiole and bent under their new weight once rather than twice. Use this rather than the two single-fraction calls when advancing both.

Parameters
plant_idID of the plant instance
shoot_idShoot index within the plant
node_indexPhytomer index within the shoot
petiole_indexPetiole within the phytomer
petiole_scale_factor_fractionFraction of the fully-elongated petiole length
leaf_scale_factor_fractionFraction of the fully-elongated leaf scale factor
Exceptions
ValueErrorIf any identifier is not a non-negative int
PlantArchitectureErrorIf the plant, shoot, node or petiole does not exist
RuntimeErrorIf the native library predates helios-core v1.3.87

Definition at line 4765 of file PlantArchitecture.py.

◆ setPetioleLeafCount()

None pyhelios.PlantArchitecture.PlantArchitecture.setPetioleLeafCount ( self,
int plant_id,
int shoot_id,
int node_index,
int petiole_index,
int leaf_count )

Change the number of leaves (leaflets) on one petiole of an existing phytomer.

   The leaves are rebuilt procedurally. Without this, the count is fixed by the shoot
   type's ``leaf.leaves_per_petiole`` for every phytomer, so a measured compound leaf
   with a different number of leaflets could not be prescribed with
   :meth:`setPetioleLeafGeometry`.
Parameters
plant_idPlant identifier.
shoot_idShoot identifier.
node_indexIndex of the phytomer along the shoot.
petiole_indexIndex of the petiole on that phytomer.
leaf_countNumber of leaves to place on the petiole. Must be at least 1.
Exceptions
ValueErrorIf any index is negative or ``leaf_count`` is less than 1.
PlantArchitectureErrorIf the operation fails.
Note
Call this before :meth:setPetioleLeafGeometry for the same petiole, whose leaf_count must match the number of leaves on the petiole.

Definition at line 4243 of file PlantArchitecture.py.

◆ setPetioleLeafGeometry()

None pyhelios.PlantArchitecture.PlantArchitecture.setPetioleLeafGeometry ( self,
int plant_id,
int shoot_id,
int node_index,
int petiole_index,
List[vec3] leaf_bases,
List[AxisRotation] leaf_rotations,
List[float] leaf_sizes )

Prescribe the base position, orientation and size of every leaf on a petiole.

   This is the leaf-level counterpart of :meth:`setPetioleNodePositions`, intended
   for the same reconstruction workflow. Every leaf on the petiole is prescribed in
one for a compound leaf the leaflets are not independent, since a
   leaflet's roll and yaw signs and the prototype it is a copy of all follow from
   its position along the petiole. A species with one leaf per petiole passes
   one-element lists.

   Each leaf is rebuilt from its prototype and re-oriented through the same
   rotation chain used when a leaf is grown. The prescribed base, orientation and
   size are held exactly and are not changed by :meth:`advanceTime`; prescribed
   leaves are additionally exempt from the self-weight droop.

   **Rotation units and frame.** ``leaf_rotations`` are given in **radians**, as
   pitch, yaw and roll relative to the petiole and internode axes, not to world
   axes (the same convention as the native ``Phytomer::leaf_rotation``). The full
   chain that places a leaf includes the petiole's own azimuth and a
   size-dependent correction and is not invertible, so there is no exact
   conversion from a world-frame blade orientation; a caller fitting to measured
   data should iterate by forward evaluation, reading the resulting geometry back
   from the Context.

   Requires helios-core v1.3.85 or newer.
Parameters
plant_idID of the plant instance
shoot_idID of the shoot carrying the phytomer
node_indexIndex of the phytomer within the shoot, counted from the base
petiole_indexIndex of the petiole within the phytomer
leaf_basesBase position of each leaf in world coordinates, one per leaf on the petiole, in the petiole's existing leaf order
leaf_rotationsAxisRotation(pitch, yaw, roll) of each leaf in radians
leaf_sizesFully elongated size of each leaf in meters. All must be > 0
Exceptions
ValueErrorIf any index is negative, a base is not a vec3, a rotation is not an AxisRotation, a size is not positive, or the three lists differ in length
PlantArchitectureErrorIf the number of leaves does not match the petiole (the count is fixed when the phytomer is created), the native call fails, or the library predates v1.3.85
Note
Rebuilding each leaf discards primitive data a caller has attached to it. The object label and material are restored; other primitive data is not.

Definition at line 4169 of file PlantArchitecture.py.

◆ setPetioleNodePositions()

None pyhelios.PlantArchitecture.PlantArchitecture.setPetioleNodePositions ( self,
int plant_id,
int shoot_id,
int node_index,
int petiole_index,
List[vec3] node_positions,
List[float] node_radii )

Prescribe the path of a petiole on an existing phytomer from measured node positions.

   This is the organ-level counterpart of :meth:`addShootFromNodePositions`. Where
   that method prescribes the internode skeleton of a shoot, this one prescribes the
   centerline of a single petiole hanging off it, so that a reconstruction from
   labelled measurements (a segmented point cloud, a digitized plant) can follow the
   measured petiole rather than the path the shoot type's petiole pitch and
   curvature would generate.

   The supplied positions are the nodes of the petiole tube, ordered from the base
   outward. Their number is free and need not match the shoot type's
   ``petiole.length_segments``; the petiole tube is rebuilt to match. The first
   position is snapped onto the tip of the internode the petiole grows from and the
   rest of the path is translated by the same amount, so all relative geometry is
   preserved exactly. An error is raised if that discrepancy is large enough that
   the petiole would not be attached to the stem.

   The prescribed petiole is not re-scaled by subsequent calls to
   :meth:`advanceTime`, and its radii are held as given.

   Requires helios-core v1.3.85 or newer.
Parameters
plant_idID of the plant instance
shoot_idID of the shoot carrying the phytomer
node_indexIndex of the phytomer within the shoot, counted from the base
petiole_indexIndex of the petiole within the phytomer
node_positionsPetiole node positions in world coordinates, base to tip. At least two are required, and no two consecutive positions may be coincident
node_radiiRadius of the petiole at each node, one per position. All must be > 0
Exceptions
ValueErrorIf any index is negative, a position is not a vec3, a radius is not positive, fewer than two nodes are given, or the counts differ
PlantArchitectureErrorIf the native call fails or the library predates v1.3.85
Note
Call this before :meth:setPetioleLeafGeometry for the same petiole, since leaf placement is oriented from the petiole axis.

Definition at line 4099 of file PlantArchitecture.py.

◆ setPetioleScaleFraction()

None pyhelios.PlantArchitecture.PlantArchitecture.setPetioleScaleFraction ( self,
int plant_id,
int shoot_id,
int node_index,
int petiole_index,
float petiole_scale_factor_fraction )

Set one petiole's current length as a fraction of its fully-elongated length, leaving the leaves it carries at the size they are.

A petiole is a stem segment rather than part of the blade and goes on extending after the blade has finished expanding, which is why its growth is driven by the shoot's internode rate rather than the leaf expansion rate. The leaves ride out along the petiole as it lengthens without changing size.

Parameters
plant_idID of the plant instance
shoot_idShoot index within the plant
node_indexPhytomer index within the shoot
petiole_indexPetiole within the phytomer
petiole_scale_factor_fractionFraction of the fully-elongated length (1.0 for a fully-elongated petiole)
Exceptions
ValueErrorIf any identifier is not a non-negative int
PlantArchitectureErrorIf the plant, shoot, node or petiole does not exist
RuntimeErrorIf the native library predates helios-core v1.3.87

Definition at line 4727 of file PlantArchitecture.py.

◆ setPlantCarbohydrateParameters()

None pyhelios.PlantArchitecture.PlantArchitecture.setPlantCarbohydrateParameters ( self,
int plant_id,
Union[dict, CarbohydrateParameters] parameters )

Set carbohydrate-model parameters for a plant.

Parameters
plant_idTarget plant instance ID
parametersA flat dict or a CarbohydrateParameters object.
Exceptions
ValueErrorIf parameters is not a dict or CarbohydrateParameters
PlantArchitectureErrorIf the operation fails

Definition at line 959 of file PlantArchitecture.py.

◆ setPlantMaxAge()

None pyhelios.PlantArchitecture.PlantArchitecture.setPlantMaxAge ( self,
int plant_id,
float max_age )

Set the maximum age of a plant, beyond which it stops growing.

   Once a plant's age reaches this value, :meth:`advanceTime` stops advancing it and
   its geometry becomes static. The default is 999 days. Every plant model in the
   library sets its own value as part of its builder (an apple tree, for example,
   uses 1460 days), but a plant assembled manually with :meth:`addPlantInstance`
   keeps the default and so silently stops growing after 999 days.

   Setting a maximum age below the plant's current age is permitted, and freezes the
   plant at its current form.
Parameters
plant_idID of the plant instance
max_ageMaximum age of the plant in days. Must be non-negative.
Exceptions
ValueErrorIf plant_id is negative or max_age is negative
PlantArchitectureErrorIf the plant does not exist
Example
>>> plantarch.setPlantMaxAge(plant_id, 1460.0)

Definition at line 2026 of file PlantArchitecture.py.

◆ setPlantNitrogenParameters()

None pyhelios.PlantArchitecture.PlantArchitecture.setPlantNitrogenParameters ( self,
int plant_id,
Union[dict, NitrogenParameters] parameters )

Set nitrogen-model parameters for a plant.

Parameters
plant_idTarget plant instance ID
parametersA flat dict or a NitrogenParameters object.
Exceptions
ValueErrorIf parameters is not a dict or NitrogenParameters
PlantArchitectureErrorIf the operation fails

Definition at line 1007 of file PlantArchitecture.py.

◆ setPlantPhenologicalThresholds()

None pyhelios.PlantArchitecture.PlantArchitecture.setPlantPhenologicalThresholds ( self,
int plant_id,
float time_to_dormancy_break,
float time_to_flower_initiation,
float time_to_flower_opening,
float time_to_fruit_set,
float time_to_fruit_maturity,
float time_to_dormancy,
float max_leaf_lifespan = 1e6,
bool is_evergreen = False )

Set phenological timing thresholds for plant developmental stages.

   Controls the timing of key phenological events based on thermal time
   or calendar time depending on the plant model.
Parameters
plant_idID of the plant instance
time_to_dormancy_breakDegree-days or days until dormancy ends
time_to_flower_initiationTime until flower buds are initiated
time_to_flower_openingTime until flowers open
time_to_fruit_setTime until fruit begins developing
time_to_fruit_maturityTime until fruit reaches maturity
time_to_dormancyTime until plant enters dormancy
max_leaf_lifespanMaximum leaf lifespan in days (default: 1e6)
is_evergreenIf True, the plant retains leaves through dormancy instead of shedding them at senescence (default: False)
Exceptions
ValueErrorIf plant_id is negative
PlantArchitectureErrorIf phenology setting fails
Example
>>> # Set phenology for perennial fruit tree >>> plantarch.setPlantPhenologicalThresholds( ... plant_id=plant_id, ... time_to_dormancy_break=60, # Spring: 60 degree-days ... time_to_flower_initiation=90, # Early spring flowering ... time_to_flower_opening=105, # Bloom period ... time_to_fruit_set=120, # Fruit set after pollination ... time_to_fruit_maturity=200, # Summer fruit maturation ... time_to_dormancy=280, # Fall dormancy ... max_leaf_lifespan=180 # Deciduous - 6 month leaf life ... )

Definition at line 2170 of file PlantArchitecture.py.

◆ setProgressCallback()

pyhelios.PlantArchitecture.PlantArchitecture.setProgressCallback ( self,
callback )

Set a callback to receive progress updates during long-running operations.

   The callback fires during advanceTime() and adjustFruitForObstacleCollision()
   as the underlying ProgressBar updates.
Parameters
callbackA callable(progress: float, message: str) where progress is in [0, 1], or None to clear the callback.
Exceptions
ValueErrorIf callback is not callable and not None.

Definition at line 778 of file PlantArchitecture.py.

◆ setShootInternodeLengthMax()

None pyhelios.PlantArchitecture.PlantArchitecture.setShootInternodeLengthMax ( self,
int plant_id,
int shoot_id,
float internode_length_max )

Set the target length of internodes grown at the apex of an existing shoot.

   A shoot built by :meth:`addShootFromNodePositions` otherwise grows toward the mean
   of its prescribed internode lengths, so a measured seedling -- whose measured stem
   is mostly hypocotyl -- could not be grown forward with realistic internodes.
Parameters
plant_idPlant identifier.
shoot_idShoot identifier.
internode_length_maxTarget internode length in meters. Must be positive.
Exceptions
ValueErrorIf an identifier is negative or the length is not positive.
PlantArchitectureErrorIf the operation fails.
Note
This value is not saved by :meth:writePlantStructureXML, so it must be set again after :meth:readPlantStructureXML.

Definition at line 4282 of file PlantArchitecture.py.

◆ setSoftCollisionAvoidanceParameters()

None pyhelios.PlantArchitecture.PlantArchitecture.setSoftCollisionAvoidanceParameters ( self,
float view_half_angle_deg = 80.0,
float look_ahead_distance = 0.1,
int sample_count = 256,
float inertia_weight = 0.4 )

Configure parameters for soft collision avoidance algorithm.

   These parameters control the cone-based gap detection algorithm that guides
   plant growth away from obstacles. Adjusting these values allows fine-tuning
   the balance between collision avoidance and natural growth patterns.
Parameters
view_half_angle_degHalf-angle of detection cone in degrees (0-180). Default 80° provides wide field of view.
look_ahead_distanceDistance to look ahead for collisions in meters. Larger values detect distant obstacles. Default 0.1m.
sample_countNumber of ray samples within cone. More samples improve accuracy but reduce performance. Default 256.
inertia_weightWeight for previous growth direction (0-1). Higher values make growth smoother but less responsive. Default 0.4.
Exceptions
ValueErrorIf parameters are outside valid ranges
PlantArchitectureErrorIf parameter setting fails
Example
>>> # Use default parameters (recommended) >>> plantarch.setSoftCollisionAvoidanceParameters() >>> >>> # Tune for dense canopy with close obstacles >>> plantarch.setSoftCollisionAvoidanceParameters( ... view_half_angle_deg=60.0, # Narrower detection cone ... look_ahead_distance=0.05, # Shorter look-ahead ... sample_count=512, # More accurate detection ... inertia_weight=0.3 # More responsive to obstacles ... )

Definition at line 2936 of file PlantArchitecture.py.

◆ setStaticObstacles()

None pyhelios.PlantArchitecture.PlantArchitecture.setStaticObstacles ( self,
List[int] target_UUIDs )

Mark geometry as static obstacles for collision detection optimization.

   This method tells the collision detection system that certain geometry will not
   move during the simulation. The system can then build an optimized Bounding Volume
   Hierarchy (BVH) for these obstacles, significantly improving collision detection
   performance in scenes with many static obstacles.
Parameters
target_UUIDsList of primitive UUIDs representing static obstacles
Exceptions
ValueErrorIf target_UUIDs is empty
PlantArchitectureErrorIf static obstacle configuration fails
Note
Collision avoidance must be enabled BEFORE calling this method – the native call raises "Collision detection must be enabled before setting static obstacles" otherwise. Static obstacles cannot be modified or moved after being marked static.
Example
>>> # Enable collision avoidance first >>> plantarch.enableSoftCollisionAvoidance() >>> # Then mark ground and building geometry as static >>> static_uuids = ground_uuids + building_uuids >>> plantarch.setStaticObstacles(static_uuids)

Definition at line 3095 of file PlantArchitecture.py.

◆ terminateApicalBud()

None pyhelios.PlantArchitecture.PlantArchitecture.terminateApicalBud ( self,
int plant_id,
int shoot_id )

Stop a shoot's apex from adding any further phytomers.

   The shoot keeps everything it already has, and its vegetative buds keep whatever
   state they are in -- this kills only the apical meristem. The shoot therefore stops
   extending at its tip but can still throw laterals; to stop those as well, pair this
   with :meth:`removeShootVegetativeBuds`.

   This is the standard way to freeze the old wood of a reconstructed tree before
   growing it forward with :meth:`advanceTime`.
Parameters
plant_idID of the plant instance
shoot_idShoot index within the plant (see :meth:getAllShootIDs)
Exceptions
ValueErrorIf either identifier is not a non-negative int
PlantArchitectureErrorIf the plant or shoot does not exist
Example
>>> # Freeze the measured scaffold so only last year's growth extends >>> for shoot_id in plantarch.getTerminalShootIDs(plant_id): ... plantarch.terminateApicalBud(plant_id, shoot_id)

Definition at line 4324 of file PlantArchitecture.py.

◆ updateAttractionPoints()

None pyhelios.PlantArchitecture.PlantArchitecture.updateAttractionPoints ( self,
List[vec3] points,
Optional[int] plant_id = None )

Replace the current attraction point set.

Parameters
pointsReplacement target locations as a list of vec3
plant_idUpdate this plant only. Updates globally when None.
Exceptions
ValueErrorIf points is empty or contains a non-vec3, or plant_id is negative
PlantArchitectureErrorIf the operation fails

Definition at line 680 of file PlantArchitecture.py.

◆ writePlantGrowthUSD()

None pyhelios.PlantArchitecture.PlantArchitecture.writePlantGrowthUSD ( self,
int plant_id,
Union[str, Path] filename,
float seconds_per_frame = 1.0 )

Export all registered growth frames as a time-sampled USD animation file.

   The resulting file can be imported directly into Blender. This is a visual-only
   export — no physics prims, joints, or collision shapes are written.
Parameters
plant_idID of the plant instance to export
filenameOutput file path (should have .usda extension)
seconds_per_frameDuration in seconds each growth frame occupies (default: 1.0)
Exceptions
ValueErrorIf plant_id is negative or filename is empty
PlantArchitectureErrorIf plant doesn't exist or file cannot be written

Definition at line 3395 of file PlantArchitecture.py.

◆ writePlantMeshVertices()

None pyhelios.PlantArchitecture.PlantArchitecture.writePlantMeshVertices ( self,
int plant_id,
Union[str, Path] filename )

Write all plant mesh vertices to file for external processing.

   This method exports all vertex coordinates (x,y,z) for every primitive in the plant,
   writing one vertex per line. Useful for external processing such as computing bounding
   volumes, convex hulls, or performing custom geometric analysis.
Parameters
plant_idID of the plant instance to export
filenamePath to output file (absolute or relative to current working directory)
Exceptions
ValueErrorIf plant_id is negative or filename is empty
PlantArchitectureErrorIf plant doesn't exist or file cannot be written
Example
>>> # Export vertices for convex hull analysis >>> plantarch.writePlantMeshVertices(plant_id, "plant_vertices.txt") >>> >>> # Use with Path object >>> from pathlib import Path >>> output_dir = Path("output") >>> output_dir.mkdir(exist_ok=True) >>> plantarch.writePlantMeshVertices(plant_id, output_dir / "vertices.txt")

Definition at line 3168 of file PlantArchitecture.py.

◆ writePlantStructureUSD()

None pyhelios.PlantArchitecture.PlantArchitecture.writePlantStructureUSD ( self,
int plant_id,
Union[str, Path] filename,
float elastic_modulus = 5e9,
float wood_density = 800.0,
float damping_ratio = 0.1,
float static_friction = 0.5,
float dynamic_friction = 0.3,
float restitution = 0.1,
float organ_spring_stiffness = 10.0,
float organ_spring_damping = 1.0,
float leaf_mass_per_area = 0.05,
float fruit_mass = 0.01,
float flower_mass = 0.002,
int solver_position_iterations = 32,
float min_segment_length = 0.001 )

Export plant structure as a USD articulated rigid body for NVIDIA IsaacSim physics.

   Each tube segment becomes a capsule-shaped rigid link connected by spherical joints.
   Spring/damper drives are derived from beam bending stiffness (E*I/L). Leaves, fruits,
   and flowers are represented as mass bodies attached by spring links.
Parameters
plant_idID of the plant instance to export
filenameOutput file path (should have .usda extension)
elastic_modulusYoung's modulus (Pa) for joint stiffness, K = E*I/L
wood_densityWood density (kg/m^3) used to compute mass from capsule volume
damping_ratioJoint damping ratio (dimensionless)
static_frictionStatic friction coefficient for collision material
dynamic_frictionDynamic friction coefficient for collision material
restitutionRestitution (bounciness) for collision material
organ_spring_stiffnessSpring stiffness (N*m/rad) for organ attachment joints
organ_spring_dampingDamping (N*m*s/rad) for organ attachment joints
leaf_mass_per_areaLeaf mass per unit area (kg/m^2)
fruit_massMass per fruit (kg)
flower_massMass per flower (kg)
solver_position_iterationsPhysX articulation solver position iteration count
min_segment_lengthMinimum segment length (m); shorter segments are skipped
Exceptions
ValueErrorIf plant_id is negative or filename is empty
PlantArchitectureErrorIf plant doesn't exist or file cannot be written
Example
>>> plantarch.writePlantStructureUSD(plant_id, "plant.usda")

Definition at line 3321 of file PlantArchitecture.py.

◆ writePlantStructureXML()

None pyhelios.PlantArchitecture.PlantArchitecture.writePlantStructureXML ( self,
int plant_id,
Union[str, Path] filename )

Save plant structure to XML file for later loading.

   This method exports the complete plant architecture to an XML file, including
   all shoots, phytomers, organs, and their properties. The saved plant can be
   reloaded later using readPlantStructureXML().
Parameters
plant_idID of the plant instance to save
filenamePath to output XML file (absolute or relative to current working directory)
Exceptions
ValueErrorIf plant_id is negative or filename is empty
PlantArchitectureErrorIf plant doesn't exist or file cannot be written
Note
The XML format preserves the complete plant state including:
  • Shoot structure and hierarchy
  • Phytomer properties and development stage
  • Organ geometry and attributes
  • Growth parameters and phenological state
Example
>>> # Save plant at current growth stage >>> plantarch.writePlantStructureXML(plant_id, "bean_day30.xml") >>> >>> # Later, reload the saved plant >>> loaded_plant_ids = plantarch.readPlantStructureXML("bean_day30.xml") >>> print(f"Loaded {len(loaded_plant_ids)} plants")

Definition at line 3216 of file PlantArchitecture.py.

◆ writeQSMCylinderFile()

None pyhelios.PlantArchitecture.PlantArchitecture.writeQSMCylinderFile ( self,
int plant_id,
Union[str, Path] filename )

Export plant structure in TreeQSM cylinder format.

   This method writes the plant structure as a series of cylinders following the
   TreeQSM format (Raumonen et al., 2013). Each row represents one cylinder with
   columns for radius, length, start position, axis direction, branch topology,
   and other structural properties. Useful for biomechanical analysis and
   quantitative structure modeling.
Parameters
plant_idID of the plant instance to export
filenamePath to output file (absolute or relative, typically .txt extension)
Exceptions
ValueErrorIf plant_id is negative or filename is empty
PlantArchitectureErrorIf plant doesn't exist or file cannot be written
Note
The TreeQSM format includes columns for:
  • Cylinder dimensions (radius, length)
  • Spatial position and orientation
  • Branch topology (parent ID, extension ID, branch ID)
  • Branch hierarchy (branch order, position in branch)
  • Quality metrics (mean absolute distance, surface coverage)
Example
>>> # Export for biomechanical analysis >>> plantarch.writeQSMCylinderFile(plant_id, "tree_structure_qsm.txt") >>> >>> # Use with external QSM tools >>> import pandas as pd >>> qsm_data = pd.read_csv("tree_structure_qsm.txt", sep="\\t") >>> print(f"Tree has {len(qsm_data)} cylinders")
References
Raumonen et al. (2013) "Fast Automatic Precision Tree Models from Terrestrial Laser Scanner Data" Remote Sensing 5(2):491-520

Definition at line 3272 of file PlantArchitecture.py.

Member Data Documentation

◆ _current_plant_model

pyhelios.PlantArchitecture.PlantArchitecture._current_plant_model = None
protected

Definition at line 322 of file PlantArchitecture.py.

◆ _plantarch_ptr

pyhelios.PlantArchitecture.PlantArchitecture._plantarch_ptr = None
protected

Definition at line 319 of file PlantArchitecture.py.

◆ _progress_callback_ref

pyhelios.PlantArchitecture.PlantArchitecture._progress_callback_ref = plantarch_wrapper.PROGRESS_CALLBACK(_c_callback)
protected

Definition at line 790 of file PlantArchitecture.py.

◆ context

pyhelios.PlantArchitecture.PlantArchitecture.context = context

Definition at line 318 of file PlantArchitecture.py.


The documentation for this class was generated from the following file: