Table of Contents

Graphs configuration properties

See How to add a graph easily to create a graph. This documentation deals about the configuration of graphs, with configuration properties.

What is a configuration property

To analyse a simulation under Capsis, it is possible to open graphs. The graphs compatible with the current simulation are available in the lateral Selector of Capsis' main frame. Double clicking on the name of a graph opens it, synchronised on the current simulation step.

The Capsis graphs accept several data series from different simulation steps. To add a data series from another step, click on the step (becomes 'current'), then right click on the graph > Add <name of the current step> (or Ctrl+click on the graph for a shortcut).

A graph with 2 data series coming from 2 different steps

These graphs are often configurable. To open the configuration dialog, right click on the graph > Configure (or double click on the graph for a shortcut).

The first tab in the configuration dialog is for common configuration. This means the changes in this panel will be applied to all the data series in the graph. E.g. if 'Per hectare' is chosen, all the data series will be recalculated per hectare.

On the individual tab, the user may configure the data series separately. On this example, 2 data series coming from the same simulation step have been added (Ctrl+Click on the graph). These 2 data series can be configured separately.

Configuring 2 distinct data series from the same simulation step in the graph with the Individual configuration tab

Note: the third tab is proposed to configure the renderer (showing the data).

See below for an explanation of the various available configuration properties.

The setConfigProperties () method

The Capsis graphs are internally based on data extractors, they explore the simulation steps to build data series to be rendered in the user interface.

A data extractor has a name, e.g. 'Basal area / Time', it produces one or several data series relative to a referent simulation step (can be all steps from the root step to this referent step to check the evolution). One or several data extractors are grouped and displayed in a single graph (a data renderer). The data renderers can be switched to have the data series shown in an histogram, in a table, etc.

New data extractors can be created in Capsis by following the related docs. In a data extractor, the configuration properties must be declared in the setConfigProperties () method.

/**
 * This method is called by superclass DataExtractor.
 */
public void setConfigProperties() {
 
	// Choose configuration properties
	addConfigProperty(PaleoDataExtractor.TREE_GROUP);
	addConfigProperty(PaleoDataExtractor.I_TREE_GROUP);
	addConfigProperty(PaleoDataExtractor.STATUS);
 
	addDoubleProperty("classWidthInM", 5d);
	addDoubleProperty("minThresholdInM", 0d);
 
	addBooleanProperty("perHectare");
	addBooleanProperty("displayClassNames", false);
	addBooleanProperty("roundN");
 
	addBooleanProperty("centerClasses");
}

Common properties

Boolean property

A boolean property can be added with addBooleanProperties (propertyName, defaultValue);

Note: a translation is expected in french/english in a pair of translation files (ending with _fr and _en.properties). Here, we consider perHectare is translated into Per hectare in the english file. These translations are used when preparing the widgets on the user interface.

The user can change the value by clicking on the check box. If other opened graphs or other data series in the same graphs have the same option, the user can propagate his choice to them by clicking on the propagation button on the right before validating the dialog (here, all the data series in all opened graphs would immediately go per hectare).

The value of the property can be checked with isSet(propertyName). It is checked in the methods responsible of the data series creation (or update if the configuration changed). The standard method for this in the data extractors is called doExtraction (), generally containing a loop to gather the data and store them in lists. Some other data extractors rely on a method called getValue(…) (see the doc cited at the top of this page).

E.g. in DEHeightClassNN / Height classes

// in setConfigProperties ()...
	addBooleanProperty("perHectare");
 
// in doExtraction ()...
 
	// per Ha computation
	double coefHa = 1;
	if (isSet("perHectare"))
		coefHa = 10000 / getSceneArea(step.getScene());
 
	// Then multiply all values of the data series by coefHa...

Combo property

A combo property can be added with addComboProperty (propertyName, listOfStrings);

The property name and all options are to be translated in the pair of translation files for french/english.

The user can choose the value for each combo property by using the matching combo box widget.

To get the selected value in the extractor code (doExtraction(), getValue()), use getComboProperty(propertyName)

Example code: DEIntertypeSpatial : Intertype L12(r ) function

// in setConfigProperties ()...
 
LinkedList c = new LinkedList(grouperNames);
addComboProperty("Type 1", c);
LinkedList c2 = new LinkedList(grouperNames);
addComboProperty("Type 2", c2);
 
// in doExtraction ()...
 
Grouper g1 = gm.getGrouper(getComboProperty("Type 1"));

Radio property

A radio property can be added in a graph with addRadioProperty (String[] candidateOptions);

All the option names are to be translated in the pair of translation files for french/english.

