qiskit/pulse/samplers/decorators.py
def sampler(sample_function: Callable) -> Callable:
    """Sampler decorator base method.

    Samplers are used for converting an continuous function to a discretized pulse.

    They operate on a function with the signature:
        `def f(times: np.ndarray, *args, **kwargs) -> np.ndarray`
    Where `times` is a numpy array of floats with length n_times and the output array
    is a complex numpy array with length n_times. The output of the decorator is an
    instance of `FunctionalPulse` with signature:
        `def g(duration: int, *args, **kwargs) -> SamplePulse`

    Note if your continuous pulse function outputs a `complex` scalar rather than a
    `np.ndarray`, you should first vectorize it before applying a sampler.


    This class implements the sampler boilerplate for the sampler.

    Args:
        sample_function: A sampler function to be decorated.
    """

    def generate_sampler(continuous_pulse: Callable) -> Callable:
        """Return a decorated sampler function."""

        @functools.wraps(continuous_pulse)
        def call_sampler(duration: int, *args, **kwargs) -> commands.SamplePulse:
            """Replace the call to the continuous function with a call to the sampler applied
            to the anlytic pulse function."""
            sampled_pulse = sample_function(continuous_pulse, duration, *args, **kwargs)
            return np.asarray(sampled_pulse, dtype=np.complex_)

        # Update type annotations for wrapped continuous function to be discrete
        call_sampler = _update_annotations(call_sampler)
        # Update docstring with that of the sampler and include sampled function documentation.
        call_sampler = _update_docstring(call_sampler, sample_function)
        # Unset wrapped to return base sampler signature
        # but still get rest of benefits of wraps
        # such as __name__, __qualname__
        call_sampler.__dict__.pop('__wrapped__')
        # wrap with functional pulse
        return commands.functional_pulse(call_sampler)

    return generate_sampler
def sampler(sample_function: Callable) -> Callable:
    """Sampler decorator base method.

    Samplers are used for converting an continuous function to a discretized pulse.

    They operate on a function with the signature:
        `def f(times: np.ndarray, *args, **kwargs) -> np.ndarray`
    Where `times` is a numpy array of floats with length n_times and the output array
    is a complex numpy array with length n_times. The output of the decorator is an
    instance of `FunctionalPulse` with signature:
        `def g(duration: int, *args, **kwargs) -> SamplePulse`

    Note if your continuous pulse function outputs a `complex` scalar rather than a
    `np.ndarray`, you should first vectorize it before applying a sampler.


    This class implements the sampler boilerplate for the sampler.

    Args:
        sample_function: A sampler function to be decorated.
    """

    def generate_sampler(continuous_pulse: Callable) -> Callable:
        """Return a decorated sampler function."""

        @functools.wraps(continuous_pulse)
        def call_sampler(duration: int, *args, **kwargs) -> commands.SamplePulse:
            """Replace the call to the continuous function with a call to the sampler applied
            to the anlytic pulse function."""
            sampled_pulse = sample_function(continuous_pulse, duration, *args, **kwargs)
            return np.asarray(sampled_pulse, dtype=np.complex_)

        # Update type annotations for wrapped continuous function to be discrete
        call_sampler = _update_annotations(call_sampler)
        # Update docstring with that of the sampler and include sampled function documentation.
        call_sampler = _update_docstring(call_sampler, sample_function)
        # Unset wrapped to return base sampler signature
        # but still get rest of benefits of wraps
        # such as __name__, __qualname__
        call_sampler.__dict__.pop('__wrapped__')
        # wrap with functional pulse
        return commands.functional_pulse(call_sampler)

    return generate_sampler
Sampler decorator base method.

    Samplers are used for converting an continuous function to a discretized pulse.

    They operate on a function with the signature:
        `def f(times: np.ndarray, *args, **kwargs) -> np.ndarray`
    Where `times` is a numpy array of floats with length n_times and the output array
    is a complex numpy array with length n_times. The output of the decorator is an
    instance of `FunctionalPulse` with signature:
        `def g(duration: int, *args, **kwargs) -> SamplePulse`

    Note if your continuous pulse function outputs a `complex` scalar rather than a
    `np.ndarray`, you should first vectorize it before applying a sampler.


    This class implements the sampler boilerplate for the sampler.

    Args:
        sample_function: A sampler function to be decorated.