Source code for qupulse.pulses.measurement

from typing import Optional, List, Tuple, Union, Dict, Set, Mapping, AbstractSet
from numbers import Real
import itertools

from qupulse.expressions import Expression, ExpressionScalar
from qupulse.utils.types import MeasurementWindow
from qupulse.parameter_scope import Scope

MeasurementDeclaration = Tuple[str, Union[Expression, str, Real], Union[Expression, str, Real]]


[docs]class MeasurementDefiner: def __init__(self, measurements: Optional[List[MeasurementDeclaration]]): if measurements is None: self._measurement_windows = [] else: self._measurement_windows = [(name, begin if isinstance(begin, Expression) else ExpressionScalar(begin), length if isinstance(length, Expression) else ExpressionScalar(length)) for name, begin, length in measurements] for _, _, length in self._measurement_windows: if (length < 0) is True: raise ValueError('Measurement window length may not be negative')
[docs] def get_measurement_windows(self, parameters: Union[Mapping[str, Real], Scope], measurement_mapping: Dict[str, Optional[str]]) -> List[MeasurementWindow]: """Calculate measurement windows with the given parameter set and rename them with the measurement mapping. This method only returns the measurement windows that are defined on `self`. It does _not_ collect the measurement windows defined on eventual child objects that `self` has/is composed of. Args: parameters: Used to calculate the numeric begins and lengths of symbolically defined measurement windows. measurement_mapping: Used to rename/drop measurement windows. Windows mapped to None are dropped. Returns: List of measurement windows directly defined on self """ try: volatile = parameters.get_volatile_parameters().keys() except AttributeError: volatile = frozenset() resulting_windows = [] for name, begin, length in self._measurement_windows: name = measurement_mapping[name] if name is None: continue assert volatile.isdisjoint(begin.variables) and volatile.isdisjoint(length.variables), "volatile measurement parameters are not supported" begin_val = begin.evaluate_in_scope(parameters) length_val = length.evaluate_in_scope(parameters) if begin_val < 0 or length_val < 0: raise ValueError('Measurement window with negative begin or length: {}, {}'.format(begin, length)) resulting_windows.append( (name, begin_val, length_val) ) return resulting_windows
@property def measurement_parameters(self) -> AbstractSet[str]: """Return the parameters of measurements that are directly declared on `self`. Does _not_ visit eventual child objects.""" return set(var for _, begin, length in self._measurement_windows for var in itertools.chain(begin.variables, length.variables)) @property def measurement_declarations(self) -> List[MeasurementDeclaration]: """Return the measurements that are directly declared on `self`. Does _not_ visit eventual child objects.""" return [(name, begin, length) for name, begin, length in self._measurement_windows] @property def measurement_names(self) -> Set[str]: """Return the names of measurements that are directly declared on `self`. Does _not_ visit eventual child objects.""" return {name for name, *_ in self._measurement_windows}