PFS API Reference#

Complete API reference for NeurEco Parametric Frequency Sweep (PFS) models.

Import#

from NeurEco import NeurEcoFrequential as freq

PFS#

class freq.PFS

Parametric Frequency Sweep model for complex-valued frequency response prediction.

File extension: .efnn

Constructor#

model = freq.PFS(dll_path=None)

Parameters:

  • dll_path (str, optional) — Path to NeurEco binaries

Methods#

build#

status = model.build(config)

Train the PFS model.

Parameters:

  • config (PFSBuildConfig) — Build configuration

Returns: int — Status code (0 = success)

evaluate#

outputs = model.evaluate(inputs, vec=None)

Run inference on input data.

Parameters:

  • inputs (ndarray or list) — Input data, shape (n_samples, n_inputs). First column must be frequency.

  • vec (ndarray, optional) — Custom weights

Returns: ndarray — Complex-valued predictions, dtype complex128

Warning

The first column of inputs must always be the frequency, even when evaluating at a single frequency point.

compute_error#

error = model.compute_error(predictions, targets)

Compute L2 relative error for complex-valued data.

Parameters:

  • predictions (ndarray) — Model predictions (complex)

  • targets (ndarray) — Ground truth (complex)

Returns: float — L2 relative error

load / save#

model.load(path)
model.save(path)

Load or save model.

Parameters:

  • path (str) — File path

Returns: int — Status code

get_input_count / get_output_count#

n_inputs = model.get_input_count()
n_outputs = model.get_output_count()

Get number of input and output features.

Returns: int

get_denominator_size#

denom_size = model.get_denominator_size()

Get the denominator size of the rational approximation.

Returns: int

The denominator size indicates model complexity. Larger values can capture more complex frequency behavior (more poles/zeros) but increase computation time.

perform_input_sweep#

model.perform_input_sweep(
    input_feature,
    input_id,
    input_interval,
    output_id,
    n_points=100,
    show=True,
    save_path=None
)

Visualize how one input affects the output.

Parameters:

  • input_feature (ndarray) — Reference input sample (1D)

  • input_id (int) — Index of input to sweep

  • input_interval (list) — [min, max] range

  • output_id (int) — Output to plot

  • n_points (int) — Number of sweep points

  • show (bool) — Display plot

  • save_path (str) — Path to save figure

export_fmu#

status = model.export_fmu(path)

Export to FMU format.

Parameters:

  • path (str) — Output .fmu file path

Returns: int — Status code

Note

Requires NeurEco Embed PFS license.

get_number_of_networks_from_checkpoint#

n = model.get_number_of_networks_from_checkpoint(path)

Get number of models saved in a checkpoint.

Parameters:

  • path (str) — Checkpoint path

Returns: int — Number of checkpointed models

load_model_from_checkpoint#

model.load_model_from_checkpoint(path, model_index)

Load a specific model from checkpoint.

Parameters:

  • path (str) — Checkpoint path

  • model_index (int) — Model index (0-based)

The build log and the GUI number checkpoints from 1: “Checkpoint N” there is model_index N - 1 here.

get_weights / set_weights#

weights = model.get_weights()
model.set_weights(weights)

Get or set model weights.

delete#

model.delete()

Free native memory. Always call when done.

PFSBuildConfig#

config = freq.PFSBuildConfig(
    # Required
    input_data,
    output_data,
    # Optional
    validation_input_data=None,
    validation_output_data=None,
    test_input_data=None,
    test_output_data=None,
    valid_percentage=33.33,
    write_model_to="model.efnn",
    checkpoint_address="ckpt.checkpoint",
    reduced_space_dimension=5,
    min_enrichment_steps=10,
    max_enrichment_steps=200,
    unsuccessful_enrichment_steps=4,
    enrichment_rate=0.2,
)

Parameters:

Parameter

Default

Description

input_data

(required)

Training inputs, shape (n_samples, n_inputs). First column = frequency.

output_data

(required)

Training outputs, shape (n_samples, n_outputs), dtype complex128

validation_input_data

None

Validation inputs

validation_output_data

None

Validation outputs

test_input_data

None

Test inputs

test_output_data

None

Test outputs

valid_percentage

