Ornstein-Uhlenbeck process

Ornstein-Uhlenbeck process

Figure 2: Two realizations of the Ornstein-Uhlenbeck process for parameters τ=1.0 and σ=0.1 (black curve), and for τ=0.1 and σ=0.31622 (red curve). In both cases the noise intensity is σ^2*τ=0.01 . The red curve represents a noise that more closely mimics Gaussian white noise. Both realizations begin here at x(0)=1.0 , after which the mean decays exponentially to zero with time constant τ.

Andre Longtin (2010) Stochastic dynamical systems. Scholarpedia, 5(4):1619.

Sebastian Schmitt, 2022

// ornstein_uhlenbeck.py
from brian2 import *

N = NeuronGroup(
    1,
    """
    tau : second
    sigma : 1
    dy/dt = -y/tau + sqrt(2*sigma**2/tau)*xi : 1
    """,
    method="euler"
)

N.tau = 0.5 * second
N.sigma = 0.1
N.y = 1

M = StateMonitor(N, "y", record=True)

run(10 * second)
<!-- ornstein_uhlenbeck.html -->
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Brian2 WASM Simulation</title>

    <!-- Plotly and MathJax -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/plotly.js/2.14.0/plotly.min.js"></script>
    <script>
        MathJax = {
          tex: {
            inlineMath: [['$', '$'], ['\\(', '\\)']]
          },
          svg: {
            fontCache: 'global'
          }
        };
    </script>
    <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
    <script src="brian.js"></script>

    <!-- Internal CSS -->
    <style>
        body {
            font-family: Arial, sans-serif;
            background-color: #f4f4f4;
            text-align: center;
            padding: 20px;
        }

        h1 {
            color: #333;
        }

        h2 {
            font-size: 20px;
            color: #444;
        }

        p {
            font-size: 18px;
            margin-bottom: 20px;
        }

        #brian_canvas {
            background: white;
            border: 2px solid #ccc;
            margin: 20px auto;
        }

        progress {
            margin-top: 10px;
            height: 20px;
            border-radius: 5px;
        }

        input[type="range"] {
            width: 200px;
            margin: 10px;
        }

        button {
            background-color: #007bff;
            color: white;
            border: none;
            padding: 10px 15px;
            font-size: 16px;
            cursor: pointer;
            border-radius: 5px;
            margin-top: 10px;
        }

        button:disabled {
            background-color: #aaa;
            cursor: not-allowed;
        }

        #brian_progress_text {
            font-size: 16px;
            font-weight: bold;
            margin-top: 5px;
        }
    </style>
</head>
<body>
    <h1>Brian2 WASM Simulation</h1>

    <h2>Ornstein-Uhlenbeck Process Equation:</h2>
    <p>
        \[
        \frac{dy}{dt} = -\frac{y}{\tau} + \sigma \xi(t)
        \]
    </p>

    <div id="brian_canvas" style="width: 600px; height: 400px;"></div>
    <progress id="brian_progress_bar" max="1.0" value="0.0" style="width: 90%"></progress>
    <div id="brian_progress_text"></div>

    <label for="tau">Tau (τ): </label>
    <input type="range" id="tau" min="0.1" max="2.0" step="0.1" value="0.5"
           oninput="document.getElementById('tau_value').textContent = this.value;">
    <span id="tau_value">0.5</span> s
    <br>

    <label for="sigma">Sigma (σ): </label>
    <input type="range" id="sigma" min="0.01" max="1.5" step="0.05" value="0.9"
           oninput="document.getElementById('sigma_value').textContent = this.value;">
    <span id="sigma_value">0.9</span>
    <br>

    <button type="button" id="brian_run_button" onclick="runSimulation()">Run Simulation</button>

    <script>
        var brian_sim = new BrianSimulation();

        function runSimulation() {
            let tauValue = parseFloat(document.getElementById("tau").value);
            let sigmaValue = parseFloat(document.getElementById("sigma").value);

            // Disable the run button and show "Running Simulation..."
            document.getElementById("brian_run_button").disabled = true;
            document.getElementById("brian_progress_bar").value = 0;
            document.getElementById("brian_progress_text").textContent = "Running Simulation...";

            // Reset graph before new simulation
            Plotly.react('brian_canvas', [{ x: [], y: [], mode: 'lines' }], {
                xaxis: { title: { text: 'Time (s)' }, range: [0, 10] , autorange: true},
                yaxis: { title: { text: 'Ornstein-Uhlenbeck process' }, range: [-1, 1] , autorange: true},
                datarevision: 0
            });

            brian_sim.run({
                'neurongroup.tau': tauValue,
                'neurongroup.sigma': sigmaValue
            });
        }

        window.onload = () => {
            brian_sim.init();
            brian_sim.last_plot_time = 0.0;

            // Create empty plot
            var layout = {
                xaxis: { title: { text: 'Time (s)' }, range: [0, 10] , autorange: true},
                yaxis: { title: { text: 'Ornstein-Uhlenbeck process' }, range: [-1, 1] , autorange: true},
                datarevision: 0
            };

            var spikes = [{ x: [], y: [], mode: 'markers', marker: { size: 1 }, type: 'scatter' }];
            Plotly.react('brian_canvas', spikes, layout);

            let old_onmessage = brian_sim.worker.onmessage;

            brian_sim.worker.onmessage = (e) => {
                if (e.data.type === 'results') {
                    let t = [...e.data.results.statemonitor.t];
                    let index = [...e.data.results.statemonitor.y];

                    // Get current values of tau and sigma
                    let tauValue = document.getElementById("tau").value;
                    let sigmaValue = document.getElementById("sigma").value;

                    // Define layout before using it
                    let layout = {
                        xaxis: { title: { text: 'Time (s)' }, range: [0, 10] , autorange: true},
                        yaxis: { title: { text: 'Ornstein-Uhlenbeck process' }, range: [-1, 1] , autorange: true},
                        datarevision: 0,
                    };

                    let traces = [
                        {
                            x: t,
                            y: index[0],
                            mode: 'lines',
                            line: { color: 'red' }
                        }
                    ];

                    // Update graph with new data
                    layout.datarevision += 1;  // Increment data revision
                    Plotly.react('brian_canvas', traces, layout);

                    // Stop progress bar & enable button
                    document.getElementById("brian_progress_bar").value = 1;
                    document.getElementById("brian_progress_text").textContent = "Simulation complete!";
                    document.getElementById("brian_run_button").disabled = false;
                } else {
                    old_onmessage(e);
                }
            };
        };
    </script>
</body>
</html>
python - m brian2wasm ornstein_uhlenbeck.py

Output

../_images/result_ornstein_uhlenbeck.png