Tested under Linux Ubuntu 9.10 with java 1.6.x, python 2.6, OpenAlea 0.8 and Capsis 4.2.1.
Use a python script for regeneration in a Capsis module
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.)
Example: Create an OpenAlea node to encapsulate a Capsis-MaddModule script: MaddScript1.
__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 in maddmodule.py
# 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