Blocks modular exampleΒΆ
Experiment
from artiq.experiment import kernel, delay, us, ms
from atomiq import AtomiqBlock, AtomiqExperiment
from atomiq.components.primitives import Switchable
class Imaging(AtomiqBlock):
"""
Take Image
This block does everything to take a flouresence image
"""
# The components defined here do not need to exist in the components dict
# as long as every experiment calling us does map these names to something
# existing
components = [("ttl_trigger", Switchable)]
arguments = {"exposure_time": {"default": 0.2, "unit": "s", "scale": 1, "ndecimals": 3}}
@kernel
def step(self, point):
# lets call a function here to see that the importing of all needed members
# works when the block is loaded
self._print_hello()
@kernel
def _print_hello(self):
self.log.info("Testmessage from the Imaging")
self.log.info(self.ttl_trigger)
delay(1 * us)
self.ttl_trigger.pulse(4 * ms)
class MOT(AtomiqBlock):
"""
Load the MOT
This block does everything needed to load a magneto-optical trap
"""
# The components defined here do not need to exist in the components dict
# as long as every experiment calling us does map these names to something
# existing. If the components exist in the components dict, they don't need
# to be specified by the caller. It is strongly recommended to specify the
# type of the expected component here. If the caller specifies something
# else, atomiq will complain.
components = [("ttl_cool", Switchable), ("ttl_ids_camera", Switchable)]
# We can list here sets of the form (class, component_map, alias) to replace
# the component names in the blocks we import (component_map) or to change the
# name under which the block becomes available in our step function. Using an alias
# also allows to use the same block several times with different arguments.
blocks = [(Imaging, {"ttl_trigger": "ttl_cool"}, "Image1"), (Imaging, {"ttl_trigger": "ttl_ids_camera"}, "Image2")]
arguments = {
"mot_cooler_det": {"default": -12, "unit": "MHz", "scale": 1e6, "ndecimals": 3},
"mot_cooler_amplitude": {"default": 0.3, "scale": 1},
"mot_repumper_det": {"default": -12, "unit": "MHz", "scale": 1e6, "ndecimals": 3},
"mot_repumper_amplitude": {"default": 0.3, "scale": 1},
"mot_loading_time": {"default": 0.2, "unit": "s", "scale": 1, "ndecimals": 3},
}
@kernel
def step(self, point):
self.log.info("Testmessage from the MOT")
# call the imaging block
self.Image1.step(point)
# doing some operation with the locally defined components
self.ttl_cool.pulse(3 * ms)
# call the imaging block with different component mapping (ttl_trigger -> ttl_ids_camera)
self.Image2.step(point)
class ModBlockExperiment(AtomiqExperiment):
blocks = [MOT, (Imaging, {"ttl_trigger": "ttl_cool"}, "Image3")]
@kernel
def step(self, point):
self.MOT.step(point)
self.Image3.step(point)
Components
components = {"type": None}
# Add core stuff
components.update(
{
"log": {"classname": "atomiq.components.basics.log.KernelLogger"},
"herosink": {"classname": "atomiq.components.basics.datasink.HEROSink"},
}
)
# Add locks
components.update({"lock_cooler": {"classname": "atomiq.components.lock.ULELock", "arguments": {"lock_offset": 34e6}}})
# Add calibrations
components.update(
{
"cal_pd_cooler": {
"classname": "atomiq.components.basics.calibration.LinearCalibration",
"arguments": {"input_unit": "mV", "output_unit": "mW", "a": 0.342, "b": 0.002},
},
"cal_aom_cooler": {
"classname": "atomiq.components.basics.calibration.InvSigmoidCalibration",
"arguments": {
"input_unit": "amp",
"output_unit": "amp",
"A": 5.0,
"k": 1.0,
"x_offset": 10.0,
"y_offset": 0.3,
},
},
}
)
# Add low level Sinara hardware
components.update(
{
"kasli0": {"classname": "atomiq.components.sinara.Kasli", "arguments": {}},
"sampler0": {
"classname": "atomiq.components.sinara.Sampler",
"arguments": {"sampler_device": "@sampler0", "sampler_default_gain": [1, 0, 0, 0, 0, 0, 0, 0]},
},
"urukul0": {"classname": "atomiq.components.sinara.Urukul", "arguments": {"cpld": "@urukul0_cpld"}},
}
)
# Add low Sinara DIOs
components.update(
{
"ttl_test": {
"classname": "atomiq.components.sinara.DioOutput",
"arguments": {"kasli": "&kasli0", "ttl": "@led0"},
},
"ttl_cool": {
"classname": "atomiq.components.sinara.DioOutput",
"arguments": {"kasli": "&kasli0", "ttl": "@ttl4"},
},
"ttl_repump": {
"classname": "atomiq.components.sinara.DioOutput",
"arguments": {"kasli": "&kasli0", "ttl": "@ttl6"},
},
"ttl_ids_camera": {
"classname": "atomiq.components.sinara.DioOutput",
"arguments": {"kasli": "&kasli0", "ttl": "@ttl5"},
},
}
)
# Add DDS channels
components.update(
{
"dds_cooler": {
"classname": "atomiq.components.sinara.UrukulChannel",
"arguments": {"urukul": "&urukul0", "device": "@urukul0_ch0", "ttl": "@ttl_urukul0_sw0"},
},
"dds_repumper": {
"classname": "atomiq.components.sinara.UrukulChannel",
"arguments": {"urukul": "&urukul0", "device": "@urukul0_ch1", "ttl": "@ttl_urukul0_sw1"},
},
}
)
# Add AOMs
components.update(
{
"aom_cooler": {
"classname": "atomiq.components.optoelectronics.lightmodulator.AOM",
"arguments": {
"rfsource": "&dds_cooler",
"switch": "&dds_cooler",
"center_freq": 80e6,
"switching_delay": 30e-9,
},
},
"aom_repumper": {
"classname": "atomiq.components.optoelectronics.lightmodulator.AOM",
"arguments": {
"rfsource": "&dds_repumper",
"switch": "&ttl_repump",
"center_freq": 110e6,
"switching_delay": 45e-9,
},
},
}
)
# Add analog inputs
components.update(
{
"input_cooler_pd": {
"classname": "atomiq.components.sinara.SamplerChannel",
"arguments": {"adc_device": "&sampler0", "channel": 0, "default_gain": 0},
},
"input_dummy": {
"classname": "atomiq.components.electronics.adc.ADCChannel",
"arguments": {
"adc_device": "&adc_dummy0",
"channel": 0,
},
},
}
)
# Add photodiodes
components.update(
{
"pd_cooler": {
"classname": "atomiq.components.optoelectronics.photodiode.CalibratedPhotodiode",
"arguments": {"adc_channel": "&input_cooler_pd", "calibration": "&cal_pd_cooler"},
}
}
)
# Add lasers
components.update(
{
"laser_cooler": {
"classname": "atomiq.components.sinara.BisectionAOMLaser",
"arguments": {"lock": "&lock_cooler", "monitor_pd": "&pd_cooler", "aom": "&aom_cooler"},
}
}
)
# Add Datasinks
components.update(
{
"pubsub": {
"classname": "atomiq.components.basics.datasink.RPCPublisherSink",
"arguments": {"rpc_publisher": "@messagebuswriter", "topic_prefix": "artiq.", "default_topic": "newData"},
}
}
)