.. _highlevel: Devices (High-level interface) ============================== What is a Device? ----------------- The high-level interface of Autolab is an abstraction layer of its low-level interface, which allows easy and safe communication with laboratory instruments without knowing the structure of their associated **Driver**. In this approach, an instrument is fully described with a hierarchy of three particular **Elements**: the **Modules**, the **Variables** and the **Actions**. * A **Module** is an **Element** that consists in a group of **Variables**, **Actions**, and sub-**Modules**. The top-level **Module** of an instrument is called a **Device**. * A **Variable** is an **Element** that refers to a physical quantity, whose value can be either set and/or read from an instrument (wavelength of an optical source, position of a linear stage, optical power measured with a power meter, spectrum measured with a spectrometer...). Depending on the nature of the physical quantity, it may have a unit. * An **Action** is an **Element** that refers to a particular operation that can be performed by an instrument. (homing of a linear stage, zeroing of a power meter, acquisition of a spectrum with a spectrometer, etc.). An **Action** may have a parameter. The **Device** of a simple instrument is usually represented by only one **Module**, and a few **Variables** and **Actions** attached to it. .. code-block:: python -- Tunics (Module/Device) |-- Wavelength (Variable) |-- Output state (Variable) Some instruments are a bit more complex, in the sense that they can host several different modules. Their representation in this interface generally consists of one top level **Module** (the frame) and several others sub-**Modules** containing the **Variables** and **Actions** of each associated module. .. code-block:: python -- XPS Controller (Module/Device) |-- ND Filter (Module) |-- Angle (Variable) |-- Transmission (Variable) |-- Homing (Action) |-- Linear stage (Module) |-- Position (Variable) |-- Homing (Action) This hierarchy of **Elements** is implemented for each instrument in its driver files, and is thus ready to use. Load and close a Device ----------------------- The procedure to load a **Device** is almost the same as for the **Driver**, but with the ``get_device`` function. You need to provide the nickname of a driver defined in the ``devices_config.ini`` (see :ref:`localconfig`). .. code-block:: python >>> lightSource = autolab.get_device('my_tunics') .. note:: You can temporarily overwrite some of the parameters values of a configuration by simply providing them as keywords arguments in the ``get_device`` function: .. code-block:: python >>> laserSource = autolab.get_device('my_tunics', address='GPIB::9::INSTR') To properly close the connection to the instrument, simply call the ``close`` function of the **Device**. This object will no longer be usable. .. code-block:: python >>> lightSource.close() To close the connection to all instruments (devices, not drivers) at once, you can use Autolab's ``close`` function. .. code-block:: python >>> autolab.close() Navigation and help in a Device ------------------------------- Navigation in the hierarchy of **Elements** of a given **Device** is based on relative attributes. For instance, to access the **Variable** ``wavelength`` of the **Module** (**Device**) ``my_tunics``, simply execute the following command: .. code-block:: python >>> lightSource.wavelength In the case of a more complex **Device**, for instance a power meter named ``my_power_meter`` that has several channels, you can access the **Variable** ``power`` of the first channel ``channel1`` with the following command: .. code-block:: python >>> powerMeter = autolab.get_device('my_power_meter') >>> powerMeter.channel1.power Every **Element** in Autolab is provided with a ``help`` function that can be called to obtain some information about it, but also to know which further **Elements** can be accessed through it, in the case of a **Module**. For a **Variable**, it will display its read and/or write functions (from the driver), its Python type, and its unit if provided in the driver. For an **Action**, il will display the associated function in the driver, and its parameter (Python type and unit) if it has one. You can also ``print()`` the object to display this help. .. code-block:: python >>> lightSource.help() >>> print(lightSource.wavelength) >>> powerMeter.help() >>> print(powerMeter.channel1) >>> powerMeter.channel1.power.help() Use a Variable -------------- If a **Variable** is readable (read function provided in the driver), its current value can be read by calling its attribute: .. code-block:: python >>> lightSource.wavelength() 1550.55 >>> lightSource.output() False If a **Variable** is writable (write function provided in the driver), its current value can be set by calling its attribute with the desired value: .. code-block:: python >>> lightSource.wavelength(1549) >>> lightSource.output(True) To save the value of a readable **Variable** locally, use its `save` function with the path of the desired output directory (default filename), or file: .. code-block:: python >>> lightSource.wavelength.save('.\mesures\') >>> lightSource.wavelength.save('.\mesures\power.txt') Use an Action ------------- You can execute an **Action** simply by calling its attribute: .. code-block:: python >>> linearStage = autolab.get_device('my_linear_stage') >>> linearStage.goHome() Script example -------------- With all these commands, you can now create your own Python script. Here is an example of a script that sweeps the wavelength of a light source, and measures the power of a power meter: .. code-block:: python # Import the package import autolab import pandas as pd # Open the Devices myTunics = autolab.get_device('my_tunics') myPowerMeter = autolab.get_device('my_power_meter') # Turn on the light source myTunics.output(True) # Sweep its wavelength and measure a power with a power meter df = pd.DataFrame() step = 0.01 start = 1550 stop = 1560 points = int(1 + (stop - start)/step) for wl in np.linspace(start, stop, points): # Set the parameter myTunics.wavelength(wl) # Measures the values wl_measured = myTunics.wavelength() power = myPowerMeter.line1.power() # Store the values in a list df = df.append({'wl_measured': wl_measured, 'power': power}, ignore_index=True) # Turn off the light source myTunics.output(False) # Close the Devices myTunics.close() myPowerMeter.close() # Or use autolab.close() # Save data df.to_csv('data.csv')