Generated reference › Feature Selector — Machine Learning/Preprocessing
kind: generated#block#machine-learning-preprocessing

Feature Selector — Machine Learning/Preprocessing

Machine_Learning/Preprocessing/Feature_Selector · 1 input / 1 output port(s) at insert · exports to Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text

Description#

The block's own DESCRIPTION_HTML, rendered verbatim — the same text the config dialog's info panel and the library navigator show. Fix a wrong sentence in the block's .cpp (R-D9), never here.

Feature Selector

Machine Learning / Preprocessing

Keeps an arbitrary, ordered list of entries out of a wider vector: yᵢ = u[Indicesᵢ]. This is what sits between a source that produces every channel available and a model that was fitted on a subset of them, in a particular order – the selection step of a deployed pipeline.

It is deliberately not a window. A fitted selector keeps entries like 11, 2 and 40; Submatrix in Matrix Operations takes a contiguous range and cannot express that.

Ports

  • u – the full feature column, [d,1]. d must be large enough that every entry of Indices exists; the block checks this and reports rather than reading past the end.
  • Outputy, [k,1], where k is the number of entries in Indices. The output width therefore comes from the parameter, not from the input – this block changes the signal dimension.

Parameters

  • Indices – the entries to keep, in the order they are listed, as a column or a row. Order matters and is preserved, so this block also re-orders; the list may repeat an entry, which duplicates it. Interpreted relative to Index Base.
  • Index Base – what the first entry of the input is called:
    • Zero-based (PyTorch, numpy) – index 0 selects the first element. The default, and what a selector fitted in Python will give you.
    • One-based (MATLAB) – index 1 selects the first element.
    Getting this wrong is reported at the start of the run as an out-of-range index, not silently absorbed.
  • Sampling Time (s) – zero or less inherits the solver's rate; a positive value runs the block at that period.

Code export

All ten targets: Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog and PLC Structured Text. The resolved indices are baked into the generated code as straight-line assignments; there is no tunable parameter, because the selection determines which assignments are emitted rather than a value they use.

Every target is exact, not merely within tolerance, because the block performs no arithmetic – each output element is a copy. For the same reason the three HDL targets are genuinely synthesizable: the body reduces to wiring, with no multiplier, no divider and nothing transcendental. This is the cheapest block in the family on every target.

Simulink bridge

None. Neither the Statistics and Machine Learning Toolbox nor the Deep Learning Toolbox is installed here, so a bridge could not be run against a parity testbench even if one were written. Base Simulink has no fitted selector either – the nearest thing is a Selector block, whose index list is a mask parameter rather than a fitted artefact, and mapping onto it would claim an equivalence this block does not make. The bridge reports the block rather than dropping it silently, and it has no parity testbench, which is the documented consequence of Support::None rather than a gap. Code export verification still covers it across all ten languages.

Notes

  • Algebraic and stateless: the output depends only on the current sample, so the block cannot break an algebraic loop.
  • It changes the signal width, from [d,1] to [k,1]. k may be larger than d if the list repeats entries.
  • No state space, although selection genuinely is linear (y = S·u for a selection matrix of zeros and ones). The width of S depends on the input signal, which is not known when the block is constructed, and a state space that only appears after the first run is refused by model reduction anyway – so the block carries none rather than publishing one that is right only sometimes.
  • The index base is resolved once when the configuration is loaded, so the block and all ten exported cores use the identical resolved list. A consequence worth knowing: code export verification cannot detect a wrong base, because both sides read the same resolved values. The range check at the start of the run is what catches it.

Code facts#

FactValue
registered typeMachine_Learning/Preprocessing/Feature_Selector
familyMachine_Learning/Preprocessing
solver environment classICoreBlock_0_Machine_Learning_1_Preprocessing_2_Feature_Selector
sourcesrc/ICoreSDK/ICoreBlockLibrary/Blocks/Machine_Learning/Preprocessing/Feature_Selector/ICoreBlock_0_Machine_Learning_1_Preprocessing_2_Feature_Selector.cpp
headersrc/ICoreSDK/ICoreBlockLibrary/Blocks/Machine_Learning/Preprocessing/Feature_Selector/ICoreBlock_0_Machine_Learning_1_Preprocessing_2_Feature_Selector.h
default size on canvas120 × 80 px
ports at insert1 in, 1 out
code generators implementedPython, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text

