SDK Model¶
The System Model¶
In order for the SDK to control a system, it needs to know what hardware it consists of. The SDK achieves this by constructing a system model that mirrors the hardware components. The system model is entirely modular, in the same way as the spectroradiometer system. It is the system model that coordinates the activities of the various pieces of hardware and allows almost any system, however large and complicated, to be controlled by the same set of simple, high-level functions.
The system model is built from a system configuration file. This describes the spectroradiometer in terms of what components it consists of, how the PC can communicate with them, and how they interact. System configuration files rarely need to be changed, and where possible they are pre-written and supplied with the SDK.
Example 1: Simple TM300 System¶
The following example shows a system configuration file for a simple TM300 based DC system:
#
# Demo TM300 system
#
USB_COMMS comms vid 1240, pid 5892
USB msd vid 1240, pid 5893
Amp487 dc_amp address 64
ADC487 adc address 72
FW252 fwheel drive 2
SAM exit_sam drive 1
TM300 mono use fwheel, use exit_sam
This configuration describes the following system:
1 USB_COMMS - USB electronics controller at vid 1240 and pid 5892
1 USB - USB mechanical controller at vid 1240 and pid 5893
1 Amp487 - DC amplifier at address 64 on the I2C bus in the electronics bin
1 ADC487 - ADC at address 72 on the I2C bus in the electronics bin
1 252 filter wheel controlled by drive 2 of the MSD
1 SAM controlled by drive 1 of the MSD
1 TM300 monochromator housing the previously described SAM and filter wheel
System Configuration File Format¶
The format of a system configuration file is as follows:
One component is described per line
For each line:
The first column declares the type of the component
The second column gives the component an identifier
The third column contains any parameters (e.g. address), with multiple parameters separated by commas
Anything following a ‘#’ on a line is a comment and is ignored
The system configuration file is the means by which the SDK knows what hardware is present and how it is connected to the PC. It must contain one line for each PC controlled hardware module.
Building the System Model¶
The first task when writing a system configuration is to declare how the PC communicates with any electronics in the system. These lines defining how the PC communicates must appear in the file before any other system component so the SDK knows how to communicate with the hardware in the system.
The next step is to add a line describing each hardware module in turn. A good ‘bottom-up’ approach is to start with each electronics module (e.g. amplifiers and ADC), then each mechanical/stepper motor drive controlled unit (e.g. filter wheel, SAMs, SOBs, MVSSs), and finally the monochromator.
Component Identifiers and Parameters¶
The identifier can contain any alphanumeric characters and the ‘_’ (underscore) character, but the first character must be a letter or ‘_’. Each identifier must be unique and cannot be any of the system configuration keywords (i.e. a type or parameter). The identifier is case sensitive.
In systems with more than one electronics controller, the entry for each device must specify which controller the component is connected to. This is achieved by the use parameter. Inserting the identifier of a controller as the value for the use parameter instructs the system model to operate the component via that controller.
In systems with more than one stepper motor drive (SMD), the entry for each SMD controlled component must specify which SMD the component is connected to in a similar way. When there is more than one SMD in a system and the SMD is not specified for a component, the SDK will assign a default, but it may not be the correct one.
The use parameter also allows some components (specifically filter wheels, SAMs, and MVSSs) to be attached to the monochromator. The system model needs to know what components are part of the monochromator so that it can correctly coordinate all of their operations.
The use parameter is the reason for the suggested bottom-up order of adding components to the system configuration. This is because one component cannot be used by another unless it has been declared first.
Example 2: Advanced DTM300 System¶
A more sophisticated example shows an AC system based on a DTM300 with a filter wheel, 2 SAMs and 3 MVSSs:
#-------------------------------------------------------------------
# Example system configuration file 2
#-------------------------------------------------------------------
# Specifies CEC488 controlled system
PC488 comms address 21
# Defines an MSD3 connected to COM1 rather than the IEEE bus
MSD3 mono_drive port COM1
# Defines a MAC at address 20
MAC slit_drive address 20, cards 3
# Defines a 277 pre-amplifier at address 28
Amp277 pre_amp address 28
# Defines a 225 lock-in amplifier at address 27
Amp225 ac_amp address 27
# Defines a 228A ADC at address 29
ADC228A adc address 29
# Defines 3 MVSSs, all controlled by the same MAC
MVSS entrance_slit drive 1, use slit_drive
MVSS middle_slit drive 2, use slit_drive
MVSS exit_slit drive 3, use slit_drive
# Defines a filter wheel controlled by card 3 of the MSD
FW252 fwheel card 3, use mono_drive
# Defines a SAM controlled as SAM1 on card 1 of the MSD
SAM exit1_sam card 11, use mono_drive
# Defines a SAM controlled as SAM2 on card 1 of the MSD
SAM exit2_sam card 12, use mono_drive
# Defines a DTM300 containing all of the slits, SAMs and filter wheel
# Note that long lines are OK, but cannot contain any line breaks
DTM300 mono use fwheel, use exit1_sam, use exit2_sam, use entrance_slit, use middle_slit, use exit_slit, use mono_drive
The number of component types along with all of their different parameters may seem daunting, but once set up, the system configuration file should never need altering. As the SDK functions access components via their identifiers as defined in the configuration file, the only usual reason for looking at it is to find out what these identifiers are.
Once a system configuration file has been written, it is passed to the SDK using the build_system_model function. This instructs the SDK to compile a system model from the system configuration file. The function reports its success or failure and gives the reason for any failure to compile.
Component Groups¶
Simple spectroradiometer systems contain the same basic set of components: a monochromator, a stepper motor drive, an amplifier, possibly a pre-amplifier and an ADC. Measurements are made by repeatedly selecting a wavelength and taking a reading. In this situation all of the components are used together.
More sophisticated systems are possible. For example, consider a system designed to take both AC and DC measurements, possibly during the same scan. This time measurements would be made by selecting a wavelength and taking a reading using just one of the sets of detection electronics. In this situation the system model needs to know what set of components it should be using to perform the required operation.
To allow this, the system model includes the concept of component groups. A component group is a set of components that are used together to perform operations. At any given time there is one active group; this is the component group that is used for all operations, such as selecting a wavelength or taking a measurement. A component group is a sub-set of the system model.
Building and Managing Groups¶
New component groups are added with the build_group function. This constructs a new, empty component group and returns its sequence number. The first group is group 1, the next group created is group 2, the next group 3, and so on. There can be up to 10 component groups. When the system model is built, the SDK constructs a single empty default component group (group 1).
Existing component groups can be edited by using the group_add and group_remove functions to add and remove components to and from groups. For each function the component is referred to by its identifier as set in the system configuration file and the group by its sequence number.
The function use_group sets the active group. All of the hardware operation functions (initialise, close_shutter, park, zero_calibration, select_wavelength, autorange and measurement) work with the active group. Obviously for simple systems the active group will always be the default group (group 1).
Example 3: System with AC and DC Detection¶
The following example shows a system configuration for a TM300 based system with both AC and DC detection electronics:
#-------------------------------------------------
# Example system configuration
#-------------------------------------------------
PC488 comms address 21
MAC smd address 30, cards 2
# Note DC and AC detection electronics
Amp267 dc_amp address 26
Amp277 pre_amp address 28
Amp225 ac_amp address 25
ADC228A adc address 29
# SOB to select DC or AC input to ADC
SOB adc_input drive 11
FW252 fwheel drive 2
TM300 mono use fwheel
The input to the ADC (from the 267 or 225) is selected by the SOB, which is controlled by the MAC. In order to make AC and DC measurements, two groups must be created:
One containing the monochromator, SMD, SOB, ADC, 277 and 225
One containing the monochromator, SMD, SOB, ADC and 267
This can be achieved using the following sequence of SDK function calls:
# Build first group (AC)
i = build_group()
group_add("mono", i)
group_add("smd", i)
group_add("adc_input", i)
group_add("adc", i)
group_add("pre_amp", i)
group_add("ac_amp", i)
# Build second group (DC)
i = build_group()
group_add("mono", i)
group_add("smd", i)
group_add("adc_input", i)
group_add("adc", i)
group_add("dc_amp", i)
Assuming that when the SOB is relaxed/off the ADC is reading from the 225, the following sequence of commands is a simple example of a measurement scan using both groups:
for wl in range(start_wl, stop_wl, increment):
# Measurement with group 1 (AC)
use_group(1)
set("adc_input", SOBState, 0, 0)
select_wavelength(wl, settle_time)
wait(settle_time)
autorange()
measurement(reading)
# Measurement with group 2 (DC)
use_group(2)
set("adc_input", SOBState, 0, 1)
select_wavelength(wl, settle_time)
wait(settle_time)
autorange()
measurement(reading)
Important Notes on Groups¶
The zero_calibration function needs to access the monochromator in order to correctly measure the zero offset and dark current for each state that the system will be in over the specified wavelength range. The measurement function also needs to access the monochromator in order to retrieve the zero calibration values for the current wavelength. This means that if measurements performed using a group are to be zero calibrated, the group must include the monochromator.
While the SDK will not create default component groups, save_setup records which components are in which groups in the system attributes file and load_setup deletes any existing component groups and builds new ones from the information in the system attribute file.
System Attributes Files (.atr)¶
In addition to system configuration files (.cfg) that define the hardware structure, the SDK uses system attributes files (.atr) to store the current state and settings of all components in the system. These files work together with the load_setup and save_setup functions to allow complete system configurations to be saved and restored.
What are .atr Files?¶
System attributes files (.atr) are text-based files that store the runtime attributes of all components in the system model. Unlike .cfg files which define what hardware exists, .atr files contain the current settings, calibration values, and state information for each component.
Common uses for .atr files include:
Saving instrument calibration data (e.g., grating constants, wavelength calibration)
Storing component settings (e.g., amplifier gains, slit widths, filter positions)
Recording component group configurations
Preserving system state between measurement sessions
File Format and Syntax¶
System attributes files follow a structured text format:
Each component’s attributes are grouped in a component block
Component blocks start with the component identifier (as defined in the .cfg file)
Attributes are listed as
attribute name = valuepairsComponent blocks end with the
endkeywordComments start with
#and continue to the end of the lineValues can be integers, floating-point numbers, or text strings
Example .atr File Structure¶
#------------------------------------------------------------------------------
# Bentham Instruments system model attributes file
# Created 14/11/2025 11:03:18
# This file should NOT be edited by hand
#------------------------------------------------------------------------------
mono
cos alpha = 9.72700000000000E-0001
ZordSwitch SAM for turret,1 = -1
end
monoTurret 1
grating,1 = 1200
minimum wavelength,1 = 200
maximum wavelength,1 = 300
zord,1,1 = 47663
alpha,1,1 = 9.99600000000000E-0001
high current threshold = 0
move speed = 9
end
fwheel
settle time = 500
filter,1 = 0.00000000000000E+0000
filter,2 = 4.00000000000000E+0002
end
~System
dispersion multiplier = 1.500
group = ,acamp,,,acadc,,,,,,mono,
end
Attribute Names and Values¶
Attribute names within a component block can contain:
Alphanumeric characters and spaces
Commas to indicate indexed attributes (e.g.,
grating,1,filter,2)Multiple comma-separated indices for multi-dimensional attributes (e.g.,
zord,1,1)
Values are stored as:
Integer numbers (e.g.,
1200,-1)Floating-point numbers (e.g.,
0.9727or9.72700000000000E-0001)Text strings (typically for labels or names)
The ~System block at the end contains global system settings and component group information.
Using save_setup and load_setup¶
The save_setup Function¶
The save_setup function writes the current state of all components to a .atr file:
# Python example
hw.save_setup("my_system_state.atr")
When save_setup is called, the SDK:
Queries all components in the system model for their current attribute values
Writes these values to the specified .atr file in the proper format
Includes component group membership information in the
~SystemblockAdds a timestamp header to the file
The load_setup Function¶
The load_setup function restores system state from a .atr file:
# Python example
hw.load_setup("my_system_state.atr")
When load_setup is called, the SDK:
Reads the .atr file and parses the component blocks
Applies each attribute value to the corresponding component in the system model
Rebuilds component groups according to the group information in the
~SystemblockValidates that all referenced components exist in the current system model
Important Notes on .atr Files¶
.atr files are system-specific and may not work correctly if loaded on a different hardware configuration
The component identifiers in the .atr file must match those in the system’s .cfg file
load_setup will fail if the .atr file references components that don’t exist in the current system model
Always call
build_system_modelwith a .cfg file before callingload_setupwith a .atr fileSome components may have read-only attributes that are not saved/loaded
Typical Workflow¶
A typical workflow using configuration and attributes files:
# 1. Build the system model from the configuration file
hw.build_system_model("system.cfg")
# 2. Initialize the hardware
hw.initialise()
# 3. Load previously saved settings and calibration
hw.load_setup("calibrated_system.atr")
# 4. Perform measurements
hw.select_wavelength(500.0, 1000)
reading = hw.measurement()
# 5. Save current settings for next time
hw.save_setup("current_state.atr")