You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 2 Next »

  • 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:

  1. writing the code for the custom tranformation.
  2. configuring the custom tranformation,

How to write a custom transformation?

First step is to write the actual code for the tranformation. Running and debugging the actual transformation can be done by writing unit tests.

Lets say we want to write a simple transformation that calculates the output value by using the following formula:

output = input1 x correctionFactor1 + input2 x correctionFactor2

The code needed for such a transformation would be quite basic and is given below:

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.Variable;
import org.apache.log4j.Logger;

public class Example1 implements Calculation {
    private static final Logger log = Logger.getLogger(Example1.class.getName());

    @Input
    float option1;

    @Input
    float option2;

    @Input
    Variable input1 = null;

    @Input
    Variable input2 = null;

    @Output
    Variable output = null;

    @Override
    public void calculate() throws Exception {
        if (Float.isNaN(input1.value) || Float.isNaN(input2.value)) return;
        log.info("Input is " + input1.value + " and " + input2.value);
        output.value = (input1.value * option1 + input2.value * option2) / 2;
        log.info("Output is " + output.value);
    }
}

Now the code above will explained step by step to understand the details. First note that tranformation implements the interface Calculation.

The interface Calculation has one method void calculate().

package nl.wldelft.fews.openapi.transformationmodule;

import nl.wldelft.util.Initializable;
import nl.wldelft.util.TimeZeroConsumer;

public interface Calculation extends Function {

    /**
     * This method is called by the framework to do the actual calculations.
     * The implementing class should get the input from its InputVariable
     * fields and put the calculation output in its OutputVariable fields.
     * The framework will initialize the InputVariable and OutputVariable
     * fields and set the input values in the InputVariables before calling
     * this method and get the output values out of the OutputVariables
     * afterwards.
     *
     * @throws Exception
     */
    void calculate() throws Exception;
}

The method calculate will contain the actual code for the transformation. The FEWS Transformation framework will automaticly invoke this method.

Once the workflow containing the custom transformation is executed. The java code in the calculate method is self explaining will not be explained in more detail here.

Next step is to explain the correctionfactors and the input values used in the calculate-method.

They are both defined as fields in the java-class.

@Input
float option1;

@Input
float option2;

@Input
Variable input1 = null;

@Input
Variable input2 = null;

The fields option1 and option2 however dont have any values assigned! How can they have a value during runtime?
The answer is that the FEWS Transformation will inject the values at runtime in these variables. The actual values
are described in the configuration. In the upcoming section, the configuration will be explained in detail.

The input timeseries are defined as input1 and input2. They are marked as being input timeseries by the annotation @Input.
It is important to note that input timeseries can be defined as a:

  1. Variable (as is done in the example above)
  2. TimSeriesArray
  3. Variable[]

  4. TimeSeriesArray[]

The major difference between the use of the class Variable and TimeSeriesArray is that Variable is used when the output is only dependend on input values

of the same timestep. For example when the transformation is calculating the discharge from the stage by using a rating curve than the output is only dependend of

the input value at the same time step. However when a transformation is calculating the aggregation of the input time series over a certain period than the output

is dependend on other values at other time steps in the input time series. In this case one should use the TimeSeriesArray.

The same logic applies to the cases when a Variable[] or TimeSeriesArray[] is used. The difference between a Variable and a Variable[] is that when in the configuration several

timeseries are defined in the timeseriesset config a Variable[] is used. For example by configuring a locationSet in the timeSeriesSet. When the timeseriesset only defines a single

timeseries than a Variable is used.

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.

 @Output
 Variable output = null;
  • No labels