<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Julia Community 🟣: César Bertoni</title>
    <description>The latest articles on Julia Community 🟣 by César Bertoni (@ceboc).</description>
    <link>https://forem.julialang.org/ceboc</link>
    <image>
      <url>https://forem.julialang.org/images/54OMFkTpNWICNd6GeC-PFrV4mjASNFmXpjYGzE1KbQQ/rs:fill:90:90/g:sm/mb:500000/ar:1/aHR0cHM6Ly9mb3Jl/bS5qdWxpYWxhbmcu/b3JnL3JlbW90ZWlt/YWdlcy91cGxvYWRz/L3VzZXIvcHJvZmls/ZV9pbWFnZS8xNzY5/L2EyYjA4Y2IxLTI5/NGYtNDI0Zi04YzVl/LTgyYWY4ODlmMzZh/Yy5wbmc</url>
      <title>Julia Community 🟣: César Bertoni</title>
      <link>https://forem.julialang.org/ceboc</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.julialang.org/feed/ceboc"/>
    <language>en</language>
    <item>
      <title>Experiments automation with Julia</title>
      <dc:creator>César Bertoni</dc:creator>
      <pubDate>Thu, 25 Jan 2024 23:38:47 +0000</pubDate>
      <link>https://forem.julialang.org/ceboc/experiments-automation-with-julia-40fc</link>
      <guid>https://forem.julialang.org/ceboc/experiments-automation-with-julia-40fc</guid>
      <description>&lt;p&gt;In this post I will give a short introduction on how to automate data acquisition in your experiments using Julia. I will show how &lt;a href="https://github.com/JuliaPy/PyCall.jl"&gt;PyCall&lt;/a&gt;, &lt;a href="https://docs.makie.org/stable/"&gt;Makie&lt;/a&gt; and &lt;a href="https://github.com/JuliaIO/JLD2.jl"&gt;JLD2&lt;/a&gt; can be used for these tasks. &lt;/p&gt;




&lt;h2&gt;
  
  
  Table Of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Why?&lt;/li&gt;
&lt;li&gt;VISA installation&lt;/li&gt;
&lt;li&gt;PyVISA in Julia&lt;/li&gt;
&lt;li&gt;PyLabLib in Julia&lt;/li&gt;
&lt;li&gt;A tiny experiment&lt;/li&gt;
&lt;li&gt;Saving data and metadata&lt;/li&gt;
&lt;li&gt;Conclusions&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why? &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The solution to the two-language problem is something we can take more or less seriously, and try to use Julia for everything humanly possible, or use C or Python with Julia as an intermediary and forget it exists. However, the programmer's need and reasonable judgment must be present to use the right tools for the right tasks. Just as we don't use tweezers to eat a piece of beef, we don't use C++ to write an email from scratch.&lt;sup id="fnref1"&gt;1&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;In particular, "the" industry standard for data acquisition system automation and control and test hardware standard is LabVIEW. A software that allows the creation of user interfaces and communication between devices at a very complex level, using a graphical programming paradigm. However, I must point out that: being a proprietary software, we do not know what it does underneath, the licensing terms make it necessary to pay ridiculous amounts of money for tasks that may be simple. And although in principle it is presented as a simple programming paradigm, the code can easily turn into spaghetti, and not figuratively.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://forem.julialang.org/images/VHXJYyjkdNTaV_hD38ibeg4XNv0WN968rfNJn5j4_QQ/rt:fit/w:800/g:sm/q:0/mb:500000/ar:1/aHR0cHM6Ly9mb3Jl/bS5qdWxpYWxhbmcu/b3JnL3JlbW90ZWlt/YWdlcy91cGxvYWRz/L2FydGljbGVzL3Rn/aWdzM3J3cDU0bXFt/emtmaThqLnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://forem.julialang.org/images/VHXJYyjkdNTaV_hD38ibeg4XNv0WN968rfNJn5j4_QQ/rt:fit/w:800/g:sm/q:0/mb:500000/ar:1/aHR0cHM6Ly9mb3Jl/bS5qdWxpYWxhbmcu/b3JnL3JlbW90ZWlt/YWdlcy91cGxvYWRz/L2FydGljbGVzL3Rn/aWdzM3J3cDU0bXFt/emtmaThqLnBuZw" alt="Bunch of LabVIEW code." width="800" height="430"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Example of a LabVIEW code. This code is intended to control a tunable laser and an Optical Spectrum Analyzer together. As seen, there are many cables, so track the information flux is not always easy.&lt;/em&gt;&lt;sup id="fnref2"&gt;2&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Some additional problems I encountered when programming experiment automation in LabVIEW were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The lack of version control.&lt;/li&gt;
&lt;li&gt;The software tends to get slow as data arrays get larger, more instruments are connected, or three-dimensional data is plotted for monitoring.&lt;/li&gt;
&lt;li&gt;An absurdly heavy installation.&lt;/li&gt;
&lt;li&gt;A large number of bugs and crashes that are not documented or whose solutions and causes are not clear, even to advanced users in the community forums.&lt;/li&gt;
&lt;li&gt;Broken connections when using the "self-cleaning" tool or simply by saving the .vi file.&lt;/li&gt;
&lt;li&gt;While each function can be programmed in a box, they have such small connections that it is not always easy to connect them. It doesn't help that the software has no close-ups.&lt;sup id="fnref3"&gt;3&lt;/sup&gt;
&lt;/li&gt;
&lt;li&gt;The program can quickly turn into a ridiculous amount of embedded .vi's, making it easy to have 10 or more windows open during development. &lt;/li&gt;
&lt;li&gt;Poor support for anything other but Windows.&lt;/li&gt;
&lt;li&gt;Arrays! What a pain to declare and use matrices in LabVIEW. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We cannot entirely blame the software, it is a valid solution, so much so that it is a standard. And maybe such insolvencies could be part of a misuse by the user. Personally, however, I don't advocate this position very much.&lt;/p&gt;

&lt;p&gt;Instead, it helps that many lab equipment manufacturers liberalize the use of their SDKs and drivers to be used with C, C++, or Python, through (at best) the &lt;a href="https://www.ivifoundation.org/specifications/default.html#visa-specifications"&gt;VISA&lt;/a&gt; protocol via &lt;a href="https://www.ivifoundation.org/specifications/default.html#standard-commands-for-programmable-instruments-scpi"&gt;SCPI&lt;/a&gt; commands and a good base of programming examples, or (at worst) some dll library (whose documentation quality may vary), and typically without Linux support.&lt;sup id="fnref4"&gt;4&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;So what does this have to do with Julia? Unfortunately, I have not found a comprehensive discussion of how to use Julia for experiment automation, despite the language's great potential for this purpose:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Speed, simplicity and clarity.&lt;/li&gt;
&lt;li&gt;Easy handling of matrices and data storage.&lt;/li&gt;
&lt;li&gt;Access to several graphing libraries.&lt;/li&gt;
&lt;li&gt;Access to other programming languages (C, R, Python).&lt;/li&gt;
&lt;li&gt;Compatibility with a version control system (git).&lt;/li&gt;
&lt;li&gt;Synchronous and asynchronous programming access.&lt;/li&gt;
&lt;li&gt;Access to multithreaded and GPU programming.&lt;/li&gt;
&lt;li&gt;Access to programming environments.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This lack of resources means that there is no documentation on how to accomplish these tasks in Julia,&lt;sup id="fnref5"&gt;5&lt;/sup&gt; and essentially no packages exist natively in this language.&lt;sup id="fnref6"&gt;6&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;The purpose of this document is therefore to give a small introduction to how to automate experiments in Julia using existing Python solutions such as &lt;a href="https://pylablib.readthedocs.io/en/latest/"&gt;PyLabLib&lt;/a&gt; or &lt;a href="https://pyvisa.readthedocs.io/en/latest/"&gt;PyVISA&lt;/a&gt;.&lt;sup id="fnref7"&gt;7&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;As a Julia user who does not consider himself to be particularly good at programming, and who does not have too much time to reinvent the wheel,&lt;sup id="fnref8"&gt;8&lt;/sup&gt; or to delve into the world of interfaces and communication protocols, I believe that this small manual can be useful, especially for master's and PhD students who are in a hurry to automate their experiments, but whose main programming language is Julia (yes, we exist).&lt;/p&gt;