To get the user choice in the extractor source code, use the same method than for a boolean property : isSet(optionName), it will return true for the selected option and false for the others.

E.g. in the GymnoTimeWoodTypeBasal area / Time / Wood Type class:

// in setConfigProperties ()...
 
addRadioProperty(new String[] { "normal", "hectare", "percent" });
(...)
 
// lower, in doExtraction ()...
 
total = (juvenileSum + matureSum + sapSum) * coef;
if (isSet("percent"))
	coef = 1d / total;
(...)

Int property

An int property can be added in a graph with addIntProperty(propertyName, defaultValue);

The property name is to be translated in a pair of french/english files.

To get the value chosen by the user in the source code of the graph, use the method getIntProperty(propertyName)

E.g. in DETimeClassNN / Age classes

// in setConfigProperties ()...
 
addIntProperty("DEAgeClassN.classWidthInYears", 5);
 
// in doExtraction...
 
int classWidth = getIntProperty("DEAgeClassN.classWidthInYears");

Double property

A double property is added in a graph with addDoubleProperty(propertyName, defaultValue);

The property name is to be translated in a pair of french/english files.

To get the value chosen by the user, use the method getDoubleValue (propertyName)

E.g. in DEDbhClassNN / Diameter classes

// in setConfigProperties ()...
 
addDoubleProperty("classWidthInCm", 5d);
 
// in doExtraction ()...
 
double classWidth = getDoubleProperty("classWidthInCm");

String property

A string property can be added in a graph with addStringProperty(propertyName, defaultValue);

The property name is to be translated in a pair of french/english files.

To get the String chosen by the user, use the method getStringProperty(propertyName);

E.g. in ModisVolumeTableVolume and income

// in setConfigProperties () (the string here is an encoded suite of numbers)...
 
addStringProperty("limits", "45 (35) 15 (20) 12 (14) 8 (7) 5");
 
// optional: in additionalChecks (): get the string, check the format 
// is correct, else tell the user with MessageDialog and return false...
 
/**
 * Called by multi configuration panel on Ok, just after checksAreOk () (dealing
 * with general checks), here we can see it the user limits are in an expected form.
 */
@Override
public boolean additionalChecks() {
 
	// Checking encoded limits
	String encodedLimits = getStringProperty("limits");
 
	try {
		// The method below throws an exception if trouble
		ModisVolumeAndIncomeInterpretor.decodeLimitsProperty(encodedLimits);
 
	} catch (Exception e) {
		MessageDialog.print(this, e.getMessage());
		return false;
	}
 
	return true;
}
 
// in doExtraction (), get the property and use it to build the data series...
 
String encodedLimits = getStringProperty("limits");
(...)
makeTable("Living trees", stand.getTrees(), mp, encodedLimits);

Set property

A set property can be added in a graph with addSetProperty(propertyName, possibleValues, selectedValues);

Note: we use 'set' instead of 'list' because the sets in Java do not contain duplicates and this is what is expected here, i.e. the possible values can not contain the same option twice.

The property name and all option names are to be translated in a pair of french/english files.

To get the set of selected options chosen by the user, use getSetProperty(propertyName);

E.g. in DEAlleleFrequencies2Genetics: Allele frequency / Locus (2018)

// in setConfigProperties ()...
 
// Which loci do we want to see (here, all the possible values are selected)
addSetProperty("DEAlleleFrequencies2.locusNames", possibleValues, possibleValues);
 
// optional, if the property possible values must be updated, e.g. because 
// user chose to restrict to a group...
 
/**
 * Called when a group is set or changed.
 */
public void grouperChanged(String grouperName) { // cp - 30.11.2004
 
	(...)
	// Changing groups: there may be two species in the scene, update
	// the locusNames
	String[] locusNames = findLocusNames(gee);
	updateSetProperty("DEAlleleFrequencies2.locusNames", locusNames);
	(...)
}
 
// in doExtraction ()...
 
// Get the user chosen loci
List loci = getSetProperty("DEAlleleFrequencies2.locusNames");

Common or Individual properties

Group property

The grouping system of Capsis can be activated in the graphs to restrict them to some individuals belonging to a given group.

If activated at the common level, all the data series in the graph will be restricted to the given group. If tuned at the individual level, data series based on different groups will become comparable in the same graph.

A group property can be added with addGroupProperty (type, target);

Note: it is possible to activate the group feature at both common and individual levels. If user selects both, he will be told that one only can be chosen at at time.

The user can activate the feature, choose the group and optionaly choose to use the complementary. He also can create a new group on the fly to be added to the current list of available groups (then saved and restored).

