API reference

Map

AMBER.vesanto_size(n_samples: int) int[source]

Return the map side length recommended by Vesanto & Alhoniemi (2000).

The rule of thumb is that the total number of neurons should be approximately 5·√N, giving a square map of side √(5·√N).

Reference:

Vesanto, J. & Alhoniemi, E. (2000). Clustering of the self-organizing map. IEEE Transactions on Neural Networks, 11(3).

Parameters:

n_samples – number of training samples N

Returns:

integer map side length (minimum 2)

class AMBER.Map(data: ndarray | None = None, size: int | None = None, period: int = 10, initial_lr: float = 0.1, initial_neighbourhood: int = 0, distance: str = 'euclidean', dtw_band: int | None = None, use_decay: bool = False, lr_decay: str = 'linear', normalization: str = 'none', presentation: str = 'random', weights: str = 'random', random_seed: int | None = None)[source]

Bases: object

Map class is the main component of AMBER. It contains the classifying map that allows for classification and is subject of analysis in search of data information

calculate_bmu(pattern: ndarray) Tuple[source]

Calculates the Best Matching Unit (BMU) for a pattern using the configured signal-space distance.

Parameters:

pattern – 1-D array of the input pattern

Returns:

  • bmu_dist: distance from pattern to BMU weight vector

  • bmu_pos: (row, col) grid coordinates of the BMU

  • second_bmu_dist: distance from pattern to second-best neuron

  • second_bmu_pos: (row, col) grid coordinates of the second-best neuron

static decay(distance_BMU: ndarray, current_neighbourhood: float) ndarray[source]

Gaussian neighbourhood function h(r, t).

Returns the influence weight for every neuron given its grid distance to the BMU and the current neighbourhood radius σ(t):

h(r, t) = exp(−‖r − r_BMU‖² / (2σ(t)²))

This is Kohonen’s original formulation. Influence tapers smoothly toward zero as distance grows — no hard boundary is applied.

Parameters:
  • distance_BMU – (rows, cols) array of grid distances to the BMU

  • current_neighbourhood – current neighbourhood radius σ(t)

Returns:

(rows, cols) array of influence weights in (0, 1]

classmethod load_classifier(filename: str = 'Model') Map[source]

Load a previously saved Map from a JSON file.

Parameters:

filename – path without the .json extension (default 'Model')

Returns:

a fully restored Map instance ready for classification

Raises:

FileNotFoundError – if <filename>.json does not exist

reinforce(training_data: ndarray, reinforcement: int = 0, extension: int = 1, compression: float = 0.5) None[source]

Continue training with a fine-tuning (reinforcement) phase.

Each reinforcement round multiplies period by extension and compresses the learning rate by compression. The neighbourhood radius decays from its current value to 1 over the extended period, honouring the use_decay and lr_decay settings configured at construction time.

Note

reinforcement=0 (default) is a no-op — the map is unchanged. Pass reinforcement >= 1 to activate the phase.

Parameters:
  • training_data – 2-D numpy array — rows are samples, columns are features

  • reinforcement – number of additional reinforcement rounds (0 = no-op)

  • extension – period multiplier applied each round (e.g. 2 doubles iterations)

  • compression – learning-rate scale factor per round (e.g. 0.5 halves lr)

save_classifier(filename: str = 'Model') None[source]

Serialise the trained Map to a JSON file.

Saves weights, hyperparameters, and training metadata so the map can be fully restored with load_classifier().

Parameters:

filename – path without the .json extension (default 'Model')

train(data: ndarray) None[source]

Train the SOM on the provided data.

Parameters:

data – 2-D numpy array — rows are samples, columns are features

transform(data: ndarray) ndarray[source]

Apply the normalization fitted during training to new data.

For global methods (zscore, robust, 01scale), uses the parameters stored during train(). For per-sample methods the transformation is reapplied independently to each row. For 'none' returns data unchanged.

Always pass raw (un-normalised) data — the same scale as what was passed to train().

Parameters:

data – 2-D array of samples, shape (n, d)

Returns:

normalised array with the same shape

static variation_learning_rate(initial_lr: float, i: int, iterations_number: int, mode: str = 'linear') float[source]

