Skip to content

Qblox qmi driver - #215

Open
heevasti wants to merge 9 commits into
mainfrom
qblox-qmi-driver
Open

heevasti wants to merge 9 commits into
mainfrom
qblox-qmi-driver

Conversation

@heevasti

@heevasti heevasti commented Jun 2, 2026

Copy link
Copy Markdown
Collaborator

Add a QMI driver for Qblox Cluster series device.

The driver contains only base functions to control the cluster, and trigger channels, and receive system info and module | function reference objects.

@heevasti
heevasti requested a review from pieterjbotma June 2, 2026 11:45

@bvanommen bvanommen left a comment •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests look good, maybe bit of overlap between the two cluster modules.

I don't have experience with the device but looks OK. I would like to know why there are two classes. Is it to control either via SCPI commands or "native" control?

Comment thread qmi/instruments/qblox/cluster.py Outdated
EXT_TRIGGERS_IN_CLUSTER = 15
# Module configuration constants:
# AO_IN_MODULE: Analog output channels in modules with value range -1V...+1V.
# AI_IN_MODULE: Analog output channels in modules with value range -1V...+1V.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

input channels presumeably

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, will correct this, thanks!

Comment thread qmi/instruments/qblox/cluster.py Outdated
# Add type handles as callables
for type_handle, value in self.cluster._type_handle.__dict__.items():
if type_handle.startswith("_is"):
# As 'value' gets overridden in memory for the lambda function, do like this:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overwritten

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will correct this, thanks!

Comment thread qmi/instruments/qblox/cluster.py Outdated
idn = self.cluster._get_idn()
_, model, _, _ = idn.split(",")
self._modules = {"0": _QbloxModule(model, self.cluster_funcs)}
for k, v in self.cluster._mod_handles.items():

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

code would be a bit more readable if these keys and values have a bit more descriptive names

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess the v's are modules?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I will change 'k' to refer to the slot numbers and 'v' to module handles.

if str(module) == module_type:
# Just double check module type before returning
if (
module_type == "QCM"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if these two are on the same line it looks much better

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if Ruff formatter will agree on that. I'll see what it thinks.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, Ruff left it that way.

self.cluster._slot_reset()

@rpc_method
def get_module(self, module_type: str, slot_no: int | None = None) -> NativeCluster | _QbloxModule:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it might be fair enough, but if you have multiple of the same module and you specify the module name, it's not clear which one you're gonna get. Maybe ideally you warn the user (or refuse) when you know there are duplicate modules and they didn't specify the slot.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The module you will get is the first match, i.e. with smallest slot number. I could add a message for the logger here to say the the first matching module will be 'get' when no slot number was provided. To 'know' if there are >1 modules of given type, I would have to change the loop to go to the end or do some pre-loop with the module names only. I think the call description (dosctring) in the base class and a logger info should be informative enough, without making extra checks here.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure I guess that's fine!

Comment thread qmi/instruments/qblox/cluster.py Outdated
for sequencer in range(SEQUENCERS_IN_MODULE[module_type]):
try:
sequencer_config = module_func_refs["_get_sequencer_config"](sequencer)
if channel_type in [0, 1] and AI_IN_MODULE[module_type] > 0:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

magical constants, ideally we replace

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean the channel_type? Those are explained in the base class docstring. But we could consider making enumerated integers class for them, which would make them more clear. Like

class ChannelTypes(Enum.Enum):
    ALL_CHANNELS = 0  # all channels (default)
    AI_CHANNELS = 1  # analog input channels (adc)
    AO_CHANNELS = 2  # analog output channels (dac)
    MRK_CHANNELS =  3  # marker channels
    IO_CHANNELS = 4  # IO channels (QTM only)

and replace

if channel_type in [ChannelTypes.ALL_CHANNELS, ChannelTypes.AI] ...

Or perhaps with even shorter names as we use these only internally, really:
_ChannelTypes.ALL, _ChannelTypes.AI etc.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah sorry my comment was a bit short. Indeed It was not clear to me what channel type 0 and 1 would refer to. I think the second solution is good!

Comment thread qmi/instruments/qblox/cluster.py Outdated
for channel in sequencer_channel_map[1]:
channels[f"adc{channel}_acq_Q{sequencer}"] = sequencer_config["awg"]

if channel_type in [0, 2] and AO_IN_MODULE[module_type] > 0:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

idem with previous

Comment thread qmi/instruments/qblox/cluster.py Outdated
for channel in sequencer_channel_map[1]:
channels[f"dac{channel}_Q{sequencer}"] = sequencer_config["awg"] # TODO: Is this always valid?

if channel_type in [0, 3] and DIGITAL_MARKERS_IN_MODULE[module_type] > 0:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and here

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

idem with previous.

invert: Any


class Qblox_QcodesCluster(Qblox_ClusterBase):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is the difference between this class and Qblox_NativeCluster?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The difference is that the 'NativeCluster' communicates directly with the cluster SCPI interface, while the 'QcodesCluster' communicates with the QCoDeS interface, which then communicates via SCPI interface (and a couple of special features). Both have their pros and cons, which I haven't managed to decide so far which one is overall better. The qblox_instruments API has changed a lot over the development of various versions, and 'QcodesCluster' option was a bit more stable towards the changes, whereas 'NativeCluster' usually needed more smaller changes. On the other hand, at times the 'QcodesCluster' option's dependency 'Cluster' class radically changed with much more complex changes in the 'QcodesCluster' as result.

The other thing is that communicating directly with the SCPI interface we actually do not need the QCoDeS dependency. This reduces also considerably dependency conflicts with other packages as we can override or ignore the QCoDeS version be something else than in the qblox_instruments requirements.

This is of course more maintenance work which is not desirable in the long term. But so far I couldn't weight one out against the other such that a decision could be made into which option we will focus on.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, thanks for the explanation, that is very clear. Then let's keep both for now.
Maybe you could add a sentence or two in comments somewhere that documents this difference? It would be quite informative

@heevasti
heevasti requested a review from bvanommen September 28, 2026 12:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants