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.

How to use a Python/OpenAlea function from Java/Capsis

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.)

How to use a Java/Capsis module from Python/OpenAlea

Example: Create an OpenAlea node to encapsulate a Capsis-MaddModule script: MaddScript1.

# __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),)
                   )
# 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
Screenshot