Skip to content

Commit

Permalink
The measurement_windows can now be read in the Waveform.
Browse files Browse the repository at this point in the history
  • Loading branch information
j340m3 authored and lumip committed Dec 7, 2015
1 parent 701e664 commit 2c4285c
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 58 deletions.
9 changes: 5 additions & 4 deletions qctoolkit/pulses/function_pulse_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ def build_sequence(self,
conditions: Dict[str, 'Condition'],
instruction_block: InstructionBlock) -> None:
if self.__is_measurement_pulse:
self.measurement.measure(self.get_pulse_length(parameters))
waveform = FunctionWaveform(parameters, self.__expression, self.__duration_expression, self.__measurement)
self.__measurement.measure(self.get_pulse_length(parameters))
waveform = FunctionWaveform(parameters, self.__expression, self.__duration_expression, self.__measurement.instantiate(parameters))
instruction_block.add_instruction_exec(waveform)

def requires_stop(self, parameters: Dict[str, Parameter], conditions: Dict[str, 'Condition']) -> bool:
Expand Down Expand Up @@ -122,5 +122,6 @@ def sample(self, sample_times: np.ndarray, first_offset: float=0) -> np.ndarray:
return voltages

@property
def measurement(self):
return self.__measurement
def measurement_windows(self, first_offset: float = 0):
self.__measurement.offset = first_offset
return self.__measurement.build()
12 changes: 9 additions & 3 deletions qctoolkit/pulses/instructions.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,9 @@ def sample(self, sample_times: numpy.ndarray, first_offset: float=0) -> numpy.nd
"""

@abstractproperty
def measurement(self):
"""Returns a Measurement-Object which indicates, where the Waveform has to be measured."""
def measurement_windows(self, first_offset: float=0):
"""Returns a list of Tuples, where the first element indicates the "t" of the beginning of the measurement, and
the second indicates their ending."""

class Trigger(Comparable):

Expand Down Expand Up @@ -181,6 +182,7 @@ def __init__(self, outer_block: 'InstructionBlock' = None) -> None:
self.__offset = 0
self.return_ip = None
self.__compiled_sequence = None # type: InstructionSequence
self.__compiled_measurements = None # type: List[Tuple[int]]

def add_instruction(self, instruction: Instruction) -> None:
# change to instructions -> invalidate cached compiled sequence
Expand Down Expand Up @@ -236,7 +238,11 @@ def compile_sequence(self) -> InstructionSequence:
self.__compiled_sequence.extend(blockSequence)

return self.__compiled_sequence


def compile_measurements(self) -> List[Tuple[int]]:
self.compile_sequence()
return self.__compiled_measurements

def get_start_address(self) -> int:
if self.__offset is None:
raise InstructionBlockNotYetPlacedException()
Expand Down
114 changes: 75 additions & 39 deletions qctoolkit/pulses/measurements.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
from typing import NamedTuple
from typing import NamedTuple, Dict, Union

from .instructions import Waveform
from .parameters import Parameter, ParameterDeclaration

SleepWindow = NamedTuple("SleepWindow", [('start', float), ('end', float)])

class Measurement:
def __init__(self, waveform: Waveform, offset: float = 0):
def __init__(self, waveform: Waveform, offset: Union[float, ParameterDeclaration] = 0):
self.__offset = offset
self.__windows = []
self.__waveform = waveform

def measure(self, end: float, start: float=0):
# Standard usage
if isinstance(end, Window):
end.offset = self.__get_end_offset()
end.parent = self
self.__windows.append(end)
else:
self.__windows.append(
Window(start = start, end = end, parent = self, offset = self.__get_end_offset()))
def measure(self, start: Union[float, ParameterDeclaration], end: Union[float, ParameterDeclaration]):
if not isinstance(end, ParameterDeclaration) and not isinstance(start, ParameterDeclaration):
if end < start:
raise ValueError("Measure: Start has to be smaller than end!")
offset = self.__get_end_offset()
if start != 0:
self.sleep(start)
self.__windows.append(
Window(start=start, end=end, parent = self, offset = offset))
return self

def measure_list(self, list_, end, start = 0):
Expand All @@ -35,12 +35,16 @@ def __get_end_offset(self):
else:
return self.__windows[-1].end

def sleep(self, end: float, start: float = 0):
pass
def sleep(self, duration: float):
self.__windows.append(Window(start=0,
end = duration,
parent = self,
is_measure=False,
offset = self.__get_end_offset()))

@property
def duration(self):
self.__waveform.duration
return self.__waveform.duration

@property
def offset(self):
Expand All @@ -55,7 +59,8 @@ def __len__(self):

def __iter__(self):
for i in self.__windows:
yield (i.start, i.end)
if i.is_measure:
yield (i.start, i.end)

def __repr__(self):
res = "Measurement: "
Expand All @@ -64,26 +69,31 @@ def __repr__(self):
as_list.append("({},{})".format(i.start, i.end))
res += ",".join(as_list)

def build(self, parameters: Parameter):
def build(self):
list_ = []
for i in self.__windows:
tuple = 0
if i.is_measure:
tuple = ()
if isinstance(i.start, ParameterDeclaration):
tuple[0] = i.start.get_value(parameters)
else:
tuple[0] = i.start
if isinstance(i.end, ParameterDeclaration):
tuple[0] = i.end.get_value(parameters)
else:
tuple[0] = i.end
list_.append(tuple)
list_.append((i.start,i.end))
return list_

def instantiate(self, parameters: Dict[str, Parameter]):
if isinstance(self.__offset, ParameterDeclaration):
offset = self.__offset.get_value(parameters)
else:
offset = self.__offset
res = Measurement(self.__waveform, offset)
for i in self.__windows:
if i.is_measure:
instance_ = i.instantiate(parameters, res)
res.__windows.append(instance_)
return res

class Window:
def __init__(self, start: float, end: float, parent: Measurement, is_measure: bool = True, offset: float = 0):
def __init__(self, start: Union[float,ParameterDeclaration],
end: Union[float,ParameterDeclaration],
parent: Measurement,
is_measure: bool = True,
offset: Union[float,ParameterDeclaration] = 0):
self.__start = start
self.__end = end
self.__offset = offset
Expand All @@ -92,28 +102,54 @@ def __init__(self, start: float, end: float, parent: Measurement, is_measure: bo

@property
def start(self):
return self.__start + self.__offset + self.__parent.offset
if isinstance(self.__start, ParameterDeclaration):
raise ValueError("Can't calculate with ParameterDeclaration: start")
elif isinstance(self.__offset, ParameterDeclaration):
raise ValueError("Can't calculate with ParameterDeclaration: offset")
elif isinstance(self.__parent.offset, ParameterDeclaration):
raise ValueError("Can't calculate with ParameterDeclaration: parent.offset")
else:
return self.__start + self.__offset + self.__parent.offset

@property
def end(self):
return self.__end + self.__offset + self.__parent.offset
if isinstance(self.__end,ParameterDeclaration):
raise ValueError("Can't calculate with ParameterDeclaration: end")
elif isinstance(self.__offset,ParameterDeclaration):
raise ValueError("Can't calculate with ParameterDeclaration: offset")
elif isinstance(self.__parent.offset, ParameterDeclaration):
raise ValueError("Can't calculate with ParameterDeclaration: parent.offset")
else:
return self.__end + self.__offset + self.__parent.offset

@property
def offset(self):
return self.__offset

@offset.setter
def offset(self, value):
self.__offset = value

@property
def parent(self):
return self.__parent

@parent.setter
def parent(self, value):
self.__parent = value

@property
def is_measure(self):
return self.is_measure
return self.__is_measure

def instantiate(self, parameters: Dict[str, Parameter], parent: Measurement):
args = {}
if isinstance(self.__start, ParameterDeclaration):
args["start"] = self.__start.get_value(parameters)
else:
args["start"] = self.__start

if isinstance(self.__end, ParameterDeclaration):
args["end"] = self.__end.get_value(parameters)
else:
args["end"] = self.__end

if isinstance(self.__offset, ParameterDeclaration):
args["offset"] = self.__offset.get_value(parameters)
else:
args["offset"] = self.__offset
args["parent"] = parent
args["is_measure"] = self.__is_measure
return Window(**args)
1 change: 0 additions & 1 deletion qctoolkit/pulses/parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,6 @@ def deserialize(serializer: Serializer,
max_value = float("+inf")
return ParameterDeclaration(name, min=min_value, max=max_value, default=default_value)


class ParameterNotProvidedException(Exception):
"""Indicates that a required parameter value was not provided."""

Expand Down
11 changes: 6 additions & 5 deletions qctoolkit/pulses/table_pulse_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def __init__(self, measurement=False, identifier: Optional[str]=None) -> None:
'hold': HoldInterpolationStrategy(),
'jump': JumpInterpolationStrategy()
}
self.measurement = Measurement(self)
self.__measurement = Measurement(self)

@staticmethod
def from_array(times: np.ndarray, voltages: np.ndarray, measurement=False) -> 'TablePulseTemplate':
Expand Down Expand Up @@ -280,8 +280,8 @@ def build_sequence(self,
instantiated = self.get_entries_instantiated(parameters)
if instantiated:
if self.__is_measurement_pulse:
self.measurement.measure(instantiated[-1].t)
waveform = TableWaveform(tuple(instantiated), self.measurement)
self.__measurement.measure(instantiated[-1].t)
waveform = TableWaveform(tuple(instantiated), self.__measurement.instantiate(parameters))
instruction_block.add_instruction_exec(waveform)

def requires_stop(self, parameters: Dict[str, Parameter], conditions: Dict[str, 'Condition']) -> bool:
Expand Down Expand Up @@ -351,5 +351,6 @@ def sample(self, sample_times: np.ndarray, offset: float) -> np.ndarray:
return voltages

@property
def measurement(self):
return self.__measurement
def measurement_windows(self, first_offset: float = 0):
self.__measurement.offset = first_offset
return self.__measurement.build()
7 changes: 4 additions & 3 deletions tests/pulses/measurements_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
class MeasurementTest(unittest.TestCase):
def setUp(self):
self.m = Measurement(10)
self.m.measure(5)
self.m.measure(5, 2)
self.m.measure(0, 5)
self.m.measure(2, 5)
self.inst = self.m.instantiate({})

def test_toList(self):
self.assertEqual([x for x in self.m], [(0, 5), (7, 10)])
self.assertEqual([x for x in self.inst], [(0, 5), (7, 10)])
2 changes: 1 addition & 1 deletion tests/pulses/plotting_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def integrated_test_with_sequencer_and_pulse_templates(self) -> None:
# run the sequencer and render the plot
sample_rate = 20
plotter = Plotter(sample_rate=sample_rate)
sequencer = Sequencer() # TODO: removed plotter argument,fix this
sequencer = Sequencer(plotter) # TODO: removed plotter argument,fix this
sequencer.push(sequence, parameters)
block = sequencer.build()
times, voltages = plotter.render(block)
Expand Down
4 changes: 2 additions & 2 deletions tests/pulses/sequencing_dummies.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ def sample(self, sample_times: numpy.ndarray, first_offset: float=0) -> numpy.nd
def offset(self):
return 0

def measurement(self):
return TablePulseTemplate().measurement
def measurement_windows(self):
return [(0,self.duration_)]

class DummySequencer(Sequencer):

Expand Down

0 comments on commit 2c4285c

Please sign in to comment.