Calculate the learning rate for iteration i.

Two decay schedules are supported:

  • 'linear' : η(t) = η₀ · (1 − t/T) Simple linear decay to zero. Widely used and easy to reason about.

  • 'asymptotic' : η(t) = η₀ / (1 + t / (T/2)) Decays quickly at first (coarse ordering) then slows down (fine-tuning). Better satisfies the Robbins–Monro stochastic approximation convergence conditions (Ση = ∞, Ση² < ∞) (Robbins & Monro, 1951, Ann. Math. Stat. 22(3):400-407).

Parameters:
  • initial_lr – initial learning rate η₀

  • i – current iteration index (1-based)

  • iterations_number – total number of iterations T

  • mode'linear' (default) or 'asymptotic'

Returns:

learning rate for iteration i

static variation_neighbourhood(initial_neighbourhood: float, i: int, iterations_number: int, final: float = 0, mode: str = 'linear') float[source]

Calculate the neighbourhood radius for iteration i.

Uses the same decay schedule as the learning rate.

  • 'linear' : σ(t) = σ_final + σ₀ · (1 − t/T)

  • 'asymptotic' : σ(t) = σ_final + σ₀ / (1 + t / (T/2))

Parameters:
  • initial_neighbourhood – initial neighbourhood radius σ₀

  • i – current iteration index (1-based)

  • iterations_number – total number of iterations T

  • final – minimum radius retained at the end (default 0)

  • mode'linear' (default) or 'asymptotic'

Returns:

neighbourhood radius for iteration i

Classification

class AMBER.Classification(som: Map, classification_data: ndarray, other: DataFrame | None = None, tagged: bool = False, verbose: bool = False)[source]

Bases: object

Clasification class. Holds information about what has been classified.

TemporalMap

class AMBER.TemporalMap(data: ndarray | None = None, size: int | None = None, period: int = 10, initial_lr: float = 0.1, initial_neighbourhood: int = 0, distance: str = 'euclidean', dtw_band: int | None = None, use_decay: bool = False, normalization: str = 'none', weights: str = 'random', context_weight: float = 0.5, context_influence: float = 0.5, random_seed: int | None = None)[source]

Bases: Map

Recurrent SOM that incorporates a temporal context vector.

calculate_bmu(pattern: ndarray) Tuple[source]

BMU search incorporating the temporal context vector.

Combines signal-space distance with context distance. After the BMU is found, updates the context vector using the winner’s weights.

Parameters:

pattern – 1-D input array

Returns:

(bmu_dist, bmu_pos, second_bmu_dist, second_bmu_pos)

classmethod load_classifier(filename: str = 'Model') TemporalMap[source]

Load a TemporalMap from a JSON file saved by save_classifier.

reinforce(training_data: ndarray, reinforcement: int = 0, extension: int = 1, compression: float = 0.5) None[source]

Reinforcement training; context is reset before each pass.

reset_context() None[source]

Reset the context vector to zero.

Call this between independent sequences (e.g. different subjects, different recordings) so that history from one sequence does not bleed into the next.

save_classifier(filename: str = 'Model') None[source]

Save map to JSON, including temporal parameters.

train(data: ndarray) None[source]

Train the map on a temporally ordered dataset.

Context is reset at the start of each training call so that separate calls to train() are independent.

TemporalAnalysis

class AMBER.TemporalAnalysis(classification)[source]

Bases: object

Temporal dynamics of a SOM classification result.

Parameters:

classification (Classification) – A completed Classification instance. The patterns in classification.classification_data are assumed to be ordered in time (as they would be for windowed biosignals or audio).

trajectory

Ordered BMU positions [(row_0, col_0), (row_1, col_1), …].

Type:

list of (int, int)

transition_matrix

Raw count of transitions; entry [i, j] = number of times the SOM moved from neuron i to neuron j between consecutive patterns. Neurons are linearised as index = row * map_size + col.

Type:

ndarray, shape (n_neurons, n_neurons)

transition_matrix_norm

Row-normalised transition matrix (transition probabilities).

Type:

ndarray, shape (n_neurons, n_neurons)

stability

Fraction of consecutive pattern pairs that share the same BMU.

Type:

float

mean_path_length

