Concerning the list handling: As mentioned in the FAQ (https://m-labs.hk/artiq/manual/faq.html), variable length arrays are not supported for @kernel
functions. This means, that operations like append
and concatenating two lists will not work in @kernel
functions. Outside of them (on the host I guess), you can use variable length lists though.
So the way I take care of it is to preallocate a list with some default value that is used in @kernel
functions and just use that or by @rpc
methods I pass values to a separate list on the host, that is being managed there and I can use all of Python's tools if necessary. The same is the case for numpy
arrays.
I also want to briefly mention the method append_to_dataset
(https://m-labs.hk/artiq/manual/core_language_reference.html) which is useful if you just want to save some values in a list for external evaluation. Then a whole list is sometimes not even needed.
As an example of list handling, here is my experiment for reading out a PMT live through a TTL. It is probably not the optimal way (e.g. I do not use append_to_dataset
here, because it is an older experiment and I did not know this method back then), but maybe helps anyway:
class PMTTimeSeries(EnvExperiment):
def build(self):
self.setattr_device("core")
self.setattr_device("ttl0")
self.setattr_device("scheduler")
self.setattr_device("ccb")
self.setattr_argument("t_accu", NumberValue(
min = 0*us,
max = 10*s,
default = 10*ms,
unit = "ms"),
tooltip="Accumulation time")
self.setattr_argument("samples", NumberValue(
min = 10,
max = 100000),
tooltip="Number of displayed samples")
@kernel
def run(self):
self.ccb.issue("create_applet", "pmt_time_series",
"${artiq_applet}plot_xy n_photons", ["PMT"])
self.set_dataset("n_photons", [None], broadcast=True)
while True:
self.core.break_realtime()
try:
photon_count = self.ttl0.count(self.ttl0.gate_rising(self.t_accu))
if self.cb(photon_count):
break
except RTIOOverflow:
continue
def cb(self, photon_count) -> TBool:
n_photons = self.get_dataset("n_photons")
if n_photons[0] is None:
n_photons[0] = photon_count
else:
n_photons.append(photon_count)
if len(n_photons) > self.samples:
n_photons.pop(0)
self.set_dataset("n_photons", n_photons, broadcast=True)
try:
self.scheduler.pause()
except TerminationRequested:
return True
return False