To apply the group in doExtraction (), use doFilter (inputList), this will return all the inputList if no group has been set by the user, else the individuals in inputList which are part of the group.

E.g. DETimeGBasal area / Time

// in setConfigProperties ()...
 
// group multiconfiguration (common)
// note: addGroupProperty(TreeList.GROUP_ALIVE_TREE, COMMON) should be preferred
addConfigProperty(PaleoDataExtractor.TREE_GROUP);
 
// group individual configuration
// note: addGroupProperty(TreeList.GROUP_ALIVE_TREE, INDIVIDUAL) should be preferred
addConfigProperty(PaleoDataExtractor.I_TREE_GROUP);	
 
 
// in doExtraction ()...
 
(...)
Collection trees = doFilter(stand);
value = ((GProvider) methodProvider).getG(stand, trees) * coefHa;
(...)

Specific property

It is possible to add a specific (i.e. customized) configuration property.

In EcoAF (agroforestry), the scene contains several parcels. The parcels are laid out with tree lines (several species) by the user during the initialisation stage. Afterwards, it is possible to open graphs to check the resulting scene, e.g. the diameter distributions. These diameter distibutions can be configured with a configuration property specific to EcoAF.

E.g. to show a specific parcel, it is possible in the Individual tab to open the EcoAF configuration property to restrict the graph to a given parcel.

An Ecoaf specific chart, diameter classes per position label, all parcels Restrict the EcoAF graph to a given parcel

A specific property can be added in a graph with:

Where

All the labels to be shown on the user interface are to be translated in a pair of french/english files.

To get the result of the user configuration, use

These two methods return the DESpecificProperty object sent at the time of addSpecificProperty () call, the internal configuration can be used in doExtraction () or getValue () to tune the data series extraction (in this example, keep only data for Parcel 2).

In this example, the filter is a pair of classes: EcoafFilter (the filter extending DESpecificProperty) and its configuration dialog for user interaction, EcoafFilterDialog.

E.g. EcoafDbhClassNN / Dbh classes (Ecoaf)

// in setConfigProperties ()...
 
@Override
public void setConfigProperties() {
 
	EcoafScene scene = (EcoafScene) step.getScene();
 
	String[] graphType = { "EcoafDbhClassN.perSpecies", "EcoafDbhClassN.perPosition" };
	addRadioProperty(graphType);
 
	addDoubleProperty("EcoafDbhClassN.minThreshold", 0);
	addDoubleProperty("EcoafDbhClassN.classWidth", 10);
 
//	addSpecificProperty("Shared.ecoafFilter", new EcoafFilter()); // common configuration
 
	// We use the individual configuration level, if several distributions in the graph, 
	// it will be possible to configure them separately, e.g. on different parcels
	addSpecificProperty("Shared.ecoafFilter", this, new EcoafFilter()); // individual configuration
 
}
 
// in doExtraction ()...
 
	(...)
	EcoafFilter ecoafFilter = (EcoafFilter) getSpecificProperty("Shared.ecoafFilter", this);
 
	// The extractor may have been synchronized on another simulation step, the
	// filters must be updated
	ecoafFilter.update(scene);
 
	List<EcoafTree> trees = ecoafFilter.getSelectedTrees(scene);
	(...)

Individual properties

Restrict to a given list of individuals

If the connected model manages individuals, it is possible to activate the TREE_IDS configuration property.

To activate it, use addConfigProperty(PaleoDataExtractor.TREE_IDS);

To get the selected individual ids (generally tree ids), use getTreeIds()

E.g. in DETimeHHeight / Time

Status property

This configuration property is compatible only with the TreeList class. This class is a superclass for many Capsis modules managing trees as individuals in their scene object. TreeList proposes a feature to keep individual which are removed from the alive tree list: they can be put in a list under a chosen status. Standard status are “dead” and “cut”. Other status may be used in some modules to keep track of disappearing trees, they are generally managed in the model processEvolutionLoop ().

If status can be found, a list of the possible values are proposed to the user who can choose one or several to be considered and trees with other status will be ignored in the graph.

The status config property can be activated with addConfigProperty(PaleoDataExtractor.STATUS);

To get the result, use the same method than for the groups: doFilter (inputList)

Configuration properties disabling

It may be needed to sometimes disable a property added in setConfigProperties (), it can be done with setPropertyEnabled (propertyName, booleanValue) at the end of setConfigProperties () or in init ().