Mean Euclidean grid distance between consecutive BMU positions.

Type:

float

mean_chebyshev_jump

Mean Chebyshev (L∞) grid distance between consecutive BMU positions. Chebyshev distance counts diagonal steps as 1, matching the 8-neighbour topology of the SOM grid.

Type:

float

temporal_coherence

Fraction of consecutive pattern pairs whose BMUs are the same neuron or immediate neighbours (Chebyshev distance ≤ 1). A value of 1.0 means every step stays within the local neighbourhood; a standard SOM on non-stationary data typically achieves 0.4–0.6, while a well-tuned RSOM approaches 1.0 on smooth temporal sequences.

Type:

float

dwell_times()[source]

Return a dict mapping each BMU (row, col) to its mean consecutive dwell time (number of steps the SOM stays on that neuron).

most_frequent_transitions(top_k=10)[source]

Return the top-k most frequent transitions as a list of dicts.

Each dict has keys ‘from’ (row, col), ‘to’ (row, col), ‘count’.

summary() str[source]

Return a short human-readable summary string.

The summary is also emitted at INFO level via the standard logging framework so library users can control visibility with their own logging configuration.

Returns:

formatted summary string

FeatureExtractor

class AMBER.FeatureExtractor(fs=1.0, n_mfcc=13, mfcc_hop_length=512, sample_entropy_m=2, sample_entropy_r=None, spectral_rolloff_pct=0.85, eeg_bands=None)[source]

Bases: object

Extracts a flat feature vector from a 1-D signal window.

Usage:

fe = FeatureExtractor(fs=256)

# single window → 1-D feature vector
x = fe.extract(signal, features=['rms', 'spectral_entropy', 'hjorth_activity'])

# batch of windows → (n_windows, n_features) array ready for Map.train
X = fe.extract_batch(windows, features=['rms', 'zero_crossing_rate', 'alpha_power'])

Available features

Statistical (no fs needed):

mean, std, var, skewness, kurtosis, rms, peak_to_peak, zero_crossing_rate, line_length

Spectral (fs required):

spectral_power, dominant_frequency, spectral_entropy, spectral_centroid, spectral_rolloff, delta_power, theta_power, alpha_power, beta_power, gamma_power

Complexity (no fs needed):

hjorth_activity, hjorth_mobility, hjorth_complexity, sample_entropy

Librosa (fs + librosa required):

mfcc → produces n_mfcc values (mean of each coefficient over time)

COMPLEXITY = frozenset({'hjorth_activity', 'hjorth_complexity', 'hjorth_mobility', 'sample_entropy'})
LIBROSA_FEATURES = frozenset({'mfcc'})
SPECTRAL = frozenset({'alpha_power', 'beta_power', 'delta_power', 'dominant_frequency', 'gamma_power', 'spectral_centroid', 'spectral_entropy', 'spectral_power', 'spectral_rolloff', 'theta_power'})
STATISTICAL = frozenset({'kurtosis', 'line_length', 'mean', 'peak_to_peak', 'rms', 'skewness', 'std', 'var', 'zero_crossing_rate'})
extract(signal, features=None)[source]

Extract a 1-D feature vector from a single signal window.

Parameters:
  • signal – 1-D array-like

  • features – list of feature names; None → all statistical + complexity

Returns:

1-D numpy array

extract_batch(signals, features=None)[source]

Extract features from a 2-D batch of signal windows.

Parameters:
  • signals – (n_windows, window_length) array-like

  • features – list of feature names; None → all statistical + complexity

Returns:

(n_windows, n_features) numpy array

feature_names(features=None)[source]

Return feature names in the same order as extract().

Multi-valued features (mfcc) are expanded to individual names.

IterativeSOM

class AMBER.IterativeSOM(data, period, initial_lr, size_range=None, give_best=False, random_seed=None, validation_data=None)[source]

Bases: object

Trains multiple SOMs across a range of map sizes and optionally returns the best one.

static calculate_range(data, min_size=2, max_size=None)[source]

Returns a range of map sizes centred on the Vesanto recommendation.

Visualization

class AMBER.Visualization[source]

Bases: object

Static collection of plotting helpers for trained SOMs.

All methods are @staticmethod — no instance is needed:

