Skip to contents

Decomposes the series of a long table of records, grouped by record and quantity, with one method of the package, and returns homogeneous tables for all the methods.

Usage

decomposeTSL(TSL, method, control, by)

Arguments

TSL

Long table, a data frame or a data.table, with rows, unique column names and the columns t, the time in seconds; s, the sample; ID, the quantity, such as "AT", "VT" or "DT"; and OCID, the component. t and s are finite numbers; ID and OCID are character without NA. The other columns are metadata; they cannot take the names mode, iterations, converged, stopReason, innerStopReason, frequency or boundary. Also reserved for the selected method are realization for EEMD; realization and sign for CEEMD; phase for MaskedEMD; and direction for BEMD. TSL is not modified.

method

One of listDecompositions().

control

Named list of arguments of method, common to all the groups, except those the operation derives for each group: signal, samplingInterval, noise and noiseChannels. The ensembles take realizationCount in place of noise; decomposeNAMEMD takes noiseChannelCount and noiseRatio, a finite number \(\ge 0\), in place of noiseChannels. Controls in the units of the signal are rejected, because AT, VT and DT do not share units: the rule "pair" of decomposeMaskedEMD and any stopping$stopRule of decomposeSVMD other than "modeCount".

by

Character vector naming the metadata columns that identify a record, or character() for a single record.

Details

A group is a record and an ID; its OCID are the channels of the group and must share one time grid. Groups follow by ascending and the IDs "AT", "VT" and "DT" first, then the other IDs ascending; the OCID of a group ascend. The order of the rows of TSL does not intervene. A series needs two samples or more, a time cannot repeat within a series, and the metadata other than by must be constant within each record, ID and OCID.

The grid of a group is uniform when diff(t) equals the mean step \(\Delta t = (t_N - t_1)/(N - 1)\) under all.equal; it is then used unchanged, with samplingInterval \(\Delta t\). A grid that is not uniform is regularized with one warning per group: the step becomes \(1/F_s\), with \(F_s\) the smallest \(2^a 5^b\) not below \(1/\Delta t\); the grid is \(t_1 + k/F_s\), and each OCID is interpolated on it by stats::splinefun(method = "monoH.FC"). The table signal holds the series actually decomposed.

Scalar methods decompose each OCID separately with the same controls. The coupled methods decompose the matrix of the OCID of a group in ascending order, without standardization: decomposeBEMD needs exactly two OCID and decomposeMEMD at least two; their iterations, converged, stopReason and centers are common and repeat for every OCID. The ensembles draw realizationCount unit normal realizations for each OCID from the random stream of the caller, in the order group, OCID, realization. decomposeNAMEMD draws noiseChannelCount channels for each group and scales them by noiseRatio times \(\sqrt{\mathrm{mean}(s_c^2)}\), \(s_c\) the sample deviations of the OCID of the group; the noise channels give no rows. A control valid for one group and not for another, such as a center above the Nyquist frequency of a group, stops the operation. Units are not inferred, validated or converted; the metadata are carried to the output.

Channels are coupled within a record and an ID. The operation does not impose a kinematic relationship between separate AT, VT and DT groups. Equal mode indices across those groups do not establish corresponding physical contributions.

Value

A named list of data.table tables, each with the by columns, the other metadata, OCID and ID, followed by

signal

t, s: the series decomposed, on the output grid.

modes

mode, an integer from 1, t, s. Each OCID keeps its own number of modes, without padding; an OCID without modes has no rows.

residue, fitResidual, meanNoise

t, s, for the fields that the method returns.

diagnostics

mode, iterations, converged, when the method returns iterations.

termination

stopReason, and innerStopReason for decomposeIteratedMaskedEMD, when the method returns a termination. EEMD, CEEMD, MaskedEMD and BEMD carry the columns and rows of their native termination data frame, with the series keys added; the BEMD row repeats for both channels. In these rows mode identifies the next attempted extraction, not a returned mode; diagnostics continues to describe only returned modes.

