# Autonomous Circadian Oscillators Intrinsic to Cell Membranes

Computational models and simulation code for the membrane-based circadian oscillator described in:

**"Autonomous circadian oscillators intrinsic to cell membranes"**  
Mauro A. Forlino, Oreste Piro, Monika Stengl & Martin E. Garcia  
[https://doi.org/10.21203/rs.3.rs-8788655/v1](https://doi.org/10.21203/rs.3.rs-8788655/v1)


## Overview

This work shows that circadian rhythms can arise from membrane-associated post-translational feedback loops (PTFLs), operating independently of nuclear transcription-translation feedback loops (TTFLs). Two cell types are modelled:

1. **Red blood cells**: anucleate cells with circadian oscillations in metabolism, redox state and ion transport.
2. **Neurons**: nucleated cells in which the membrane oscillator modulates excitability and firing rate on a circadian timescale.


## Requirements

Python 3.9+ with `numpy`, `scipy` and `matplotlib` (3.5 or newer).

```bash
pip install numpy scipy matplotlib
```

Tested with Python 3.12, NumPy 2.4, SciPy 1.17 and Matplotlib 3.10.


## Contents

| File | Description |
|---|---|
| `RBC.py` | Red blood cell membrane oscillator |
| `NEURON.py` | Neuronal membrane oscillator simulation |
| `NEURON_plot.py` | Figures from the neuronal simulation output |
| `Figure_1.svg`, `Supplementary_Figure.svg` | Output of `RBC.py` |
| `neuron_data.npz` | Output of `NEURON.py` |
| `Figure_2.svg` | Output of `NEURON_plot.py` |

All files sit in a single directory, and the scripts read and write from their
own working directory. The figures and data file included here are reference
outputs; re-running the scripts overwrites them.


## Red blood cell model

```bash
python RBC.py
```

Runs in a few seconds and writes two figures.

`Figure_1.svg` shows the Hill functions used by the model, the Gardos
conductance and intracellular $[K^+]$ under control conditions, the
$[K^+]$–$Met_1$ limit cycle, the effect of hyperpolarization, and the MG132
condition. Two cells in the upper-left of the layout are intentionally blank,
reserved for schematics added during figure assembly.

`Supplementary_Figure.svg` compares all conditions on a 5 × 4 grid. Rows are
PK, $Met_3$, PRX-SO2/3, $G_{Gardos}$ and $[K^+]$; columns are (1) control at
V = −10 mV overlaid with hyperpolarized V = −30 mV, (2) Conoidin A, (3) MG132
and (4) K+ removal, where the dashed line marks the switch to K+-free medium at
t = 24 h. The PRX-SO2/3 row uses a broken y-axis to accommodate the MG132
branch.

Conditions simulated, all integrated over 48 h:

| Condition | Implementation |
|---|---|
| Control | V = −10 mV |
| Hyperpolarized membrane (valinomycin) | V = −30 mV |
| MG132 (proteasomal inhibition) | `lambda_PrxII = 0` |
| Conoidin A (PRX inhibition) | `alpha_PrxII` reduced to 25% |
| K+ removal | K+ dynamics switched off at t = 24 h |


## Neuronal model

### Step 1: simulate

```bash
python NEURON.py
```

Simulates 4 days of activity, coupling Hodgkin-Huxley electrophysiology on the
millisecond timescale to the membrane oscillator on the hour timescale.
Integration proceeds in 1-hour chunks. **This is a long run** — sub-millisecond
resolution over 96 simulated hours takes several hours of wall-clock time.

Results are written to `neuron_data.npz`:

| Key | Contents |
|---|---|
| `time` | Time points, regular 60-second grid over the full run (ms) |
| `Ncc` | Clock channel availability |
| `Y` | Inhibitor concentration |
| `cAMP` | Cyclic AMP concentration |
| `spike_t0`, `spike_isi`, `spike_quantum_ms` | Spike train (see below) |
| `T_series_min`, `V_series_min`, `Ca_series_min` | 1-second window at the minimum firing rate of the last simulated day |
| `T_series_max`, `V_series_max`, `Ca_series_max` | 1-second window at the maximum firing rate |

The spike train is stored as a first time plus inter-spike intervals, both as
integer multiples of `spike_quantum_ms`. To recover absolute spike times in ms,
use `reconstruct_spike_train` from `NEURON_plot.py`, or:

```python
import numpy as np
d = np.load("neuron_data.npz")
steps = np.concatenate([[0], np.cumsum(d["spike_isi"], dtype=np.int64)])
spike_times_ms = (d["spike_t0"] + steps) * d["spike_quantum_ms"]
```

During the run, data is appended to scratch files prefixed `_raw_`, which are
packed into the archive and deleted on completion. If a run is interrupted, the
partial data remains in those files.

### Step 2: plot

```bash
python NEURON_plot.py
```

Takes a few seconds and writes `Figure_2.svg`, showing clock channel availability and firing
rate across the 4 days on a Zeitgeber Time axis, the cAMP–$N_{CC}$ limit cycle,
firing rate against cAMP and against $N_{CC}$, and 1-second voltage and calcium
traces at the daily firing-rate minimum (green, dotted) and maximum (red,
solid).


## Citation

If you use this code, please cite:

> Forlino, M. A., Piro, O., Stengl, M., & Garcia, M. E. (2026). *Autonomous
> circadian oscillators intrinsic to cell membranes.* Research Square.
> https://doi.org/10.21203/rs.3.rs-8788655/v1

```bibtex
@article{forlino2026membrane,
  title   = {Autonomous circadian oscillators intrinsic to cell membranes},
  author  = {Forlino, Mauro A. and Piro, Oreste and Stengl, Monika
             and Garcia, Martin E.},
  year    = {2026},
  journal = {Research Square},
  doi     = {10.21203/rs.3.rs-8788655/v1},
  note    = {Preprint}
}
```

Posted 6 February 2026 as a preprint; not yet peer reviewed.