&lt;h2&gt;
  
  
  VISA installation &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;As a prerequisite, the necessary libraries must be installed. There are two main distributions, National Instruments (&lt;a href="https://www.ni.com/en/support/downloads/drivers/download.ni-visa.html#521671"&gt;NI-VISA&lt;/a&gt;), which is the most widely used, and &lt;a href="https://www.keysight.com/us/en/lib/software-detail/computer-software/io-libraries-suite-downloads-2175637.html"&gt;Keysight IO Library Suites&lt;/a&gt;. Both support Linux and Windows, but the former is the most widely used and adds macOS X support. Installation instructions are described in the respective links.  &lt;/p&gt;

&lt;p&gt;There is also &lt;a href="https://pyvisa.readthedocs.io/projects/pyvisa-py/en/latest/"&gt;PyVISA-py&lt;/a&gt;, which covers a subset of the VISA standard functionality, and it appears that it does not support all protocols on all bus systems.&lt;sup id="fnref9"&gt;9&lt;/sup&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  PyVISA in Julia &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;As I mentioned before, we will use Python packages in Julia, this because the native packages of Julia (&lt;a href="https://github.com/PainterQubits/VISA.jl"&gt;VISA.jl&lt;/a&gt; and &lt;a href="https://github.com/BBN-Q/Instruments.jl"&gt;Instruments.jl&lt;/a&gt;) seem to be abandoned. We will install &lt;a href="https://github.com/JuliaPy/PyCall.jl"&gt;PyCall&lt;/a&gt; to access Python, for this we will enter a terminal with Julia to the package manager with the &lt;code&gt;"["&lt;/code&gt; key and execute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="n"&gt;Pkg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="n"&gt;PyCall&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We return to the programming environment by pressing the backspace key when the installation is complete. We will now install &lt;a href="https://pyvisa.readthedocs.io/en/latest/"&gt;PyVISA&lt;/a&gt; using the following commands:&lt;sup id="fnref10"&gt;10&lt;/sup&gt;&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;PyCall&lt;/span&gt;
&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`$(PyCall.python) -m pip install -U pyvisa`&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we want to use &lt;a href="https://pyvisa.readthedocs.io/projects/pyvisa-py/en/latest/"&gt;pyvisa-py&lt;/a&gt; in addition, we can install this library thought this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`$(PyCall.python) -m pip install -U pyvisa-py`&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's open a VISA session and list the available devices&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="c"&gt;# py-visa import&lt;/span&gt;
&lt;span class="n"&gt;visa&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pyimport&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"pyvisa"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Now, we open a resource manager. If we give "@py" as argument, we would indicate that we want to use pyvisa-py as the VISA interface.&lt;/span&gt;
&lt;span class="n"&gt;rm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;visa&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResourceManager&lt;/span&gt;&lt;span class="x"&gt;()&lt;/span&gt;

&lt;span class="c"&gt;# We list the resources&lt;/span&gt;
&lt;span class="n"&gt;list_resources&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rm_list_resoruces&lt;/span&gt;&lt;span class="x"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This last lane of code will have some output like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;list_resources&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RM&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;list_resources&lt;/span&gt;&lt;span class="x"&gt;()&lt;/span&gt;
&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"USB0::0x0957::0x1798::MYXXXXXXXX::INSTR"&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"TCPIP0::OSA-MIUP3TTVFTZ::inst0::INSTR"&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"TCPIP0::192.168.1.120::inst0::INSTR"&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"TCPIP0::192.168.1.122::inst0::INSTR"&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ASRL1::INSTR"&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ASRL7::INSTR"&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ASRL18::INSTR"&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"USB0::0x1313::0x8072::1911409::0::INSTR"&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"USB0::0x1313::0x8078::P0011224::0::INSTR"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These elements are the identification strings of each device connected or visible to the computer. Here we see two devices available on the network via TCPIP and one USB device. We will connect to the USB device and ask it who it is.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="c"&gt;# We open a VISA session for this device&lt;/span&gt;
&lt;span class="n"&gt;OSC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open_resource&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"USB0::0x0957::0x1798::MYXXXXXXXX::INSTR"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have three functions at our disposal, &lt;code&gt;write&lt;/code&gt; to write instructions to the buffer, &lt;code&gt;read&lt;/code&gt; to read the values and responses stored in the buffer, and &lt;code&gt;query&lt;/code&gt;, which writes an instruction and then reads the response from the computer (steps 3 and 4). There are more details about this last command that we will see later. Let's ask him who he is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;OSC&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"*IDN?"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
&lt;span class="s"&gt;"AGILENT TECHNOLOGIES,DSO-X 2014A,MYXXXXXXXX,02.65.2021030741&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the string in the argument contains the &lt;code&gt;*IDN?&lt;/code&gt; command. This is one of the mandatory commands of the SCIPI standard, and any device that supports VISA must be able to respond to it by returning an identification string. In our case, we see that the device responded with its manufacturer name, model, serial number, and firmware version. The response may vary depending on the manufacturer and the device, but it must provide the necessary information to identify the device; the details of the response string must be included in the user (or programmer) manual. &lt;/p&gt;

&lt;p&gt;Let's proceed to acquire and plot the data. To do this, let's define the following function to reset the acquisition parameters and apply an autoscale.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="nf"&gt; OSC_inic&lt;/span&gt;&lt;span class="x"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;OSC&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"*RST"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;OSC&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":AUTOSCALE"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;OSC&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"TIMebase:Scale 2.0E-3"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;OSC&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"CHANNEL2:DISPLAY 1"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;OSC&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"CHANNEL2:SCALE 100 mV"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;OSC&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"CHANNEL1:OFFSet 0 V"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;OSC&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"CHANNEL1:OFFSet 370 mV"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we run the function, we get the next behavior&lt;sup id="fnref11"&gt;11&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/qjZGTzG4Px8"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;As a note, the addition of timeouts in the code (using the &lt;code&gt;sleep&lt;/code&gt; function) is to allow time for the device to respond. Sometimes instructions may not be written or executed correctly if these timeouts are omitted. The amount of time we need to pause between one instruction and another depends on the device we are using. Sometimes adding such timeouts is unnecessary.&lt;/p&gt;

&lt;p&gt;Now that we have the oscilloscope configured, we will proceed to collect the measured data on the screen. To do this, we need to know that the basic operation we will be performing is a query. We know that the device will return a series of numbers, but these may differ in format, as they can be a series of ASCII values or, failing that, binary values. Let's see what happens when we do a simple query&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="n"&gt;OSC&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"WAVeform:SOURce CHAN1"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;OSC&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"WAVeform:DATA?"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And what we get back is a string with the values of the measurement, albeit with an interpretation error. In order for these values to be returned correctly in an array, the following function must be used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;OSC&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query_ascii_values&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"WAVeform:preamble?"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Float64&lt;/span&gt;&lt;span class="x"&gt;}&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
     &lt;span class="mf"&gt;0.0&lt;/span&gt;
     &lt;span class="mf"&gt;0.0&lt;/span&gt;
 &lt;span class="mf"&gt;62500.0&lt;/span&gt;
     &lt;span class="mf"&gt;1.0&lt;/span&gt;
     &lt;span class="mf"&gt;3.2e-7&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;0.01&lt;/span&gt;
     &lt;span class="mf"&gt;0.0&lt;/span&gt;
     &lt;span class="mf"&gt;0.4020101&lt;/span&gt;
     &lt;span class="mf"&gt;0.37&lt;/span&gt;
   &lt;span class="mf"&gt;128.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, these values are misinterpreted because the oscilloscope output is configured for binary values. Since we know which numbering format our oscilloscope uses, we will use the next function&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;OSC&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query_binary_values&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"WAVeform:DATA?"&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;datatype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"B"&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;is_big_endian&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;      
&lt;span class="mi"&gt;62500&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="x"&gt;}&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
 &lt;span class="mi"&gt;127&lt;/span&gt;
 &lt;span class="mi"&gt;126&lt;/span&gt;
 &lt;span class="mi"&gt;127&lt;/span&gt;
 &lt;span class="mi"&gt;127&lt;/span&gt;
 &lt;span class="mi"&gt;127&lt;/span&gt;
   &lt;span class="n"&gt;⋮&lt;/span&gt;
 &lt;span class="mi"&gt;127&lt;/span&gt;
 &lt;span class="mi"&gt;126&lt;/span&gt;
 &lt;span class="mi"&gt;126&lt;/span&gt;
 &lt;span class="mi"&gt;127&lt;/span&gt;
 &lt;span class="mi"&gt;127&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This translates the binary value type into a list of numbers, which is more useful for us. But even this is not enough, the values returned by the oscilloscope need to be scaled according to the acquisition configuration of the oscilloscope, so let's define that the returned data is scaled accordingly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="nf"&gt; data_to_values&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;typo&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_points&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x_incr&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x_orig&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x_ref&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_incr&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_orig&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_ref&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;puntos&lt;/span&gt;
    &lt;span class="n"&gt;xs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;@.&lt;/span&gt; &lt;span class="x"&gt;((&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;x_ref&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;x_incr&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;x_orig&lt;/span&gt;
    &lt;span class="n"&gt;ys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;@.&lt;/span&gt; &lt;span class="x"&gt;((&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;y_ref&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;y_incr&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;y_orig&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="n"&gt;xs&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ys&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we define a function that automatically returns the data for a specific channel of the oscilloscope.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="nf"&gt; OSC_Channel_adq&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;OSC&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"WAVEFORM:SOURCE CHAN&lt;/span&gt;&lt;span class="si"&gt;$&lt;/span&gt;&lt;span class="s"&gt;channel"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;OSC&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query_ascii_values&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"wav:preamble?"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;OSC&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query_binary_values&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"WAVeform:DATA?"&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;datatype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"B"&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;is_big_endian&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;data_to_values&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we will use the above to get the data and plot it with GLMakie.jl.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="n"&gt;dat_chan_1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;OSC_channel_adq&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;dat_chan_2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;OSC_channel_adq&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;GLMakie&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;LaTeXStrings&lt;/span&gt;

&lt;span class="k"&gt;begin&lt;/span&gt;
   &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Figure&lt;/span&gt;&lt;span class="x"&gt;()&lt;/span&gt;
   &lt;span class="n"&gt;ax&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Axis&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;],&lt;/span&gt;
             &lt;span class="n"&gt;xlabel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;L"t"&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt;
             &lt;span class="n"&gt;ylabel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;L"V"&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt;
             &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Oscilloscope"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
   &lt;span class="n"&gt;lines!&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ax&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt;&lt;span class="n"&gt;dat_chan_1&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"ch. 1"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
   &lt;span class="n"&gt;lines!&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ax&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt;&lt;span class="n"&gt;dat_chan_2&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;],&lt;/span&gt;&lt;span class="n"&gt;dat_chan_2&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="x"&gt;],&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"ch. 2"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
   &lt;span class="n"&gt;axislegend&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ax&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
   &lt;span class="n"&gt;f&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://forem.julialang.org/images/HsGXJcqIjBQdqYl38UAwwgyeMq6W5yOvDTyk-Sk8NMc/rt:fit/w:800/g:sm/q:0/mb:500000/ar:1/aHR0cHM6Ly9mb3Jl/bS5qdWxpYWxhbmcu/b3JnL3JlbW90ZWlt/YWdlcy91cGxvYWRz/L2FydGljbGVzLzNm/MzN0N2Z4eWQ0aTMw/MHhuOTJyLnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://forem.julialang.org/images/HsGXJcqIjBQdqYl38UAwwgyeMq6W5yOvDTyk-Sk8NMc/rt:fit/w:800/g:sm/q:0/mb:500000/ar:1/aHR0cHM6Ly9mb3Jl/bS5qdWxpYWxhbmcu/b3JnL3JlbW90ZWlt/YWdlcy91cGxvYWRz/L2FydGljbGVzLzNm/MzN0N2Z4eWQ0aTMw/MHhuOTJyLnBuZw" alt="Plotted data from an oscilloscope. There are two data series, a triangular signal and a series of Lorentzian-like curves." width="602" height="482"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To end the VISA session with the oscilloscope, we need to do it correctly with the following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;OSC&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="x"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It should be noted that each piece of equipment is different, so we must refer to the manual to know how to obtain useful data from the measuring instruments we use.&lt;/p&gt;




&lt;h2&gt;
  
  
  PyLabLib in Julia &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;There are devices to which we cannot connect through a VISA session, but we have to do it through their respective controllers. For this we will use &lt;a href="https://pylablib.readthedocs.io/en/latest/"&gt;PyLabLib&lt;/a&gt;, a library that has solved communication with devices of different manufacturers and categories, such as cameras, motors and detectors. The list of supported devices can be found in the package documentation. We will install the full version of the library in PyCall with the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;PyCall&lt;/span&gt;
&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`$(PyCall.python) -m pip install -U pylablib"[devio-full]"`&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's move on to controlling a Thorlabs K10CR1 rotary mount, for which we must first install the drivers from the following &lt;a href="https://www.thorlabs.com/software_pages/ViewSoftwarePage.cfm?Code=Motion_Control&amp;amp;viewtab=1"&gt;Thorlab's page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now, we import the functions that will allow us to control the motor and list the motors connected. We note that the second identified motor is the one we are going to move. We will connect it to inform us which scale it will use according to its model.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Thor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pyimport&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"pylablib.devices.Thorlabs"&lt;/span&gt;&lt;span class="x"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;list_thor_devices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Thor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;list_kinesis_devices&lt;/span&gt;&lt;span class="x"&gt;()&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Tuple&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="x"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
 &lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"27252406"&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Brushed Motor Controller"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
 &lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"55257014"&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Kinesis K10CR1 Rotary Stage"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;KDC_entr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Thor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;KinesisMotor&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;list_thor_devices&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="x"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;],&lt;/span&gt;&lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"K10CR1"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's see what other functions are available&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="c"&gt;# List of available functions that can be accessed by pressing the Tab key.&lt;/span&gt;
&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;KDC_entr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;CommData&lt;/span&gt;                       &lt;span class="n"&gt;CommShort&lt;/span&gt;                      &lt;span class="n"&gt;Error&lt;/span&gt;                          &lt;span class="n"&gt;NoParameterCaller&lt;/span&gt;              &lt;span class="n"&gt;__bool__&lt;/span&gt;                       &lt;span class="n"&gt;__class__&lt;/span&gt;
&lt;span class="n"&gt;__delattr__&lt;/span&gt;                    &lt;span class="n"&gt;__dict__&lt;/span&gt;                       &lt;span class="n"&gt;__dir__&lt;/span&gt;                        &lt;span class="n"&gt;__doc__&lt;/span&gt;                        &lt;span class="n"&gt;__enter__&lt;/span&gt;                      &lt;span class="n"&gt;__eq__&lt;/span&gt;
&lt;span class="n"&gt;__exit__&lt;/span&gt;                       &lt;span class="n"&gt;__format__&lt;/span&gt;                     &lt;span class="n"&gt;__ge__&lt;/span&gt;                         &lt;span class="n"&gt;__getattribute__&lt;/span&gt;               &lt;span class="n"&gt;__gt__&lt;/span&gt;                         &lt;span class="n"&gt;__hash__&lt;/span&gt;
&lt;span class="n"&gt;__init__&lt;/span&gt;                       &lt;span class="n"&gt;__init_subclass__&lt;/span&gt;              &lt;span class="n"&gt;__le__&lt;/span&gt;                         &lt;span class="n"&gt;__lt__&lt;/span&gt;                         &lt;span class="n"&gt;__module__&lt;/span&gt;                     &lt;span class="n"&gt;__ne__&lt;/span&gt;
&lt;span class="n"&gt;__new__&lt;/span&gt;                        &lt;span class="n"&gt;__reduce__&lt;/span&gt;                     &lt;span class="n"&gt;__reduce_ex__&lt;/span&gt;                  &lt;span class="n"&gt;__repr__&lt;/span&gt;                       &lt;span class="n"&gt;__setattr__&lt;/span&gt;                    &lt;span class="n"&gt;__sizeof__&lt;/span&gt;
&lt;span class="n"&gt;__str__&lt;/span&gt;                        &lt;span class="n"&gt;__subclasshook__&lt;/span&gt;               &lt;span class="n"&gt;__weakref__&lt;/span&gt;                    &lt;span class="n"&gt;_add_device_variable&lt;/span&gt;           &lt;span class="n"&gt;_add_info_variable&lt;/span&gt;             &lt;span class="n"&gt;_add_parameter_class&lt;/span&gt;
&lt;span class="n"&gt;_add_settings_variable&lt;/span&gt;         &lt;span class="n"&gt;_add_status_variable&lt;/span&gt;           &lt;span class="n"&gt;_as_parameter_class&lt;/span&gt;            &lt;span class="n"&gt;_autodetect_stage&lt;/span&gt;              &lt;span class="n"&gt;_axes&lt;/span&gt;                          &lt;span class="n"&gt;_axis_parameter_name&lt;/span&gt;
&lt;span class="n"&gt;_axis_value_case&lt;/span&gt;               &lt;span class="n"&gt;_bg_msg_counters&lt;/span&gt;               &lt;span class="n"&gt;_calculate_scale&lt;/span&gt;               &lt;span class="n"&gt;_call_without_parameters&lt;/span&gt;       &lt;span class="n"&gt;_close_on_error&lt;/span&gt;                &lt;span class="n"&gt;_connection_parameters&lt;/span&gt;
&lt;span class="n"&gt;_cycle_rts&lt;/span&gt;                     &lt;span class="n"&gt;_d2p&lt;/span&gt;                           &lt;span class="n"&gt;_default_axis&lt;/span&gt;                  &lt;span class="n"&gt;_default_get_status&lt;/span&gt;            &lt;span class="n"&gt;_device_SN&lt;/span&gt;                     &lt;span class="n"&gt;_device_var_ignore_error&lt;/span&gt;
&lt;span class="n"&gt;_device_vars&lt;/span&gt;                   &lt;span class="n"&gt;_device_vars_order&lt;/span&gt;             &lt;span class="n"&gt;_enable_channel&lt;/span&gt;                &lt;span class="n"&gt;_find_bays&lt;/span&gt;                     &lt;span class="n"&gt;_forward_positive&lt;/span&gt;              &lt;span class="n"&gt;_get_adc_inputs&lt;/span&gt;
&lt;span class="n"&gt;_get_connection_parameters&lt;/span&gt;     &lt;span class="n"&gt;_get_device_model&lt;/span&gt;              &lt;span class="n"&gt;_get_device_variables&lt;/span&gt;          &lt;span class="n"&gt;_get_gen_move_parameters&lt;/span&gt;       &lt;span class="n"&gt;_get_homing_parameters&lt;/span&gt;         &lt;span class="n"&gt;_get_jog_parameters&lt;/span&gt;
&lt;span class="n"&gt;_get_kcube_trigio_parameters&lt;/span&gt;   &lt;span class="n"&gt;_get_kcube_trigpos_parameters&lt;/span&gt;  &lt;span class="n"&gt;_get_limit_switch_parameters&lt;/span&gt;   &lt;span class="n"&gt;_get_polctl_parameters&lt;/span&gt;         &lt;span class="n"&gt;_get_position&lt;/span&gt;                  &lt;span class="n"&gt;_get_scale&lt;/span&gt;
&lt;span class="n"&gt;_get_stage&lt;/span&gt;                     &lt;span class="n"&gt;_get_status&lt;/span&gt;                    &lt;span class="n"&gt;_get_status_n&lt;/span&gt;                  &lt;span class="n"&gt;_get_step_scale&lt;/span&gt;                &lt;span class="n"&gt;_get_velocity_parameters&lt;/span&gt;       &lt;span class="n"&gt;_home&lt;/span&gt;
&lt;span class="n"&gt;_is_channel_enabled&lt;/span&gt;            &lt;span class="n"&gt;_is_homed&lt;/span&gt;                      &lt;span class="n"&gt;_is_homing&lt;/span&gt;                     &lt;span class="n"&gt;_is_moving&lt;/span&gt;                     &lt;span class="n"&gt;_is_rack_system&lt;/span&gt;                &lt;span class="n"&gt;_jog&lt;/span&gt;
&lt;span class="n"&gt;_make_channel&lt;/span&gt;                  &lt;span class="n"&gt;_make_dest&lt;/span&gt;                     &lt;span class="n"&gt;_mapped_axes&lt;/span&gt;                   &lt;span class="n"&gt;_model&lt;/span&gt;                         &lt;span class="n"&gt;_model_match&lt;/span&gt;                   &lt;span class="n"&gt;_move_by&lt;/span&gt;
&lt;span class="n"&gt;_move_by_mode&lt;/span&gt;                  &lt;span class="n"&gt;_move_to&lt;/span&gt;                       &lt;span class="n"&gt;_moving_status&lt;/span&gt;                 &lt;span class="n"&gt;_multiplex_func&lt;/span&gt;                &lt;span class="n"&gt;_original_axis_parameter&lt;/span&gt;       &lt;span class="n"&gt;_p2d&lt;/span&gt;
&lt;span class="n"&gt;_p_channel_id&lt;/span&gt;                  &lt;span class="n"&gt;_p_direction&lt;/span&gt;                   &lt;span class="n"&gt;_p_home_direction&lt;/span&gt;              &lt;span class="n"&gt;_p_hw_limit_kind&lt;/span&gt;               &lt;span class="n"&gt;_p_jog_mode&lt;/span&gt;                    &lt;span class="n"&gt;_p_kcube_trigio_mode&lt;/span&gt;
&lt;span class="n"&gt;_p_limit_switch&lt;/span&gt;                &lt;span class="n"&gt;_p_pzmot_channel_enabled&lt;/span&gt;       &lt;span class="n"&gt;_p_stop_mode&lt;/span&gt;                   &lt;span class="n"&gt;_p_sw_limit_kind&lt;/span&gt;               &lt;span class="n"&gt;_parameters&lt;/span&gt;                    &lt;span class="n"&gt;_pzmot_autoenable&lt;/span&gt;
&lt;span class="n"&gt;_pzmot_enable_channels&lt;/span&gt;         &lt;span class="n"&gt;_pzmot_get_drive_parameters&lt;/span&gt;    &lt;span class="n"&gt;_pzmot_get_enabled_channels&lt;/span&gt;    &lt;span class="n"&gt;_pzmot_get_jog_parameters&lt;/span&gt;      &lt;span class="n"&gt;_pzmot_get_kind&lt;/span&gt;                &lt;span class="n"&gt;_pzmot_get_position&lt;/span&gt;
&lt;span class="n"&gt;_pzmot_get_status&lt;/span&gt;              &lt;span class="n"&gt;_pzmot_get_status_n&lt;/span&gt;            &lt;span class="n"&gt;_pzmot_jog&lt;/span&gt;                     &lt;span class="n"&gt;_pzmot_kind&lt;/span&gt;                    &lt;span class="n"&gt;_pzmot_move_by&lt;/span&gt;                 &lt;span class="n"&gt;_pzmot_move_to&lt;/span&gt;
&lt;span class="n"&gt;_pzmot_req&lt;/span&gt;                     &lt;span class="n"&gt;_pzmot_set&lt;/span&gt;                     &lt;span class="n"&gt;_pzmot_set_position_reference&lt;/span&gt;  &lt;span class="n"&gt;_pzmot_setup_drive&lt;/span&gt;             &lt;span class="n"&gt;_pzmot_setup_jog&lt;/span&gt;               &lt;span class="n"&gt;_pzmot_stop&lt;/span&gt;
&lt;span class="n"&gt;_pzmot_wait_for_status&lt;/span&gt;         &lt;span class="n"&gt;_remove_device_variable&lt;/span&gt;        &lt;span class="n"&gt;_replace_parameter_class&lt;/span&gt;       &lt;span class="n"&gt;_resolve_axis&lt;/span&gt;                  &lt;span class="n"&gt;_scale&lt;/span&gt;                         &lt;span class="n"&gt;_scale_units&lt;/span&gt;
&lt;span class="n"&gt;_set_position_reference&lt;/span&gt;        &lt;span class="n"&gt;_set_supported_channels&lt;/span&gt;        &lt;span class="n"&gt;_setup_comm_parameters&lt;/span&gt;         &lt;span class="n"&gt;_setup_gen_move&lt;/span&gt;                &lt;span class="n"&gt;_setup_homing&lt;/span&gt;                  &lt;span class="n"&gt;_setup_jog&lt;/span&gt;
&lt;span class="n"&gt;_setup_kcube_trigio&lt;/span&gt;            &lt;span class="n"&gt;_setup_kcube_trigpos&lt;/span&gt;           &lt;span class="n"&gt;_setup_limit_switch&lt;/span&gt;            &lt;span class="n"&gt;_setup_parameter_classes&lt;/span&gt;       &lt;span class="n"&gt;_setup_polctl&lt;/span&gt;                  &lt;span class="n"&gt;_setup_velocity&lt;/span&gt;
&lt;span class="n"&gt;_stage&lt;/span&gt;                         &lt;span class="n"&gt;_status_comm&lt;/span&gt;                   &lt;span class="n"&gt;_stop&lt;/span&gt;                          &lt;span class="n"&gt;_update_axes&lt;/span&gt;                   &lt;span class="n"&gt;_update_device_variable_order&lt;/span&gt;  &lt;span class="n"&gt;_wait_for_home&lt;/span&gt;
&lt;span class="n"&gt;_wait_for_status&lt;/span&gt;               &lt;span class="n"&gt;_wait_for_stop&lt;/span&gt;                 &lt;span class="n"&gt;_wait_move&lt;/span&gt;                     &lt;span class="n"&gt;_wap&lt;/span&gt;                           &lt;span class="n"&gt;_wip&lt;/span&gt;                           &lt;span class="n"&gt;_wop&lt;/span&gt;
&lt;span class="n"&gt;add_background_comm&lt;/span&gt;            &lt;span class="n"&gt;apply_settings&lt;/span&gt;                 &lt;span class="n"&gt;blink&lt;/span&gt;                          &lt;span class="n"&gt;check_background_comm&lt;/span&gt;          &lt;span class="n"&gt;close&lt;/span&gt;                          &lt;span class="n"&gt;dv&lt;/span&gt;
&lt;span class="n"&gt;flush_comm&lt;/span&gt;                     &lt;span class="n"&gt;get_all_axes&lt;/span&gt;                   &lt;span class="n"&gt;get_all_channels&lt;/span&gt;               &lt;span class="n"&gt;get_device_info&lt;/span&gt;                &lt;span class="n"&gt;get_device_variable&lt;/span&gt;            &lt;span class="n"&gt;get_full_info&lt;/span&gt;
&lt;span class="n"&gt;get_full_status&lt;/span&gt;                &lt;span class="n"&gt;get_gen_move_parameters&lt;/span&gt;        &lt;span class="n"&gt;get_homing_parameters&lt;/span&gt;          &lt;span class="n"&gt;get_jog_parameters&lt;/span&gt;             &lt;span class="n"&gt;get_kcube_trigio_parameters&lt;/span&gt;    &lt;span class="n"&gt;get_kcube_trigpos_parameters&lt;/span&gt;
&lt;span class="n"&gt;get_limit_switch_parameters&lt;/span&gt;    &lt;span class="n"&gt;get_number_of_channels&lt;/span&gt;         &lt;span class="n"&gt;get_polctl_parameters&lt;/span&gt;          &lt;span class="n"&gt;get_position&lt;/span&gt;                   &lt;span class="n"&gt;get_scale&lt;/span&gt;                      &lt;span class="n"&gt;get_scale_units&lt;/span&gt;
&lt;span class="n"&gt;get_settings&lt;/span&gt;                   &lt;span class="n"&gt;get_stage&lt;/span&gt;                      &lt;span class="n"&gt;get_status&lt;/span&gt;                     &lt;span class="n"&gt;get_status_n&lt;/span&gt;                   &lt;span class="n"&gt;get_velocity_parameters&lt;/span&gt;        &lt;span class="n"&gt;home&lt;/span&gt;
&lt;span class="n"&gt;instr&lt;/span&gt;                          &lt;span class="n"&gt;is_homed&lt;/span&gt;                       &lt;span class="n"&gt;is_homing&lt;/span&gt;                      &lt;span class="n"&gt;is_moving&lt;/span&gt;                      &lt;span class="n"&gt;is_opened&lt;/span&gt;                      &lt;span class="n"&gt;jog&lt;/span&gt;
&lt;span class="n"&gt;list_devices&lt;/span&gt;                   &lt;span class="n"&gt;lock&lt;/span&gt;                           &lt;span class="n"&gt;locking&lt;/span&gt;                        &lt;span class="n"&gt;move_by&lt;/span&gt;                        &lt;span class="n"&gt;move_to&lt;/span&gt;                        &lt;span class="n"&gt;open&lt;/span&gt;
&lt;span class="n"&gt;query&lt;/span&gt;                          &lt;span class="n"&gt;recv_comm&lt;/span&gt;                      &lt;span class="n"&gt;remap_axes&lt;/span&gt;                     &lt;span class="n"&gt;send_comm&lt;/span&gt;                      &lt;span class="n"&gt;send_comm_data&lt;/span&gt;                 &lt;span class="n"&gt;set_default_channel&lt;/span&gt;
&lt;span class="n"&gt;set_device_variable&lt;/span&gt;            &lt;span class="n"&gt;set_position_reference&lt;/span&gt;         &lt;span class="n"&gt;set_supported_channels&lt;/span&gt;         &lt;span class="n"&gt;setup_gen_move&lt;/span&gt;                 &lt;span class="n"&gt;setup_homing&lt;/span&gt;                   &lt;span class="n"&gt;setup_jog&lt;/span&gt;
&lt;span class="n"&gt;setup_kcube_trigio&lt;/span&gt;             &lt;span class="n"&gt;setup_kcube_trigpos&lt;/span&gt;            &lt;span class="n"&gt;setup_limit_switch&lt;/span&gt;             &lt;span class="n"&gt;setup_polctl&lt;/span&gt;                   &lt;span class="n"&gt;setup_velocity&lt;/span&gt;                 &lt;span class="n"&gt;status_bits&lt;/span&gt;
&lt;span class="n"&gt;stop&lt;/span&gt;                           &lt;span class="n"&gt;unlock&lt;/span&gt;                         &lt;span class="n"&gt;using_channel&lt;/span&gt;                  &lt;span class="n"&gt;wait_for_home&lt;/span&gt;                  &lt;span class="n"&gt;wait_for_status&lt;/span&gt;                &lt;span class="n"&gt;wait_for_stop&lt;/span&gt;
&lt;span class="n"&gt;wait_move&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we are in doubt about what a function does, we can always use Julia's help environment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;?&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;KDC_entr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;home&lt;/span&gt;

        &lt;span class="n"&gt;Home&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;

        &lt;span class="n"&gt;If&lt;/span&gt; &lt;span class="sb"&gt;``&lt;/span&gt;&lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="n"&gt;True&lt;/span&gt;&lt;span class="sb"&gt;``&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wait&lt;/span&gt; &lt;span class="n"&gt;until&lt;/span&gt; &lt;span class="n"&gt;homing&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;done&lt;/span&gt; &lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;given&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
        &lt;span class="n"&gt;If&lt;/span&gt; &lt;span class="sb"&gt;``&lt;/span&gt;&lt;span class="n"&gt;force&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="n"&gt;False&lt;/span&gt;&lt;span class="sb"&gt;``&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;only&lt;/span&gt; &lt;span class="n"&gt;home&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt; &lt;span class="n"&gt;isn&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="n"&gt;homed&lt;/span&gt; &lt;span class="n"&gt;already&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will do the following, we will send the mount to the home position, and we will define a function that will rotate it to the desired position and inform us of its current position.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;θc_cal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="nf"&gt; θ_c&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;θ₀&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;θ&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;θ₀&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;θc_cal&lt;/span&gt;
    &lt;span class="nd"&gt;@info&lt;/span&gt; &lt;span class="s"&gt;"Moving cube to &lt;/span&gt;&lt;span class="si"&gt;$&lt;/span&gt;&lt;span class="s"&gt;(θ₀)°                    "&lt;/span&gt;
    &lt;span class="n"&gt;KDC_entr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;move_to&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;θ&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;KDC_entr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_status&lt;/span&gt;&lt;span class="x"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"moving_bk"&lt;/span&gt;
        &lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Cube position,  θ = &lt;/span&gt;&lt;span class="si"&gt;$&lt;/span&gt;&lt;span class="s"&gt;(round(KDC_entr.get_position(),digits=4) - θc_cal)°                     &lt;/span&gt;&lt;span class="se"&gt;\r&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="nd"&gt;@info&lt;/span&gt; &lt;span class="s"&gt;"Cube angle &lt;/span&gt;&lt;span class="si"&gt;$&lt;/span&gt;&lt;span class="s"&gt;(θ₀)°                               "&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remember to use &lt;code&gt;KDC_1.close()&lt;/code&gt; to close the connection when it is no longer needed.&lt;/p&gt;

&lt;p&gt;The details of connection, data acquisition, and status checking will vary from device to device. Even the connection to the controllers is different, so I highly recommend consulting the package and instrument documentation to see how these tasks are performed. &lt;/p&gt;

&lt;p&gt;Sometimes we have to find the controllers manually, for example the following lines will allow us to connect to the SDK controllers of a monochromator and an Andor camera.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="n"&gt;py&lt;/span&gt;&lt;span class="s"&gt;"""
import pylablib as pll
pll.par["&lt;/span&gt;&lt;span class="n"&gt;devices&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;dlls&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;andor_shamrock&lt;/span&gt;&lt;span class="s"&gt;"] = "&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;:\&lt;/span&gt;&lt;span class="n"&gt;Program&lt;/span&gt; &lt;span class="n"&gt;Files&lt;/span&gt;&lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="n"&gt;Andor&lt;/span&gt; &lt;span class="n"&gt;SOLIS&lt;/span&gt;&lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="n"&gt;Drivers&lt;/span&gt;&lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="n"&gt;Shamrock64&lt;/span&gt;&lt;span class="s"&gt;"
"""&lt;/span&gt;
&lt;span class="n"&gt;andor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pyimport&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"pylablib.devices.Andor"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  A tiny experiment &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Let's take what we've seen so far and measure an optical signal transmitted by a particular device by rotating a polarizer cube, and store the data in the appropriate matrices.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="c"&gt;# This code was tested with Julia 1.10.0&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;PyCall&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;GLMakie&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;LaTeXStrings&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;ProgressMeter&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;JLD2&lt;/span&gt;

&lt;span class="c"&gt;# Connection with the oscilloscope&lt;/span&gt;
&lt;span class="n"&gt;visa&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pyimport&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"pyvisa"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;RM&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;visa&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResourceManager&lt;/span&gt;&lt;span class="x"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;list_resources&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RM&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;list_resources&lt;/span&gt;&lt;span class="x"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;OSC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RM&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open_resource&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;list_resources&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;])&lt;/span&gt;

