MTG Tutorial - Analysis#
MTG is an OpenAlea model. MTG (Multiscale Tree Graph) allows to represent plant architecture on a graph at different scales.
Also, you may want to extract topological data from a MTG.
In this tutorial, we will work on a part of a Noylum MTG.
For that we will follow different steps:
Load the tree digitised MTG
Explore the MTG as an architectural database
number of vertices
class of vertices
number of scales
properties
In order to make all these graphs, we used Pyvis.
Introduction#
First, let’s import the packages we need for the tutorial.
[1]:
import openalea
from openalea.mtg import *
from openalea.mtg.data import data_dir
from openalea.widgets.mtg import plot
from openalea.widgets.plantgl import PlantGL
Some vocabulary :
MTG data structure : g
Vertex identifier: vid
Load and Display the MTG#
Now, we collect MTG data.
[2]:
g = MTG(data_dir/'boutdenoylum2.mtg')
We plot the MTG. Different colors represent different complexes and each complex begins with a box node which is the component root.
Notice that you can click and drag on a particuliar node to make it move. Also, you can see some properties of the node by putting you mouse over a node.
[3]:
plot(g)
[3]:
MTG Extraction and Visualisation#
Scales and Classes represent modularities#
Scale 1: P = Plant#
Scale 2: A = Axes#
Scale 3 : Growth Unit#
S : Shoot
U : Unit
Let’s find the number of scales in the MTG and print how many vertices per scale and the classes in each scale.
[4]:
nb_scales = g.nb_scales()
# Print the vertices at different scales
for scale in range(1, nb_scales):
print('Nb vertices at scale ', scale, ': ', g.nb_vertices(scale=scale))
print('Classes : ', list(set(g.class_name(vid) for vid in g.vertices(scale=scale))))
Nb vertices at scale 1 : 1
Classes : ['P']
Nb vertices at scale 2 : 63
Classes : ['A']
Nb vertices at scale 3 : 198
Classes : ['U', 'S']
Actually, the default scale is the max scale (3 here) but you can change it to plot it at a different scale.
[5]:
plot(g, scale=g.max_scale()-1)
[5]:
We can select all the vertices of each class.
[6]:
classes = list(set(g.class_name(vid) for vid in g.vertices() if g.class_name(vid)))
print(classes)
def vertices(g, class_name='P'):
return [vid for vid in g.vertices() if g.class_name(vid)==class_name]
vids_U = vertices(g, 'U')
print('Nb U', len(vids_U))
['P', 'U', 'S', 'A']
Nb U 84
Let’s plot the graph with the selected vertices corresponding to the U class.
[7]:
plot(g, selection=vids_U)
[7]:
Property Extraction#
Let’s go on by displaying a whole property through the graph.
[8]:
# Properties on the MTG: this exclude all the topological properties
print(g.property_names())
# Retrieve one property for the MTG (dict)
phi = g.property('phi')
['edge_type', 'label', 'index', 'Dist', 'El1', 'Az1', 'Inc', 'Azm', 'XX', 'YY', 'ZZ', 'psi', 'teta', 'phi', 'TopDia', 'NFe', 'Nf', 'Lum1', 'Lum2', 'Lum3', 'Lum4', '_line', 'position']
Once you’ve extracted the ‘phi’ dictionary. You can change the labels of the graph nodes with it.
Now, if you zoom in a node, you will see that the labels have changed.
[9]:
plot(g, labels=phi)
[9]:
Trunk Extraction#
In this part, we will make our first selections on the MTG and visualise them. Let’s begin with the trunk.
[10]:
root = next(g.roots_iter(scale=g.max_scale()))
trunk = g.Trunk(root)
Now we have the selection of the trunk, we can visualise it.
[11]:
plot(g, selection=trunk)
[11]:
Leaves Extraction#
Let’s select the leaves and display them.
[12]:
leaves = [vid for vid in g.vertices(scale=g.max_scale()) if g.is_leaf(vid)]
plot(g, selection=leaves)
[12]:
Component Roots Extraction#
Now, we select the first component of each complex, which are the component roots.
[13]:
c_roots = [next(g.component_roots_at_scale_iter(cid, scale=g.max_scale())) for cid in g.vertices(scale=g.max_scale()-1)]
plot(g, selection=c_roots)
[13]:
Descendants Extraction#
Here, we select all the descendants of one particuliar node.
[14]:
root_id = 139
s = g.Descendants(root_id)
plot(g, selection=s, cdn_resources='in_line')
[14]:
PlantFrame 3D#
Now, we can display the MTG in 3D. You can check the PlantFrame tutorial.
[15]:
drf = data_dir/'walnut.drf'
dressing_data = dresser.dressing_data_from_file(drf)
dressing_data = plantframe.DressingData(DiameterUnit=10)
pf = plantframe.PlantFrame(g, TopDiameter='TopDia', DressingData = dressing_data)
scene = pf.plot(gc=True, display=False)
PlantGL(scene)
[15]:
[ ]:
[ ]: