Skip to main content
Have a personal or library account? Click to login
Atomize: A Modular Software for Control and Automation of Scientific and Industrial Instruments Cover

Atomize: A Modular Software for Control and Automation of Scientific and Industrial Instruments

Open Access
|Nov 2025

Full Article

(1) Overview

Introduction

Remote control of spectrometers and automation of various measurements are usually carried out using software that is either home-written or supplied with the instruments. Such software is often limited to performing a predefined set of experiments with a certain device configuration. It usually provides a graphical user interface (GUI) that allows users to modify a fixed set of parameters and then run one of several available procedures. This approach works perfectly and reliably until a user needs to conduct an experiment or measurement for which the program was not written. Usually, to solve this problem, it is necessary to significantly modify the existing program or even write a new one. This process can be time-consuming and requires a high level of expertise in device programming and automation. Apart from new type of experiments, the same problems may arise if any part of the spectrometer needs to be replaced with a new, but functionally similar device, either due to the device failure or as part of an upgrade. Atomize was created to provide greater flexibility in this regards and to offer a range of features aimed to simplify interaction with instruments. These are as follows:

  1. Users can configure new experiments without having to modify the core part of the software.

  2. Experiments are easy to program. All complex and verbose syntax is hidden from users.

  3. The sequence of actions and logic of the experiment are understandable even without significant programming experience.

  4. The devices of the same type are exchangeable, and support for new devices does not require any changes in the core part of the software.

  5. There is a mechanism to prevent improper use of equipment.

  6. Users can plot, save, and process the acquired data.

These features are primarily available due to the modular design of the software. For each device available in Atomize, there is a special module that allows users to control it using high-level functions with self-explanatory names. This simplifies setting up a new experiment or modifying an existing one, without requiring detailed knowledge about the internals of the program or how the devices are controlled by the computer. Various methods of device classes can be combined into a sequence of actions in one Python script, opening up virtually unlimited possibilities for automating experiments and measurements, as well as processing and visualizing the acquired data. The latter includes one- and two-dimensional graphs and can be done using simple high-level functions based on the highly productive pyqtgraph library. As of 2025, Atomize supports more than 27 different devices, including 6 series of devices. All of them are listed in Table 1. The modules have more than 200 device specific and general-purpose functions.

Table 1

Devices supported by Atomize as of 2025.

TYPE OF DEVICEMANUFACTURER/MODEL
Temperature ControllerLakeshore 325; 331; 332; 335; 336; 340
Oxford Instruments ITC 503
Termodat 11M6; 13KX3
Stanford Research PTC10
Scientific Instruments SCM10
Lock-in AmplifierStanford Research SR-810; SR-830; SR-850; SR-860; SR-865a
OscilloscopeKeysight InfiniiVision 2000, 3000, 4000 X-Series (Ethernet)
Tektronix 3000, 4000 Series
Tektronix 5 Series MSO
Digitizer (PCI, PCIe ADC)Spectrum M4I 4450 X8; M4I 2211 X8
Insys FM214x3GDA
L-card L502
Arbitrary Wave Generator(PCI, PCIe DAC; Oscilloscope DAC)Spectrum M4I 6631 X8
Insys FM214x3GDA
Keysight InfiniiVision 2000, 3000, 4000 X-Series
Multichannel TTL Pulse GeneratorPulse Blaster ESR 500 Pro
Pulse Programmer Micran based on Insys FMC126P
Insys FM214x3GDA
Frequency CounterAgilent 53181A; 53131A/132A; 5343A
Keysight 53230A/220A
Magnetic Field ControllerBruker BH15; ER032M
Microwave Bridge ControllerMicran X-band MW Bridge
Micran Q-band MW Bridge
GaussmeterLakeshore 455 DSP
NMR Gaussmeter Sibir 1
Power SupplyRigol DP800 Series
Stanford Research DC205; PS300
Magnet Power SupplyCryomagnetics 4G
Delay GeneratorStanford Research DG535
Moisture MeterIVG-1/1
BalanceCPWplus 150
OtherRODOS-10N
Owen-MK110-220.4DN.4R
Cryomagnetics LM-510
Cryomech CPA2896, CPA1110

Development of the software began in 2020 and was inspired by another ideologically close program, fsc2, created by Jens Törring [1]. Unfortunately, fsc2 is no longer supported, and the use of its own interpreted language, EDL, creates a rather high barrier to maintain it. Given the widespread use of Python and its exceptionally large developer community, using this language for measurement automation currently appears to be a more practical and sustainable choice. Due to development history of Atomize, the software is focused on electron paramagnetic resonance (EPR) spectrometers. However, its flexible design makes it easy to use for automating other experiments in laboratories and research centers not related to EPR.

The main analogues of Atomize are the commercial software LabVIEW from National Instruments and several open-source programs described below. LabVIEW has been developed and used for over 30 years, which indicates its high demand and degree of sophistication. However, depending on the scale and funding of a project, purchasing expensive proprietary software is not always feasible, so open source projects comes to the rescue in this case. The first example is the already mentioned fsc2. Fsc2 is one of the pioneers in the field of scientific measurement automation. The program was actively developed between 2000 and 2015. At present, its development has effectively ceased. There are also similar to Atomize open source Python projects, such as pyMeasure, PyMoDAQ, Bluesky [24]. These are well-developed, maintained programs that represent another implementation of most of Atomize’s ideas. They have a different set of available devices that, for example, does not include PCI and PCIe multichannel pulse generators, analogue-to-digital converters (ADCs) and digital-to-analogue converters (DACs), which are actively used in the field of magnetic resonance. The authors do not have experience working with these packages to provide unbiased comparison, so we will try to highlight the main features of Atomize. The first is a unified set of semantic methods for similar instruments, which greatly simplifies device exchangeability and creates versatility in experimental scripts. The second feature of Atomize is test runs that allow users to check the logic of the experiment and the device setting without the risk of damaging it; see also the Quality Control section. As for other important aspects of automation software, they are quite similar. A brief comparison with a focus on Atomize is presented in the following points:

  1. PyMeasure, PyMoDAQ, and Atomize have GUI mechanisms, which are particularly well developed in PyMoDAQ. In the case of Atomize, the GUI only allows basic interaction with the acquired data and experimental scripts, without, for example, templates to interactively scan a given parameter, provided in PyMeasure.

  2. PyMeasure, PyMoDAQ, and Atomize use the same pyqtgraph library for plotting one-dimensional graphs, which determines their virtually identical performance. PyMoDAQ and Atomize can also plot two-dimensional graphs, and in the case of Atomize, several two-dimensional graphs can be combined into a single multi-graph with a third axis defining the number of the 2D plot.

  3. PyMoDAQ and Bluesky have sophisticated data management capabilities, while Atomize only offers basic options such as saving and opening text files, or simple mathematical modules such as a Fourier transform module.

  4. PyMeasure, PyMoDAQ, Bluesky have fairly large, established, and active communities of developers and users. For example, specially planned training sessions are organized for PyMoDAQ users. Atomize is still niche software, focused primarily on magnetic resonance applications.

  5. PyMeasure and Bluesky have the largest number of available device modules which is their strong advantage. PyMoDAQ provides the ability to use PyMeasure instrument modules, which may also be a reasonable solution for Atomize, see also the Further Extension section.

To summarize briefly, all these projects share common ideas and goals, and each of them could benefit significantly from potential cooperation.

Usage

At the moment, Atomize is used to control several spectrometers using a broad range of different devices at research institutes in the Russian Federation [5]. The cases known to the developers are listed in Table 2. Due to the professional background of the developers, they are mainly associated with EPR spectroscopy, but the general concept of the software is not limited to a specific field of science. The software was also used to automate the custom measurements, presented in several scientific papers [6, 7, 8, 9, 10]. There is also at least one case where Atomize completely replaced LabVIEW for controlling a liquid helium plant LHeP22 (Cryomech, USA).

Table 2

Research institutes known to the developers that use Atomize software as of 2025.

ORGANIZATIONTYPE OF SPECTROMETERREFERENCE
Vorozhtsov Novosibirsk Institute of Organic Chemistry SB RASX-band pulsed EPR[5]
Vorozhtsov Novosibirsk Institute of Organic Chemistry SB RASQ-band pulsed EPR
International Tomography Center SB RASADC and DAC unit for X-, Q-band pulsed EPR[8]
Budker Institute of Nuclear Physics SB RAS, International Tomography Center SB RASX-band EPR endstation at the Novosibirsk free electron laser facility[7, 9, 10, 11, 12]
Zavoisky Physical-Technical Institute RASADC, DAC, and multichannel pulse generator unit for X-, Q-band pulsed EPR
International Tomography Center SB RASControl software for Cryomech liquid helium plant LHeP22

Implementation And Architecture

Atomize represents a set of relatively independent modules that cover various aspects of control and automation of scientific experiments. These modules provide (i) the ability of interacting with various equipments connected to the computer via different communication protocols, (ii) a convenient way to plot and treat the experimental data acquired, (iii) general-purpose functions that simplify the code and minimize its amount. The modules are usually written in Python, but for some high-performance PCI or PCIe devices, a combination of C code and ctypes-based API is used. The user of the software can combine the necessary modules in a single Python program to create a so-called experimental script. Essentially, the latter is a description of a sequence of action for configuring instruments, acquiring, processing, displaying, and saving experimental data. To simplify interaction with the software, all verbose syntax constructs are hidden in the internal parts of the modules, allowing the user to utilize only simple high-level functions and ensuring that the logic of the experiment is understandable even without substantial programming background. The described architecture is schematically shown in Figure 1, and the implementation of individual parts of the software is discussed in more detail in the following subsections.

Figure 1

The general structure of the modular software Atomize.

Internal structure of the module

Each device module is a Python class with a number of methods that allow users to perform various operations with the device, such as changing its settings, querying current settings, or requesting acquired data. The internal structure of the module can be described by a few simple rules that are mainly aimed at simplifying the use of the device module in experimental scripts. These are as follows:

  1. Each device has a configuration file. This file specifies the communication protocol settings and device specific parameters, for example, the number of analog channels of an oscilloscope or the number of temperature controller loops.

  2. The class initialization method connects the computer to the device.

  3. Device methods of the same type have the same names and, as far as possible, the same arguments. For example, all oscilloscopes modules have a method oscilloscope_get_curve() that queries data from the oscilloscope. Method names are usually self-explanatory and contain the device type and the function performed by the method, e.g. lock_in_time_constant() or magnet_field().

  4. If possible, the same method requests and sets the target value of a certain device parameter. An example is shown in Listing 1.

  5. Certain available values of different device settings are listed in the initialization method, usually in the form of Python dictionaries to convert the syntax of a specific device to the general arguments of Atomize. The parameter limits are also given in the initialization method. All of them are used during test runs; see the Quality Control section. Several examples are shown in Listing 2. If a parameter can only take one of several available discrete values, the methods have built-in automatic rounding to the nearest allowed value with a corresponding indication to the user.

  6. Currently, Atomize does not use the dimensions of physical quantities. Instead, Python dictionaries are used, as shown in Listing 3.

Listing 1

The same method lock_in_time_constant() sets and queries the time constant of the lock-in amplifier used.

Listing 2

Several examples of auxiliary dictionaries and parameter limits from different modules.

Listing 3

Examples of Python dictionaries for handling the dimensions of physical quantities.

Plotting Functions

Plotting of data acquired by different devices is available via liveplot library [13]. This library has not been updated for the past 10 years, so Atomize developers modified it according to the aims of the project and embedded it directly into Atomize. Liveplot is currently unavailable as a separate package, but Atomize without devices is its equivalent. The general idea of liveplot is to be able to view data as it comes in to your Python script with minimal effort using an appropriate shell to cover verbose syntax. The library is based on the highly productive graphics library pyqtgraph [14] and uses a server-client approach. It allows users to plot one- and two-dimensional graphs and combine the latter into a single set of 2D plots. The typical redraw rate is about a few milliseconds for a plot, based on a medium-sized array, e.g. arrays of shape (~ 104–105) for 1D and (103, 103) for 2D data. Both numpy arrays and python lists are supported. The high-level plotting methods have self-explanatory names, plot_1d() and plot_2d(), and can be executed in a parallel thread using the threading library of Python with a special keyword argument. All these functions belong to the Atomize general functions module. Minimal examples of using these methods inside the experimental script are shown in Listings 4, 5.

Listing 4