E.g. DETimeDbhDiameter / Time is a standard extractor compatible with many models dealing with a list of trees having a dbh. Some of them have additional features and other data can sometimes be plotted in the graph along with the dbh evolution over time.

To see what features can be added, the methodProvider of the module is asked: 'can you return Dg ?', 'can you return Ddom ?'…

The non available properties will be set disabled after their declaration and the matching checkBoxes will be shown desactivated.

// in setConfigProperties ()...
 
public void setConfigProperties() {
 
	checkMethodProvider(step.getProject().getModel().getMethodProvider());
 
	// Choose configuration properties
	addConfigProperty(PaleoDataExtractor.TREE_IDS);
 
	addBooleanProperty("showDg");
	addBooleanProperty("showDdom");
	addBooleanProperty("showDamapsim");
	addBooleanProperty("showDgamapsim");
	addBooleanProperty("showDm");
	addBooleanProperty("showDmedian");
	addBooleanProperty("showDbhStandardDeviation");
	addBooleanProperty("showDmin");
	addBooleanProperty("showDmax");
	addBooleanProperty("incrementInsteadOfValue"); // TL - december 2017
	addBooleanProperty("incrementPerYear"); // PhD 2009-04-16
 
	// According to module capabiblities, disable some configProperties
	setPropertyEnabled("showDg", availableDg);
	setPropertyEnabled("showDdom", availableDdom);
	setPropertyEnabled("showDamapsim", availableDamapsim);
	setPropertyEnabled("showDgamapsim", availableDgamapsim);
	setPropertyEnabled("showDm", availableDm);
	setPropertyEnabled("showDmedian", availableDmedian);
	setPropertyEnabled("showDbhStandardDeviation", availableDbhStandardDeviation);
	setPropertyEnabled("showDmin", availableDmin);
	setPropertyEnabled("showDmax", availableDmax);
	setPropertyEnabled("incrementInsteadOfValue", true); // TL-december 2017
	setPropertyEnabled("incrementPerYear", true); // PhD 2009-04-16
 
}

Checking the user entries

Sometimes, the user entry does not need to be checked because an error is not possible, e.g. clicking on a checkBox, choosing an option in a comboBox. But sometimes, the user is expected to enter a certain type of answer (e.g. in a textField) and a check is needed to tell him if a correction is needed.

Two levels of checks are provided and called when user validates the config panel:

The checksAreOk () method is specific to each type of config property, it is responsible for checking types. For example, if a textField is expected to contain an integer, the check will be done in this method. This method is proposed in AbstractConfigurationProperty, it is abstract and must be redefined in all subclasses.

When no type check is needed, it returns true directly (e.g. BooleanPropertyManager / checkBox).

When needed, it runs the check and if the check fails, it tells the user with MessageDialog and returns false. The user will have to change its entry to comply to the expected type or format.

E.g. in IntPropertyManager, the checksAreOk () method below checks all the intProperties textFields found in the extractor (if any was added in setConfigProperties ()). These are only common properties. In case of trouble, a message is sent to the user and false is returned.

@Override
public boolean checksAreOk() {
 
	// Check intProperties type (must be int)
	Iterator keys = intPropertiesTextFields.keySet().iterator();
	Iterator values = intPropertiesTextFields.values().iterator();
	while (keys.hasNext() && values.hasNext()) {
		String propertyName = (String) keys.next();
		JTextField f = (JTextField) values.next();
		if (extractor.isIndividualProperty(propertyName))
			continue;
		String value = f.getText();
		try {
			new Integer(value);
		} catch (Exception e) {
			// Trouble, tell user and return false
			MessageDialog.print(this, Translator.swap(propertyName) 
			+ " " + Translator.swap("DataExtractor.mustBeAnInteger"));
			return false;
		}
	}
	return true;
}

The second level of checks () can be run in the additionalChecks () of the ConfigurableDataExtractor. This method is called after all the checkAreOk () methods were called and at this time it is possible to use all the methods to get the user choices like getIntProperty (propertyName), etc.

Here, it is possible to check if the various config properties are compatible together. E.g. if the user has asked for a min and a max value, a check than min if strictly lower than max should be run and the user told if this is not the case.

A default implementation of additionalChecks () is provided in ConfigurableExtractor, as these checks are less frequent, it returns true. It is possible to override if needed.

Layout options

By default, the configuration properties are presented to the user in the configuration panel grouped type by type: group properties, boolean properties, etc.

An option makes it possible to keep the order they are declared in setConfigProperties (). After having declared the properties, just add setPropertyDeclarationOrderKept()

Please note some properties will not be concerned by this option, e.g. the group features if activated will always displayed at the top of the panel.