dond to support time-dependence measurements (perhaps with ElapsedTimeParameter)
astafan8 opened this issue · 4 comments
something like
etp = ElapsedTimeParameter()
dond(etp, stuff_to_sweep_and_measure_here, ...)
first of all, ElapsedTimeParameter
does not have a set
method, so it can't be used in dond
as an independent parameter. Secondly, the ask is to run a measurement until elapsed time is more than a specified value (e.g. until elapsed time is more than 10 minutes).
One quick workaround would be to use a dummy parameter as the doNd
set parameter and include the ElapsedTimeParameter
in the list of meas_params
.
Originally requested by @guenp @samantha-ho
Thanks @astafan8 for creating this issue!
The reason why I initially thought it would be great for dond
to support time as a parameter is because in the users' mind, time is just another dimension along which we want to measure a set of parameters or rasters. I'm not fixated on using dond
for this if it is not within the package's design principles, but the convenience of being able to set up a measurement with dond
, then decide "What if I monitor this thing over time"? and only having to make a small change will be great to be able to cover somehow.
Another request for this just came in: for every value of an outer parameter, measure some other parameter as a function of time by acquiring a value every 10 seconds for 5 minutes. I suggested the following solution:
from qcodes.dataset import dond, LinSweep
from qcodes.parameters import ElapsedTimeParameter, Parameter
from qcodes.dataset import new_experiment
new_experiment("some_experiment", "some_sample")
outer_p = Parameter("outer", set_cmd=None, get_cmd=None)
time_p = ElapsedTimeParameter("time_p")
outer_sweep = LinSweep(
outer_p,
0,
2,
10,
# reset the elapsed time parameter
# for every new value of this sweep
post_actions=(time_p.reset_clock,)
)
# For use with LinSweep we need to make another parameter
# that can be `set` that will wrap the time parameter because
# the ElapsedTimeParameter does not have a `set` and `dond` call
# would break if we use ElapsedTimeParameter directly
time_p_with_set = Parameter(
"time",
get_cmd=time_p.get, # returns the value of the time parameter
set_cmd=None # can be set, but we will ignore this value in the dond
)
time_sweep = LinSweep(
time_p_with_set, # we use the wrapping time parameter
start=0, # this value does not matter
stop=5, # this value does not matter
num_points=5*60/10, # 5 mins / 10 seconds, this is the number of times the measurement will be done
delay=10, # seconds, the delay between the time measurements
get_after_set=True, # thanks to #4759
)
# Let's create a fake measurement parameter to use in this example:
meas_p = Parameter("meas", set_cmd=False, get_cmd=lambda: outer_p.get()+time_p.get()*2)
# And this is the measurement!
dond(outer_sweep, time_sweep, meas_p)
my personal opinion is that this snippet is not graceful at all. so i'd welcome a more readable solution.
@astafan8, this issue just came up again. This is the workaround that @ThorvaldLarsen came up with:
time_param = ElapsedTimeParameter('time')
time_param._settable = True
time_param.set = lambda x: None
time_sweep = LinSweep(time_param, 1, 1000, 1000, 0, get_after_set=True)
time_param.reset_clock()
ds, _, _ = dond(time_sweep, *params_to_measure)
This solution is not ideal because we have to pick the number of repetitions based on how long we want the measurement to run, instead of just specifying "please measure for 10 minutes".
We were wondering if it might make sense to implement something like this that behaves more like a while
loop:
time_param = ElapsedTimeParameter('time')
time_sweep = TimeSweep(time_param, start=0, stop=10*60, delay=0)
ds, _, _ = dond(time_sweep , *params_to_measure)
Now that they're released, it makes more sense to use the datasaver_builder
and dond_into
extension than try to make this work in the base dond method.
In rough pseudocode, it would look like this:
time_param = ElapsedTimeParameter('time')
start_time = time.now()
with datasaver_builder(dataset_definition) as datasavers:
while time_param < start_time + duration:
dond_into(datasavers[0], *params_to_measure, additional_setpoints=(time_param,))
time.sleep(delay)
ds = datasavers[0].dataset