Visualization.heat_map(classification)
Visualization.umatrix(classification)
static bar_chart(data, filename='bar_chart')[source]

Interactive bar chart of an arbitrary 1-D data array (Plotly).

Parameters:
  • data – array-like of values to plot

  • filename – Plotly filename / title (default 'bar_chart')

static characteristics_bargraph(map, row, column, labels=array([], dtype=float64), size_x=10, size_y=10, angle=45)[source]

Colour-coded bar chart of the weight vector for a single neuron.

Each bar corresponds to one input feature; bars are coloured with the tab20 colormap for easy visual discrimination.

Parameters:
  • map – a trained Map instance

  • row – row index of the neuron

  • column – column index of the neuron

  • labels – feature-name labels for the x-axis (optional)

  • size_x – figure width in inches (default 10)

  • size_y – figure height in inches (default 10)

  • angle – x-tick label rotation in degrees (default 45)

static characteristics_graph(map, row, column, labels=array([], dtype=float64), size_x=10, size_y=10, angle=45)[source]

Line plot of the weight vector for a single neuron.

Parameters:
  • map – a trained Map instance

  • row – row index of the neuron

  • column – column index of the neuron

  • labels – feature-name labels for the x-axis (optional)

  • size_x – figure width in inches (default 10)

  • size_y – figure height in inches (default 10)

  • angle – x-tick label rotation in degrees (default 45)

static codebook_vector(map, index=0, header='none', filename='codebook_vector')[source]

Annotated heatmap of a single codebook (weight) dimension across all neurons.

Displays the value of feature index for every neuron in the grid, useful for understanding how a particular input dimension is distributed across the map.

Parameters:
  • map – a trained Map instance

  • index – feature index to display (default 0)

  • header – plot title; 'none' suppresses the title

  • filename – Plotly filename (default 'codebook_vector')

static codebook_vectors(map, headers=array([], dtype=float64))[source]

Plot codebook_vector() for every input dimension of the map.

Parameters:
  • map – a trained Map instance

  • headers – feature names used as plot titles; defaults to 0, 1, …, D-1

static dwell_time_map(temporal_analysis, classification, cmap='Blues', figsize=(6, 5), title='Mean Dwell Time per Neuron')[source]

Heatmap showing how long the signal dwells on each BMU on average.

Parameters:
  • temporal_analysis – a TemporalAnalysis instance

  • classification – the matching Classification instance

  • cmap – matplotlib colormap

  • figsize – figure size in inches

  • title – plot title

static elevation_map(classification, filename='elevation_map')[source]

3-D surface plot of BMU activation counts (elevation = activation frequency).

Parameters:
  • classification – a completed Classification instance

  • filename – Plotly filename / title (default 'elevation_map')

static full_map_weights(map, labels=array([], dtype=float64), size_x=25, size_y=30, filename='full_map_weights')[source]

Grid of weight-vector line plots — one subplot per neuron.

Produces a map_size × map_size panel of weight profiles and saves it to disk as an image file.

Parameters:
  • map – a trained Map instance

  • labels – feature-name labels for the x-axis of each subplot

  • size_x – total figure width in inches (default 25)

  • size_y – total figure height in inches (default 30)

  • filename – output file path (no extension); saved via fig.savefig

static heat_map(classification, filename='heat_map', colorscale='Reds', cmax=0)[source]

Annotated heatmap of BMU activation counts across the SOM grid.

Parameters:
  • classification – a completed Classification instance

  • filename – Plotly filename / title (default 'heat_map')

  • colorscale – Plotly colorscale name (default 'Reds')

  • cmax – maximum value for the colour scale; 0 = auto-scale to data maximum

static hit_map(classification, labels, class_names=None, palette=None, figsize=(10, 9), title=None, filename=None)[source]

Hit map where cell size encodes sample count and colour encodes majority class.

Each neuron cell is drawn as a coloured square whose side length scales with sqrt(n / n_max), so high-load neurons appear larger and dead neurons (no samples) are shown as an empty grey background cell. A light-tinted background fills the full cell area with the majority-class colour, providing an additional visual cue.

