Adding parameters to custom blocks

Custom DSP, Learn and Transformation blocks can have custom parameters. You use these to give the user an option to visually configure the block. For example to select the cutoff for a filter in a DSP block, or what data augmentation to apply in an ML algorithm.

Defining parameters

Each parameter is defined as a JSON object. Here's a basic example:

{
    "name": "Scale axes",
    "value": 1,
    "type": "float",
    "help": "Multiplies axes by this number",
    "param": "scale-axes"
}

This renders the following UI element:

Here "name" maps to the label of the element, "help" is shown under a tooltip, "value" is the default value of the element, and "type" is enforced if you enter an invalid value.

"param" is the parameter that'll be sent to your block. Depending on the type of block this is either:

  • DSP Blocks: Passed in an HTTP request to the block, and then (by default) passed as an argument to the Python function implementing the block. See Building custom processing blocks > Adding configuration options.

  • All other blocks: Passed in as command line arguments, prefixed with --. E.g. for the example above your block will be called with --scale-axes 1.

parameters.json file

Parameters are described in a parameters.json file placed in the root of your block. This is then automatically picked up by the Studio when rendering your block.

Example parameters.json file for DSP blocks

For DSP blocks the parameters.json file also contains metadata for the block, and the parameters are listed in the parameters object. Additionally, DSP blocks can contain multiple groups. Each group has a header element that is rendered.

{
    "info": {
        "title": "My awesome DSP Block",
        "author": "Jan Jongboom",
        "description": "My first DSP Block.",
        "name": "First DSP Block",
        "cppType": "my_awesome_dsp_block",
        "latestImplementationVersion": 1,
        "visualization": "dimensionalityReduction",
        "preferConvolution": true
    },
    "parameters": [
        {
            "group": "Group 1",
            "items": [
                {
                    "name": "Scale axes",
                    "value": 1,
                    "type": "float",
                    "help": "Multiplies axes by this number",
                    "param": "scale-axes"
                }
            ]
        }
    ]
}

This is rendered as:

Example parameters.json file for Learn blocks

For learn blocks the parameters.json file just contains an array of items.

[{
    "name": "Learning rate #1",
    "value": 0.01,
    "type": "float",
    "help": "Learning rate for the first 10 epochs",
    "param": "learning-rate-1"
}, {
    "name": "Learning rate #2",
    "value": 0.001,
    "type": "float",
    "help": "Fine-tuning learning rate",
    "param": "learning-rate-2"
}]

This is rendered as:

And passed into your script as:

--learning-rate-1 0.01 --learning-rate-2 0.001

If a learn block has no parameters (either no parameters.json file or one with an empty array) then the 'Number of training cycles' (maps to --epochs) and 'Learning rate' (maps to --learning-rate) elements are rendered.

Example parameters.json file for Transformation blocks

For transformation blocks the parameters.json file just contains an array of items.

[{
    "name": "Bucket",
    "type": "bucket",
    "param": "bucket-name",
    "value": "",
    "help": "The bucket where you're hosting all data"
},
{
    "name": "Bucket prefix",
    "value": "my-test-prefix/",
    "type": "string",
    "param": "bucket-prefix",
    "help": "The prefix in the bucket, where you're hosting the data"
}]

This is rendered as:

And passed into your script as:

--bucket-name "ei-data-dev" --bucket-prefix "my-test-prefix/"

Transformation blocks have two extra types: dataset and bucket. Both render a dropdown menu listing all datasets or all configured cloud buckets in your organization. The name of the dataset/bucket will be passed in to your script (e.g. in the configuration above ei-data-dev is passed in).

All types

The supported properties for the type attribute are:

string, int, float

These all render a text box.

select

This renders a dropdown menu and needs to be paired with a valid parameter listing all options. E.g.:

{
    "name": "Input decimation ratio",
    "value": "1",
    "type": "select",
    "valid": [ "1", "3", "10", "30", "100", "1000" ],
    "param": "input-decimation-ratio"
}

Renders as:

And:

To use a different label and value for the select element you can pass in an array of objects to valid. E.g.:

"valid": [
    { "label": "gpu (NDP101)", "value": "gpu" },
    { "label": "log-bin (NDP120/200)", "value": "log-bin" }
]

Here the UI renders the label ("gpu (NDP101)" and "log-bin (NDP120/200)") but the values ("gpu" or "log-bin") are actually passed to your blocks.

