Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

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:

  1. Variable
  2. 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.