Parameters:
  • classification – a completed Classification instance. Must have been created with tagged=True.

  • labels – 1-D array-like of integer class codes, one per sample.

  • class_names – list of human-readable class names in class-code order. Defaults to 'Class 0', 'Class 1', …

  • palette – list of matplotlib colour strings in class-code order. Defaults to the tab10 colormap.

  • figsize – figure size in inches (default (10, 9)).

  • title – figure suptitle. If None, a generic title is used.

  • filename – if given, save the figure to this path; otherwise plt.show() is called.

static neurons_per_num_activations_map(classification, filename='neurons_per_num_activations_map', save=False)[source]

Bar chart of the number of neurons activated exactly k times, for k = 0 … max.

Useful for diagnosing dead neurons (activated 0 times) and over-used neurons.

Parameters:
  • classification – a completed Classification instance

  • filename – Plotly filename / title

  • save – unused (reserved for future file-export support)

static trajectory(classification, temporal_analysis, background='activations', cmap_path='plasma', cmap_bg='YlOrRd', figsize=(7, 7), title='BMU Trajectory', random_seed=None)[source]

Plot the time-ordered sequence of BMU positions on the SOM grid.

The path is drawn as a colour-coded line (early = dark, late = bright) with arrows indicating direction. The background shows either the activation counts or the U-matrix.

Parameters:
  • classification – a completed Classification instance

  • temporal_analysis – the matching TemporalAnalysis instance

  • background – ‘activations’ or ‘umatrix’

  • cmap_path – matplotlib colormap for the trajectory line

  • cmap_bg – matplotlib colormap for the background heatmap

  • figsize – figure size in inches

  • title – plot title

  • random_seed – seed for the jitter RNG that slightly offsets overlapping trajectory points; pass an integer for a reproducible figure, None for a different jitter each call

static transition_matrix_plot(temporal_analysis, normalised=True, cmap='Blues', figsize=(8, 7), title='Transition Matrix')[source]

Heatmap of neuron-to-neuron transition frequencies.

Parameters:
  • temporal_analysis – a TemporalAnalysis instance

  • normalised – if True, shows row-normalised probabilities; if False, shows raw counts

  • cmap – matplotlib colormap

  • figsize – figure size in inches

  • title – plot title

static umatrix(classification, colorscale='binary')[source]

Display the U-matrix (unified distance matrix) of the trained map.

Each cell in the U-matrix encodes the mean distance between a neuron and its neighbours; dark regions indicate cluster boundaries.

Parameters:
  • classification – a completed Classification instance

  • colorscale – matplotlib colormap name (default 'binary')

static umatrix_labeled(classification, labels, class_names=None, palette=None, figsize=(8, 9), title=None, filename=None)[source]

U-matrix overlaid with majority-class markers for each neuron.

Combines topology (greyscale U-matrix background) with semantics (coloured circle markers showing the majority class and sample count of each active neuron). The legend is placed between the title and the axes so it never overlaps neuron markers.

Parameters:
  • classification – a completed Classification instance. Must have been created with tagged=True so that classification_map['labels'] contains integer class codes.

  • labels – 1-D array-like of integer class codes, one per sample, used to build the legend (values must match those stored in classification_map['labels']).

  • class_names – list of human-readable class names in class-code order. If None, names default to 'Class 0', 'Class 1', …

  • palette – list of matplotlib colour strings in class-code order. If None, the tab10 colormap is used.

  • figsize – figure size in inches (default (8, 9)).

  • title – figure suptitle. If None, a generic title is used.

  • filename – if given, save the figure to this path (PNG/PDF/…). If None, the figure is displayed with plt.show().

static weight_map_grid(som, classification, labels, class_names=None, palette=None, figsize=None, title=None, filename=None)[source]

Grid of weight-vector profiles coloured by majority class.

Produces a map_size × map_size panel of subplots. Each subplot shows the weight vector of one neuron as a line plot. The subplot background is tinted with the majority-class colour; dead neurons (no assigned samples) are shown with a neutral grey background. The neuron address [row, col] and sample count n=… are annotated inside each cell.