&lt;span class="nd"&gt;@info&lt;/span&gt; &lt;span class="n"&gt;OSC&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"*IDN?"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Connection with the motor stage&lt;/span&gt;
&lt;span class="n"&gt;Thor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pyimport&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"pylablib.devices.Thorlabs"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;list_thor_devices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Thor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;list_kinesis_devices&lt;/span&gt;&lt;span class="x"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;KDC_entr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Thor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;KinesisMotor&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;list_thor_devices&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="x"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;],&lt;/span&gt;&lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"K10CR1"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Definition of oscilloscope's functions&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="nf"&gt; data_to_values&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;formato&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tipo&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;puntos&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cuenta&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x_incr&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x_orig&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x_ref&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_incr&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_orig&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_ref&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;puntos&lt;/span&gt;
    &lt;span class="n"&gt;xs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;@.&lt;/span&gt; &lt;span class="x"&gt;((&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;x_ref&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;x_incr&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;x_orig&lt;/span&gt;
    &lt;span class="n"&gt;ys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;@.&lt;/span&gt; &lt;span class="x"&gt;((&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;y_ref&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;y_incr&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;y_orig&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;xs&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ys&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="nf"&gt; OSC_Channel_adq&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;OSC&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"WAVEFORM:SOURCE CHAN&lt;/span&gt;&lt;span class="si"&gt;$&lt;/span&gt;&lt;span class="s"&gt;channel"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;OSC&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query_ascii_values&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"wav:preamble?"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;OSC&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query_binary_values&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"WAVeform:DATA?"&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;datatype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"B"&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;is_big_endian&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;data_to_values&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c"&gt;# Definition of motor stage's functions&lt;/span&gt;
&lt;span class="n"&gt;θc_cal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt; &lt;span class="c"&gt;# Calibration constant&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="nf"&gt; θ_c&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;θ₀&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;θ&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;θ₀&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;θc_cal&lt;/span&gt;
    &lt;span class="nd"&gt;@info&lt;/span&gt; &lt;span class="s"&gt;"Moving cube to &lt;/span&gt;&lt;span class="si"&gt;$&lt;/span&gt;&lt;span class="s"&gt;(θ₀)°                    "&lt;/span&gt;
    &lt;span class="n"&gt;KDC_entr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;move_to&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;θ&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;KDC_entr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_status&lt;/span&gt;&lt;span class="x"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"moving_bk"&lt;/span&gt;
        &lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Cube at position,  θ = &lt;/span&gt;&lt;span class="si"&gt;$&lt;/span&gt;&lt;span class="s"&gt;(round(KDC_entr.get_position(),digits=4) - θc_cal)°                     &lt;/span&gt;&lt;span class="se"&gt;\r&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="nd"&gt;@info&lt;/span&gt; &lt;span class="s"&gt;"Cube angle &lt;/span&gt;&lt;span class="si"&gt;$&lt;/span&gt;&lt;span class="s"&gt;(θ₀)°                               "&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c"&gt;# Setting matrices sizes&lt;/span&gt;
&lt;span class="n"&gt;θs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;360&lt;/span&gt;
&lt;span class="n"&gt;ts1&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ch1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;OSC_Channel_adq&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;ts_ch1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="x"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;ts_ch2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="x"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;Data_ch1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;zeros&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ch1&lt;/span&gt;&lt;span class="x"&gt;),&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;θs&lt;/span&gt;&lt;span class="x"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;Data_ch2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;zeros&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ch1&lt;/span&gt;&lt;span class="x"&gt;),&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;θs&lt;/span&gt;&lt;span class="x"&gt;))&lt;/span&gt;

