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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,6 @@ doc/_build

# baugetfa
tmp*
test/data/test_rsml_io.rsml
out.csv

14 changes: 7 additions & 7 deletions doc/example/example_rsml_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
into continuous mtg representation
- set the resolution according to the unit precised in the rsml, in Hydroroot lengths are in meter
- transform the continuous mtg to discrete mtg usable in Hydroroot according to resolution
- calculation of g properties (radius, mylength) and flux
- calculation of g properties (radius, dist_to_base) and flux

- export discrete mtg to rsml
- re-import rsml to continuous mtg, transform the latter to discrete mtg
- re-do calculation of g properties (radius, mylength) and flux
- re-do calculation of g properties (radius, dist_to_base) and flux

- compare both calculations should be zero

Expand Down Expand Up @@ -53,7 +53,7 @@ def set_mtg_properties(g):
Set MTG properties and perform some gemetrical calculation

The vertex radius properties is set.
The following properties are computed: length, position, mylength, surface, volume, total length,
The following properties are computed: length, position, dist_to_base, surface, volume, total length,
primary root length

:param:
Expand All @@ -75,11 +75,11 @@ def set_mtg_properties(g):
# Calculation of the distance from base of each vertex, used for cut and flow
# Remark: this calculation is done in flux.segments_at_length; analysis.nb_roots but there is a concern with the
# parameter dl which should be equal to vertex length but which is not pass
_mylength = {}
_dist_to_base = {}
for v in traversal.pre_order2(g, 1):
pid = g.parent(v)
_mylength[v] = _mylength[pid] + parameter.archi['segment_length'] if pid else parameter.archi['segment_length']
g.properties()['mylength'] = _mylength
_dist_to_base[v] = _dist_to_base[pid] + parameter.archi['segment_length'] if pid else parameter.archi['segment_length']
g.properties()['dist_to_base'] = _dist_to_base

