I would like to implement a new measurement class of the API as a parameter for the Swabian Instruments TimeTagger driver.
The measurement generates a histogram of time differences between subsequent clicks. Since these can be arbitrarily far apart, the bins are dynamic with only the smallest bin width being defined at start time. Hence, when getting the data at any point after the measurement has started, the array returned will (most likely) have a different shape than the last time it was fetched. To account for this, both the time bins (the setpoints in qcodes lingo) and the counts within (the actual data) are returned together.
The qcodes parameter most naturally suited for this (an array with setpoints) would of course be a ParameterWithSetpoints. However, that requires both an Arrays validator and setpoints with an Arrays validator with a given shape -- which is unknown at setup time. To avoid a chicken-egg problem when making the shape dynamic, i.e., a callback, one would have to call the getData() method of the API for each validator to determine the shape of the data. But then the actual get on the parameter might already have a new shape, because the measurement is ongoing in between calls.
Next, one could think about using MultiParameter. It requires some hacking to make the setpoints and shapes dynamic, but this sort of works:
class DynamicMultiParameter(MultiParameter):
@property
def shapes(self):
return tuple(array.shape for array in self.get_latest())
@shapes.setter
def shapes(self, val):
# the constructor wants to set this
pass
@property
def setpoints(self):
return tuple(tuple(np.arange(n) for n in shape) for shape in self.shapes)
@setpoints.setter
def setpoints(self, val):
# the constructor wants to set this
pass
class MyParam(DynamicMultiParameter):
def get_raw(self):
# api returns array of shape (n, 2)
return tuple(self.instrument.api.getData().T)
While it works, it's not perfect because one of the parameters in this MultiParameter is the others' setpoint, and we'd like to reflect that relationship. The same goes of course for the trivial solution Parameter(..., get_cmd=api.getData).
My questions now are:
- does anybody have a neater solution?
- if not, can we adapt
ParameterWithSetpoints to allow for dynamically sized setpoints/data somehow?
- or else, what would a new parameter type look like that reflects this sort of relationship, and would it have a place in the qcodes core?
I would like to implement a new measurement class of the API as a parameter for the Swabian Instruments TimeTagger driver.
The measurement generates a histogram of time differences between subsequent clicks. Since these can be arbitrarily far apart, the bins are dynamic with only the smallest bin width being defined at start time. Hence, when getting the data at any point after the measurement has started, the array returned will (most likely) have a different shape than the last time it was fetched. To account for this, both the time bins (the setpoints in qcodes lingo) and the counts within (the actual data) are returned together.
The qcodes parameter most naturally suited for this (an array with setpoints) would of course be a
ParameterWithSetpoints. However, that requires both anArraysvalidator and setpoints with anArraysvalidator with a givenshape-- which is unknown at setup time. To avoid a chicken-egg problem when making the shape dynamic, i.e., a callback, one would have to call thegetData()method of the API for each validator to determine the shape of the data. But then the actualgeton the parameter might already have a new shape, because the measurement is ongoing in between calls.Next, one could think about using
MultiParameter. It requires some hacking to make the setpoints and shapes dynamic, but this sort of works:While it works, it's not perfect because one of the parameters in this
MultiParameteris the others' setpoint, and we'd like to reflect that relationship. The same goes of course for the trivial solutionParameter(..., get_cmd=api.getData).My questions now are:
ParameterWithSetpointsto allow for dynamically sized setpoints/data somehow?