Experimental session and instruments

The first script does totally useless things but it shows how FluidLab can be used for very simple scripts to control experiments. An “experimental session” with one “data table” is created or loaded if it already exists. A figure to plot the two quantities U0 and U1 is defined. Data is saved at each time step of a short time loop.

Since there is no physical instruments, you should be able to try this script. You can modify the argument email_to to a real email address and uncomment the lines starting with “email” in the instantiation of the session. You can also modify the flag raise_error to see what it gives with the logger and the emails.

from __future__ import print_function, division

import numpy as np

from fluidlab.exp import Session, Timer
from fluidlab.output import show

raise_error = False

# unless explicitly mentioned, FluidLab uses SI units, so the times are is s
total_time = 5.0
time_step = 0.2
omega = 2 * np.pi / 2.0

# conversion volt into temperature (nothing physical, just for the example)
alpha = 2.0

# initialize session, log, saving and emails
session = Session(
    path="Tests",
    name="False_exp",
    # email_to='experimentalist@lab.earth',
    email_title="False experiment without instrument",
    email_delay=30,  # time in s
)

print = session.logger.print_log

data_table = session.get_data_table(fieldnames=["U0", "U1", "T0", "T1"])

data_table.init_figure(["U0", "U1"])
data_table.init_figure(["T0", "T1"])

# initialization of the time loop
t_last_print = 0.0
t = 0.0
timer = Timer(time_step)

# start the time loop
while t < total_time:

    U0 = np.cos(omega * t) + 0.1 * np.random.rand()
    U1 = U0 * np.random.rand()

    data_table.save({"U0": U0, "U1": U1, "T0": alpha * U0, "T1": alpha * U1})

    if t - t_last_print > 1 - time_step / 2.0:
        t_last_print = t
        print(f"time till start: {t:8.5} s")
        data_table.update_figures()
        session.logger.send_email_if_has_to(figures=data_table.figures)

    t = timer.wait_tick()

if raise_error:
    print("let's raise a ValueError to see what it gives.")
    raise ValueError("The flag raise_error is True...")

print(f"Time end: {t:8.5} s")

show()

The next script also corresponds to a false experiment but two real instruments, a function generator (fluidlab.instruments.funcgen.tektronix_afg3022b) and an oscilloscope (fluidlab.instruments.scope.agilent_dsox2014a), are used:

from __future__ import print_function, division

import numpy as np

from fluidlab.exp import Session, Timer
from fluidlab.output import show

from fluidlab.instruments.scope.agilent_dsox2014a import AgilentDSOX2014a
from fluidlab.instruments.funcgen.tektronix_afg3022b import TektronixAFG3022b

total_time = 5.0
time_step = 1.0
omega = 2 * np.pi / 2.0

# conversion volt into temperature (nothing physical, just for the example)
alpha = 0.01

# initialize session, log, saving and emails
session = Session(
    path="Tests",
    name="Exp_funcgen_scope",
    # email_to='experimentalist@lab.earth',
    # email_title='False experiment with function generator and oscilloscope',
    # email_delay=2*3600
)

print = session.logger.print_log
send_email_if_has_to = session.logger.send_email_if_has_to

data_table = session.get_data_table(fieldnames=["U0", "U1", "T0", "T1"])

data_table.init_figure(["T0", "T1"])

# setup the function generator
funcgen = TektronixAFG3022b("USB0::1689::839::C034062::0::INSTR")
offset = 1.0
funcgen.function_shape.set("sin")
funcgen.frequency.set(1e4)
funcgen.voltage.set(0.0)
funcgen.offset.set(offset)
funcgen.output1_state.set(True)

# setup the oscilloscope
scope = AgilentDSOX2014a("USB0::2391::6040::MY51450715::0::INSTR")
scope.channel1_coupling.set("DC")
scope.channel1_range.set(5.0)
scope.timebase_range.set(1e-3)
scope.trigger_level.set(offset)

# initialization of the time loop
t_last_print = 0.0
t = 0.0
timer = Timer(time_step)

# start the time loop
while t < total_time:

    volts_out = np.cos(omega * t) + 0.1 * np.random.rand()

    funcgen.voltage.set(volts_out)

    time, volts = scope.get_curve(nb_points=200)

    U0 = volts.min()
    U1 = volts.max()

    data_table.save({"U0": U0, "U1": U1, "T0": alpha * U0, "T1": alpha * U1})

    if t - t_last_print > 1 - time_step / 2.0:
        t_last_print = t
        print(f"time till start: {t:8.5} s")
        data_table.update_figures()
        send_email_if_has_to()

    t = timer.wait_tick()

print(f"Time end: {t:8.5} s")
show()