Understanding the YAML files¶
The Pharos controller needs YAML files to configure some basic parameters. The YAML files are not just a whim, they make very explicit the different variables available to someone programming and therefore be used as a quick reference.
They also make possible quick changes in some default values, for example if a new photodiode is connected to the NI card, the laser changes from a GPIB connection to an USB connection, etc. Understanding the layout of these files is important but bear in mind that they are always read by a python program, that you are free to modify at your own discretion.
Devices.yml¶
The Pharos Controller was built upon an outdated idea of how to define devices. Basically everything in a setup is a device. The main difference is that some devices are connected to other instead of to a computer. Therefore, the program uses only one devices.yml file.
A general device such as a laser can be defined like this:
TSL-710:
type: scan laser
name: Santec Laser
driver: controller.santec.tsl710/tsl710
connection:
type: GPIB
port: 1
defaults: config/devices_defaults.yml
Remember that per-se, yaml files do not do anything. They have to be interpreted later by python code. The main key, TSL-710 identifies the device and has to be unique, however is not use in downstream code. What is used is the name, that also hase to be unique (and can be the same as the main key). The driver specifies which Python module has to be used to communicate with the device. That particular line would translate to Python code like this:
from controller.santec.tsl710 import tsl710
Todo
The code should rely on models that have standardized behavior, more than directly on drivers.
The connection block will be interpreted later on, and will be fed to the driver to make a connection. Knowing the type of communication the device has (GPIB, USB, Serial, etc.) and the port to which it is connected, is a responsibility of the user.
A daq card, such as an NI card can be defined as follows:
NI-DAQ:
name: NI-DAQ
type: daq
model: ni
number: 2
driver: pharos.model.daq.ni/ni
connection:
type: daq
port: 2
trigger: external
trigger_source: PFI0
Again, the name is the important parameter here. Moreover the last block specifies the kind of trigger we want to use for the DAQ.
Todo
Specifying the trigger when defining the DAQ is not a good idea, since in the same experiment there can be different needs. Monitoring a signal while aligning can be done without an external trigger. Being that the case, it would have made the code much more reusable if the trigger is defined elsewhere.
A photodiode connected to the ADQ can be defined like so:
PhotoDiode2:
name: Photodiode 2
port: 2
type: analog
mode: input
description: Forward Intensity
calibration:
units: V
slope: 1
offset: 0
limits:
min: -2.5
max: 2.5
connection:
type: daq
device: NI-DAQ
Everything is more or less self explanatory. The calibration refers to how to convert from Volts to the units of the device. For example a piezo stage receives voltage, but it is transduced into distance. A thermocouple outputs voltage, but has a meaning of temperature, etc. The units here can be anything interpreted by the Pint module. The limits are the limits in the units given by the calibration. Limits are mandatory when dealing with NI cards, since it automatically chooses the best gain to optimize the digitalization range.
Lastly, the connection block explicitly states to which device it is connected.
Warning
This structure is cumbersome and was already superseded in the Experimentor program. If you are going to develop something new, I strongly suggest that you check that other program.
Measurement.yml¶
The measurement.yml file defines the basic structure of an experiment. It defines what parameters are needed, what detectors are recorded, etc. Whatever you add in here will be later available in the experiment class. Each main key of the file should be different steps of your experiment. For example:
init:
devices: 'config/devices.yml'
When initializing, the only important thing is to know where the file with the definition of the devices is. In the initialization step, we can use the information used in the property devices to initialize the appropriate drivers, etc.
Once we have our devices configured, we would like to do a scan. We call this a monitor, because in principle the scan can be repeating itself over and over:
monitor:
laser:
name: Santec Laser
params:
start_wavelength: 1491 nm
stop_wavelength: 1510 nm
wavelength_speed: 10 nm/s
interval_trigger: 0.01 nm
sweep_mode: ContOne
wavelength_sweeps: 1
detectors:
- Photodiode Test
- Photodiode 2
You see now that we define the laser we want to scan (in case there is more than one), and we refer to it by its name. We define some parameters and some detectors.
Note
Because of how the parser of the YAML file works, params is going to be a dictionary, while detectors is going to be a list.
If we want to fancy things up a bit, for example with 2-D scans instead of just 1D, we have to define which axis are we scanning. This axis should be another device and should have a range. If the device is not connected to a DAQ, we should also specify which property we would like to scan. We can do it like so:
scan:
laser:
name: Santec Laser
params:
start_wavelength: 1492 nm
stop_wavelength: 1548 nm
wavelength_speed: 50 nm/s
interval_trigger: 0.01 nm
sweep_mode: ContOne
wavelength_sweeps: 1
axis:
device:
name: Rotation 1
range: [35deg, 55deg, 1deg]
property: position
detectors:
- Photodiode Test
- Photodiode 2
Imagine now that later on, you decide you need to have a shutter controlling a secondary laser. And you need that shutter to be closed after a scan, and to have a small delay before a new line scan starts. At least in what the configuration needs, you should only add these three lines:
shutter:
port: PFI2
delay: 100ms
And of course we should also include what to do once the experiment is over. For example we want to close the shutter of the laser, but not switch it off:
finish:
TSL-10:
shutter: False