33.33

Validation split percentage (1-50)

write_model_to

"model.efnn"

Path to save trained model

checkpoint_address

"ckpt.checkpoint"

Path for checkpoints

reduced_space_dimension

5

Dimension of compressed output space

min_enrichment_steps

10

Minimum enrichment iterations

max_enrichment_steps

200

Maximum enrichment iterations

unsuccessful_enrichment_steps

4

Failures before early stopping

enrichment_rate

0.2

Parameter addition rate (0 < rate <= 1)

Data Format#

Input Data#

  • Shape: (n_samples, n_inputs) where n_inputs >= 2

  • Type: float64

  • First column must be frequency

# Example: frequency + 3 design parameters
inputs = np.zeros((n_samples, 4), dtype=np.float64)
inputs[:, 0] = frequencies     # Column 0: frequency (REQUIRED)
inputs[:, 1] = param1_values   # Column 1: parameter 1
inputs[:, 2] = param2_values   # Column 2: parameter 2
inputs[:, 3] = param3_values   # Column 3: parameter 3

Output Data#

  • Shape: (n_samples, n_outputs)

  • Type: complex128

outputs = np.zeros((n_samples, 2), dtype=np.complex128)
outputs[:, 0] = complex_response_1
outputs[:, 1] = complex_response_2

Normalization#

PFS performs automatic normalization:

Inputs (per feature):

\[x_{norm} = \frac{x - \min(x)}{\max(x) - \min(x)}\]

Outputs (global):

\[y_{norm} = \frac{y}{\max(|y|)}\]

Example Usage#

Basic Usage#

from NeurEco import NeurEcoFrequential as freq
import numpy as np

# Load data
x_train = np.load('inputs_train.npy')   # (n_samples, n_inputs), float64
y_train = np.load('targets_train.npy')  # (n_samples, n_outputs), complex128

# Build
model = freq.PFS()
config = freq.PFSBuildConfig(
    input_data=x_train,
    output_data=y_train,
    write_model_to="./pfs_model.efnn"
)
model.build(config)

# Evaluate
predictions = model.evaluate(x_test)
error = model.compute_error(predictions, y_test)
print(f"L2 error: {100*error:.2f}%")

# Model info
print(f"Denominator size: {model.get_denominator_size()}")

model.delete()

Exploring Checkpoints#

model = freq.PFS()

# Get checkpoint info
n_models = model.get_number_of_networks_from_checkpoint("./pfs_checkpoint")

# Find best accuracy/complexity trade-off
for i in range(n_models):
    model.load_model_from_checkpoint("./pfs_checkpoint", i)
    outputs = model.evaluate(x_test)
    error = model.compute_error(outputs, y_test)
    denom = model.get_denominator_size()
    print(f"Model {i}: error={100*error:.2f}%, denom_size={denom}")

Visualizing Frequency Response#

import matplotlib.pyplot as plt

# Evaluate over frequency range
frequencies = np.linspace(1, 500, 200)
param_value = 0.05

# Remember: first column is always frequency
inputs = np.column_stack([frequencies, np.full(200, param_value)])
outputs = model.evaluate(inputs)

# Plot magnitude (dB)
magnitude_db = 20 * np.log10(np.abs(outputs[:, 0]))
plt.plot(frequencies, magnitude_db)
plt.xlabel("Frequency (Hz)")
plt.ylabel("Magnitude (dB)")
plt.grid(True)
plt.show()

# Plot phase
phase_deg = np.angle(outputs[:, 0], deg=True)
plt.plot(frequencies, phase_deg)
plt.xlabel("Frequency (Hz)")
plt.ylabel("Phase (degrees)")
plt.grid(True)
plt.show()

Single-Point Evaluation#

Even when evaluating at a single point, the frequency column must be present:

# Single frequency evaluation - frequency column required!
single_input = np.array([[100.0, 0.5, 1.2]])  # [freq, param1, param2]
single_output = model.evaluate(single_input)

print(f"Response at 100 Hz: {single_output[0, 0]}")
print(f"Magnitude: {np.abs(single_output[0, 0]):.4f}")
print(f"Phase: {np.angle(single_output[0, 0], deg=True):.2f} degrees")