Creating a new disease label
Labels and label values in STEM are used to hold the state of a population at any given time during a simulation. For instance, a compartmental SIR disease model has an SIRLabelValue that includes (among other things) the 3 EMF attributes s, i and r (of type EDouble).
It is possible to create custom EMF labels and label values to represent other more exotic models. For instance, in tuberculosis the population can be be thought of as being in 2 infected states, either actively infected or latently infected. To implement such a disease model we need to create a new label and label value having two infected compartments instead of one.
All disease model labels and label values must extend the StandardDiseaseModelLabel and StandardDiseaseModelLabelValue. By doing this, you inherit three mandatory attributes:
S: The susceptible population.
incidence: The number of new infectious cases in a given time period. You can sub-divide the incidence into particular incidences if a susceptible person can transition onto more than one I compartment, but they you need to aggregate the total incidence into this attribute.
diseaseDeaths. The cumulative number of disease deaths. As for incidence, you can sub-divide this into one attribute for each infected compartment. However, you need to aggregate the number into this attribute.
To create a new label and label value, in your (disease model) plugin (new or existing):
1. Create a new EMF class XYZLabel extending StandardDiseaseModelLabel
2. Create a new EMF class XYZLabelValue extending StandardDiseaseModelLabelValue. You will inherit the mandatory S, incidence and disease deaths attributes.
3. Add 4 EReference attributes to XYZLabel of type XYZLabelValue. The names must be deltaValue, tempValue, probeValue and errorScale. These values are needed to do the integration using Runge Kutta.
5. In XYZLabelValueImpl add the arithmetic methods:
5.1 DiseaseModelLabelValue set(IntegrationLabelValue value) Call super.set(…) and then set any local state variables from the input
5.2 DiseaseModelLabelValue add(IntegrationLabelValue value) Call super.add(…) and then add to any local state variables from the input
5.3 DiseaseModelLabelValue sub(IntegrationLabelValue value) Call super.sub(…) and then subtract from any local state variables from the input
5.4 DiseaseModelLabelValue scale(double scaleFactor) Call super.scale(…) and then scale any local state variables from the input
5.5 DiseaseModelLabelValue add(double addition) Call super.add(…) then add the scalar to any local state variables
5.6 DiseaseModelLabelValue abs() Call super.abs(…) and then set local state variables to their absolute values.
5.7 IntegrationLabelValue divide(IntegrationLabelValue d) Call super.divide(…) then divide any local state variables from the input
5.8 double max() Call super.max() and determine the maximum value of any state variables.
5.9 public void reset() Call super.reset() and reset any local state variables to their default values
6. In XYZLabelImpl, modify the constructor to initialize all the label values, i.e. call setCurrentValue(XYZFactory.eINSTANCE.createXYZLabelValue()), setNextValue(XYZFactory.eINSTANCE.createXYZLabelValue()), setTempValue(XYZFactory.eINSTANCE.createXYZLabelValue()), setProbeValue(XYZFactory.eINSTANCE.createXYZLabelValue()), setErrorScaleValue(XYZFactory.eINSTANCE.createXYZLabelValue()), setDeltaValue(XYZFactory.eINSTANCE.createXYZLabelValue())
7. In XYZLabelValueImpl, add the method "getPopulationCount" and call super.getPopulationCount() and then add to it any population from local state variables
8. For map views and time series views etc. to work, you need to determine how to calculate a relative value (between 0.0 and 1.0) for any of the compartment states in your XYZLabelValue. Do do this, you write an XYZRelativeValueProviderAdapterFactory, register the factory when STEM starts up and implement the code to:
8.1. Retrive the state variables (properties) to make available in the drop-down used to select the compartment to view in the map view. The method is called getProperties().
8.2. Implement the getRelativeValue(final EstructuralFeature feature) to calculate a relative value for a given feature in your XYZLabelValue class
8.3. Implement the getDenominator(final EstructuralFeature feature) to return the denominator (typically the total population count) for a given feature
One way to ensure that the factory your write is loaded at startup is to have it implement the IStartup interface and register an org.eclipse.ui.startup extension point in your plugin.xml. To see an example of how a factory might look like, see the ExperimentalRelativeValueProviderAdapterFactory.java class.