This documentation is for the Capsis modellers. It explains how to implement easily a new graph in Java for their own model.
Once a new Graph created from one of the examples below, compile it with 'ant compile', then when built successfully, declare it in capsis with 'capsis -se' (i.e. 'search extensions'). To configure a graph, right click on it > configure.
When everything is ok, add all files to svn, then commit.
Create a subclass of capsis.extension.dataextractor.DEDistribution in an “extension.dataextractor” package, then explicit the following:
This is a simple example:
package quergus.extension.dataextractor; import jeeb.lib.util.Translator; import quergus.model.QGModel; import quergus.model.QGTree; import capsis.extension.dataextractor.DEDistribution; /** * Trees energy distribution. * * @author F. de Coligny - April 2012 */ public class DEEnergyDistribution extends DEDistribution { static { Translator.addBundle("quergus.extension.dataextractor.DEEnergyDistribution"); } public static final String NAME = "DEEnergyDistribution"; public static final String DESCRIPTION = "DEEnergyDistribution.description"; public static final String AUTHOR = "F. de Coligny"; public static final String VERSION = "1.0"; public static boolean matchWith (Object referent) { return referent instanceof QGModel; } @Override protected String getXLabel() { return Translator.swap("DEEnergyDistribution.energy"); } @Override protected Number getValue(Object o) { return ((QGTree) o).getTreeLight().getEnergy(); } }
You must also provide translations for the following keys in a couple of files for english and french.
# quergus/extension/dataextractor/DEEnergyDistribution_en.properties DEEnergyDistribution = N / Energy classes DEEnergyDistribution.description = Distribution per energy classes DEEnergyDistribution.energy = Energy (MJ)
# quergus/extension/dataextractor/DEEnergyDistribution_fr.properties DEEnergyDistribution = N / Classes d'énergie DEEnergyDistribution.description = Distribution par classes d'énergie DEEnergyDistribution.energy = Energie (MJ)
Create a subclass of capsis.extension.dataextractor.DETimeY in an “extension.dataextractor” package, then explicit the following:
This is a simple example:
package lsfmgm.extension.dataextractor; import lsfmgm.model.LSFMModel; import lsfmgm.model.LSFMStand; import capsis.extension.dataextractor.DETimeY; import capsis.kernel.GModel; import capsis.kernel.GScene; /** * Species Diversity versus Date. * * @author Chris Shen of CAF, 21th, Nov, 2009 */ public class DETimeSpeciesDiversity extends DETimeY { static { Translator.addBundle("lsfmgm.extension.dataextractor.DETimeSpeciesDiversity"); } public static final String NAME = "DETimeSpeciesDiversity"; public static final String DESCRIPTION = "DETimeSpeciesDiversity.description"; public static final String AUTHOR = "Xiangdong Lei, Ma Wu, Chris Shen"; public static final String VERSION = "1.1"; static public boolean matchWith(Object referent) { if (!(referent instanceof LSFMModel)) {return false;} return true; } @Override protected Number getValue(GModel m, GScene stand, int date) { return ((LSFMStand) stand).getSpeciesDiversity(); // returns an int or a double } }
You must also provide translations for the following keys in a couple of files for english and french.
# lsfmgm/extension/dataextractor/DETimeSpeciesDiversity_en.properties DETimeSpeciesDiversity = SpeciesDiversity / Time DETimeSpeciesDiversity.yLabel = SpeciesDiversity DETimeSpeciesDiversity.description = SpeciesDiversity over time
# lsfmgm/extension/dataextractor/DETimeSpeciesDiversity_fr.properties DETimeSpeciesDiversity = Diversité des espèces / Temps DETimeSpeciesDiversity.yLabel = Diversité DETimeSpeciesDiversity.description = Diversité des espèces en fonction du temps
Create a subclass of capsis.extension.dataextractor.DETimeYs (with an 's') in an “extension.dataextractor” package, then explicit the following:
This is a simple example:
package woudyfor.extension.dataextractor; import java.util.Iterator; import java.util.List; import jeeb.lib.util.Translator; import woudyfor.model.WoudyModel; import woudyfor.model.WoudyScene; (...) import capsis.extension.dataextractor.DETimeYs; import capsis.kernel.GModel; import capsis.kernel.GScene; /** * A graph Number of seedlings over time * * @author Florian Delerue - March 2012 */ public class WoudyTimeSeedlingN extends DETimeYs { static { Translator.addBundle("woudyfor.extension.dataextractor.WoudyGraphs"); } public static final String NAME = "WoudyTimeSeedlingN"; public static final String DESCRIPTION = "WoudyTimeSeedlingN.description"; public static final String AUTHOR = "Florian Delerue"; public static final String VERSION = "1.0"; static public boolean matchWith(Object referent) { // compatible with WoudyModel only return referent instanceof WoudyModel; } @Override public String[] getYAxisVariableNames() { return new String[] {"mean", "max"}; // the names of the 2 variables } @Override protected Number getValue(GModel m, GScene scene, int date, int i) { // value for the 'i'th variable WoudyScene ws = (WoudyScene) scene; if (i <= 0) { return getMean (ws); } else { return getMax (ws); } } private double getMax (WoudyScene scene) { // calculate and return 'max' on the given scene (...) return max; } private double getMean (WoudyScene scene) { // calculate and return 'mean' on the given scene (...) return mean; } }
You must also provide translations for the following keys in a couple of files for english and french.
# woudyfor/extension/dataextractor/WoudyGraphs_en.properties WoudyTimeSeedlingN = Number of seedlings / Time WoudyTimeSeedlingN.description = Number of seedlings over time for non empty cells WoudyTimeSeedlingN.yLabel = N/m2
# woudyfor/extension/dataextractor/WoudyGraphs_fr.properties WoudyTimeSeedlingN = Nombre de plantules / Temps WoudyTimeSeedlingN.description = Nombre de plantules en fonction du temps pour les cellules occupées WoudyTimeSeedlingN.yLabel = N/m2
To set different colors for the curves, you may redefine the getColors () method and return a vector of colors with n = getCurves ().size () - 1 entries. The default graph color (the color on the matching step button in the project manager) can be guessed with getColor (). The example below returns the default color for the mean curve and the red color for the max curve.
/** * Returns a color per curve: getCurves ().size () - 1. */ public Vector getColors () { // fc-28.11.2013 changed DFCurves into DFColoredCurves, provided this default implementation // for getcolors () (no change). Subclasses can redefine this method to return a different // color for each curve Vector v = new Vector (); Color singleColor = getColor (); // see AbstractDataExtractor v.add (singleColor); // mean v.add (Color.RED); // max return v; }
It is possible to add options in the graphs by redefining the setConfigProperties () method. These options may be used to optionally remove some data series by adapting the code below.
All possible configuration possibilities are explained in this doc.
Note: for better result, you may provide translations in english and french for 'mean' and 'max' in the labels files.
@Override public void setConfigProperties() { addBooleanProperty("mean", true); addBooleanProperty("max", true); } @Override protected Number getValue(GModel m, GScene scene, int date, int i) { WoudyScene ws = (WoudyScene) scene; if (i <= 0) { return isSet ("mean") ? getMean (ws) : Double.NaN; } else { return isSet ("max") ? getMax (ws) : Double.NaN; } }
This is a simple example:
package heterofor.extension.dataextractor; import heterofor.model.HetModel; import heterofor.model.HetScene; import heterofor.model.HetTree; import jeeb.lib.util.Translator; import capsis.extension.dataextractor.DETimeYsTrees; import capsis.kernel.GModel; import capsis.kernel.GScene; /** * A graph 'biomass for 5 compartments' over time for a given list of trees. * * @author F. de Coligny, M. Jonard - November 2013 */ public class DETimeBiomass extends DETimeYsTrees { static { Translator.addBundle ("heterofor.extension.dataextractor.DELabels"); } public static final String NAME = "DETimeBiomass"; public static final String DESCRIPTION = "DETimeBiomass.description"; public static final String AUTHOR = "F. de Coligny, M. Jonard"; public static final String VERSION = "1.0"; static public boolean matchWith (Object referent) { // compatible with HetModel only return referent instanceof HetModel; } @Override public String[] getYAxisVariableNames () { // the names of the variables return new String[] {Translator.swap ("leafBiomass"), Translator.swap ("branchBiomass"), Translator.swap ("stemBiomass"), Translator.swap ("rootBiomass"), Translator.swap ("fineRootBiomass")}; } /** * Returns the value for the 'i'th variable of the tree 'treeId'. */ @Override protected Number getValue (GModel m, GScene scene, int treeId, int date, int i) { HetScene sc = (HetScene) scene; HetTree t = (HetTree) sc.getTree (treeId); if (i <= 0) { return t.getLeafBiomass (); } else if (i == 1) { return t.getBranchBiomass (); } else if (i == 2) { return t.getStemBiomass (); } else if (i == 3) { return t.getRootBiomass (); } else if (i == 4) { return t.getFineRootBiomass (); } else { return 0; } } }