Parameters

You can add parameters to your algorithm by creating a property with a getter and setter. Then you annotate the getter and setter with the same @JIPipeParameter keys. Also add an @JIPipeDocumentation annotation to either the getter or setter.

Parameters are automatically serialized and deserialized.

Please make sure to send an event when the parameter is set, so the UI can update.

// ... see previous tutorials
public class MyAlgorithm extends JIPipeIteratingAlgorithm {

    private float roundness = 0.5f;

    // ... see previous tutorials

    @JIPipeParameter("roundness")
    @JIPipeDocumentation(name = "Roundness", description = "Value within [0, 1]")
    public float getRoundness() {
        return roundness;
    }

    @JIPipeParameter("roundness")
    public boolean setRoundness(float roundness)  {
        if(roundness < 0 || roundness > 1)
            return false; // Reject this value
        this.roundness = roundness;
        // Send the change out to listeners
        getEventBus().post(new ParameterChangedEvent(this, "roundness"));
    }

}

Your setter can return a boolean. If the output is true, JIPipe considers the value as valid. If false, the JIPipe UI re-loads a valid value via the getter.

Please make sure that your parameter key is unique. Only one getter and one setter should have the same key.

Not all data types are supported. Data types are registered into JIPipe and available via JIPipeUIParametertypeRegistry.getInstance(). In a later tutorial we show how to register custom data types. JIPipe supports common primitives like boolean, int, float, double, String, and all enum data types.

Accessing parameters from within code

When a user sets a parameter within the UI, it goes through an instance of JIPipeParameterAccess. This object is responsible for triggering the required events to notify the UI.

If you set a parameter setter via code, you will notice that any open parameter UI does not respond to this change - due to the absence of the JIPipeParameterAccess.ParameterChangedEvent.

Use the provided triggerParameterChange(key) function to trigger the appropriate parameter change event for a parameter. Alternatively, you can use the setParameter(key, value) method to set parameters.

MyAlgorithm algorithm = new MyAlgorithm(...);

// This will NOT update the UI
algorithm.setRoundness(1.0f);

// Either trigger the event manually
algorithm.setRoundness(1.0f);
algorithm.triggerParameterChange("roundness");

// Or just use the setParameter() function
algorithm.setParameter("roundness", 1.0f);

// DO NOT DO THIS EVER:
algorithm.setRoundness(1.0f);
algorithm.isParameterUIVisible(); // DON'T DO THIS!!! THIS WILL UPDATE THE UI, BUT NOT INFORM DEPENDENT PARAMETERS

You can also read parameters via their key using getParameter()

MyAlgorithm algorithm = new MyAlgorithm(...);
algorithm.getParameter("roundness", Float.class) // Returns 1.0 

Accessing the whole parameter tree

The mentioned functions getParameter and setParameter are utilities around JIPipeParameterTree, which manages the whole set of parameters and sub-parameters of a JIPipeParameterCollection. We recommend to create such an object directly, if you want to access many parameters at once or want to read parameter metadata like names, documentation, annotations, and more. It also gives you more control on how parameters are accessed (for example it can force using reflection parameters), which can be helpful in more special cases.

MyAlgorithm algorithm = new MyAlgorithm(...);
JIPipeParameterTree tree = new JIPipeParameterTree(algorithm);

// The access object contains the metadata
JIPipeParameterAccess access = tree.getParameters().get("roundness");
access.set(1.0f);

// You can also access sub-parameters (by key or by object)
JIPipeParameterTree.Node subParameterNode = tree.getSourceNode(algorithm.getSubParameter());
subParameterNode.getDescription(); // Access to various settings

Parameter settings

Some parameter types have different styles or other settings that can change the behavior of the parameter editor UI. An example is StringParameterSettings that allows to change between single-line and multi-line editors.

Sub-parameters

JIPipeAlgorithm, like any JIPipeParameterCollection allows sub-parameters.

To create a sub-parameter create a getter to an JIPipeParameterCollection and annotate it with @JIPipeParameter. The key provided with the annotation should be an unique parameter key. The parameters in the sub-parameter instance are automatically displayed as new group in the parameter editor.

@JIPipeDocumentation(name = "Gaussian filter")
@JIPipeParameter(value = "gaussian-algorithm")
public GaussianBlur2DAlgorithm getGaussianAlgorithm() {
    return gaussianAlgorithm;
}

The @JIPipeParameter annotation allows you to determine various properties, like if the sub-parameter should be collapsed or hidden by default.

Please do not forget to listen for the ParameterStructureChangedEvent and pass it to the algorithm’s event bus. Otherwise there can be issues with the extension builder. You can use the registerSubParameter() method in the constructor and copy constructor as a shortcut.

Conditional parameters

Each parameter collection (including nodes) allow the conditional display of parameters or sub-parameters. To setup this display, override the isParameterUIVisible method. There are two overloads, one for displaying or hiding single parameters, and one for controlling the display of sub-parameters.

// Example for conditional showing/hidding of single parameters
 @Override
public boolean isParameterUIVisible(JIPipeParameterTree tree, JIPipeParameterAccess access) {
    if (access.getKey().equals("mode"))
        return true;
    if (mode == Mode.Automatic) {
        return !access.getKey().equals("custom-name");
    } else {
        if (access.getKey().equals("ignore-missing-metadata"))
            return true;
        if (access.getKey().equals("missing-string"))
            return true;
        return access.getKey().equals("custom-name");
    }
} 

// Example for sub-parameters
@Override
public boolean isParameterUIVisible(JIPipeParameterTree tree, JIPipeParameterCollection subParameter) {
    if(!scaleToModelSize && subParameter == getScale2DAlgorithm()) {
        return false;
    }
    return super.isParameterUIVisible(tree, subParameter);
}

Use triggerParameterUIChange() to trigger an update of the UI in the setter function if you have dependencies between parameters. This will work for parameters and parameter groups.

User-defined parameters

If you want to make it possible for users to create custom parameters, create an JIPipeDynamicParameterHolder as sub-parameter. You can control the list of allowed parameter types and other settings.

// Field that initializes the dynamic parameter collection with all supported parameter types
private JIPipeDynamicParameterCollection scriptParameters = new JIPipeDynamicParameterCollection(true,
            JIPipe.getParameterTypes().getRegisteredParameters().values());
            
public MyClass() {
    registerSubParameter(scriptParameters);
}

public MyClass(MyClass other) {
    this.scriptParameters = new JIPipeDynamicParameterCollection(other.scriptParameters);
    registerSubParameter(scriptParameters);
}

@JIPipeDocumentation(name = "Script parameters")
@JIPipeParameter(value = "script-parameters", persistence = JIPipeParameterPersistence.Object) // Important: Set persistence
public JIPipeDynamicParameterCollection getScriptParameters() {
    return scriptParameters;
}

Do not forget to deep-copy the JIPipeDynamicParameterHolder. The class has a copy constructor for such an operation.

Please do not forget to listen for the ParameterStructureChangedEvent and pass it to the algorithm’s event bus. Otherwise there can be issues with the extension builder. JIPipeAlgorithm comes with a pre-made function registerSubParameters() that should be called in the constructors.

We recommend setting the persistence of the getter to JIPipeParameterPersistence.Object. Otherwise, JIPipe will have issues with de-serializing the parameter and lose all settings.

Full control

You can inherit from JIPipeCustomParameterHolder to define all parameters manually without the need for an JIPipeDynamicParameterHolder or annotations.