Skip to content

SWAT Set A: Zt amplitude too low → deep-sleep (level 2) almost never fires #5

@ajaytalati

Description

@ajaytalati

Observation

Inspecting the simulated SWAT Set A 14-day artifact (produced by psim v0.1.2 from `PARAM_SET_A` + `INIT_STATE_A`), the latent Zt trace stays mostly in [0, 3] over the full trajectory. The deep-sleep threshold is c2 = c_tilde + delta_c = 3.0 + 1.5 = 4.5. So sleep_level=2 almost never fires.

In the ordinal sleep generator (`gen_sleep` in `version_1/models/swat/simulation.py`):

```
P(level=2 = deep) = sigmoid(Zt - c2)
```

With Zt peaking at ~3 (and rarely at ~3.5), P(deep) ≈ sigmoid(-1.5) ≈ 0.18 at peaks, P(deep) ≈ sigmoid(-3) ≈ 0.05 typically. The simulated label sequence shows < 5% deep-sleep coverage, vs the ~20-25% deep sleep typical for healthy adults.

See attached: psim diagnostic plot (`outputs/swat/set_A_healthy_14d/swat_channels.png` produced by `psim/examples/swat/14d_set_A_healthy.py`).

Why Zt amplitude is low

The flip-flop dynamics:
```
dZt = (A_SCALE * sigmoid(u_Z) - Zt) / tau_Z # A_SCALE = 6.0
u_Z = -gamma_3 * W - V_n + beta_Z * a
```

For overnight sleep (W=0) with Set A defaults (Vn=0.3, beta_Z=2.5, tau_a=3h):

  • Adenosine `a` rises during wake (W=1), with timescale tau_a=3h. After ~16h wake, a≈1.
  • At sleep onset: u_Z = -0.3 + 2.5·1 = 2.2 → Zt → 6 · sigmoid(2.2) ≈ 5.4 (deep)
  • But `a` clears with same timescale 3h during sleep, so Zt's peak drops over the night.

In practice, the Zt peak in the artifact is only ~3, suggesting either:

  • `a` doesn't reach high values during wake (peak in plot looks like 0.7-0.8, not 1.0)
  • OR `tau_Z=2h` slow-tracks a fast-changing target
  • OR coupling `beta_Z=2.5` is on the low side relative to what's needed

Suggested re-tuning (any one or combination)

For the healthy basin (Set A) to produce realistic deep-sleep proportions (~20-25%):

  1. Lower c_tilde (e.g. 2.5 → c2 = 4.0 makes deep-sleep threshold reachable for typical Zt~3-4)
  2. Boost beta_Z (e.g. 2.5 → 4.0) to amplify a→Zt coupling, pushing Zt closer to 5-6 in deep sleep
  3. Lower tau_Z (2h → 1h) so Zt tracks a more aggressively
  4. Keep tau_a=3h but lower its decay during sleep — would require a model change

Empirically, (1)+(2) combined would make the deep-sleep threshold reachable without changing the timescales.

Why this matters

For SMC² inference, the sleep ordinal channel is essentially providing only binary information (wake vs any sleep) when level=2 almost never fires. This impairs identification of:

  • `c_tilde` (the level-1 threshold)
  • `delta_c` (the level-2 threshold offset; effectively unconstrained because no level-2 data)
  • `beta_Z`, `tau_a` (which together set Zt's overnight amplitude)

All three currently come back with narrow CIs locked off-truth in the SMC² rolling-window estimation (separate finding from the SMC² bug currently being investigated as part of the SWAT port to smc2-blackjax-rolling).

Out of scope here

  • Fix for the SMC² inference bug (in `smc2-blackjax-rolling/smc2bj/log_density/gk_dpf_v3_lite.py`). That's tracked separately in the SMC² repo (private).
  • Sets B/C/D may need similar audit but Set A is the immediate concern.

Reference

  • Plot: `~/Repos/Python-Model-Scenario-Simulation/outputs/swat/set_A_healthy_14d/swat_channels.png`
  • Generator: `version_1/models/swat/simulation.py:gen_sleep`
  • Healthy-adult deep-sleep reference: 13-23% of total sleep, declining with age (Ohayon et al. 2004).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions