Blocks ========== In atomiq you can define so-called blocks which can be used as black boxes within other atomiq experiments or other atomiq blocks (you smell the recursion?). This allows you work out a part of your sequence (e.g. MOT-loading, transfer, imaging,...) once and then reuse it easily in all your other experiments. Since an atomiq block is also an atomiq experiment in itself, you can also run your block standalone. You define that your experiment relies on a certain block by adding it to the class-level blocks list of your experiment class. Then atomiq takes care for all the house-keeping (e.g. initialization of the needed components and recursive block initialization) of the block and import all the block members (functions and attributes you defined) to your experiment. .. rubric:: Example In the following code the experiment with the name `ATQExperiment` wants to use the sequence defined in the `MOT` class. By stating `blocks = [MOT]` the `ATQExperiment` requires the `MOT` block. The `step()` function becomes available as `self.MOT.step()`, reflecting the name of the block. In addition to the required argument `point` it is also possible to specify further keyword arguments to be able to change the behavior of the block when calling it. In the example below this is done by the keyword argument `optional_argument`. .. code-block:: python :emphasize-lines: 22,31 from artiq.experiment import kernel, ms, TBool from atomiq import AtomiqExperiment, AtomiqBlock from my_blocks import Imaging class MOT(AtomiqBlock): components = ["ttl_cool"] @kernel def step(self, point, optional_argument: TBool = False): self.log.info("Test message from the MOT") if optional_argument: self.ttl_cool.pulse(3*ms) class ATQExperiment(AtomiqExperiment): components = ["lock_cooler", "aom_cooler"] blocks = [MOT] @kernel def step(self, point): self.log.info("Test message from the core") delay(3*ms) self.aom_cooler.detune(3e6) self.MOT.step(point, optional_argument=True)