A minimal example of plotting one-dimensional data

Listing 5

A minimal example of plotting two-dimensional data

Each plot drawn in the script has a user-defined name and is stored as a QDockWidget in a special list in the liveplot tab; see the Graphical User Interface subsection below. Qt docks have basic interactive capabilities, such as changing shape, minimizing, undocking into a separate window, etc. In addition to the many features of the native pyqtgraph, the plotting part of Atomize has several additional widgets, such as cross-hair marker, cross-section cuts for 2D data, etc.

General Functions and Modules

In addition to plotting methods, the Atomize general functions module also contains several general-purpose methods. These include a method for pausing inside an experimental script, wait(), for an infinite loop, to_infinity(), for performing repeated measurements, scans(), etc. The main purpose of these methods is to efficiently implement test runs of experimental scripts, see the Quality Control section. For example, to avoid checking all unnecessary repetitions of identical scans that may be present in the script. There is also a module for interactive saving of data obtained in the script, which hides the complex syntax required for this. There are two implementations of this module: the first in Qt and the second in tkinter. The same idea of covering complex syntax and simplifying interaction with the software can be used for mathematical operations, required to process raw data in experimental scripts. At the moment, Atomize has only one example, namely a module for computing Fourier transforms, which is mainly due to the fact that the developers work in the field of magnetic resonance. For remote monitoring of the current status of the experiment, there is a possibility of integration with a Telegram bot. Using the corresponding function in the experimental script, messages with the desired parameters or screenshots of key moments of the experiment can be sent directly to a mobile phone. To ensure concurrency and work with instruments that may take a long time to respond, there is a module called returned_thread. It allows to run a specified function in a parallel thread and receive returned values from it when the thread has finished. A relevant example is provided in the documentation. Finally, it is also possible to create a macro script that sequentially runs a set of different measurements, further supporting experimental workflows.

Graphical User Interface

To improve usability, Atomize has a simple GUI. The GUI is written in Qt and includes two main tabs. The first tab is for opening, testing, editing, and running scripts, and the second tab is for drawing graphs. The first tab also contains a text field to display the outputs of experimental scripts, if specified by the user, or the results of test runs, see the Quality Control section.

Quality Control

Atomize is essentially an aggregator of self-sufficient modules for various instruments or general-purpose functions, such as plotting or computing Fourier transforms. To ensure that the experimental script behaves as expected, the software uses a kind of unit testing. After preparing the experimental script and running it in the software, a test run of the script is always performed. The main purpose of the test run is to check for syntax and logical errors in the script. While syntax checking will be performed by the Python interpreter in any case, logical errors can easily be overlooked, which is rather annoying. Logical errors mainly mean situations where certain parameters go beyond the device limits during script execution. For example, without a test run, it may happen that at some point during the experiment, the magnet field should be set to a value that the magnet cannot produce. This will inevitably lead to the script stopping and a loss of time, and in the worst case, to damage to the device being used. In contrast, during the test run, the function responsible for setting the magnet to a new field is called with all the values expected during the actual experiment, allowing invalid field settings to be detected and prevented. To speed up testing and ensure the safety of the devices used, in the test run, access to the devices is not provided, calls of the wait() function do not cause the program to sleep for the requested time, plots are not drawn etc. An overview of the experimental script execution in Atomize is shown in Figure 2.

Figure 2

The schematic representation of the execution flow of experimental scripts. After an experimental script is written and launched in Atomize, a test run is performed, in which there is no access to the devices used. Test runs only check the correctness of device settings, experiment logic, and syntax. If there are no errors in the script, after the test run, the same script is immediately executed in the standard mode with full access to the instruments used.

Module developers have an important responsibility to ensure that the test run can be performed. Since real hardware is not accessed during tests, the modules must handle requests for data from devices in a reasonable way, creating appropriate test data instead of real data. An example of an internal check of a certain parameter in a device module is shown in Listing 6.

Listing 6

An example of a parameter check used in the lock_in_ref_amplitude() method of the Stanford Research SR-830 module. The test_flag parameter is used to indicate the start of the test part of the module. A class attribute self.test_amplitude shows an example of the specially generated test data.

Assessing correctness of the software usage is also supported by the provided example scripts and documentation. The latter includes detailed instructions on installing the software, using its features, and developing new modules.

