DocsBCILattice Custom Blocks
BCILattice Documentation

BCILattice Custom Blocks

All custom and built-in special blocks available in the ML Suite (MLFlow) and Workflow Designer canvases, injected at runtime by the training server.

v1.0BCINexus Platform · 2026-05-20[email protected]

Overview

In addition to the 5,400+ catalog blocks loaded from the CSV, BCILattice injects a set of custom built-in blocks at server startup. These cover analysis utilities, pipeline I/O, code execution, file selection, and Workflow graph controls.

New here? The Block Index lists every one of our blocks in a single line, grouped as the palette groups them.

Custom blocks are not classes; they run as functions or server-side routines and appear in the block palette alongside catalog blocks. They are marked is_custom: true internally.

BlockCategoryCanvas
Channel SelectionAnalysis (BCILattice)MLFlow + Workflow
Signal ProjectionAnalysis (BCILattice)MLFlow + Workflow
Time-Frequency FeaturesAnalysis (BCILattice)MLFlow + Workflow
Custom LabelsInputs (BCILattice)MLFlow + Workflow
Input BlockInputs (BCILattice)MLFlow + Workflow
Output BlockOutputs (BCILattice)MLFlow + Workflow
Loop BlockFlow Control (BCILattice)MLFlow + Workflow
Custom CodePipeline BlocksMLFlow + Workflow
Data GraphGraphs (BCILattice)MLFlow + Workflow
Confusion Matrix GraphGraphs (BCILattice)MLFlow + Workflow
Graph OutputGraphs (BCILattice)MLFlow + Workflow
Graph EndpointPipeline BlocksWorkflow only
Select FilesInputs (BCILattice)Workflow only
Compiled PipelineModel/Pipelines (Compiled)Workflow (runtime)

Analysis Blocks

These blocks call the local training server's analysis routes (/xlb9/…) and are available in both the ML Suite and Workflow Designer canvases.

Channel Selection

AnalysisML SuiteWorkflow DesignerFunction (custom)

Ranks and filters EEG/fNIRS/EMG channels by statistical relevance. Calls /xlb9/channel_selection/run. The Workflow canvas exposes an extra data_type selector; the ML Suite version omits it.

Inputs

Data:AnyLabels:Any

Outputs

Selected Data:AnySelected Channels:AnyScores:Any

Settings

SettingTypeDefaultDescription
method_nameselectt-Value MethodChannel ranking algorithm
rest_labelint0Integer label for the rest/baseline class
percentileint5Top-N percentile of channels to keep
ignore_classesstrComma-separated class labels to exclude
data_typeselectfNIRSWorkflow only

Custom Labels

AnalysisML SuiteWorkflow DesignerFunction (custom)

Injects or overrides the label column used by downstream blocks. Accepts a path to a label CSV or a comma-separated string of manual labels.

Inputs

Data:Any

Outputs

Labels:Any

Settings

SettingTypeDefaultDescription
label_filestrPath to a CSV file whose first column is used as labels
manual_labelsstrComma-separated label values (overrides label_file if set)

Signal Projection

AnalysisML SuiteWorkflow DesignerFunction (custom)

Converts 2-D time-series signals into 2-D images using time-frequency or recurrence transforms. Calls /xlb9/signal_projection/run. Useful for feeding EEG into CNN-based image classifiers.

Inputs

Data:Any

Outputs

Projected Images:AnyShape:Any

Settings

SettingTypeDefaultDescription
method_nameselectGramian Angular Field (GAF)Projection algorithm
image_sizeint64Output image resolution in pixels (square)

Time-Frequency Features

Analysis (BCILattice)ML SuiteWorkflow DesignerFunction (custom)

Turns the Analysis suite's time-frequency output into a trainable feature table. It reduces a per-trial ERSP cube — (epochs, channels, freqs, times) — down to X[n_trials, n_features] with labels that stay index-aligned, so a time-frequency analysis can actually train a decoder instead of only rendering a figure.

On fNIRS data, time-frequency peaks read roughly 30% low. That is a resolution limit of the transform in the very low fNIRS band, not a defect in this block — treat the peak frequency as approximate when interpreting fNIRS results.

Inputs

Trials:AnyLabels:AnyFreqs:AnyTimes:Any

Outputs

Features:AnyLabels:AnyFeature Names:AnyX:AnyY:AnyInfo:Any

Settings

SettingTypeDefaultDescription
aggregationselectband_meansHow the freq × time cube collapses to features. band_means = one value per band per channel; flatten keeps everything (very wide)
tminfloat0Start of the analysis window in seconds. 0 with tmax 0 means the whole epoch
tmaxfloat0End of the analysis window in seconds
n_time_windowsint4Windows per band when aggregation is band_time_windows
bandsstrCustom bands as "name:low-high" pairs. Empty uses the standard delta/theta/alpha/beta/gamma set
standardizeboolfalsez-score each feature across trials before returning

