Welcome to mjolnir’s documentation!#
Welcome to Mjolnir’s documentation#
This package implements abstraction of physical into logical instruments as well as measurement routines for electric and optical experiments. It provides three main logical instruments which bundle functionality of certain parts of the experiment:
ExcitationPath: manages all instruments that are part of the excitation arm of the setup, e.g., the pump laser and the cw-laser chiller.DetectionPath: manages all instruments that are part of the detection arm of the setup, e.g., the spectrometer and the CCD.Sample: manages all instruments that control sample parameters, e.g., the DAC.
These logical instruments live inside a qcodes.Station which is defined by a yaml file in mjolnir/config/. Furthermore, several parameters can be automatically calibrated, for instance the excitation power or the CCD’s pixel-to-wavelength conversion.
Measurements using these logical instruments are controlled through a MeasurementHandler, which provides the measure() method and can be customized to suit a specific measurement types’ requirements through sublcassing. Measurements are defined in terms of Sweeps and Measures, which specify parameters to set (sweep) and get (measure), respectively.
Since a large part of this package consists of hardware abstraction, offline testing is possible only to limited extent. We can, however, demonstrate the typical workflow for measurements (typically run from main.ipy). The following example is also available as a doctest in the measurements module and recreates the doNd sweep example from the QCoDeS documentation’s 15 minutes introduction to QCoDeS notebook.
Boilerplate code to recreate the setup from the QCoDeS documentation
import tempfile
from pathlib import Path
from qcodes import initialise_or_create_database_at, load_or_create_experiment
from qcodes import Station, Instrument
from qcodes.instrument_drivers.mock_instruments import (DummyInstrument,
DummyInstrumentWithMeasurement)
from mjolnir.measurements.sweeps import GridSweep
from mjolnir.measurements.measures import Measure
initialise_or_create_database_at(Path(tempfile.gettempdir(), 'example.db'))
exp = load_or_create_experiment('dummy_experiment', 'dummy_smaple')
dac = DummyInstrument('dac', gates=['ch1', 'ch2'])
dmm = DummyInstrumentWithMeasurement('dmm', setter_instr=dac)
station = Station()
station.add_component(dac)
station.add_component(dmm)
station.add_component(Instrument('dummy_smaple'), update_snapshot=False)
With the setup out of the way, running the measurement is as simple as
handler = DefaultMeasurementHandler(station, 'dummy_smaple')
sweeps = (GridSweep(dac.ch1, (-1, 1), 20, 'lin', delay=0.01)
| GridSweep(dac.ch2, (-1, 1), 20, 'lin', delay=0.01))
measures = Measure(dmm.v1) | Measure(dmm.v2)
run_id = handler.measure(sweeps, measures, show_progress=True)
Here, the | (or) operator specifies that the two sweeps should be nested (i.e., an “outer product”). We can also concatenate Sweep objects using the @ operator, which sequences them in time, and sweep in parallel using the & (and) operator, which sets parameters in parallel (i.e., a “direct product”) so that the diagonal of the parameter space is swept.
In pseudo (Python) code, these operators can be understood in the following way:
from itertools import product, chain
# | (loop nesting)
sweep = sweep_A | sweep_B
for setpoints_A, setpoints_B in product(sweep_A.setpoints, sweep_B.setpoints):
sweep_A.set(setpoints_A)
sweep_B.set(setpoints_B)
# & (loop parallelization)
sweep = sweep_A & sweep_B
for setpoints_A, setpoints_B in zip(sweep_A.setpoints, sweep_B.setpoints):
sweep_A.set(setpoints_A)
sweep_B.set(setpoints_B)
# @ (loop concatenation)
sweep = sweep_A @ sweep_B
for setpoints in chain(setpoints_A, setpoints_B):
sweep.set(setpoints)
Measure objects do not provide much more functionality to the user than the parameters’ get methods. They mostly exist for the MeasurementHandler to know what to expect when measuring them. Additionally, they provide live plotting routines.
Finally, there exists a plotting module, which provides live-monitoring of CCD data and power meter readings as well as a powerful plot_nd() function which can display n-D data by use of slider widgets:

Installation#
python -m pip install --src some/directory -e "mjolnir @ git+https://git-ce.rwth-aachen.de/qutech/lab_software/python-mjolnir.git"
The repository contains QCoDeS instrument .yaml configuration files as submodules in the src/mjolnir/configs directory. Since these can potentially contain sensitive information like connection details, they are kept in a private repository.
If you have access, initialize the submodule like so:
git submodule init
git submodule update
There are some example files under src/mjolnir/configs/examples.
Documentation#
The auto-generated API documentation can be found at the Gitlab Pages.
To build the documentation locally, navigate to doc/ and run
make html
or
sphinx-build -b html _build
Make sure the dependencies are installed via
python -m pip install -e .[doc]
in the top-level directory.
To check if everything works for a clean install (requires hatch to be installed), run
python -m hatch run doc:build
Tests#
There are only rudimentary doctests which
are run on CI.
You can run the tests either via
python -m pytest --doctest-modules
or to check if everything works for a clean install (requires hatch to be installed)
python -m hatch run tests:run
mjolnir API Documentation#
QCoDeS-based instrument abstraction and measurement toolkit. |