Ports#

#DirectionSignal typeDescription label
1inICoreDoubleu
2outICoreDoubley

Ports the constructor creates. A block whose port list changes with its configuration adds or removes ports at load time; the count above is the one a freshly inserted block has.

Configuration variables#

Config variableDefaultSimulink parameter
Indices[2; 0; 4]
Index BaseZero-based (PyTorch, numpy)%~%One-based (MATLAB)~~Zero-ba…

Every block also carries Sampling Time (s) from ICoreBlockSolverEnvironment: zero or less inherits the solver's rate, a positive value runs the block at that period.

supportSupport::None
Simulink path
port-count rulePortsParam::None
SampleTime parameteryes

Caveat (shown to the user): no verifiable Simulink equivalent. Neither the Statistics and Machine Learning Toolbox nor the Deep Learning Toolbox is installed on this machine, so a bridge could not be run against a parity testbench even if one were written. Simulink's Selector is the nearest block, but its index list is a mask parameter rather than a fitted artefact and it carries no notion of an index base, so mapping onto it would claim an equivalence this block does not make. Re-create the selection with a Selector and paste the same indices

Catalog contract: src/ICoreSDK/ICoreCoder/ICoreCommandSystem/SimulinkBridge/ICoreSimulinkBlockCatalog.h

Description vs code#

The checker has a blind spot here — it could not resolve something (a grouped port bullet, a computed config name), which is reported and never counted as a pass. A reader has to settle it:

  • B0 every stimulus in the sample errored — cross-checks skipped

The verdict above is tools/docs/check_block_descriptions.py (P7.1), which compares LISTS. It cannot read a sentence: "stateless" on a block with a state, an initial-value semantic the recursion does not implement, a "not synthesizable" caveat the HDL banner contradicts. That is the agent audit (P7.3) on BLOCK_DESCRIPTION_AUDIT.md, and this tool's green is not a substitute for one.

File banner (developer view)#

The top comment of the block's .cpp — the maths, the realization and the export strategy, addressed to whoever changes it. It must not contradict the description above (P7.5).

Feature Selector — keep an arbitrary, ordered list of features out of a wider vector y[i] = u[ Indices[i] ] for i = 0 .. k-1

The step between a source that produces every available channel and a model fitted on a SUBSET of them, in a particular order. Not Submatrix: that takes a contiguous window, and a fitted selector's indices almost never are.

⚠ There is NO arithmetic in this block. Every output element is a copy of an input element, so all ten targets are EXACT rather than within a tolerance, and the three HDL targets are genuinely synthesizable -- they reduce to wiring. That is why nothing below quantizes, accumulates, or reaches for the simulation-only real escape hatch that the transcendental blocks in this family need.

⚠ The index base is resolved ONCE, in loadBlockConfig(), and every generator bakes the resolved zero-based values in. One implementation of the rule instead of eleven. The cost is stated rather than hidden: export verification compares ICore against its own generated code, and BOTH read the same already-resolved list, so a green row proves nothing whatever about "Index Base". That is the vacuous-rig trap of §7, and the honest place for the base rule is the range check in verifyInitializedPortSignals() -- which does fire, loudly, and is where a user actually finds a one-based list pasted into a zero-based block.

Sample results#

No stimulus produced a sampled output in this rig — Index out of range at: ICore Blocks/Home/Feature Selector. That is a fact about the single-block rig, not a verdict on the block: an offline batch fit, a block whose output only appears at onSolverFinish, or one that needs a driven environment cannot be exercised alone.

Category unsampled · sample time 0.1 · 60 steps · commit ccf005c8 · produced by docsSample --out <folder> --steps 60

Sample data: docs/generated/samples/Machine_Learning__Preprocessing__Feature_Selector.json