Table of Contents
Connection with CPython and OpenAlea
Tested under Linux Ubuntu 9.10 with java 1.6.x, python 2.6, OpenAlea 0.8 and Capsis 4.2.1.
- Java (sun version) must be installed and in the system PATH.
- Python must be installed and in the system PATH.
- OpenAlea must be installed from https://openalea.gforge.inria.fr
- Capsis must be installed from https://capsis.cirad.fr/capsis/
How to use a Python/OpenAlea function from Java/Capsis
Use a python script for regeneration in a Capsis module
- The connection is done with Jepp (https://jepp.sourceforge.net/) (installed within Capsis)
- You should not have to set particular environment variables for a Capsis / Python connection
- A boolean in MaddInitialParameters switches between java / python regeneration
- MaddModel.processEvolution() calls the python script
Initialise the connection before the temporal loop
reg = new MaddRegeneration();
Call the python regeneration procedure at each iteration
reg.execute(newStand, treeIdDispenser);
The MaddRegeneration.java object is in the maddmodule.openalea package, with a matching MaddRegeneration.py script.
Each call to execute () calls the regeneration procedure in python. The python script uses the java methods addTree () and getStand () to actually add new young trees in the stand.
public class MaddRegeneration { private TicketDispenser idDispenser; private MaddStand stand; private Jep jep; public MaddRegeneration() throws Exception { try { jep = new Jep(false, CapsisSettings.getModelDir() + "/maddmodule/openalea"); jep.set("maddRegeneration", this); } catch(JepException e) { throw new Exception(e.toString()); } } public void execute(MaddStand stand, TicketDispenser idDispenser) throws Exception { this.stand = stand; this.idDispenser = idDispenser; try { jep.runScript(CapsisSettings.getModelDir() + "/maddmodule/openalea/MaddRegeneration.py"); } catch(JepException e) { e.printStackTrace(); throw new Exception(e.toString()); } } public void addTree(int age, double height, double dbh, double x, double y, double z) { MaddTree tree = new MaddTree(idDispenser.getNext(), stand, age, height, dbh, false, x, y, z, true, MaddStatus.LOW); stand.addTree(tree); } public TreeList getStand() {return stand;} }
The python regeneration script is called every year in the loop to add 5 trees with random coordinates in the stand.
This particular scrit uses an OpenAlea Composite node called 'spatial distribution' to calculate the coordinates. To use this node as a 'spdist' function, the OpenAlea PackageManager must be loaded. This load may be long and is done only once for the evolution process (see below in the code).
Then the script gets the x and y extension of the stand by calling a java accessor: getStand (). spdist is then used to calculate the coordinates. Finally, the java method addTree () is called for each tree to be added (5 times).
from openalea.core.alea import load_package_manager, function # load Package Manager try: if(pm is None): pass except: pm = load_package_manager() nf = pm['openalea.spatial']['spatial distribution'] spdist = function(nf) stand = maddRegeneration.getStand() minx = stand.getOrigin().x miny = stand.getOrigin().y maxx = stand.getWidth() + minx maxy = stand.getHeight() + miny # get list of point listx, listy = spdist(5, minx, maxx, miny, maxy) for x,y in zip(listx, listy): maddRegeneration.addTree(333, 1., 1., x, y, 0.)
How to use a Java/Capsis module from Python/OpenAlea
Example: Create an OpenAlea node to encapsulate a Capsis-MaddModule script: MaddScript1.
- The connection is done with Jpype (https://jpype.sourceforge.net/) (must be downloaded and installed)
- JAVA_HOME must be correctly set
- The OpenAlea Capsis package is located in capsis/etc/openalea
- It contains the
__wralea__.py
(nodes description)
# __wralea__.py __doc__ = """ Capsis nodes """ __revision__=" $Id " from openalea.core import * from openalea.core.pkgdict import protected __name__ = "capsis" __version__ = '0.0.1', __license__ = 'CECILL-C' __authors__ = 'S. Dufour-Kowalski, F. de Coligny' __institutes__ = 'INRA' __description__ = 'Capsis models' __url__ = 'https://capsis.cirad.fr' __all__ = ['maddmodule1', 'list2objs'] maddmodule1 = Factory(name='maddmodule1', description='MaddModule', category='forestry', nodemodule='maddmodule', nodeclass='maddmodule1', inputs = (dict(name='filename', interface=IFileStr, value=""), dict(name='nbyear', interface=IInt, value=10), ), outputs=(dict(name='stand', interface=ISequence),) ) list2objs = Factory(name='list2objs', description='MaddModule', category='forestry', nodemodule='maddmodule', nodeclass='list2objs', inputs = (dict(name='list', interface=ISequence), ), outputs=(dict(name='objs', interface=ISequence),) )
capsis/etc/openalea
also contains the python functions for the nodes inmaddmodule.py
- See the OpenAlea documentation
# maddmodule.py import os # import fake package to get the directory import path from jpype import * def maddmodule1(filename, nbyear): """ Run Capsis maddmodule script """ return run(filename, nbyear) def build_classpath(basedir): """ list jar in a directory """ res = "" for f in os.listdir(basedir): if(f.endswith(".jar")): res += basedir + os.sep + f + os.pathsep return res[:-1] def run(filename, nbyear): """ Execute the Capsis script @param filename: initial stand description @param nbyear: duration of the evolution """ # find capsis path with fake package path BASEDIR = os.path.dirname(str(path).split()[3][1:-9]) BASEDIR = os.path.normpath(BASEDIR + "/../../") # Start JVM : warning JAVA_HOME must be set if not isJVMStarted() : jarcp = build_classpath(BASEDIR + "/ext") startJVM(getDefaultJVMPath(), "-Djava.class.path="+BASEDIR+"/bin:"+BASEDIR+"/class/:" + jarcp) # Start capsis script script = JPackage ('maddmodule').myscripts.MaddScript1 s = script() s.run(filename, nbyear) stand = s.getResult().getScene() return stand_to_list(stand) def stand_to_list(stand): """ Convert a TreeList to a list [(age, dbh, height, x, y), (age, dbh, height, x, y), ...] """ ret = [] for t in stand.getTrees(): age = t.getAge() dbh = t.getDbh() h = t.getHeight() x = t.getX() y = t.getY() cbh = t.getCrownBaseHeight() cr = t.getCrownRadius() ret.append( (age, x, y, dbh, h, cbh, cr ) ) return ret def list2objs (l): """ Convert a dendro data list to a list of plottable objects """ from openalea.csv.csv import Obj # Create a list of obj to be plotted with PlantGL # ... return ret