# _length is the total length of the RSA (sum of the length of all the segments)
_length = g.nb_vertices(scale = 1) * parameter.archi['segment_length']
Expand Down Expand Up @@ -139,7 +139,7 @@ def hydro_calculation(g, axfold = 1., radfold = 1., axial_data = None, k_radial
# continuous mtg to discrete mtg
g = import_rsml_to_discrete_mtg(g_c, segment_length = parameter.archi['segment_length'], resolution = resolution)

# calculation of g properties: radius, mylength, etc.
# calculation of g properties: radius, dist_to_base, etc.
g, primary_length, _length, surface = set_mtg_properties(g)

# flux calculation
Expand Down
166 changes: 166 additions & 0 deletions doc/example/metafspm/example_metafspm_archi_from_file.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
#!/usr/bin/env python
# coding: utf-8

# # Measured architecture

# Read architecture from text file and run a simulation of the sap flux from an Arabidopsis de-topped root plunged in a hydroponic solution at a hydrostatic pressure of 0.4 Mpa when its base is at the atmospheric pressure.

# ## The text format architecture file
#
# |distance_from_base_(mm) |lateral_root_length_(mm) |order|
# |:-: | :-: | :-: |
# |0.89 |90.81 |1|
# |3.02 |63.98 |1|
# |102.94 |0.0 |1|
# |2.14 |23.72 |1-1|
# |90.81 |0.0 |1-1|
# |2.48 |5.15 |1-2|
# |63.98 |0.0 |1-2|
#
# This is a tab separated text file with 3 columns:
#
# 1. the distance from base of the branching laterals in mm
#
# 2. the lateral root length in mm
#
# 3. a string of one or more number indicating the parent root
#
# In the example above, the root has two lateral of 1st order and on each of them one lateral of 2d order. The order of 1 indicates that the laterals are on the primary root. The last line with order 1 with 0.0 in the second column indicates the primary root tip. The line with order 1-1 indicates that this a second order lateral on the first lateral positioned at 2.14 mm from the branching on the primary root. And so on.
#
# A 4th column with the averaged diameter of the root may be given, that may be used to build the MTG representing the architecture.

# ## Running the calculation
# If the package HydroRoot is not installed, the following examples can be run by cloning the sources from git and then sourcing the src directory in Ipython console for instance like this:

# In[1]:


get_ipython().run_line_magic('matplotlib', 'inline')


# In[2]:


import matplotlib
from openalea.widgets.plantgl import PlantGL # notebook viewer 3D
from openalea.plantgl.algo.view import view # 2D view
from openalea.hydroroot.display import mtg_scene
from openalea.hydroroot.read_file import read_archi_data
from openalea.hydroroot.main import hydroroot_flow, root_builder
from openalea.hydroroot.generator import measured_root
from openalea.hydroroot import model
from openalea.mtg import MTG


# Read the architecture file as DataFrame

# In[3]:


df = read_archi_data('../data/plant-01.txt')


# Building the MTG from the file, and return the primary root length, the total length and the surface. The seed refer to the seed of the root generator when the MTG is not built from a file but is generated.

# In[4]:

segment_length = 1.0e-4
time_step = 1.0e-4

g = measured_root.mtg_from_aqua_data(df, segment_length)
hydromodel = model.HydroRootModel(g, time_step)
hydromodel.compute_metrics()

# Some conductance data versus distance to tip

# In[5]:


hydromodel.compute_radial_conductance(data = ([0, 0.2],[30.0,30.0]))
hydromodel.compute_axial_conductance(data = ([0, 0.2],[3.0e-7,4.0e-4]))


# Flux and equivalent conductance calculation, for a root in an external hydroponic medium at 0.4 MPa, its base at 0.1 MPa, and with the conductances set above.

# In[6]:

# g = hydromodel.g
# g, keq, jv = hydroroot_flow(g, psi_e = 0.4, psi_base = 0.1, axial_conductivity_data = K_axial_data, radial_conductivity_data = k_radial_data)
hydromodel.psi_e = 0.4
hydromodel.psi_base = 0.1
hydromodel.hydrostatic_solver_flux()

# In[7]:


print('equivalent root conductance (microL/s/MPa): ',hydromodel.keq, 'sap flux (microL/s): ', hydromodel.Jv)


# ## Plots

# Display the local water uptake heatmap in 3D

# In[8]:


s = mtg_scene(g, prop_cmap = 'j') # create a scene from the mtg with the property j is the radial flux in ul/s
PlantGL(s) # display the root into the plantgl oawidget


# You may change the property to display to the hydrostatic pressure inside the xylem vessels for instance
#
# to reduce notebook size we use here a 2D view but you can use the openalea.widgets `PlantGL(s)` to display an interactive 3D view

# In[9]:


s = mtg_scene(g, prop_cmap='psi_in')
view(s) #PlantGL(s)


# You may change the radial conductivity and see the impact on the water uptake

# In[10]:


hydromodel.compute_radial_conductance(data = ([0, 0.2],[300.0,300.0]))
hydromodel.hydrostatic_solver_flux()
print('sap flux (microL/s): ', hydromodel.Jv)
s = mtg_scene(g, prop_cmap='j')
view(s) # to reduce notebook size we use here a 2D view but use PlantGL(s) to 3D


# Or the axial conductance

# In[11]:


hydromodel.compute_radial_conductance(data = ([0, 0.2],[30.0,30.0]))
hydromodel.compute_axial_conductance(data = ([0, 0.2],[3.0e-7,4.0e-4]))
hydromodel.hydrostatic_solver_flux()
print('sap flux (microL/s): ', hydromodel.Jv)
s = mtg_scene(g, prop_cmap='j')
view(s) # to reduce notebook size we use here a 2D view but use PlantGL(s) to 3D


# ## PlantGl viewer
#
# This is only working on **local machine**.
#
# HydroRoot has also a function using the standalone Plantgl viewer allowing to specify the mtg property.
#
# The following will open a standalone window with a 3D representation of the root. Uncomment the lines to run the cell locally.

# In[12]:


# from openalea.hydroroot.display import plot
# %gui qt
# plot(g, prop_cmap='psi_in')
from openalea.hydroroot.init_parameter import Parameters
parameter = Parameters()
parameter.read_file('parameters_plant_01.yml')
scenario = parameter.metafspm_scenario()
hydromodel = model.HydroRootModel(g, time_step, **scenario)
hydromodel.hydrostatic_solver_flux()
print('sap flux (microL/s): ', hydromodel.Jv)
118 changes: 118 additions & 0 deletions doc/example/metafspm/parameters_plant_01.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
#%YAML

#All parameters should be in SI units

#Few parameters may be set to list of float or integer allowing to run successive simulation
# there are two syntaxes:
# [x1, ..., xn] or range(start, end, step)
# eg. range(0.02, 0.09, 0.02) or [0.02, 0.04, 0.06, 0.08] will give the same results
# the parameter will take successively the values 0.02, 0.04, 0.06 and 0.08

archi:
#if read_architecture is true then architecture will be constructed from the file(s) given by input_dir and input_file
#otherwise the architecture will be generated according to the parameters
read_architecture: True

#Input architecture from scanned image (distance_from_base_(mm) \t lateral_root_length_(mm) \t order)
#folder name
input_dir: ../data/

#File name:
#may be a list of names, eg. [file1, file2, file3] wildcar may be used
input_file: [plant-01.txt]

seed:

#file names with length laws relative path
#file format: "LR_length_mm" ; "relative_distance_to_tip"
#laws used to generate lateral roots of the 1st order (1_order_law), and lateral roots of order above 1 (2_order_law)
length_file:
- ../data/length*order1*.csv
- ../data/length*order2*.csv

#length of the primary root
#float or list of float
#unit: m
primary_length: 0.32

#branching delay
#float or list of float
#unit: m
branching_delay: 1.0e-4

#branching variability
#float between [0 ; 1], 0.25 means 25%
branching_variability: 0.25

#maximum roots order
order_max: 4

#vertices length
#unit: m
segment_length: 1.0e-4

#part of roots without any lateral root, distance from tip
#float or list of float
#unit: m
nude_length: 0.03

#reference radius of the primary root
#float
#unit: m
ref_radius: 7.0e-5

#radius decrease factor applied when increasing order
#float
#radius lateral order n: r = order_decrease_factor^n * ref_radius
order_decrease_factor: 0.7

hydro:
#radial conductivity
#float
#unit: microL/(s.MPa.m**2)
k0:
- [0.0, 0.32]
- [10.0, 10.0]

#axial_conductance_data
# - [x1, ......, xn]
# - [K1, ....., Kn]
#list of float
#unit: microL.m/(s.Mpa)
axial_conductance_data:
- [0, 0.32]
- [3.0e-9,2.0e-4]

experimental:
#water flux at the root base
#float
#unit: microL/s
Jv: 4.52e-3

#hydric potential outside the roots (pressure chamber)
#float
#unit: MPa
psi_e: 0.501325

#hydric potential at the root base (e.g. atmospheric pressure for decapitated plant)
#float
#unit: MPa
psi_base: .101325

output:
#distance from the base for intercepts calculation
# float or list of float
#unit: m
intercepts: []

#factor to explore a k0 range
# float or list of float
radfold: 1.

#like radfold but apply to axial_conductance_data
axfold: 1.

#number of run with the same set of parameters i.e. number of different seeds
#integer
#enable only if read_architecture is false
run_nb: 1
6 changes: 3 additions & 3 deletions src/openalea/hydroroot/analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ def nb_roots(g, l, root=1, dl=1e-4, max_order=None):
"""
length = {}

if 'mylength' in g.property_names():
length = g.property('mylength')
if 'dist_to_base' in g.property_names():
length = g.property('dist_to_base')
else:
for v in pre_order2(g, root):
pid = g.parent(v)
length[v] = length[pid] + dl if pid else dl
g.properties()['mylength'] = length
g.properties()['dist_to_base'] = length

order = None
if max_order is not None:
Expand Down
8 changes: 4 additions & 4 deletions src/openalea/hydroroot/display.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ def root_visitor(g, v, turtle, prune=prune):
:param prune: (float) - distance from base after witch the MTG is no longer read (Default value = None)

"""
mylength = {}
if prune and ('mylength' in g.properties()):
mylength = g.property('mylength')
dist_to_base = {}
if prune and ('dist_to_base' in g.properties()):
dist_to_base = g.property('dist_to_base')
angles = [90,45]+[30]*5
n = g.node(v)
# radius = n.radius*1.e4
Expand All @@ -49,7 +49,7 @@ def root_visitor(g, v, turtle, prune=prune):
length = n.length * factor

if prune:
if mylength.get(v,0.)>prune:
if dist_to_base.get(v,0.)>prune:
return

if g.edge_type(v) == '+':
Expand Down
6 changes: 3 additions & 3 deletions src/openalea/hydroroot/flux.py
Original file line number Diff line number Diff line change
Expand Up @@ -482,13 +482,13 @@ def segments_at_length(g, l, root=1, dl=1e-4):
"""
length = {}

if 'mylength' in g.property_names():
length = g.property('mylength')
if 'dist_to_base' in g.property_names():
length = g.property('dist_to_base')
else:
for v in traversal.pre_order2(g, root):
pid = g.parent(v)
length[v] = length[pid] + dl if pid else dl
g.properties()['mylength'] = length
g.properties()['dist_to_base'] = length

vids = []
for v in g:
Expand Down
Loading
Loading