centers, maskFrequencies

mode, frequency in Hz.

boundaries

boundary, frequency in Hz.

Rows follow the by columns, OCID, ID, mode or boundary, and t.

References

The regularization of the grid is adapted from .regularize and .rationalize of gmsp 0.8.0, copyright (c) 2026 Alejandro Verri Kozlowski, MIT License: gmsp starts from the smallest difference of the times and returns the grid from zero, whereas here the step starts from the mean and the grid keeps the origin \(t_1\). See the NOTICE file of the installed package.

Examples

Time <- seq(0, 9, length.out = 3000)
Signal <- sin(pi * Time) + sin(2 * pi * Time) + sin(6 * pi * Time) +
    0.5 * Time
# The same series under three IDs and three components.
TSL <- data.table::rbindlist(lapply(c("AT", "VT", "DT"), function(id) {
    data.table::rbindlist(lapply(c("H1", "H2", "UP"), function(ocid) {
        data.table::data.table(ID = id, OCID = ocid, t = Time, s = Signal)
    }))
}))
OUT <- decomposeTSL(TSL, method = "decomposeEMD",
                    control = list(sifting = list(stopRule = "doubleThreshold")),
                    by = character())
names(OUT)
#> [1] "signal"      "modes"       "residue"     "diagnostics" "termination"
OUT$termination
#>      OCID     ID          stopReason
#>    <char> <char>              <char>
#> 1:     H1     AT insufficientExtrema
#> 2:     H1     VT insufficientExtrema
#> 3:     H1     DT insufficientExtrema
#> 4:     H2     AT insufficientExtrema
#> 5:     H2     VT insufficientExtrema
#> 6:     H2     DT insufficientExtrema
#> 7:     UP     AT insufficientExtrema
#> 8:     UP     VT insufficientExtrema
#> 9:     UP     DT insufficientExtrema
head(OUT$modes)
#>      OCID     ID  mode           t          s
#>    <char> <char> <int>       <num>      <num>
#> 1:     H1     AT     1 0.000000000 -0.8149686
#> 2:     H1     AT     1 0.003001000 -0.7334793
#> 3:     H1     AT     1 0.006002001 -0.6524386
#> 4:     H1     AT     1 0.009003001 -0.5720312
#> 5:     H1     AT     1 0.012004001 -0.4924402
#> 6:     H1     AT     1 0.015005002 -0.4138474

# A coupled method: three channels of one record decomposed together.
SamplingInterval <- 1 / 1000
TimeV <- seq_len(1000) * SamplingInterval
Series <- cbind(cos(2 * pi * 2 * TimeV) + 0.25 * cos(2 * pi * 24 * TimeV) +
                    0.0625 * cos(2 * pi * 288 * TimeV),
                cos(2 * pi * 2 * TimeV), 0.25 * cos(2 * pi * 24 * TimeV))
Record <- data.table::data.table(ID = "AT",
                                 OCID = rep(c("H1", "H2", "UP"), each = 1000),
                                 t = rep(TimeV, 3), s = as.vector(Series))
Coupled <- decomposeTSL(Record, method = "decomposeMVMD",
                        control = list(initialCenters = (0:2) / (6 * SamplingInterval),
                                       alpha = 2000 * SamplingInterval^2 / (8 * pi^2),
                                       tau = 0.5, fixedZeroCenter = FALSE,
                                       tolerance = 1e-6, maxIterations = 98),
                        by = character())
Coupled$centers
#>      OCID     ID  mode  frequency
#>    <char> <char> <int>      <num>
#> 1:     H1     AT     1   2.000017
#> 2:     H1     AT     2  23.999987
#> 3:     H1     AT     3 287.943889
#> 4:     H2     AT     1   2.000017
#> 5:     H2     AT     2  23.999987
#> 6:     H2     AT     3 287.943889
#> 7:     UP     AT     1   2.000017
#> 8:     UP     AT     2  23.999987
#> 9:     UP     AT     3 287.943889