Parameters:
  • som – a trained Map instance.

  • classification – a completed Classification instance created with tagged=True.

  • labels – 1-D array-like of integer class codes, one per sample.

  • class_names – list of human-readable class names in class-code order. Defaults to 'Class 0', 'Class 1', …

  • palette – list of matplotlib colour strings in class-code order. Defaults to the tab10 colormap.

  • figsize – figure size in inches. Defaults to (2.4 * map_size, 1.9 * map_size).

  • title – figure suptitle. Defaults to a generic title.

  • filename – if given, save to this path; otherwise plt.show().

Distances

Signal-space distance functions for AMBER.

Two families are provided:

Signal distances — compare weight vectors to an input pattern; used for BMU search. Grid distances — compare 2-D neuron positions on the map grid; used for neighbourhood update.

Each signal distance exposes:
  • a scalar function foo_distance(a, b) for single pairs

  • a matrix function foo_distance_matrix(W, p) that returns a (rows, cols) array over the

    whole weight grid W shaped (rows, cols, dim)

Vectorised matrix functions are provided for all distances except DTW and cross-correlation, which require a per-neuron loop due to their sequential nature.

AMBER.distances.chebyshev_distance(a, b)[source]

L∞ distance (maximum absolute component difference).

AMBER.distances.chebyshev_distance_matrix(weights, pattern)[source]

(rows, cols) L∞ distances.

AMBER.distances.correlation_distance(a, b)[source]

1 - abs(Pearson correlation). Pure shape similarity; ignores mean and amplitude. Ideal for comparing waveform morphology across subjects or sessions.

AMBER.distances.correlation_distance_matrix(weights, pattern)[source]

(rows, cols) correlation distances. Vectorised.

AMBER.distances.cosine_distance(a, b)[source]

1 - cosine similarity. Amplitude-invariant; suited to spectral feature vectors.

AMBER.distances.cosine_distance_matrix(weights, pattern)[source]

(rows, cols) cosine distances. Vectorised over the full grid.

AMBER.distances.cross_correlation_distance(a, b)[source]

1 - peak of normalised cross-correlation. Shift-invariant similarity.

Suitable for periodic biosignals (ECG beats, EEG oscillations) where the pattern of interest may appear at different phases across windows.

Both inputs are L2-normalised before correlation. By the Cauchy-Schwarz inequality every lag of np.correlate(a_n, b_n, 'full') is bounded by the product of the partial L2-norms of the two sub-vectors, which are each ≤ 1, so max|xcorr| [0, 1] and the returned distance is in [0, 1].

Parameters:
  • a – 1-D array

  • b – 1-D array

Returns:

distance in [0, 1]; 0 means perfect match at some lag

AMBER.distances.cross_correlation_distance_matrix(weights, pattern)[source]

(rows, cols) cross-correlation distances. Requires a per-neuron loop.

AMBER.distances.dtw_distance(a, b, band=None)[source]

Dynamic Time Warping distance with optional Sakoe-Chiba band constraint.

Handles temporal misalignment between signals — the standard choice for biosignals (ECG, EEG) and audio where patterns may be stretched or shifted in time.

Parameters:
  • a – 1-D array, first signal

  • b – 1-D array, second signal

  • band – Sakoe-Chiba half-width in samples (None = unconstrained). Constraining the band greatly reduces O(n²) cost; a value of 10–20 % of signal length is a good default for biosignals.

Returns:

DTW distance (scalar)

AMBER.distances.dtw_distance_matrix(weights, pattern, band=None)[source]

(rows, cols) DTW distances. Requires a per-neuron loop.

AMBER.distances.euclidean_distance(a, b)[source]

L2 distance between two 1-D arrays.

AMBER.distances.euclidean_distance_matrix(weights, pattern)[source]

(rows, cols) L2 distances from every neuron weight to pattern.

AMBER.distances.grid_chebyshev(ids_matrix, bmu)[source]

Chebyshev distance from every grid position to bmu. Returns (rows, cols) array.

AMBER.distances.grid_euclidean(ids_matrix, bmu)[source]

Euclidean distance from every grid position to bmu. Returns (rows, cols) array.

AMBER.distances.manhattan_distance(a, b)[source]

L1 distance. More robust to spike artefacts than L2.

AMBER.distances.manhattan_distance_matrix(weights, pattern)[source]

(rows, cols) L1 distances.