5. Tutorial: Create MTG file from scratch

This tutorial briefly introduces the main features of the package and should show you the contents and potential of the openalea.mtg library.

All the examples can be tested in a Python interpreter.

5.1. MTG creation

Let us consider the following example:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import openalea.mtg as mtg

g = mtg.MTG()

print len(g)
print g.nb_vertices()
print g.nb_scales()

root = g.root
print g.scale(root)
  • First, the package is imported (line 1).
  • Then, a mtg is instantiated without parameters (line 3).
  • However, as for a Tree, the mtg is not empty (line 5-7).
  • There is always a root node at scale 0 (line 9-10).

5.2. Simple edition

We add a component root1 to the root node, which will be the root node of the tree at the scale 1.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
root1 = g.add_component(root)

# Edit the tree at scale 1 by adding three children
# to the vertex `root1`.
v1 = g.add_child(root1)
v2 = g.add_child(root1)
v3 = g.add_child(root1)

g.parent(v1) == root1
g.complex(v1) == root
v3 in g.siblings(v1)

5.3. 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 (container_algo_traversal):

  • pre_order
  • post_order
  • 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. They will return an iterator on the traversed vertices.

1
2
3
4
5
6
7
from openalea.container.traversal.tree 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

On MTG data structure, methods that return collection of vertices always return an iterator rather than list, array, or set.

You have to convert the iterator into a list if you want to display it, or compute its length.

>>> print len(g.components(root)) #doctest: +SKIP
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object of type 'generator' has no len()

Use rather:

>>> components = list(g.components(root)) #doctest: +SKIP
>>> print components #doctest: +SKIP
[1, 2, 3, 4]

5.4. Full example: how to create an MTG

../_images/fig3_4.png

Figure 1: Graphical representation of the MTG file code_file2.mtg used as an input file to all examples contained in this page

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
from openalea.mtg.mtg import *
from openalea.mtg.aml import *


g = mtg.MTG()
plant_id = g.add_component(g.root, label='P1')

#first u1
u1 = g.add_component(plant_id, label='U1', Length=10, Diameter=5.9)
i = g.add_component(u1,label='I1' )
i = g.add_child(i,label='I2', edge_type='<' )
i = g.add_child(i,label='I3', edge_type='<' )
i = g.add_child(i,label='I4', edge_type='<' )
i = g.add_child(i,label='I5', edge_type='<' )
i6 = i = g.add_child(i,label='I6', edge_type='<' )

#u2 branch
i,u2 = g.add_child_and_complex(i6,label='I20', edge_type='+', Length=7, Diameter=3.5 )
g.node(u2).label='U2'
g.node(u2).edge_type='+'
i = g.add_child(i,label='I21', edge_type='<' )
i = g.add_child(i,label='I22', edge_type='<' )
i = g.add_child(i,label='I23', edge_type='<' )
i = g.add_child(i,label='I24', edge_type='<' )

#u3 branch
i,u3 = g.add_child_and_complex(i,label='I25', edge_type='<', Length=4, Diameter=2.1)
g.node(u3).label='U3'
g.node(u3).edge_type='<'
i = g.add_child(i,label='I25', edge_type='<' )
i = g.add_child(i,label='I26', edge_type='<' )
i = g.add_child(i,label='I27', edge_type='<' )
i = g.add_child(i,label='I28', edge_type='<' )
i = g.add_child(i,label='I29', edge_type='<' )

#continue u1
i = g.add_child(i6,label='I7', edge_type='<' )
i = g.add_child(i,label='I8', edge_type='<' )
i = g.add_child(i,label='I9', edge_type='<' )

# u2 main axe
i,c = g.add_child_and_complex(i,label='I10', edge_type='<' , Length=8, Diameter=4.3)
g.node(c).label='U2'
g.node(c).edge_type='<'
i = g.add_child(i,label='I11', edge_type='<' )
i = g.add_child(i,label='I12', edge_type='<' )
i = g.add_child(i,label='I13', edge_type='<' )
i = g.add_child(i,label='I14', edge_type='<' )
i = g.add_child(i,label='I15', edge_type='<' )


# u3 main axe
i,c = g.add_child_and_complex(i,label='I16', edge_type='<', Length=7.5, diameter=3.9 )
g.node(c).label='U3'
g.node(c).edge_type='<'
i = g.add_child(i,label='I17', edge_type='<' )
i = g.add_child(i,label='I18', edge_type='<' )
i = g.add_child(i,label='I19', edge_type='<' )


#fat_mtg(g)

print g.is_valid()
print g

for id in g.vertices():
    print g[id]
from openalea.mtg.io import *

print list(g.property_names())
properties = [(p, 'REAL') for p in g.property_names() if p not in ['edge_type', 'index', 'label']]
print properties
mtg_lines = write_mtg(g, properties)
f = open('test.mtg', 'w')
f.write(mtg_lines)
f.close()

Authors:Christophe Pradal <christophe pradal __at__ cirad fr>, Thomas Cokelaer <thomas cokelaer __at__ sophia inria fr>