Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 33 additions & 32 deletions doc/user/quick_start.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 <agraf.mtg>` and the :download:`agraf DRF file <agraf.drf>`.
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
==========
Expand All @@ -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
Expand All @@ -73,66 +76,64 @@ 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
equivalent to Father(v, EdgeType-> '<'). It thus returns the father
(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.

Expand Down
6 changes: 2 additions & 4 deletions doc/user/tutorial.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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::

Expand Down
2 changes: 1 addition & 1 deletion src/openalea/mtg/mtg.py
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
8 changes: 4 additions & 4 deletions src/openalea/mtg/plantframe/plantframe.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]


Expand Down Expand Up @@ -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::
Expand Down Expand Up @@ -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::
Expand Down
Loading