boolean

This renders a checkbox. E.g.:

{
    "name": "Take log of spectrum?",
    "value": true,
    "type": "boolean",
    "param": "do-log"
}

Renders as:

Boolean values are passed into your transformation and learn blocks with either the value 0 (false) or 1 (true):

--do-log 1

If you don't want a value (so just --do-log passed into the script) then use a flag (see the next section).

flag

A flag renders exactly the same as a boolean, but for transformation and learn blocks the parameter is passed to your script differently.

If the value is true then the parameter is just passed in as an argument, e.g.:

--do-log

If the value is false then the parameter is omitted.

dataset (transformation blocks only)

This renders a dropdown menu with all your organizational datasets. E.g.:

{
    "name": "Dataset to refresh",
    "type": "dataset",
    "param": "dataset",
    "value": ""
}

Renders as:

The name of the dataset is passed into your script.

bucket (transformation blocks only)

This renders a dropdown menu with all your organizational buckets. E.g.:{

{
    "name": "Bucket prefix",
    "value": "my-test-prefix/",
    "type": "string",
    "param": "bucket-prefix",
    "help": "The prefix in the bucket, where you're hosting the data"
}

Renders as:

The name of the bucket is passed into your script.

Basic logic for parameters

Parameters can be shown depending on the state of other parameters using the showIf property. E.g.:

[
    {
        "name": "Apply augmentation",
        "value": false,
        "type": "boolean",
        "param": "augmentation"
    },
    {
        "name": "How much augmentation",
        "value": "A little",
        "type": "select",
        "valid": [
            "A little",
            "A lot"
        ],
        "param": "how-much-augmentation",
        "showIf": {
            "parameter": "augmentation",
            "operator": "eq",
            "value": "true"
        }
    }
]

Here the 'How much augmentation' property is shown only when the 'Apply augmentation' checkbox is checked.

Default state:

State when the checkbox is checked:

You can also use neq as the operator to show elements when a clause is not true. Other operators are currently not supported.

Show parameters depending on implementation version (DSP Blocks)

DSP Blocks can have multiple implementation versions. This is used heavily in our internal code to add new functionality to existing blocks without breaking earlier implementations. You set the latest implementation version in the info object of the parameters.json file (new blocks are created with this implementation version). E.g.:

{
    "info": {
        "title": "Spectral Analysis",
        ...
        "latestImplementationVersion": 4
    },

Then to show certain parameters only for certain implementation versions, you use the showForImplementationVersion property:

{
    "name": "Type",
    "value": "FFT",
    "help": "Type of spectral analysis to apply",
    "type": "select",
    "valid": [ "FFT", "Wavelet" ],
    "param": "analysis-type",
    "showForImplementationVersion": [ 3, 4 ]
}

Now the FFT parameter is only shown for implementation versions 3 and 4. You can find complete examples of this behavior in the spectral analysis DSP block.

Full spec

type DSPParameterItem = {
    // Rendered as the label
    name: string;
    // Default value
    value: string | number | boolean;
    // Type of UI element to render
    type: 'string' | 'int' | 'float' | 'select' | 'boolean' | 'bucket' | 'dataset' | 'flag';
    // Optional help text (rendered as a help icon, text is shown on hover)
    help?: string;
    // Parameter that maps back to your block (no spaces allowed)
    param: string;
    // When type is "select" lists all options for the dropdown menu
    // you can either pass in an array of strings, or a list of objects
    // (if you want to customize the label)
    valid?: string[] | ({ label: string, value: string }[]);
    // If this is set, the field is rendered as readonly with the text "Click to set"
    // when clicked the UI changes to a normal text box.
    optional?: boolean;
    // Whether the field should be rendered as readonly.
    // These fields are shown, but cannot be changed.
    readonly?: boolean;
    // If set, this item is only shown if the implementation version of the block matches
    // (only for DSP blocks)
    showForImplementationVersion: number[] | undefined;
    // Show/hide the item depending on another parameter
    showIf: ({
        parameter: string,
        operator: 'eq' | 'neq',
        value: string,
    }) | undefined;
    // DSP only. If set, a macro is created like:
    // #define EI_DSP_PARAMS_BLOCKCPPTYPE_PARAM     VALUE
    createMacro?: boolean;
    // When type is "select" the value passed into your block will be a string,
    // you can use configType to override the type (used during deployment only)
    configType?: string;
};

Last updated