&lt;span class="nd"&gt;@showprogress&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt;&lt;span class="n"&gt;θ&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;enumerate&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;θs&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
   &lt;span class="n"&gt;θ_c&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;θ&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
   &lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
   &lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;V1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;OSC_Channel_adq&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
   &lt;span class="n"&gt;t2&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;V2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;OSC_Channel_adq&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
   &lt;span class="n"&gt;Data_ch1&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt; &lt;span class="o"&gt;.=&lt;/span&gt; &lt;span class="n"&gt;V1&lt;/span&gt;
   &lt;span class="n"&gt;Data_ch2&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt; &lt;span class="o"&gt;.=&lt;/span&gt; &lt;span class="n"&gt;V2&lt;/span&gt;
   &lt;span class="n"&gt;push!&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ts_ch1&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt;&lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
   &lt;span class="n"&gt;push!&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ts_ch2&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt;&lt;span class="n"&gt;t2&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;maxs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="n"&gt;maximum&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cols&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;cols&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;eachcol&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Data_ch1&lt;/span&gt;&lt;span class="x"&gt;)]&lt;/span&gt;
&lt;span class="n"&gt;mins&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="n"&gt;minimum&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cols&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;cols&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;eachcol&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Data_ch2&lt;/span&gt;&lt;span class="x"&gt;)]&lt;/span&gt;

