Methods ======= `lpy_treesim` marries biologically inspired L-systems with rule-based care operations (tying, pruning, support placement) so you can synthesize orchard-ready tree geometries. This page explains how the major pieces interact. Prototype-driven L-System ------------------------- `base_lpy.lpy` is the only grammar we execute at runtime. Rather than handcode every rule, it reads extern variables that point to Python classes in `examples/`: ``prototype_dict_path`` Imports the shared `basicwood_prototypes` mapping. Each entry contains a `TreeBranch` subclass plus its `BasicWoodConfig`, which exposes stochastic bending, bud spacing, lengths, and colors. ``trunk_class_path`` The entry class that seeds the axiom. All other branches sprout from the prototypes configured on this trunk. ``simulation_class_path`` / ``simulation_config_class_path`` Provide training-system-specific behaviors (e.g., UFO trellis vs. Envy spindle). The config dataclass is serialized and handed to the runtime simulation via `TreeSimulationBase`. During each derivation step the grammar delegates to your Python classes to decide when buds break, which prototype to spawn, and how to orient each new segment. Because everything happens inside Python, you can use NumPy, random sampling, and heuristics tailored to your target cultivar. Tying, pruning, and supports --------------------------- The base simulation loop interleaves three routines: 1. **Derive**: expand the L-system string using the prototype logic. 2. **Tie**: after a configurable number of iterations (`num_iteration_tie`), the simulation attaches branches to the virtual support wires generated by `TreeSimulationBase.generate_points()`. 3. **Prune**: after `num_iteration_prune`, branches that exceed thresholds (age, curvature, or spacing) are removed. The decision functions live inside `stochastic_tree.py` and can be augmented via your prototypes. All three phases reuse the `ColorManager` so instance labels remain stable even after pruning removes geometry. Batch export pipeline --------------------- `tree_generation/make_n_trees.py` wraps the grammar in a CLI tool: * Builds a fresh `Lsystem` object per tree and injects the extern dictionary. * Seeds Python's RNG per tree so stochastic decisions differ while still being reproducible when `--rng-seed` is provided. * Calls `sceneInterpretation` to convert the final string into a PlantGL scene. * Writes the mesh using `tree_generation.helpers.write`, which emits ASCII PLY with normals and color attributes. * Dumps `{namespace}_{tree_name}_{index:05d}_colors.json` containing the mapping from instance IDs to semantic roles (spur, branch, trunk, tie, etc.). The naming scheme caps at 99,999 trees per run; start a new namespace if you need more. Extending the system -------------------- To add a brand-new method (new pruning heuristic, new tie behavior), derive from the appropriate class in `simulation_base.py` or `stochastic_tree.py` and inject your class via the extern dictionary. Because all extern paths are strings, `make_n_trees.py` can consume any importable module without further code changes.