{
  "schema_version": 2,
  "purpose": "numerical teaching animations; not benchmark evidence",
  "source_baseline": "c209d81fc9f9624fddf04c922c091bc86c820b60",
  "render_environments": [
    {
      "python_version": "3.12.14",
      "dependencies": {
        "numpy": "2.3.5",
        "scipy": "1.17.0",
        "statsmodels": "0.15.0",
        "matplotlib": "3.10.8",
        "Pillow": "12.3.0",
        "PyWavelets": "1.10.0",
        "EMD-signal": "1.10.0",
        "vmdpy": "0.2",
        "PySDKit": "0.5.0"
      }
    },
    {
      "python_version": "3.11.3",
      "dependencies": {
        "numpy": "2.4.6",
        "scipy": "1.17.1",
        "statsmodels": "0.15.0",
        "matplotlib": "3.11.2",
        "Pillow": "13.0.0",
        "PyWavelets": "1.9.0",
        "EMD-signal": "1.10.0",
        "vmdpy": "0.2",
        "PySDKit": "0.5.0"
      }
    }
  ],
  "method_count": 31,
  "source_hashes": {
    "scripts/generate_method_animations.py": "f62989af55a7e48495c24afcfee31751d3785e5f78bb4b900bef23a429deaa84",
    "scripts/method_animations/common.py": "73ad7e8b4e5b67f87d13e59adab2c93e983fe1aaf06ee627d22cb7c7e696016a",
    "scripts/method_animations/neural.py": "fc1c2a73490391f0f863ede52e38f12924cc1fec572b7188356a2308216716e6",
    "src/detime/backends.py": "7432dcf59e382580dfb32f1f57e61ff71a30567c049b35243e24e3644523eda6",
    "src/detime/core.py": "d95b348cd8b16b56d18840965579c947a11628d969dd6c32c4af7723f5a027f4",
    "src/detime/methods/neural_blocks/neural_block_portfolio.py": "2aab635b9927d1d42bbcd8e0b4f37cb9fcdcf85cbd0331b5011621b495c4acfa",
    "src/detime/registry.py": "e934ffca17880cefe5add728aa497e63ea811d7ae43abec1ea498de718094066",
    "src/detime/methods/neural_blocks/forecasting_blocks.py": "8404a89cab00a5443f75aae2b168b55218485fbb256f7723250f9470637ccb02",
    "scripts/method_animations/adaptive.py": "7d728d88b4ba1a8dd82890c7a6b017d542728b50dc477c281e9bbfcbae164a1d",
    "src/detime/methods/ceemdan.py": "3afa048be78ff8bf1671a3f80412a1e717a8574ef85a8f9a2aea5354e605c694",
    "src/detime/methods/emd.py": "42eb21caed63d31775cbe060a2c4367b1cb8a17d978e3c65c957062c1ef4c027",
    "native/src/gabor.cpp": "705f5c9465d1639be25bdfed903c8518748a1dbfe3d6cf883ea2438e41db6384",
    "src/detime/methods/gabor_cluster.py": "e8836ac9567ada7a8a7edb3cb66b63916d721ee1e554e282987c177d2eb3e2e7",
    "src/detime/methods/neural_blocks/leddam_block.py": "f357dc97c6ce1303f9c22002966371bfabc158a4316ae050fa28f55967d9bdd2",
    "native/src/ma_baseline.cpp": "752b3dfc9bea7353510ce5f7d4104d38ea6da45879af4402f7bee4618774dbc6",
    "scripts/method_animations/classical.py": "8a8a9ef82936f0aa5b1c5775c6c0158c3b48d3bc7dca1de691b83d95e5c23ba3",
    "src/detime/methods/ma_baseline.py": "1197a6fa5dd7f3a807f603e331986d2b75ff87962f54314521e3e149d5241d54",
    "src/detime/methods/memd.py": "e6eb06c058644f123495d3593a804b40e677f6a5bfc2f2e289cb6c3e11d6e022",
    "src/detime/methods/mvmd.py": "3e66ea12f131795eeb5ebbb24bd6affe7bfc104ac94ef7d8cdeaff6073413fd7",
    "native/src/mssa.cpp": "4aaea22b4d2dea62dc6dd942d2e116f81a646c95e3f4f610c58f79302e69da2b",
    "src/detime/methods/mssa.py": "ada7362bacc75c18fe034fd4d4e08f279b9887ea21944b667b37d4cc27571d51",
    "src/detime/methods/utils.py": "6963d1ecdf76f1920671a262d125f0d822ae620b1e532849a002be1b7b36e7fd",
    "src/detime/methods/stl.py": "bb9db3808691490849d06b6eff3f1d6083b6d79fa4d0ea526201e6cec11bdd4d",
    "src/detime/methods/neural_blocks/learned_priors.py": "af5a1d6b744e01a46358847aa05e156e92859d5f58334b0bc6a74d3169d2f2f0",
    "native/src/ssa.cpp": "9ed883b360325878d3bc7c087be5396b8052001fe9a8450f871929267b44ba08",
    "src/detime/methods/ssa.py": "ccb7b7d19fb9bdacedb12f8241f0ea0fc233edd498444a008b6040e21b4faac9",
    "native/src/std.cpp": "5d5fddc1b7267985d73336386b9a34834b688eab60266430669b4a049c59ad4c",
    "src/detime/methods/std.py": "7d72be4a4bff8c15f3723eaf1198d55b6863c517caa592690a5858f3e30f3578",
    "native/src/vmd.cpp": "27b730744b4c17b2b0cfa4d2c4c0d29798d335294a71fb6a7a3e077e3012041b",
    "src/detime/methods/vmd.py": "249bdc7e67595c7f556d32dd70c64e6f8ee7bd7a0e6c3b0277a8010fc1f0cf67",
    "src/detime/methods/wavelet.py": "a2a416a768bb7e2ac516e14b5f8a57d6641f40068890b91dc0c1a5db780779a0",
    "src/detime/methods/neural_blocks/xpatch_block.py": "4630da9874dd75fbc23dc688b29124ec6944d2dc9f56a200929a36ace4919ffc"
  },
  "methods": [
    {
      "method": "AMD_BLOCK",
      "slug": "amd-block",
      "title": "AMD block: average smoothing scales",
      "summary": "Several fixed moving-average windows are evaluated on the prefix, then averaged with equal weights. The next step uses phase-wise means of the detrended prefix. The frames expose those buckets, their cumulative averages and the repeated seasonal output. The source architecture's adaptive weighting is represented here by a nonlearned, equal-weight average of fixed smoothers.",
      "steps": [
        {
          "title": "Compute several smooth trends",
          "text": "Several fixed moving-average windows are evaluated on the prefix, then averaged with equal weights."
        },
        {
          "title": "Average equal seasonal phases",
          "text": "Subtract the trend on the fitting prefix. Group samples by index modulo the specified period and average each phase bucket."
        },
        {
          "title": "Repeat the phase template",
          "text": "Tile the fitted phase means over the record. The suffix does not update the template in this prefix configuration."
        },
        {
          "title": "Inspect the derived residual",
          "text": "Compute input minus the implemented trend and seasonal estimate. This residual is part of a retrospective decomposition, not a forecast score."
        }
      ],
      "parameters": [
        {
          "name": "multiscale_windows",
          "effect": "Sets the windows whose trends are equally averaged; this standalone operator does not learn scale weights."
        },
        {
          "name": "primary_period",
          "effect": "Defines phase buckets in samples; the fitting prefix must contain enough cycles for an interpretable average."
        },
        {
          "name": "fit_scope / train_fraction",
          "effect": "Explicitly selects a two-thirds prefix in this example; it does not create a rolling forecasting evaluation."
        }
      ],
      "cautions": [
        "The source architecture's adaptive weighting is represented here by a nonlearned, equal-weight average of fixed smoothers.",
        "Prefix fitting is a fixed fitting convention. It does not certify rolling causality or an out-of-sample prediction experiment.",
        "A repeated phase template assumes that the fitted seasonal shape remains useful over the displayed suffix.",
        "The residual is derived by subtraction; exact reconstruction does not validate the scientific interpretation of either component."
      ],
      "references": [
        {
          "title": "Implemented DeTime operator",
          "url": "https://github.com/systems-mechanobiology/DeTime/blob/main/src/detime/methods/neural_blocks/neural_block_portfolio.py"
        },
        {
          "title": "Hu et al. (2024), Adaptive Multi-Scale Decomposition Framework for Time Series Forecasting",
          "url": "https://arxiv.org/abs/2406.03751"
        }
      ],
      "trace_kind": "computed_operator_trace",
      "trace_note": "Intermediate arrays are computed with the implemented operator helpers. The final trend, season and residual are checked against public decompose(). The animation explains this standalone experimental block; its source architecture is cited for provenance.",
      "input_note": "Deterministic synthetic teaching signal; not a benchmark.",
      "example_config": {
        "method": "AMD_BLOCK",
        "params": {
          "primary_period": 24,
          "fit_scope": "prefix",
          "train_fraction": 0.6666666666666666,
          "multiscale_windows": [
            13,
            25,
            49
          ]
        },
        "backend": "python"
      },
      "checks": {
        "public_method_executed": true,
        "method_output_max_abs_errors": {
          "trend": 0.0,
          "season": 0.0,
          "residual": 0.0
        },
        "reconstruction_max_abs_error": 4.440892098500626e-16,
        "validation_scope": "One deterministic teaching input; no benchmark claim.",
        "fit_end": 96
      },
      "source_files": [
        "src/detime/methods/neural_blocks/neural_block_portfolio.py"
      ],
      "frames": 32,
      "duration_ms": 12050,
      "poster_frame": 15,
      "width": 1280,
      "height": 820,
      "artifacts": {
        "gif": {
          "file": "amd-block.gif",
          "bytes": 354512,
          "sha256": "863fda873f8c64fcb72890b44d39195b2c1cb1ca5ac11eaa0320b33699ee2296"
        },
        "poster": {
          "file": "amd-block.png",
          "bytes": 130403,
          "sha256": "7023b168469580b3a8dd11aa67f7bda927b5ad2863d6787e97408e868dce8410"
        },
        "data": {
          "file": "amd-block.npz",
          "bytes": 9503,
          "sha256": "1f0e56a4e44b4342d36e4d8f744ba48ae66d36cb7db3af5d78e61d0900fe9cb0"
        }
      },
      "source_arrays": {
        "observed": [
          144
        ],
        "trend_candidates": [
          3,
          144
        ],
        "trend": [
          144
        ],
        "detrended": [
          144
        ],
        "prefix_phase_matrix": [
          4,
          24
        ],
        "raw_template": [
          144
        ],
        "season": [
          144
        ],
        "residual": [
          144
        ],
        "fit_end": []
      },
      "render_provenance": {
        "python_version": "3.12.14",
        "dependencies": {
          "numpy": "2.3.5",
          "scipy": "1.17.0",
          "statsmodels": "0.15.0",
          "matplotlib": "3.10.8",
          "Pillow": "12.3.0",
          "PyWavelets": "1.10.0",
          "EMD-signal": "1.10.0",
          "vmdpy": "0.2",
          "PySDKit": "0.5.0"
        },
        "source_hashes": {
          "scripts/generate_method_animations.py": "f62989af55a7e48495c24afcfee31751d3785e5f78bb4b900bef23a429deaa84",
          "scripts/method_animations/common.py": "73ad7e8b4e5b67f87d13e59adab2c93e983fe1aaf06ee627d22cb7c7e696016a",
          "scripts/method_animations/neural.py": "fc1c2a73490391f0f863ede52e38f12924cc1fec572b7188356a2308216716e6",
          "src/detime/backends.py": "7432dcf59e382580dfb32f1f57e61ff71a30567c049b35243e24e3644523eda6",
          "src/detime/core.py": "d95b348cd8b16b56d18840965579c947a11628d969dd6c32c4af7723f5a027f4",
          "src/detime/methods/neural_blocks/neural_block_portfolio.py": "2aab635b9927d1d42bbcd8e0b4f37cb9fcdcf85cbd0331b5011621b495c4acfa",
          "src/detime/registry.py": "e934ffca17880cefe5add728aa497e63ea811d7ae43abec1ea498de718094066"
        }
      }
    },
    {
      "method": "AUTOFORMER_BLOCK",
      "slug": "autoformer-block",
      "title": "Autoformer block: moving-average split",
      "summary": "The implemented operator replaces each sample with a centered local mean and assigns the input minus that mean to a second stream. Edge replication maintains the original length. AUTOFORMER_BLOCK, DLINEAR_BLOCK and MOVING_AVERAGE_DECOMPOSITION_BLOCK call the same numeric implementation at equal settings; their method identifiers record provenance. The animation therefore shows the same numerical mechanism for all three, with a separate named asset for each entry.",
      "steps": [
        {
          "title": "Specify the filter",
          "text": "Inspect the normalized filter weights and the replicated-edge input window used for a local mean."
        },
        {
          "title": "Move along the series",
          "text": "At each sample, multiply the local values by the same fixed kernel and sum them to form the trend."
        },
        {
          "title": "Subtract the trend",
          "text": "Compute the nontrend stream as the input minus the smoothed trend, sample by sample."
        },
        {
          "title": "Inspect the output contract",
          "text": "The two streams already reconstruct the input, leaving a derived residual of zero up to arithmetic precision."
        }
      ],
      "parameters": [
        {
          "name": "moving_avg",
          "effect": "Sets the smoothing window. Larger windows average more samples; even requests become odd windows."
        },
        {
          "name": "window",
          "effect": "Acts as an alias after moving_avg. If neither is supplied, period hints are checked before the default window of 25."
        },
        {
          "name": "primary_period",
          "effect": "Can supply a window hint; this operator does not fit a periodic template."
        }
      ],
      "cautions": [
        "The three registered moving-average block names are numerical aliases at equal configuration.",
        "This is the decomposition head. It does not execute Autoformer attention or DLinear's fitted forecasting projections.",
        "The nontrend stream can contain noise and transients. Here season = input - trend, so the derived residual is zero by construction.",
        "The centered filter uses future neighbours relative to an interior sample in a full-record analysis."
      ],
      "references": [
        {
          "title": "Implemented DeTime operator",
          "url": "https://github.com/systems-mechanobiology/DeTime/blob/main/src/detime/methods/neural_blocks/forecasting_blocks.py"
        },
        {
          "title": "Wu et al. (2021), Autoformer: Decomposition Transformers with Auto-Correlation for Long-Term Series Forecasting",
          "url": "https://proceedings.neurips.cc/paper_files/paper/2021/hash/bcc0d400288793e8bdcd7c19a8ac0c2b-Abstract.html"
        }
      ],
      "trace_kind": "computed_operator_trace",
      "trace_note": "Intermediate arrays are computed with the implemented operator helpers. The final trend, season and residual are checked against public decompose(). The animation explains this standalone experimental block; its source architecture is cited for provenance.",
      "input_note": "Deterministic synthetic teaching signal; not a benchmark.",
      "example_config": {
        "method": "AUTOFORMER_BLOCK",
        "params": {
          "moving_avg": 25
        },
        "backend": "python"
      },
      "checks": {
        "public_method_executed": true,
        "method_output_max_abs_errors": {
          "trend": 0.0,
          "season": 0.0,
          "residual": 0.0
        },
        "reconstruction_max_abs_error": 1.1102230246251565e-16,
        "validation_scope": "One deterministic teaching input; no benchmark claim.",
        "kernel_sum": 1.0,
        "shared_operator_identifiers": [
          "AUTOFORMER_BLOCK",
          "DLINEAR_BLOCK",
          "MOVING_AVERAGE_DECOMPOSITION_BLOCK"
        ]
      },
      "source_files": [
        "src/detime/methods/neural_blocks/forecasting_blocks.py"
      ],
      "frames": 32,
      "duration_ms": 12050,
      "poster_frame": 15,
      "width": 1280,
      "height": 820,
      "artifacts": {
        "gif": {
          "file": "autoformer-block.gif",
          "bytes": 315925,
          "sha256": "48c3e58a33d85ac5a7757f203933ecf33e2b4da20d9e4a5c26d21dd1ceff5269"
        },
        "poster": {
          "file": "autoformer-block.png",
          "bytes": 123953,
          "sha256": "2303c0c749e218e9fa95a7710459f8be4237a1730b34901e30108397f77bb5f1"
        },
        "data": {
          "file": "autoformer-block.npz",
          "bytes": 4444,
          "sha256": "1eb3ce696b5a4ad419debcc65bbac0a64a7a9d0268391442a62414af844b6f2e"
        }
      },
      "source_arrays": {
        "observed": [
          144
        ],
        "kernel": [
          25
        ],
        "trend": [
          144
        ],
        "season": [
          144
        ],
        "residual": [
          144
        ]
      },
      "render_provenance": {
        "python_version": "3.12.14",
        "dependencies": {
          "numpy": "2.3.5",
          "scipy": "1.17.0",
          "statsmodels": "0.15.0",
          "matplotlib": "3.10.8",
          "Pillow": "12.3.0",
          "PyWavelets": "1.10.0",
          "EMD-signal": "1.10.0",
          "vmdpy": "0.2",
          "PySDKit": "0.5.0"
        },
        "source_hashes": {
          "scripts/generate_method_animations.py": "f62989af55a7e48495c24afcfee31751d3785e5f78bb4b900bef23a429deaa84",
          "scripts/method_animations/common.py": "73ad7e8b4e5b67f87d13e59adab2c93e983fe1aaf06ee627d22cb7c7e696016a",
          "scripts/method_animations/neural.py": "fc1c2a73490391f0f863ede52e38f12924cc1fec572b7188356a2308216716e6",
          "src/detime/backends.py": "7432dcf59e382580dfb32f1f57e61ff71a30567c049b35243e24e3644523eda6",
          "src/detime/core.py": "d95b348cd8b16b56d18840965579c947a11628d969dd6c32c4af7723f5a027f4",
          "src/detime/methods/neural_blocks/forecasting_blocks.py": "8404a89cab00a5443f75aae2b168b55218485fbb256f7723250f9470637ccb02",
          "src/detime/registry.py": "e934ffca17880cefe5add728aa497e63ea811d7ae43abec1ea498de718094066"
        }
      }
    },
    {
      "method": "CEEMDAN",
      "slug": "ceemdan",
      "title": "CEEMDAN: ensemble averaging with adaptive noise",
      "summary": "CEEMDAN repeatedly estimates components from perturbed signals and updates a shared residual. The noise modes and ensemble averages are algorithmic inputs, not decorative uncertainty bands.",
      "steps": [
        {
          "title": "Generate perturbations",
          "text": "Normalize the input, draw seeded noise, and decompose the noise realizations."
        },
        {
          "title": "Average first IMFs",
          "text": "Apply EMD to each perturbed input and average its first IMF."
        },
        {
          "title": "Update adaptively",
          "text": "Perturb the current residual with the next noise mode, average local means, and extract the next cIMF."
        },
        {
          "title": "Retain the residue",
          "text": "Continue until the stopping criterion, then retain the remaining signal for additive reconstruction."
        }
      ],
      "parameters": [
        {
          "name": "trials",
          "effect": "Number of ensemble members; this small animation uses 8, while DeTime's default is 100."
        },
        {
          "name": "epsilon",
          "effect": "Controls the perturbation scale; this visibility-oriented trace uses 0.04, not the default 0.005."
        },
        {
          "name": "seed and n_jobs",
          "effect": "The trace uses seed 42 and serial execution. Preserve both for reproducibility."
        },
        {
          "name": "primary_period",
          "effect": "Affects DeTime's grouping after the upstream component extraction."
        }
      ],
      "cautions": [
        "Different CEEMDAN variants exist; PyEMD includes the later improved formulation documented by its authors.",
        "An ensemble average does not establish that an IMF is a unique physical component.",
        "Raw DeTime IMF arrays use (mode, time, channel), including a singleton channel for one series."
      ],
      "references": [
        {
          "title": "PyEMD CEEMDAN implementation and reproducibility",
          "url": "https://pyemd.readthedocs.io/en/latest/ceemdan.html"
        },
        {
          "title": "Torres et al. (2011)",
          "url": "https://doi.org/10.1109/ICASSP.2011.5947265"
        },
        {
          "title": "Colominas et al. (2014)",
          "url": "https://doi.org/10.1016/j.bspc.2014.06.009"
        }
      ],
      "trace_kind": "upstream execution trace",
      "trace_note": "Trial inputs, first IMFs, and adaptive local means recorded from EMD-signal 1.10.0; max_imf=3 bounds this upstream teaching run. DeTime's example below exposes the public controls and does not set this internal trace cap.",
      "input_note": "Deterministic synthetic teaching signal; not a benchmark.",
      "example_config": {
        "method": "CEEMDAN",
        "params": {
          "trials": 8,
          "epsilon": 0.04,
          "primary_period": 24
        },
        "seed": 42,
        "n_jobs": 1,
        "backend": "python"
      },
      "checks": {
        "first_ensemble_mean_error": 2.7755575615628914e-17,
        "second_local_mean_error": 8.881784197001252e-16,
        "sum_of_returned_slices_error": 4.440892098500626e-16
      },
      "source_files": [
        "src/detime/methods/ceemdan.py"
      ],
      "frames": 32,
      "duration_ms": 12050,
      "poster_frame": 15,
      "width": 1280,
      "height": 820,
      "artifacts": {
        "gif": {
          "file": "ceemdan.gif",
          "bytes": 1104178,
          "sha256": "356f2cd9d4ffc56bd6447684ef34bcbeeceffdef5a35b3ea3d9c2d84248ccf99"
        },
        "poster": {
          "file": "ceemdan.png",
          "bytes": 191370,
          "sha256": "ee73513398f425a56e30d75c9fdd7459eeb3ae026f73a6eb9833b8f8edfb387a"
        },
        "data": {
          "file": "ceemdan.npz",
          "bytes": 60494,
          "sha256": "5f654fae2d8d9e015b88e60d2edff162874eff2b21c43bd8927b318a970e1af6"
        }
      },
      "source_arrays": {
        "time": [
          144
        ],
        "input": [
          144
        ],
        "first_trial_input_and_imf": [
          8,
          2,
          144
        ],
        "adaptive_trial_input_and_local_mean": [
          8,
          2,
          144
        ],
        "first_running_means": [
          8,
          144
        ],
        "adaptive_running_means": [
          8,
          144
        ],
        "returned_slices": [
          4,
          144
        ]
      },
      "render_provenance": {
        "python_version": "3.12.14",
        "dependencies": {
          "numpy": "2.3.5",
          "scipy": "1.17.0",
          "statsmodels": "0.15.0",
          "matplotlib": "3.10.8",
          "Pillow": "12.3.0",
          "PyWavelets": "1.10.0",
          "EMD-signal": "1.10.0",
          "vmdpy": "0.2",
          "PySDKit": "0.5.0"
        },
        "source_hashes": {
          "scripts/generate_method_animations.py": "f62989af55a7e48495c24afcfee31751d3785e5f78bb4b900bef23a429deaa84",
          "scripts/method_animations/adaptive.py": "7d728d88b4ba1a8dd82890c7a6b017d542728b50dc477c281e9bbfcbae164a1d",
          "scripts/method_animations/common.py": "73ad7e8b4e5b67f87d13e59adab2c93e983fe1aaf06ee627d22cb7c7e696016a",
          "src/detime/backends.py": "7432dcf59e382580dfb32f1f57e61ff71a30567c049b35243e24e3644523eda6",
          "src/detime/core.py": "d95b348cd8b16b56d18840965579c947a11628d969dd6c32c4af7723f5a027f4",
          "src/detime/methods/ceemdan.py": "3afa048be78ff8bf1671a3f80412a1e717a8574ef85a8f9a2aea5354e605c694",
          "src/detime/registry.py": "e934ffca17880cefe5add728aa497e63ea811d7ae43abec1ea498de718094066"
        }
      }
    },
    {
      "method": "DELELSTM_BLOCK",
      "slug": "delelstm-block",
      "title": "DeLELSTM block: level, slope and phase",
      "summary": "A Holt-style recurrence updates a level and slope on the prefix; its last slope extrapolates the trend afterward. The next step uses phase-wise means of the detrended prefix. The frames expose those buckets, their cumulative averages and the repeated seasonal output. The implemented trend is a level/slope recurrence with a phase template. No LSTM cell is trained or evaluated.",
      "steps": [
        {
          "title": "Update level and slope",
          "text": "A Holt-style recurrence updates a level and slope on the prefix; its last slope extrapolates the trend afterward."
        },
        {
          "title": "Average equal seasonal phases",
          "text": "Subtract the trend on the fitting prefix. Group samples by index modulo the specified period and average each phase bucket."
        },
        {
          "title": "Repeat the phase template",
          "text": "Tile the fitted phase means over the record. The suffix does not update the template in this prefix configuration."
        },
        {
          "title": "Inspect the derived residual",
          "text": "Compute input minus the implemented trend and seasonal estimate. This residual is part of a retrospective decomposition, not a forecast score."
        }
      ],
      "parameters": [
        {
          "name": "alpha / beta",
          "effect": "Control level and slope updates in the implemented Holt recurrence; no LSTM cell is evaluated."
        },
        {
          "name": "primary_period",
          "effect": "Defines phase buckets in samples; the fitting prefix must contain enough cycles for an interpretable average."
        },
        {
          "name": "fit_scope / train_fraction",
          "effect": "Explicitly selects a two-thirds prefix in this example; it does not create a rolling forecasting evaluation."
        }
      ],
      "cautions": [
        "The implemented trend is a level/slope recurrence with a phase template. No LSTM cell is trained or evaluated.",
        "Prefix fitting is a fixed fitting convention. It does not certify rolling causality or an out-of-sample prediction experiment.",
        "A repeated phase template assumes that the fitted seasonal shape remains useful over the displayed suffix.",
        "The residual is derived by subtraction; exact reconstruction does not validate the scientific interpretation of either component."
      ],
      "references": [
        {
          "title": "Implemented DeTime operator",
          "url": "https://github.com/systems-mechanobiology/DeTime/blob/main/src/detime/methods/neural_blocks/neural_block_portfolio.py"
        },
        {
          "title": "Wang et al. (2023), DeLELSTM: Decomposition-based Linear Explainable LSTM to Capture Instantaneous and Long-term Effects in Time Series",
          "url": "https://arxiv.org/abs/2308.13797"
        }
      ],
      "trace_kind": "computed_operator_trace",
      "trace_note": "Intermediate arrays are computed with the implemented operator helpers. The final trend, season and residual are checked against public decompose(). The animation explains this standalone experimental block; its source architecture is cited for provenance.",
      "input_note": "Deterministic synthetic teaching signal; not a benchmark.",
      "example_config": {
        "method": "DELELSTM_BLOCK",
        "params": {
          "primary_period": 24,
          "fit_scope": "prefix",
          "train_fraction": 0.6666666666666666,
          "alpha": 0.4,
          "beta": 0.2
        },
        "backend": "python"
      },
      "checks": {
        "public_method_executed": true,
        "method_output_max_abs_errors": {
          "trend": 0.0,
          "season": 0.0,
          "residual": 0.0
        },
        "reconstruction_max_abs_error": 4.440892098500626e-16,
        "validation_scope": "One deterministic teaching input; no benchmark claim.",
        "fit_end": 96
      },
      "source_files": [
        "src/detime/methods/neural_blocks/neural_block_portfolio.py"
      ],
      "frames": 32,
      "duration_ms": 12050,
      "poster_frame": 15,
      "width": 1280,
      "height": 820,
      "artifacts": {
        "gif": {
          "file": "delelstm-block.gif",
          "bytes": 335104,
          "sha256": "17692b1686cabde00e6c967fddc150703b27e6f4777f154e8944df9512ab1c40"
        },
        "poster": {
          "file": "delelstm-block.png",
          "bytes": 122208,
          "sha256": "70f9733688c7f368d1c94cf9c661a25947b0243673ba8240048b995d979fa71c"
        },
        "data": {
          "file": "delelstm-block.npz",
          "bytes": 8790,
          "sha256": "712d097fcb5d5e29e55e8030afe530ec689599d8a8d8371a64b1c07371c71221"
        }
      },
      "source_arrays": {
        "observed": [
          144
        ],
        "trend_candidates": [
          1,
          144
        ],
        "trend": [
          144
        ],
        "detrended": [
          144
        ],
        "prefix_phase_matrix": [
          4,
          24
        ],
        "raw_template": [
          144
        ],
        "season": [
          144
        ],
        "residual": [
          144
        ],
        "fit_end": []
      },
      "render_provenance": {
        "python_version": "3.12.14",
        "dependencies": {
          "numpy": "2.3.5",
          "scipy": "1.17.0",
          "statsmodels": "0.15.0",
          "matplotlib": "3.10.8",
          "Pillow": "12.3.0",
          "PyWavelets": "1.10.0",
          "EMD-signal": "1.10.0",
          "vmdpy": "0.2",
          "PySDKit": "0.5.0"
        },
        "source_hashes": {
          "scripts/generate_method_animations.py": "f62989af55a7e48495c24afcfee31751d3785e5f78bb4b900bef23a429deaa84",
          "scripts/method_animations/common.py": "73ad7e8b4e5b67f87d13e59adab2c93e983fe1aaf06ee627d22cb7c7e696016a",
          "scripts/method_animations/neural.py": "fc1c2a73490391f0f863ede52e38f12924cc1fec572b7188356a2308216716e6",
          "src/detime/backends.py": "7432dcf59e382580dfb32f1f57e61ff71a30567c049b35243e24e3644523eda6",
          "src/detime/core.py": "d95b348cd8b16b56d18840965579c947a11628d969dd6c32c4af7723f5a027f4",
          "src/detime/methods/neural_blocks/neural_block_portfolio.py": "2aab635b9927d1d42bbcd8e0b4f37cb9fcdcf85cbd0331b5011621b495c4acfa",
          "src/detime/registry.py": "e934ffca17880cefe5add728aa497e63ea811d7ae43abec1ea498de718094066"
        }
      }
    },
    {
      "method": "DLINEAR_BLOCK",
      "slug": "dlinear-block",
      "title": "DLinear block: moving-average split",
      "summary": "The implemented operator replaces each sample with a centered local mean and assigns the input minus that mean to a second stream. Edge replication maintains the original length. AUTOFORMER_BLOCK, DLINEAR_BLOCK and MOVING_AVERAGE_DECOMPOSITION_BLOCK call the same numeric implementation at equal settings; their method identifiers record provenance. The animation therefore shows the same numerical mechanism for all three, with a separate named asset for each entry.",
      "steps": [
        {
          "title": "Specify the filter",
          "text": "Inspect the normalized filter weights and the replicated-edge input window used for a local mean."
        },
        {
          "title": "Move along the series",
          "text": "At each sample, multiply the local values by the same fixed kernel and sum them to form the trend."
        },
        {
          "title": "Subtract the trend",
          "text": "Compute the nontrend stream as the input minus the smoothed trend, sample by sample."
        },
        {
          "title": "Inspect the output contract",
          "text": "The two streams already reconstruct the input, leaving a derived residual of zero up to arithmetic precision."
        }
      ],
      "parameters": [
        {
          "name": "moving_avg",
          "effect": "Sets the smoothing window. Larger windows average more samples; even requests become odd windows."
        },
        {
          "name": "window",
          "effect": "Acts as an alias after moving_avg. If neither is supplied, period hints are checked before the default window of 25."
        },
        {
          "name": "primary_period",
          "effect": "Can supply a window hint; this operator does not fit a periodic template."
        }
      ],
      "cautions": [
        "The three registered moving-average block names are numerical aliases at equal configuration.",
        "This is the decomposition head. It does not execute Autoformer attention or DLinear's fitted forecasting projections.",
        "The nontrend stream can contain noise and transients. Here season = input - trend, so the derived residual is zero by construction.",
        "The centered filter uses future neighbours relative to an interior sample in a full-record analysis."
      ],
      "references": [
        {
          "title": "Implemented DeTime operator",
          "url": "https://github.com/systems-mechanobiology/DeTime/blob/main/src/detime/methods/neural_blocks/forecasting_blocks.py"
        },
        {
          "title": "Zeng et al. (2023), Are Transformers Effective for Time Series Forecasting?",
          "url": "https://ojs.aaai.org/index.php/AAAI/article/view/26317"
        }
      ],
      "trace_kind": "computed_operator_trace",
      "trace_note": "Intermediate arrays are computed with the implemented operator helpers. The final trend, season and residual are checked against public decompose(). The animation explains this standalone experimental block; its source architecture is cited for provenance.",
      "input_note": "Deterministic synthetic teaching signal; not a benchmark.",
      "example_config": {
        "method": "DLINEAR_BLOCK",
        "params": {
          "moving_avg": 25
        },
        "backend": "python"
      },
      "checks": {
        "public_method_executed": true,
        "method_output_max_abs_errors": {
          "trend": 0.0,
          "season": 0.0,
          "residual": 0.0
        },
        "reconstruction_max_abs_error": 1.1102230246251565e-16,
        "validation_scope": "One deterministic teaching input; no benchmark claim.",
        "kernel_sum": 1.0,
        "shared_operator_identifiers": [
          "AUTOFORMER_BLOCK",
          "DLINEAR_BLOCK",
          "MOVING_AVERAGE_DECOMPOSITION_BLOCK"
        ]
      },
      "source_files": [
        "src/detime/methods/neural_blocks/forecasting_blocks.py"
      ],
      "frames": 32,
      "duration_ms": 12050,
      "poster_frame": 15,
      "width": 1280,
      "height": 820,
      "artifacts": {
        "gif": {
          "file": "dlinear-block.gif",
          "bytes": 316548,
          "sha256": "68b90cf768b0d19055dc01f8d5406925a0c76ee6ab466323bfdf2db70493d202"
        },
        "poster": {
          "file": "dlinear-block.png",
          "bytes": 122674,
          "sha256": "a8bdad06b91d876ae9b0bc17102ee4f2e151723eea213bff2b289d13cdbcaaa4"
        },
        "data": {
          "file": "dlinear-block.npz",
          "bytes": 4444,
          "sha256": "1eb3ce696b5a4ad419debcc65bbac0a64a7a9d0268391442a62414af844b6f2e"
        }
      },
      "source_arrays": {
        "observed": [
          144
        ],
        "kernel": [
          25
        ],
        "trend": [
          144
        ],
        "season": [
          144
        ],
        "residual": [
          144
        ]
      },
      "render_provenance": {
        "python_version": "3.12.14",
        "dependencies": {
          "numpy": "2.3.5",
          "scipy": "1.17.0",
          "statsmodels": "0.15.0",
          "matplotlib": "3.10.8",
          "Pillow": "12.3.0",
          "PyWavelets": "1.10.0",
          "EMD-signal": "1.10.0",
          "vmdpy": "0.2",
          "PySDKit": "0.5.0"
        },
        "source_hashes": {
          "scripts/generate_method_animations.py": "f62989af55a7e48495c24afcfee31751d3785e5f78bb4b900bef23a429deaa84",
          "scripts/method_animations/common.py": "73ad7e8b4e5b67f87d13e59adab2c93e983fe1aaf06ee627d22cb7c7e696016a",
          "scripts/method_animations/neural.py": "fc1c2a73490391f0f863ede52e38f12924cc1fec572b7188356a2308216716e6",
          "src/detime/backends.py": "7432dcf59e382580dfb32f1f57e61ff71a30567c049b35243e24e3644523eda6",
          "src/detime/core.py": "d95b348cd8b16b56d18840965579c947a11628d969dd6c32c4af7723f5a027f4",
          "src/detime/methods/neural_blocks/forecasting_blocks.py": "8404a89cab00a5443f75aae2b168b55218485fbb256f7723250f9470637ccb02",
          "src/detime/registry.py": "e934ffca17880cefe5add728aa497e63ea811d7ae43abec1ea498de718094066"
        }
      }
    },
    {
      "method": "EMD",
      "slug": "emd",
      "title": "EMD: estimate envelopes, subtract their mean, and sift",
      "summary": "EMD adapts its oscillatory modes to the extrema of the current signal. DeTime then groups upstream modes into its trend/season/residual result.",
      "steps": [
        {
          "title": "Locate extrema",
          "text": "Local maxima and minima anchor the envelope construction."
        },
        {
          "title": "Build envelopes",
          "text": "PyEMD interpolates upper and lower envelopes with its boundary treatment."
        },
        {
          "title": "Sift",
          "text": "Subtract their pointwise mean, recompute extrema, and apply the stopping criteria."
        },
        {
          "title": "Remove the IMF",
          "text": "Subtract the accepted mode from the signal and continue on the remainder."
        }
      ],
      "parameters": [
        {
          "name": "n_imfs",
          "effect": "Limits extracted modes in DeTime's PyEMD call; a final residue can also be returned."
        },
        {
          "name": "primary_period / explicit IMF groups",
          "effect": "Controls DeTime's subsequent grouping; it does not determine the sifting envelopes."
        },
        {
          "name": "PyEMD stopping criteria",
          "effect": "This trace uses the upstream defaults; DeTime's wrapper exposes a narrower parameter surface."
        }
      ],
      "cautions": [
        "EMD modes are not uniquely identified physical sources; the first mode is not automatically the desired season.",
        "Spline boundary choices and added observations can change previously estimated components.",
        "The animation records the first IMF; it does not imply the algorithm stops after one mode."
      ],
      "references": [
        {
          "title": "PyEMD EMD algorithm and envelope API",
          "url": "https://pyemd.readthedocs.io/en/latest/emd.html"
        },
        {
          "title": "Huang et al. (1998)",
          "url": "https://doi.org/10.1098/rspa.1998.0193"
        }
      ],
      "trace_kind": "upstream execution trace",
      "trace_note": "Envelope calls recorded from EMD-signal 1.10.0 with default sifting settings and max_imf=1. All curves are computed; no intermediate curve is interpolated between final results.",
      "input_note": "Deterministic synthetic teaching signal; not a benchmark.",
      "example_config": {
        "method": "EMD",
        "params": {
          "n_imfs": 3,
          "primary_period": 24
        }
      },
      "checks": {
        "recorded_sifts": 11,
        "imf_plus_remainder_max_abs_error": 2.220446049250313e-16,
        "sequential_sift_update_error": 0.0,
        "final_sift_matches_first_imf": 0.0,
        "finite_sifts": true
      },
      "source_files": [
        "src/detime/methods/emd.py"
      ],
      "frames": 32,
      "duration_ms": 12050,
      "poster_frame": 15,
      "width": 1280,
      "height": 820,
      "artifacts": {
        "gif": {
          "file": "emd.gif",
          "bytes": 450248,
          "sha256": "67b3c109bce56b68f572ae368b80c9c7ec42078839fd1729c9efb242eeaf2e04"
        },
        "poster": {
          "file": "emd.png",
          "bytes": 186211,
          "sha256": "5da1acc1afe87523606fb8f2d74e738be8310ae12ba025928ef254e870186ff8"
        },
        "data": {
          "file": "emd.npz",
          "bytes": 49095,
          "sha256": "8cf09db8ba2515d039ed48306aebeebc8a4ae62361d81c73f06c97f409c50a17"
        }
      },
      "source_arrays": {
        "time": [
          192
        ],
        "input": [
          192
        ],
        "sift_candidate_upper_lower": [
          11,
          3,
          192
        ],
        "first_imf": [
          192
        ],
        "remainder": [
          192
        ],
        "maxima": [
          23
        ],
        "minima": [
          23
        ]
      },
      "render_provenance": {
        "python_version": "3.11.3",
        "dependencies": {
          "numpy": "2.4.6",
          "scipy": "1.17.1",
          "statsmodels": "0.15.0",
          "matplotlib": "3.11.2",
          "Pillow": "13.0.0",
          "PyWavelets": "1.9.0",
          "EMD-signal": "1.10.0",
          "vmdpy": "0.2",
          "PySDKit": "0.5.0"
        },
        "source_hashes": {
          "scripts/generate_method_animations.py": "f62989af55a7e48495c24afcfee31751d3785e5f78bb4b900bef23a429deaa84",
          "scripts/method_animations/adaptive.py": "7d728d88b4ba1a8dd82890c7a6b017d542728b50dc477c281e9bbfcbae164a1d",
          "scripts/method_animations/common.py": "73ad7e8b4e5b67f87d13e59adab2c93e983fe1aaf06ee627d22cb7c7e696016a",
          "src/detime/backends.py": "7432dcf59e382580dfb32f1f57e61ff71a30567c049b35243e24e3644523eda6",
          "src/detime/core.py": "d95b348cd8b16b56d18840965579c947a11628d969dd6c32c4af7723f5a027f4",
          "src/detime/methods/emd.py": "42eb21caed63d31775cbe060a2c4367b1cb8a17d978e3c65c957062c1ef4c027",
          "src/detime/registry.py": "e934ffca17880cefe5add728aa497e63ea811d7ae43abec1ea498de718094066"
        }
      }
    },
    {
      "method": "FREQMOE_BLOCK",
      "slug": "freqmoe-block",
      "title": "FreqMoE block: average frequency fits",
      "summary": "This standalone operator obtains candidate periods from an FFT magnitude ranking and fits a separate harmonic projection for each one. The selected seasonal estimate is their equal-weight average. The frames expose the selection signal, rounded periods, candidate curves and averaging operation. The parameter expert_width determines the harmonic count by rounding expert_width / 64. It does not size a fitted mixture-of-experts network here.",
      "steps": [
        {
          "title": "Separate trend and selection input",
          "text": "Compute the moving-average trend. FreqMoE selects frequencies from the detrended signal; Times2D selects them from the original signal after mean removal."
        },
        {
          "title": "Select discrete spectral peaks",
          "text": "Rank FFT magnitudes, convert bin positions into rounded integer periods, and retain distinct periods as implemented."
        },
        {
          "title": "Fit and average candidate seasons",
          "text": "Fit a harmonic projection of the detrended signal for each selected period, then take the arithmetic mean of these projections."
        },
        {
          "title": "Inspect actual output streams",
          "text": "The final trend, averaged projection and derived residual are checked against the public registered operator."
        }
      ],
      "parameters": [
        {
          "name": "trend_window",
          "effect": "Sets the centered moving-average trend."
        },
        {
          "name": "num_bands",
          "effect": "Controls how many distinct rounded FFT periods are retained."
        },
        {
          "name": "expert_width",
          "effect": "Sets harmonic capacity through round(expert_width / 64)."
        },
        {
          "name": "fit_scope",
          "effect": "Explicitly full in this animation; prefix settings restrict the fitting interval."
        }
      ],
      "cautions": [
        "The parameter expert_width determines the harmonic count by rounding expert_width / 64. It does not size a fitted mixture-of-experts network here.",
        "A large FFT bin need not correspond to a stable physical oscillation. Trends, finite windows and rounding affect the selected periods.",
        "The independent candidate projections are averaged, rather than jointly fitted as one combined design.",
        "All coefficients use the selected fitting interval; no held-out forecast accuracy is shown."
      ],
      "references": [
        {
          "title": "Implemented DeTime operator",
          "url": "https://github.com/systems-mechanobiology/DeTime/blob/main/src/detime/methods/neural_blocks/neural_block_portfolio.py"
        },
        {
          "title": "Liu (2025), FreqMoE: Enhancing Time Series Forecasting through Frequency Decomposition Mixture of Experts",
          "url": "https://arxiv.org/abs/2501.15125"
        }
      ],
      "trace_kind": "computed_operator_trace",
      "trace_note": "Intermediate arrays are computed with the implemented operator helpers. The final trend, season and residual are checked against public decompose(). The animation explains this standalone experimental block; its source architecture is cited for provenance.",
      "input_note": "Deterministic synthetic teaching signal; not a benchmark.",
      "example_config": {
        "method": "FREQMOE_BLOCK",
        "params": {
          "primary_period": 24,
          "trend_window": 49,
          "fit_scope": "full",
          "num_bands": 3,
          "expert_width": 128
        },
        "backend": "python"
      },
      "checks": {
        "public_method_executed": true,
        "method_output_max_abs_errors": {
          "trend": 0.0,
          "season": 0.0,
          "residual": 0.0
        },
        "reconstruction_max_abs_error": 4.440892098500626e-16,
        "validation_scope": "One deterministic teaching input; no benchmark claim.",
        "selected_periods": [
          24,
          12,
          48
        ]
      },
      "source_files": [
        "src/detime/methods/neural_blocks/neural_block_portfolio.py"
      ],
      "frames": 32,
      "duration_ms": 12050,
      "poster_frame": 15,
      "width": 1280,
      "height": 820,
      "artifacts": {
        "gif": {
          "file": "freqmoe-block.gif",
          "bytes": 344315,
          "sha256": "cfca14380c652bdc14891a27c0931681dff6c27d4ffeb49b7ef7f051d6534ce2"
        },
        "poster": {
          "file": "freqmoe-block.png",
          "bytes": 132464,
          "sha256": "aa4108121655835e7a64a63f73271cc29ac9480773020ef1ff0c44ce5db3ffa4"
        },
        "data": {
          "file": "freqmoe-block.npz",
          "bytes": 10760,
          "sha256": "21b779ed4252af6a8309711ba04ba9f808989ed95efbbfca31ee20b830285f84"
        }
      },
      "source_arrays": {
        "observed": [
          144
        ],
        "trend": [
          144
        ],
        "detrended": [
          144
        ],
        "selection_input": [
          144
        ],
        "spectrum": [
          73
        ],
        "fft_frequencies": [
          73
        ],
        "selected_periods": [
          3
        ],
        "candidate_seasons": [
          3,
          144
        ],
        "season": [
          144
        ],
        "residual": [
          144
        ]
      },
      "render_provenance": {
        "python_version": "3.12.14",
        "dependencies": {
          "numpy": "2.3.5",
          "scipy": "1.17.0",
          "statsmodels": "0.15.0",
          "matplotlib": "3.10.8",
          "Pillow": "12.3.0",
          "PyWavelets": "1.10.0",
          "EMD-signal": "1.10.0",
          "vmdpy": "0.2",
          "PySDKit": "0.5.0"
        },
        "source_hashes": {
          "scripts/generate_method_animations.py": "f62989af55a7e48495c24afcfee31751d3785e5f78bb4b900bef23a429deaa84",
          "scripts/method_animations/common.py": "73ad7e8b4e5b67f87d13e59adab2c93e983fe1aaf06ee627d22cb7c7e696016a",
          "scripts/method_animations/neural.py": "fc1c2a73490391f0f863ede52e38f12924cc1fec572b7188356a2308216716e6",
          "src/detime/backends.py": "7432dcf59e382580dfb32f1f57e61ff71a30567c049b35243e24e3644523eda6",
          "src/detime/core.py": "d95b348cd8b16b56d18840965579c947a11628d969dd6c32c4af7723f5a027f4",
          "src/detime/methods/neural_blocks/neural_block_portfolio.py": "2aab635b9927d1d42bbcd8e0b4f37cb9fcdcf85cbd0331b5011621b495c4acfa",
          "src/detime/registry.py": "e934ffca17880cefe5add728aa497e63ea811d7ae43abec1ea498de718094066"
        }
      }
    },
    {
      "method": "GABOR_CLUSTER",
      "slug": "gabor-cluster",
      "title": "Gabor clustering: assign time-frequency atoms and reconstruct masks",
      "summary": "DeTime's experimental operator builds windowed Fourier atoms, assigns their features to a supplied codebook, and reconstructs cluster-specific contributions with overlap-add.",
      "steps": [
        {
          "title": "Window and transform",
          "text": "Slide the normalized Gaussian window and compute real FFT coefficients."
        },
        {
          "title": "Build atom features",
          "text": "Represent each time-frequency bin by normalized time, normalized frequency, and log amplitude."
        },
        {
          "title": "Assign the codebook",
          "text": "Standardize features with the stored mean/scale and select the nearest supplied centroid."
        },
        {
          "title": "Mask and reconstruct",
          "text": "Retain each cluster's complex coefficients, apply inverse FFT and normalized overlap-add, then group contributions heuristically."
        }
      ],
      "parameters": [
        {
          "name": "model / model_path",
          "effect": "A supplied GaborClusterModel is required; the decomposition function does not train a codebook."
        },
        {
          "name": "win_len / hop / n_fft",
          "effect": "Stored in the model; the example uses 48/12/64 and a Gaussian window."
        },
        {
          "name": "max_clusters",
          "effect": "Optionally retains the highest-energy clusters before reconstruction."
        },
        {
          "name": "trend_freq_thr",
          "effect": "Heuristic threshold on the de-standardized centroid frequency, normalized from zero to Nyquist."
        }
      ],
      "cautions": [
        "This is an experimental, repository-specific operator, not a claimed reproduction of a canonical forecasting or decomposition architecture.",
        "The fixed four-centroid teaching codebook is neither trained nor evidence of a useful scientific clustering.",
        "The current frame grid can leave an uncovered tail when the record length is not aligned with the hop; the residual retains that difference.",
        "Cluster labels are codebook labels; assigning low-frequency clusters to trend is a heuristic."
      ],
      "references": [
        {
          "title": "DeTime Gabor operator source",
          "url": "https://github.com/systems-mechanobiology/DeTime/blob/main/src/detime/methods/gabor_cluster.py"
        },
        {
          "title": "DeTime native Gabor kernels",
          "url": "https://github.com/systems-mechanobiology/DeTime/blob/main/native/src/gabor.cpp"
        }
      ],
      "trace_kind": "repository numerical stages with illustrative fixed codebook",
      "trace_note": "Uses the current repository's window, STFT, feature extraction and inverse-overlap-add functions. Squared Euclidean assignment matches the supplied-centroid operation; native cluster reconstructions are independently compared when available. Model normalization, fixed teaching centroids, and numeric window settings are saved with the trace. The public call requires a GaborClusterModel or a model archive created with its save() method; the generic config is incomplete until that model is supplied.",
      "input_note": "Deterministic synthetic teaching signal; not a benchmark.",
      "example_config": {
        "method": "GABOR_CLUSTER",
        "params": {
          "trend_freq_thr": 0.08
        }
      },
      "checks": {
        "mask_partition_error": 0,
        "overlap_add_reconstruction_error": 7.888691721635865e-06,
        "component_plus_residual_error": 0.0,
        "native_cluster_component_max_abs_difference": 6.273240017895532e-06
      },
      "source_files": [
        "src/detime/methods/gabor_cluster.py",
        "native/src/gabor.cpp"
      ],
      "frames": 32,
      "duration_ms": 12050,
      "poster_frame": 15,
      "width": 1280,
      "height": 820,
      "artifacts": {
        "gif": {
          "file": "gabor-cluster.gif",
          "bytes": 485807,
          "sha256": "2630a00c6330661f93bba093b0530c08cf4434c0bd91870fa0140dde8fe019ef"
        },
        "poster": {
          "file": "gabor-cluster.png",
          "bytes": 158211,
          "sha256": "eaf6213fed290c5c172ca225ae8569d1ac201ab91b1d305f2d7d91849293e173"
        },
        "data": {
          "file": "gabor-cluster.npz",
          "bytes": 23164,
          "sha256": "107ee113443ec8b28620d26cf205b6cd6f5dcd4b3bc5a65bd50ef2a3fa833ed6"
        }
      },
      "source_arrays": {
        "time": [
          192
        ],
        "input": [
          192
        ],
        "window": [
          48
        ],
        "stft": [
          13,
          33
        ],
        "raw_features": [
          429,
          3
        ],
        "feature_mean": [
          3
        ],
        "feature_scale": [
          3
        ],
        "raw_demo_centroids": [
          4,
          3
        ],
        "standardized_demo_centroids": [
          4,
          3
        ],
        "squared_centroid_distances": [
          429,
          4
        ],
        "cluster_labels": [
          13,
          33
        ],
        "cluster_components": [
          4,
          192
        ],
        "residual": [
          192
        ],
        "config_win_len": [],
        "config_hop": [],
        "config_n_fft": [],
        "config_use_log_amp": []
      },
      "render_provenance": {
        "python_version": "3.12.14",
        "dependencies": {
          "numpy": "2.3.5",
          "scipy": "1.17.0",
          "statsmodels": "0.15.0",
          "matplotlib": "3.10.8",
          "Pillow": "12.3.0",
          "PyWavelets": "1.10.0",
          "EMD-signal": "1.10.0",
          "vmdpy": "0.2",
          "PySDKit": "0.5.0"
        },
        "source_hashes": {
          "native/src/gabor.cpp": "705f5c9465d1639be25bdfed903c8518748a1dbfe3d6cf883ea2438e41db6384",
          "scripts/generate_method_animations.py": "f62989af55a7e48495c24afcfee31751d3785e5f78bb4b900bef23a429deaa84",
          "scripts/method_animations/adaptive.py": "7d728d88b4ba1a8dd82890c7a6b017d542728b50dc477c281e9bbfcbae164a1d",
          "scripts/method_animations/common.py": "73ad7e8b4e5b67f87d13e59adab2c93e983fe1aaf06ee627d22cb7c7e696016a",
          "src/detime/backends.py": "7432dcf59e382580dfb32f1f57e61ff71a30567c049b35243e24e3644523eda6",
          "src/detime/core.py": "d95b348cd8b16b56d18840965579c947a11628d969dd6c32c4af7723f5a027f4",
          "src/detime/methods/gabor_cluster.py": "e8836ac9567ada7a8a7edb3cb66b63916d721ee1e554e282987c177d2eb3e2e7",
          "src/detime/registry.py": "e934ffca17880cefe5add728aa497e63ea811d7ae43abec1ea498de718094066"
        }
      }
    },
    {
      "method": "INPARFORMER_BLOCK",
      "slug": "inparformer-block",
      "title": "InParformer block: smooth, group, repeat",
      "summary": "A centered moving average estimates the prefix trend and the final trend level is held constant afterward. The next step uses phase-wise means of the detrended prefix. The frames expose those buckets, their cumulative averages and the repeated seasonal output. The computation shown contains smoothing and phase averaging. It does not execute evolutionary search or interactive parallel attention.",
      "steps": [
        {
          "title": "Smooth the prefix",
          "text": "A centered moving average estimates the prefix trend and the final trend level is held constant afterward."
        },
        {
          "title": "Average equal seasonal phases",
          "text": "Subtract the trend on the fitting prefix. Group samples by index modulo the specified period and average each phase bucket."
        },
        {
          "title": "Repeat the phase template",
          "text": "Tile the fitted phase means over the record. The suffix does not update the template in this prefix configuration."
        },
        {
          "title": "Inspect the derived residual",
          "text": "Compute input minus the implemented trend and seasonal estimate. This residual is part of a retrospective decomposition, not a forecast score."
        }
      ],
      "parameters": [
        {
          "name": "trend_window",
          "effect": "Sets the centered moving-average support on the prefix; its endpoint is extended as a constant."
        },
        {
          "name": "primary_period",
          "effect": "Defines phase buckets in samples; the fitting prefix must contain enough cycles for an interpretable average."
        },
        {
          "name": "fit_scope / train_fraction",
          "effect": "Explicitly selects a two-thirds prefix in this example; it does not create a rolling forecasting evaluation."
        }
      ],
      "cautions": [
        "The computation shown contains smoothing and phase averaging. It does not execute evolutionary search or interactive parallel attention.",
        "Prefix fitting is a fixed fitting convention. It does not certify rolling causality or an out-of-sample prediction experiment.",
        "A repeated phase template assumes that the fitted seasonal shape remains useful over the displayed suffix.",
        "The residual is derived by subtraction; exact reconstruction does not validate the scientific interpretation of either component."
      ],
      "references": [
        {
          "title": "Implemented DeTime operator",
          "url": "https://github.com/systems-mechanobiology/DeTime/blob/main/src/detime/methods/neural_blocks/neural_block_portfolio.py"
        },
        {
          "title": "Cao et al. (2023), InParformer: Evolutionary Decomposition Transformers with Interactive Parallel Attention for Long-Term Time Series Forecasting",
          "url": "https://ojs.aaai.org/index.php/AAAI/article/view/25845"
        }
      ],
      "trace_kind": "computed_operator_trace",
      "trace_note": "Intermediate arrays are computed with the implemented operator helpers. The final trend, season and residual are checked against public decompose(). The animation explains this standalone experimental block; its source architecture is cited for provenance.",
      "input_note": "Deterministic synthetic teaching signal; not a benchmark.",
      "example_config": {
        "method": "INPARFORMER_BLOCK",
        "params": {
          "primary_period": 24,
          "fit_scope": "prefix",
          "train_fraction": 0.6666666666666666,
          "trend_window": 49
        },
        "backend": "python"
      },
      "checks": {
        "public_method_executed": true,
        "method_output_max_abs_errors": {
          "trend": 0.0,
          "season": 0.0,
          "residual": 0.0
        },
        "reconstruction_max_abs_error": 2.220446049250313e-16,
        "validation_scope": "One deterministic teaching input; no benchmark claim.",
        "fit_end": 96
      },
      "source_files": [
        "src/detime/methods/neural_blocks/neural_block_portfolio.py"
      ],
      "frames": 32,
      "duration_ms": 12050,
      "poster_frame": 15,
      "width": 1280,
      "height": 820,
      "artifacts": {
        "gif": {
          "file": "inparformer-block.gif",
          "bytes": 330623,
          "sha256": "8d695c1ca71ce2e1f9b18429c04abccee947debf098b14647b596a543518e4b6"
        },
        "poster": {
          "file": "inparformer-block.png",
          "bytes": 125995,
          "sha256": "5a2a4c88053367e42071535b07d608631af1441fbc46c7d7bc4fca1f931bb265"
        },
        "data": {
          "file": "inparformer-block.npz",
          "bytes": 8059,
          "sha256": "a239a4ed76ac20789b09dfdba126a66fa19d50092f6bcb70feb8c581422034bc"
        }
      },
      "source_arrays": {
        "observed": [
          144
        ],
        "trend_candidates": [
          1,
          144
        ],
        "trend": [
          144
        ],
        "detrended": [
          144
        ],
        "prefix_phase_matrix": [
          4,
          24
        ],
        "raw_template": [
          144
        ],
        "season": [
          144
        ],
        "residual": [
          144
        ],
        "fit_end": []
      },
      "render_provenance": {
        "python_version": "3.12.14",
        "dependencies": {
          "numpy": "2.3.5",
          "scipy": "1.17.0",
          "statsmodels": "0.15.0",
          "matplotlib": "3.10.8",
          "Pillow": "12.3.0",
          "PyWavelets": "1.10.0",
          "EMD-signal": "1.10.0",
          "vmdpy": "0.2",
          "PySDKit": "0.5.0"
        },
        "source_hashes": {
          "scripts/generate_method_animations.py": "f62989af55a7e48495c24afcfee31751d3785e5f78bb4b900bef23a429deaa84",
          "scripts/method_animations/common.py": "73ad7e8b4e5b67f87d13e59adab2c93e983fe1aaf06ee627d22cb7c7e696016a",
          "scripts/method_animations/neural.py": "fc1c2a73490391f0f863ede52e38f12924cc1fec572b7188356a2308216716e6",
          "src/detime/backends.py": "7432dcf59e382580dfb32f1f57e61ff71a30567c049b35243e24e3644523eda6",
          "src/detime/core.py": "d95b348cd8b16b56d18840965579c947a11628d969dd6c32c4af7723f5a027f4",
          "src/detime/methods/neural_blocks/neural_block_portfolio.py": "2aab635b9927d1d42bbcd8e0b4f37cb9fcdcf85cbd0331b5011621b495c4acfa",
          "src/detime/registry.py": "e934ffca17880cefe5add728aa497e63ea811d7ae43abec1ea498de718094066"
        }
      }
    },
    {
      "method": "LEDDAM_BLOCK",
      "slug": "leddam-block",
      "title": "LEDDAM block: fixed Gaussian smoothing",
      "summary": "This standalone implementation evaluates a fixed Gaussian-weighted convolution. Its kernel is normalized to sum to one, the edge samples are replicated, and the filtered signal becomes the trend stream. Subtracting that stream from the input creates the second stream. The animation displays actual weights and local products before assembling the output. The kernel is not trained in this operator.",
      "steps": [
        {
          "title": "Specify the filter",
          "text": "Inspect the normalized filter weights and the replicated-edge input window used for a local mean."
        },
        {
          "title": "Move along the series",
          "text": "At each sample, multiply the local values by the same fixed kernel and sum them to form the trend."
        },
        {
          "title": "Subtract the trend",
          "text": "Compute the nontrend stream as the input minus the smoothed trend, sample by sample."
        },
        {
          "title": "Inspect the output contract",
          "text": "The two streams already reconstruct the input, leaving a derived residual of zero up to arithmetic precision."
        }
      ],
      "parameters": [
        {
          "name": "kernel_size",
          "effect": "Sets the odd filter support; even requests are rounded to an odd size and clipped to input length."
        },
        {
          "name": "sigma",
          "effect": "Controls the Gaussian weight spread in sample units. The example uses 4.0; the implementation default is 1.0."
        }
      ],
      "cautions": [
        "The package computes a fixed Gaussian kernel. Its LEDDAM-inspired name does not imply trained convolution weights or the complete dual-attention architecture.",
        "Centered windows use samples on both sides of an interior point. Use only the history available at each forecast origin for forecasting features.",
        "The second stream contains everything removed by smoothing; its name does not establish periodicity. The derived residual is zero by construction."
      ],
      "references": [
        {
          "title": "Implemented DeTime operator",
          "url": "https://github.com/systems-mechanobiology/DeTime/blob/main/src/detime/methods/neural_blocks/leddam_block.py"
        },
        {
          "title": "Yu et al. (2024), Revitalizing Multivariate Time Series Forecasting: Learnable Decomposition with Inter-Series Dependencies and Intra-Series Variations Modeling",
          "url": "https://arxiv.org/abs/2402.12694"
        }
      ],
      "trace_kind": "computed_operator_trace",
      "trace_note": "Intermediate arrays are computed with the implemented operator helpers. The final trend, season and residual are checked against public decompose(). The animation explains this standalone experimental block; its source architecture is cited for provenance.",
      "input_note": "Deterministic synthetic teaching signal; not a benchmark.",
      "example_config": {
        "method": "LEDDAM_BLOCK",
        "params": {
          "kernel_size": 25,
          "sigma": 4.0
        },
        "backend": "python"
      },
      "checks": {
        "public_method_executed": true,
        "method_output_max_abs_errors": {
          "trend": 0.0,
          "season": 0.0,
          "residual": 0.0
        },
        "reconstruction_max_abs_error": 5.551115123125783e-17,
        "validation_scope": "One deterministic teaching input; no benchmark claim.",
        "kernel_sum": 1.0000000000000002
      },
      "source_files": [
        "src/detime/methods/neural_blocks/leddam_block.py"
      ],
      "frames": 32,
      "duration_ms": 12050,
      "poster_frame": 15,
      "width": 1280,
      "height": 820,
      "artifacts": {
        "gif": {
          "file": "leddam-block.gif",
          "bytes": 303658,
          "sha256": "e9a968b5987a4427a0c45c0c4b6a3b88c4c7882dbb161296def6ee9b11505723"
        },
        "poster": {
          "file": "leddam-block.png",
          "bytes": 128178,
          "sha256": "b017eaac7f9faddf93a3105dd64f082dceda5f4a39930cdeacc9e0020bd3fe34"
        },
        "data": {
          "file": "leddam-block.npz",
          "bytes": 4574,
          "sha256": "156c9f9385505f015ea268de01b39c80dfb220d0d98b2422d478defc52f381c3"
        }
      },
      "source_arrays": {
        "observed": [
          144
        ],
        "kernel": [
          25
        ],
        "trend": [
          144
        ],
        "season": [
          144
        ],
        "residual": [
          144
        ]
      },
      "render_provenance": {
        "python_version": "3.12.14",
        "dependencies": {
          "numpy": "2.3.5",
          "scipy": "1.17.0",
          "statsmodels": "0.15.0",
          "matplotlib": "3.10.8",
          "Pillow": "12.3.0",
          "PyWavelets": "1.10.0",
          "EMD-signal": "1.10.0",
          "vmdpy": "0.2",
          "PySDKit": "0.5.0"
        },
        "source_hashes": {
          "scripts/generate_method_animations.py": "f62989af55a7e48495c24afcfee31751d3785e5f78bb4b900bef23a429deaa84",
          "scripts/method_animations/common.py": "73ad7e8b4e5b67f87d13e59adab2c93e983fe1aaf06ee627d22cb7c7e696016a",
          "scripts/method_animations/neural.py": "fc1c2a73490391f0f863ede52e38f12924cc1fec572b7188356a2308216716e6",
          "src/detime/backends.py": "7432dcf59e382580dfb32f1f57e61ff71a30567c049b35243e24e3644523eda6",
          "src/detime/core.py": "d95b348cd8b16b56d18840965579c947a11628d969dd6c32c4af7723f5a027f4",
          "src/detime/methods/neural_blocks/leddam_block.py": "f357dc97c6ce1303f9c22002966371bfabc158a4316ae050fa28f55967d9bdd2",
          "src/detime/registry.py": "e934ffca17880cefe5add728aa497e63ea811d7ae43abec1ea498de718094066"
        }
      }
    },
    {
      "method": "MA_BASELINE",
      "slug": "ma-baseline",
      "title": "Smooth, fold, and average",
      "summary": "A centered uniform moving average supplies the trend; equal-phase means of the detrended series supply one repeated seasonal template.",
      "steps": [
        {
          "title": "Slide a uniform window",
          "text": "Use uniform weights over an odd-length window. DeTime increments an even requested window by one. Its NumPy mode='same' convolution uses zero extension at both ends, so the divisor remains the full window length even near an edge."
        },
        {
          "title": "Subtract the smooth trend",
          "text": "Compute detrended = observed - trend. Folding this array into cycle rows shows the values that share each seasonal phase."
        },
        {
          "title": "Average seasonal phases",
          "text": "For each phase offset, average the detrended values separated by season_period samples. Repeat those means along the record. If season_period is omitted, the seasonal component is identically zero."
        },
        {
          "title": "Center and form residual",
          "text": "Subtract the mean of the complete repeated seasonal array, then return residual = observed - trend - season. This guarantees an additive identity without establishing that each assigned component is physically correct."
        }
      ],
      "parameters": [
        {
          "name": "trend_window",
          "effect": "Smoothing width; even requests are advanced to the next odd integer. The animation uses 25."
        },
        {
          "name": "season_period",
          "effect": "Spacing between observations assigned to the same seasonal phase; omitted means no seasonal estimate."
        }
      ],
      "cautions": [
        "This is an in-package baseline, not a reproduction of a separately published forecasting model.",
        "Zero extension pulls endpoint moving averages toward zero. Inspect boundary behavior before using the resulting components.",
        "One repeated phase template cannot express arbitrary cycle-to-cycle shape changes.",
        "Centered smoothing and full-record phase averaging use future observations relative to earlier time points; causal forecasting requires an origin-specific pipeline."
      ],
      "references": [
        {
          "title": "DeTime moving-average baseline implementation",
          "url": "https://github.com/systems-mechanobiology/DeTime/blob/main/src/detime/methods/ma_baseline.py"
        }
      ],
      "trace_kind": "computed operator trace",
      "trace_note": "Window values, zero extension, uniform weights, phase averages, and centering follow the Python source. Final arrays are checked against the public Python execution path.",
      "input_note": "Deterministic synthetic teaching signal; not a benchmark.",
      "example_config": {
        "method": "MA_BASELINE",
        "backend": "python",
        "params": {
          "trend_window": 25,
          "season_period": 24
        }
      },
      "checks": {
        "trend_max_abs_error": 0.0,
        "season_max_abs_error": 0.0,
        "additive_reconstruction_max_abs_error": 4.440892098500626e-16
      },
      "source_files": [
        "src/detime/methods/ma_baseline.py",
        "native/src/ma_baseline.cpp"
      ],
      "frames": 32,
      "duration_ms": 12050,
      "poster_frame": 15,
      "width": 1280,
      "height": 820,
      "artifacts": {
        "gif": {
          "file": "ma-baseline.gif",
          "bytes": 514040,
          "sha256": "1fbff0e095909bec14e9dec2d97cc15bbd924c5f96f2e5cabe1b3e743f275edd"
        },
        "poster": {
          "file": "ma-baseline.png",
          "bytes": 120490,
          "sha256": "021ec8f06a80ce59ba9bb032764642393a96744b1d50a1db3fa31fe54c9c8095"
        },
        "data": {
          "file": "ma-baseline.npz",
          "bytes": 8423,
          "sha256": "94da88b0a3182ba095625e68d2e95a4fdc58b919eee7b618b91225805ce1e5fd"
        }
      },
      "source_arrays": {
        "t": [
          144
        ],
        "observed": [
          144
        ],
        "zero_padded_input": [
          168
        ],
        "trend": [
          144
        ],
        "detrended": [
          144
        ],
        "phase_means": [
          24
        ],
        "uncentered_season": [
          144
        ],
        "season": [
          144
        ],
        "residual": [
          144
        ]
      },
      "render_provenance": {
        "python_version": "3.12.14",
        "dependencies": {
          "numpy": "2.3.5",
          "scipy": "1.17.0",
          "statsmodels": "0.15.0",
          "matplotlib": "3.10.8",
          "Pillow": "12.3.0",
          "PyWavelets": "1.10.0",
          "EMD-signal": "1.10.0",
          "vmdpy": "0.2",
          "PySDKit": "0.5.0"
        },
        "source_hashes": {
          "native/src/ma_baseline.cpp": "752b3dfc9bea7353510ce5f7d4104d38ea6da45879af4402f7bee4618774dbc6",
          "scripts/generate_method_animations.py": "f62989af55a7e48495c24afcfee31751d3785e5f78bb4b900bef23a429deaa84",
          "scripts/method_animations/classical.py": "8a8a9ef82936f0aa5b1c5775c6c0158c3b48d3bc7dca1de691b83d95e5c23ba3",
          "scripts/method_animations/common.py": "73ad7e8b4e5b67f87d13e59adab2c93e983fe1aaf06ee627d22cb7c7e696016a",
          "src/detime/backends.py": "7432dcf59e382580dfb32f1f57e61ff71a30567c049b35243e24e3644523eda6",
          "src/detime/core.py": "d95b348cd8b16b56d18840965579c947a11628d969dd6c32c4af7723f5a027f4",
          "src/detime/methods/ma_baseline.py": "1197a6fa5dd7f3a807f603e331986d2b75ff87962f54314521e3e149d5241d54",
          "src/detime/registry.py": "e934ffca17880cefe5add728aa497e63ea811d7ae43abec1ea498de718094066"
        }
      }
    },
    {
      "method": "MEMD",
      "slug": "memd",
      "title": "MEMD: project multichannel data to estimate a joint envelope mean",
      "summary": "MEMD uses many projection directions to construct a multivariate local mean. Its sifting preserves aligned mode slices across the input channels.",
      "steps": [
        {
          "title": "Project the data",
          "text": "Use Hammersley-based unit directions and locate extrema of each scalar projection."
        },
        {
          "title": "Construct vector envelopes",
          "text": "At the projection extrema times, interpolate the original vector samples and average valid envelopes."
        },
        {
          "title": "Sift jointly",
          "text": "Subtract the direction-averaged vector mean and repeat the multivariate stopping test."
        },
        {
          "title": "Extract aligned modes",
          "text": "Remove the accepted multichannel IMF, continue on the vector residue, and keep the final residue."
        }
      ],
      "parameters": [
        {
          "name": "n_dir (upstream trace)",
          "effect": "This bounded PySDKit demonstration uses 16 projection directions; the DeTime wrapper does not expose this as a documented public control."
        },
        {
          "name": "Stopping rule (upstream trace)",
          "effect": "Uses PySDKit's default Rilling-style test with a safety cap of 50 sifts."
        },
        {
          "name": "primary_period / explicit mode groups",
          "effect": "Used by DeTime after upstream extraction, independently of the projection directions."
        }
      ],
      "cautions": [
        "This PySDKit backend requires at least three channels for MEMD; the example uses three aligned channels.",
        "Projection count, envelope boundaries, and stopping rules affect the result.",
        "Aligned IMF indexes do not establish physiological or other physical source identity."
      ],
      "references": [
        {
          "title": "PySDKit MEMD API and implementation",
          "url": "https://pysdkit.readthedocs.io/en/stable/API/pysdkit._emd.html"
        },
        {
          "title": "Rehman and Mandic: Multivariate empirical mode decomposition",
          "url": "https://doi.org/10.1098/rspa.2009.0502"
        }
      ],
      "trace_kind": "upstream numerical stages and execution trace",
      "trace_note": "Computed with PySDKit 0.5.0: its direction, extrema, and boundary helpers supply the vector envelopes; actual first-IMF sifting calls are recorded. The reduced direction count is a teaching setting, not a benchmark setting.",
      "input_note": "Deterministic synthetic teaching signal; not a benchmark.",
      "example_config": {
        "method": "MEMD",
        "params": {
          "primary_period": 24
        },
        "backend": "python"
      },
      "checks": {
        "unit_direction_error": 1.1102230246251565e-16,
        "mean_matches_upstream_helper": 0.0,
        "first_recorded_mean_error": 0.0,
        "sum_of_returned_slices_error": 2.220446049250313e-16,
        "recorded_first_imf_sifts": 4
      },
      "source_files": [
        "src/detime/methods/memd.py",
        "src/detime/methods/mvmd.py"
      ],
      "frames": 32,
      "duration_ms": 12050,
      "poster_frame": 15,
      "width": 1280,
      "height": 820,
      "artifacts": {
        "gif": {
          "file": "memd.gif",
          "bytes": 707599,
          "sha256": "78c317ebdd8a6ce44a1014970253d38baf442b257eccb30a8c878e57e20014de"
        },
        "poster": {
          "file": "memd.png",
          "bytes": 179901,
          "sha256": "2b6d7eecdb41bd7002baa3fa78ab47c55c661cd62dc383e91f1d6d6d7038e93b"
        },
        "data": {
          "file": "memd.npz",
          "bytes": 209903,
          "sha256": "4665f659b06832f24f79cf40b228d5a882b481d960dfc4e330161d5d3ae20689"
        }
      },
      "source_arrays": {
        "time": [
          144
        ],
        "input_channels": [
          144,
          3
        ],
        "directions": [
          16,
          3
        ],
        "projections": [
          144,
          16
        ],
        "valid_direction_ids": [
          16
        ],
        "vector_envelopes": [
          16,
          2,
          144,
          3
        ],
        "running_vector_means": [
          16,
          144,
          3
        ],
        "first_imf_sifts": [
          4,
          2,
          144,
          3
        ],
        "returned_imfs": [
          4,
          144,
          3
        ]
      },
      "render_provenance": {
        "python_version": "3.11.3",
        "dependencies": {
          "numpy": "2.4.6",
          "scipy": "1.17.1",
          "statsmodels": "0.15.0",
          "matplotlib": "3.11.2",
          "Pillow": "13.0.0",
          "PyWavelets": "1.9.0",
          "EMD-signal": "1.10.0",
          "vmdpy": "0.2",
          "PySDKit": "0.5.0"
        },
        "source_hashes": {
          "scripts/generate_method_animations.py": "f62989af55a7e48495c24afcfee31751d3785e5f78bb4b900bef23a429deaa84",
          "scripts/method_animations/adaptive.py": "7d728d88b4ba1a8dd82890c7a6b017d542728b50dc477c281e9bbfcbae164a1d",
          "scripts/method_animations/common.py": "73ad7e8b4e5b67f87d13e59adab2c93e983fe1aaf06ee627d22cb7c7e696016a",
          "src/detime/backends.py": "7432dcf59e382580dfb32f1f57e61ff71a30567c049b35243e24e3644523eda6",
          "src/detime/core.py": "d95b348cd8b16b56d18840965579c947a11628d969dd6c32c4af7723f5a027f4",
          "src/detime/methods/memd.py": "e6eb06c058644f123495d3593a804b40e677f6a5bfc2f2e289cb6c3e11d6e022",
          "src/detime/methods/mvmd.py": "3e66ea12f131795eeb5ebbb24bd6affe7bfc104ac94ef7d8cdeaff6073413fd7",
          "src/detime/registry.py": "e934ffca17880cefe5add728aa497e63ea811d7ae43abec1ea498de718094066"
        }
      }
    },
    {
      "method": "MOVING_AVERAGE_DECOMPOSITION_BLOCK",
      "slug": "moving-average-decomposition-block",
      "title": "Moving-average block: moving-average split",
      "summary": "The implemented operator replaces each sample with a centered local mean and assigns the input minus that mean to a second stream. Edge replication maintains the original length. AUTOFORMER_BLOCK, DLINEAR_BLOCK and MOVING_AVERAGE_DECOMPOSITION_BLOCK call the same numeric implementation at equal settings; their method identifiers record provenance. The animation therefore shows the same numerical mechanism for all three, with a separate named asset for each entry.",
      "steps": [
        {
          "title": "Specify the filter",
          "text": "Inspect the normalized filter weights and the replicated-edge input window used for a local mean."
        },
        {
          "title": "Move along the series",
          "text": "At each sample, multiply the local values by the same fixed kernel and sum them to form the trend."
        },
        {
          "title": "Subtract the trend",
          "text": "Compute the nontrend stream as the input minus the smoothed trend, sample by sample."
        },
        {
          "title": "Inspect the output contract",
          "text": "The two streams already reconstruct the input, leaving a derived residual of zero up to arithmetic precision."
        }
      ],
      "parameters": [
        {
          "name": "moving_avg",
          "effect": "Sets the smoothing window. Larger windows average more samples; even requests become odd windows."
        },
        {
          "name": "window",
          "effect": "Acts as an alias after moving_avg. If neither is supplied, period hints are checked before the default window of 25."
        },
        {
          "name": "primary_period",
          "effect": "Can supply a window hint; this operator does not fit a periodic template."
        }
      ],
      "cautions": [
        "The three registered moving-average block names are numerical aliases at equal configuration.",
        "This is the decomposition head. It does not execute Autoformer attention or DLinear's fitted forecasting projections.",
        "The nontrend stream can contain noise and transients. Here season = input - trend, so the derived residual is zero by construction.",
        "The centered filter uses future neighbours relative to an interior sample in a full-record analysis."
      ],
      "references": [
        {
          "title": "Implemented DeTime operator",
          "url": "https://github.com/systems-mechanobiology/DeTime/blob/main/src/detime/methods/neural_blocks/forecasting_blocks.py"
        },
        {
          "title": "Wu et al. (2021), Autoformer: Decomposition Transformers with Auto-Correlation for Long-Term Series Forecasting",
          "url": "https://proceedings.neurips.cc/paper_files/paper/2021/hash/bcc0d400288793e8bdcd7c19a8ac0c2b-Abstract.html"
        },
        {
          "title": "Zeng et al. (2023), Are Transformers Effective for Time Series Forecasting?",
          "url": "https://ojs.aaai.org/index.php/AAAI/article/view/26317"
        }
      ],
      "trace_kind": "computed_operator_trace",
      "trace_note": "Intermediate arrays are computed with the implemented operator helpers. The final trend, season and residual are checked against public decompose(). The animation explains this standalone experimental block; its source architecture is cited for provenance.",
      "input_note": "Deterministic synthetic teaching signal; not a benchmark.",
      "example_config": {
        "method": "MOVING_AVERAGE_DECOMPOSITION_BLOCK",
        "params": {
          "moving_avg": 25
        },
        "backend": "python"
      },
      "checks": {
        "public_method_executed": true,
        "method_output_max_abs_errors": {
          "trend": 0.0,
          "season": 0.0,
          "residual": 0.0
        },
        "reconstruction_max_abs_error": 1.1102230246251565e-16,
        "validation_scope": "One deterministic teaching input; no benchmark claim.",
        "kernel_sum": 1.0,
        "shared_operator_identifiers": [
          "AUTOFORMER_BLOCK",
          "DLINEAR_BLOCK",
          "MOVING_AVERAGE_DECOMPOSITION_BLOCK"
        ]
      },
      "source_files": [
        "src/detime/methods/neural_blocks/forecasting_blocks.py"
      ],
      "frames": 32,
      "duration_ms": 12050,
      "poster_frame": 15,
      "width": 1280,
      "height": 820,
      "artifacts": {
        "gif": {
          "file": "moving-average-decomposition-block.gif",
          "bytes": 317641,
          "sha256": "8d9142395d48d4f28f2884c3c3b90954fa21567064273e6c687611dd2ccb4b73"
        },
        "poster": {
          "file": "moving-average-decomposition-block.png",
          "bytes": 127700,
          "sha256": "b3d1fc52f2c6220fc9e9b6236c8fb64e89dbf7da4a131dcf8d2d0f77b3f8b30f"
        },
        "data": {
          "file": "moving-average-decomposition-block.npz",
          "bytes": 4444,
          "sha256": "1eb3ce696b5a4ad419debcc65bbac0a64a7a9d0268391442a62414af844b6f2e"
        }
      },
      "source_arrays": {
        "observed": [
          144
        ],
        "kernel": [
          25
        ],
        "trend": [
          144
        ],
        "season": [
          144
        ],
        "residual": [
          144
        ]
      },
      "render_provenance": {
        "python_version": "3.12.14",
        "dependencies": {
          "numpy": "2.3.5",
          "scipy": "1.17.0",
          "statsmodels": "0.15.0",
          "matplotlib": "3.10.8",
          "Pillow": "12.3.0",
          "PyWavelets": "1.10.0",
          "EMD-signal": "1.10.0",
          "vmdpy": "0.2",
          "PySDKit": "0.5.0"
        },
        "source_hashes": {
          "scripts/generate_method_animations.py": "f62989af55a7e48495c24afcfee31751d3785e5f78bb4b900bef23a429deaa84",
          "scripts/method_animations/common.py": "73ad7e8b4e5b67f87d13e59adab2c93e983fe1aaf06ee627d22cb7c7e696016a",
          "scripts/method_animations/neural.py": "fc1c2a73490391f0f863ede52e38f12924cc1fec572b7188356a2308216716e6",
          "src/detime/backends.py": "7432dcf59e382580dfb32f1f57e61ff71a30567c049b35243e24e3644523eda6",
          "src/detime/core.py": "d95b348cd8b16b56d18840965579c947a11628d969dd6c32c4af7723f5a027f4",
          "src/detime/methods/neural_blocks/forecasting_blocks.py": "8404a89cab00a5443f75aae2b168b55218485fbb256f7723250f9470637ccb02",
          "src/detime/registry.py": "e934ffca17880cefe5add728aa497e63ea811d7ae43abec1ea498de718094066"
        }
      }
    },
    {
      "method": "MSSA",
      "slug": "mssa",
      "title": "Extract shared modes across channels",
      "summary": "A joint trajectory-matrix SVD produces modes that are reconstructed separately for each channel.",
      "steps": [
        {
          "title": "Stack aligned windows",
          "text": "Use a common window length and start positions for all channels, then stack their trajectory matrices vertically. Columns describe simultaneous multichannel windows."
        },
        {
          "title": "Compute shared singular modes",
          "text": "Compute the exact NumPy SVD and retain the requested rank. Every matrix mode spans all channel blocks, so a mode can express related temporal structure across channels."
        },
        {
          "title": "Reconstruct each channel",
          "text": "Split each rank-one matrix into its original channel blocks. Within each block, average entries representing the same time index to obtain one reconstructed series per channel."
        },
        {
          "title": "Group trend and season",
          "text": "This example uses DeTime's primary-period frequency heuristic. Low-frequency modes are assigned to trend and modes near 1/period to season, with documented fallbacks if a group is empty. Residual is the observed input minus those two groups. For MSSA, the grouping frequency comes from the mean across channels of each reconstructed mode."
        }
      ],
      "parameters": [
        {
          "name": "window",
          "effect": "Embedding length L; changes the temporal scale and matrix dimensions."
        },
        {
          "name": "rank",
          "effect": "Number of singular modes available for grouping; more modes can retain both signal structure and noise."
        },
        {
          "name": "primary_period",
          "effect": "Target period for the frequency-based seasonal grouping heuristic."
        },
        {
          "name": "trend_components / season_components",
          "effect": "Optional zero-based mode indices that explicitly define the groups."
        },
        {
          "name": "season_freq_tol_ratio / trend_freq_threshold",
          "effect": "Control the frequency bands used by automatic grouping."
        }
      ],
      "cautions": [
        "The labels trend and season come from a grouping rule; singular-value order alone does not establish physical meaning.",
        "Changing window, rank, or grouping can change components even when additive reconstruction remains exact.",
        "The animation uses backend='python', speed_mode='exact'. Native or randomized fast paths are separate numerical execution choices.",
        "This is an offline decomposition. Forecasting features must be recomputed using only observations available at each forecast origin.",
        "Channel magnitudes affect the stacked SVD. Scale channels deliberately when units or amplitudes differ.",
        "The current automatic grouping uses the mean across channels; opposing phases can cancel in that mean."
      ],
      "references": [
        {
          "title": "Golyandina and Zhigljavsky (2020), Singular Spectrum Analysis for Time Series",
          "url": "https://link.springer.com/book/10.1007/978-3-662-62436-4"
        }
      ],
      "trace_kind": "computed operator trace",
      "trace_note": "The trajectory matrix, exact SVD, reconstructed modes, and grouped outputs are computed from the source algorithm. Checks compare trace modes and final groups with the configured Python implementation. The animation explains construction order, not solver wall-clock execution.",
      "input_note": "Deterministic synthetic teaching signal; not a benchmark.",
      "example_config": {
        "method": "MSSA",
        "backend": "python",
        "speed_mode": "exact",
        "params": {
          "window": 36,
          "rank": 8,
          "primary_period": 24
        }
      },
      "checks": {
        "trace_modes_vs_implementation_max_abs_error": 0.0,
        "grouped_trend_max_abs_error": 0.0,
        "grouped_season_max_abs_error": 0.0,
        "additive_reconstruction_max_abs_error": 4.440892098500626e-16,
        "full_svd_matrix_reconstruction_max_abs_error": 1.0880185641326534e-14
      },
      "source_files": [
        "src/detime/methods/mssa.py",
        "native/src/mssa.cpp",
        "src/detime/methods/utils.py"
      ],
      "frames": 32,
      "duration_ms": 12050,
      "poster_frame": 15,
      "width": 1280,
      "height": 820,
      "artifacts": {
        "gif": {
          "file": "mssa.gif",
          "bytes": 972227,
          "sha256": "1f192f556cb731601742fbc01d4abb29c511b99fcfb04495696ea3b68c7622fc"
        },
        "poster": {
          "file": "mssa.png",
          "bytes": 154476,
          "sha256": "521304f1322908a04c5d79b3d0d69d9efefe7795813a8b6bc6bf70fbbda0f251"
        },
        "data": {
          "file": "mssa.npz",
          "bytes": 767972,
          "sha256": "4379295fc7755fdc3ff6c9f04d912322078b00bd36a6210d55a525b196481ba5"
        }
      },
      "source_arrays": {
        "t": [
          144
        ],
        "observed": [
          144,
          3
        ],
        "trajectory": [
          108,
          109
        ],
        "singular_values": [
          108
        ],
        "rank_one_matrices": [
          8,
          108,
          109
        ],
        "reconstructed_modes": [
          8,
          144,
          3
        ],
        "dominant_frequencies": [
          8
        ],
        "trend_indices": [
          2
        ],
        "season_indices": [
          2
        ],
        "trend": [
          144,
          3
        ],
        "season": [
          144,
          3
        ],
        "residual": [
          144,
          3
        ]
      },
      "render_provenance": {
        "python_version": "3.12.14",
        "dependencies": {
          "numpy": "2.3.5",
          "scipy": "1.17.0",
          "statsmodels": "0.15.0",
          "matplotlib": "3.10.8",
          "Pillow": "12.3.0",
          "PyWavelets": "1.10.0",
          "EMD-signal": "1.10.0",
          "vmdpy": "0.2",
          "PySDKit": "0.5.0"
        },
        "source_hashes": {
          "native/src/mssa.cpp": "4aaea22b4d2dea62dc6dd942d2e116f81a646c95e3f4f610c58f79302e69da2b",
          "scripts/generate_method_animations.py": "f62989af55a7e48495c24afcfee31751d3785e5f78bb4b900bef23a429deaa84",
          "scripts/method_animations/classical.py": "8a8a9ef82936f0aa5b1c5775c6c0158c3b48d3bc7dca1de691b83d95e5c23ba3",
          "scripts/method_animations/common.py": "73ad7e8b4e5b67f87d13e59adab2c93e983fe1aaf06ee627d22cb7c7e696016a",
          "src/detime/backends.py": "7432dcf59e382580dfb32f1f57e61ff71a30567c049b35243e24e3644523eda6",
          "src/detime/core.py": "d95b348cd8b16b56d18840965579c947a11628d969dd6c32c4af7723f5a027f4",
          "src/detime/methods/mssa.py": "ada7362bacc75c18fe034fd4d4e08f279b9887ea21944b667b37d4cc27571d51",
          "src/detime/methods/utils.py": "6963d1ecdf76f1920671a262d125f0d822ae620b1e532849a002be1b7b36e7fd",
          "src/detime/registry.py": "e934ffca17880cefe5add728aa497e63ea811d7ae43abec1ea498de718094066"
        }
      }
    },
    {
      "method": "MSTL",
      "slug": "mstl",
      "title": "Alternate between seasonal periods",
      "summary": "MSTL repeatedly estimates one seasonal period while removing the current estimates of the others, then returns a trend and remainder.",
      "steps": [
        {
          "title": "Specify the seasonal periods",
          "text": "Supply the periods and their seasonal smoothing windows. This synthetic signal contains periods 12 and 36, and both are specified explicitly. The FFT panel describes the input; it is not an automatic period-selection stage in the wrapper."
        },
        {
          "title": "Estimate seasonal terms",
          "text": "Initialize seasonal arrays at zero. For each period in the upstream processing order, fit STL to the currently adjusted series and subtract the estimated seasonal term before processing the next period."
        },
        {
          "title": "Add back and refine each term",
          "text": "On each later pass, add back the previous estimate for the period being updated, refit that seasonal term, and subtract its replacement. This preserves the other current seasonal estimates while refining one term at a time."
        },
        {
          "title": "Aggregate the common output",
          "text": "Use the trend from the last STL fit and subtract it from the deseasonalized series to obtain residual. DeTime sums separate upstream seasonal columns into result.season. This animation uses lmbda=None; transformed fits require the wrapper's documented original-scale allocation."
        }
      ],
      "parameters": [
        {
          "name": "periods",
          "effect": "One or more integer cycle lengths. Upstream MSTL sorts them and filters periods that are too long for the record."
        },
        {
          "name": "windows",
          "effect": "Odd seasonal-smoothing spans paired with the periods; this example uses 11 and 15."
        },
        {
          "name": "iterate",
          "effect": "Number of passes over the seasonal terms; this example uses two."
        },
        {
          "name": "lmbda",
          "effect": "Optional Box-Cox transform. None keeps the additive trace in the original scale; transformed components cannot be inverted independently and then simply added."
        },
        {
          "name": "stl_kwargs",
          "effect": "Options forwarded to each STL fit, including its robustness setting."
        }
      ],
      "cautions": [
        "Choose periods with enough observed repetitions. The example is illustrative and does not identify periods from data.",
        "Closely related periods and smoothing choices can change how variation is allocated between seasonal terms.",
        "DeTime's common season field is the sum of upstream seasonal columns; individual periods in this animation are instrumented from the upstream procedure.",
        "For Box-Cox fits, DeTime uses inverse(T) for trend and inverse(T+S)-inverse(T) for combined season, with the remaining difference in residual. This no-transform trace does not animate that nonlinear allocation."
      ],
      "references": [
        {
          "title": "Bandara, Hyndman, and Bergmeir (2025), MSTL",
          "url": "https://www.inderscience.com/info/e_inarticle.php?artid=143957"
        },
        {
          "title": "statsmodels MSTL implementation contract",
          "url": "https://www.statsmodels.org/stable/generated/statsmodels.tsa.seasonal.MSTL.html"
        },
        {
          "title": "Cleveland et al. (1990), STL: A Seasonal-Trend Decomposition Procedure Based on Loess",
          "url": "https://www.scb.se/contentassets/ca21efb41fee47d293bbee5bf7be7fb3/stl-a-seasonal-trend-decomposition-procedure-based-on-loess.pdf"
        }
      ],
      "trace_kind": "computed upstream procedure trace",
      "trace_note": "The alternating STL loop follows the installed statsmodels MSTL.fit procedure with an explicit two-period, no-transform setup. Its separate seasonal estimates, final trend, and public DeTime output are checked numerically.",
      "input_note": "Deterministic synthetic teaching signal; not a benchmark.",
      "example_config": {
        "method": "MSTL",
        "backend": "python",
        "params": {
          "periods": [
            12,
            36
          ],
          "windows": [
            11,
            15
          ],
          "iterate": 2,
          "lmbda": null
        }
      },
      "checks": {
        "separate_seasons_vs_upstream_max_abs_error": 0.0,
        "trace_trend_vs_upstream_max_abs_error": 0.0,
        "aggregate_season_max_abs_error": 0.0,
        "trend_max_abs_error": 0.0,
        "residual_max_abs_error": 0.0,
        "additive_reconstruction_max_abs_error": 4.440892098500626e-16
      },
      "source_files": [
        "src/detime/methods/stl.py"
      ],
      "frames": 32,
      "duration_ms": 12050,
      "poster_frame": 15,
      "width": 1280,
      "height": 820,
      "artifacts": {
        "gif": {
          "file": "mstl.gif",
          "bytes": 443564,
          "sha256": "2775454700149bfd468fd77d953f94d099377b368e371f982d75815ccbb8c205"
        },
        "poster": {
          "file": "mstl.png",
          "bytes": 169208,
          "sha256": "c8a5d7e26fa2a51077a7801928422906a45e5ff1355eb1dabc00b29534d95bc1"
        },
        "data": {
          "file": "mstl.npz",
          "bytes": 29722,
          "sha256": "9888a9226aad8f91e5195507c1d22d2dbf73c0e9867310895a74a09bdffdd1a1"
        }
      },
      "source_arrays": {
        "t": [
          144
        ],
        "observed": [
          144
        ],
        "periods": [
          2
        ],
        "windows": [
          2
        ],
        "snapshot_inputs": [
          4,
          144
        ],
        "snapshot_old_seasons": [
          4,
          144
        ],
        "snapshot_new_seasons": [
          4,
          144
        ],
        "snapshot_all_seasons": [
          4,
          2,
          144
        ],
        "snapshot_adjusted": [
          4,
          144
        ],
        "upstream_seasonal_columns": [
          144,
          2
        ],
        "trend": [
          144
        ],
        "season": [
          144
        ],
        "residual": [
          144
        ]
      },
      "render_provenance": {
        "python_version": "3.12.14",
        "dependencies": {
          "numpy": "2.3.5",
          "scipy": "1.17.0",
          "statsmodels": "0.15.0",
          "matplotlib": "3.10.8",
          "Pillow": "12.3.0",
          "PyWavelets": "1.10.0",
          "EMD-signal": "1.10.0",
          "vmdpy": "0.2",
          "PySDKit": "0.5.0"
        },
        "source_hashes": {
          "scripts/generate_method_animations.py": "f62989af55a7e48495c24afcfee31751d3785e5f78bb4b900bef23a429deaa84",
          "scripts/method_animations/classical.py": "8a8a9ef82936f0aa5b1c5775c6c0158c3b48d3bc7dca1de691b83d95e5c23ba3",
          "scripts/method_animations/common.py": "73ad7e8b4e5b67f87d13e59adab2c93e983fe1aaf06ee627d22cb7c7e696016a",
          "src/detime/backends.py": "7432dcf59e382580dfb32f1f57e61ff71a30567c049b35243e24e3644523eda6",
          "src/detime/core.py": "d95b348cd8b16b56d18840965579c947a11628d969dd6c32c4af7723f5a027f4",
          "src/detime/methods/stl.py": "bb9db3808691490849d06b6eff3f1d6083b6d79fa4d0ea526201e6cec11bdd4d",
          "src/detime/registry.py": "e934ffca17880cefe5add728aa497e63ea811d7ae43abec1ea498de718094066"
        }
      }
    },
    {
      "method": "MVMD",
      "slug": "mvmd",
      "title": "MVMD: share mode frequencies across multiple channels",
      "summary": "MVMD couples channel-specific mode spectra through shared center frequencies. The modes can have different amplitudes and phases in each channel.",
      "steps": [
        {
          "title": "Align the channels",
          "text": "Supply measurements on a common time grid and prepare their mirrored spectra."
        },
        {
          "title": "Update channel spectra",
          "text": "Each channel fits a mode around the current shared center."
        },
        {
          "title": "Pool spectral energy",
          "text": "Update each center using the spectral energy from all channels, then repeat."
        },
        {
          "title": "Recover mode stacks",
          "text": "Invert the spectra and retain the (mode,time,channel) organization before application-specific grouping."
        }
      ],
      "parameters": [
        {
          "name": "K and alpha",
          "effect": "The teaching run uses three modes and bandwidth penalty 1500."
        },
        {
          "name": "Upstream trace settings",
          "effect": "Uniform initialization, tau=0, and max_iter=60 bound this PySDKit demonstration; not all are public DeTime parameters."
        },
        {
          "name": "primary_period / mode groups",
          "effect": "Controls DeTime's assignment of the returned modes to output components."
        }
      ],
      "cautions": [
        "The optional backend requires aligned multichannel input and an explicitly checked axis convention.",
        "PySDKit's all-axis FFT shift changes the internal channel order; its final inverse shift restores input order. The animation applies that same restoration to every displayed iterate.",
        "A shared mode center does not identify a shared causal source, and tau=0 can leave reconstruction error."
      ],
      "references": [
        {
          "title": "PySDKit MVMD interface and implementation",
          "url": "https://pysdkit.readthedocs.io/en/stable/API/pysdkit._vmd.html"
        },
        {
          "title": "Multivariate variational mode decomposition",
          "url": "https://doi.org/10.1109/TSP.2019.2951223"
        }
      ],
      "trace_kind": "upstream execution trace",
      "trace_note": "Captured PySDKit 0.5.0 joint solver arrays on input shaped (channel,time). Internal channels correspond to input indexes [2, 0, 1] (zero-based); applying indexes [1, 2, 0] restores original order in every displayed spectrum and mode. The final trace is checked against the upstream returned modes.",
      "input_note": "Deterministic synthetic teaching signal; not a benchmark.",
      "example_config": {
        "method": "MVMD",
        "params": {
          "K": 3,
          "alpha": 1500.0,
          "primary_period": 24
        },
        "backend": "python"
      },
      "checks": {
        "captured_final_iteration": 18,
        "trace_matches_upstream_modes": 1.8490349884547896e-07,
        "mode_sum_rmse": 0.05570209440280112,
        "backend_version": "0.5.0",
        "internal_channel_input_indexes": [
          2,
          0,
          1
        ],
        "output_channel_permutation": [
          1,
          2,
          0
        ],
        "finite_trace": true
      },
      "source_files": [
        "src/detime/methods/mvmd.py"
      ],
      "frames": 32,
      "duration_ms": 12050,
      "poster_frame": 15,
      "width": 1280,
      "height": 820,
      "artifacts": {
        "gif": {
          "file": "mvmd.gif",
          "bytes": 419913,
          "sha256": "32619e36a8e1a296dc46cdf9c85818f476f9c49a463b22d8b13efea16c0e05b1"
        },
        "poster": {
          "file": "mvmd.png",
          "bytes": 191673,
          "sha256": "9a7171d5f66eab1c0489e69167168e6ecb43a99555d8858909209b8c7fd06cd8"
        },
        "data": {
          "file": "mvmd.npz",
          "bytes": 250939,
          "sha256": "585b033414568d6f0e1feb3c571d70c088c4e001dad04176926d15528c6fbf9e"
        }
      },
      "source_arrays": {
        "time": [
          144
        ],
        "input_channels": [
          144,
          3
        ],
        "frequency_grid": [
          288
        ],
        "iteration_ids": [
          8
        ],
        "mode_spectra": [
          8,
          288,
          3,
          3
        ],
        "internal_mode_spectra": [
          8,
          288,
          3,
          3
        ],
        "shared_centers": [
          19,
          3
        ],
        "input_order_mode_trace": [
          8,
          3,
          144,
          3
        ],
        "internal_channel_input_indexes": [
          3
        ],
        "output_channel_permutation": [
          3
        ],
        "upstream_returned_modes": [
          3,
          144,
          3
        ]
      },
      "render_provenance": {
        "python_version": "3.11.3",
        "dependencies": {
          "numpy": "2.4.6",
          "scipy": "1.17.1",
          "statsmodels": "0.15.0",
          "matplotlib": "3.11.2",
          "Pillow": "13.0.0",
          "PyWavelets": "1.9.0",
          "EMD-signal": "1.10.0",
          "vmdpy": "0.2",
          "PySDKit": "0.5.0"
        },
        "source_hashes": {
          "scripts/generate_method_animations.py": "f62989af55a7e48495c24afcfee31751d3785e5f78bb4b900bef23a429deaa84",
          "scripts/method_animations/adaptive.py": "7d728d88b4ba1a8dd82890c7a6b017d542728b50dc477c281e9bbfcbae164a1d",
          "scripts/method_animations/common.py": "73ad7e8b4e5b67f87d13e59adab2c93e983fe1aaf06ee627d22cb7c7e696016a",
          "src/detime/backends.py": "7432dcf59e382580dfb32f1f57e61ff71a30567c049b35243e24e3644523eda6",
          "src/detime/core.py": "d95b348cd8b16b56d18840965579c947a11628d969dd6c32c4af7723f5a027f4",
          "src/detime/methods/mvmd.py": "3e66ea12f131795eeb5ebbb24bd6affe7bfc104ac94ef7d8cdeaff6073413fd7",
          "src/detime/registry.py": "e934ffca17880cefe5add728aa497e63ea811d7ae43abec1ea498de718094066"
        }
      }
    },
    {
      "method": "NBEATS_INTERPRETABLE",
      "slug": "nbeats-interpretable",
      "title": "N-BEATS: untrained basis illustration",
      "summary": "This teaching illustration follows the source's polynomial and Fourier basis formulas and its separate backcast/output branches. All coefficients are explicitly chosen constants. The actual NBEATS_INTERPRETABLE method trains an MLP for each decomposition call using Torch, but that optional backend is not executed for this asset. The animation explains the basis mechanism and residual bookkeeping without presenting an untrained curve as a learned decomposition.",
      "steps": [
        {
          "title": "Construct fixed basis functions",
          "text": "The source creates polynomial trend bases and integer Fourier harmonics on a normalized grid from zero to one."
        },
        {
          "title": "Separate backcast and output weights",
          "text": "An actual trained block predicts separate coefficients for backcast subtraction and output accumulation. Here both coefficient vectors are explicitly chosen teaching values."
        },
        {
          "title": "Pass a remainder to seasonal blocks",
          "text": "Subtract the backcast contribution, then illustrate a seasonal block's separate backcast and output branches using the Fourier bases."
        },
        {
          "title": "Distinguish the two residuals",
          "text": "The internal remainder subtracts backcasts. The public wrapper instead derives its residual from the observed input minus the accumulated trend and seasonal outputs."
        }
      ],
      "parameters": [
        {
          "name": "degree_of_polynomial",
          "effect": "Sets the degree of the trend basis on the normalized full-record grid."
        },
        {
          "name": "num_harmonics",
          "effect": "Sets integer Fourier harmonics on normalized time; primary_period does not set these frequencies."
        },
        {
          "name": "trend_blocks / seasonality_blocks",
          "effect": "Set the numbers of residual-processing MLP blocks in an actual Torch execution."
        },
        {
          "name": "n_epochs / restarts / seed",
          "effect": "Control actual optimization when the optional method is run; they do not generate the fixed coefficients in this animation."
        }
      ],
      "cautions": [
        "This is an untrained basis illustration. No neural checkpoint, optimization trace or public-method output is claimed for this asset.",
        "The example configuration below would train the optional method and will not reproduce the illustration's chosen coefficients.",
        "The current source standardizes using the full record before applying a prefix loss mask. fit_scope='prefix' therefore must not be described as leakage-free forecasting.",
        "The source fits a decomposition to one supplied series. Its same-length outputs do not establish generalization to unseen future observations.",
        "The public residual is recomputed from the named outputs and differs from the internal remainder produced by subtracting backcasts."
      ],
      "references": [
        {
          "title": "Implemented DeTime operator",
          "url": "https://github.com/systems-mechanobiology/DeTime/blob/main/src/detime/methods/neural_blocks/learned_priors.py"
        },
        {
          "title": "Oreshkin et al. (2020), N-BEATS: Neural basis expansion analysis for interpretable time series forecasting",
          "url": "https://openreview.net/forum?id=r1ecqn4YwB"
        }
      ],
      "trace_kind": "basis_illustration_untrained",
      "trace_note": "NumPy evaluates the polynomial/Fourier basis formulas with recorded, fixed teaching coefficients. Torch is not required, the public method is not run, and equality to a trained model is not asserted.",
      "input_note": "Deterministic synthetic teaching signal; not a benchmark.",
      "example_config": {
        "method": "NBEATS_INTERPRETABLE",
        "backend": "python",
        "params": {
          "degree_of_polynomial": 2,
          "num_harmonics": 6,
          "trend_blocks": 1,
          "seasonality_blocks": 1,
          "layers": 1,
          "layer_size": 16,
          "fit_scope": "full",
          "n_epochs": 30,
          "restarts": 1,
          "device": "cpu",
          "seed": 42
        }
      },
      "checks": {
        "public_method_executed": false,
        "trained_checkpoint_used": false,
        "coefficient_provenance": "Explicit fixed teaching constants in neural.py",
        "basis_formula_source_inspected": true,
        "illustrative_reconstruction_max_abs_error": 2.220446049250313e-16
      },
      "source_files": [
        "src/detime/methods/neural_blocks/learned_priors.py"
      ],
      "frames": 32,
      "duration_ms": 12050,
      "poster_frame": 15,
      "width": 1280,
      "height": 820,
      "artifacts": {
        "gif": {
          "file": "nbeats-interpretable.gif",
          "bytes": 336173,
          "sha256": "d2b1f8e23f7f15e079579569dd451a148737d2ea6440d8e06ff7b8cb8d8fb5c2"
        },
        "poster": {
          "file": "nbeats-interpretable.png",
          "bytes": 140332,
          "sha256": "7992ac1c765fed524a06adc57265a37fc51a8ce62f4de8b393e2961f716d2e7e"
        },
        "data": {
          "file": "nbeats-interpretable.npz",
          "bytes": 18539,
          "sha256": "3e478e580ebaf53688689721e8bf89a318d9f33faf0a3e9d3bf19a498ef8e6d2"
        }
      },
      "source_arrays": {
        "observed": [
          144
        ],
        "normalized_input": [
          144
        ],
        "normalized_time": [
          144
        ],
        "polynomial_basis": [
          3,
          144
        ],
        "cosine_basis": [
          6,
          144
        ],
        "sine_basis": [
          6,
          144
        ],
        "trend_backcast_coefficients": [
          3
        ],
        "trend_output_coefficients": [
          3
        ],
        "season_backcast_cos_coefficients": [
          6
        ],
        "season_backcast_sin_coefficients": [
          6
        ],
        "season_output_cos_coefficients": [
          6
        ],
        "season_output_sin_coefficients": [
          6
        ],
        "trend_backcast": [
          144
        ],
        "season_backcast": [
          144
        ],
        "internal_remainder": [
          144
        ],
        "illustrative_trend_output": [
          144
        ],
        "illustrative_season_output": [
          144
        ],
        "illustrative_public_residual": [
          144
        ]
      },
      "render_provenance": {
        "python_version": "3.12.14",
        "dependencies": {
          "numpy": "2.3.5",
          "scipy": "1.17.0",
          "statsmodels": "0.15.0",
          "matplotlib": "3.10.8",
          "Pillow": "12.3.0",
          "PyWavelets": "1.10.0",
          "EMD-signal": "1.10.0",
          "vmdpy": "0.2",
          "PySDKit": "0.5.0"
        },
        "source_hashes": {
          "scripts/generate_method_animations.py": "f62989af55a7e48495c24afcfee31751d3785e5f78bb4b900bef23a429deaa84",
          "scripts/method_animations/common.py": "73ad7e8b4e5b67f87d13e59adab2c93e983fe1aaf06ee627d22cb7c7e696016a",
          "scripts/method_animations/neural.py": "fc1c2a73490391f0f863ede52e38f12924cc1fec572b7188356a2308216716e6",
          "src/detime/backends.py": "7432dcf59e382580dfb32f1f57e61ff71a30567c049b35243e24e3644523eda6",
          "src/detime/core.py": "d95b348cd8b16b56d18840965579c947a11628d969dd6c32c4af7723f5a027f4",
          "src/detime/methods/neural_blocks/learned_priors.py": "af5a1d6b744e01a46358847aa05e156e92859d5f58334b0bc6a74d3169d2f2f0",
          "src/detime/registry.py": "e934ffca17880cefe5add728aa497e63ea811d7ae43abec1ea498de718094066"
        }
      }
    },
    {
      "method": "PARSIMONY_BLOCK",
      "slug": "parsimony-block",
      "title": "Parsimony block: a compact harmonic fit",
      "summary": "This implementation first smooths the observed series, then projects the remaining signal onto cosine and sine columns at a supplied period. It is a fixed-basis least-squares operator. The trace makes the design matrix, fitted coefficients and additive contributions visible; it does not reproduce a complete forecasting architecture from the cited paper.",
      "steps": [
        {
          "title": "Remove a smoothed trend",
          "text": "Estimate the trend with a 25-sample centered mean, then form the signal to project onto harmonic basis functions."
        },
        {
          "title": "Build the harmonic design",
          "text": "Create cosine and sine columns at the requested period and its harmonics, and solve their coefficients by ordinary least squares."
        },
        {
          "title": "Add fitted basis terms",
          "text": "The animation adds the already fitted weighted basis terms. This is an algebraic construction, not an optimization trajectory."
        },
        {
          "title": "Inspect the decomposition",
          "text": "The trend, harmonic projection and remaining residual match the registered standalone operator."
        }
      ],
      "parameters": [
        {
          "name": "trend_window",
          "effect": "Controls which structure remains after centered trend smoothing."
        },
        {
          "name": "primary_period",
          "effect": "Sets the base harmonic period in sample units."
        },
        {
          "name": "num_harmonics",
          "effect": "Adds paired cosine/sine columns. More terms increase representational capacity without guaranteeing better identification."
        },
        {
          "name": "fit_scope",
          "effect": "The example uses the complete record. Prefix fitting estimates coefficients on the chosen prefix and evaluates the basis over the record."
        }
      ],
      "cautions": [
        "The harmonic coefficients are fitted numerically, but this standalone operator has no trained neural backbone.",
        "Changing the supplied period changes the basis. The algorithm does not establish that the period is physically correct.",
        "The visual addition of basis terms is not the temporal sequence of a training algorithm.",
        "Full-record smoothing and fitting require an appropriate information boundary before downstream forecasting."
      ],
      "references": [
        {
          "title": "Implemented DeTime operator",
          "url": "https://github.com/systems-mechanobiology/DeTime/blob/main/src/detime/methods/neural_blocks/neural_block_portfolio.py"
        },
        {
          "title": "Deng et al. (2024), Parsimony or Capability? Decomposition Delivers Both in Long-term Time Series Forecasting",
          "url": "https://arxiv.org/abs/2401.11929"
        }
      ],
      "trace_kind": "computed_operator_trace",
      "trace_note": "Intermediate arrays are computed with the implemented operator helpers. The final trend, season and residual are checked against public decompose(). The animation explains this standalone experimental block; its source architecture is cited for provenance.",
      "input_note": "Deterministic synthetic teaching signal; not a benchmark.",
      "example_config": {
        "method": "PARSIMONY_BLOCK",
        "params": {
          "primary_period": 24,
          "trend_window": 25,
          "num_harmonics": 2,
          "fit_scope": "full"
        },
        "backend": "python"
      },
      "checks": {
        "public_method_executed": true,
        "method_output_max_abs_errors": {
          "trend": 0.0,
          "season": 0.0,
          "residual": 0.0
        },
        "reconstruction_max_abs_error": 4.440892098500626e-16,
        "validation_scope": "One deterministic teaching input; no benchmark claim."
      },
      "source_files": [
        "src/detime/methods/neural_blocks/neural_block_portfolio.py"
      ],
      "frames": 32,
      "duration_ms": 12050,
      "poster_frame": 15,
      "width": 1280,
      "height": 820,
      "artifacts": {
        "gif": {
          "file": "parsimony-block.gif",
          "bytes": 378903,
          "sha256": "65f5f167a8383684ed8bb9ef047e02605c89c0eb4fa0c674f9fdd6eb50d355c8"
        },
        "poster": {
          "file": "parsimony-block.png",
          "bytes": 147676,
          "sha256": "d9d9578389859bedc8d1c975bbd9344f8394e517c3f1bbd547d2d7de9cff48f0"
        },
        "data": {
          "file": "parsimony-block.npz",
          "bytes": 9888,
          "sha256": "75509beb3764e2b80ce556f64b6637069e483a257447b4bf9fa011553c71e471"
        }
      },
      "source_arrays": {
        "observed": [
          144
        ],
        "trend": [
          144
        ],
        "detrended": [
          144
        ],
        "harmonic_design": [
          144,
          4
        ],
        "coefficients": [
          4
        ],
        "weighted_terms": [
          4,
          144
        ],
        "season": [
          144
        ],
        "residual": [
          144
        ]
      },
      "render_provenance": {
        "python_version": "3.12.14",
        "dependencies": {
          "numpy": "2.3.5",
          "scipy": "1.17.0",
          "statsmodels": "0.15.0",
          "matplotlib": "3.10.8",
          "Pillow": "12.3.0",
          "PyWavelets": "1.10.0",
          "EMD-signal": "1.10.0",
          "vmdpy": "0.2",
          "PySDKit": "0.5.0"
        },
        "source_hashes": {
          "scripts/generate_method_animations.py": "f62989af55a7e48495c24afcfee31751d3785e5f78bb4b900bef23a429deaa84",
          "scripts/method_animations/common.py": "73ad7e8b4e5b67f87d13e59adab2c93e983fe1aaf06ee627d22cb7c7e696016a",
          "scripts/method_animations/neural.py": "fc1c2a73490391f0f863ede52e38f12924cc1fec572b7188356a2308216716e6",
          "src/detime/backends.py": "7432dcf59e382580dfb32f1f57e61ff71a30567c049b35243e24e3644523eda6",
          "src/detime/core.py": "d95b348cd8b16b56d18840965579c947a11628d969dd6c32c4af7723f5a027f4",
          "src/detime/methods/neural_blocks/neural_block_portfolio.py": "2aab635b9927d1d42bbcd8e0b4f37cb9fcdcf85cbd0331b5011621b495c4acfa",
          "src/detime/registry.py": "e934ffca17880cefe5add728aa497e63ea811d7ae43abec1ea498de718094066"
        }
      }
    },
    {
      "method": "ROBUST_STL",
      "slug": "robust-stl",
      "title": "Reweight observations and refit",
      "summary": "Residual-based robustness weights limit how strongly unusual observations influence subsequent STL smooths.",
      "steps": [
        {
          "title": "Fit initial smooths",
          "text": "DeTime's ROBUST_STL selects statsmodels STL with robust=True by default. The initial inner loop estimates seasonal and trend structure before robustness weights are updated."
        },
        {
          "title": "Compute robustness weights",
          "text": "The first outer update uses absolute residuals from the initial fit. With h equal to six times their median, the bisquare rule assigns (1 - (abs(residual)/h)^2)^2 below h and zero above h. This example computes those weights and checks them against statsmodels."
        },
        {
          "title": "Refit and update the weights",
          "text": "Repeated outer iterations recalculate robustness weights and refit seasonal and trend smooths. Each shown checkpoint is a fresh deterministic statsmodels fit with the indicated iteration budget; it reaches the same state for that budget."
        },
        {
          "title": "Retain a residual",
          "text": "The wrapper returns the final trend, seasonal component, and residual. Downweighted observations remain in the input, so their unexplained values appear in the residual. The animation also displays upstream weights, which the current DeTime wrapper does not export as a result component."
        }
      ],
      "parameters": [
        {
          "name": "period",
          "effect": "Specified number of samples in a seasonal cycle; this example uses 12."
        },
        {
          "name": "seasonal",
          "effect": "Odd LOESS span across cycles for the seasonal subseries; smaller spans allow faster seasonal change."
        },
        {
          "name": "trend / low_pass",
          "effect": "Odd smoothing spans controlling trend and low-pass behavior; this example uses 23 and 13."
        },
        {
          "name": "robust",
          "effect": "Controls the outer reweighting loop. ROBUST_STL defaults to True; setting it False disables robustness."
        }
      ],
      "cautions": [
        "ROBUST_STL is the registry name for statsmodels STL with its robust option. This name does not establish implementation of other published algorithms also called RobustSTL.",
        "Smoothing spans, seasonal period, endpoint handling, and outliers influence the estimated components.",
        "The animation uses statsmodels' actual checkpoints. Internal fits are restarted for each budget; frame count is not an execution-time measure.",
        "STL is an offline smoother. Use only available history when constructing forecasting features."
      ],
      "references": [
        {
          "title": "Cleveland et al. (1990), STL: A Seasonal-Trend Decomposition Procedure Based on Loess",
          "url": "https://www.scb.se/contentassets/ca21efb41fee47d293bbee5bf7be7fb3/stl-a-seasonal-trend-decomposition-procedure-based-on-loess.pdf"
        },
        {
          "title": "statsmodels STL: parameters and implementation contract",
          "url": "https://www.statsmodels.org/stable/generated/statsmodels.tsa.seasonal.STL.html"
        }
      ],
      "trace_kind": "computed iteration trace",
      "trace_note": "All robustness weights and iteration checkpoints are computed from statsmodels; the first bisquare update is independently calculated and compared. Final arrays match DeTime's Python wrapper.",
      "input_note": "Deterministic synthetic teaching signal; not a benchmark.",
      "example_config": {
        "method": "ROBUST_STL",
        "backend": "python",
        "params": {
          "period": 12,
          "seasonal": 7,
          "trend": 23,
          "low_pass": 13,
          "robust": true
        }
      },
      "checks": {
        "checkpoint_trend_max_abs_error": 0.0,
        "checkpoint_season_max_abs_error": 0.0,
        "checkpoint_residual_max_abs_error": 0.0,
        "additive_reconstruction_max_abs_error": 4.440892098500626e-16,
        "first_bisquare_weights_max_abs_error": 7.771561172376096e-16
      },
      "source_files": [
        "src/detime/methods/stl.py"
      ],
      "frames": 32,
      "duration_ms": 12050,
      "poster_frame": 15,
      "width": 1280,
      "height": 820,
      "artifacts": {
        "gif": {
          "file": "robust-stl.gif",
          "bytes": 567267,
          "sha256": "0ffd693725dffd72bd8886c6c088c8d5802858ec72a522f05f7d89b07a6d7e0d"
        },
        "poster": {
          "file": "robust-stl.png",
          "bytes": 143959,
          "sha256": "013b0f041bbee807192b8799682d75745470aff7649d783f013c627f9319b63c"
        },
        "data": {
          "file": "robust-stl.npz",
          "bytes": 45231,
          "sha256": "739f66750ff6b2f0133866dec3e6219ed7f36d87ef4c9b9c723e8a17628b6634"
        }
      },
      "source_arrays": {
        "t": [
          144
        ],
        "observed": [
          144
        ],
        "iteration_budgets": [
          8
        ],
        "checkpoint_trend": [
          8,
          144
        ],
        "checkpoint_season": [
          8,
          144
        ],
        "checkpoint_residual": [
          8,
          144
        ],
        "checkpoint_weights": [
          8,
          144
        ],
        "first_bisquare_weights": [
          144
        ],
        "bisquare_curve_residuals": [
          100
        ],
        "bisquare_curve_weights": [
          100
        ],
        "loess_phase_values": [
          12
        ],
        "loess_local_weights": [
          12,
          12
        ],
        "loess_local_fits": [
          12,
          12
        ],
        "trend": [
          144
        ],
        "season": [
          144
        ],
        "residual": [
          144
        ]
      },
      "render_provenance": {
        "python_version": "3.12.14",
        "dependencies": {
          "numpy": "2.3.5",
          "scipy": "1.17.0",
          "statsmodels": "0.15.0",
          "matplotlib": "3.10.8",
          "Pillow": "12.3.0",
          "PyWavelets": "1.10.0",
          "EMD-signal": "1.10.0",
          "vmdpy": "0.2",
          "PySDKit": "0.5.0"
        },
        "source_hashes": {
          "scripts/generate_method_animations.py": "f62989af55a7e48495c24afcfee31751d3785e5f78bb4b900bef23a429deaa84",
          "scripts/method_animations/classical.py": "8a8a9ef82936f0aa5b1c5775c6c0158c3b48d3bc7dca1de691b83d95e5c23ba3",
          "scripts/method_animations/common.py": "73ad7e8b4e5b67f87d13e59adab2c93e983fe1aaf06ee627d22cb7c7e696016a",
          "src/detime/backends.py": "7432dcf59e382580dfb32f1f57e61ff71a30567c049b35243e24e3644523eda6",
          "src/detime/core.py": "d95b348cd8b16b56d18840965579c947a11628d969dd6c32c4af7723f5a027f4",
          "src/detime/methods/stl.py": "bb9db3808691490849d06b6eff3f1d6083b6d79fa4d0ea526201e6cec11bdd4d",
          "src/detime/registry.py": "e934ffca17880cefe5add728aa497e63ea811d7ae43abec1ea498de718094066"
        }
      }
    },
    {
      "method": "SSA",
      "slug": "ssa",
      "title": "Turn overlapping windows into modes",
      "summary": "SSA decomposes a lag matrix and maps its grouped modes back to time-domain components.",
      "steps": [
        {
          "title": "Embed overlapping windows",
          "text": "Slide an L-sample window across the series. Put each window in a column. Repeated observations lie on anti-diagonals, which is the Hankel structure used by SSA."
        },
        {
          "title": "Factor the trajectory matrix",
          "text": "Compute X = U diag(s) V^T. Each singular triplet gives one rank-one matrix. Retaining only a chosen number of modes determines which matrix structure can enter subsequent grouping."
        },
        {
          "title": "Average each anti-diagonal",
          "text": "A rank-one matrix need not itself be Hankel. Average its anti-diagonals to turn its repeated time-index estimates back into one time-domain reconstructed component."
        },
        {
          "title": "Group trend and season",
          "text": "This example uses DeTime's primary-period frequency heuristic. Low-frequency modes are assigned to trend and modes near 1/period to season, with documented fallbacks if a group is empty. Residual is the observed input minus those two groups. Explicit component-index lists can replace this automatic grouping."
        }
      ],
      "parameters": [
        {
          "name": "window",
          "effect": "Embedding length L; changes the temporal scale and matrix dimensions."
        },
        {
          "name": "rank",
          "effect": "Number of singular modes available for grouping; more modes can retain both signal structure and noise."
        },
        {
          "name": "primary_period",
          "effect": "Target period for the frequency-based seasonal grouping heuristic."
        },
        {
          "name": "trend_components / season_components",
          "effect": "Optional zero-based mode indices that explicitly define the groups."
        },
        {
          "name": "season_freq_tol_ratio / trend_freq_threshold",
          "effect": "Control the frequency bands used by automatic grouping."
        }
      ],
      "cautions": [
        "The labels trend and season come from a grouping rule; singular-value order alone does not establish physical meaning.",
        "Changing window, rank, or grouping can change components even when additive reconstruction remains exact.",
        "The animation uses backend='python', speed_mode='exact'. Native or randomized fast paths are separate numerical execution choices.",
        "This is an offline decomposition. Forecasting features must be recomputed using only observations available at each forecast origin."
      ],
      "references": [
        {
          "title": "Golyandina and Zhigljavsky (2020), Singular Spectrum Analysis for Time Series",
          "url": "https://link.springer.com/book/10.1007/978-3-662-62436-4"
        }
      ],
      "trace_kind": "computed operator trace",
      "trace_note": "The trajectory matrix, exact SVD, reconstructed modes, and grouped outputs are computed from the source algorithm. Checks compare trace modes and final groups with the configured Python implementation. The animation explains construction order, not solver wall-clock execution.",
      "input_note": "Deterministic synthetic teaching signal; not a benchmark.",
      "example_config": {
        "method": "SSA",
        "backend": "python",
        "speed_mode": "exact",
        "params": {
          "window": 36,
          "rank": 8,
          "primary_period": 24
        }
      },
      "checks": {
        "trace_modes_vs_implementation_max_abs_error": 0.0,
        "grouped_trend_max_abs_error": 0.0,
        "grouped_season_max_abs_error": 0.0,
        "additive_reconstruction_max_abs_error": 4.440892098500626e-16,
        "full_svd_matrix_reconstruction_max_abs_error": 5.828670879282072e-15
      },
      "source_files": [
        "src/detime/methods/ssa.py",
        "native/src/ssa.cpp",
        "src/detime/methods/utils.py"
      ],
      "frames": 32,
      "duration_ms": 12050,
      "poster_frame": 15,
      "width": 1280,
      "height": 820,
      "artifacts": {
        "gif": {
          "file": "ssa.gif",
          "bytes": 721507,
          "sha256": "9fa2090a6e9a0f444e3abd3a5233b9481ce3c7d955f7e168d72213fca41e7e3a"
        },
        "poster": {
          "file": "ssa.png",
          "bytes": 128459,
          "sha256": "9b291309678ba92a563147004a4df078fe164602adef2c92d7a5e9a825e2856c"
        },
        "data": {
          "file": "ssa.npz",
          "bytes": 258022,
          "sha256": "f4a2100b2a8b516c442251de2f6fe9c434c59348a1b9d8159aabe0a6d77866bd"
        }
      },
      "source_arrays": {
        "t": [
          144
        ],
        "observed": [
          144
        ],
        "trajectory": [
          36,
          109
        ],
        "singular_values": [
          36
        ],
        "rank_one_matrices": [
          8,
          36,
          109
        ],
        "reconstructed_modes": [
          8,
          144
        ],
        "dominant_frequencies": [
          8
        ],
        "trend_indices": [
          2
        ],
        "season_indices": [
          2
        ],
        "trend": [
          144
        ],
        "season": [
          144
        ],
        "residual": [
          144
        ]
      },
      "render_provenance": {
        "python_version": "3.12.14",
        "dependencies": {
          "numpy": "2.3.5",
          "scipy": "1.17.0",
          "statsmodels": "0.15.0",
          "matplotlib": "3.10.8",
          "Pillow": "12.3.0",
          "PyWavelets": "1.10.0",
          "EMD-signal": "1.10.0",
          "vmdpy": "0.2",
          "PySDKit": "0.5.0"
        },
        "source_hashes": {
          "native/src/ssa.cpp": "9ed883b360325878d3bc7c087be5396b8052001fe9a8450f871929267b44ba08",
          "scripts/generate_method_animations.py": "f62989af55a7e48495c24afcfee31751d3785e5f78bb4b900bef23a429deaa84",
          "scripts/method_animations/classical.py": "8a8a9ef82936f0aa5b1c5775c6c0158c3b48d3bc7dca1de691b83d95e5c23ba3",
          "scripts/method_animations/common.py": "73ad7e8b4e5b67f87d13e59adab2c93e983fe1aaf06ee627d22cb7c7e696016a",
          "src/detime/backends.py": "7432dcf59e382580dfb32f1f57e61ff71a30567c049b35243e24e3644523eda6",
          "src/detime/core.py": "d95b348cd8b16b56d18840965579c947a11628d969dd6c32c4af7723f5a027f4",
          "src/detime/methods/ssa.py": "ccb7b7d19fb9bdacedb12f8241f0ea0fc233edd498444a008b6040e21b4faac9",
          "src/detime/methods/utils.py": "6963d1ecdf76f1920671a262d125f0d822ae620b1e532849a002be1b7b36e7fd",
          "src/detime/registry.py": "e934ffca17880cefe5add728aa497e63ea811d7ae43abec1ea498de718094066"
        }
      }
    },
    {
      "method": "STD",
      "slug": "std",
      "title": "Separate cycle level, scale, and shape",
      "summary": "STD represents each cycle using its mean, an L2 dispersion, and its own normalized shape.",
      "steps": [
        {
          "title": "Partition and center cycles",
          "text": "Split at the configured period, compute each block's arithmetic mean, and subtract it. DeTime assigns that mean to every sample of the block, producing a piecewise-constant trend. A final partial block uses the samples that exist."
        },
        {
          "title": "Separate dispersion and shape",
          "text": "Compute the Euclidean norm of each centered block as its dispersion. Divide by that norm to obtain a unit-length seasonal shape. A block whose norm is below eps receives zero dispersion and a zero shape."
        },
        {
          "title": "Restore each cycle's shape",
          "text": "Multiply every cycle's own normalized shape by its own dispersion. This recovers the centered block, including irregular fluctuations. Add the block mean to reconstruct the observed values."
        },
        {
          "title": "Compute the common result",
          "text": "Return trend, the scaled seasonal term, and residual = observed - trend - season, plus dispersion and seasonal-shape arrays. Residual is approximately zero by construction for nondegenerate blocks; this behavior is part of the representation and is not a denoising result."
        }
      ],
      "parameters": [
        {
          "name": "period",
          "effect": "Block length and seasonal phase convention; a wrong period changes levels, scales, and shape alignment."
        },
        {
          "name": "eps",
          "effect": "Threshold below which a centered block is treated as having zero dispersion."
        },
        {
          "name": "max_period_search",
          "effect": "Upper bound on the FFT-based period heuristic used only when period is omitted; this animation supplies the period explicitly."
        }
      ],
      "cautions": [
        "DeTime's STD/STDR use block means and L2 norms. Dispersion is not the sample standard deviation.",
        "STDR uses ordinary phase-wise means of normalized shapes. No robust loss, trimming, or outlier weights are used in this implementation.",
        "A partial cycle has its own mean and norm and contributes only available phases; its scale is not directly comparable to a full cycle without accounting for length.",
        "STD retains within-cycle irregular variation in its shape. STDR assigns deviations from a shared shape to the remainder.",
        "The supplied period and the starting phase define block boundaries; shifting the start changes the decomposition."
      ],
      "references": [
        {
          "title": "Dudek (2022), STD: A Seasonal-Trend-Dispersion Decomposition of Time Series",
          "url": "https://arxiv.org/abs/2204.10398"
        }
      ],
      "trace_kind": "computed operator trace",
      "trace_note": "Every stage follows compute_std_components and the corresponding native kernel: block means, Euclidean norms, phase counts, and scaling. Both direct-source and public Python outputs are compared. The final short block is intentional.",
      "input_note": "Deterministic synthetic teaching signal; not a benchmark.",
      "example_config": {
        "method": "STD",
        "backend": "python",
        "params": {
          "period": 24
        }
      },
      "checks": {
        "traced_block_levels_max_abs_error": 0.0,
        "traced_dispersion_max_abs_error": 0.0,
        "traced_shape_max_abs_error": 0.0,
        "traced_season_max_abs_error": 0.0,
        "source_trend_max_abs_error": 0.0,
        "source_season_max_abs_error": 0.0,
        "source_residual_max_abs_error": 0.0,
        "additive_reconstruction_max_abs_error": 1.1102230246251565e-16,
        "phase_average_trace_max_abs_error": 0.0
      },
      "source_files": [
        "src/detime/methods/std.py",
        "native/src/std.cpp"
      ],
      "frames": 32,
      "duration_ms": 12050,
      "poster_frame": 15,
      "width": 1280,
      "height": 820,
      "artifacts": {
        "gif": {
          "file": "std.gif",
          "bytes": 515998,
          "sha256": "20d38863184525ea57cdb9b1aebd01c06ee9eb3d07b9d5c0b1f540ce30202f50"
        },
        "poster": {
          "file": "std.png",
          "bytes": 101102,
          "sha256": "f3800abeaec1687e394c09a7ebdb92d19beb6bddbfe09d3c178f65b309ee4d8f"
        },
        "data": {
          "file": "std.npz",
          "bytes": 8822,
          "sha256": "bfb69bb445168616d3e7d296814dcf081fd77f0126e772ec2bfbc1d463f41ff5"
        }
      },
      "source_arrays": {
        "t": [
          139
        ],
        "observed": [
          139
        ],
        "block_means": [
          6
        ],
        "block_dispersion": [
          6
        ],
        "normalized_shapes_zero_padded": [
          6,
          24
        ],
        "phase_available_mask": [
          6,
          24
        ],
        "running_phase_counts": [
          6,
          24
        ],
        "running_average_shapes": [
          6,
          24
        ],
        "sample_dispersion": [
          139
        ],
        "returned_seasonal_shape": [
          139
        ],
        "trend": [
          139
        ],
        "season": [
          139
        ],
        "residual": [
          139
        ]
      },
      "render_provenance": {
        "python_version": "3.12.14",
        "dependencies": {
          "numpy": "2.3.5",
          "scipy": "1.17.0",
          "statsmodels": "0.15.0",
          "matplotlib": "3.10.8",
          "Pillow": "12.3.0",
          "PyWavelets": "1.10.0",
          "EMD-signal": "1.10.0",
          "vmdpy": "0.2",
          "PySDKit": "0.5.0"
        },
        "source_hashes": {
          "native/src/std.cpp": "5d5fddc1b7267985d73336386b9a34834b688eab60266430669b4a049c59ad4c",
          "scripts/generate_method_animations.py": "f62989af55a7e48495c24afcfee31751d3785e5f78bb4b900bef23a429deaa84",
          "scripts/method_animations/classical.py": "8a8a9ef82936f0aa5b1c5775c6c0158c3b48d3bc7dca1de691b83d95e5c23ba3",
          "scripts/method_animations/common.py": "73ad7e8b4e5b67f87d13e59adab2c93e983fe1aaf06ee627d22cb7c7e696016a",
          "src/detime/backends.py": "7432dcf59e382580dfb32f1f57e61ff71a30567c049b35243e24e3644523eda6",
          "src/detime/core.py": "d95b348cd8b16b56d18840965579c947a11628d969dd6c32c4af7723f5a027f4",
          "src/detime/methods/std.py": "7d72be4a4bff8c15f3723eaf1198d55b6863c517caa592690a5858f3e30f3578",
          "src/detime/registry.py": "e934ffca17880cefe5add728aa497e63ea811d7ae43abec1ea498de718094066"
        }
      }
    },
    {
      "method": "STDR",
      "slug": "stdr",
      "title": "Average normalized cycle shapes",
      "summary": "STDR uses a phase-wise average of normalized cycle shapes, then restores each cycle's dispersion and keeps a remainder.",
      "steps": [
        {
          "title": "Partition and center cycles",
          "text": "Split at the configured period, compute each block's arithmetic mean, and subtract it. DeTime assigns that mean to every sample of the block, producing a piecewise-constant trend. A final partial block uses the samples that exist."
        },
        {
          "title": "Separate dispersion and shape",
          "text": "Compute the Euclidean norm of each centered block as its dispersion. Divide by that norm to obtain a unit-length seasonal shape. A block whose norm is below eps receives zero dispersion and a zero shape."
        },
        {
          "title": "Average shapes across cycles",
          "text": "Average normalized shape entries at the same phase across cycles. For a partial cycle, increment counts only for available phases. Multiply this shared average by each cycle's own dispersion; the average shape is not normalized again."
        },
        {
          "title": "Compute the common result",
          "text": "Return trend, the scaled seasonal term, and residual = observed - trend - season, plus dispersion and seasonal-shape arrays. Deviations from the common cycle shape remain in the residual. In the cited formulation, R denotes a remainder; the code does not perform robust reweighting."
        }
      ],
      "parameters": [
        {
          "name": "period",
          "effect": "Block length and seasonal phase convention; a wrong period changes levels, scales, and shape alignment."
        },
        {
          "name": "eps",
          "effect": "Threshold below which a centered block is treated as having zero dispersion."
        },
        {
          "name": "max_period_search",
          "effect": "Upper bound on the FFT-based period heuristic used only when period is omitted; this animation supplies the period explicitly."
        }
      ],
      "cautions": [
        "DeTime's STD/STDR use block means and L2 norms. Dispersion is not the sample standard deviation.",
        "STDR uses ordinary phase-wise means of normalized shapes. No robust loss, trimming, or outlier weights are used in this implementation.",
        "A partial cycle has its own mean and norm and contributes only available phases; its scale is not directly comparable to a full cycle without accounting for length.",
        "STD retains within-cycle irregular variation in its shape. STDR assigns deviations from a shared shape to the remainder.",
        "The supplied period and the starting phase define block boundaries; shifting the start changes the decomposition."
      ],
      "references": [
        {
          "title": "Dudek (2022), STD: A Seasonal-Trend-Dispersion Decomposition of Time Series",
          "url": "https://arxiv.org/abs/2204.10398"
        }
      ],
      "trace_kind": "computed operator trace",
      "trace_note": "Every stage follows compute_std_components and the corresponding native kernel: block means, Euclidean norms, phase counts, and scaling. Both direct-source and public Python outputs are compared. The final short block is intentional.",
      "input_note": "Deterministic synthetic teaching signal; not a benchmark.",
      "example_config": {
        "method": "STDR",
        "backend": "python",
        "params": {
          "period": 24
        }
      },
      "checks": {
        "traced_block_levels_max_abs_error": 0.0,
        "traced_dispersion_max_abs_error": 0.0,
        "traced_shape_max_abs_error": 0.0,
        "traced_season_max_abs_error": 0.0,
        "source_trend_max_abs_error": 0.0,
        "source_season_max_abs_error": 0.0,
        "source_residual_max_abs_error": 0.0,
        "additive_reconstruction_max_abs_error": 4.440892098500626e-16,
        "phase_average_trace_max_abs_error": 0.0
      },
      "source_files": [
        "src/detime/methods/std.py",
        "native/src/std.cpp"
      ],
      "frames": 32,
      "duration_ms": 12050,
      "poster_frame": 15,
      "width": 1280,
      "height": 820,
      "artifacts": {
        "gif": {
          "file": "stdr.gif",
          "bytes": 590036,
          "sha256": "7e4fc040e546acf0c56a10d193de27d60f51cb298d201e03c7d07c79bcbdfc59"
        },
        "poster": {
          "file": "stdr.png",
          "bytes": 104021,
          "sha256": "9b00955566a630496fcf5bd390d754b1fb0e44ac15285ac877b33e40c0487772"
        },
        "data": {
          "file": "stdr.npz",
          "bytes": 8984,
          "sha256": "5dfb855c020a2714f5b8c341cd49b83827cd53faf581ea00cf9aed51f45db2c6"
        }
      },
      "source_arrays": {
        "t": [
          139
        ],
        "observed": [
          139
        ],
        "block_means": [
          6
        ],
        "block_dispersion": [
          6
        ],
        "normalized_shapes_zero_padded": [
          6,
          24
        ],
        "phase_available_mask": [
          6,
          24
        ],
        "running_phase_counts": [
          6,
          24
        ],
        "running_average_shapes": [
          6,
          24
        ],
        "sample_dispersion": [
          139
        ],
        "returned_seasonal_shape": [
          139
        ],
        "trend": [
          139
        ],
        "season": [
          139
        ],
        "residual": [
          139
        ]
      },
      "render_provenance": {
        "python_version": "3.12.14",
        "dependencies": {
          "numpy": "2.3.5",
          "scipy": "1.17.0",
          "statsmodels": "0.15.0",
          "matplotlib": "3.10.8",
          "Pillow": "12.3.0",
          "PyWavelets": "1.10.0",
          "EMD-signal": "1.10.0",
          "vmdpy": "0.2",
          "PySDKit": "0.5.0"
        },
        "source_hashes": {
          "native/src/std.cpp": "5d5fddc1b7267985d73336386b9a34834b688eab60266430669b4a049c59ad4c",
          "scripts/generate_method_animations.py": "f62989af55a7e48495c24afcfee31751d3785e5f78bb4b900bef23a429deaa84",
          "scripts/method_animations/classical.py": "8a8a9ef82936f0aa5b1c5775c6c0158c3b48d3bc7dca1de691b83d95e5c23ba3",
          "scripts/method_animations/common.py": "73ad7e8b4e5b67f87d13e59adab2c93e983fe1aaf06ee627d22cb7c7e696016a",
          "src/detime/backends.py": "7432dcf59e382580dfb32f1f57e61ff71a30567c049b35243e24e3644523eda6",
          "src/detime/core.py": "d95b348cd8b16b56d18840965579c947a11628d969dd6c32c4af7723f5a027f4",
          "src/detime/methods/std.py": "7d72be4a4bff8c15f3723eaf1198d55b6863c517caa592690a5858f3e30f3578",
          "src/detime/registry.py": "e934ffca17880cefe5add728aa497e63ea811d7ae43abec1ea498de718094066"
        }
      }
    },
    {
      "method": "STL",
      "slug": "stl",
      "title": "Smooth seasonal phases and trend",
      "summary": "STL alternates local seasonal and trend smoothing while retaining a residual component.",
      "steps": [
        {
          "title": "Form seasonal-phase subseries",
          "text": "After removing the current trend, collect values at the same phase in successive cycles. STL smooths along each of these subseries, allowing the seasonal pattern to vary through the record."
        },
        {
          "title": "Use local polynomial smoothing",
          "text": "The illustrative panel computes a tricube-weighted local linear fit for one phase. Full STL also extends boundaries, applies low-pass filtering, and combines the smoothed subseries; the illustration is not a replacement implementation of those internals."
        },
        {
          "title": "Alternate seasonal and trend",
          "text": "The seasonal estimate is subtracted to form a deseasonalized series, which is smoothed for trend. The numerical checkpoints come from exact statsmodels fits with one through five inner iterations and no outer robustness loop."
        },
        {
          "title": "Form the additive result",
          "text": "The final five-iteration checkpoint matches the configured DeTime STL wrapper. Residual is the input minus the returned trend and seasonal component. Reconstruction consistency does not validate a unique physical interpretation."
        }
      ],
      "parameters": [
        {
          "name": "period",
          "effect": "Specified number of samples in a seasonal cycle; this example uses 12."
        },
        {
          "name": "seasonal",
          "effect": "Odd LOESS span across cycles for the seasonal subseries; smaller spans allow faster seasonal change."
        },
        {
          "name": "trend / low_pass",
          "effect": "Odd smoothing spans controlling trend and low-pass behavior; this example uses 23 and 13."
        },
        {
          "name": "robust",
          "effect": "Controls the outer reweighting loop. ROBUST_STL defaults to True; setting it False disables robustness."
        }
      ],
      "cautions": [
        "ROBUST_STL is the registry name for statsmodels STL with its robust option. This name does not establish implementation of other published algorithms also called RobustSTL.",
        "Smoothing spans, seasonal period, endpoint handling, and outliers influence the estimated components.",
        "The animation uses statsmodels' actual checkpoints. Internal fits are restarted for each budget; frame count is not an execution-time measure.",
        "STL is an offline smoother. Use only available history when constructing forecasting features."
      ],
      "references": [
        {
          "title": "Cleveland et al. (1990), STL: A Seasonal-Trend Decomposition Procedure Based on Loess",
          "url": "https://www.scb.se/contentassets/ca21efb41fee47d293bbee5bf7be7fb3/stl-a-seasonal-trend-decomposition-procedure-based-on-loess.pdf"
        },
        {
          "title": "statsmodels STL: parameters and implementation contract",
          "url": "https://www.statsmodels.org/stable/generated/statsmodels.tsa.seasonal.STL.html"
        }
      ],
      "trace_kind": "illustrative internals + actual output",
      "trace_note": "The local weighted regression illustrates LOESS numerically and omits STL's full low-pass and boundary machinery. Exact statsmodels inner-iteration checkpoints and final DeTime output are shown separately and compared.",
      "input_note": "Deterministic synthetic teaching signal; not a benchmark.",
      "example_config": {
        "method": "STL",
        "backend": "python",
        "params": {
          "period": 12,
          "seasonal": 7,
          "trend": 23,
          "low_pass": 13,
          "robust": false
        }
      },
      "checks": {
        "checkpoint_trend_max_abs_error": 0.0,
        "checkpoint_season_max_abs_error": 0.0,
        "checkpoint_residual_max_abs_error": 0.0,
        "additive_reconstruction_max_abs_error": 4.440892098500626e-16
      },
      "source_files": [
        "src/detime/methods/stl.py"
      ],
      "frames": 32,
      "duration_ms": 12050,
      "poster_frame": 15,
      "width": 1280,
      "height": 820,
      "artifacts": {
        "gif": {
          "file": "stl.gif",
          "bytes": 501932,
          "sha256": "01ebe001f4b1e58a3fe363f78d6d8ea611509c48eb50ec74f88fe55a8dc2f3dd"
        },
        "poster": {
          "file": "stl.png",
          "bytes": 138917,
          "sha256": "646b3d042fe4f3425ed74fcaa0af532b8dfbd087416a8c2e716c6610ceeac01e"
        },
        "data": {
          "file": "stl.npz",
          "bytes": 27845,
          "sha256": "31c41d0378263d81d2b3847bcaa0c732c6aaaf1a10a5d3144cfbbb14de42b797"
        }
      },
      "source_arrays": {
        "t": [
          144
        ],
        "observed": [
          144
        ],
        "iteration_budgets": [
          5
        ],
        "checkpoint_trend": [
          5,
          144
        ],
        "checkpoint_season": [
          5,
          144
        ],
        "checkpoint_residual": [
          5,
          144
        ],
        "checkpoint_weights": [
          5,
          144
        ],
        "first_bisquare_weights": [
          144
        ],
        "bisquare_curve_residuals": [
          100
        ],
        "bisquare_curve_weights": [
          100
        ],
        "loess_phase_values": [
          12
        ],
        "loess_local_weights": [
          12,
          12
        ],
        "loess_local_fits": [
          12,
          12
        ],
        "trend": [
          144
        ],
        "season": [
          144
        ],
        "residual": [
          144
        ]
      },
      "render_provenance": {
        "python_version": "3.12.14",
        "dependencies": {
          "numpy": "2.3.5",
          "scipy": "1.17.0",
          "statsmodels": "0.15.0",
          "matplotlib": "3.10.8",
          "Pillow": "12.3.0",
          "PyWavelets": "1.10.0",
          "EMD-signal": "1.10.0",
          "vmdpy": "0.2",
          "PySDKit": "0.5.0"
        },
        "source_hashes": {
          "scripts/generate_method_animations.py": "f62989af55a7e48495c24afcfee31751d3785e5f78bb4b900bef23a429deaa84",
          "scripts/method_animations/classical.py": "8a8a9ef82936f0aa5b1c5775c6c0158c3b48d3bc7dca1de691b83d95e5c23ba3",
          "scripts/method_animations/common.py": "73ad7e8b4e5b67f87d13e59adab2c93e983fe1aaf06ee627d22cb7c7e696016a",
          "src/detime/backends.py": "7432dcf59e382580dfb32f1f57e61ff71a30567c049b35243e24e3644523eda6",
          "src/detime/core.py": "d95b348cd8b16b56d18840965579c947a11628d969dd6c32c4af7723f5a027f4",
          "src/detime/methods/stl.py": "bb9db3808691490849d06b6eff3f1d6083b6d79fa4d0ea526201e6cec11bdd4d",
          "src/detime/registry.py": "e934ffca17880cefe5add728aa497e63ea811d7ae43abec1ea498de718094066"
        }
      }
    },
    {
      "method": "ST_MTM_BLOCK",
      "slug": "st-mtm-block",
      "title": "ST-MTM block: smooth a phase template",
      "summary": "A centered moving average estimates the prefix trend and the final trend level is held constant afterward. The next step uses phase-wise means of the detrended prefix. The frames expose those buckets, their cumulative averages and the repeated seasonal output. The computation shown has a smoothed template. It does not perform masked-time-series pretraining.",
      "steps": [
        {
          "title": "Smooth the prefix",
          "text": "A centered moving average estimates the prefix trend and the final trend level is held constant afterward."
        },
        {
          "title": "Average equal seasonal phases",
          "text": "Subtract the trend on the fitting prefix. Group samples by index modulo the specified period and average each phase bucket."
        },
        {
          "title": "Smooth the repeated template",
          "text": "Tile the fitted phase means over the record. The ST-MTM variant additionally smooths that repeated curve with a centered mean."
        },
        {
          "title": "Inspect the derived residual",
          "text": "Compute input minus the implemented trend and seasonal estimate. This residual is part of a retrospective decomposition, not a forecast score."
        }
      ],
      "parameters": [
        {
          "name": "trend_window",
          "effect": "Sets the centered moving-average support on the prefix; its endpoint is extended as a constant."
        },
        {
          "name": "primary_period",
          "effect": "Defines phase buckets in samples; the fitting prefix must contain enough cycles for an interpretable average."
        },
        {
          "name": "fit_scope / train_fraction",
          "effect": "Explicitly selects a two-thirds prefix in this example; it does not create a rolling forecasting evaluation."
        },
        {
          "name": "season_smooth_window",
          "effect": "Smooths the tiled phase estimate. It changes amplitudes and edge values after bucket averaging."
        }
      ],
      "cautions": [
        "The computation shown has a smoothed template. It does not perform masked-time-series pretraining.",
        "Prefix fitting is a fixed fitting convention. It does not certify rolling causality or an out-of-sample prediction experiment.",
        "A repeated phase template assumes that the fitted seasonal shape remains useful over the displayed suffix.",
        "The residual is derived by subtraction; exact reconstruction does not validate the scientific interpretation of either component."
      ],
      "references": [
        {
          "title": "Implemented DeTime operator",
          "url": "https://github.com/systems-mechanobiology/DeTime/blob/main/src/detime/methods/neural_blocks/neural_block_portfolio.py"
        },
        {
          "title": "Seo and Lim (2025), ST-MTM: Masked Time Series Modeling with Seasonal-Trend Decomposition for Time Series Forecasting",
          "url": "https://arxiv.org/abs/2507.00013"
        }
      ],
      "trace_kind": "computed_operator_trace",
      "trace_note": "Intermediate arrays are computed with the implemented operator helpers. The final trend, season and residual are checked against public decompose(). The animation explains this standalone experimental block; its source architecture is cited for provenance.",
      "input_note": "Deterministic synthetic teaching signal; not a benchmark.",
      "example_config": {
        "method": "ST_MTM_BLOCK",
        "params": {
          "primary_period": 24,
          "fit_scope": "prefix",
          "train_fraction": 0.6666666666666666,
          "trend_window": 49,
          "season_smooth_window": 13
        },
        "backend": "python"
      },
      "checks": {
        "public_method_executed": true,
        "method_output_max_abs_errors": {
          "trend": 0.0,
          "season": 0.0,
          "residual": 0.0
        },
        "reconstruction_max_abs_error": 2.220446049250313e-16,
        "validation_scope": "One deterministic teaching input; no benchmark claim.",
        "fit_end": 96
      },
      "source_files": [
        "src/detime/methods/neural_blocks/neural_block_portfolio.py"
      ],
      "frames": 32,
      "duration_ms": 12050,
      "poster_frame": 15,
      "width": 1280,
      "height": 820,
      "artifacts": {
        "gif": {
          "file": "st-mtm-block.gif",
          "bytes": 341219,
          "sha256": "c89124fc52ef1eaf7ce3e2aba90e7b83a6c5a146ebdf8f4d9dc96fb71af2d250"
        },
        "poster": {
          "file": "st-mtm-block.png",
          "bytes": 125264,
          "sha256": "14e99c4f77a3bbd497111450c96fa8bc24ac536d419465d69e2e33189857a532"
        },
        "data": {
          "file": "st-mtm-block.npz",
          "bytes": 8163,
          "sha256": "dd91a213722f6640412e0ee7a380e613e67bdd2ed57446f97337d0da96363e4a"
        }
      },
      "source_arrays": {
        "observed": [
          144
        ],
        "trend_candidates": [
          1,
          144
        ],
        "trend": [
          144
        ],
        "detrended": [
          144
        ],
        "prefix_phase_matrix": [
          4,
          24
        ],
        "raw_template": [
          144
        ],
        "season": [
          144
        ],
        "residual": [
          144
        ],
        "fit_end": []
      },
      "render_provenance": {
        "python_version": "3.12.14",
        "dependencies": {
          "numpy": "2.3.5",
          "scipy": "1.17.0",
          "statsmodels": "0.15.0",
          "matplotlib": "3.10.8",
          "Pillow": "12.3.0",
          "PyWavelets": "1.10.0",
          "EMD-signal": "1.10.0",
          "vmdpy": "0.2",
          "PySDKit": "0.5.0"
        },
        "source_hashes": {
          "scripts/generate_method_animations.py": "f62989af55a7e48495c24afcfee31751d3785e5f78bb4b900bef23a429deaa84",
          "scripts/method_animations/common.py": "73ad7e8b4e5b67f87d13e59adab2c93e983fe1aaf06ee627d22cb7c7e696016a",
          "scripts/method_animations/neural.py": "fc1c2a73490391f0f863ede52e38f12924cc1fec572b7188356a2308216716e6",
          "src/detime/backends.py": "7432dcf59e382580dfb32f1f57e61ff71a30567c049b35243e24e3644523eda6",
          "src/detime/core.py": "d95b348cd8b16b56d18840965579c947a11628d969dd6c32c4af7723f5a027f4",
          "src/detime/methods/neural_blocks/neural_block_portfolio.py": "2aab635b9927d1d42bbcd8e0b4f37cb9fcdcf85cbd0331b5011621b495c4acfa",
          "src/detime/registry.py": "e934ffca17880cefe5add728aa497e63ea811d7ae43abec1ea498de718094066"
        }
      }
    },
    {
      "method": "TIMEKAN_BLOCK",
      "slug": "timekan-block",
      "title": "TimeKAN block: template–harmonic blending",
      "summary": "The current standalone TimeKAN-inspired operator combines familiar numerical estimates. It smooths a trend, selects periods from a prefix FFT, averages phase templates, and fits a harmonic projection at the supplied primary period. A fixed rule blends the two seasonal estimates. The animation shows that rule directly; it does not portray the complete frequency-decomposition KAN architecture from the cited paper.",
      "steps": [
        {
          "title": "Smooth and inspect prefix frequencies",
          "text": "Estimate the trend from the selected prefix and use the detrended prefix FFT to obtain candidate periods."
        },
        {
          "title": "Fit two kinds of seasonal estimate",
          "text": "Average phase templates at selected periods and separately fit a harmonic projection at primary_period."
        },
        {
          "title": "Apply the implemented fixed blend",
          "text": "Combine the template average and harmonic projection using a weight determined by num_bands. No KAN is optimized in this operator."
        },
        {
          "title": "Inspect the checked output",
          "text": "Return the smoothed trend, blended seasonal estimate and input-minus-components residual."
        }
      ],
      "parameters": [
        {
          "name": "num_bands",
          "effect": "Controls the selected template periods and the fixed blend weight 0.35 + 0.1 × min(num_bands, 4), clipped by the implementation."
        },
        {
          "name": "kan_width",
          "effect": "Maps to max(1, kan_width // 32) harmonics in this operator."
        },
        {
          "name": "primary_period",
          "effect": "Sets the harmonic projection's period; FFT-selected periods define the separate templates."
        },
        {
          "name": "fit_scope / train_fraction",
          "effect": "The animation explicitly fits on the first two thirds of the record."
        }
      ],
      "cautions": [
        "No KAN coefficients or neural network are fitted by this standalone implementation.",
        "Template and harmonic components can overlap spectrally; the displayed blend is an explicit heuristic.",
        "Prefix fitting and suffix extension do not establish forecast accuracy or causal identification.",
        "The residual is defined from the observed series after forming both named components."
      ],
      "references": [
        {
          "title": "Implemented DeTime operator",
          "url": "https://github.com/systems-mechanobiology/DeTime/blob/main/src/detime/methods/neural_blocks/neural_block_portfolio.py"
        },
        {
          "title": "Huang et al. (2025), TimeKAN: KAN-based Frequency Decomposition Learning Architecture for Long-term Time Series Forecasting",
          "url": "https://arxiv.org/abs/2502.06910"
        }
      ],
      "trace_kind": "computed_operator_trace",
      "trace_note": "Intermediate arrays are computed with the implemented operator helpers. The final trend, season and residual are checked against public decompose(). The animation explains this standalone experimental block; its source architecture is cited for provenance.",
      "input_note": "Deterministic synthetic teaching signal; not a benchmark.",
      "example_config": {
        "method": "TIMEKAN_BLOCK",
        "params": {
          "primary_period": 24,
          "trend_window": 25,
          "num_bands": 2,
          "kan_width": 64,
          "fit_scope": "prefix",
          "train_fraction": 0.6666666666666666
        },
        "backend": "python"
      },
      "checks": {
        "public_method_executed": true,
        "method_output_max_abs_errors": {
          "trend": 0.0,
          "season": 0.0,
          "residual": 0.0
        },
        "reconstruction_max_abs_error": 2.220446049250313e-16,
        "validation_scope": "One deterministic teaching input; no benchmark claim.",
        "selected_periods": [
          24,
          12
        ],
        "template_blend_weight": 0.55
      },
      "source_files": [
        "src/detime/methods/neural_blocks/neural_block_portfolio.py"
      ],
      "frames": 32,
      "duration_ms": 12050,
      "poster_frame": 15,
      "width": 1280,
      "height": 820,
      "artifacts": {
        "gif": {
          "file": "timekan-block.gif",
          "bytes": 257497,
          "sha256": "01cfe15be7bbe059b4fbf5810756f0410d540652e772bfbf47d910d348a85960"
        },
        "poster": {
          "file": "timekan-block.png",
          "bytes": 171621,
          "sha256": "2e0a856c6e19a1b9b1299870c6ab804933b47feee7729690db707d93173c588b"
        },
        "data": {
          "file": "timekan-block.npz",
          "bytes": 7762,
          "sha256": "df3ef98ddd8e49cb6164cd0682f8bbef61269ffb06b2ac5a525023190138f29f"
        }
      },
      "source_arrays": {
        "observed": [
          144
        ],
        "trend": [
          144
        ],
        "detrended": [
          144
        ],
        "templates": [
          2,
          144
        ],
        "selected_periods": [
          2
        ],
        "template_mean": [
          144
        ],
        "harmonic_fit": [
          144
        ],
        "blend_weights": [
          2
        ],
        "season": [
          144
        ],
        "residual": [
          144
        ]
      },
      "render_provenance": {
        "python_version": "3.12.14",
        "dependencies": {
          "numpy": "2.3.5",
          "scipy": "1.17.0",
          "statsmodels": "0.15.0",
          "matplotlib": "3.10.8",
          "Pillow": "12.3.0",
          "PyWavelets": "1.10.0",
          "EMD-signal": "1.10.0",
          "vmdpy": "0.2",
          "PySDKit": "0.5.0"
        },
        "source_hashes": {
          "scripts/generate_method_animations.py": "f62989af55a7e48495c24afcfee31751d3785e5f78bb4b900bef23a429deaa84",
          "scripts/method_animations/common.py": "73ad7e8b4e5b67f87d13e59adab2c93e983fe1aaf06ee627d22cb7c7e696016a",
          "scripts/method_animations/neural.py": "fc1c2a73490391f0f863ede52e38f12924cc1fec572b7188356a2308216716e6",
          "src/detime/backends.py": "7432dcf59e382580dfb32f1f57e61ff71a30567c049b35243e24e3644523eda6",
          "src/detime/core.py": "d95b348cd8b16b56d18840965579c947a11628d969dd6c32c4af7723f5a027f4",
          "src/detime/methods/neural_blocks/neural_block_portfolio.py": "2aab635b9927d1d42bbcd8e0b4f37cb9fcdcf85cbd0331b5011621b495c4acfa",
          "src/detime/registry.py": "e934ffca17880cefe5add728aa497e63ea811d7ae43abec1ea498de718094066"
        }
      }
    },
    {
      "method": "TIMES2D_BLOCK",
      "slug": "times2d-block",
      "title": "Times2D block: selected-period projections",
      "summary": "This standalone operator obtains candidate periods from an FFT magnitude ranking and fits a separate harmonic projection for each one. The selected seasonal estimate is their equal-weight average. The frames expose the selection signal, rounded periods, candidate curves and averaging operation. The operator uses rounded FFT periods and harmonic projections. It does not implement a two-dimensional derivative-mapping forecasting backbone.",
      "steps": [
        {
          "title": "Separate trend and selection input",
          "text": "Compute the moving-average trend. FreqMoE selects frequencies from the detrended signal; Times2D selects them from the original signal after mean removal."
        },
        {
          "title": "Select discrete spectral peaks",
          "text": "Rank FFT magnitudes, convert bin positions into rounded integer periods, and retain distinct periods as implemented."
        },
        {
          "title": "Fit and average candidate seasons",
          "text": "Fit a harmonic projection of the detrended signal for each selected period, then take the arithmetic mean of these projections."
        },
        {
          "title": "Inspect actual output streams",
          "text": "The final trend, averaged projection and derived residual are checked against the public registered operator."
        }
      ],
      "parameters": [
        {
          "name": "trend_window",
          "effect": "Sets the centered moving-average trend."
        },
        {
          "name": "top_k_periods",
          "effect": "Controls how many distinct rounded FFT periods are retained."
        },
        {
          "name": "num_harmonics",
          "effect": "Sets the number of cosine/sine pairs in each candidate projection."
        },
        {
          "name": "fit_scope",
          "effect": "Explicitly full in this animation; prefix settings restrict the fitting interval."
        }
      ],
      "cautions": [
        "The operator uses rounded FFT periods and harmonic projections. It does not implement a two-dimensional derivative-mapping forecasting backbone.",
        "A large FFT bin need not correspond to a stable physical oscillation. Trends, finite windows and rounding affect the selected periods.",
        "The independent candidate projections are averaged, rather than jointly fitted as one combined design.",
        "All coefficients use the selected fitting interval; no held-out forecast accuracy is shown."
      ],
      "references": [
        {
          "title": "Implemented DeTime operator",
          "url": "https://github.com/systems-mechanobiology/DeTime/blob/main/src/detime/methods/neural_blocks/neural_block_portfolio.py"
        },
        {
          "title": "Nematirad, Pahwa, and Natarajan (2025), Times2D: Multi-Period Decomposition and Derivative Mapping for General Time Series Forecasting",
          "url": "https://arxiv.org/abs/2504.00118"
        }
      ],
      "trace_kind": "computed_operator_trace",
      "trace_note": "Intermediate arrays are computed with the implemented operator helpers. The final trend, season and residual are checked against public decompose(). The animation explains this standalone experimental block; its source architecture is cited for provenance.",
      "input_note": "Deterministic synthetic teaching signal; not a benchmark.",
      "example_config": {
        "method": "TIMES2D_BLOCK",
        "params": {
          "primary_period": 24,
          "trend_window": 49,
          "fit_scope": "full",
          "top_k_periods": 2,
          "num_harmonics": 1
        },
        "backend": "python"
      },
      "checks": {
        "public_method_executed": true,
        "method_output_max_abs_errors": {
          "trend": 0.0,
          "season": 0.0,
          "residual": 0.0
        },
        "reconstruction_max_abs_error": 2.220446049250313e-16,
        "validation_scope": "One deterministic teaching input; no benchmark claim.",
        "selected_periods": [
          24,
          144
        ]
      },
      "source_files": [
        "src/detime/methods/neural_blocks/neural_block_portfolio.py"
      ],
      "frames": 32,
      "duration_ms": 12050,
      "poster_frame": 15,
      "width": 1280,
      "height": 820,
      "artifacts": {
        "gif": {
          "file": "times2d-block.gif",
          "bytes": 279388,
          "sha256": "9d7b4fc77b31e37e181ac9991123178b15040039ccbe80bccc4cc8ae78b90403"
        },
        "poster": {
          "file": "times2d-block.png",
          "bytes": 116023,
          "sha256": "bcaefc457289056cc78fe83ed40f61f51786e2500361af56dea5fbc827077812"
        },
        "data": {
          "file": "times2d-block.npz",
          "bytes": 11014,
          "sha256": "e79710bccc89e33a310467a0519a265e1d65dd8abdbb83f70bc6e20a3f2083d9"
        }
      },
      "source_arrays": {
        "observed": [
          144
        ],
        "trend": [
          144
        ],
        "detrended": [
          144
        ],
        "selection_input": [
          144
        ],
        "spectrum": [
          73
        ],
        "fft_frequencies": [
          73
        ],
        "selected_periods": [
          2
        ],
        "candidate_seasons": [
          2,
          144
        ],
        "season": [
          144
        ],
        "residual": [
          144
        ]
      },
      "render_provenance": {
        "python_version": "3.12.14",
        "dependencies": {
          "numpy": "2.3.5",
          "scipy": "1.17.0",
          "statsmodels": "0.15.0",
          "matplotlib": "3.10.8",
          "Pillow": "12.3.0",
          "PyWavelets": "1.10.0",
          "EMD-signal": "1.10.0",
          "vmdpy": "0.2",
          "PySDKit": "0.5.0"
        },
        "source_hashes": {
          "scripts/generate_method_animations.py": "f62989af55a7e48495c24afcfee31751d3785e5f78bb4b900bef23a429deaa84",
          "scripts/method_animations/common.py": "73ad7e8b4e5b67f87d13e59adab2c93e983fe1aaf06ee627d22cb7c7e696016a",
          "scripts/method_animations/neural.py": "fc1c2a73490391f0f863ede52e38f12924cc1fec572b7188356a2308216716e6",
          "src/detime/backends.py": "7432dcf59e382580dfb32f1f57e61ff71a30567c049b35243e24e3644523eda6",
          "src/detime/core.py": "d95b348cd8b16b56d18840965579c947a11628d969dd6c32c4af7723f5a027f4",
          "src/detime/methods/neural_blocks/neural_block_portfolio.py": "2aab635b9927d1d42bbcd8e0b4f37cb9fcdcf85cbd0331b5011621b495c4acfa",
          "src/detime/registry.py": "e934ffca17880cefe5add728aa497e63ea811d7ae43abec1ea498de718094066"
        }
      }
    },
    {
      "method": "VMD",
      "slug": "vmd",
      "title": "VMD: update narrow-band modes and their center frequencies",
      "summary": "VMD alternates between frequency-domain mode updates and spectral-energy centers. DeTime's grouping into trend and season is a separate step after this optimization.",
      "steps": [
        {
          "title": "Prepare the spectrum",
          "text": "Mirror the signal, compute its FFT, and retain the positive-frequency representation."
        },
        {
          "title": "Update a mode",
          "text": "Fit the remaining spectrum with a bandwidth penalty around the current center frequency."
        },
        {
          "title": "Update its center",
          "text": "Use the mode's positive-frequency energy to update its center, then repeat across modes."
        },
        {
          "title": "Reconstruct and group",
          "text": "Complete the conjugate spectrum, invert the FFT, crop the mirrored margins, and group modes."
        }
      ],
      "parameters": [
        {
          "name": "K",
          "effect": "Number of modes; the demonstration uses 3."
        },
        {
          "name": "alpha",
          "effect": "Penalizes spectral spread around each center; the demonstration uses 1500."
        },
        {
          "name": "tau",
          "effect": "Dual-update step; zero permits noise slack and does not enforce an exact sum of modes."
        },
        {
          "name": "init / tol",
          "effect": "Initialization and convergence tolerance affect the computed solution."
        }
      ],
      "cautions": [
        "The animation captures the optional vmdpy path; the native path has its own implementation and iteration control.",
        "Center frequencies shown here are raw solver frequencies in cycles/sample, not DeTime's converted metadata field.",
        "VMD modes need a grouping rule before being named trend or season; frequency ordering is not a physical-source guarantee."
      ],
      "references": [
        {
          "title": "Original VMD paper",
          "url": "https://doi.org/10.1109/TSP.2013.2288675"
        },
        {
          "title": "vmdpy reference implementation",
          "url": "https://github.com/vrcarva/vmdpy"
        },
        {
          "title": "Maintained sktime continuation",
          "url": "https://www.sktime.net/docs/api-reference/sktimetransformationsvmdvmdtransformer/"
        }
      ],
      "trace_kind": "upstream execution trace",
      "trace_note": "Captured vmdpy 0.2 loop arrays without changing solver updates; intermediate time-domain modes use its conjugate-completion and mirror-cropping convention.",
      "input_note": "Deterministic synthetic teaching signal; not a benchmark.",
      "example_config": {
        "method": "VMD",
        "params": {
          "K": 3,
          "alpha": 1500.0,
          "tau": 0.0,
          "init": 1,
          "tol": 1e-07,
          "primary_period": 24
        },
        "backend": "python"
      },
      "checks": {
        "recorded_final_iterate": 24,
        "trace_matches_upstream_modes": 0.0,
        "mode_sum_rmse": 0.05055252233370291
      },
      "source_files": [
        "src/detime/methods/vmd.py",
        "native/src/vmd.cpp"
      ],
      "frames": 32,
      "duration_ms": 12050,
      "poster_frame": 15,
      "width": 1280,
      "height": 820,
      "artifacts": {
        "gif": {
          "file": "vmd.gif",
          "bytes": 399253,
          "sha256": "847bfe96e5ebeb3695fe6d45a3af338f02b549724f28ab777f291b43346fc8cb"
        },
        "poster": {
          "file": "vmd.png",
          "bytes": 179243,
          "sha256": "1d69db3c4af2c1486d1a940875ab9b45b1636250df729557cfc10bb80f6c9237"
        },
        "data": {
          "file": "vmd.npz",
          "bytes": 117559,
          "sha256": "915fb7429247169e4055010b741c8ff459bc31b1388010075d8430ed0a899d0e"
        }
      },
      "source_arrays": {
        "time": [
          192
        ],
        "input": [
          192
        ],
        "mirrored_input": [
          384
        ],
        "frequency_grid": [
          384
        ],
        "iteration_ids": [
          8
        ],
        "mode_spectra": [
          8,
          384,
          3
        ],
        "center_frequency_trace": [
          25,
          3
        ],
        "mode_trace": [
          8,
          3,
          192
        ],
        "returned_modes": [
          3,
          192
        ]
      },
      "render_provenance": {
        "python_version": "3.11.3",
        "dependencies": {
          "numpy": "2.4.6",
          "scipy": "1.17.1",
          "statsmodels": "0.15.0",
          "matplotlib": "3.11.2",
          "Pillow": "13.0.0",
          "PyWavelets": "1.9.0",
          "EMD-signal": "1.10.0",
          "vmdpy": "0.2",
          "PySDKit": "0.5.0"
        },
        "source_hashes": {
          "native/src/vmd.cpp": "27b730744b4c17b2b0cfa4d2c4c0d29798d335294a71fb6a7a3e077e3012041b",
          "scripts/generate_method_animations.py": "f62989af55a7e48495c24afcfee31751d3785e5f78bb4b900bef23a429deaa84",
          "scripts/method_animations/adaptive.py": "7d728d88b4ba1a8dd82890c7a6b017d542728b50dc477c281e9bbfcbae164a1d",
          "scripts/method_animations/common.py": "73ad7e8b4e5b67f87d13e59adab2c93e983fe1aaf06ee627d22cb7c7e696016a",
          "src/detime/backends.py": "7432dcf59e382580dfb32f1f57e61ff71a30567c049b35243e24e3644523eda6",
          "src/detime/core.py": "d95b348cd8b16b56d18840965579c947a11628d969dd6c32c4af7723f5a027f4",
          "src/detime/methods/vmd.py": "249bdc7e67595c7f556d32dd70c64e6f8ee7bd7a0e6c3b0277a8010fc1f0cf67",
          "src/detime/registry.py": "e934ffca17880cefe5add728aa497e63ea811d7ae43abec1ea498de718094066"
        }
      }
    },
    {
      "method": "WAVEFORM_BLOCK",
      "slug": "waveform-block",
      "title": "WaveForM block: reconstruct wavelet bands",
      "summary": "The implemented operator delegates the transform to PyWavelets. It reconstructs the coarsest approximation as trend and selected detail arrays as season, then derives the residual by subtraction. The animation exposes the analysis filter taps, coefficient arrays and inverse reconstructions. The WaveForM and WaveletMixer identifiers have different default wavelets and selected bands; neither operator runs the cited complete forecasting backbone.",
      "steps": [
        {
          "title": "Analyze with fixed wavelet filters",
          "text": "PyWavelets applies the selected analysis filters to produce approximation and detail coefficients at several resolutions."
        },
        {
          "title": "Reconstruct the approximation",
          "text": "Keep only the coarsest approximation coefficients, zero the other coefficient arrays and apply inverse reconstruction to obtain the trend."
        },
        {
          "title": "Reconstruct selected detail bands",
          "text": "Keep the explicitly selected coefficient-list positions and reconstruct their combined sample-aligned contribution as season."
        },
        {
          "title": "Inspect the remaining detail",
          "text": "The residual is the observed input minus the approximation and selected details. All displayed components match the public operator."
        }
      ],
      "parameters": [
        {
          "name": "wavelet",
          "effect": "Selects the fixed analysis/synthesis wavelet family; db4 and sym4 are used by these two examples."
        },
        {
          "name": "level",
          "effect": "Requests decomposition depth, limited by the implementation using the input length and filter length."
        },
        {
          "name": "season_levels",
          "effect": "Contains coefficient-list positions: 1 denotes cD_L, 2 denotes cD_(L-1), and so on; position 0 is the trend approximation."
        }
      ],
      "cautions": [
        "WaveForM's graph enhancement and WaveletMixer's trained mixing layers are outside these standalone operators.",
        "The source uses PyWavelets' default symmetric boundary extension; boundary values depend on that convention.",
        "A selected frequency-scale band is called season by the common result contract; periodic interpretation requires separate evidence.",
        "The coefficient heatmap pads unequal-length arrays with zeros for display only. Computation uses their original lengths."
      ],
      "references": [
        {
          "title": "Implemented DeTime operator",
          "url": "https://github.com/systems-mechanobiology/DeTime/blob/main/src/detime/methods/neural_blocks/neural_block_portfolio.py"
        },
        {
          "title": "Yang et al. (2023), WaveForM: Graph Enhanced Wavelet Learning for Long Sequence Forecasting of Multivariate Time Series",
          "url": "https://ojs.aaai.org/index.php/AAAI/article/view/26276"
        }
      ],
      "trace_kind": "computed_operator_trace",
      "trace_note": "Intermediate arrays are computed with the implemented operator helpers. The final trend, season and residual are checked against public decompose(). The animation explains this standalone experimental block; its source architecture is cited for provenance.",
      "input_note": "Deterministic synthetic teaching signal; not a benchmark.",
      "example_config": {
        "method": "WAVEFORM_BLOCK",
        "params": {
          "wavelet": "db4",
          "level": 3,
          "season_levels": [
            1,
            2
          ]
        },
        "backend": "python"
      },
      "checks": {
        "public_method_executed": true,
        "method_output_max_abs_errors": {
          "trend": 0.0,
          "season": 0.0,
          "residual": 0.0
        },
        "reconstruction_max_abs_error": 2.220446049250313e-16,
        "validation_scope": "One deterministic teaching input; no benchmark claim.",
        "all_bands_reconstruction_max_abs_error": 1.3322676295501878e-15,
        "effective_level": 3
      },
      "source_files": [
        "src/detime/methods/neural_blocks/neural_block_portfolio.py"
      ],
      "frames": 32,
      "duration_ms": 12050,
      "poster_frame": 15,
      "width": 1280,
      "height": 820,
      "artifacts": {
        "gif": {
          "file": "waveform-block.gif",
          "bytes": 310085,
          "sha256": "e07af7df8ab25c740fcf5738d4dfa37b18379e9fd4c29e204cc82a5e6385b6ee"
        },
        "poster": {
          "file": "waveform-block.png",
          "bytes": 149688,
          "sha256": "4abe2a46f24a648ac6521cb72009efcec9d05a81200c454c1bec36e8f62143a6"
        },
        "data": {
          "file": "waveform-block.npz",
          "bytes": 13809,
          "sha256": "9a66fe09e98ff47914dfe485408a256cdb779eaaecbf9c592df21cbcd675c292"
        }
      },
      "source_arrays": {
        "observed": [
          144
        ],
        "coefficient_display": [
          4,
          75
        ],
        "reconstructed_bands": [
          4,
          144
        ],
        "trend": [
          144
        ],
        "season": [
          144
        ],
        "residual": [
          144
        ],
        "coefficient_0": [
          24
        ],
        "coefficient_1": [
          24
        ],
        "coefficient_2": [
          41
        ],
        "coefficient_3": [
          75
        ]
      },
      "render_provenance": {
        "python_version": "3.12.14",
        "dependencies": {
          "numpy": "2.3.5",
          "scipy": "1.17.0",
          "statsmodels": "0.15.0",
          "matplotlib": "3.10.8",
          "Pillow": "12.3.0",
          "PyWavelets": "1.10.0",
          "EMD-signal": "1.10.0",
          "vmdpy": "0.2",
          "PySDKit": "0.5.0"
        },
        "source_hashes": {
          "scripts/generate_method_animations.py": "f62989af55a7e48495c24afcfee31751d3785e5f78bb4b900bef23a429deaa84",
          "scripts/method_animations/common.py": "73ad7e8b4e5b67f87d13e59adab2c93e983fe1aaf06ee627d22cb7c7e696016a",
          "scripts/method_animations/neural.py": "fc1c2a73490391f0f863ede52e38f12924cc1fec572b7188356a2308216716e6",
          "src/detime/backends.py": "7432dcf59e382580dfb32f1f57e61ff71a30567c049b35243e24e3644523eda6",
          "src/detime/core.py": "d95b348cd8b16b56d18840965579c947a11628d969dd6c32c4af7723f5a027f4",
          "src/detime/methods/neural_blocks/neural_block_portfolio.py": "2aab635b9927d1d42bbcd8e0b4f37cb9fcdcf85cbd0331b5011621b495c4acfa",
          "src/detime/registry.py": "e934ffca17880cefe5add728aa497e63ea811d7ae43abec1ea498de718094066"
        }
      }
    },
    {
      "method": "WAVELET",
      "slug": "wavelet",
      "title": "Wavelets: filter, downsample, and reconstruct selected scales",
      "summary": "A discrete wavelet transform separates scales through paired low-pass and high-pass filters. DeTime reconstructs selected coefficient blocks onto the original sample grid.",
      "steps": [
        {
          "title": "Choose the filter bank",
          "text": "The wavelet fixes the analysis and synthesis filters; this trace uses db4."
        },
        {
          "title": "Build the pyramid",
          "text": "Low-pass and high-pass filtering are followed by decimation; repeat on the approximation."
        },
        {
          "title": "Select coefficient blocks",
          "text": "Retain a block, zero the others, and apply the inverse transform to obtain a sample-aligned contribution."
        },
        {
          "title": "Assign outputs",
          "text": "This example assigns A3 to trend and D3+D2 to season; the remainder is input minus those outputs."
        }
      ],
      "parameters": [
        {
          "name": "wavelet",
          "effect": "Controls filters and their support; db4 has eight analysis taps."
        },
        {
          "name": "level",
          "effect": "Controls pyramid depth; the example uses three levels."
        },
        {
          "name": "trend_levels / season_levels",
          "effect": "Indexes the wavedec list [A3,D3,D2,D1] here, not ascending physical scales."
        },
        {
          "name": "Boundary convention",
          "effect": "The current wrapper uses PyWavelets' default symmetric mode."
        }
      ],
      "cautions": [
        "Wavelet detail coefficients are decimated and should not be mistaken for sample-aligned output curves.",
        "Assigning scales to trend or season is an application choice; the transform does not identify physical mechanisms.",
        "The animation uses a safe fixed depth; excessive levels make boundary effects dominate."
      ],
      "references": [
        {
          "title": "PyWavelets discrete transform",
          "url": "https://pywavelets.readthedocs.io/en/stable/ref/dwt-discrete-wavelet-transform.html"
        },
        {
          "title": "Inverse transform and partial reconstruction",
          "url": "https://pywavelets.readthedocs.io/en/stable/ref/idwt-inverse-discrete-wavelet-transform.html"
        },
        {
          "title": "Signal-extension modes",
          "url": "https://pywavelets.readthedocs.io/en/stable/ref/signal-extension-modes.html"
        }
      ],
      "trace_kind": "upstream numerical stages",
      "trace_note": "Computed with PyWavelets 1.10.0; inverse band reconstructions call the current DeTime helper. Moving filter support is a labeled illustration; coefficient values are actual library outputs.",
      "input_note": "Deterministic synthetic teaching signal; not a benchmark.",
      "example_config": {
        "method": "WAVELET",
        "params": {
          "wavelet": "db4",
          "level": 3,
          "trend_levels": [
            0
          ],
          "season_levels": [
            1,
            2
          ]
        }
      },
      "checks": {
        "all_band_reconstruction_max_abs_error": 1.7763568394002505e-15,
        "pyramid_matches_wavedec": 0.0
      },
      "source_files": [
        "src/detime/methods/wavelet.py"
      ],
      "frames": 32,
      "duration_ms": 12050,
      "poster_frame": 15,
      "width": 1280,
      "height": 820,
      "artifacts": {
        "gif": {
          "file": "wavelet.gif",
          "bytes": 226237,
          "sha256": "76e2029cd628c60a7542df8b9f8feb9aea7ac7292aabaa556c46cc94a63290c2"
        },
        "poster": {
          "file": "wavelet.png",
          "bytes": 194914,
          "sha256": "4ea9def42c329cabb85e3ca79d5c381510a93cd08942a19c7d8b4ca742d8597c"
        },
        "data": {
          "file": "wavelet.npz",
          "bytes": 14888,
          "sha256": "ee04357085b42f960e622d1c70bc071f1afae4e1c9884d585dc326c7fa440f82"
        }
      },
      "source_arrays": {
        "time": [
          192
        ],
        "input": [
          192
        ],
        "analysis_lowpass": [
          8
        ],
        "analysis_highpass": [
          8
        ],
        "reconstructed_bands": [
          4,
          192
        ],
        "approximation_0": [
          192
        ],
        "approximation_1": [
          99
        ],
        "approximation_2": [
          53
        ],
        "approximation_3": [
          30
        ],
        "detail_1": [
          99
        ],
        "detail_2": [
          53
        ],
        "detail_3": [
          30
        ]
      },
      "render_provenance": {
        "python_version": "3.12.14",
        "dependencies": {
          "numpy": "2.3.5",
          "scipy": "1.17.0",
          "statsmodels": "0.15.0",
          "matplotlib": "3.10.8",
          "Pillow": "12.3.0",
          "PyWavelets": "1.10.0",
          "EMD-signal": "1.10.0",
          "vmdpy": "0.2",
          "PySDKit": "0.5.0"
        },
        "source_hashes": {
          "scripts/generate_method_animations.py": "f62989af55a7e48495c24afcfee31751d3785e5f78bb4b900bef23a429deaa84",
          "scripts/method_animations/adaptive.py": "7d728d88b4ba1a8dd82890c7a6b017d542728b50dc477c281e9bbfcbae164a1d",
          "scripts/method_animations/common.py": "73ad7e8b4e5b67f87d13e59adab2c93e983fe1aaf06ee627d22cb7c7e696016a",
          "src/detime/backends.py": "7432dcf59e382580dfb32f1f57e61ff71a30567c049b35243e24e3644523eda6",
          "src/detime/core.py": "d95b348cd8b16b56d18840965579c947a11628d969dd6c32c4af7723f5a027f4",
          "src/detime/methods/wavelet.py": "a2a416a768bb7e2ac516e14b5f8a57d6641f40068890b91dc0c1a5db780779a0",
          "src/detime/registry.py": "e934ffca17880cefe5add728aa497e63ea811d7ae43abec1ea498de718094066"
        }
      }
    },
    {
      "method": "WAVELETMIXER_BLOCK",
      "slug": "waveletmixer-block",
      "title": "WaveletMixer block: combine detail bands",
      "summary": "The implemented operator delegates the transform to PyWavelets. It reconstructs the coarsest approximation as trend and selected detail arrays as season, then derives the residual by subtraction. The animation exposes the analysis filter taps, coefficient arrays and inverse reconstructions. The WaveForM and WaveletMixer identifiers have different default wavelets and selected bands; neither operator runs the cited complete forecasting backbone.",
      "steps": [
        {
          "title": "Analyze with fixed wavelet filters",
          "text": "PyWavelets applies the selected analysis filters to produce approximation and detail coefficients at several resolutions."
        },
        {
          "title": "Reconstruct the approximation",
          "text": "Keep only the coarsest approximation coefficients, zero the other coefficient arrays and apply inverse reconstruction to obtain the trend."
        },
        {
          "title": "Reconstruct selected detail bands",
          "text": "Keep the explicitly selected coefficient-list positions and reconstruct their combined sample-aligned contribution as season."
        },
        {
          "title": "Inspect the remaining detail",
          "text": "The residual is the observed input minus the approximation and selected details. All displayed components match the public operator."
        }
      ],
      "parameters": [
        {
          "name": "wavelet",
          "effect": "Selects the fixed analysis/synthesis wavelet family; db4 and sym4 are used by these two examples."
        },
        {
          "name": "level",
          "effect": "Requests decomposition depth, limited by the implementation using the input length and filter length."
        },
        {
          "name": "season_levels",
          "effect": "Contains coefficient-list positions: 1 denotes cD_L, 2 denotes cD_(L-1), and so on; position 0 is the trend approximation."
        }
      ],
      "cautions": [
        "WaveForM's graph enhancement and WaveletMixer's trained mixing layers are outside these standalone operators.",
        "The source uses PyWavelets' default symmetric boundary extension; boundary values depend on that convention.",
        "A selected frequency-scale band is called season by the common result contract; periodic interpretation requires separate evidence.",
        "The coefficient heatmap pads unequal-length arrays with zeros for display only. Computation uses their original lengths."
      ],
      "references": [
        {
          "title": "Implemented DeTime operator",
          "url": "https://github.com/systems-mechanobiology/DeTime/blob/main/src/detime/methods/neural_blocks/neural_block_portfolio.py"
        },
        {
          "title": "Zhang et al. (2025), WaveletMixer: A Multi-Resolution Wavelets Based MLP-Mixer for Multivariate Long-Term Time Series Forecasting",
          "url": "https://ojs.aaai.org/index.php/AAAI/article/view/34434"
        }
      ],
      "trace_kind": "computed_operator_trace",
      "trace_note": "Intermediate arrays are computed with the implemented operator helpers. The final trend, season and residual are checked against public decompose(). The animation explains this standalone experimental block; its source architecture is cited for provenance.",
      "input_note": "Deterministic synthetic teaching signal; not a benchmark.",
      "example_config": {
        "method": "WAVELETMIXER_BLOCK",
        "params": {
          "wavelet": "sym4",
          "level": 4,
          "season_levels": [
            1,
            2,
            3
          ]
        },
        "backend": "python"
      },
      "checks": {
        "public_method_executed": true,
        "method_output_max_abs_errors": {
          "trend": 0.0,
          "season": 0.0,
          "residual": 0.0
        },
        "reconstruction_max_abs_error": 4.440892098500626e-16,
        "validation_scope": "One deterministic teaching input; no benchmark claim.",
        "all_bands_reconstruction_max_abs_error": 2.2332691251847336e-12,
        "effective_level": 4
      },
      "source_files": [
        "src/detime/methods/neural_blocks/neural_block_portfolio.py"
      ],
      "frames": 32,
      "duration_ms": 12050,
      "poster_frame": 15,
      "width": 1280,
      "height": 820,
      "artifacts": {
        "gif": {
          "file": "waveletmixer-block.gif",
          "bytes": 286896,
          "sha256": "fdcf974583c885592f27e1888350b52ebc0424e49c82b77747a172fb241c44a4"
        },
        "poster": {
          "file": "waveletmixer-block.png",
          "bytes": 137730,
          "sha256": "160533b43ab4cd77f30578d2c6e768db59280a366d14e8ccad676ea9ced24d70"
        },
        "data": {
          "file": "waveletmixer-block.npz",
          "bytes": 15194,
          "sha256": "7fcc55d58c7f630b4d47dd9cc3a69355127b86aa3c0d3f180c944abde49faae5"
        }
      },
      "source_arrays": {
        "observed": [
          144
        ],
        "coefficient_display": [
          5,
          75
        ],
        "reconstructed_bands": [
          5,
          144
        ],
        "trend": [
          144
        ],
        "season": [
          144
        ],
        "residual": [
          144
        ],
        "coefficient_0": [
          15
        ],
        "coefficient_1": [
          15
        ],
        "coefficient_2": [
          24
        ],
        "coefficient_3": [
          41
        ],
        "coefficient_4": [
          75
        ]
      },
      "render_provenance": {
        "python_version": "3.12.14",
        "dependencies": {
          "numpy": "2.3.5",
          "scipy": "1.17.0",
          "statsmodels": "0.15.0",
          "matplotlib": "3.10.8",
          "Pillow": "12.3.0",
          "PyWavelets": "1.10.0",
          "EMD-signal": "1.10.0",
          "vmdpy": "0.2",
          "PySDKit": "0.5.0"
        },
        "source_hashes": {
          "scripts/generate_method_animations.py": "f62989af55a7e48495c24afcfee31751d3785e5f78bb4b900bef23a429deaa84",
          "scripts/method_animations/common.py": "73ad7e8b4e5b67f87d13e59adab2c93e983fe1aaf06ee627d22cb7c7e696016a",
          "scripts/method_animations/neural.py": "fc1c2a73490391f0f863ede52e38f12924cc1fec572b7188356a2308216716e6",
          "src/detime/backends.py": "7432dcf59e382580dfb32f1f57e61ff71a30567c049b35243e24e3644523eda6",
          "src/detime/core.py": "d95b348cd8b16b56d18840965579c947a11628d969dd6c32c4af7723f5a027f4",
          "src/detime/methods/neural_blocks/neural_block_portfolio.py": "2aab635b9927d1d42bbcd8e0b4f37cb9fcdcf85cbd0331b5011621b495c4acfa",
          "src/detime/registry.py": "e934ffca17880cefe5add728aa497e63ea811d7ae43abec1ea498de718094066"
        }
      }
    },
    {
      "method": "XPATCH_BLOCK",
      "slug": "xpatch-block",
      "title": "xPatch block: exponential level updates",
      "summary": "The implemented xPatch-inspired block offers EMA and a Holt-style level/slope option named dema. This animation uses EMA with alpha = 0.25, followed by the optional five-sample smoother of the nontrend stream. It shows the exact two-term update and the effect of a second alpha. The raw EMA is one-sided; the selected centered seasonal smoother changes that information boundary.",
      "steps": [
        {
          "title": "Mix observation and state",
          "text": "Initialize the level with the first sample, then update it as alpha times the observation plus one minus alpha times the previous level."
        },
        {
          "title": "Advance the recurrence",
          "text": "Continue the EMA update through the record. A second, explicitly labelled alpha illustrates a parameter change."
        },
        {
          "title": "Smooth the difference",
          "text": "This example smooths input minus trend with the requested five-sample centered mean; the remaining difference becomes residual."
        },
        {
          "title": "Inspect all three streams",
          "text": "The final display matches the public xPatch-inspired operator at the stated configuration."
        }
      ],
      "parameters": [
        {
          "name": "alpha",
          "effect": "Weights the newest observation in the EMA level update; the other weight is 1 - alpha."
        },
        {
          "name": "ma_type",
          "effect": "Selects ema or the implemented Holt-style level/slope recurrence called dema."
        },
        {
          "name": "season_smooth",
          "effect": "Optionally smooths the nontrend stream with an odd centered mean; omission leaves a zero derived residual."
        },
        {
          "name": "beta",
          "effect": "Controls the slope update when ma_type='dema'; it does not affect the EMA path shown."
        }
      ],
      "cautions": [
        "This operator does not run the complete xPatch forecasting architecture.",
        "The source's dema option is a level/slope recurrence; interpret it from the code rather than assuming every library uses the same DEMA definition.",
        "With season_smooth enabled, the seasonal stream uses centered smoothing even though EMA itself is one-sided.",
        "When alpha is omitted, trend_window can derive it. Explicit alpha takes precedence."
      ],
      "references": [
        {
          "title": "Implemented DeTime operator",
          "url": "https://github.com/systems-mechanobiology/DeTime/blob/main/src/detime/methods/neural_blocks/xpatch_block.py"
        },
        {
          "title": "Stitsyuk and Choi (2024), xPatch: Dual-Stream Time Series Forecasting with Exponential Seasonal-Trend Decomposition",
          "url": "https://arxiv.org/abs/2412.17323"
        }
      ],
      "trace_kind": "computed_operator_trace",
      "trace_note": "Intermediate arrays are computed with the implemented operator helpers. The final trend, season and residual are checked against public decompose(). The animation explains this standalone experimental block; its source architecture is cited for provenance.",
      "input_note": "Deterministic synthetic teaching signal; not a benchmark.",
      "example_config": {
        "method": "XPATCH_BLOCK",
        "params": {
          "ma_type": "ema",
          "alpha": 0.25,
          "season_smooth": 5
        },
        "backend": "python"
      },
      "checks": {
        "public_method_executed": true,
        "method_output_max_abs_errors": {
          "trend": 0.0,
          "season": 0.0,
          "residual": 0.0
        },
        "reconstruction_max_abs_error": 2.220446049250313e-16,
        "validation_scope": "One deterministic teaching input; no benchmark claim."
      },
      "source_files": [
        "src/detime/methods/neural_blocks/xpatch_block.py"
      ],
      "frames": 32,
      "duration_ms": 12050,
      "poster_frame": 15,
      "width": 1280,
      "height": 820,
      "artifacts": {
        "gif": {
          "file": "xpatch-block.gif",
          "bytes": 410144,
          "sha256": "f4173936d517a865481558a7c5ef8a0ce137e8d52f226f62d041f70784e9ad98"
        },
        "poster": {
          "file": "xpatch-block.png",
          "bytes": 165512,
          "sha256": "662d4d1ddc0504fa7f3a82f9e5084843d1ccb23b01c56abddb52a6b65e4d1dfd"
        },
        "data": {
          "file": "xpatch-block.npz",
          "bytes": 8113,
          "sha256": "45edaa61c89af20902adb6fe88cf5f2b001f0892bad9b8e78a9f357786c81393"
        }
      },
      "source_arrays": {
        "observed": [
          144
        ],
        "trend": [
          144
        ],
        "raw_difference": [
          144
        ],
        "season": [
          144
        ],
        "residual": [
          144
        ],
        "alpha_065_trend": [
          144
        ]
      },
      "render_provenance": {
        "python_version": "3.12.14",
        "dependencies": {
          "numpy": "2.3.5",
          "scipy": "1.17.0",
          "statsmodels": "0.15.0",
          "matplotlib": "3.10.8",
          "Pillow": "12.3.0",
          "PyWavelets": "1.10.0",
          "EMD-signal": "1.10.0",
          "vmdpy": "0.2",
          "PySDKit": "0.5.0"
        },
        "source_hashes": {
          "scripts/generate_method_animations.py": "f62989af55a7e48495c24afcfee31751d3785e5f78bb4b900bef23a429deaa84",
          "scripts/method_animations/common.py": "73ad7e8b4e5b67f87d13e59adab2c93e983fe1aaf06ee627d22cb7c7e696016a",
          "scripts/method_animations/neural.py": "fc1c2a73490391f0f863ede52e38f12924cc1fec572b7188356a2308216716e6",
          "src/detime/backends.py": "7432dcf59e382580dfb32f1f57e61ff71a30567c049b35243e24e3644523eda6",
          "src/detime/core.py": "d95b348cd8b16b56d18840965579c947a11628d969dd6c32c4af7723f5a027f4",
          "src/detime/methods/neural_blocks/xpatch_block.py": "4630da9874dd75fbc23dc688b29124ec6944d2dc9f56a200929a36ace4919ffc",
          "src/detime/registry.py": "e934ffca17880cefe5add728aa497e63ea811d7ae43abec1ea498de718094066"
        }
      }
    }
  ]
}
