"""
colzette module related turtle and visitor to build plant geometry
"""
import numpy as np
from math import pi, radians
from functools import partial
import openalea.plantgl.all as pgl
from openalea.mtg import MTG
from openalea.colzette.colzette import update_MTG, bell_shaped_dist, get_nb_leaflets
[docs]
def BrassicaVisitor(
g,
v,
turtle,
make_leafshape = None,
ustride=9,
vstride=2,
):
'''
Visitor that can handle an MTG file with multiple Rapeseed plants
This function is called by the scene3D() function when creating the 3D scene
:param g: (MTG) - In contains all the geometrical information needed by the visitor
:param v: (int) - the ID of the vertex being generated
:param turtle: turtle used to create the 3D space
:param ustride: (int) - number of triangles in u direction
:param vstride: (int) - number of triangles in v direction
'''
# retrieve the node and its label
nid = g.node(v)
label = g.label(v)
turtle.setId(v)
if label != 'Plant':
turtle.rollL(nid.Phyllotaxy)
# turtle.rollL(137.5)
if g.edge_type(v) == '+':
turtle.setWidth(nid.PetioleDiam)
if label == 'Leaf':
leafscale = pgl.Vector3(1, nid.LeafWidth, nid.LeafLength)
turtle.down(nid.InsertionAngle)
turtle.setColor(2)
turtle.F(nid.PetioleLength)
turtle.setColor(3)
turtle.down(nid.LeafAngle - nid.InsertionAngle)
my_leaf = pgl.Scaled(leafscale, make_leafshape(u = ustride, v = vstride))
turtle.customGeometry(my_leaf)
if label == 'Internode':
turtle.setWidth(nid.StemDiam)
turtle.setColor(1)
turtle.F(nid.NodeLength)
[docs]
def LegumeVisitor(
g,
v,
turtle,
make_leaflet_shape = None,
ustride=9,
vstride=2,
):
'''
Visitor that can handle an MTG file with multiple Fababean plants
This function is called by the scene3D() function when creating the 3D scene
:param g: (MTG) - In contains all the geometrical information needed by the visitor
:param v: (int) - the ID of the vertex being generated
:param turtle: turtle used to create the 3D space
:param ustride: (int) - number of triangles in u direction
:param vstride: (int) - number of triangles in v direction
'''
# retrieve the node and its label
nid = g.node(v)
label = g.label(v)
turtle.setId(v)
plant_id = g.complex_at_scale(v, scale=1)
coeff_width = g.node(plant_id).coeff_width
coeff_petiole_d = g.node(plant_id).coeff_petiole_d
stem_d = g.node(plant_id).stem_d
if 'PetioleLength1' in g.properties():
PetioleLength1 = nid.PetioleLength1
PetioleLength2 = nid.PetioleLength2
else:
PetioleLength1 = nid.PetioleLength
PetioleLength2 = nid.PetioleLength
if label != 'Plant':
turtle.rollL(nid.Phyllotaxy)
if g.edge_type(v) == '+':
turtle.setWidth(nid.PetioleDiam)
if label == 'Leaf':
nb_leaflets = nid.Nb_leaflets
leafscale = multi_leaflets(make_leaflet_shape,
nb_leaflets=int(nb_leaflets),
leaf_surface=nid.LeafSurface,
coeff_width=nid.coeff_width,
petiole_leaflet_length1=PetioleLength1,
petiole_leaflet_length2=PetioleLength2,
coeff_petiole_d=coeff_petiole_d,
stem_d=stem_d,
ustride=ustride,
vstride=vstride)
turtle.down(nid.InsertionAngle)
turtle.setColor(2)
my_leaf = leafscale
turtle.customGeometry(my_leaf)
if label == 'Internode':
turtle.setWidth(nid.StemDiam)
turtle.setColor(1)
turtle.F(nid.NodeLength)
[docs]
def RapeseedVisitor(
g,
v,
turtle,
ustride=9,
vstride=2,
):
'''
Visitor that can handle an MTG file with multiple Rapeseed plants
This function is called by the scene3D() function when creating the 3D scene
:param g: (MTG) - In contains all the geometrical information needed by the visitor
:param v: (int) - the ID of the vertex being generated
:param turtle: turtle used to create the 3D space
:param ustride: (int) - number of triangles in u direction
:param vstride: (int) - number of triangles in v direction
'''
# retrieve the node and its label
nid = g.node(v)
label = g.label(v)
turtle.setId(v)
# if nid.parent() is None:#this is a new plant base
# p = nid.complex_at_scale(scale=1)
# print('plant no',p)
# if 'position' in p.properties():
# print (p.label, 'moving to ', p.position)
# turtle.move(list(map(float,p.position)))
# else:
# print('standing still')
# turtle.move(0,0,0)
# if 'azimuth' in p.properties():
# turtle.rollR(p.azimuth)
if label != 'Plant':
turtle.rollL(nid.Phyllotaxy)
# turtle.rollL(137.5)
if g.edge_type(v) == '+':
turtle.setWidth(nid.PetioleDiam)
if label == 'Leaf':
leafscale = pgl.Vector3(1, nid.LeafWidth, nid.LeafLength)
turtle.down(nid.InsertionAngle)
turtle.setColor(2)
turtle.F(nid.PetioleLength)
turtle.setColor(3)
turtle.down(nid.LeafAngle - nid.InsertionAngle)
my_leaf = pgl.Scaled(leafscale, make_leafshape_rapeseed(u = ustride, v = vstride))
turtle.customGeometry(my_leaf)
if label == 'Internode':
turtle.setWidth(nid.StemDiam)
turtle.setColor(1)
turtle.F(nid.NodeLength)
[docs]
def CamelinaVisitor(
g,
v,
turtle,
ustride=9,
vstride=2,
):
"""
Visitor that can handle an MTG file with multiple plants
This function is called by the scene3D() function when creating the 3D scene
g is an MTG tree. In contains all the geometrical information needed by the visitor
v is the ID of the vertex being generated (int)
turtle is the turtle used to create the 3D space
"""
# retrieve the node and its label
nid = g.node(v)
label = g.label(v)
turtle.setId(v)
# if nid.parent() is None:#this is a new plant base
# p = nid.complex_at_scale(scale=1)
# print('plant no',p)
# if 'position' in p.properties():
# print (p.label, 'moving to ', p.position)
# turtle.move(list(map(float,p.position)))
# else:
# print('standing still')
# turtle.move(0,0,0)
# if 'azimuth' in p.properties():
# turtle.rollR(p.azimuth)
if label != 'Plant':
turtle.rollL(nid.Phyllotaxy)
# turtle.rollL(137.5)
if g.edge_type(v) == '+':
turtle.setWidth(nid.PetioleDiam)
if label == 'Leaf':
leafscale = pgl.Vector3(1, nid.LeafWidth, nid.LeafLength)
turtle.down(nid.InsertionAngle)
turtle.setColor(2)
turtle.F(nid.PetioleLength)
turtle.setColor(3)
turtle.down(nid.LeafAngle - nid.InsertionAngle)
my_leaf = pgl.Scaled(leafscale, make_leafshape_camelina(u = ustride, v = vstride))
turtle.customGeometry(my_leaf)
if label == 'Internode':
turtle.setWidth(nid.StemDiam)
turtle.setColor(1)
turtle.F(nid.NodeLength)
[docs]
def FababeanVisitor(
g,
v,
turtle,
ustride=9,
vstride=2,
):
'''
Visitor that can handle an MTG file with multiple Fababean plants
This function is called by the scene3D() function when creating the 3D scene
:param g: (MTG) - In contains all the geometrical information needed by the visitor
:param v: (int) - the ID of the vertex being generated
:param turtle: turtle used to create the 3D space
:param ustride: (int) - number of triangles in u direction
:param vstride: (int) - number of triangles in v direction
'''
# retrieve the node and its label
nid = g.node(v)
label = g.label(v)
turtle.setId(v)
plant_id = g.complex_at_scale(v, scale=1)
coeff_width = g.node(plant_id).coeff_width
coeff_petiole_d = g.node(plant_id).coeff_petiole_d
stem_d = g.node(plant_id).stem_d
if label != 'Plant':
turtle.rollL(nid.Phyllotaxy)
if g.edge_type(v) == '+':
turtle.setWidth(nid.PetioleDiam)
if label == 'Leaf':
nb_leaflets = nid.Nb_leaflets
leafscale = multi_leaflets_fababean(nb_leaflets=int(nb_leaflets),
leaf_surface=nid.LeafSurface,
coeff_width=nid.coeff_width,
petiole_leaflet_length1=nid.PetioleLength1,
petiole_leaflet_length2=nid.PetioleLength2,
coeff_petiole_d=coeff_petiole_d,
stem_d=stem_d,
ustride=ustride,
vstride=vstride)
turtle.down(nid.InsertionAngle)
turtle.setColor(2)
my_leaf = leafscale
turtle.customGeometry(my_leaf)
if label == 'Internode':
turtle.setWidth(nid.StemDiam)
turtle.setColor(1)
turtle.F(nid.NodeLength)
[docs]
def LentilVisitor(
g,
v,
turtle,
ustride=9,
vstride=2,
):
"""
Visitor that can handle an MTG file with multiple plants
This function is called by the scene3D() function when creating the 3D scene
g is an MTG tree. In contains all the geometrical information needed by the visitor
v is the ID of the vertex being generated (int)
turtle is the turtle used to create the 3D space
"""
# retrieve the node and its label
nid = g.node(v)
label = g.label(v)
turtle.setId(v)
plant_id = g.complex_at_scale(v, scale=1)
coeff_width = g.node(plant_id).coeff_width
coeff_petiole_d = g.node(plant_id).coeff_petiole_d
stem_d = g.node(plant_id).stem_d
if label != 'Plant':
turtle.rollL(nid.Phyllotaxy)
if g.edge_type(v) == '+':
turtle.setWidth(nid.PetioleDiam)
if label == 'Leaf':
nb_leaflets = nid.Nb_leaflets
leafscale = multi_leaflets_lentil(nb_leaflets=int(nb_leaflets),
leaf_surface=nid.LeafSurface,
coeff_width=nid.coeff_width,
petiole_leaflet_length=nid.PetioleLength,
coeff_petiole_d=coeff_petiole_d,
stem_d=stem_d,
ustride=ustride,
vstride=vstride)
turtle.down(nid.InsertionAngle)
turtle.setColor(2)
my_leaf = leafscale
turtle.customGeometry(my_leaf)
if label == 'Internode':
turtle.setWidth(nid.StemDiam)
turtle.setColor(1)
turtle.F(nid.NodeLength)
[docs]
def multi_leaflets(make_leaflet_shape,
nb_leaflets=5.0,
leaf_surface=1.0,
coeff_width=0.7,
petiole_leaflet_length1=2.0,
petiole_leaflet_length2=2.0,
coeff_petiole_d=0.5,
stem_d=0.035,
ustride=9,
vstride=2):
surface_leaflet = leaf_surface/nb_leaflets # each leaflet has the same surface
leaflet_length=2*(surface_leaflet/(coeff_width*pi))**(0.5)
leaflet_width=leaflet_length*coeff_width
leafscale = pgl.Vector3(1, leaflet_width, leaflet_length)
leafletshape = make_leaflet_shape(u=ustride, v=vstride)
leaflet = pgl.Scaled(leafscale,leafletshape)
if nb_leaflets < 2:
nb_petiole = 1
else:
nb_petiole = (nb_leaflets)//2
total_petiole_leaflet = petiole_leaflet_length1 + petiole_leaflet_length2*(nb_petiole-1)
petiole = pgl.Cylinder(radius=stem_d*coeff_petiole_d/2,height=total_petiole_leaflet)
leaflet_left = pgl.AxisRotated(axis=(1,0,0),angle=-radians(60),geometry=leaflet)
leaflet_right = pgl.AxisRotated(axis=(1,0,0),angle=radians(60),geometry=leaflet)
leaflets = [petiole]
translate = [0,0,petiole_leaflet_length1]
count_leaflets = nb_leaflets
leaflets.append(pgl.Translated(translate,leaflet_left))
leaflets.append(pgl.Translated(translate,leaflet_right))
for i in range(nb_petiole):
leaflets.append(pgl.Translated(translate,leaflet_left))
leaflets.append(pgl.Translated(translate,leaflet_right))
translate[2] += petiole_leaflet_length2
count_leaflets -=2
if count_leaflets == 1:
leaflets.append(pgl.Translated((0,0,total_petiole_leaflet),leaflet))
leafshape = pgl.Group(leaflets)
return leafshape
[docs]
def multi_leaflets_fababean(nb_leaflets=5.0,
leaf_surface=1.0,
coeff_width=0.7,
petiole_leaflet_length1=2.0,
petiole_leaflet_length2=2.0,
coeff_petiole_d=0.5,
stem_d=0.035,
ustride=9,
vstride=2):
surface_leaflet = leaf_surface/nb_leaflets # each leaflet has the same surface
leaflet_length=2*(surface_leaflet/(coeff_width*pi))**(0.5)
leaflet_width=leaflet_length*coeff_width
leafscale = pgl.Vector3(1, leaflet_width, leaflet_length)
leafletshape_fababean = make_leaflet_shape_fababean(u=ustride, v=vstride)
leaflet = pgl.Scaled(leafscale,leafletshape_fababean)
if nb_leaflets < 2:
nb_petiole = 1
else:
nb_petiole = (nb_leaflets)//2
total_petiole_leaflet = petiole_leaflet_length1 + petiole_leaflet_length2*(nb_petiole-1)
petiole = pgl.Cylinder(radius=stem_d*coeff_petiole_d/2,height=total_petiole_leaflet)
leaflet_left = pgl.AxisRotated(axis=(1,0,0),angle=-radians(60),geometry=leaflet)
leaflet_right = pgl.AxisRotated(axis=(1,0,0),angle=radians(60),geometry=leaflet)
leaflets = [petiole]
translate = [0,0,petiole_leaflet_length1]
count_leaflets = nb_leaflets
leaflets.append(pgl.Translated(translate,leaflet_left))
leaflets.append(pgl.Translated(translate,leaflet_right))
for i in range(nb_petiole):
leaflets.append(pgl.Translated(translate,leaflet_left))
leaflets.append(pgl.Translated(translate,leaflet_right))
translate[2] += petiole_leaflet_length2
count_leaflets -=2
if count_leaflets == 1:
leaflets.append(pgl.Translated((0,0,total_petiole_leaflet),leaflet))
leafshape_fababean = pgl.Group(leaflets)
return leafshape_fababean
[docs]
def multi_leaflets_lentil(nb_leaflets=5.0,
leaf_surface=1.0,
coeff_width=0.7,
petiole_leaflet_length=2.0,
coeff_petiole_d=0.5,
stem_d=0.035,
ustride=9,
vstride=2):
surface_leaflet = leaf_surface/nb_leaflets # each leaflet has the same surface
leaflet_length=2*(surface_leaflet/(coeff_width*pi))**(0.5)
leaflet_width=leaflet_length*coeff_width
leafscale = pgl.Vector3(1, leaflet_width, leaflet_length)
leafletshape_lentil = make_leaflet_shape_lentil(u=ustride, v=vstride)
leaflet = pgl.Scaled(leafscale,leafletshape_lentil)
if nb_leaflets < 2:
nb_petiole = 1
else:
nb_petiole = (nb_leaflets)//2
total_petiole_leaflet = petiole_leaflet_length * nb_petiole
petiole = pgl.Cylinder(radius=stem_d*coeff_petiole_d/2,height=total_petiole_leaflet)
leaflet_left = pgl.AxisRotated(axis=(1,0,0),angle=-radians(60),geometry=leaflet)
leaflet_right = pgl.AxisRotated(axis=(1,0,0),angle=radians(60),geometry=leaflet)
leaflets = [petiole]
translate = [0,0,petiole_leaflet_length]
count_leaflets = nb_leaflets
leaflets.append(pgl.Translated(translate,leaflet_left))
leaflets.append(pgl.Translated(translate,leaflet_right))
for i in range(nb_petiole):
leaflets.append(pgl.Translated(translate,leaflet_left))
leaflets.append(pgl.Translated(translate,leaflet_right))
translate[2] += petiole_leaflet_length
count_leaflets -=2
if count_leaflets == 1:
leaflets.append(pgl.Translated((0,0,total_petiole_leaflet),leaflet))
leafshape_lentil = pgl.Group(leaflets)
return leafshape_lentil
# Functions to generate leaf shapes (with leaflets for Fababean)
[docs]
def make_leafshape_rapeseed(u=9, v=2):
sc_factor = 3.572567770618656
pts = lambda x,y,z : pgl.Vector4(x/sc_factor,y/sc_factor,z/sc_factor,1.0)
r1=[pts(0,0,0), pts(7,-0.5,1), pts(3,-3,2), pts(1.5,-5,2.75), pts(-1,0,3)]
r2=[pts(0,0,0), pts(7,0.5,1), pts(3,3,2), pts(1.5,5,2.75), pts(-1,0,3)]
m=pgl.Point4Matrix([r1,r2])
leafshape_rapeseed=pgl.BezierPatch(m, ustride=u, vstride=v)
return(leafshape_rapeseed)
#original
[docs]
def make_leafshape_rapeseed_original(u=9, v=2):
sc_factor = 3.54673835885395
pts = lambda x,y,z : pgl.Vector4(x/sc_factor,y/sc_factor,z/sc_factor,1.0)
r1=[pts(0,0,0), pts(5,-0.5,1), pts(5,-3,2), pts(-1,-5,2.75), pts(-1,0,3)]
r2=[pts(0,0,0), pts(5,0.5,1), pts(5,3,2), pts(-1,5,2.75), pts(-1,0,3)]
m=pgl.Point4Matrix([r1,r2])
leafshape_rapeseed=pgl.BezierPatch(m, ustride=u, vstride=v)
return(leafshape_rapeseed)
[docs]
def make_leaflet_shape_fababean(u=9, v=2):
sc_factor = 3.173
pts = lambda x,y,z : pgl.Vector4(x/sc_factor,y/sc_factor,z/sc_factor,1.0)
r1=[pts(0,0,0), pts(0,-1,0.1), pts(0,-2,1), pts(0,-3,2), pts(0,-1,3), pts(0,-1,3.9), pts(0,0,4)]
r2=[pts(0,0,0), pts(0,1,0.1), pts(0,2,1), pts(0,3,2), pts(0,1,3), pts(0,1,3.9), pts(0,0,4)]
m=pgl.Point4Matrix([r1,r2])
leafletshape_fababean=pgl.BezierPatch(m, ustride=u, vstride=v)
return(leafletshape_fababean)
[docs]
def make_leafshape_camelina(u=9, v=2):
sc_factor = 3.572567770618656
pts = lambda x,y,z : pgl.Vector4(x/sc_factor,y/sc_factor,z/sc_factor,1.0)
r1=[pts(0,0,0), pts(0,-0.5,1), pts(0,-3,2), pts(0,-5,2.75), pts(0,0,3)]
r2=[pts(0,0,0), pts(0,0.5,1), pts(0,3,2), pts(0,5,2.75), pts(0,0,3)]
m=pgl.Point4Matrix([r1,r2])
leafshape_camelina=pgl.BezierPatch(m, ustride=u, vstride=v)
return(leafshape_camelina)
[docs]
def make_leaflet_shape_lentil(u=9, v=2):
sc_factor = 3.173
pts = lambda x,y,z : pgl.Vector4(x/sc_factor,y/sc_factor,z/sc_factor,1.0)
r1=[pts(0,0,0), pts(0,-1,0.1), pts(0,-2,1), pts(0,-3,2), pts(0,-1,3), pts(0,-1,3.9), pts(0,0,4)]
r2=[pts(0,0,0), pts(0,1,0.1), pts(0,2,1), pts(0,3,2), pts(0,1,3), pts(0,1,3.9), pts(0,0,4)]
m=pgl.Point4Matrix([r1,r2])
leafletshape_lentil=pgl.BezierPatch(m, ustride=u, vstride=v)
return(leafletshape_lentil)
# Create MTGs for rapeseed and Fababean
[docs]
def vegetative(
DJ: int = 950,
dict_params={},
coord=[(0, 0, 0)],
species ='Fababean'):
""" Build a field with nrows(coord) plants that have n_nodes internodes
"""
phyllochrone = dict_params['phylloc']
n_nodes = int(round(DJ * phyllochrone))
if species == 'Fababean' or species == 'Lentil':
total_height = total_height_sigmoid(DJ, dict_params)
if n_nodes > 0.0:
node_length = total_height / n_nodes # equal height distribution among internodes
else:
node_length = 0.0
elif species == 'Rapeseed' or species == 'Camelina':
growth_node = dict_params['growth_node']
node_length = DJ * growth_node
g = MTG()
vid = g.add_component(g.root,
label='Plant',
edge_type='/',
position=coord) # vid = vertex_id
vid = g.add_child(vid, edge_type='<', label='Internode')
g.node(vid).NodeLength = node_length
leaf_id = g.add_child(vid, edge_type='+', label='Leaf')
for i in range(n_nodes - 1):
vid = g.add_child(vid, edge_type='<', label='Internode')
g.node(vid).NodeLength = node_length
leaf_id = g.add_child(vid, edge_type='+', label='Leaf')
return g
[docs]
def total_height_sigmoid(DJ, dict_params):
L = dict_params['L_height']
k = dict_params['k_height']
x0 = dict_params['x0_height']
# L = 36
# k = 0.1
# x0 = 600
total_height = L / (1 + np.exp(-k * (DJ - x0)))
return total_height
[docs]
def phenotype_rapeseed(g,
total_surface=200,
dict_params_rape={}):
"""
applies phenotypical attributes to an MTG based on parameters.
leaf_max : [float between 0 and 1] Expectation of the bell curve => Position of the biggest leaf along the stem.
phyllot: [float, degrees] phyllotaxy angle
ins_angle: [float, degrees] insertion angle of the petiole
leaf_angle: [float, degrees] angle of the flat of the leaf
total_surface: [int, cm2] surface to be shared following the bell proportion
coeff_width: [float] Leaf Width / Leaf Length ratio (limb only)
coeff_petiole: [float] Petiole Length / Leaf Length
stem_d: [float, cm] stem diameter
coeff_petiole_d : [float] petiole diameter / stem diameter ration
"""
leaf_max = dict_params_rape['rmax'] # float=0.6587057,
skew = dict_params_rape['k'] # float=5,
phyllot = dict_params_rape['phyllot'] # float = 137.5,
ins_angle = dict_params_rape['ins_angle'] # float = 60,
leaf_angle = 80.0 # à mesurer expérimentallement
coeff_width = dict_params_rape['coeff_width_leaf'] # float =0.831562,
coeff_petiole = dict_params_rape['coeff_petiole_leaf'] # float =0.51017, #limb length to petiole length , 0.31017 length/whole leag length
stem_d = 0.1
coeff_petiole_d = 0.5
output = dict()
plants = [k for k, v in g.properties()['label'].items() if v == 'Plant']
leaves = [k for k, v in g.properties()['label'].items() if v == 'Leaf']
internodes = [k for k, v in g.properties()['label'].items() if v == 'Internode']
output['coeff_width'] = dict(zip(plants, [coeff_width] * len(plants)))
output['coeff_petiole_d'] = dict(zip(plants, [coeff_petiole_d] * len(plants)))
output['stem_d'] = dict(zip(plants, [stem_d] * len(plants)))
surface = bell_shaped_dist(total_area=1, nb_phy=int(len(leaves) / len(plants)), rmax=leaf_max, skewness=skew)
output['SurfaceRepartition'] = dict(zip(leaves, surface * len(leaves)))
output['LeafSurface'] = dict(zip(leaves, [element * total_surface for element in surface] * len(leaves)))
output['LeafLength'] = dict(zip(leaves,
[2 * (element / (coeff_width * pi)) ** (0.5) for element in
output['LeafSurface'].values()] * len(leaves)))
output['LeafWidth'] = dict(zip(leaves,
[element * coeff_width for element in output['LeafLength'].values()] * len(leaves)))
output['SurfTheo'] = dict(zip(leaves, [pi * (element / 2) * (coeff_width * element / 2) for element in
output['LeafLength'].values()] * len(leaves)))
output['PetioleLength'] = dict(
zip(leaves, [element * coeff_petiole for element in output['LeafLength'].values()] * len(leaves)))
output['InsertionAngle'] = dict(zip(leaves, [ins_angle] * len(leaves)))
output['LeafAngle'] = dict(zip(leaves, [leaf_angle] * len(leaves)))
output['Phyllotaxy'] = dict(zip(internodes, [phyllot] * len(internodes)))
output['Phyllotaxy'].update(dict(zip(leaves, [phyllot] * len(leaves))))
output['StemDiam'] = dict(zip(internodes, [stem_d] * len(internodes)))
output['PetioleDiam'] = dict(zip(leaves, [stem_d * coeff_petiole_d] * len(leaves)))
update_MTG(g, output)
[docs]
def phenotype_camelina(g,
total_surface=200,
dict_params_came={}):
"""
applies phenotypical attributes to an MTG based on parameters.
leaf_max : [float between 0 and 1] Expectation of the bell curve => Position of the biggest leaf along the stem.
phyllot: [float, degrees] phyllotaxy angle
ins_angle: [float, degrees] insertion angle of the petiole
leaf_angle: [float, degrees] angle of the flat of the leaf
total_surface: [int, cm2] surface to be shared following the bell proportion
coeff_width: [float] Leaf Width / Leaf Length ratio (limb only)
coeff_petiole: [float] Petiole Length / Leaf Length
stem_d: [float, cm] stem diameter
coeff_petiole_d : [float] petiole diameter / stem diameter ration
"""
leaf_max = dict_params_came['rmax'] # float=0.6587057,
skew = dict_params_came['k'] # float=5,
phyllot = dict_params_came['phyllot'] # float = 137.5,
ins_angle = dict_params_came['ins_angle'] # float = 60,
leaf_angle = ins_angle # à mesurer expérimentallement
coeff_width = dict_params_came['coeff_width_leaf'] # float =0.831562,
coeff_petiole = dict_params_came['coeff_petiole_leaf'] # float =0.51017, #limb length to petiole length , 0.31017 length/whole leag length
stem_d = 0.1
coeff_petiole_d = 0.5
output = dict()
plants = [k for k, v in g.properties()['label'].items() if v == 'Plant']
leaves = [k for k, v in g.properties()['label'].items() if v == 'Leaf']
internodes = [k for k, v in g.properties()['label'].items() if v == 'Internode']
output['coeff_width'] = dict(zip(plants, [coeff_width] * len(plants)))
output['coeff_petiole_d'] = dict(zip(plants, [coeff_petiole_d] * len(plants)))
output['stem_d'] = dict(zip(plants, [stem_d] * len(plants)))
surface = bell_shaped_dist(total_area=1, nb_phy=int(len(leaves) / len(plants)), rmax=leaf_max, skewness=skew)
output['SurfaceRepartition'] = dict(zip(leaves, surface * len(leaves)))
output['LeafSurface'] = dict(zip(leaves, [element * total_surface for element in surface] * len(leaves)))
output['LeafLength'] = dict(zip(leaves,
[2 * (element / (coeff_width * pi)) ** (0.5) for element in
output['LeafSurface'].values()] * len(leaves)))
output['LeafWidth'] = dict(zip(leaves,
[element * coeff_width for element in output['LeafLength'].values()] * len(leaves)))
output['SurfTheo'] = dict(zip(leaves, [pi * (element / 2) * (coeff_width * element / 2) for element in
output['LeafLength'].values()] * len(leaves)))
output['PetioleLength'] = dict(
zip(leaves, [element * coeff_petiole for element in output['LeafLength'].values()] * len(leaves)))
output['InsertionAngle'] = dict(zip(leaves, [ins_angle] * len(leaves)))
output['LeafAngle'] = dict(zip(leaves, [leaf_angle] * len(leaves)))
output['Phyllotaxy'] = dict(zip(internodes, [phyllot] * len(internodes)))
output['Phyllotaxy'].update(dict(zip(leaves, [phyllot] * len(leaves))))
output['StemDiam'] = dict(zip(internodes, [stem_d] * len(internodes)))
output['PetioleDiam'] = dict(zip(leaves, [stem_d * coeff_petiole_d] * len(leaves)))
update_MTG(g, output)
[docs]
def phenotype_fababean(g,
total_surface: float = 300,
dict_params_faba={}):
"""
applies phenotypical attributes to an MTG based on parameters.
leaf_max : [float between 0 and 1] Expectation of the bell curve => Position of the biggest leaf along the stem.
phyllot: [float, degrees] phyllotaxy angle
ins_angle: [float, degrees] insertion angle of the petiole
leaf_angle: [float, degrees] angle of the flat of the leaf
total_surface: [int, cm2] surface to be shared following the bell proportion
coeff_width: [float] Leaf Width / Leaf Length ratio (limb only)
coeff_petiole: [float] Petiole Length / Leaf Length
stem_d: [float, cm] stem diameter
coeff_petiole_d : [float] petiole diameter / stem diameter ration
"""
leaf_max = dict_params_faba['rmax'] # float=0.6587057
skew = dict_params_faba['k'] # float=5
phyllot = dict_params_faba['phyllot'] # float = 163.5
ins_angle = dict_params_faba['ins_angle'] # float = 60
leaf_angle: float = 110 # à mesurer expérimentallement
coeff_width1 = dict_params_faba['coeff_width_leaflet1'] # float =0.831562
coeff_width2 = dict_params_faba['coeff_width_leaflet2'] # float =0.831562
coeff_petiole_leaflet1 = dict_params_faba[
'coeff_petiole_leaflet1'] # float =0.51017, #limb length to petiole length , 0.31017 length/whole leag length
coeff_petiole_leaflet2 = dict_params_faba[
'coeff_petiole_leaflet2'] # float =0.51017, #limb length to petiole length , 0.31017 length/whole leag length
stem_d = 0.1
coeff_petiole_d = 0.8
output = dict()
plants = [k for k, v in g.properties()['label'].items() if v == 'Plant']
leaves = [k for k, v in g.properties()['label'].items() if v == 'Leaf']
internodes = [k for k, v in g.properties()['label'].items() if v == 'Internode']
ranks = [i for i in range(1, len(leaves) + 1)]
nb_leaflets = [get_nb_leaflets(ri) for ri in ranks]
output['Nb_leaflets'] = dict(zip(leaves, nb_leaflets))
vec_coeff_width = [coeff_width1] * 2 + [coeff_width2] * (len(leaves) - 2)
output['coeff_width'] = dict(zip(leaves, vec_coeff_width))
# output['coeff_width'] = dict(zip(plants,[coeff_width]*len(plants)))
output['coeff_petiole_d'] = dict(zip(leaves, [coeff_petiole_d] * len(leaves)))
output['stem_d'] = dict(zip(leaves, [stem_d] * len(leaves)))
surface = bell_shaped_dist(total_area=1, nb_phy=int(len(leaves) / len(plants)), rmax=leaf_max, skewness=skew)
output['SurfaceRepartition'] = dict(zip(surface, leaves))
output['LeafSurface'] = dict(zip(leaves, [element * total_surface for element in surface]))
vec_leaflet_surface = [surface[i] * total_surface / nb_leaflets[i] for i in range(0, len(surface))]
output['LeafletSurface'] = dict(zip(leaves, vec_leaflet_surface))
# output['LeafLength']= dict(zip(leaves,vec_leaflet_length))
vec_leaflet_length = [2 * (vec_leaflet_surface[i] / (vec_coeff_width[i] * pi)) ** (0.5) for i in
range(0, len(vec_leaflet_surface))]
# leaflet_length = [2*(element/(coeff_width*pi))**(0.5) for element in output['LeafletSurface'].values()]
output['LeafletLength'] = dict(zip(leaves, vec_leaflet_length))
# output['LeafWidth']=dict(zip(leaves,
# [element *coeff_width for element in output['LeafLength'].values()]*len(leaves)))
vec_leaflet_width = [vec_leaflet_length[i] * vec_coeff_width[i] for i in range(0, len(vec_leaflet_length))]
output['LeafletWidth'] = dict(zip(leaves, vec_leaflet_width))
vec_surftheo = [pi * (vec_leaflet_length[i] / 2) * (vec_coeff_width[i] * vec_leaflet_length[i] / 2) * nb_leaflets[i]
for i in range(0, len(vec_leaflet_length))]
output['SurfTheo'] = dict(zip(leaves, vec_surftheo))
output['PetioleLength1'] = dict(
zip(leaves, [element * coeff_petiole_leaflet1 for element in output['LeafletLength'].values()]))
output['PetioleLength2'] = dict(
zip(leaves, [element * coeff_petiole_leaflet2 for element in output['LeafletLength'].values()]))
output['InsertionAngle'] = dict(zip(leaves, [ins_angle] * len(leaves)))
output['LeafAngle'] = dict(zip(leaves, [leaf_angle] * len(leaves)))
output['Phyllotaxy'] = dict(zip(internodes, [phyllot] * len(internodes)))
output['Phyllotaxy'].update(dict(zip(leaves, [0] * len(leaves))))
output['StemDiam'] = dict(zip(internodes, [stem_d] * len(internodes)))
output['PetioleDiam'] = dict(zip(leaves, [stem_d * coeff_petiole_d] * len(leaves)))
update_MTG(g, output)
[docs]
def phenotype_lentil(g,
total_surface: float = 300,
dict_params_lent={}):
"""
applies phenotypical attributes to an MTG based on parameters.
leaf_max : [float between 0 and 1] Expectation of the bell curve => Position of the biggest leaf along the stem.
phyllot: [float, degrees] phyllotaxy angle
ins_angle: [float, degrees] insertion angle of the petiole
leaf_angle: [float, degrees] angle of the flat of the leaf
total_surface: [int, cm2] surface to be shared following the bell proportion
coeff_width: [float] Leaf Width / Leaf Length ratio (limb only)
coeff_petiole: [float] Petiole Length / Leaf Length
stem_d: [float, cm] stem diameter
coeff_petiole_d : [float] petiole diameter / stem diameter ration
"""
leaf_max = dict_params_lent['rmax'] # float=0.6587057
skew = dict_params_lent['k'] # float=5
phyllot = dict_params_lent['phyllot'] # float = 163.5
ins_angle = dict_params_lent['ins_angle'] # float = 60
leaf_angle: float = 110 # à mesurer expérimentallement
coeff_width = dict_params_lent['coeff_width_leaflet'] # float =0.831562
coeff_petiole_leaflet = dict_params_lent[
'coeff_petiole_leaflet'] # float =0.51017, #limb length to petiole length , 0.31017 length/whole leag length
stem_d = 0.1
coeff_petiole_d = 0.8
output = dict()
plants = [k for k, v in g.properties()['label'].items() if v == 'Plant']
leaves = [k for k, v in g.properties()['label'].items() if v == 'Leaf']
internodes = [k for k, v in g.properties()['label'].items() if v == 'Internode']
ranks = [i for i in range(1, len(leaves) + 1)]
nb_leaflets = [get_nb_leaflets(ri) for ri in ranks]
output['Nb_leaflets'] = dict(zip(leaves, nb_leaflets))
vec_coeff_width = [coeff_width] * len(leaves)
output['coeff_width'] = dict(zip(leaves, vec_coeff_width))
# output['coeff_width'] = dict(zip(plants,[coeff_width]*len(plants)))
output['coeff_petiole_d'] = dict(zip(leaves, [coeff_petiole_d] * len(leaves)))
output['stem_d'] = dict(zip(leaves, [stem_d] * len(leaves)))
surface = bell_shaped_dist(total_area=1, nb_phy=int(len(leaves) / len(plants)), rmax=leaf_max, skewness=skew)
output['SurfaceRepartition'] = dict(zip(surface, leaves))
output['LeafSurface'] = dict(zip(leaves, [element * total_surface for element in surface]))
vec_leaflet_surface = [surface[i] * total_surface / nb_leaflets[i] for i in range(0, len(surface))]
output['LeafletSurface'] = dict(zip(leaves, vec_leaflet_surface))
# output['LeafLength']= dict(zip(leaves,vec_leaflet_length))
vec_leaflet_length = [2 * (vec_leaflet_surface[i] / (vec_coeff_width[i] * pi)) ** (0.5) for i in
range(0, len(vec_leaflet_surface))]
# leaflet_length = [2*(element/(coeff_width*pi))**(0.5) for element in output['LeafletSurface'].values()]
output['LeafletLength'] = dict(zip(leaves, vec_leaflet_length))
# output['LeafWidth']=dict(zip(leaves,
# [element *coeff_width for element in output['LeafLength'].values()]*len(leaves)))
vec_leaflet_width = [vec_leaflet_length[i] * vec_coeff_width[i] for i in range(0, len(vec_leaflet_length))]
output['LeafletWidth'] = dict(zip(leaves, vec_leaflet_width))
vec_surftheo = [pi * (vec_leaflet_length[i] / 2) * (vec_coeff_width[i] * vec_leaflet_length[i] / 2) * nb_leaflets[i]
for i in range(0, len(vec_leaflet_length))]
output['SurfTheo'] = dict(zip(leaves, vec_surftheo))
output['PetioleLength'] = dict(
zip(leaves, [element * coeff_petiole_leaflet for element in output['LeafletLength'].values()]))
output['InsertionAngle'] = dict(zip(leaves, [ins_angle] * len(leaves)))
output['LeafAngle'] = dict(zip(leaves, [leaf_angle] * len(leaves)))
output['Phyllotaxy'] = dict(zip(internodes, [phyllot] * len(internodes)))
output['Phyllotaxy'].update(dict(zip(leaves, [0] * len(leaves))))
output['StemDiam'] = dict(zip(internodes, [stem_d] * len(internodes)))
output['PetioleDiam'] = dict(zip(leaves, [stem_d * coeff_petiole_d] * len(leaves)))
update_MTG(g, output)
# backward compatibility
vegetative_fababean = vegetative
vegetative_rapeseed = partial(vegetative, species='Rapeseed')