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