Mentions légales du service

Skip to content
Snippets Groups Projects
Commit 7c699c93 authored by LEGRAND Jonathan's avatar LEGRAND Jonathan
Browse files

Fix some doc and docstrings

parent 7c9569d4
Branches
No related tags found
2 merge requests!3Improve lpy_tools,!2Add conda packaging
Pipeline #468627 failed
# Snapshots creation # Snapshots creation
Snapshots creates figures automatically from Lpy models using the python API
The module makes it possible to call a L-system from the user API and to plot figures Snapshot creates figures automatically from L-Py models using the python API.
corresponding to simulations obtained by varying some model parameters.
The module makes it possible to call a L-system from the user API and to plot figures corresponding to simulations obtained by varying some model parameters.
Two parameters at most can be varied to create the figure. Two parameters at most can be varied to create the figure.
The lscene_snapshot library offers 2 main functions: The `lscene_snapshot` library offers 2 main functions:
- simulate_and_shoot(model_filename, variables, suffix, cam_settings = camdict) - `simulate_and_shoot(model_filename, variables, suffix, cam_settings = camdict)`
- grid_simulate_and_shoot(simpoints, model_filename, free_variable_list, fixed_variables_dict, cam_settings = cam_setting_fun1, short_names = variable_short_names) - `grid_simulate_and_shoot(simpoints, model_filename, free_variable_list, fixed_variables_dict, cam_settings = cam_setting_fun1, short_names = variable_short_names)`
## Declaration of variables in the L-system model ## Declaration of variables in the L-system model
The L-system must export parameters that need to be controlled from the outside of the L-system file. The L-system must export parameters that need to be controlled from the outside of the L-system file.
Asssume for instance that parameters `diam, length, age, name` and `simtime` need to be exported. Assume for instance that parameters `diam, length, age, name` and `simtime` need to be exported.
This is done by declaring in the L-system file: This is done by declaring in the L-system file:
```
extern(diam = 2.3) extern(diam = 2.3)
extern(length = 10.6) extern(length = 10.6)
extern(age = 20) extern(age = 20)
extern(name = 'orchid') extern(name = 'orchid')
extern(simtime = 30) extern(simtime = 30)
param1 = 12.4 param1 = 12.4
param2 = True param2 = True
```
This means that only the variables `diam, length, age, name` and `simtime` can be changed by resetting them from the outside. This means that only the variables `diam, length, age, name` and `simtime` can be changed by resetting them from the outside.
Note that `param1` and `param2` cannot by changed from the outside of the L-system file (as they are not declared as `extern`). Note that `param1` and `param2` cannot be changed from the outside of the L-system file (as they are not declared as `extern`).
## Defining variables to call function `simulate_and_shoot()` of the library ## Defining variables to call function `simulate_and_shoot()` of the library
A dictionary of variables chosen among the extern variable of the model system can be defined. A dictionary of variables chosen among the extern variable of the model system can be defined.
Example: Example:
```python
vardict = {'diam':0.1, name:'fern', 'simtime': 38} vardict = {'diam':0.1, name:'fern', 'simtime': 38}
```
and then call the `simulate_and_shoot()` function. and then call the `simulate_and_shoot()` function.
```python
simulate_and_shoot(model_filename, variables, suffix, cam_settings = camdict) simulate_and_shoot(model_filename, variables, suffix, cam_settings = camdict)
```
suffix is an array of strings to store the computed images. suffix is an array of strings to store the computed images.
TODO: explain ... TODO: explain ...
...@@ -46,119 +47,121 @@ TODO: explain ... ...@@ -46,119 +47,121 @@ TODO: explain ...
It is possible to select a pair of variables for which we want to create a figure by giving them different values. It is possible to select a pair of variables for which we want to create a figure by giving them different values.
`(x1,y1)(x2,y2), ... (xn,yn)` `(x1,y1)(x2,y2), ... (xn,yn)`
For this, we first need to identify the pair of variables selected variable that we want to browse. This is done by defining the list `free_variable_list` For this, we first need to identify the pair of variables selected variable that we want to browse.
free_variable_list containing the list of free variables to vary for launching the set of simulations: This is done by defining the list `free_variable_list`.
`free_variable_list` containing the list of free variables to vary for launching the set of simulations:
free_variable_list = ['diam','age'] ```python
free_variable_list = ['diam','age']
The first variable `diam` is considered as the x variable, while the second variable is the y variable (x will vary on the horizontal axis of the figure and y on the vertical axis. ```
The first variable `diam` is considered as the x variable, while the second variable is the y variable (x will vary on the horizontal axis of the figure and y on the vertical axis).
Other extern variables of the model can be given a constant value different from that they have in the L-system file by listing them in the list fixed_variables_dict, and then redefining their value:
Other extern variables of the model can be given a constant value different from that they have in the L-system file by listing them in the list `fixed_variables_dict`, and then redefining their value:
fixed_variables_dict = {'length', 'name'} ```python
fixed_variables_dict = {'length', 'name'}
```
All the other extern variables will keep constant and defined with the value given in the L-system file. All the other extern variables will keep constant and defined with the value given in the L-system file.
Finally, to define the list of pairs of values of the free variables x and y (here `diam` and `age`), a dictionary is defined as follaws: Finally, to define the list of pairs of values of the free variables x and y (here `diam` and `age`), a dictionary is defined as follows:
```
simpoints = { y1:[x1,x2,..,xk], y2:[x1',x2',..,xl'], y3: ... , yn:[x1'',x2'', ..,xl''] } simpoints = { y1:[x1,x2,..,xk], y2:[x1',x2',..,xl'], y3: ... , yn:[x1'',x2'', ..,xl''] }
```
`simpoints` defines for each value of y a list of values of x for which a pair (x,y) must be computed by the simulation. `simpoints` defines for each value of y a list of values of x for which a pair (x,y) must be computed by the simulation.
In our example e.g.: In our example _e.g._:
```python
simpoints = { 10:[1,2,3,4], 20:[1,2,3,4], 30.0:[1,2,5] } simpoints = { 10:[1,2,3,4], 20:[1,2,3,4], 30.0:[1,2,5] }
```
Meaning that (diam,age) values `(1,10), (2,10),(3,10),(4,10),(1,20),(2,20),(3,20),...,(5,30)` will be used to launch 11 simulations. Meaning that (diam,age) values `(1,10), (2,10),(3,10),(4,10),(1,20),(2,20),(3,20),...,(5,30)` will be used to launch 11 simulations.
Note that the y-arrays need not be of the same size nor have the same values. Note that the y-arrays need not be of the same size nor have the same values.
### Redefining variable name to be printed in figures ### Redefining variable name to be printed in figures
The dictionary variable_short_names can be set to give a short name to each The dictionary `variable_short_names` can be set to give a short name to each variable (extern or intern) that will be used to the label the small images.
variable (extern or intern) that will be used to the label the small images.
Only names in this list will be used to construct small image labels: Only names in this list will be used to construct small image labels:
```python
variable_short_names = {'diam':'D', 'length': 'L'} variable_short_names = {'diam':'D', 'length': 'L'}
```
### Setting camera attributes ### Setting camera attributes
Camera attributes can be set prior to calling the simulation and shooting. Here are the attributes that can be defined with exmaple values:
target_point = None # looks a bit above z = 0. Value is a 3-uple (x,y,z)
zoomcoef = 1. # increase to zoom out
camdist = 1. # increase to widen the observation window
elevation = 30 # elevation of the camera sight (in degrees)
azimuth = 0. # Azimuth of the camera
bb = None # Bounding box
width = 400 # Window size in pixels
height = 400 # Window size in pixels
aspectratio = 1.0 # contraction of X and Y direction defined by Height/Width
znear = 0.1 # defines the plane on which the scene is projected as the distance between camera and object that should not intersect visualized objects
zfar = 200 # Same thing for the farthest plane in the camera. Only objects between these two planes can be seen
lightpos = (0, 0, 10) # light characteristics
ambiant = (255, 255, 255)
diffuse = (0, 0, 0)
specular = (0, 0, 0))
Camera attributes can be set prior to calling the simulation and shooting.
Here are the attributes that can be defined with example values:
```
target_point = None # looks a bit above z = 0. Value is a 3-uple (x,y,z)
zoomcoef = 1. # increase to zoom out
camdist = 1. # increase to widen the observation window
elevation = 30 # elevation of the camera sight (in degrees)
azimuth = 0. # Azimuth of the camera
bb = None # Bounding box
width = 400 # Window size in pixels
height = 400 # Window size in pixels
aspectratio = 1.0 # contraction of X and Y direction defined by Height/Width
znear = 0.1 # defines the plane on which the scene is projected as the distance between camera and object that should not intersect visualized objects
zfar = 200 # Same thing for the farthest plane in the camera. Only objects between these two planes can be seen
lightpos = (0, 0, 10) # light characteristics
ambiant = (255, 255, 255)
diffuse = (0, 0, 0)
specular = (0, 0, 0))
```
Then all these values can be assembled in a dictionary that will be passed to the simulation and shooting function: Then all these values can be assembled in a dictionary that will be passed to the simulation and shooting function:
```python
camdict = {'camdist':camdist, 'zoomcoef':zoomcoef, 'bb':None, 'target_point':target_point} camdict = {'camdist':camdist, 'zoomcoef':zoomcoef, 'bb':None, 'target_point':target_point}
```
This camdict can be read directly from a LPy camera file using This camdict can be read directly from a LPy camera file using
```python
camdict = read_camera('my_camera.txt') camdict = read_camera('my_camera.txt')
```
Alternatively, if the camera parameters depend on the values of the free variables, Alternatively, if the camera parameters depend on the values of the free variables, on can define a function of the two free variables, that will return a dictionary corresponding to each pair of free variables values:
on can define a function of the two free variables, that will return a dictionary corresponding to each pair of free variables values: ```python
def cam_setting_fun1(x,y):
def cam_setting_fun1(x,y): '''
''' Function that defines the camera setting values for each pair of parameter values (x,y)
Function that defines the camera setting values for each pair of parameter values (x,y) '''
''' t = target_point
t = target_point z = zoomcoef
z = zoomcoef c = camdist
c = camdist
return {'camdist':c, 'zoomcoef':z, 'bb':None, 'target_point':t, 'elevation':0.0}
return {'camdist':c, 'zoomcoef':z, 'bb':None, 'target_point':t, 'elevation':0.0} ```
### Launching the simulation ### Launching the simulation
```shell
shell> ipython --gui=qt make_snapshots.py ipython --gui=qt make_snapshots.py
```
or within ipython: or within `ipython`:
```shell
ipython> %gui qt # to make sure that qt will be used for interpreting the event loop of PlantGL viewer ipython> %gui qt # to make sure that qt will be used for interpreting the event loop of PlantGL viewer
ipython> %run make_snapshots.py ipython> %run make_snapshots.py
```
### Example of use ### Example of use
```python
from openalea.plantgl.all import Vector3 from openalea.plantgl.all import Vector3
from openalea import lpy from .lscene_snapshots import simulate_and_shoot, grid_simulate_and_shoot, plot_images, build_suffix
from .lscene_snapshots import simulate_and_shoot, grid_simulate_and_shoot, plot_images, build_suffix
model_filename = 'model.lpy'
model_filename = 'model.lpy'
###########################################
########################################### # Define the simulations parameters
# Define the simulations parameters ###########################################
###########################################
free_variable_list = ['diam','age']
free_variable_list = ['diam','age'] fixed_variables_dict = {'length', 'name'}
fixed_variables_dict = {'length', 'name'} simpoints = { 10:[1,2,3,4], 20:[1,2,3,4], 30.0:[1,2,5] } # {age:[list of diams], ...}
simpoints = { 10:[1,2,3,4], 20:[1,2,3,4], 30.0:[1,2,5] } # {age:[list of diams], ...}
# Definition of shortnames for variables (used for generating small image names)
# Definition of shortnames for variables (used for generating small image names) variable_short_names = {'diam':'D', 'length': 'L'}
variable_short_names = = {'diam':'D', 'length': 'L'}
###########################################
########################################### # Define the camera parameters
# Define the camera parameters ###########################################
###########################################
target_point = Vector3(0,0,30.) # looks a bit above z = 0
target_point = Vector3(0,0,30.) # looks a bit above z = 0 zoomcoef = 1 # increase to zoom out
zoomcoef = 1 # increase to zoom out camdist = 150. # increase to widen the observation window
camdist = 150. # increase to widen the observation window camdict = {'camdist':camdist, 'zoomcoef':zoomcoef, 'bb':None, 'target_point':target_point}
camdict = {'camdist':camdist, 'zoomcoef':zoomcoef, 'bb':None, 'target_point':target_point}
grid_simulate_and_shoot(simpoints,
grid_simulate_and_shoot(simpoints, model_filename,
model_filename, free_variable_list,
free_variable_list, fixed_variables_dict,
fixed_variables_dict, cam_settings = cam_dict,
cam_settings = cam_dict, short_names = variable_short_names)
short_names = variable_short_names) ```
\ No newline at end of file
# Reference snapshots API # Reference snapshots API
## Module `lpy_tools.snapshots.lscene_snapshots` ## Module `lpy_tools.snapshots.lscene_snapshots`
```{eval-rst} ```{eval-rst}
.. automodule:: lpy_tools.snapshots.lscene_snapshots .. automodule:: lpy_tools.snapshots.lscene_snapshots
:members: :members:
......
...@@ -14,15 +14,7 @@ ...@@ -14,15 +14,7 @@
# ----------------------------------------------------------------------- # -----------------------------------------------------------------------
""" """
Library of tools to take snapshots of the result of a l-system simulations Library of tools to take snapshots of the result of an L-System simulations.
Authors: Christophe Godin, Inria, 2021
Licence: Open source LGPL
The lscene_snapshot library offers 2 main functions:
simulate_and_shoot(model_filename, variables, suffix, cam_settings = camdict)
grid_simulate_and_shoot(simpoints, model_filename, free_variable_list, fixed_variables_dict, cam_settings = cam_setting_fun1, short_names = variable_short_names)
""" """
import os import os
...@@ -53,8 +45,8 @@ def read_camera(filename): ...@@ -53,8 +45,8 @@ def read_camera(filename):
tokens = data.split() tokens = data.split()
camdict = { camdict = {
'azimuth': float(tokens[0]), # Azimuth of the camera frame (originaly positionned at eye position) 'azimuth': float(tokens[0]), # Azimuth of the camera frame (originally positioned at eye position)
'elevation': float(tokens[1]), # Elevation of camera frame (originaly positionned at eye position) 'elevation': float(tokens[1]), # Elevation of camera frame (originally positioned at eye position)
'stepmove': int(tokens[2]), # ReadOnly - cannot be changed by API 'stepmove': int(tokens[2]), # ReadOnly - cannot be changed by API
'center': (float(tokens[3]), float(tokens[4]), float(tokens[5])), 'center': (float(tokens[3]), float(tokens[4]), float(tokens[5])),
'eye': (float(tokens[6]), float(tokens[7]), float(tokens[8])), 'eye': (float(tokens[6]), float(tokens[7]), float(tokens[8])),
...@@ -191,30 +183,33 @@ def take_snapshot(viewer, filename_prefix=".", suffix="", ...@@ -191,30 +183,33 @@ def take_snapshot(viewer, filename_prefix=".", suffix="",
def take_offline_snapshot(lscene, filename_prefix=".", suffix="", def take_offline_snapshot(lscene, filename_prefix=".", suffix="",
cam_settings={'camdist': 1., 'zoomcoef': 1., 'bb': None, 'target_point': None}): cam_settings={'camdist': 1., 'zoomcoef': 1., 'bb': None, 'target_point': None}):
""" """Take a snapshot of a computed lpy_scene without the need of running L-Py.
take a snapshot of a computed lpy_scene without the need of running LPy.
Camera attributes defined in cam_settings:
- target_point is the point at which the camera is looking (Vector3)
- camdist fixes the distance of the camera to the target point (in screen units)
- zoomcoef is a multiplicative zoom factor (higher means zooming out)
- azimuth is an angle in degrees
- elevation is a height in screen units with respect to the (x,y) plane (applied after having zoomed in/out)
filename_prefix:
suffix: name of the image
Parameters Parameters
---------- ----------
lscene lscene : ???
???
filename_prefix: str, optional filename_prefix: str, optional
A prefix directory may be defined (default is current directory '.') A prefix directory may be defined (default is current directory '.')
suffix suffix : str, optional
cam_settings Name of the image.
cam_settings : dict
A dictionary of camera settings. See ``grid_simulate_and_shoot``.
Returns Returns
------- -------
str str
name of the png file Name of the png file.
Notes
-----
Camera attributes defined in `cam_settings`:
- target_point is the point at which the camera is looking (Vector3)
- camdist fixes the distance of the camera to the target point (in screen units)
- zoomcoef is a multiplicative zoom factor (higher means zooming out)
- azimuth is an angle in degrees
- elevation is a height in screen units with respect to the (x,y) plane (applied after having zoomed in/out)
""" """
# May be try this to simplyfy what follows # May be try this to simplyfy what follows
...@@ -325,7 +320,6 @@ def take_offline_snapshot(lscene, filename_prefix=".", suffix="", ...@@ -325,7 +320,6 @@ def take_offline_snapshot(lscene, filename_prefix=".", suffix="",
zb.lookAt(np, c, upvect) zb.lookAt(np, c, upvect)
# LIGHT: setLight(lightpos, ambiant, diffuse, specular) # LIGHT: setLight(lightpos, ambiant, diffuse, specular)
zb.setLight(lightpos, ambiant, diffuse, specular) zb.setLight(lightpos, ambiant, diffuse, specular)
# MAKE PICTURE # MAKE PICTURE
...@@ -419,6 +413,31 @@ def take_circular_snapshots(viewer, delta_a=36, filename_prefix=".", suffix="", ...@@ -419,6 +413,31 @@ def take_circular_snapshots(viewer, delta_a=36, filename_prefix=".", suffix="",
def simulate_and_shoot(model_filename, variables, suffix, cam_settings): def simulate_and_shoot(model_filename, variables, suffix, cam_settings):
"""Build the L-system with its input variables
Parameters
----------
model_filename : str
File name (and path) to the L-Py model.
variables : ???
???.
suffix : str
The suffix string built from the list of variables. See ``build_suffix``.
cam_settings : dict
A dictionary of camera settings. See ``grid_simulate_and_shoot``.
Returns
-------
str
Name of the png file.
See Also
--------
build_suffix
grid_simulate_and_shoot
take_offline_snapshot
"""
# build the L-system with its input variables # build the L-system with its input variables
lsys = lpy.Lsystem(model_filename, variables) lsys = lpy.Lsystem(model_filename, variables)
...@@ -455,12 +474,26 @@ def simulate_and_shoot(model_filename, variables, suffix, cam_settings): ...@@ -455,12 +474,26 @@ def simulate_and_shoot(model_filename, variables, suffix, cam_settings):
return iname return iname
def build_suffix(var, short_names=None): def build_suffix(var, short_names=None, sep=" "):
""" """Build a string from a dictionary of variables.
takes a dict of variables and constructs a str suffix identifying uniquely this set of parameter
Takes a dict of variables and constructs a str suffix identifying uniquely this set of parameter
(for further defining a name corresponding to this set of parameters for storage on disk of corresponding results) (for further defining a name corresponding to this set of parameters for storage on disk of corresponding results)
Parameters
----------
var
short_names : ???, optional
list of short names ???
sep : {' ', '_', '#'}, optional
The separator to use to concatenate the variables. Defaults to `" "`, a space.
Returns
-------
str
The string built from the dictionary of variables.
""" """
sep = ' ' # could also be ' ', '_' or '#'
stg = '' stg = ''
index = 0 index = 0
for name in var: for name in var:
...@@ -481,16 +514,32 @@ def build_suffix(var, short_names=None): ...@@ -481,16 +514,32 @@ def build_suffix(var, short_names=None):
def build_variables_dict(x, y, free_variable_list, fixed_variables): def build_variables_dict(x, y, free_variable_list, fixed_variables):
""" """Builds a dictionary of variables by blending free variables (made of two variables)
builds a dictionary of variables by blending free variables (made of two variables)
- x,y are the values of the two free free_variables Parameters
- free_variable_list contains the names of the free variables ----------
- fixed_variables is a dict of variables with already defined values (i.e. fixed) x, y : float
Values of the free variables.
free_variable_list : list of str
The names of the free variables `x` & `y`.
fixed_variables : dict
Dictionary of variables with already defined values, *i.e.* fixed.
Returns
-------
dict
Dictionary of variable names & values ``{'name': value}``.
Raises
------
ValueError
If the `free_variable_list` is not at least of length 2.
Precondition: len(free_variable_list) >= 2
""" """
assert len(free_variable_list) >= 2 # (at list names for x and y should be defined) try:
assert len(free_variable_list) >= 2 # (at list names for x and y should be defined)
except AssertionError:
raise ValueError(f"Parameter `free_variable_list` should be at least of length 2, got '{len(free_variable_list)}'!")
vardict = fixed_variables.copy() vardict = fixed_variables.copy()
vardict.update({free_variable_list[0]: x}) vardict.update({free_variable_list[0]: x})
...@@ -502,16 +551,24 @@ def build_variables_dict(x, y, free_variable_list, fixed_variables): ...@@ -502,16 +551,24 @@ def build_variables_dict(x, y, free_variable_list, fixed_variables):
def grid_simulate_and_shoot(simpoints, model_filename, free_variable_list, fixed_variables, def grid_simulate_and_shoot(simpoints, model_filename, free_variable_list, fixed_variables,
cam_settings={'camdist': 1., 'zoomcoef': 1., 'bb': None, 'target_point': None}, cam_settings={'camdist': 1., 'zoomcoef': 1., 'bb': None, 'target_point': None},
short_names=None): short_names=None):
""" """Launch simulations of the lpy model `model_filename` for free parameters values defined in `simpoints`.
launches simulations of the lpy model model_filename for free parameters values defined in simpoints,
- simpoints is a dict whose keys are the y values and the values are lists of x-values for each y key
- free variable names are given in free_variable_list and
- fixed variables are defined with their values in the fixed_variables dict (parameters fixed for all simulations)
- cam_setting can be a simple dict Parameters
cam_settings = {'camdist':1., 'zoomcoef':1., 'bb':None, 'target_point':None} ----------
or a function returning a dict for args = (x,y) = pair of values of the free parameters simpoints : dict
cam_settings(x,y) --> {'camdist':val1, 'zoomcoef':val2, 'bb':val3, 'target_point':val4} A dictionary hose keys are the y values and the values are lists of x-values for each y key
model_filename : str
File name (and path) to the L-Py model.
free_variable_list : list of str
The names of the free variables `x` & `y`.
fixed_variables : dict
Dictionary of variables with already defined values, *i.e.* fixed.
cam_settings : dict, optional
Can be a simple dictionary like ``cam_settings = {'camdist':1., 'zoomcoef':1., 'bb':None, 'target_point':None}``.
Or a function returning a dict for args = (x,y) = pair of values of the free parameters like
``cam_settings(x,y) --> {'camdist':val1, 'zoomcoef':val2, 'bb':val3, 'target_point':val4}``
short_names : ???, optional
list of short names ???
""" """
...@@ -568,19 +625,25 @@ def grid_simulate_and_shoot(simpoints, model_filename, free_variable_list, fixed ...@@ -568,19 +625,25 @@ def grid_simulate_and_shoot(simpoints, model_filename, free_variable_list, fixed
def plot_images(image_name_list, index_list=None, dir='.', size=(1, 1)): def plot_images(image_name_list, index_list=None, dir='.', size=(1, 1)):
""" """Plots the grid of png images @ grid positions defined by index_list.
Plots the grid of png images @ grid positions defined by index_list
Parameters
----------
image_name_list : list of str
List of image files to plot.
index_list : list, optional
1 dimensional position, flattened 2D position in a grid of ``(size[0], size[1])``
dir : str, optional
specifies the directory where to print
size : tuple, optional
The dimensions of the underlying 2D grid
- index_list = 1 dimensional position = flattened 2D position in a grid of size[0]xsize[1]
- dir specifies the directory where to print
- size is the dimensions of the underlying 2D grid
""" """
# A figure is a canvas that contains axes (= places on which to plot) # A figure is a canvas that contains axes (= places on which to plot)
# by default the figure has one axis # by default the figure has one axis
# plot functions can be called on axes only (and not on figures) # plot functions can be called on axes only (and not on figures)
# but a different setting of axes can be created wth subplots # but a different setting of axes can be created wth subplots
# fig = plt.figure(figsize=(10, 15))
dim2 = min(size[0] * 3, 10) dim2 = min(size[0] * 3, 10)
dim1 = min(size[1] * 3, 15) dim1 = min(size[1] * 3, 15)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment