From af793c70bb10e564c7e9c2d490beefb6b130c086 Mon Sep 17 00:00:00 2001 From: baugetfa Date: Thu, 4 Dec 2025 15:00:48 +0100 Subject: [PATCH 1/4] openalea.container.traversal does not exist anymore replaced by openalea.mtg.traversal --- doc/user/tutorial.rst | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/doc/user/tutorial.rst b/doc/user/tutorial.rst index 50cff97..6828224 100644 --- a/doc/user/tutorial.rst +++ b/doc/user/tutorial.rst @@ -67,11 +67,10 @@ Traversing the mtg at one scale The mtg can be traversed at any scales like a regular tree. -Their are three traversal algorithms working on Tree data structures (:ref:`container_algo_traversal`): +Their are three traversal algorithms working on Tree data structures: * :class:`pre_order` * :class:`post_order` - * :class:`level_order` These methods take as parameters a tree like data structure, and a vertex. They will traverse the subtree rooted on this vertex in a specific order. @@ -80,13 +79,12 @@ They will return an iterator on the traversed vertices. .. code-block:: python :linenos: - from openalea.container.traversal.tree import * + from openalea.mtg.traversal import * print(list(g.components(root))) print(list(pre_order(g, root1))) print(list(post_order(g, root1))) - print(list(level_order(g, root1))) .. warning:: From bbddb628d10146a2e604d47c7060ec075c7a3edc Mon Sep 17 00:00:00 2001 From: pradal Date: Thu, 4 Dec 2025 15:59:33 +0100 Subject: [PATCH 2/4] Update example in quickstart --- doc/user/quick_start.rst | 65 ++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/doc/user/quick_start.rst b/doc/user/quick_start.rst index f110a48..7d58fe9 100644 --- a/doc/user/quick_start.rst +++ b/doc/user/quick_start.rst @@ -16,23 +16,25 @@ A plant architecture described in a coding file can be loaded in :mod:`openalea. .. doctest:: - >>> from openalea.mtg.aml import MTG - >>> g1 = MTG('user/agraf.mtg') # some errors may occur while loading the MTG - ERROR: Missing component for vertex 2532 + >>> from openalea.mtg import MTG + >>> from openalea.mtg.data import data_dir + >>> agraf = data_dir / 'agraf.mtg' + >>> g1 = MTG(agraf) # some errors may occur while loading the MTG -.. note:: In order to reproduce the example, download :download:`agraf MTG file ` and the :download:`agraf DRF file `. - Other files that may be required are also available in the same directory (`*smb` files) but are not compulsary. +.. note:: Some example files are provided with the Python package. + However, you can provide your own files by giving the absolute path to the MTG function. The MTG function attempts to read a valid MTG description and parses the coding file. If errors are detected during the parsing, they are displayed on the screen and the parsing fails. In this case, no MTG is built and the user should make corrections to the coding file. If the parsing succeeds, this function creates an internal representation of the plant (or a set of plants) encoded as a MTG. In this example, the MTG object is stored in variable `g1` for further use. Note that a MTG should always be stored in a variable otherwise it is destroyed immediately after its building. The last built MTG is considered as the "active" MTG. It is used as an implicit argument by all the functions of the MTG module. -It is possible to change the active MTG using :func:`Activate` :: +To be backward compatible with AML, it is possible to set one active MTG as a global variable using :func:`Activate` :: + from openalea.mtg.aml import Activate, MTG g1 = MTG("filename1") # g1 is the current MTG g2 = MTG("filename2") # g2 becomes the current MTG Activate(g1) # g1 is now again the current MTG -.. warning:: the notion of activation is very important. Each call to a function in the package MTG will look at the active MTG. +.. warning:: for AML like interface, the notion of activation is very important. Each call to a function in the package MTG will look at the active MTG. Plotting ========== @@ -46,17 +48,18 @@ information about the MTG and DRF syntax. Note that the following code should be .. code-block:: python :linenos: - from openalea.mtg.aml import MTG - from openalea.mtg.dresser import dressing_data_from_file - from openalea.mtg.plantframe import PlantFrame, compute_axes, build_scene - g = MTG('agraf.mtg') - dressing_data = dressing_data_from_file('agraf.drf') + from openalea.mtg.data import data_dir + from openalea.mtg import MTG + from openalea.mtg.plantframe.plantframe import PlantFrame, compute_axes, build_scene + from openalea.mtg.plantframe.dresser import dressing_data_from_file + g = MTG(agraf) + dressing_data = dressing_data_from_file(data_dir/'agraf.drf') topdia = lambda x: g.property('TopDia').get(x) pf = PlantFrame(g, TopDiameter=topdia, DressingData = dressing_data) axes = compute_axes(g, 3, pf.points, pf.origin) diameters = pf.algo_diameter() scene = build_scene(pf.g, pf.origin, axes, pf.points, diameters, 10000) - from vplants.plantgl.all import Viewer + from openalea.plantgl.all import Viewer Viewer.display(scene) .. figure:: fig3_5_bis.png @@ -73,54 +76,51 @@ Functions related to MTGs There exists a comprehensive set of functions related to MTGs. These functions may be directly used on the active MTG or they may be combined with each other in order to define new functions on MTGs. Here are some of them. Full details may be found elsewhere either in the tutorials (e.g., :ref:`newmtg_tutorial_mtg_aml`) or in the :ref:`newmtg_reference` section. * **MTG constructor**. - We've already seen how to read a MTG file by using :func:`~openalea.mtg.aml.MTG`, which takes one mandatory argument, namely the MTG's filename. + We've already seen how to read a MTG file by using :func:`~openalea.mtg.mtg.MTG`, which takes one mandatory argument, namely the MTG's filename. * **Extraction of vertex sets: e.g. VtxList().** - Different types of lists of vertices can be extracted from a MTG through the function :func:`~openalea.mtg.aml.VtxList`. Notably, the set of functions at a given scale is obtained with the optional argument **Scale**: + Different types of lists of vertices can be extracted from a MTG through the function :meth:`~openalea.mtg.mtg.MTG.vertices`. Notably, the set of functions at a given scale is obtained with the optional argument **scale**: .. code-block:: python :linenos: - from openalea.mtg.aml import VtxList - VtxList() - vtx1 = VtxList(Scale=1) # vtx 1 returns a list e.g., [1] - vtx2 = VtxList(Scale=2) - vtx3 = VtxList(Scale=3) + g.vertices() + vtx1 = g.vertices(scale=1) # vtx 1 returns a list e.g., [1] + vtx2 = g.vertices(scale=2) + vtx3 = g.vertices(scale=3) - On line 2, we extract the vertices that have scale set to 1. The returned list contains only 1 element that have the index 1. Conversely, we could use the :func:`~openalea.mtg.aml.Scale` function to figure out what is the Scale of the vertex that have the index 1: + On line 2, we extract the vertices that have scale set to 1. The returned list contains only 1 element that have the index 1. Conversely, we could use the :meth:`~openalea.mtg.mtg.MTG.scale` method to figure out what is the Scale of the vertex that have the index 1: .. doctest:: - >>> from openalea.mtg.aml import Scale - >>> Scale(1) + >>> g.scale(1) 1 - * **Functions returning vertex attributes: e.g. Class(vtx), Index(vtx), Feature(vtx, feature_name).** + * **Functions returning vertex attributes: e.g. class_name(vtx), index(vtx), property(property_name).** The different attributes attached to a given vertex can be retrieved by these functions. The class and the index of a vertex are respectively returned by functions :func:`~openalea.mtg.aml.Class()` and :func:`~openalea.mtg.aml.Index()`. The value of any other attribute may be obtained by specifying its name: .. doctest:: - >>> from openalea.mtg.aml import Feature, Class, Index - >>> vtxList = VtxList(Scale=2) # get a list of vertices according to a scale + >>> vtxList = g.vertices(scale=2) # get a list of vertices according to a scale >>> v1 = vtxList[0] # look at the first vertex >>> # Feature(vertex_id, name) - >>> Feature(v1, "XX") + >>> g.property("XX")[v1] 0.0 - >>> Class(v1) + >>> g.class_name(v1) 'U' - >>> Index(v1) + >>> g.index(v1) 94 Returns the attribute "XX" (if any) of a vertex v1. These functions return scalar (INTEGER, STRING, REAL), i.e. elementary types different from VTX. - * **Functions for moving in MTGs: e.g. Father(vtx), Complex(vtx), Successor(vtx), Predecessor(vtx).** + * **Functions for moving in MTGs: e.g. parent(vtx), complex(vtx), Successor(vtx), Predecessor(vtx).** Some functions take a VTX as an argument and return a VTX. These functions allow topological moves in the MTG, i.e. they allow to select new vertices with topological reference to given vertices. See :func:`~openalea.mtg.aml.Father`, :func:`~openalea.mtg.aml.Predecessor` , :func:`~openalea.mtg.aml.Successor`, and :func:`~openalea.mtg.aml.Complex` .. doctest:: >>> from openalea.mtg.aml import Father, Successor, Predecessor - >>> Father(v1) + >>> g.parent(v1) # Equivalent of the old aml function Father(v1) >>> Predecessor(v1) .. note:: The predecessor is a special case of Father; predecessor function is @@ -128,11 +128,12 @@ There exists a comprehensive set of functions related to MTGs. These functions m (at the same scale) of the argument - * **Functions for creating collections of vertices: e.g. Sons(vtx), Components(vtx), Axix(vtx).** + * **Functions for creating collections of vertices: e.g. children(vtx), components(vtx), algo.axis(vtx).** These functions return sets of vertices associated with a certain vertex. Components() returns all the vertices that compose at the scale immediately superior a given vertex. Axis() returns the ordered set of vertices which compose the axis which the argument belongs to. * **Functions for creating graphical representations of MTGs: PlantFrame(), Plot(), DressingData** PlantFrame() enables the user to compute 3D-geometrical representations of MTGs. + It now use the openalea.plantgl package. The above functions can be combined together using the Python language to extract from plant databases various types of information. From f0e1d5ddf9b19da3ca1a4363a55405927d0b67fa Mon Sep 17 00:00:00 2001 From: pradal Date: Thu, 4 Dec 2025 16:12:30 +0100 Subject: [PATCH 3/4] Remove some warnings due to backslash char in the doc --- src/openalea/mtg/mtg.py | 2 +- src/openalea/mtg/plantframe/plantframe.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/openalea/mtg/mtg.py b/src/openalea/mtg/mtg.py index 8adaac5..9d81835 100644 --- a/src/openalea/mtg/mtg.py +++ b/src/openalea/mtg/mtg.py @@ -179,7 +179,7 @@ def scales(self): def max_scale(self): '''Return the max scale identifier. - By convention, the mtg contains scales in :math:`[0,max\_scale]`. + By convention, the mtg contains scales in :math:`[0,max_scale]`. :Usage: >>> print(g.max_scale()) diff --git a/src/openalea/mtg/plantframe/plantframe.py b/src/openalea/mtg/plantframe/plantframe.py index ef7a542..a86913e 100644 --- a/src/openalea/mtg/plantframe/plantframe.py +++ b/src/openalea/mtg/plantframe/plantframe.py @@ -312,8 +312,8 @@ def propagate_constraints(self): for vid in self.bottom_diameter: pid = g.parent(vid) if pid is not None : - if pid not in self.top_diameter \ - and (g.nb_children(pid) == 1 or edge_type.get(vid) == '<'): + if pid not in (self.top_diameter and + (g.nb_children(pid) == 1 or edge_type.get(vid) == '<')): self.top_diameter[pid] = self.bottom_diameter[vid] @@ -1010,7 +1010,7 @@ def compute_diameter(self, vid=None): return p.get(vid) if vid else p def compute_surface(self, vid=None): - """ Return the surface of a vertex or for all vertices. + r""" Return the surface of a vertex or for all vertices. The surface is for a tapered is .. math:: @@ -1038,7 +1038,7 @@ def compute_surface(self, vid=None): return p.get(vid) if vid else p def compute_volume(self, vid=None): - """ Return the volume of a vertex or for all vertices. + r""" Return the volume of a vertex or for all vertices. The volume is for a tapered is .. math:: From 080c8e02caf651daaf4bdc5a73ddc2260e684800 Mon Sep 17 00:00:00 2001 From: pradal Date: Thu, 4 Dec 2025 16:45:07 +0100 Subject: [PATCH 4/4] Fix a bug I just introduce --- src/openalea/mtg/plantframe/plantframe.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/openalea/mtg/plantframe/plantframe.py b/src/openalea/mtg/plantframe/plantframe.py index a86913e..c3b1d47 100644 --- a/src/openalea/mtg/plantframe/plantframe.py +++ b/src/openalea/mtg/plantframe/plantframe.py @@ -312,8 +312,8 @@ def propagate_constraints(self): for vid in self.bottom_diameter: pid = g.parent(vid) if pid is not None : - if pid not in (self.top_diameter and - (g.nb_children(pid) == 1 or edge_type.get(vid) == '<')): + if (pid not in self.top_diameter and + (g.nb_children(pid) == 1 or edge_type.get(vid) == '<')): self.top_diameter[pid] = self.bottom_diameter[vid]