Hello,

We want to be able to set parameters of the experimental sequence in a user friendly manner. As far as I can see we have 2 options:
1) Use datasets:

  • store parameters in a dataset
  • prepare a PyQt based GUI that takes variables that will be used to mutate datasets
  • mutate datasets in another @kernel (as in a build method datasets are in read only mode)
  • run the experimental sequence

2) Use "setattr_argument" in a build method and use artiq_dashboard GUI to set the parameters

Am I correct? Or are there other convenient ways to do this, that does not require deep understanding in programming (servers etc.)

Regrading the "setattr_argument", it creates a box with an input. Is there a straightforward way to create similar boxes with different sizes, drop-down menu etc. within artiq_dashboard?

These are the two main ways I use at least. Experiment-specific values are set with attribute arguments and overarching state variables (e.g. detection threshold for the ion) are saved in persistent datasets.

setattr_argument can take a variety of different styles of input types, found here: https://m-labs.hk/artiq/manual/core_language_reference.html#module-artiq.language.environment . The one most used is probably NumberValue, but also drop-downs with EnumerationValue are possible:

self.setattr_argument(
            "command", EnumerationValue(
                ["get", "set"]
            )
   )
  • vli replied to this.

    steine01 Thanks for your reply.

    Can I somehow organize positions and sizes of those input forms? It would be nice to be able to group them in the modules. For example a group of sweeping parameters, a group of laser 1 (frequency, amplitude, on/off TTL signal) etc.

    Also may I ask you how you make an experimental sequence? Do you create different classes for modules of your experiment? For example you have a cooling module as a separate class and adjust it parameters in its build method mutating datasets. If this is the case, how do you schedule different modules? I mean if there are modules it is convenient to have a GUI where you can select and order of modules that you want to implement in a particular experimental sequence and then press a button that will schedule them simultaneously with corresponding priorities to execute them.

    If possible may be a snapshot of your GUI that you use would be very helpful. Just to have an idea how to organize user friendly interface.

    Thanks in advance!

      Datasets can be set in a run() stage on the host, they don't need to be set in a kernel method.

      They can be edited/deleted from either the dashboard (right clicking on a dataset listed under the datasets tab) or directly in the dataset_db.pyon file (for datasets that are persistent). Unless functionality is expanded in the future, to add a new dataset you need to write your own experiment. I've included a rough copy of mine below:

      `
      from artiq.experiment import *
      import std_include

      class SetDataset(EnvExperiment):
      """
      Set a Dataset

      Allows user to manually set/add a new dataset
      """


      # \/ \/ \/ \/ \/ \/ build \/ \/ \/ \/ \/ \/
      
      def build(self):
          #user arguments
          self.setattr_argument("key", StringValue())
          self.setattr_argument("value", PYONValue(default=None))
          self.setattr_argument("broadcast", BooleanValue(default=True))
          self.setattr_argument("persist", BooleanValue(default=False))
          self.setattr_argument("archive", BooleanValue(default=False))
      
          #set scheduler defaults
          self.set_default_scheduling(priority=99)
      
      # /\ /\ /\ /\ /\ /\ build /\ /\ /\ /\ /\ /\
      
      
      # \/ \/ \/ \/ \/ \/ run \/ \/ \/ \/ \/ \/        
      
      def run(self):
          #check that dataset key or value is legitimate
          if self.value is None or self.key == "":
              print(std_include.delimiter)
      
              #no name
              if self.key == "":
                  print("The dataset needs a key (i.e. a name)!")
      
              #no value
              if self.value is None:
                  print("The dataset needs a value!")
      
              print(std_include.delimiter)
      
          #key and value are valid; make dataset
          else:
              self.set_dataset(key=self.key, value=self.value, broadcast=self.broadcast, persist=self.persist, archive=self.archive)
      
      # /\ /\ /\ /\ /\ /\ run /\ /\ /\ /\ /\ /\

      `

      Datasets can be grouped into folders using .

      I set parameters in my experiments using the setattr_argument() method in build(), these can be grouped together using the group argument, documented here. I've written classes derived from HasEnvironment to run commonly used subroutines (e.g. one for cooling, one for detection etc.) and my experiments, derived from EnvExperiment, (e.g. a Rabi flopping experiment) can have instances of these classes, whose methods are called to perform the desired task (e.g. cool the ions). Many of the default values for setattr_argument() I load from datasets. For example, my class to perform detection uses setattr_argument() to allow the user to specify the detection time, number of experimental repetitions for a datapoint, etc. in a given experiment. The default values for these are stored in persistent datasets.

      edit: Sorry for the weird code block formatting... not sure why I can't get it to format correctly.

        vli In general I have a similiar setup to what connorgoham describes in their post. Grouping of parameters is most easily done with the group parameter (as they said as well):

        self.setattr_argument(
                    "trap_attenuation", NumberValue(
                        default = 7*dB,
                        min = 0*dB,
                        max = +31.5*dB,
                        step = 1*dB, unit = "dB",
                        ndecimals = 4
                    ), group = "Trap RF drive", tooltip = "Attenuation trap"
                )
                self.setattr_argument(
                    "trap_frequency", NumberValue(
                        default = 13.642*MHz,
                        min = 0*MHz,
                        max = +20*MHz,
                        step = 0.001*MHz, unit = "MHz",
                        ndecimals = 8
                    ), group = "Trap RF drive", tooltip = "Trap RF frequency"
                )
                self.setattr_argument(
                    "trap_phase", NumberValue(
                        default = 0,
                        min = 0,
                        max = 360,
                        step = 0.01, unit = "",
                        ndecimals = 8
                    ), group = "Trap RF drive", tooltip = "Phase trap RF"
                )

        For reusing sequences, I also use HasEnvironment subclasses, e.g. for a bit more comfortable access to the Urukul or Zotino controllers. I do not use a GUI to rearrange the methods of these subclasses or anything like that, it is all done in code by writing separate experiments. I am also not aware of any established GUI that supports this.

        As for a snapshot of the GUI, it is just the artiq_dashboard supplied by ARTIQ itself, so it is not that interesting. What I will add is, that you can put python files in subfolders in the repository main folder and these will then be represented in the Dashboard explorer as well. This makes it easy to group experiments by their purpose (e.g. Ion Loading, Set Laser Parameters, ...)

        If you have any other questions, just go ahead and ask, but I think it would help if you have a specific example in mind, that is representative for something you want to accomplish and you can then also share some of the code/work you have done so far. That makes it easier to discuss advantages and disadvantages of certain approaches.

        connorgoham Just about the code block: I found that for some reason you need to add a newline just after the beginning of the block, so that the forum formats it correctly. You can then delete that newline again and it stays formatted correctly. I have no idea why that is though.

        • vli replied to this.

          steine01 @connorgoham
          Thanks a lot for your comments! I am still digesting everything what you wrote. But I really appreciate your help. I am becoming aware of things by looking at other people's examples. The thing about grouping arguments is very useful. I will definitely get back once I will have some working code. I think sharing working things to show how things are implemented and what can be done is the best way to help people with a small experience in programming to get thinks working.

          BTW it would be a nice pratice to put the solution to a problem in the end to let others reuse it. It is not always the case. I usually find people saying: "thanks I was able to solve it". But how exactly, would be helpful, for dummies at least =)