Pipeline Blocks

Structural blocks that control data flow and code execution within a pipeline. Available in both canvases unless noted otherwise.

Input Block

Pipeline BlocksML SuiteWorkflow DesignerFunction (custom)

Marks one entry point of the pipeline, and nothing else. Drag one onto the canvas for each data stream the pipeline accepts. Each Input Block becomes exactly one input port on the compiled-pipeline block when this pipeline is dropped into a Workflow, which tells you where to connect what. Which files arrive, how they split into runs and how they are filtered are set on the Workflow's Select Files.

The canvas port is labelled with port_name, so what you see here is exactly what you will wire to on the compiled block. Give each Input Block a distinct name — two blocks sharing one name compile to two identically named ports.

Outputs

port_name:Any

Settings

SettingTypeDefaultDescription
port_namestrIn_1Names both the port drawn on the canvas and the port exposed on the compiled block

File Path

Inputs (BCILattice)MLFlow DesignerWorkflow DesignerFunction (custom)

Points at one file on disk and emits its path. It reads nothing — that is the point: a block that does its own file reading needs the path, and Select Files cannot give it one usefully, because Select Files exists to load a processing stage into a table.

One file in, one path out. For several recordings use Select Files, whose File Paths port carries every recording you picked. A wired path always beats a reader's own file_path property.

Outputs

File Path:Any

Settings

SettingTypeDefaultDescription
file_pathfileThe file to point at
must_existbooltrueRefuse a path that is not on disk, naming it. Turn off for a file an earlier step produces

Output Block

Pipeline BlocksML SuiteWorkflow DesignerFunction (custom)

Marks one exit point of the pipeline. Whatever is connected here becomes one output port on the compiled-pipeline block. Every pipeline needs exactly one final output node — an Output Block, Graph Output or Graph Endpoint — or compiling fails.

It forwards the first non-null value arriving on a connected edge. Ambient values deliberately lose: an embedded pipeline runs with the caller's inputs pre-seeded, so a naive “first non-null” would forward the pipeline's own input and return the data unchanged while appearing to have run.

Inputs

port_name:Any

Settings

SettingTypeDefaultDescription
port_namestrOut_1Names both the port drawn on the canvas and the port exposed on the compiled block

Loop Block

Pipeline BlocksML SuiteWorkflow DesignerFunction (custom)

Repeats a sub-section of the pipeline for N iterations or epoch-by-epoch. Set start_node and end_node to the labels of the blocks that mark the loop boundary.

Inputs

Loop Input:Any

Outputs

Loop Output:Any

Settings

SettingTypeDefaultDescription
iterationsint1Number of times to repeat the loop body
start_nodestrLabel of the first block inside the loop
end_nodestrLabel of the last block inside the loop
modeselectEpochSequential runs the whole loop N times; Epoch iterates once per data epoch

Custom Code

Pipeline BlocksML SuiteWorkflow DesignerFunction (custom)

Executes an arbitrary Python function inline inside the pipeline. The function receives the upstream data tensor as its first argument and must return the transformed result.

def custom_process(data):
    # data is the input tensor from the previous block
    # transform it here
    return data

Inputs

Data:Any

Outputs

Result:Any

Settings

SettingTypeDefaultDescription
codecodedef custom_process(data): return dataPython function body: must accept data and return output

Model Structure Blocks

The only two blocks that take models in and hand a model out. Everything else on the canvas moves data; these build the shape of one network.

Chaining layer blocks already composes them in order — these are for the case a chain cannot express: several branches over the same input, joined back together. Each wired Branch N receives the identical input inside the composed module's forward.

Do not confuse these with Feature Concatenator, Parallel Fan-out or Ensemble Voter in Data Routing and Flow Control. Those combine arrays — data between models, or predictions from several models. These combine models, inside one network. Wiring data into a Branch N port is refused with a message saying which block you wanted.

Model Concat

Model Structure (BCILattice)ML SuiteWorkflow DesignerFunction (custom)

Runs every wired branch on the same input and concatenates the results into one tensor. This is how a multi-scale CNN or a two-stream model is drawn: three Conv1d branches with different kernel sizes, joined here, then a shared head.

A single wired branch collapses to that branch, so the block is safe to leave in place while you build the other paths.

Inputs

Branch 1:AnyBranch 2:AnyBranch 3:Any

Outputs

model_obj:Any

Settings

SettingTypeDefaultDescription
n_inputsint3Number of Branch ports (1–12)
dimint1Axis to join on. 1 is the feature axis of a (batch, features, …) tensor — joining the last axis of a conv output concatenates along time instead, which is rarely what you want

Model Add

Model Structure (BCILattice)ML SuiteWorkflow DesignerFunction (custom)

Runs every wired branch on the same input and sums the results. Put a transformed path on one branch and an Identity layer on the other, and you have a residual/skip connection.

Every branch must produce the same shape — addition has no broadcasting rule that would be safe to guess here.

Inputs

Branch 1:AnyBranch 2:Any

Outputs

model_obj:Any

Settings

SettingTypeDefaultDescription
n_inputsint2Number of Branch ports (1–12)

Trainer Trigger

Model Structure (BCILattice)ML SuiteWorkflow DesignerFunction (custom)

Hands one side of the trainer's train/test split to a block that fits on its own. Use it when a model block shows X and y ports — that block is a constructor and a fit call in one, and it must not see the rows the trainer will score against.

The source is chosen by name, not by a wire, so one Select Files can feed a dozen triggers without a dozen edges crossing the canvas.

It uses the trainer’s split, not its own. The split settings are read from the BCILattice Trainer in the same graph, and the partition is derived with the identical call the trainer makes — same strategy, same test_size, same seed, so the same rows. Every trigger in a run shares one partition, which is what keeps X and y index-aligned.

Outputs

Data:Any

Settings

SettingTypeDefaultDescription
source_blockselectWhich block the data comes from — the list is read from the canvas, so it is always what actually exists
source_portselectWhich of its outputs — for example Select Files → X, or → Y
splitselecttrainWhich side of the trainer’s split to hand over. train by default: a block that fits must not see the test rows

Graph Blocks

Four ways to get a picture out of a run. The important distinction is tap vs. terminal: Data Graph passes its value straight through, so it can be spliced anywhere, any number of times. Graph Output and Graph Endpoint are terminal nodes, so they compete for the “exactly one final output” slot every compiled graph must have.

Data Graph

Graphs (BCILattice)ML SuiteWorkflow DesignerFunction (custom)

A general-purpose plot tap: it renders whatever reaches it and passes the same value out unchanged on its Data port. Because it is not a terminal node, you can drop it onto an existing connection to inspect what is flowing through mid-pipeline without rewiring anything downstream.

A value that cannot be drawn never silently disappears — the reason lands on the Graph Error port. Wire it somewhere, or read it in the node inspector, when a plot does not appear.

Inputs

Data:Any

Outputs

Graph:AnyData:AnyGraph File:AnyGraph Error:Any

Settings

SettingTypeDefaultDescription
graph_namestrData GraphTitles the plot, so several taps stay distinguishable in the Training dashboard Graphs tab
plot_typeselectautoauto picks by shape: curves for training history, an annotated matrix for a confusion matrix, lines/heatmap for arrays
save_pathstrOptional path to write the image
image_formatselectpngpng · jpg

Confusion Matrix Graph

Graphs (BCILattice)ML SuiteWorkflow DesignerFunction (custom)

Draws a confusion matrix from true and predicted labels. Wire it to a trainer's Test Labels and Test Predictions outputs (out-of-fold when a Validation Scheme is wired).

Inputs

y_true:Anyy_pred:Any

Outputs

Graph:Any

Settings

SettingTypeDefaultDescription
titlestrConfusion Matrix—
normalizeselectnonetrue = row-normalised (recall per class), pred = column-normalised (precision), all = over the whole matrix
colormapstrBluesAny matplotlib colormap name
display_labelsstrComma-separated class names. Empty uses the raw label values

Graph Output

Graphs (BCILattice)ML SuiteWorkflow DesignerFunction (custom)

Terminal plot node: renders the incoming value and saves it to disk. Counts as a pipeline's single final output, so it can end a graph in place of an Output Block.

Inputs

Graph Data:Any

Outputs

Graph File:AnyGraph:AnyGraph Error:Any

Settings

SettingTypeDefaultDescription
graph_namestrWorkflow GraphDisplay title embedded in the image
save_pathstrFile path to write the output image
image_formatselectpngpng · jpg · pdf

Graph Endpoint

Pipeline BlocksWorkflow DesignerFunction (custom)

The other terminal plot node. Behaves like Graph Output but writes to its own output_path, and is the node the workflow HTTP route targets when a graph is executed over REST.

Inputs

Graph Data:Any

Outputs

Graph File:AnyGraph:AnyGraph Error:Any

Settings

SettingTypeDefaultDescription
graph_namestrWorkflow Graph—
output_pathstrFile path to write the rendered image

Workflow-Only Blocks

Loading real recordings is a Workflow-canvas concern, so this block exists only there. An ML Suite pipeline takes its data through an Input Block instead, and is fed by whatever the Workflow wires into it.

Select Files

Inputs (BCILattice)Workflow DesignerFunction (custom)

Loads real recordings from the Data Manager: pick a modality, a processing stage, a session and the subjects, and it emits the feature table X and labels Y. This is where a workflow actually gets its data.

