def sampler(sample_function: Callable) -> Callable:
def generate_sampler(continuous_pulse: Callable) -> Callable:<EOL><INDENT>"""<STR_LIT>"""<EOL>@functools.wraps(continuous_pulse)<EOL>def call_sampler(duration: int, *args, **kwargs) -> commands.SamplePulse:<EOL><INDENT>"""<STR_LIT>"""<EOL>sampled_pulse = sample_function(continuous_pulse, duration, *args, **kwargs)<EOL>return np.asarray(sampled_pulse, dtype=np.complex_)<EOL><DEDENT>call_sampler = _update_annotations(call_sampler)<EOL>call_sampler = _update_docstring(call_sampler, sample_function)<EOL>call_sampler.__dict__.pop('<STR_LIT>')<EOL>return commands.functional_pulse(call_sampler)<EOL><DEDENT>return generate_sampler<EOL>
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.