&lt;span class="n"&gt;extrema_amp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;maxs&lt;/span&gt; &lt;span class="o"&gt;.-&lt;/span&gt; &lt;span class="n"&gt;mins&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's plot the amplitudes of the resulting signals.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
    &lt;span class="n"&gt;F&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Figure&lt;/span&gt;&lt;span class="x"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;ax&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Axis&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;xlabel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;L"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;heta \:[^\circ]"&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ylabel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;L"V"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;lines!&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ax&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt;&lt;span class="n"&gt;θs&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt;&lt;span class="n"&gt;extrema_amp&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;DataInspector&lt;/span&gt;&lt;span class="x"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;F&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://forem.julialang.org/images/7KnkXS2pbSpZ6r4u5tD3UJWHx2TTGmKD74tVZvWGb_g/rt:fit/w:800/g:sm/q:0/mb:500000/ar:1/aHR0cHM6Ly9mb3Jl/bS5qdWxpYWxhbmcu/b3JnL3JlbW90ZWlt/YWdlcy91cGxvYWRz/L2FydGljbGVzLzN4/aDliczVmZ2g0a2Zt/d2l6d3ZqLnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://forem.julialang.org/images/7KnkXS2pbSpZ6r4u5tD3UJWHx2TTGmKD74tVZvWGb_g/rt:fit/w:800/g:sm/q:0/mb:500000/ar:1/aHR0cHM6Ly9mb3Jl/bS5qdWxpYWxhbmcu/b3JnL3JlbW90ZWlt/YWdlcy91cGxvYWRz/L2FydGljbGVzLzN4/aDliczVmZ2g0a2Zt/d2l6d3ZqLnBuZw" alt="Experimental data of the transmitted power of a polarized laser through a Glam Taylor polarizer at several degrees." width="602" height="482"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Experimental data of the transmitted power of a polarized laser through a Glam Taylor polarizer at several degrees.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As we can see, the result shows a transmission peak at a certain angle. &lt;/p&gt;


&lt;h2&gt;
  
  
  Saving data and metadata &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;In an experiment, it is not enough to save the results of the measurements, we also need to know the conditions under which we made them. In our example above, we need to know what equipment we used, how it was configured, what positions the motor took, or when we ran the experiment. &lt;/p&gt;

