![]() |
0.1.33
|
High-level interface for plant architecture modeling and procedural plant generation. More...
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.
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[vec3] | getPlantLeafBases (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) | |
| pyhelios.PlantArchitecture.PlantArchitecture.__init__ | ( | self, | |
| Context | context ) |
Initialize PlantArchitecture with a Helios context.
| context | Active Helios Context instance |
| PlantArchitectureError | If plugin not available in current build |
| RuntimeError | If plugin initialization fails |
Definition at line 300 of file PlantArchitecture.py.
| pyhelios.PlantArchitecture.PlantArchitecture.__del__ | ( | self | ) |
Destructor to ensure C++ resources freed even without 'with' statement.
Definition at line 348 of file PlantArchitecture.py.
| pyhelios.PlantArchitecture.PlantArchitecture.__enter__ | ( | self | ) |
Context manager entry.
Definition at line 338 of file PlantArchitecture.py.
| pyhelios.PlantArchitecture.PlantArchitecture.__exit__ | ( | self, | |
| exc_type, | |||
| exc_val, | |||
| exc_tb ) |
Context manager exit - cleanup resources.
Definition at line 342 of file PlantArchitecture.py.
| 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.
|
protected |
Raise if the owning Context has been destroyed (see Context.check_context_alive).
Definition at line 334 of file PlantArchitecture.py.
|
protected |
Return a shoot's child IDs, or an empty list if it no longer resolves.
Definition at line 2719 of file PlantArchitecture.py.
|
protected |
Whether a shoot has been pruned away or no longer resolves at all.
Definition at line 2756 of file PlantArchitecture.py.
|
protected |
Child shoot IDs that have not been pruned away, ascending.
Definition at line 2728 of file PlantArchitecture.py.
|
protected |
Shared body for the per-organ built-geometry queries.
Definition at line 1822 of file PlantArchitecture.py.
|
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.
|
protected |
Shared body for the three shoot-level organ removal methods.
Definition at line 2521 of file PlantArchitecture.py.
|
protected |
Shared body for the per-shoot hierarchy accessors.
Definition at line 1781 of file PlantArchitecture.py.
|
staticprotected |
Reject point sets the native layer would misread or silently ignore.
Definition at line 753 of file PlantArchitecture.py.
|
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.
|
staticprotected |
Reject a non-int or negative phytomer index.
Definition at line 4982 of file PlantArchitecture.py.
|
staticprotected |
Validate a measured node path and return it as plain lists for the ctypes layer.
Definition at line 3902 of file PlantArchitecture.py.
|
protected |
Reject a non-int or negative petiole/leaf index.
Definition at line 4994 of file PlantArchitecture.py.
|
staticprotected |
Reject a non-int or negative plant ID, returning it as a plain int.
Definition at line 4956 of file PlantArchitecture.py.
|
protected |
Coerce a sequence of plant IDs, rejecting an empty or malformed one.
Definition at line 4968 of file PlantArchitecture.py.
|
staticprotected |
Reject a non-numeric or non-positive scale factor.
Definition at line 5001 of file PlantArchitecture.py.
|
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.
| 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.
| plant_id | ID of the plant instance |
| current_node_number | Starting node number for this shoot (typically 1) |
| base_rotation | Orientation as AxisRotation(pitch, yaw, roll) in radians (use math.radians() to convert) |
| internode_radius | Base radius of internodes in meters (must be > 0) |
| internode_length_max | Maximum internode length in meters (must be > 0) |
| internode_length_scale_factor_fraction | Scale factor for internode length (0-1 typically) |
| leaf_scale_factor_fraction | Scale factor for leaf size (0-1 typically) |
| radius_taper | Rate of radius decrease along shoot (0-1, where 1=no taper) |
| shoot_type_label | Label identifying shoot type - must match a type from loaded model |
| ValueError | If parameters are invalid (negative IDs, non-positive dimensions, empty label) |
| PlantArchitectureError | If shoot creation fails or shoot type doesn't exist |
Definition at line 3642 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| parent_shoot_id | ID of the parent shoot |
| parent_node_index | Index of the parent node where child emerges (0-based) |
| current_node_number | Starting node number for this child shoot |
| shoot_base_rotation | Orientation as AxisRotation(pitch, yaw, roll) in radians (use math.radians() to convert) |
| internode_radius | Base radius of child shoot internodes in meters (must be > 0) |
| internode_length_max | Maximum internode length in meters (must be > 0) |
| internode_length_scale_factor_fraction | Scale factor for internode length (0-1 typically) |
| leaf_scale_factor_fraction | Scale factor for leaf size (0-1 typically) |
| radius_taper | Rate of radius decrease along shoot (0-1, where 1=no taper) |
| shoot_type_label | Label identifying shoot type - must match loaded model |
| petiole_index | Which petiole at the node to branch from (default: 0) |
| ValueError | If parameters are invalid (negative values, non-positive dimensions, empty label) |
| PlantArchitectureError | If child shoot creation fails, parent doesn't exist, or shoot type not defined |
Definition at line 3840 of file PlantArchitecture.py.
| 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.
| base_position | Cartesian (x,y,z) coordinates of plant base as vec3 |
| current_age | Current age of the plant in days (must be >= 0) |
| ValueError | If age is negative |
| PlantArchitectureError | If plant creation fails |
Definition at line 3533 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| parent_shoot_id | ID of the shoot to attach to, or -1 to create a base stem shoot at the start of a new plant |
| parent_node_index | Node of the parent shoot at which the new shoot is added. Ignored when parent_shoot_id is -1 |
| node_positions | Internode 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_radii | Radius of the shoot at each node, one per position. All must be > 0 |
| shoot_type_label | Shoot type whose parameters build the measured geometry. Must already be defined (by :meth:loadPlantModelFromLibrary or :meth:defineShootType) |
| growth_shoot_type_label | Optional shoot type whose parameters govern the shoot's future growth. None grows the shoot with shoot_type_label |
| petiole_index | Petiole within the parent node to attach to (default 0) |
| ValueError | If 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 |
| PlantArchitectureError | If the native build fails (undefined shoot type, coincident consecutive nodes, base too far from the parent, ...) or the library predates v1.3.85 |
breakPlantDormancy before :meth:advanceTime if it is to grow.Definition at line 4016 of file PlantArchitecture.py.
| 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.
| dt | Time step to advance in days (must be >= 0) |
| plant_id | Advance only this plant. Mutually exclusive with plant_ids. |
| plant_ids | Advance only these plants. Mutually exclusive with plant_id. |
| years | Advance this many whole years in addition to dt days. Applies to all plants and cannot be combined with plant_id or plant_ids. |
| ValueError | If dt or years is negative, or selectors are combined |
| PlantArchitectureError | If time advancement fails |
Definition at line 566 of file PlantArchitecture.py.
| None pyhelios.PlantArchitecture.PlantArchitecture.appendAttractionPoints | ( | self, | |
| List[vec3] | points, | ||
| Optional[int] | plant_id = None ) |
Add to the current attraction point set.
| points | Additional target locations as a list of vec3 |
| plant_id | Append for this plant only. Appends globally when None. |
| ValueError | If points is empty or contains a non-vec3, or plant_id is negative |
| PlantArchitectureError | If the operation fails |
Definition at line 704 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| parent_shoot_id | ID of the parent shoot to extend |
| current_node_number | Starting node number for this shoot |
| base_rotation | Orientation as AxisRotation(pitch, yaw, roll) in radians (use math.radians() to convert) |
| internode_radius | Base radius of internodes in meters (must be > 0) |
| internode_length_max | Maximum internode length in meters (must be > 0) |
| internode_length_scale_factor_fraction | Scale factor for internode length (0-1 typically) |
| leaf_scale_factor_fraction | Scale factor for leaf size (0-1 typically) |
| radius_taper | Rate of radius decrease along shoot (0-1, where 1=no taper) |
| shoot_type_label | Label identifying shoot type - must match loaded model |
| ValueError | If parameters are invalid (negative IDs, non-positive dimensions, empty label) |
| PlantArchitectureError | If shoot appending fails, parent doesn't exist, or shoot type not defined |
Definition at line 3734 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| shoot_id | Shoot index within the plant |
| node_index | Phytomer index within the shoot |
| petiole_index | Petiole within the phytomer |
| ValueError | If any identifier is not a non-negative int |
| PlantArchitectureError | If the plant, shoot, node or petiole does not exist |
| RuntimeError | If the native library predates helios-core v1.3.87 |
Definition at line 4902 of file PlantArchitecture.py.
| 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.
| plant_id | Identifier of the plant whose dormancy should be broken |
| ValueError | If plant_id is negative |
| PlantArchitectureError | If the plant does not exist or the call fails |
Definition at line 2298 of file PlantArchitecture.py.
| 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.
| canopy_center | Cartesian (x,y,z) coordinates of canopy center as vec3 |
| plant_spacing | Spacing between plants in x- and y-directions (meters) as vec2 |
| plant_count | Number of plants in x- and y-directions as int2 |
| age | Age of all plants in days (must be >= 0) |
| germination_rate | Probability 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_parameters | Optional 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. |
| ValueError | If age is negative, germination_rate is not in [0, 1], plant count values are not positive, or build_parameters is invalid |
| PlantArchitectureError | If canopy building fails |
Definition at line 491 of file PlantArchitecture.py.
| 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.
| base_position | Cartesian (x,y,z) coordinates of plant base as vec3 |
| age | Age of the plant in days (must be >= 0) |
| build_parameters | Optional 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:
|
| walnut | trunk_height, num_scaffolds, scaffold_angle
|
| catch_wire_height | All other models read no build parameters. |
| ValueError | If age is negative or build_parameters is invalid |
| PlantArchitectureError | If plant building fails |
| RuntimeError | If no model has been loaded |
Definition at line 424 of file PlantArchitecture.py.
| None pyhelios.PlantArchitecture.PlantArchitecture.clearGrowthFrames | ( | self, | |
| int | plant_id ) |
Clear stored growth animation frames for a plant.
| plant_id | ID of the plant instance whose frames should be cleared |
| ValueError | If plant_id is negative |
Definition at line 3422 of file PlantArchitecture.py.
| 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.
| shoot_type_label | Unique name for this shoot type |
| parameters | A nested dict matching the ShootParameters structure, or a ShootParameters object. |
| ValueError | If shoot_type_label is empty, or parameters is not a dict or ShootParameters |
| PlantArchitectureError | If shoot type definition fails |
Definition at line 902 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance to delete |
| ValueError | If plant_id is negative |
| PlantArchitectureError | If plant deletion fails or plant doesn't exist |
Definition at line 3576 of file PlantArchitecture.py.
| None pyhelios.PlantArchitecture.PlantArchitecture.disableAttractionPoints | ( | self, | |
| Optional[int] | plant_id = None ) |
Stop steering growth toward attraction points.
| plant_id | Disable for this plant only. Disables globally when None. |
| ValueError | If plant_id is negative |
| PlantArchitectureError | If the operation fails |
Definition at line 658 of file PlantArchitecture.py.
| 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.
| PlantArchitectureError | If disabling fails |
Definition at line 2896 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| ValueError | If ``plant_id`` is not a non-negative int |
| PlantArchitectureError | If the plant does not exist |
| RuntimeError | If the native library predates helios-core v1.3.87 |
Definition at line 4588 of file PlantArchitecture.py.
| 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).
| PlantArchitectureError | If the call fails |
Definition at line 2860 of file PlantArchitecture.py.
| 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.
| plant_id | Identifier of the plant whose phenology is to be disabled |
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.| ValueError | If plant_id is negative |
| PlantArchitectureError | If disabling phenology fails |
Definition at line 2233 of file PlantArchitecture.py.
| 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().
| points | Target locations as a list of vec3 |
| plant_id | Apply to this plant only. Applies to every plant when None. |
| view_half_angle_deg | Half-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_distance | How far ahead a shoot tip looks, in meters |
| attraction_weight | Strength of the steering, 0 to 1 |
| ValueError | If points is empty or contains a non-vec3, or plant_id is negative |
| PlantArchitectureError | If the operation fails |
Definition at line 626 of file PlantArchitecture.py.
| 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.
| ground_height | Height of the ground plane (default 0.0) |
| ValueError | If ground_height is not a number |
| PlantArchitectureError | If the call fails |
Definition at line 2834 of file PlantArchitecture.py.
| 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.
| plant_ids | A single plant ID, or a sequence of plant IDs to steer together |
| beta_mu_inclination | Mean parameter of the Beta inclination distribution |
| beta_nu_inclination | Shape parameter of the Beta inclination distribution |
| eccentricity | Eccentricity of the ellipse defining the azimuth distribution |
| ellipse_rotation_degrees | Rotation of that ellipse (degrees) |
| lambda_degrees | How 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. |
| ValueError | If any plant ID is not a non-negative int, or the list is empty |
| PlantArchitectureError | If a plant does not exist |
| RuntimeError | If the native library predates helios-core v1.3.87 |
Definition at line 4485 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| eccentricity | Eccentricity of the ellipse defining the azimuth distribution |
| ellipse_rotation_degrees | Rotation of that ellipse (degrees) |
| lambda_degrees | How strongly to favour filling the distribution over keeping each leaf near the angle the model gave it |
| ValueError | If ``plant_id`` is not a non-negative int |
| PlantArchitectureError | If the plant does not exist |
| RuntimeError | If the native library predates helios-core v1.3.87 |
Definition at line 4559 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| beta_mu_inclination | Mean parameter of the Beta inclination distribution |
| beta_nu_inclination | Shape parameter of the Beta inclination distribution |
| lambda_degrees | How strongly to favour filling the distribution over keeping each leaf near the angle the model gave it |
| ValueError | If ``plant_id`` is not a non-negative int |
| PlantArchitectureError | If the plant does not exist |
| RuntimeError | If the native library predates helios-core v1.3.87 |
Definition at line 4525 of file PlantArchitecture.py.
| None pyhelios.PlantArchitecture.PlantArchitecture.enableMessages | ( | self | ) |
Re-enable standard output from the plantarchitecture plugin.
| PlantArchitectureError | If the call fails |
Definition at line 2876 of file PlantArchitecture.py.
| 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.
| target_object_UUIDs | List of primitive UUIDs to avoid collisions with. If empty, avoids all geometry in the context. |
| target_object_IDs | List of compound object IDs to avoid collisions with. |
| enable_petiole_collision | Enable collision detection for leaf petioles |
| enable_fruit_collision | Enable collision detection for fruit organs |
| PlantArchitectureError | If collision detection activation fails |
Definition at line 2798 of file PlantArchitecture.py.
| 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.
| obstacle_UUIDs | List of primitive UUIDs representing solid obstacles |
| avoidance_distance | Minimum distance to maintain from obstacles (meters). Growth stops if obstacles are closer. Default 0.5m. |
| enable_fruit_adjustment | Adjust fruit positions away from obstacles |
| enable_obstacle_pruning | Remove plant organs that penetrate obstacles |
| ValueError | If obstacle_UUIDs is empty or avoidance_distance is non-positive |
| PlantArchitectureError | If solid obstacle configuration fails |
Definition at line 3044 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| shoot_id | Shoot whose descendants to collect |
Definition at line 1748 of file PlantArchitecture.py.
| 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.
| PlantArchitectureError | If retrieval fails |
Definition at line 1230 of file PlantArchitecture.py.
| 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.
| PlantArchitectureError | If retrieval fails |
Definition at line 1256 of file PlantArchitecture.py.
| 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.
| PlantArchitectureError | If retrieval fails |
Definition at line 1155 of file PlantArchitecture.py.
| 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.
| PlantArchitectureError | If retrieval fails |
Definition at line 1132 of file PlantArchitecture.py.
| 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.
| PlantArchitectureError | If retrieval fails |
Definition at line 1279 of file PlantArchitecture.py.
| 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.
| PlantArchitectureError | If retrieval fails |
Definition at line 1204 of file PlantArchitecture.py.
| 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.
| PlantArchitectureError | If retrieval fails |
Definition at line 1178 of file PlantArchitecture.py.
| 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.
| PlantArchitectureError | If retrieval fails |
Definition at line 1302 of file PlantArchitecture.py.
| List[int] pyhelios.PlantArchitecture.PlantArchitecture.getAllPlantObjectIDs | ( | self, | |
| int | plant_id ) |
Get all object IDs for a specific plant.
| plant_id | ID of the plant instance |
| ValueError | If plant_id is negative |
| PlantArchitectureError | If retrieval fails |
Definition at line 1327 of file PlantArchitecture.py.
| List[int] pyhelios.PlantArchitecture.PlantArchitecture.getAllPlantUUIDs | ( | self, | |
| int | plant_id, | ||
| bool | include_hidden = False ) |
Get all primitive UUIDs for a specific plant.
| plant_id | ID of the plant instance |
| include_hidden | If True, also include UUIDs of hidden prototype primitives managed by this PlantArchitecture instance. |
| ValueError | If plant_id is negative |
| PlantArchitectureError | If retrieval fails |
Definition at line 1551 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
Definition at line 1574 of file PlantArchitecture.py.
| 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.
| PlantArchitectureError | If retrieval fails |
Definition at line 1109 of file PlantArchitecture.py.
| List[str] pyhelios.PlantArchitecture.PlantArchitecture.getAvailablePlantModels | ( | self | ) |
Get list of all available plant models in the library.
| PlantArchitectureError | If retrieval fails |
Definition at line 1035 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| shoot_id | Shoot index within the plant |
Definition at line 1728 of file PlantArchitecture.py.
| 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'.
| shoot_type_label | Label for the shoot type. Labels are species-specific, e.g. "trifoliate" (bean), "trunk"/"scaffold" (almond). |
| return_typed | If True, return a typed :class:pyhelios.plant_architecture_params.ShootParameters object instead of a plain nested dict. |
dict (default) or a ShootParameters object containing:phytomer_parameters with nested internode/petiole/leaf/peduncle/ inflorescence parameters and the leaf prototype| ValueError | If shoot_type_label is empty |
| PlantArchitectureError | If parameter retrieval fails |
Definition at line 845 of file PlantArchitecture.py.
| 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`.
| return_typed | If True, return a typed :class:pyhelios.plant_architecture_params.CarbohydrateParameters. |
dict (default) or CarbohydrateParameters object. Definition at line 939 of file PlantArchitecture.py.
| 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`.
| return_typed | If True, return a typed :class:pyhelios.plant_architecture_params.NitrogenParameters. |
dict (default) or NitrogenParameters object. Definition at line 987 of file PlantArchitecture.py.
| int pyhelios.PlantArchitecture.PlantArchitecture.getGrowthFrameCount | ( | self, | |
| int | plant_id ) |
Get the number of registered growth frames for a plant.
| plant_id | ID of the plant instance to query |
registerGrowthFrame| ValueError | If plant_id is negative |
Definition at line 3444 of file PlantArchitecture.py.
| int pyhelios.PlantArchitecture.PlantArchitecture.getParentShootID | ( | self, | |
| int | plant_id, | ||
| int | shoot_id ) |
Get the ID of the shoot a shoot grew from.
| plant_id | ID of the plant instance |
| shoot_id | Shoot index within the plant (see :meth:getAllShootIDs) |
Definition at line 1632 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| shoot_id | Shoot index within the plant |
Definition at line 1710 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| shoot_id | Shoot index within the plant |
| node_index | Phytomer index within the shoot |
| petiole_index | Petiole within the phytomer; None for the phytomer mean |
| ValueError | If any identifier is not a non-negative int |
| PlantArchitectureError | If the plant, shoot, node or petiole does not exist |
| RuntimeError | If the native library predates helios-core v1.3.87 |
Definition at line 4655 of file PlantArchitecture.py.
| float pyhelios.PlantArchitecture.PlantArchitecture.getPlantAge | ( | self, | |
| int | plant_id ) |
Get the current age of a plant in days.
| plant_id | ID of the plant instance |
| ValueError | If plant_id is negative |
| PlantArchitectureError | If retrieval fails |
Definition at line 1966 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| ValueError | If plant_id is negative |
| PlantArchitectureError | If retrieval fails |
Definition at line 3132 of file PlantArchitecture.py.
| List[int] pyhelios.PlantArchitecture.PlantArchitecture.getPlantFlowerObjectIDs | ( | self, | |
| int | plant_id ) |
Get object IDs for all flower (inflorescence) objects on a specific plant.
| plant_id | ID of the plant instance |
| ValueError | If plant_id is negative |
| PlantArchitectureError | If retrieval fails |
Definition at line 1450 of file PlantArchitecture.py.
| List[int] pyhelios.PlantArchitecture.PlantArchitecture.getPlantFruitObjectIDs | ( | self, | |
| int | plant_id ) |
Get object IDs for all fruit objects on a specific plant.
| plant_id | ID of the plant instance |
[].| ValueError | If plant_id is negative |
| PlantArchitectureError | If retrieval fails |
Definition at line 1482 of file PlantArchitecture.py.
| float pyhelios.PlantArchitecture.PlantArchitecture.getPlantHeight | ( | self, | |
| int | plant_id ) |
Get the height of a plant in meters.
| plant_id | ID of the plant instance |
| ValueError | If plant_id is negative |
| PlantArchitectureError | If retrieval fails |
Definition at line 2055 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| ValueError | If plant_id is negative |
| PlantArchitectureError | If the query fails or the library predates v1.3.85 |
Definition at line 1891 of file PlantArchitecture.py.
| float pyhelios.PlantArchitecture.PlantArchitecture.getPlantLeafArea | ( | self, | |
| int | plant_id ) |
Get the total leaf area of a plant in m².
| plant_id | ID of the plant instance |
| ValueError | If plant_id is negative |
| PlantArchitectureError | If retrieval fails |
Definition at line 2083 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| ValueError | If plant_id is negative |
| PlantArchitectureError | If the query fails or the library predates v1.3.85 |
Definition at line 1864 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| ValueError | If plant_id is negative |
| PlantArchitectureError | If retrieval fails |
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.)Definition at line 1519 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| ValueError | If plant_id is not a non-negative int |
| PlantArchitectureError | If the plant does not exist |
Definition at line 4401 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| ValueError | If plant_id is negative |
| PlantArchitectureError | If the query fails or the library predates v1.3.85 |
Definition at line 1920 of file PlantArchitecture.py.
| List[int] pyhelios.PlantArchitecture.PlantArchitecture.getPlantLeafObjectIDs | ( | self, | |
| int | plant_id ) |
Get object IDs for all leaf objects on a specific plant.
| plant_id | ID of the plant instance |
| ValueError | If plant_id is negative |
| PlantArchitectureError | If retrieval fails |
getPlantLeafBases. The two are built by independent traversals of the shoot tree, so their index correspondence is not guaranteed by the native API.Definition at line 1359 of file PlantArchitecture.py.
| float pyhelios.PlantArchitecture.PlantArchitecture.getPlantMaxAge | ( | self, | |
| int | plant_id ) |
Get the maximum age of a plant, beyond which it stops growing.
| plant_id | ID of the plant instance |
setPlantMaxAge.| ValueError | If plant_id is negative |
| PlantArchitectureError | If retrieval fails |
Definition at line 1993 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| ValueError | If plant_id is negative |
| PlantArchitectureError | If retrieval fails |
Definition at line 1420 of file PlantArchitecture.py.
| 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`.
| plant_id | ID of the plant instance |
| ValueError | If plant_id is negative |
| PlantArchitectureError | If retrieval fails |
Definition at line 1389 of file PlantArchitecture.py.
| Dict[str, Any] pyhelios.PlantArchitecture.PlantArchitecture.getShoot | ( | self, | |
| int | plant_id, | ||
| int | shoot_id ) |
Get a read-only view of a shoot's topology.
| plant_id | ID of the plant instance |
| shoot_id | Shoot index within the plant (see :meth:getAllShootIDs) |
rank, parent_shoot_id (-1 for the base stem), parent_node_index, and node_count. Definition at line 1594 of file PlantArchitecture.py.
| 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.
| 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`.
| plant_id | ID of the plant instance |
| shoot_id | Shoot index within the plant |
Definition at line 1670 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
Definition at line 1768 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| ValueError | If plant_id is negative |
| PlantArchitectureError | If the plant does not exist |
Definition at line 2556 of file PlantArchitecture.py.
| 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.
| 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.
| 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`.
| plant_id | ID of the plant instance |
| shoot_id | Shoot index within the plant |
Definition at line 1653 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| shoot_id | Shoot index within the plant (see :meth:getAllShootIDs) |
| state | Count only buds in this :class:~pyhelios.BudState. None (the default) counts buds in every state. |
| ValueError | If an identifier is negative, or ``state`` is not a BudState |
| PlantArchitectureError | If the plant or shoot does not exist |
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.Definition at line 4367 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| ValueError | If plant_id is negative |
| PlantArchitectureError | If the plant does not exist |
Definition at line 2590 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance to harvest |
| ValueError | If plant_id is negative |
| PlantArchitectureError | If the plant does not exist or the call fails |
harvestPlant states. Use :meth:removePlantLeaves to defoliate.Definition at line 2408 of file PlantArchitecture.py.
| bool pyhelios.PlantArchitecture.PlantArchitecture.is_available | ( | self | ) |
Check if PlantArchitecture is available in current build.
Definition at line 5015 of file PlantArchitecture.py.
| bool pyhelios.PlantArchitecture.PlantArchitecture.isLeafAngleDistributionTrackingEnabled | ( | self, | |
| int | plant_id ) |
Whether a plant's leaf angles are being steered toward a prescribed distribution.
| plant_id | ID of the plant instance |
| ValueError | If ``plant_id`` is not a non-negative int |
| PlantArchitectureError | If the plant does not exist |
| RuntimeError | If the native library predates helios-core v1.3.87 |
Definition at line 4614 of file PlantArchitecture.py.
| bool pyhelios.PlantArchitecture.PlantArchitecture.isPlantDormant | ( | self, | |
| int | plant_id ) |
Check whether a plant is dormant.
| plant_id | Identifier of the plant to check |
| ValueError | If plant_id is negative |
| PlantArchitectureError | If the plant does not exist or the query fails |
Definition at line 2327 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| shoot_id | Shoot index within the plant |
| ValueError | If either ID is negative |
| PlantArchitectureError | If the query fails or the library predates v1.3.85 |
Definition at line 1945 of file PlantArchitecture.py.
| 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`.
| plant_id | ID of the plant instance |
| shoot_id | Shoot index within the plant |
Definition at line 1693 of file PlantArchitecture.py.
| 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.
| plant_model | Query this library model without changing the currently loaded one. Use getAvailablePlantModels() for valid names. Mutually exclusive with plant_id. |
| plant_id | Query 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().
| ValueError | If both plant_model and plant_id are given, or plant_id is negative |
| PlantArchitectureError | If no model is loaded, or the model or plant is unknown |
Definition at line 1074 of file PlantArchitecture.py.
| None pyhelios.PlantArchitecture.PlantArchitecture.loadPlantModelFromLibrary | ( | self, | |
| str | plant_label ) |
Load a plant model from the built-in library.
| plant_label | Plant 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" |
| ValueError | If plant_label is empty or invalid |
| PlantArchitectureError | If model loading fails |
Definition at line 375 of file PlantArchitecture.py.
| 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.
| plant_id | Identifier of the plant to make dormant |
| ValueError | If plant_id is negative |
| PlantArchitectureError | If the plant does not exist or the call fails |
Definition at line 2270 of file PlantArchitecture.py.
| 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.
| object_data_labels | A 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. |
| ValueError | If a label is empty or not a string |
| PlantArchitectureError | If an invalid label is supplied or the operation otherwise fails |
Definition at line 2119 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| shoot_id | Shoot index within the plant (see :meth:getAllShootIDs) |
| node_index | Node on the shoot to cut at, in [0, node_count) |
| ValueError | If any identifier is negative |
| PlantArchitectureError | If the plant or shoot does not exist, if node_index is beyond the shoot's current node count, or if the native call fails |
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".Definition at line 2372 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| min_rank | Lowest rank to prune. Must be at least 1 – rank 0 is the base stem, and pruning it would destroy the plant. |
| ValueError | If plant_id is negative or min_rank is less than 1 |
| PlantArchitectureError | If the plant does not exist |
deletePlantInstance; to cut the base stem itself call :meth:pruneBranch directly.Definition at line 2631 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| shoot_id | Root of the branch system to remove |
| include_self | If True (default) the shoot itself is cut at node 0. If False the shoot is kept and only its child shoots are cut. |
| ValueError | If either identifier is negative |
| PlantArchitectureError | If the plant or shoot does not exist |
Definition at line 2669 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| stride | Spacing between pruned tips. Must be at least 1; stride=1 prunes every terminal shoot. |
| ValueError | If plant_id is negative or stride is less than 1 |
| PlantArchitectureError | If the plant does not exist |
Definition at line 2701 of file PlantArchitecture.py.
| 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.
| filename | Path to XML file to load (absolute or relative to current working directory) |
| quiet | If True, suppress console output during loading (default: False) |
| ValueError | If filename is empty |
| PlantArchitectureError | If file doesn't exist, cannot be parsed, or loading fails |
Definition at line 3488 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| shoot_id | Shoot index within the plant |
| node_index | Phytomer index within the shoot |
| petiole_index | Petiole within the phytomer |
| ValueError | If any identifier is not a non-negative int |
| PlantArchitectureError | If the plant, shoot, node or petiole does not exist |
| RuntimeError | If the native library predates helios-core v1.3.87 |
Definition at line 4937 of file PlantArchitecture.py.
| 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`.
| plant_id | ID of the plant instance to capture |
| min_segment_length | Minimum segment length (m); shorter segments are skipped |
| ValueError | If plant_id is negative |
| PlantArchitectureError | If plant doesn't exist |
Definition at line 3370 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance to defoliate |
| ValueError | If plant_id is negative |
| PlantArchitectureError | If the plant does not exist or the call fails |
Definition at line 2436 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| shoot_id | Shoot index within the plant (see :meth:getAllShootIDs) |
| ValueError | If either identifier is negative |
| PlantArchitectureError | If the plant or shoot does not exist |
Definition at line 2515 of file PlantArchitecture.py.
| None pyhelios.PlantArchitecture.PlantArchitecture.removeShootLeaves | ( | self, | |
| int | plant_id, | ||
| int | shoot_id ) |
Remove all leaves from a single shoot.
| plant_id | ID of the plant instance |
| shoot_id | Shoot index within the plant (see :meth:getAllShootIDs) |
| ValueError | If either identifier is negative |
| PlantArchitectureError | If the plant or shoot does not exist |
Definition at line 2461 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| shoot_id | Shoot index within the plant (see :meth:getAllShootIDs) |
| ValueError | If either identifier is negative |
| PlantArchitectureError | If 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.
Definition at line 2494 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| shoot_id | Shoot index within the plant |
| node_index | Phytomer index within the shoot |
| scale_factor | Factor to scale the mature leaf size by; must be positive |
| ValueError | If an identifier is invalid or ``scale_factor`` is not positive |
| PlantArchitectureError | If the plant, shoot or node does not exist |
| RuntimeError | If the native library predates helios-core v1.3.87 |
Definition at line 4809 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| shoot_id | Shoot index within the plant |
| node_index | Phytomer index within the shoot |
| scale_factor | Factor to scale the fully-elongated length by; must be positive |
| ValueError | If an identifier is invalid or ``scale_factor`` is not positive |
| PlantArchitectureError | If the plant, shoot or node does not exist |
| RuntimeError | If the native library predates helios-core v1.3.87 |
Definition at line 4690 of file PlantArchitecture.py.
| 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.
| view_half_angle_deg | Half-angle of the search cone in degrees |
| look_ahead_distance | How far ahead a shoot tip looks, in meters |
| attraction_weight | Strength of the steering, 0 to 1 |
| obstacle_reduction_factor | Scales attraction where an obstacle intervenes |
| plant_id | Apply to this plant only. Applies globally when None. |
| ValueError | If plant_id is negative |
| PlantArchitectureError | If the operation fails |
Definition at line 731 of file PlantArchitecture.py.
| 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.
| 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.
| include_internodes | Include stem internodes in collision detection |
| include_leaves | Include leaf blades in collision detection |
| include_petioles | Include leaf petioles in collision detection |
| include_flowers | Include flowers in collision detection |
| include_fruit | Include fruit in collision detection |
| PlantArchitectureError | If organ filtering fails |
Definition at line 2995 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| shoot_id | Shoot index within the plant |
| node_index | Phytomer index within the shoot |
| petiole_index | Petiole within the phytomer |
| leaf_index | Leaf within the petiole |
| target_normal | Direction the blade should face, in world coordinates. Need not be normalized. |
| ValueError | If an identifier is invalid, or ``target_normal`` is not a vec3 |
| PlantArchitectureError | If the leaf has no geometry, the blade's facet normals cancel, or the target cannot be reached by a roll-pitch pair |
| RuntimeError | If the native library predates helios-core v1.3.87 |
Definition at line 4854 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| shoot_id | Shoot index within the plant |
| node_index | Phytomer index within the shoot |
| petiole_index | Petiole within the phytomer |
| petiole_scale_factor_fraction | Fraction of the fully-elongated petiole length |
| leaf_scale_factor_fraction | Fraction of the fully-elongated leaf scale factor |
| ValueError | If any identifier is not a non-negative int |
| PlantArchitectureError | If the plant, shoot, node or petiole does not exist |
| RuntimeError | If the native library predates helios-core v1.3.87 |
Definition at line 4765 of file PlantArchitecture.py.
| 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`.
| plant_id | Plant identifier. |
| shoot_id | Shoot identifier. |
| node_index | Index of the phytomer along the shoot. |
| petiole_index | Index of the petiole on that phytomer. |
| leaf_count | Number of leaves to place on the petiole. Must be at least 1. |
| ValueError | If any index is negative or ``leaf_count`` is less than 1. |
| PlantArchitectureError | If the operation fails. |
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.
| 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.
| plant_id | ID of the plant instance |
| shoot_id | ID of the shoot carrying the phytomer |
| node_index | Index of the phytomer within the shoot, counted from the base |
| petiole_index | Index of the petiole within the phytomer |
| leaf_bases | Base position of each leaf in world coordinates, one per leaf on the petiole, in the petiole's existing leaf order |
| leaf_rotations | AxisRotation(pitch, yaw, roll) of each leaf in radians |
| leaf_sizes | Fully elongated size of each leaf in meters. All must be > 0 |
| ValueError | If 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 |
| PlantArchitectureError | If 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 |
Definition at line 4169 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| shoot_id | ID of the shoot carrying the phytomer |
| node_index | Index of the phytomer within the shoot, counted from the base |
| petiole_index | Index of the petiole within the phytomer |
| node_positions | Petiole node positions in world coordinates, base to tip. At least two are required, and no two consecutive positions may be coincident |
| node_radii | Radius of the petiole at each node, one per position. All must be > 0 |
| ValueError | If 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 |
| PlantArchitectureError | If the native call fails or the library predates v1.3.85 |
setPetioleLeafGeometry for the same petiole, since leaf placement is oriented from the petiole axis. Definition at line 4099 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| shoot_id | Shoot index within the plant |
| node_index | Phytomer index within the shoot |
| petiole_index | Petiole within the phytomer |
| petiole_scale_factor_fraction | Fraction of the fully-elongated length (1.0 for a fully-elongated petiole) |
| ValueError | If any identifier is not a non-negative int |
| PlantArchitectureError | If the plant, shoot, node or petiole does not exist |
| RuntimeError | If the native library predates helios-core v1.3.87 |
Definition at line 4727 of file PlantArchitecture.py.
| None pyhelios.PlantArchitecture.PlantArchitecture.setPlantCarbohydrateParameters | ( | self, | |
| int | plant_id, | ||
| Union[dict, CarbohydrateParameters] | parameters ) |
Set carbohydrate-model parameters for a plant.
| plant_id | Target plant instance ID |
| parameters | A flat dict or a CarbohydrateParameters object. |
| ValueError | If parameters is not a dict or CarbohydrateParameters |
| PlantArchitectureError | If the operation fails |
Definition at line 959 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| max_age | Maximum age of the plant in days. Must be non-negative. |
| ValueError | If plant_id is negative or max_age is negative |
| PlantArchitectureError | If the plant does not exist |
Definition at line 2026 of file PlantArchitecture.py.
| None pyhelios.PlantArchitecture.PlantArchitecture.setPlantNitrogenParameters | ( | self, | |
| int | plant_id, | ||
| Union[dict, NitrogenParameters] | parameters ) |
Set nitrogen-model parameters for a plant.
| plant_id | Target plant instance ID |
| parameters | A flat dict or a NitrogenParameters object. |
| ValueError | If parameters is not a dict or NitrogenParameters |
| PlantArchitectureError | If the operation fails |
Definition at line 1007 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance |
| time_to_dormancy_break | Degree-days or days until dormancy ends |
| time_to_flower_initiation | Time until flower buds are initiated |
| time_to_flower_opening | Time until flowers open |
| time_to_fruit_set | Time until fruit begins developing |
| time_to_fruit_maturity | Time until fruit reaches maturity |
| time_to_dormancy | Time until plant enters dormancy |
| max_leaf_lifespan | Maximum leaf lifespan in days (default: 1e6) |
| is_evergreen | If True, the plant retains leaves through dormancy instead of shedding them at senescence (default: False) |
| ValueError | If plant_id is negative |
| PlantArchitectureError | If phenology setting fails |
Definition at line 2170 of file PlantArchitecture.py.
| 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.
| callback | A callable(progress: float, message: str) where progress is in [0, 1], or None to clear the callback. |
| ValueError | If callback is not callable and not None. |
Definition at line 778 of file PlantArchitecture.py.
| 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.
| plant_id | Plant identifier. |
| shoot_id | Shoot identifier. |
| internode_length_max | Target internode length in meters. Must be positive. |
| ValueError | If an identifier is negative or the length is not positive. |
| PlantArchitectureError | If the operation fails. |
writePlantStructureXML, so it must be set again after :meth:readPlantStructureXML. Definition at line 4282 of file PlantArchitecture.py.
| 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.
| view_half_angle_deg | Half-angle of detection cone in degrees (0-180). Default 80° provides wide field of view. |
| look_ahead_distance | Distance to look ahead for collisions in meters. Larger values detect distant obstacles. Default 0.1m. |
| sample_count | Number of ray samples within cone. More samples improve accuracy but reduce performance. Default 256. |
| inertia_weight | Weight for previous growth direction (0-1). Higher values make growth smoother but less responsive. Default 0.4. |
| ValueError | If parameters are outside valid ranges |
| PlantArchitectureError | If parameter setting fails |
Definition at line 2936 of file PlantArchitecture.py.
| 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.
| target_UUIDs | List of primitive UUIDs representing static obstacles |
| ValueError | If target_UUIDs is empty |
| PlantArchitectureError | If static obstacle configuration fails |
Definition at line 3095 of file PlantArchitecture.py.
| 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`.
| plant_id | ID of the plant instance |
| shoot_id | Shoot index within the plant (see :meth:getAllShootIDs) |
| ValueError | If either identifier is not a non-negative int |
| PlantArchitectureError | If the plant or shoot does not exist |
Definition at line 4324 of file PlantArchitecture.py.
| None pyhelios.PlantArchitecture.PlantArchitecture.updateAttractionPoints | ( | self, | |
| List[vec3] | points, | ||
| Optional[int] | plant_id = None ) |
Replace the current attraction point set.
| points | Replacement target locations as a list of vec3 |
| plant_id | Update this plant only. Updates globally when None. |
| ValueError | If points is empty or contains a non-vec3, or plant_id is negative |
| PlantArchitectureError | If the operation fails |
Definition at line 680 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance to export |
| filename | Output file path (should have .usda extension) |
| seconds_per_frame | Duration in seconds each growth frame occupies (default: 1.0) |
| ValueError | If plant_id is negative or filename is empty |
| PlantArchitectureError | If plant doesn't exist or file cannot be written |
Definition at line 3395 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance to export |
| filename | Path to output file (absolute or relative to current working directory) |
| ValueError | If plant_id is negative or filename is empty |
| PlantArchitectureError | If plant doesn't exist or file cannot be written |
Definition at line 3168 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance to export |
| filename | Output file path (should have .usda extension) |
| elastic_modulus | Young's modulus (Pa) for joint stiffness, K = E*I/L |
| wood_density | Wood density (kg/m^3) used to compute mass from capsule volume |
| damping_ratio | Joint damping ratio (dimensionless) |
| static_friction | Static friction coefficient for collision material |
| dynamic_friction | Dynamic friction coefficient for collision material |
| restitution | Restitution (bounciness) for collision material |
| organ_spring_stiffness | Spring stiffness (N*m/rad) for organ attachment joints |
| organ_spring_damping | Damping (N*m*s/rad) for organ attachment joints |
| leaf_mass_per_area | Leaf mass per unit area (kg/m^2) |
| fruit_mass | Mass per fruit (kg) |
| flower_mass | Mass per flower (kg) |
| solver_position_iterations | PhysX articulation solver position iteration count |
| min_segment_length | Minimum segment length (m); shorter segments are skipped |
| ValueError | If plant_id is negative or filename is empty |
| PlantArchitectureError | If plant doesn't exist or file cannot be written |
Definition at line 3321 of file PlantArchitecture.py.
| 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().
| plant_id | ID of the plant instance to save |
| filename | Path to output XML file (absolute or relative to current working directory) |
| ValueError | If plant_id is negative or filename is empty |
| PlantArchitectureError | If plant doesn't exist or file cannot be written |
Definition at line 3216 of file PlantArchitecture.py.
| 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.
| plant_id | ID of the plant instance to export |
| filename | Path to output file (absolute or relative, typically .txt extension) |
| ValueError | If plant_id is negative or filename is empty |
| PlantArchitectureError | If plant doesn't exist or file cannot be written |
Definition at line 3272 of file PlantArchitecture.py.
|
protected |
Definition at line 322 of file PlantArchitecture.py.
|
protected |
Definition at line 319 of file PlantArchitecture.py.
|
protected |
Definition at line 790 of file PlantArchitecture.py.
| pyhelios.PlantArchitecture.PlantArchitecture.context = context |
Definition at line 318 of file PlantArchitecture.py.