(2) Availability

Operating system

The software can be used on any operating system (OS) with the appropriate version of Python, including GNU/Linux, Mac OSX, Windows. However, the recommended OS is GNU/Linux, on which most of the available devices have been tested. The GUI has been optimized for Ubuntu distribution, starting with version 18.04 LTS.

Programming language

Python ≥ 3.10

Additional system requirements

If devices operating via a General Purpose Interface Bus (IEEE-488, GPIB) are used, the computer must have the appropriate interfaces available, such as PCI-GPIB, PCIe-GPIB or USB-GPIB, etc. Also, the use of software modules for PCI or PCIe multichannel pulse generators, ADCs, and DACs requires corresponding kernel drivers that are usually available free of charge.

Dependencies

Atomize has the following direct dependencies:

Hatchling ≥ 1.9;

Numpy ≥ 1.25;

PyQt ≥ 6.2;

Pyqtgraph ≥ 0.12;

PyVisa ≥ 1.11;

PyVisa-py ≥ 0.5.

And the following optional dependencies:

PySerial ≥ 3.5 for using serial instruments;

Tkinter ≥ 8.6 for using tkinter realization of the data saving module;

Minimalmodbus ≥ 1.0 for using modbus instruments;

Pytelegrambotapi ≥ 4.15 for sending messages via Telegram bot;

SciPy ≥ 1.15 for mathematical modules.

List of contributors

Table 3 shows an extended list of contributors to this software who provided helpful advices or whose code was used as a starting point for the development of Atomize device modules.

Table 3

Contributors who are not listed as the authors of this paper.

NAMEAFFILIATIONCONTRIBUTIONORCHID/GITHUB
Phil ReinholdDepartment of Applied Physics, Yale University, New HavenFirst realization of the liveplot utility0000-0002-8141-1842
Jens TörringFree University of Berlin, BerlinFsc2 creator; C code for old Bruker devices
Chris BillingtonInstitute for Photonics and Advanced Sensing, University of Adelaide, MelbournePython API for Pulse Blaster ESR 500 Prochrisjbillington
Phil StarkeySoftware Developer, MelbournePython API for Pulse Blaster ESR 500 Prophilipstarkey
Michael BowmanDepartment of Chemistry & Biochemistry, University of Alabama, TuscaloosaFruitful discussions0000-0003-3464-9409
Nikolay IsaevVoevodsky Institute of Chemical Kinetics and Combustion SB RAS, NovosibirskFruitful discussions; testing0000-0002-3076-0196

Software location

Archive

Code repository

Language

English

(3) Reuse potential

Experimental Scripts

The general idea behind the software is to simplify as much as possible the performing of all kinds of scientific measurements, automating experimental workflows, or SCADA system implementations. Of course, this comes at a price: it is necessary to clearly specify how the experiment should be done. This is done by writing a usually short Python script. To assist the user, test runs are provided, see the Quality Control section, which allow for the elimination all syntax and logical errors in the script without additional code. An experimental script typically consists of four main parts, namely, (i) importing and initializing of the necessary devices, (ii) configuring the devices, (iii) defining a sequence of actions to perform a desired measurement, (iv) saving and/or processing the data obtained. To uncover the reuse potential of Atomize, consider one simple example in detail. Assume that we have built a continuous wave (CW) EPR spectrometer and now would like to realize the ability to record CW EPR spectra under different experimental conditions. Without going into detail, recording the EPR spectrum is quite simple: using a lock-in amplifier, it is necessary to measure the amplitude of the signal from the detector located in the microwave bridge at different values of the external magnetic field. The signal is caused by microwave power absorption by the spin system, observed under resonant conditions. To increase the signal to noise ratio, external magnetic field modulation is typically used, requiring the use of the lock-in detection scheme. To make the setup slightly more advanced, we will also add the possibility to measure the exact frequency of the microwave source using a frequency counter, but omit the details of tuning the microwave bridge so as not to complicate the description with a lot of EPR spectroscopy. A schematic representation of the main principles of CW EPR spectroscopy, a scheme of a possible experimental setup, and the experimental flow are shown in Figure 3.

Figure 3

