.. |MLA (TM)| unicode:: MLA U+2122 .. |copy| unicode:: U+000A9 .. COPYRIGHT SIGN .. index:: MLA programming .. _mla-programming-label: MLA programming =============== The |MLA (TM)| comes with a Python software interface consisting of two main parts: * :ref:`mla-api-label` (Application Programming Interface) is a software library for accessing the |MLA (TM)| hardware, set up and control of measurements with the |MLA (TM)|, and reading out the measurement data from the |MLA (TM)|. * :ref:`mla-gui-label` (Graphical User Interface) is a versatile interface for setting up and performing many different types of measurements with the MLA, plotting the results, and saving the data to the computer for further analysis. Thanks to Python's interactive environment it is possible to use the MLA API directly from the Python command line. Command line statements can be bunched together into scripts for automated set up and measurement. Such scripts could then be run stand-alone, integrated into other software, or run from the script panel built in to the MLA GUI. The same API is used in all cases and it serves as the foundation for full-featured interactive graphical applications, such as the MLA GUI. The MLA GUI can be used entirely without programming, but many tasks are still best performed by scripting. Therefore, a `Python shell panel` for running single Python commands, and a `Script panel` for writing and executing Python scripts, is available inside the MLA GUI. The combination of a GUI and programming capability in the same application can be very practical in many situations. For example, you can use the `Oscilloscope panel` and the `Lockin plot panel` for debugging your measurement setup. When all looks fine, you can start your script which performs the measurement, data analysis and plotting. The MLA GUI includes a rich set of built-in scripts that can be used as templates for your custom scripts. There are many options for programing the |MLA (TM)|, but no matter which option you choose, you use the **same** :ref:`mla-api-label`, so that all |MLA (TM)| commands look exactly the same. You can test your commands in the `Python shell panel` and the move them over to the `Script panel`. When you are building a larger a stand-alone measurement script, you use the `Script panel` in the MLA-GUI to test and debug pieces of code, and then paste the code into your stand-alone script. .. index:: numpy, matplotlib .. _numpy-and-matplotlib-label: NumPy and matplotlib ++++++++++++++++++++ The MLA software uses the open-source libraries `NumPy `_ for array math and `matplotlib `_ for plotting. Together, NumPy and matplotlib provide an experience much similar to the well-known MATLAB |copy| software. Both `NumPy `_ and `matplotlib `_ are well documented on their respective web pages. In particular the `matplotlib gallery `_ is very useful. If you are familiar with MATLAB |copy|, a quick way to get started would be to read `NumPy for MATLAB users `_ . In the code samples of this user manual, and in the built-in scripts that are provided with the MLA software, we use the convention that all NumPy commands start with :code:`np.`, as in :code:`y = np.sin(x)` because we :code:`import numpy as np`. Similarly, matplotlib commands can start with :code:`plt.` as in :code:`plt.plot(x,y)` because we :code:`import matplotlib.pyplot as plt`. But with matplotlib we often generate new objects, and work with their member functions, as in the sequence: .. code :: import numpy as np import matplotlib.pyplot as plt x = np.linspace(0,2*np.pi) y = np.cos(x) fig = plt.figure() ax1 = fig.add_subplot(2,1,1) ax1.plot(x,y) plt.draw() plt.show() When running integrated MLA scripts :code:`matplotlib.pyplot` sometimes uses a conflicting GUI back-end, resulting in the rest of the MLA GUI freezing while the figure is displayed. To avoid this problem, plotting can instead be done inside the MLA GUI, from the `Script plot panel` or `Pyhton shell panel`, using the :code:`scriptplot` object, as demonstrated in the example below. .. code :: x = np.linspace(0,2*np.pi) y = np.cos(x) fig = scriptplot.fig ax1 = fig.add_subplot(2,1,1) ax1.plot(x,y) wx.CallAfter(scriptplot.my_draw) For more details on script plotting inside the GUI, see :ref:`plotting-in-gui-label`. .. index:: Application Programming Interface (API), API .. _mla-api-label: MLA API +++++++ The Application Programming Interface (API) for the MLA is the main object which we always instantiate with the name :code:`mla` in Python code. This API object is a container with five basic singleton objects. .. graphviz:: graph { #rankdir=LR; mla -- lockin; mla -- osc; mla -- arb; mla -- feedback; mla -- hardware; } Complete documentation of all the member functions of each class is found under the links below. .. toctree:: :maxdepth: 0 mla_api .. index:: programming the MLA GUI, GUI programming .. _mla-gui-label: MLA GUI +++++++ The Graphical User Interface (GUI) for the MLA has a `Python shell panel` and a `Script panel` from which you can execute all commands in the :ref:`mla-api-label`. But it is also possible to control the MLA GUI itself from a Python script. For example, you can program the GUI to: * Set which panels should be visible, and their size and position * Control GUI objects such as text fields and check boxes * Configure the plots The MLA GUI is controlled through it's hierarchy of objects. At the top level there is the main controller, called `main`. There is also `mla_globals`, which is a container for global variables, and the `mla` object itself. Only a selected subset of the full MLA GUI programming interface is documented under the links below. If you need to access a function that is not documented here, please contact Intermodulation Products. .. toctree:: :maxdepth: 1 mla_gui .. index:: example scripts .. _example-scripts-label: example scripts +++++++++++++++ Here follows some examples scripts which can be run from the :ref:`script-panel-label` in the MLA GUI. They serve as starting points for designing your own measurement scripts. These examples are available in the **settings/mla_scripts/built-in** folder in the :ref:`user-folder-label`. In every script the MLA API is instantiated as the Python object called :code:`mla` and all commands are accessed in the code with the form :code:`mla.comand`. All commands used in these scripts are documented in detail in :ref:`mla-api-label` .. index:: configuring the GUI , example script setup the GUI ------------- Panels can automatically be displayed or hidden using scripts. Most panels are accessed through the `main.` object. A script can obtain its own filename with `__scriptfile__`. .. literalinclude:: ../scripts/example_setup_gui.py .. index:: plotting in the GUI, example script .. _plotting-in-gui-label: plotting in the GUI ------------------- Plotting uses matplotlib and the script plot panel. A pre-existing Figure object is first obtained from `scriptplot.fig` after which regular matplotlib syntax is used. To draw the figure on the screen the function `scriptplot.draw` has to be called. As wxPython only allows the main thread to perform to access the GUI this command has to be queued in the main loop using `wx.CallAfter`. Failure to do so can lead to unstable behavior and crashing of the software. .. literalinclude:: ../scripts/example_plot.py .. index:: lockin setup, example script configuring the lockin ---------------------- This script demonstrates configuring the lockin using explicit lists. Python lists as well as numpy arrays can be used as an argument when setting properties such as frequency, amplitude and phase. If the length of the argument is less than the number of available tones (i.e. :func:`mla.lockin.nr_output_freq`) that property will be set to zero for the remaining, unspecified, tones. .. literalinclude:: ../scripts/example_setup_lockin.py .. index:: lockin measurement loop, example script .. _lockin-measurement-loop-label: lockin measurement loop ----------------------- This example takes a lockin measurement and displays the amplitudes in a continuously updating figure. The measurement is running an infinite loop which is broken by changing the Boolean `scriptpanel.is_running`. The value of this variable will change when the user clicks the Run/Stop button in the Script panel. The Boolean `scriptplot.is_drawing` is automatically set to False when `scriptplot.draw` finishes. If a previous plot was not finished, plotting is skipped to ensure that the GUI remains responsive and the computer is not overloaded with plot requests. To speed up plotting the command `ax.plot` should be avoided in the loop as this command redraws all axes and ticks etc. Rather, update only the data in an existing matplotlib `line`. .. literalinclude:: ../scripts/example_measurement.py frequency sweep --------------- He we demonstrate changing a parameter in a measurement loop. The lockin frequency is stepped through an array `f_hz` of specified values. After tuning, each value of the bandwidth is set using the command `mla.lockin.set_df(df, wait_for_effect=False)`, followed by the command `mla.lockin.set_frequencies(f, wait_for_effect=True)`. Python does not have to wait for the MLA to reply before it goes on to the second configuration command. However, Python should wait after the last configuration command (i.e. `wait_for_effect=True`) before it goes on to get new data from the MLA. This speeds up configuration, while ensuring that the configuration is actually in effect when the measurement data is collected. Note that the lockin is started with the command `mla.lockin.start_lockin(cluster_size=1)`, specifying that only one lockin data packet is sent with each Ethernet package. This speeds up the loop by reducing the latency between the end of measurement and transfer to the computer. The feature is useful when we are interested in fast update after only one lockin measurement. However, a small cluster size will reduce the total bandwidth when a data stream of many lockin measurements is desired. This example demonstrates stepping any lockin parameters. A frequency sweep is most easily done in the :ref:`mla-gui-label` using the :ref:`frequency-sweep-panel-label`. In your own scripts, use the function :func:`lockin.Lockin.frequency_sweep`, which is optimized for speed, and has the option for multifrequency sweeping is available. .. literalinclude:: ../scripts/example_frequency_sweep.py .. index:: stand-alone scripts .. _stand-alone-scripts-label: stand-alone scripts +++++++++++++++++++ Scripts do not have to be run from the :ref:`script-panel-label`. A stand-alone python script is demonstrated in the example below. The script configures the lockin to make a frequency comb, outputs the comb, measures the comb as a time stream, and plots the measured data in both the time and frequency domain in a figure which is displayed below. Connect **OUT 1+** to **IN 1+** on the MLA before running this script. .. literalinclude:: mla_api_demo.py .. figure:: figures/mla_api_demo.png