How to add a custom transformation to my FEWS system?
Adding a custom transformation involves several steps which will be explained in detail in the upcoming section:
...
In our example the output is calculated from the input values at the same time step. Therefore we define the input time series as Variable.
The output is marked by the annotation @Output
The output can be:
- Variable
- TimeSeriesArray
In our example the output (just as the input) defined as a Variable
Code Block |
---|
@Output
Variable output = null;
|
Previously it was explained that the options are injected during runtime in the correction factor fields. Something similar is done for the input time series.
If the transformation, for example, is supposed to run for a period of a day and the input and output time series are both hourly time series than this
calculation must be executed 24 times. In the case that the output time series is defined as a Variable than the FEWS transformation framework will execute the
calculate() method in the transformation 24 times. One time for each time step in the output period. After each execution the calculated output value, which should be
stored in the output Variable in the value field is read by the framework and stored in the database.
The values of the input time series are assigned to the input1 and input2 fields prior to invoking the calculate() method.
When the output is defined as TimeSeriesArray than the calculate() method will be only called once. Prior to executing the method the entire input time series is injected
in the input (Note than when the output is defined as a TimeSeriesArray, the input should also be defined as a TimSeriesArray). The example code we are using, could for example also
be writting the input and output defined as a TimeSeriesArray.
The example code is given below.
Code Block |
---|
package example; import nl.wldelft.fews.openapi.transformationmodule.Calculation; import nl.wldelft.fews.openapi.transformationmodule.Input; import nl.wldelft.fews.openapi.transformationmodule.Output; import nl.wldelft.util.timeseries.TimeSeriesArray; import org.apache.log4j.Logger; public class Example2 implements Calculation { private static final Logger log = Logger.getLogger(Example1.class.getName()); @Input private float option1; @Input private float option2; @Input TimeSeriesArray input1 = null; @Input TimeSeriesArray input2 = null; @Output VariableTimeSeriesArray output = null; @Override public void calculate() throws Exception { for (int i = 0; i < output.size(); i++) { long time = output.getTime(i); int index1 = input1.indexOfTime(time); if (index1 == -1) continue; float value1 = input1.getValue(index1); int index2 = input2.indexOfTime(time); if (index2 == -1) continue; float value2 = input2.getValue(index2); if (Float.isNaN(value1) || Float.isNaN(value2)) return; log.info("Input is " + value1 + " and " + value2); float outputValue = (value1 * option1 + value2 * option2) / 2; log.info("Output is " + outputValue); output.setValue(i, outputValue); } } } |
The main difference between the first and the second example is that in the second example the code needs
to have a for loop to calculate the output value for each time step available in the output time series.