Basic principles of CW EPR spectroscopy. (a) A schematic representation of a continuous wave EPR experiment. The sample is continuously irradiated with microwaves, while an external magnetic field is swept. A small additional modulation of the magnetic field (typically up to 1 mT) is applied to enable lock-in detection at the modulation frequency. (b) A diagram of a possible experimental setup. A lock-in amplifier, magnetic field controller, and frequency counter are controlled via Atomize. Numbers show: 1 – sample; 2 – magnetic field modulation coils; 3 – microwave cavity; 4 – electromagnet. (c) Schematic representation of the experimental procedure presented in Listings 7, 11, 9 as an example of CW EPR spectrum measurement.

Listing 7

Import and initialization of the necessary devices required for recording CW EPR spectra.

Listing 8

Configuration of necessary devices and other script parameters.

Listing 9

The main sequence of actions for recording CW EPR spectra.

Let us now discuss the structure of the experimental script. The first part is the import and initialization of the necessary devices and other auxiliary modules, as shown in Listing 7.

After that, all the devices should be properly configured and the remaining experimental parameters defined, such as a range of external magnetic field, arrays for storing the obtained data, etc. Devices are configured using the appropriate methods from the device classes. For the rest, standard Python code can be used. This part of the experimental script is shown in Listing 8.

Finally, we are ready to measure the spectrum and plot the result. This can be done in one or two Python loops, depending on whether multiple identical scans are required, as shown in Listing 9. Due to the user-friendly names of the methods of the device modules, the described sequence of actions is understandable to users, even if they do not have significant programming experience. The script usually ends with saving the data.

The modular design of Atomize and the use of Python code in experimental scripts provide the latter with significant flexibility and ease of modification. This applies both to changes in the sequence of actions in the script and to the replacement of one piece of equipment with another. Such a replacement requires only a change in the imported device, since all the modules for devices of the same type have the same methods. All of this can be done directly in a simple text editor, embedded into to the Atomize GUI. The script structure described above is universal and can be used to automate any type of measurement, if the necessary modules are available. More examples can be found directly in the Atomize source code. These include simple tests of device module methods, as well as more complex scripts created mainly for pulsed EPR spectroscopy. Finally, there is a detailed documentation containing descriptions of all available module methods and brief examples of their use.

Further Extension

Due to the background of the developers at the moment the range of available devices and examples of experimental scripts are mostly related to the field of magnetic resonance. Nevertheless, the software was designed and programmed for a high degree of flexibility and usability in any field of science and technology. Atomize already provides the necessary interactivity and a decent number of general-purpose functions, so the main direction of further extension of the software is the creation of modules for new devices. Special attention should be given to verify new or untested device modules directly with the equipment for which they were written. Unfortunately, programming manuals do not always accurately describe device behaviour or the available parameters of internal communication functions, which can lead to unpleasant consequences. Another important direction is the creation of an interface between Atomize and other software of similar kind, for instance pyMeasure [3]. The latter provides device modules for a significant number of instruments, so such an integration would be beneficial for Atomize, while maintaining its identity and ease of use. Finally, the already used unified set of methods for similar instruments can be further extended to device classes such as temperature controllers, lock-in amplifiers, etc. This should generalize and harmonize experimental scripts and simplify the development of device modules, since instruments of the same class often have similar procedures to be implemented.

Users and developers interested in modifying, extending or maintaining Atomize can get in contact either via the GitHub issue tracker or by email. Currently, Atomize does not have direct support mechanisms, but we are constantly working on this. We are always happy to help users individually via email or GitHub and welcome any questions, suggestions, or feedback.

Acknowledgements

We would like to acknowledge all contributors and users whose engagement and feedback keep this project evolving.

Competing Interests

The authors have no competing interests to declare.

DOI: https://doi.org/10.5334/jors.594 | Journal eISSN: 2049-9647
Language: English
Submitted on: Jul 7, 2025
Accepted on: Sep 18, 2025
Published on: Nov 7, 2025
Published by: Ubiquity Press
In partnership with: Paradigm Publishing Services
Publication frequency: 1 issue per year

© 2025 Anatoly Melnikov, Anton Vedkal, Anastasia Ishchenko, Sergey Veber, published by Ubiquity Press
This work is licensed under the Creative Commons Attribution 4.0 License.