Custom feature extraction

Following examples shows how to compute custom features and save them in the transient feature database (trfdb) to visualize them in VisualAE.

The feature extraction can be live during acquisition. VisualAE will be notified, that a writer to the trfdb is active and waits for the features to be computed. Therefore, the computed features can be visualized in real time.

from pathlib import Path
from tempfile import gettempdir

import matplotlib.pyplot as plt
import numpy as np
import vallenae as vae

HERE = Path(__file__).parent if "__file__" in locals() else Path.cwd()
PRIDB = HERE / "bearing" / "bearing.pridb"
TRADB = HERE / "bearing" / "bearing_plain.tradb"
# TRFDB = HERE / "bearing" / "bearing.trfdb"
TRFDB_TMP = Path(gettempdir()) / "bearing_custom.trfdb"  # use a temp file for demo

Custom feature extraction algorithms

def rms(data: np.ndarray) -> float:
    """Root mean square (RMS)."""
    return np.sqrt(np.mean(data ** 2))


def crest_factor(data: np.ndarray) -> float:
    """Crest factor (ratio of peak amplitude and RMS)."""
    return np.max(np.abs(data)) / rms(data)


def spectral_peak_frequency(spectrum_: np.ndarray, samplerate: int) -> float:
    """
    Peak frequency in a spectrum.

    Args:
        spectrum: FFT amplitudes
        samplerate: Sample rate of the spectrum in Hz

    Returns:
        Peak frequency in Hz
    """
    def bin_to_hz(samplerate: int, samples: int, index: int):
        return 0.5 * samplerate * index / (samples - 1)

    peak_index = np.argmax(spectrum_)
    return bin_to_hz(samplerate, len(spectrum_), peak_index)

Open tradb and trfdb

tradb = vae.io.TraDatabase(TRADB)
trfdb = vae.io.TrfDatabase(TRFDB_TMP, mode="rwc")

Helper function to notify VisualAE, that the transient feature database is active/closed

def set_file_status(trfdb_: vae.io.TrfDatabase, status: int):
    """Notify VisualAE that trfdb is active/closed."""
    trfdb_.connection().execute(
        f"UPDATE trf_globalinfo SET Value = {status} WHERE Key == 'FileStatus'"
    )

Read tra records, compute features and save to trfdb

The vallenae.io.TraDatabase.listen method will read the tradb row by row and can be used during acquisition. Only if the acquisition is closed and no new records are available, the function returns.

set_file_status(trfdb, 2)  # 2 = active

for tra in tradb.listen(existing=True, wait=False):
    spectrum = np.fft.rfft(tra.data)
    features = vae.io.FeatureRecord(
        trai=tra.trai,
        features={
            "RMS": rms(tra.data),
            "CrestFactor": crest_factor(tra.data),
            "SpectralPeakFreq": spectral_peak_frequency(spectrum, tra.samplerate),
        }
    )
    trfdb.write(features)

set_file_status(trfdb, 0)  # 0 = closed

Write field infos to trfdb

Field infos can be written with vallenae.io.TrfDatabase.write_fieldinfo:

trfdb.write_fieldinfo("RMS", {"Unit": "[V]", "LongName": "Root mean square"})
trfdb.write_fieldinfo("CrestFactor", {"Unit": "[]", "LongName": "Crest factor"})
trfdb.write_fieldinfo("SpectralPeakFreq", {"Unit": "[Hz]", "LongName": "Spectral peak frequency"})

Read results from trfdb

df_trfdb = trfdb.read()
print(df_trfdb)
Trf:   0%|          | 0/490 [00:00<?, ?it/s]
Trf: 100%|██████████| 490/490 [00:00<00:00, 1920756.04it/s]
           RMS  CrestFactor  SpectralPeakFreq
trai
1     0.000129     3.684550           63800.0
2     0.000134     3.843248           65500.0
3     0.000108     3.906766           58500.0
4     0.000115     3.876217           58000.0
5     0.000106     3.548410           72000.0
...        ...          ...               ...
486   0.000006     3.624268          162900.0
487   0.000006     3.486689          250000.0
488   0.000006     3.530853          164100.0
489   0.000006     4.059815          174000.0
490   0.000006     3.545406          164700.0

[490 rows x 3 columns]

Plot AE features and custom features

Read pridb and join it with trfdb:

with vae.io.PriDatabase(PRIDB) as pridb:
    df_pridb = pridb.read_hits()

df_combined = df_pridb.join(df_trfdb, on="trai", how="left")
print(df_combined)
Hits:   0%|          | 0/490 [00:00<?, ?it/s]
Hits: 100%|██████████| 490/490 [00:00<00:00, 100849.35it/s]
        time  channel  param_id  ...       RMS  CrestFactor  SpectralPeakFreq
set_id                           ...
6       0.00        1         2  ...  0.000129     3.684550           63800.0
8       0.01        1         2  ...  0.000134     3.843248           65500.0
10      0.02        1         2  ...  0.000108     3.906766           58500.0
12      0.03        1         2  ...  0.000115     3.876217           58000.0
14      0.04        1         2  ...  0.000106     3.548410           72000.0
...      ...      ...       ...  ...       ...          ...               ...
976     4.85        1         2  ...  0.000006     3.624268          162900.0
978     4.86        1         2  ...  0.000006     3.486689          250000.0
980     4.87        1         2  ...  0.000006     3.530853          164100.0
982     4.88        1         2  ...  0.000006     4.059815          174000.0
984     4.89        1         2  ...  0.000006     3.545406          164700.0

[490 rows x 15 columns]

Plot joined features from pridb and trfdb

features = [
    # from pridb
    "amplitude",
    "energy",
    "counts",
    # from trfdb - custom
    "RMS",
    "CrestFactor",
    "SpectralPeakFreq",
]
df_combined.plot(
    x="time",
    y=features,
    xlabel="Time [s]",
    title=features,
    legend=False,
    subplots=True,
    figsize=(8, 10),
)
plt.suptitle("AE Features from pridb and custom features from trfdb")
plt.tight_layout()
plt.show()
AE Features from pridb and custom features from trfdb, amplitude, energy, counts, RMS, CrestFactor, SpectralPeakFreq

Display custom features in VisualAE

../_images/vae_custom_features.png

Total running time of the script: (0 minutes 0.915 seconds)

Gallery generated by Sphinx-Gallery