Source code for spin_pulse.environment.noise.noise_time_trace

# --------------------------------------------------------------------------------------
# This code is part of SpinPulse.
#
# (C) Copyright Quobly 2025.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
# --------------------------------------------------------------------------------------

from enum import Enum

import matplotlib.pyplot as plt
import numpy as np


[docs] class NoiseType(Enum): """Enumerate the supported noise models for spin-qubit simulations. Each enum value corresponds to the time-trace class used to generate the associated noise realization. Noise types: - QUASISTATIC: Quasistatic noise generated by `QuasistaticNoiseTimeTrace`. - PINK: Pink (1/f) noise generated by `PinkNoiseTimeTrace`. - WHITE: White Gaussian noise generated by `WhiteNoiseTimeTrace`. """
[docs] QUASISTATIC = "QuasistaticNoiseTimeTrace"
[docs] PINK = "PinkNoiseTimeTrace"
[docs] WHITE = "WhiteNoiseTimeTrace"
[docs] class NoiseTimeTrace: r"""Base class for generating and manipulating noise time traces. A noise time trace is represented as an array of length ``duration``, containing the instantaneous noise values :math:`\epsilon(t)` that affect the qubit. Subclasses implement specific noise models (quasistatic, pink, white, etc.) and populate the ``values`` array accordingly. Attributes: - duration (int): Total number of time steps in the noise trace. - values (ndarray): Array of noise values of length ``duration``. """ def __init__(self, duration: int): """Initializes an empty noise time trace of given duration. Parameters: duration (int): Total number of time steps in the noise trace. """
[docs] self.duration = duration
[docs] self.values = np.zeros(duration)
[docs] def ramsey_contrast(self, ramsey_duration: int) -> float: r"""Compute the Ramsey contrast for a qubit subject to this noise trace. The qubit is initialized in the equal superposition state :math:`\frac{\\lvert 0 \rangle + \\lvert 1 \rangle}{\\sqrt{2}}` and evolves under a pure dephasing Hamiltonian :math:`H(t) = \\omega(t) Z`. The Ramsey contrast is obtained from the accumulated phase :math:`\\sum_t \\omega(t)` over segments of length ``ramsey_duration``. The trace is divided into independent experiments of equal length and the contrast is averaged over all experiments. Parameters: ramsey_duration (int): Number of time steps per Ramsey experiment. Returns: - float: Averaged Ramsey contrast of length ``ramsey_duration``. """ n_exp = self.duration // ramsey_duration contrast = 0.0 i_min = 0 for _ in range(n_exp): omega = self.values[i_min : i_min + ramsey_duration] contrast += np.real(np.exp(-1j * np.cumsum(omega))) / n_exp i_min += ramsey_duration return contrast
[docs] def plot_ramsey_contrast(self, ramsey_duration: int): """Plot the Ramsey contrast computed from the noise trace. Parameters: ramsey_duration (int): Number of time steps per Ramsey experiment. """ contrast = self.ramsey_contrast(ramsey_duration) plt.plot(contrast, label="numerics", color="blue") plt.legend(loc=0) plt.xlabel("$t$") plt.ylabel("$C$")
[docs] def plot(self, n_max: int | None = None): """Plot the noise trace up to a specified number of points. Parameters: n_max (int | None): Number of time steps to display. If None, the full trace is shown. """ if n_max is None: n_max = self.duration plt.plot(self.values[:n_max]) plt.xlabel("$t$") plt.ylabel(r"$\epsilon(t)$")