IMF decomposition: TS2IMF (EMD / EEMD / VMD)
imfs.Rmd
# Minimal executable example
library(gmsp)
library(data.table)
#>
#> Attaching package: 'data.table'
#> The following object is masked from 'package:base':
#>
#> %notin%
t_vec <- seq(0, 5, by = 0.01)
dt_sig <- data.table(t = t_vec, s = sin(2 * pi * 2 * t_vec) + 0.3 * sin(2 * pi * 8 * t_vec))
imf_res <- TS2IMF(dt_sig, method = "vmd", K = 4, output = "IMF")
print(imf_res)
#> IMF Fo[Hz] BW[Hz] E[k]/Eo [%]
#> <char> <num> <num> <num>
#> 1: IMF1 0.8121344 0.48023152 1.479176
#> 2: IMF2 1.9518203 0.11210220 43.727802
#> 3: IMF3 2.0687453 0.08820797 27.534890
#> 4: IMF4 7.9992331 0.10765251 7.920870TS2IMF() decomposes a time series into Intrinsic
Mode Functions (IMFs) and a residue. A common
goal is to separate oscillatory components by scale / band and then
reconstruct a filtered signal by removing or keeping selected IMFs.
Canonical references: EMD (Huang et al., 1998), EEMD (Wu & Huang, 2009), VMD (Dragomiretskiy & Zosso, 2014).
What is an IMF?
In the EMD framework, a component is an IMF if it satisfies the classic definition:
- the number of zero crossings and extrema differ at most by 1, and
- the local mean of the upper and lower envelopes is approximately zero.
This enables a meaningful instantaneous frequency (via the Hilbert transform) for non-stationary signals.
Input and grouping
-
.x: one signal as adata.tablewith canonical columnstands.
Note: internally TS2IMF() regularizes
the time grid and rebuilds a time vector ts from 0. The
workflow requires t / s as the working column
names.
TS2IMF() is a worker and does not detect groups. For a
canonical TSL, group outside the helper:
Available engines
Parameter method selects one of three engines.
VMD (method = "vmd", default)
Calls VMDecomp::vmd(...). Returns a matrix
(
modes). The residue is defined as
EMD (method = "emd")
Calls EMD::emd(...) with boundary and
stop.rule controlling sifting. The output
AUX$imf and AUX$residue are taken as-is.
EEMD (method = "eemd")
Calls hht::EEMD(...) followed by
hht::EEMDCompile(...). Runs an ensemble with noise
(noise.amp, noise.type, trials).
Uses a tempdir() as a working folder and then compiles the
averaged IMFs.
Output
If output = NULL, TS2IMF() returns a list
with three elements.
| Element | Shape | Description |
|---|---|---|
TSW |
wide |
t, signal, IMF1..IMFk,
residue
|
TSL |
long | melt of TSW with columns t,
IMF, s
|
IMF |
metrics | per-IMF center frequency / bandwidth / relative energy |
If output is "TSW", "TSL" or
"IMF", only that component is returned.
Per-IMF metrics
For each IMF the code estimates the center frequency
Fo[Hz], the bandwidth BW[Hz], and the relative
energy E[k]/Eo [%]. The procedure is:
- apply a Hann window ,
- compute FFT with zero-padding to a power of 2,
- compute a power spectrum ,
- apply a −10 dB threshold relative to the maximum and compute
Fo/BWas moments of over “active” bins.
Reconstruction filters
Inside TS2IMF() a local helper
.applyIMFFilter() adds a reconstructed signal
signal.R when any of the following arguments is set.
imf.remove— ifcharacter, removes those columns (IMF1,IMF2, …); if numeric, positive values remove IMFs counted from the first mode, negative values remove IMFs counted from the last mode, and both selections are unioned. For example,c(1L, -1L, -2L)removesIMF1plus the last two IMFs. Zero, non-finite, and out-of-range numeric values are ignored.remove.Fo = c(f1, f2)— removes IMFs whose frequency interval lies entirely within .keep.Fo = c(f1, f2)— keeps only IMFs whose frequency interval lies entirely within .keep.Residue— ifTRUE,signal.Radds the residue on top of the kept IMFs.
Composing with AT2TS / VT2TS / DT2TS
In practice the typical pattern is:
- Start from a
TSL(e.g. output ofAT2TS(..., output = "TSL")). - Filter a specific
ID+OCID(e.g.ID == "DT" & OCID == "H1"). - Run
TS2IMF()on that slice, or inside adata.tablegrouped call. - Use
RES$TSL[IMF == "signal.R"]as the reconstructed (filtered) signal.
References
- Huang, N. E., Shen, Z., Long, S. R., Wu, M. C., Shih, H. H., Zheng, Q., Yen, N.-C., Tung, C. C., & Liu, H. H. (1998). The empirical mode decomposition and the Hilbert spectrum for nonlinear and non-stationary time series analysis. Proceedings of the Royal Society A, 454(1971), 903–995.
- Wu, Z., & Huang, N. E. (2009). Ensemble Empirical Mode Decomposition: A Noise-Assisted Data Analysis Method. Advances in Adaptive Data Analysis, 1(1), 1–41.
- Dragomiretskiy, K., & Zosso, D. (2014). Variational Mode Decomposition. IEEE Transactions on Signal Processing, 62(3), 531–544.