Skip to content

Node-tree based parameter structure in instruments  #773

@AdriaanRol

Description

@AdriaanRol

@jenshnielsen @WilliamHPNielsen
As discussed with @alan-geller and @sohailc .
Any work on this requires #600 to be merged (@nulinspiratie) .
Can be seen as a generalization of channel parameters (#640 #641 ) @spauka .
Relevant for future DCL QuTech drivers @nyxus .

I would like to propose supporting a node/tree based structure for parameters in an instrument.
This is motivated by the need to group certain parameters on a more generic level than channels.

Motivation

A concrete example would an instrument like the AWG5014 that has a parameter ch1_m1_high (channel 1 marker 1 high). It would be convenient to group parameters in a node structure. This would mean that instead of using underscores in the name of the parameter the instrument would have nodes with attributes, so ch1_m1_high would become ch1.m1.high.

Such a grouping of parameters would have several advantages.

  • Autocomplete of large instruments would be more managable and would immediately show the relevant groups of parameters to a user.
  • Possible to natively match structure that exists in many instruments (see e.g., colon separated commands in VISA protocols and the Zurich Instruments python API).
  • Possible to add documentation to nodes or groups of parameters.
  • Provides structure to datafiles (where snapshots are saved).
  • Provides structure that can be used in instrument monitoring capabilities.
  • I think this is simpler to understand than the Channel parameter (that does not work as per comment in Parameter improvements #600 ). This argument requires reading the section below.

Proposed implementation/required changes

To make the node based parameters work changes are required to the following methods

  • add_parameter
  • snapshot
  • print_readable_snapshot
  • datasaving/loading -> especially urgent as that is currently being redesigned.
  • A new parameter_node object.
  • Instrument.get and Instrument.set

I will now go over these points individually.

add_parameter

The Instrument.add_parameter method would need to support adding parameters to nodes in a simple way. I would propose only changing the way the name argument of the add_parameter method works.
The name would be split based on the period . character (as conventional in python), the last part of the name would be the name of the parameter. Anything before that corresponds to a node.
The example of pseudo code below shows how it should work

ins.add_parameter(name='ch1.m1.high', **kwargs) 
 -> separate string based on period "." character

 -> check if ch1 exists as a parameter in the instrument. 
           -> if ch1 does not exist, create a "node" 
           -> if ch1 is a regular parameter raise exception 
           -> if ch1 is a node parameter continue 
           -> recursively call this "add_node" part until you get to the `parameter` "high", there add the parameter as it is done now. 

snapshot

Support a nested structure for the dictionary that contains the parameter nodes with parameters in them.

print_readable_snapshot

Preserve the nesting in a readable way. To give an example I give below (part of) a snapshot of our VectorSwitchMatrix and how it could look using a nested structure.

VSM:
	parameter      value
--------------------------------------------------------------------------------
IDN             :	{'driver': "<class 'pycqed.instrument_drivers.physical_inst...
in1_out1_att    :	14
in1_out1_phase  :	0
in1_out1_switch :	EXT
in1_out2_att    :	11
in1_out2_phase  :	90
in1_out2_switch :	EXT
in2_out1_att    :	11
in2_out1_phase  :	0
... # cut short for example
mode            :	raw

Example using the node-tree structure (I couldn't get the alignment to work on github but you get the idea).

VSM:
	parameter      value
--------------------------------------------------------------------------------
IDN                  :	{'driver': "<class 'pycqed.instrument_drivers.physical_inst...
in1
    out1
         att         :	14
         phase      :	0
         switch     :	EXT
    out2
          att       :	11
          phase     :	90
          switch    :	EXT
in2
    out1
        att          :	11
        phase       :	0
... # cut short for example
mode                 :	raw

Note that the indents used here to indicate the groups are also natural folding levels in any kind of interactive monitor.

datasaving/loading

Datasaving should already support saving of snapshots as a JSON like dict (or in hdf5 as we are using). Extending this to nested dicts should not be a problem. Ofcourse this should also be taken into consideration for the future database formats but I don't see fundamental problems here.

ParameterNode object

A new node class has to be made that can be added to an instrument as a parameter but can contain parameters itself. This object should not be very difficult to make but should support the following methods.

  • snapshot -> returning the snapshot of the nodes and parameters it contains (this ensures that the higher level snapshots remain working).
  • get/set -> see below for how instrument get/set should work.
    I'm not sure if a node is more like an instrument (something that can contain parameters) or like a parameter (it can be get/set and is added to an instrument).

Instrument get/set

The get/set methods should support nested extraction of values. To give an example.
VSM.get('in1.out1.att) should return the nested value.

Fancy extensions to get/set

Above I have described the basic idea and functionality that I would like. When working this out it is only natural to think of how the get/set could be made more powerful. I consider this beyond the scope of an initial implementation but as we ( @alan-geller , @sohailc ) discussed them and they could be quite powerful I think it is worth mentioning.

  • allow asterix * character in get/set commands, setting a value to all parameters that match the description e.g., VSM.set('in*.out*.switch, 'OFF') to set all switches to off. Similarly use it to get all values that match the description. I would say that the return format should then be a dict containing the full parameter names (including parent nodes) as keys and the return values as values.
  • Allow setting using a list or dict of values. An example would be `VSM.set('in1.out*.att', [0, 2]) in which case the 0 and 2 values are mapped to out1 and out2 respectively (sorted alphabetically). Note that it is important ot use a list type here as the parameters are not guaranteed to be single valued.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions