Source code for qibosoq.components.pulses

"""Pulses objects."""

from dataclasses import dataclass, field
from enum import Enum
from typing import List, Optional

import numpy as np


[docs] @dataclass class Element: """Abstract common oject for pulses and measurements.""" type: str """Type of the pulse.""" frequency: float """Frequency of the pulse (MHz).""" start_delay: float = field(compare=False) """Delay before pulse is triggered (us).""" duration: float """Duration of the pulse (us).""" adc: int """ADC to acquire pulse back, for readout pulses.""" dac: int """DAC responsible for firing the pulse.""" @property def waveform_name(self) -> Optional[str]: """Return waveform name from parameters.""" return None @property def style(self) -> Optional[str]: """Return waveform style from parameters.""" return "arb"
[docs] @dataclass class Measurement(Element): """Measurement without pulse.""" type = "readout"
[docs] @dataclass class Pulse(Element): """Abstract Pulse object.""" amplitude: float """Amplitude factor, multiplied by maximum gain of the DAC.""" relative_phase: int """Relative phase (degrees).""" name: str """Name of the pulse, typically a serial.""" type: str """Can be 'readout', 'drive', 'flux'."""
[docs] @dataclass class Rectangular(Pulse): """Rectangular pulse.""" shape: str = "rectangular" @property def style(self) -> Optional[str]: """Return waveform style from parameters.""" return "const"
[docs] @dataclass class Gaussian(Pulse): """Gaussian pulse.""" rel_sigma: float """Sigma of the gaussian as a fraction of duration.""" shape: str = "gaussian" @property def waveform_name(self) -> Optional[str]: """Return waveform name from parameters.""" return f"{self.dac}_gaus_{round(self.rel_sigma, 2)}_{round(self.duration, 2)}"
[docs] @dataclass class Drag(Pulse): """Drag pulse.""" rel_sigma: float """Sigma of the drag as a fraction of duration.""" beta: float """Beta parameter for drag pulse.""" shape: str = "drag" @property def waveform_name(self) -> Optional[str]: """Return waveform name from parameters.""" rel_sigma = round(self.rel_sigma, 2) duration = round(self.duration, 2) beta = round(self.beta, 2) return f"{self.dac}_drag_{rel_sigma}_{duration}_{beta}"
[docs] @dataclass class FlatTop(Pulse): """FlatTop pulse.""" rel_sigma: float """Sigma of the FlatTop as a fraction of duration.""" shape: str = "flattop" @property def waveform_name(self) -> Optional[str]: """Return waveform name from parameters.""" return ( f"{self.dac}_flattop_{round(self.rel_sigma, 2)}_{round(self.duration), 2}" ) @property def style(self) -> Optional[str]: """Return waveform style from parameters.""" return "flat_top"
[docs] @dataclass class FluxExponential(Pulse): """Flux pulse with exponential rising edge to correct distortions.""" tau: float upsilon: float weight: float shape: str = "fluxexponential"
[docs] def i_values(self, duration: int, max_gain: int): """Compute the waveform i values.""" amp = int(self.amplitude * max_gain) time = np.arange(duration) i_vals = ( np.ones(duration) * np.exp(-time / self.upsilon) ) + self.weight * np.exp(-time / self.tau) return amp * i_vals / (1 + self.weight)
[docs] @dataclass class Hann(Pulse): """Hann function.""" shape: str = "hann"
[docs] def i_values(self, duration: int, max_gain: int): """Compute the waveform i values.""" amp = int(self.amplitude * max_gain) i_vals = np.sin(np.pi * np.arange(0, 1, 1 / duration)) ** 2 return amp * i_vals
[docs] @dataclass class Arbitrary(Pulse): """Custom pulse.""" i_values: List[float] q_values: List[float] shape: str = "arbitrary" @property def waveform_name(self) -> Optional[str]: """Return waveform name from parameters.""" return self.name
[docs] class Shape(Enum): """Map shape names to the corresponding objects.""" RECTANGULAR = Rectangular GAUSSIAN = Gaussian DRAG = Drag HANN = Hann FLUXEXPONENTIAL = FluxExponential FLATTOP = FlatTop ARBITRARY = Arbitrary