&lt;p&gt;To store both data and metadata in the same file, we can use the &lt;a href="https://github.com/JuliaIO/JLD2.jl"&gt;JLD2&lt;/a&gt; package, which allows us to create files compatible with the HDF5 standard. The following sample code defines and executes a function that creates a file containing the configuration parameters of the experiment and the data we measured.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="c"&gt;# Save data&lt;/span&gt;
&lt;span class="n"&gt;file_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"22012024_malus_1.jld2"&lt;/span&gt;
&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jldopen&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;joinpath&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"data"&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;file_name&lt;/span&gt;&lt;span class="x"&gt;),&lt;/span&gt; &lt;span class="s"&gt;"a+"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;
    &lt;span class="n"&gt;configuration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;JLD2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Group&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"configuration"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;datas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;JLD2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Group&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"datas"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"OSC_preamble"&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;OSC&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query_ascii_values&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"wav:preamble?"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"OSC_idn"&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;OSC&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"*IDN?"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"OSC_conf"&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;KDC_entr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_settings&lt;/span&gt;&lt;span class="x"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"MOTOR_idn"&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;list_thor_devices&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="x"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;datas&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"ts_ch1"&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ts_ch1&lt;/span&gt;
    &lt;span class="n"&gt;datas&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"ts_ch2"&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ts_ch1&lt;/span&gt;
    &lt;span class="n"&gt;datas&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"Data_ch1"&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Data_ch1&lt;/span&gt;
    &lt;span class="n"&gt;datas&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"Data_ch1"&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Data_ch1&lt;/span&gt;
    &lt;span class="n"&gt;datas&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"θs"&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;θs&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we want to recover the data, we can do it by opening the file. I always suggest that once we are done recovering the data we need, we close the file before processing the data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jldopen&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"data/24012024_malus_1.jld2"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;JLDFile&lt;/span&gt; &lt;span class="n"&gt;D&lt;/span&gt;&lt;span class="o"&gt;:\&lt;/span&gt;&lt;span class="n"&gt;Documentos&lt;/span&gt;&lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="n"&gt;Julia&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;manual&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;visa&lt;/span&gt;&lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="mi"&gt;24012024&lt;/span&gt;&lt;span class="n"&gt;_malus_1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;jld2&lt;/span&gt; &lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;only&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
 &lt;span class="n"&gt;├─&lt;/span&gt;&lt;span class="err"&gt;📂&lt;/span&gt; &lt;span class="n"&gt;configuration&lt;/span&gt;
 &lt;span class="n"&gt;│&lt;/span&gt;  &lt;span class="n"&gt;├─&lt;/span&gt;&lt;span class="err"&gt;🔢&lt;/span&gt; &lt;span class="n"&gt;OSC_preamble&lt;/span&gt;
 &lt;span class="n"&gt;│&lt;/span&gt;  &lt;span class="n"&gt;├─&lt;/span&gt;&lt;span class="err"&gt;🔢&lt;/span&gt; &lt;span class="n"&gt;OSC_idn&lt;/span&gt;
 &lt;span class="n"&gt;│&lt;/span&gt;  &lt;span class="n"&gt;├─&lt;/span&gt;&lt;span class="err"&gt;🔢&lt;/span&gt; &lt;span class="n"&gt;OSC_conf&lt;/span&gt;
 &lt;span class="n"&gt;│&lt;/span&gt;  &lt;span class="n"&gt;└─&lt;/span&gt;&lt;span class="err"&gt;🔢&lt;/span&gt; &lt;span class="n"&gt;MOTOR_idn&lt;/span&gt;
 &lt;span class="n"&gt;└─&lt;/span&gt;&lt;span class="err"&gt;📂&lt;/span&gt; &lt;span class="n"&gt;datos&lt;/span&gt;
    &lt;span class="n"&gt;├─&lt;/span&gt;&lt;span class="err"&gt;🔢&lt;/span&gt; &lt;span class="n"&gt;ts_ch1&lt;/span&gt;
    &lt;span class="n"&gt;├─&lt;/span&gt;&lt;span class="err"&gt;🔢&lt;/span&gt; &lt;span class="n"&gt;ts_ch2&lt;/span&gt;
    &lt;span class="n"&gt;├─&lt;/span&gt;&lt;span class="err"&gt;🔢&lt;/span&gt; &lt;span class="n"&gt;Data_ch1&lt;/span&gt;
    &lt;span class="n"&gt;└─&lt;/span&gt; &lt;span class="n"&gt;⋯&lt;/span&gt; &lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="n"&gt;more&lt;/span&gt; &lt;span class="n"&gt;entries&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;OSC_preamble&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"configuration"&lt;/span&gt;&lt;span class="x"&gt;][&lt;/span&gt;&lt;span class="s"&gt;"OSC_preamble"&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;
&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Float64&lt;/span&gt;&lt;span class="x"&gt;}&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
     &lt;span class="mf"&gt;0.0&lt;/span&gt;
     &lt;span class="mf"&gt;0.0&lt;/span&gt;
 &lt;span class="mf"&gt;62500.0&lt;/span&gt;
     &lt;span class="mf"&gt;1.0&lt;/span&gt;
     &lt;span class="mf"&gt;3.2e-7&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;0.01&lt;/span&gt;
     &lt;span class="mf"&gt;0.0&lt;/span&gt;
     &lt;span class="mf"&gt;0.008040201&lt;/span&gt;
     &lt;span class="mf"&gt;0.612&lt;/span&gt;
   &lt;span class="mf"&gt;128.0&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Conclusions &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;In this short tutorial I showed the basics of how to automate experiments using instrument communication via PyVISA and PyLabLib. I also briefly showed how to plot the acquired data. At the same time, I showed how to take advantage of instrument communication to store metadata in the same file using the JLD2 package.  &lt;/p&gt;

&lt;p&gt;I hope this mini-course will be useful, even though it does not cover the potential of the language to apply asynchronous functions, or to generate user interfaces with Makie, dashboards with &lt;a href="https://genieframework.com/"&gt;Genie&lt;/a&gt;, or interactive notebooks with &lt;a href="https://plutojl.org/"&gt;Pluto&lt;/a&gt;, options that are fully feasible with Julia. At the same time, the implementation of platforms such as &lt;a href="https://juliadynamics.github.io/DrWatson.jl/stable/"&gt;DrWatson&lt;/a&gt; together with experiment automation techniques seems to be a natural way to have a record of the evolution of the experiments.  As a supplement, I leave this &lt;a href="https://github.com/Ceboc/Julia-manual-visa"&gt;link&lt;/a&gt; to one of my repositories with the same example we discussed in this tutorial, but implementing some of the ideas I mentioned in this paragraph.  &lt;/p&gt;

&lt;p&gt;Have fun experimenting!&lt;/p&gt;

&lt;p&gt;&lt;sup&gt;&lt;sup&gt;All trademarks used in this document, as well as images and logos or any other mentioned entity that may appear are the property of their respective owners, and I or this channel claim no right over them.&lt;/sup&gt;&lt;/sup&gt;&lt;br&gt;
&lt;sup&gt;&lt;sup&gt;Facilities available at ICN-UNAM were used for this publication.&lt;/sup&gt;&lt;/sup&gt;&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;Of course, this is possible, but I doubt that many users would want to compile code to send a simple email or the meme of the moment. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;I wrote this code from scratch, programming every single SCIPI command in a .vi file for our OSA, because some years ago their manufacturer only provided code compatible with other models (and .vi's in Japanese!), nowadays there is a usable set of LabVIEW programs, but then this was my only solution. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;It seems that they tried to solve this with LabVIEW NGX, but the software was somehow incompatible with the traditional version and so damn slow to install and run that they ended up discontinuing it. Addendum: It appears that this functionality was enabled until not too long ago.  ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn4"&gt;
&lt;p&gt;Or, in the worst case, some software that is free but does not document its drivers, making communication with the device other than through its software very difficult, if not impossible (I'm looking at you, New Focus). ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn5"&gt;
&lt;p&gt;It's not that there aren't people discussing it, but it's not a topic that's rich in conversation. This may be the only example of this that I can give you: ↩&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://discourse.julialang.org/t/new-domain-what-are-people-using-julia-for-in-hardware"&gt;New Domain - what are people using Julia for in Hardware?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;

&lt;li id="fn6"&gt;
&lt;p&gt;Although there is &lt;a href="https://github.com/BBN-Q/Instruments.jl"&gt;Instruments.jl&lt;/a&gt; that provides an interface to VISA, I prefer not to use it because at this point it can be considered abandonware. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn7"&gt;
&lt;p&gt;There are also manufacturer's specific solutions, as those provided by Physike Instrumente (&lt;a href="https://pipython.physikinstrumente.com/"&gt;PIpython&lt;/a&gt;). ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn8"&gt;
&lt;p&gt;I once needed to use a function from the &lt;a href="https://www.boost.org/"&gt;C++ Boost library&lt;/a&gt; to access special functions not available in &lt;a href="https://github.com/JuliaMath/SpecialFunctions.jl"&gt;SpecialFunctions&lt;/a&gt;, it came out regular. Although I was able to run this function sequentially, doing it in parallel was too unstable, so I ended up rewriting the functions I needed in Julia. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn9"&gt;
&lt;p&gt;As mentioned in their documentation. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn10"&gt;
&lt;p&gt;This code is a modification from this answered question in StackOverflow: &lt;a href="https://stackoverflow.com/questions/65984539/how-to-use-in-julia-a-python-package-that-is-not-available-in-anaconda-and-needs"&gt;How to use in Julia a Python package that is not available in Anaconda and needs to be installed via pip&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn11"&gt;
&lt;p&gt;The behavior of the oscilloscope in the video corresponds to different scale values with respect to those shown in the code, but otherwise each of the instructions is executed. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>automation</category>
      <category>data</category>
      <category>experiments</category>
      <category>visa</category>
    </item>
  </channel>
</rss>
