Table of Contents
How to write an export tool
An export tool (export) makes it possible to export a given step of a simulation history into a file with a given format.
From the given step, it is also possible to write information concerning the whole scenario from the root step to the given referent step.
Exports can be called from the Capsis user interface: Step contextual menu > Export > choose an export, choose an output file, validate. They also can be called from Capsis scripts to be run during a background simulation with this kind of syntax:
// Export a given simulation step to a fileName GenExport e = new GenExport (); e.initExport (model, step); e.save (fileName);
A simple example : the Genloader export
Reminder: an entry must be added in the etc/extension.list of Capsis otherwise the extension will not be found by the ExtensionManager.
... douglas.model.DouglasInventoryLoader=enabled ...
Note: this can be done by Capsis without editing the file, by using the 'search extensions' feature from the command line once the extension written:
capsis -se
Step by step detailled comments
The code of this export is presented in the commented blocks below. The complete code can be found at the bottom of this document in case you would like to copy it to make a new intervener.
package genloader.extension.ioformat; import genloader.model.GenModel; import genloader.model.GenStand; import genloader.model.GenTree; import java.util.Date; import java.util.Iterator; import java.util.Set; import java.util.TreeSet; import jeeb.lib.util.Import; import jeeb.lib.util.Log; import jeeb.lib.util.Record; import jeeb.lib.util.Translator; import capsis.kernel.GModel; import capsis.kernel.GScene; import capsis.util.GTreeIdComparator; import capsis.util.StandRecordSet;
The export is part of the Genloader module. This module just loads inventories to watch them in the Capsis viewers.
/** * GenExport exports a GenScene to a file. * * @author F. de Coligny - may 2011 */ public class GenExport extends StandRecordSet { // Extension properties static public String NAME = Translator.swap ("GenExport"); static public String AUTHOR = "F. de Coligny"; static public String VERSION = "1.0"; static public String DESCRIPTION = Translator.swap ("GenExport.description"); static { Translator.addBundle("genloader.extension.ioformat.GenExport"); } // A tree line in the file @Import static public class TreeLine extends Record { public TreeLine () { super (); } public TreeLine (String line) throws Exception { super (line); } // public String getSeparator () {return ";";} // to change default "\t" separator public int id; // unique in the scene public int age; // years public double x; public double y; public double z; public double dbh; // m. public double height; // cm. public double crownBaseHeight; // m. public double crownRadius; // m. public int stateCode; // can match with colors in viewers public char shapeCode; // 'c' cone, 'e' ellipse... public float transparency; // 0.0 (opaque) to 1.0 (transparent) }
The export extends StandRecordSet (needed for exports).
The exports need 4 administrative constants: NAME, AUTHOR, VERSION, DESCRIPTION. NAME and DESCRIPTION must go through the Translator.
The Translator is told to load a translation bundle for this class (the language was chosen by the user at Capsis launch time). These translation may be found in the required files GenExport_en.properties and GenExport_fr.properties.
Example for the english GenExport_en.properties file:
## GenExport labels - English GenExport = GenLoader Export GenExport.description = An export for the GenLoader module
The TreeLine inner class (such inner classes are optional) describes the format of a line in the output file, there will be one line per trees in the exported scene.
/** * Constructor */ public GenExport () { super (); // Do not write the standard header lines in the output file setHeaderEnabled (false); } /** * Extension dynamic compatibility mechanism. This matchWith method checks if the extension can * deal (i.e. is compatible) with the referent. */ static public boolean matchWith (Object referent) { try { if (!(referent instanceof GenModel)) { return false; } } catch (Exception e) { Log.println (Log.ERROR, "GenExport.matchWith ()", "Error in matchWith () (returned false)", e); return false; } return true; }
The constructor is very simple, it calls the superclass constructor then disables the Capsis standard headers (optional). This header is several lines heigh and may be not needed in some cases.
The matchWith () method is there for built-in compatibility check. It will tell it's compatible only with the GenModel (model class of the GenLoader module).
/** * Export: turns the given Scene into a collection of records * In script mode, save (fileName) must be called after. */ @Override public void createRecordSet (GScene s) throws Exception { GenStand scene = (GenStand) s; super.createRecordSet (scene); // deals with RecordSet's source // 1. Custom headers add (new CommentRecord ("Genloader scene export (GenExport) at "+new Date ())); add (new EmptyRecord ()); add (new CommentRecord ("Trees")); add (new FreeRecord ("Scene at date "+scene.getDate ()+" scene area(m2) "+scene.getArea ())); add (new EmptyRecord ()); add (new KeyRecord ("origin", ""+scene.getOrigin ())); add (new KeyRecord ("xSize", ""+scene.getXSize ())); add (new KeyRecord ("ySize", ""+scene.getYSize ())); // 2. TreeRecords add (new EmptyRecord ()); add (new CommentRecord ("Trees")); add (new CommentRecord ("id age x y z dbh height crownBaseHeight crownRadius stateCode shapeCode transparency")); add (new EmptyRecord ()); // Sort the trees on their ids Set sortedTrees = new TreeSet (new GTreeIdComparator ()); sortedTrees.addAll (scene.getTrees ()); for (Iterator i = sortedTrees.iterator (); i.hasNext ();) { GenTree t = (GenTree) i.next (); TreeLine r = new TreeLine (); r.id = t.getId (); r.age = t.getAge (); r.x = t.getX (); r.y = t.getY (); r.z = t.getZ (); r.dbh = t.getDbh (); r.height = t.getHeight (); r.crownBaseHeight = t.getCrownBaseHeight (); r.crownRadius = t.getCrownRadius (); r.stateCode = t.getStateCode (); r.shapeCode = t.getShapeCode (); r.transparency = t.getTransparency (); add (r); } }
The createRecordSet () method does the export job: it turns the given scene into a number of 'Records'.
These records may be instances of:
- CommentRecord: a record begining with the comment mark (default is '#') and containing a message
- FreeRecord: a record containing a String
- KeyRecord: a record with a key and a value:
key = value
- EmptyRecord: a blank line
- TreeLine: a record for each tree, prepared by setting all its properties
All these records are directly added in the export (which extends ArrayList), the order of insertion will be kept when they are written in the file later.
/** * Importation is not implemented here */ @Override public GScene load (GModel m) throws Exception { return null; }
The load () method is not used in this export (exports may also import).
The resulting file
The following file was built by running the GenExport on the root step of a Genloader simulation with the input simulation file:
capsis4/data/genloader/biomecanicseol.csv
# Genloader scene export (GenExport) at Mon May 30 17:11:56 CEST 2011 # Trees Scene at date 0 scene area(m2) 11968.356999282842 origin = (0,0,0) xSize = 109.3499984741211 ySize = 109.44999694824219 # Trees # id age x y z dbh height crownBaseHeight crownRadius stateCode shapeCode transparency 1 10 25.1299991607666 109.20999908447266 0.0 15.449999809265137 22.5 12.1 4.1 0 e 0.0 2 10 13.109999656677246 101.37999725341797 0.0 17.950000762939453 17.829999923706055 11.34 4.4 0 e 0.0 3 10 29.309999465942383 99.04000091552734 0.0 13.579999923706055 14.5 10.3 2.5 0 e 0.0 4 10 24.649999618530273 99.83000183105469 0.0 23.020000457763672 23.979999542236328 16.73 4.85 0 e 0.0 5 10 21.700000762939453 96.16999816894531 0.0 21.81999969482422 28.5 20.22 4.85 0 e 0.0 6 10 28.59000015258789 95.12999725341797 0.0 16.139999389648438 26.329999923706055 16.91 3.9 0 e 0.0 7 10 25.34000015258789 85.51000213623047 0.0 21.43000030517578 29.600000381469727 12.5 5.0 0 e 0.0 8 10 14.350000381469727 50.619998931884766 0.0 12.760000228881836 16.799999237060547 9.5 3.4 0 e 0.0 9 10 22.770000457763672 51.58000183105469 0.0 29.110000610351562 24.5 12.4 4.0 0 e 0.0 10 10 20.3799991607666 34.81999969482422 0.0 10.579999923706055 13.5 11.5 1.8 0 e 0.0 11 10 27.979999542236328 32.5 0.0 39.220001220703125 30.399999618530273 10.1 8.8 0 e 0.0 12 10 14.119999885559082 20.860000610351562 0.0 13.5 18.700000762939453 11.1 1.9 0 e 0.0 13 10 17.780000686645508 16.239999771118164 0.0 29.760000228881836 27.229999542236328 14.77 8.4 0 e 0.0 14 10 26.719999313354492 18.790000915527344 0.0 60.959999084472656 53.70000076293945 21.7 13.4 0 e 0.0 15 10 20.549999237060547 10.75 0.0 13.670000076293945 15.5 10.4 3.1 0 e 0.0 16 10 28.100000381469727 4.380000114440918 0.0 10.699999809265137 13.220000267028809 5.77 3.0 0 e 0.0 17 10 8.869999885559082 25.260000228881836 0.0 23.260000228881836 23.200000762939453 14.3 4.15 0 e 0.0 18 10 1.4900000095367432 65.9800033569336 0.0 81.08999633789062 31.0 21.7 9.7 0 e 0.0 19 10 2.5 102.0 0.0 11.520000457763672 17.09000015258789 12.02 2.85 0 e 0.0 20 10 0.44999998807907104 59.599998474121094 0.0 14.550000190734863 18.0 12.2 2.5 0 e 0.0 21 10 30.290000915527344 36.4900016784668 0.0 11.65999984741211 24.100000381469727 15.6 2.1 0 e 0.0 22 10 33.91999816894531 77.41999816894531 0.0 13.710000038146973 17.399999618530273 12.1 0.95 0 e 0.0 23 10 32.4900016784668 98.6500015258789 0.0 26.829999923706055 26.0 17.0 4.1 0 e 0.0 24 10 39.849998474121094 101.6500015258789 0.0 24.1200008392334 28.299999237060547 11.5 4.85 0 e 0.0 25 10 47.75 7.340000152587891 0.0 11.210000038146973 10.699999809265137 7.3 1.55 0 e 0.0 26 10 41.849998474121094 15.970000267028809 0.0 57.4900016784668 39.0 30.4 9.45 0 e 0.0 27 10 49.68000030517578 17.309999465942383 0.0 28.989999771118164 24.700000762939453 16.9 2.7 0 e 0.0 28 10 46.11000061035156 75.48999786376953 0.0 16.110000610351562 19.700000762939453 14.0 2.7 0 e 0.0 29 10 47.119998931884766 74.47000122070312 0.0 10.789999961853027 15.0 11.0 2.8 0 e 0.0 30 10 49.52000045776367 80.11000061035156 0.0 24.729999542236328 23.5 15.9 4.5 0 e 0.0 31 10 49.040000915527344 81.62999725341797 0.0 23.649999618530273 22.899999618530273 16.5 2.3 0 e 0.0 32 10 47.470001220703125 80.26000213623047 0.0 15.739999771118164 19.700000762939453 13.02 2.65 0 e 0.0 33 10 43.09000015258789 87.69000244140625 0.0 22.520000457763672 23.100000381469727 17.5 1.8 0 e 0.0 34 10 43.619998931884766 91.13999938964844 0.0 15.010000228881836 18.020000457763672 10.99 3.95 0 e 0.0 35 10 49.900001525878906 107.30000305175781 0.0 23.579999923706055 28.959999084472656 18.95 3.7 0 e 0.0 36 10 50.619998931884766 19.1200008392334 0.0 36.310001373291016 27.0 23.3 5.55 0 e 0.0 37 10 54.560001373291016 72.0 0.0 18.739999771118164 18.0 14.5 1.65 0 e 0.0 38 10 54.25 74.33000183105469 0.0 9.920000076293945 11.510000228881836 9.05 3.7 0 e 0.0 39 10 50.86000061035156 88.33000183105469 0.0 18.809999465942383 22.100000381469727 15.7 3.65 0 e 0.0 40 10 56.709999084472656 88.11000061035156 0.0 41.91999816894531 34.95000076293945 15.15 8.0 0 e 0.0 41 10 52.29999923706055 94.55999755859375 0.0 40.7400016784668 25.239999771118164 16.87 6.3 0 e 0.0 42 10 57.709999084472656 92.80999755859375 0.0 36.060001373291016 27.09000015258789 15.2 5.95 0 e 0.0 43 10 58.63999938964844 96.56999969482422 0.0 19.25 18.299999237060547 16.22 4.45 0 e 0.0 44 10 57.099998474121094 99.45999908447266 0.0 15.050000190734863 16.299999237060547 11.93 3.65 0 e 0.0 45 10 59.349998474121094 101.75 0.0 12.359999656677246 9.5 3.5 1.6 0 e 0.0 46 10 58.75 104.5999984741211 0.0 31.969999313354492 24.200000762939453 16.22 6.1 0 e 0.0 47 10 50.5 105.80000305175781 0.0 23.43000030517578 21.200000762939453 16.5 5.35 0 e 0.0 48 10 50.29999923706055 107.80000305175781 0.0 22.639999389648438 21.399999618530273 12.5 2.95 0 e 0.0 49 10 69.56999969482422 14.279999732971191 0.0 62.349998474121094 33.79999923706055 29.4 7.85 0 e 0.0 50 10 64.69999694824219 14.630000114440918 0.0 22.40999984741211 22.100000381469727 16.58 4.55 0 e 0.0 51 10 63.119998931884766 22.1200008392334 0.0 26.850000381469727 22.799999237060547 18.4 2.75 0 e 0.0 52 10 64.19000244140625 35.86000061035156 0.0 21.229999542236328 31.40999984741211 27.37 2.9 0 e 0.0 53 10 64.41000366210938 42.709999084472656 0.0 29.34000015258789 22.299999237060547 12.2 5.2 0 e 0.0 54 10 60.56999969482422 40.97999954223633 0.0 24.969999313354492 27.0 20.2 4.45 0 e 0.0 55 10 61.79999923706055 55.54999923706055 0.0 10.140000343322754 15.180000305175781 9.82 2.75 0 e 0.0 56 10 60.70000076293945 63.34000015258789 0.0 13.4399995803833 13.600000381469727 9.7 1.55 0 e 0.0 57 10 66.5199966430664 75.8499984741211 0.0 10.069999694824219 15.319999694824219 9.71 2.75 0 e 0.0 58 10 64.66999816894531 79.31999969482422 0.0 16.700000762939453 20.420000076293945 14.81 3.9 0 e 0.0 59 10 69.52999877929688 83.44999694824219 0.0 28.700000762939453 28.799999237060547 24.3 4.9 0 e 0.0 60 10 76.61000061035156 2.369999885559082 0.0 13.140000343322754 18.68000030517578 11.52 3.35 0 e 0.0 61 10 76.80999755859375 35.31999969482422 0.0 45.099998474121094 36.5 21.92 6.95 0 e 0.0 62 10 71.6500015258789 39.63999938964844 0.0 59.38999938964844 39.75 30.07 5.9 0 e 0.0 63 10 76.72000122070312 53.95000076293945 0.0 13.6899995803833 17.0 10.3 2.3 0 e 0.0 64 10 73.91999816894531 53.68000030517578 0.0 12.279999732971191 18.260000228881836 12.43 1.95 0 e 0.0 65 10 76.79000091552734 62.220001220703125 0.0 11.649999618530273 14.029999732971191 9.78 1.65 0 e 0.0 66 10 73.80000305175781 70.30000305175781 0.0 17.979999542236328 21.0 11.0 2.6 0 e 0.0 67 10 76.01000213623047 84.0199966430664 0.0 22.239999771118164 18.899999618530273 14.5 4.1 0 e 0.0 68 10 85.54000091552734 15.40999984741211 0.0 56.36000061035156 36.29999923706055 24.39 7.9 0 e 0.0 69 10 83.41000366210938 15.979999542236328 0.0 35.5099983215332 26.219999313354492 18.47 8.2 0 e 0.0 70 10 85.0199966430664 25.34000015258789 0.0 16.540000915527344 17.899999618530273 14.2 3.3 0 e 0.0 71 10 83.1500015258789 36.08000183105469 0.0 47.290000915527344 33.0 28.5 9.8 0 e 0.0 72 10 84.51000213623047 48.369998931884766 0.0 9.859999656677246 11.800000190734863 7.4 1.5 0 e 0.0 73 10 85.7699966430664 63.95000076293945 0.0 13.069999694824219 19.40999984741211 15.76 3.15 0 e 0.0 74 10 88.5 64.0999984741211 0.0 15.989999771118164 19.700000762939453 13.2 3.05 0 e 0.0 75 10 95.30999755859375 24.0 0.0 82.70999908447266 44.0 30.0 9.4 0 e 0.0 76 10 93.16000366210938 37.040000915527344 0.0 20.860000610351562 25.270000457763672 17.64 3.0 0 e 0.0 77 10 91.26000213623047 44.400001525878906 0.0 22.739999771118164 20.75 7.23 2.5 0 e 0.0 78 10 92.9800033569336 47.36000061035156 0.0 37.65999984741211 29.399999618530273 23.3 3.45 0 e 0.0 79 10 94.0199966430664 50.369998931884766 0.0 47.56999969482422 29.100000381469727 18.58 15.05 0 e 0.0 80 10 90.20999908447266 61.650001525878906 0.0 15.229999542236328 22.600000381469727 17.0 3.3 0 e 0.0 81 10 109.19999694824219 5.5 0.0 78.80999755859375 32.599998474121094 24.0 15.1 0 e 0.0 82 10 105.44999694824219 4.849999904632568 0.0 17.459999084472656 22.200000762939453 14.4 3.0 0 e 0.0 83 10 100.44999694824219 2.8499999046325684 0.0 11.829999923706055 10.399999618530273 5.2 7.45 0 e 0.0 84 10 106.0 19.450000762939453 0.0 84.88999938964844 40.5 30.0 11.6 0 e 0.0 85 10 101.5 34.75 0.0 75.0999984741211 33.29999923706055 20.0 9.8 0 e 0.0 86 10 104.80000305175781 38.849998474121094 0.0 37.349998474121094 26.5 14.2 9.4 0 e 0.0 87 10 109.0999984741211 47.20000076293945 0.0 10.119999885559082 12.300000190734863 7.5 0.7 0 e 0.0 88 10 103.44999694824219 54.04999923706055 0.0 12.470000267028809 15.899999618530273 12.2 4.1 0 e 0.0 89 10 108.94999694824219 59.45000076293945 0.0 9.800000190734863 15.100000381469727 6.2 1.15 0 e 0.0 90 10 109.3499984741211 64.19999694824219 0.0 15.0600004196167 18.700000762939453 15.5 4.5 0 e 0.0 91 10 100.1500015258789 109.44999694824219 0.0 10.470000267028809 12.800000190734863 7.3 1.6 0 e 0.0 92 10 108.0999984741211 105.9000015258789 0.0 93.30000305175781 35.5 23.6 12.65 0 e 0.0
The complete code of the GenExport example
package genloader.extension.ioformat; import genloader.model.GenModel; import genloader.model.GenStand; import genloader.model.GenTree; import java.util.Date; import java.util.Iterator; import java.util.Set; import java.util.TreeSet; import jeeb.lib.util.Import; import jeeb.lib.util.Log; import jeeb.lib.util.Record; import jeeb.lib.util.Translator; import capsis.kernel.GModel; import capsis.kernel.GScene; import capsis.util.GTreeIdComparator; import capsis.util.StandRecordSet; /** * GenExport exports a GenScene to a file. * * @author F. de Coligny - may 2011 */ public class GenExport extends StandRecordSet { // Extension properties static public String NAME = Translator.swap ("GenExport"); static public String AUTHOR = "F. de Coligny"; static public String VERSION = "1.0"; static public String DESCRIPTION = Translator.swap ("GenExport.description"); static { Translator.addBundle("genloader.extension.ioformat.GenExport"); } // A tree line in the file @Import static public class TreeLine extends Record { public TreeLine () { super (); } public TreeLine (String line) throws Exception { super (line); } // public String getSeparator () {return ";";} // to change default "\t" separator public int id; // unique in the scene public int age; // years public double x; public double y; public double z; public double dbh; // m. public double height; // cm. public double crownBaseHeight; // m. public double crownRadius; // m. public int stateCode; // can match with colors in viewers public char shapeCode; // 'c' cone, 'e' ellipse... public float transparency; // 0.0 (opaque) to 1.0 (transparent) } /** * Constructor */ public GenExport () { super (); // Do not write the standard header lines in the output file setHeaderEnabled (false); } /** * Extension dynamic compatibility mechanism. This matchWith method checks if the extension can * deal (i.e. is compatible) with the referent. */ static public boolean matchWith (Object referent) { try { if (!(referent instanceof GenModel)) { return false; } } catch (Exception e) { Log.println (Log.ERROR, "GenExport.matchWith ()", "Error in matchWith () (returned false)", e); return false; } return true; } /** * Export: turns the given Scene into a collection of records * In script mode, save (fileName) must be called after. */ @Override public void createRecordSet (GScene s) throws Exception { GenStand scene = (GenStand) s; super.createRecordSet (scene); // deals with RecordSet's source // 1. Custom headers add (new CommentRecord ("Genloader scene export (GenExport) at "+new Date ())); add (new EmptyRecord ()); add (new CommentRecord ("Trees")); add (new FreeRecord ("Scene at date "+scene.getDate ()+" scene area(m2) "+scene.getArea ())); add (new EmptyRecord ()); add (new KeyRecord ("origin", ""+scene.getOrigin ())); add (new KeyRecord ("xSize", ""+scene.getXSize ())); add (new KeyRecord ("ySize", ""+scene.getYSize ())); // 2. TreeRecords add (new EmptyRecord ()); add (new CommentRecord ("Trees")); add (new CommentRecord ("id age x y z dbh height crownBaseHeight crownRadius stateCode shapeCode transparency")); add (new EmptyRecord ()); // Sort the trees on their ids Set sortedTrees = new TreeSet (new GTreeIdComparator ()); sortedTrees.addAll (scene.getTrees ()); for (Iterator i = sortedTrees.iterator (); i.hasNext ();) { GenTree t = (GenTree) i.next (); TreeLine r = new TreeLine (); r.id = t.getId (); r.age = t.getAge (); r.x = t.getX (); r.y = t.getY (); r.z = t.getZ (); r.dbh = t.getDbh (); r.height = t.getHeight (); r.crownBaseHeight = t.getCrownBaseHeight (); r.crownRadius = t.getCrownRadius (); r.stateCode = t.getStateCode (); r.shapeCode = t.getShapeCode (); r.transparency = t.getTransparency (); add (r); } } /** * Importation is not implemented here */ @Override public GScene load (GModel m) throws Exception { return null; } }