The card on the canvas states the cohort in words, not raw properties —subjects: 20 — S01, S02, S03, S04 +16 more, features: all columns (never a bare selected_features: []), and runs: 20 (Per subject, combined sessions) — the exact number of jobs subject_scope above will fan the run out into, computed the same way the training server groups the recordings. Blank filters are left off the card instead of printing as filter_task:.

The extra output ports change with data_source: a recording publishes Channels, a reducer's output publishes Components, a feature table publishes Feature Names, epochs publish Epoch Index. X and Y are always present, and so is File Paths — the recordings you picked, for a block that does its own reading (see File Path).

Samples: one unit, one number. Pick seconds, Hz or rows and a single size row appears in that unit; the card says what one sample is in words (“model rate 5 Hz, rows averaged into one”). The rate comes from the recording itself, and a sample never spans two recordings. An already-epoched Data Source (Epochs, Features, Time-Frequency…) is one sample per trial, so the Samples choices are greyed out for it — data is never epoched twice. The same settings exist as the Epoching block, for data that did not come straight from Select Files.

Media. Tick Stimulus (and/or Response) on the Media row to publish the images, video, audio or text the study presented, paired with X by one index. With Samples on, each sample takes the stimulus shown during it, and a Sample Onsets port appears for cutting a video or audio stream with Media Windower.

Outputs

X:AnyY:AnyFiles:AnyFile Paths:Any+ source-specific:Any

Settings

SettingTypeDefaultDescription
modalityselectfNIRSSignal modality filter
data_sourceselectClean DataWhich processing stage to load — clean, channel-selected, quality-checked, normalised, features, epochs, time-frequency, …
sessionselectAll SessionsSession filter
chromophoreselectAllfNIRS only: keep only hbo or only hbr. "All" feeds every optode in twice, once per chromophore
selected_filesstrSerialised list of file records chosen in the picker
selected_subjectsstrSubject IDs extracted from the selected files
selected_featureslist[]Optional column subset to keep — blank keeps every column
subject_scopeselectPer subject, combined sessionsHow the selected recordings become training runs. Subjects and sessions are independent axes: kept apart (one run each) or pooled (one run for all of them). The BCILattice Trainer's cohort_mode mirrors this same choice, and the run refuses if the two disagree
filter_taskstrComma-separated task tags to keep, e.g. "Motor Imagery". Blank matches everything
filter_paradigmstrComma-separated paradigm tags to keep
filter_datasetstrComma-separated source-dataset tags to keep
filter_qualitystrComma-separated quality tags to keep
media_stimulusboolfalsePublish the stimulus media (image, video, audio, text) per trial or sample
media_responseboolfalsePublish the participant's recorded response media
sample_byselectevery rowHow many recorded rows make one sample for the model, in the unit you think in. On a 10 Hz device, 0.2 seconds, 5 Hz and 2 rows are the same answer. Only one unit at a time
sample_sizefloat1The number, in the unit sample_by names (seconds, Hz or rows)
combineselectautostack keeps the rows as time steps (samples × channels × steps); average makes one row per sample (a lower rate). auto: average for Hz, stack otherwise
overlap_percentfloat0How much each stacked sample shares with the next. Overlapping samples must be validated with whole recordings held out
window_labelselectskip mixedThe label of a sample whose rows carry different labels. skip mixed drops it rather than inventing one

Training several models on what Select Files loads? A trainer's Model input takes one wire — the canvas refuses a second one and offers to insert a Model Collection instead, so every subject's recordings load once and each model gets its own results row. See Model Collection in the Advanced Blocks reference.

Compiled Pipeline Block

When you compile and register a pipeline from the ML Suite or Workflow Designer, BCILattice dynamically injects it as a reusable block into the Pipeline Blocks category. These blocks are created at runtime via POST /xlb9/register_compiled_pipeline or POST /xlb9/register_compiled_workflow.

Compiled Pipeline

Pipeline BlocksWorkflow DesignerDynamicFunction (custom)

A compiled and registered pipeline exposed as a single reusable block, collected in the Model/Pipelines (Compiled) palette group. It has one input port per Input Block and one output port per Output Block in the original pipeline, each named from that block's port_name.

Inputs

one per Input Block:Any

Outputs

one per Output Block:Any

Settings

SettingTypeDefaultDescription
descriptionstrCompiled pipeline: …Auto-filled with the pipeline name
block_roleselectProcessing PipelineDetermines training behaviour and loss function selection
optimizerstrAdamOptimiser name passed to the training loop
epochsint10Training epochs when block_role is ML Model or DL Model
learning_ratefloat0.001Learning rate for the optimiser
BCILattice Custom Blocks v1.0 · BCINexus Platform · 2026-05-20