{
  "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"
    }
  }
}
