Package: meavis
IntroductionMeaVis is a python framework intended to define howMeasurements have to
be run and a programming interface toVisualise resulting datasets.See more details atReadTheDocs.io.Basic exampleGeneral configuration of intrumentsLet's assume two basic drivers as follow:importvxi11classAgilentB596X(vxi11.Instrument):def__init__(self,host):super().__init__(host=host)self.channel=Noneself.mode=Nonedefconf():ifself.channelandself.mode:self.write(":SOUR{}:FUNC:MODE{}".format(self.channel,self.mode))defoutput(self,value):self.conf()ifself.channel:self.write(":OUTP{}{}".format(self.channel,"ON"ifvalueelse"OFF"))defset_channel(self,channel):self.channel=channelself.write(":SOUR{}:FUNC:SHAP DC".format(self.channel))self.conf()defset_mode(self,mode):self.mode=modeself.conf()defset_value(self,value):self.write(":SOUR{}:{}{}".format(self.channel,self.mode,value))classKeySight344XX(vxi11.Instrument):def__init__(self,host):super().__init__(host=host)self.write("*CLS")self.write("*RST")self.write("TRIG:SOUR IMM")self.write("CALC:FUNC AVER")self.write("CALC:STAT ON")self.ACorDC=Noneself.mode=Nonedefcalc_average(self):self.write("*CALC:AVER:AVER")returnfloat(self.read())defconf(self):ifself.ACorDCandself.mode:self.write("CONF:{}:{}".format(self.mode,self.ACorDC))defconf_ACorDC(self,ACorDC):self.ACorDC=ACorDCself.conf()defconf_mode(self,mode):self.mode=modeself.conf()defcount(self,value):self.write("SAMP:COUN{}".format(value))definitiate(self):self.write("INIT")defopc(self):self.write("*OPC")defset_aperture(self,value):self.write("{}:APER{}".format(self.mode,value))As you see, this driver is very close to a one-to-one correpondance between
the SPCI commands and the methods. Of course, methods can be more complexe,
however a simplest driver as possible allow more flexiblity.Then classes specific to MeaVis have to be written to decribe how to use this
driver:Drivers: Front panel instrument.MeaVis classes: How an experimentalist use the front panel.importdriversimportmeavis.tags@meavis.tags.initialiser("power_source.current_source",mode="CURR")@meavis.tags.initialiser("power_source.voltage_source",mode="VOLT")classInitialiserB596X:def__init__(self,mode):self.mode=modedefinitialise(self,handler,channel):handler_channel=drivers.AgilentB596X(**handler)handler_channel.set_channel(channel)handler_channel.set_mode(self.mode)handler_channel.output(True)returnhandler_channel@meavis.tags.initialiser("multimeter.ac_current_meter")@meavis.tags.kwargs(mode="CURR",ACorDC="AC")@meavis.tags.initialiser("multimeter.ac_volt_meter")@meavis.tags.kwargs(mode="VOLT",ACorDC="AC")@meavis.tags.initialiser("multimeter.dc_current_meter")@meavis.tags.kwargs(mode="CURR",ACorDC="DC")@meavis.tags.initialiser("multimeter.dc_volt_meter")@meavis.tags.kwargs(mode="VOLT",ACorDC="DC")classInitialiser344XX:def__init__(self,mode,ACorDC):self.ACorDC=ACorDCself.mode=modedefinitialise(self,handler,channel):handler_channel=drivers.KeySight344XX(**handler)handler_channel.conf_mode(self.mode)handler_channel.conf_ACorDC(True)returnhandler_channel@meavis.tags.parameter("power_source.current_source.current")@meavis.tags.attributes(unit="A",delay=0.1)@meavis.tags.parameter("power_source.voltage_source.voltage")@meavis.tags.attributes(unit="V",delay=0.1)classSourceValue:def__init__(self,data):self.data=datadefapply(self,handler,value):handler.set_value(value)@meavis.tags.parameter("multimeter.~.aperture")@meavis.tags.attributes(unit="s")classDMMAperture:def__init__(self,data):self.data=datadefapply(self,handler,value):handler.set_aperture(value)@meavis.tags.parameter("multimeter.~.average_count")classDMMCount:def__init__(self,data):self.data=datadefapply(self,handler,value):handler.count(value)@meavis.tags.measurement("multimeter.ac_current_meter|dc_current_meter.current")@meavis.tags.measurement("multimeter.ac_volt_meter|dc_volt_meter.voltage")classDMMAverage:deftrigger(self,handler):handler.initiate()defwait(self,handler):handler.opc()handler.calc_average()The elements mapped afterkwargswill be used to initialise the
corresponding instrument when required. For exemple, if a source is used as a
voltage source, the statementhandler = meavis_user.InitialiserB596X(mode="VOLT").intialise(/* */)will be
executed.This file have to be loaded as follow:meavis.instruments.inject(meavis_user._meavis_instruments)Note that it cannot be loaded multiple time, otherwise name collisions will
happen.Up to now the configuration is independant of what we want to measure: it only
describes how to use instruments, but not how they are connect or what we want
to do.Experiment-specific configuration of intrumentsFirst we describe how instruments are wired and for which purpose with a YAML
file:junction_bias:instrument:power_sourceusage:voltage_sourcekwargs:addr:192.168.0.0attributes:channel:1junction_current:instrument:multimeterusage:dc_current_meterkwargs:host:192.168.0.1attributes:channel:1junction_voltage:instrument:multimeterusage:dc_volt_meterkwargs:host:192.168.0.1attributes:channel:2The elements mapped afterkwargswill be used to construct the corresponding
instrument when required. For exemple, the multimeter to measure the junction
voltage is constructed with the statement:handler = meavis_user.ConstructorEthernet(host="192.168.0.1").create()when
required. Morevoer the attributechannel: 2is used for the initialisationhandler = meavis_user.InitialiserB596X(/* */).intialise(/* */, channel=2).This file have to be loaded as follow:withopen("instances.yaml")asfile:meavis.instruments.register(yaml.safe_load(file))Note that it cannot be loaded multiple time, otherwise name collisions will
happen. After this step, parameters and measurements can be accessed as
follow:meavis.parameters.junction_current.aperture([10e-3])meavis.parameters.junction_current.average_count([100])meavis.parameters.junction_voltage.aperture([100e-3])meavis.parameters.junction_voltage.average_count([10])Avaibled parameters and measurements are displayed in the log output:INFO --  Register power_source constructor [90e97748d6ea9cbb434602eb177a91c685701667] {host: 192.168.0.0}.
INFO --  Register voltage_source initialiser {mode: VOLT} for junction_bias.
INFO --  Register voltage as parameter named junction_bias.voltage.
INFO --  Register multimeter constructor [1ca226d3ca09e4167fbbfa3bd218a8323d76e12f] {host: 192.168.0.1}.
INFO --  Register dc_current_meter initialiser {mode: CURR, ACorDC: DC} for junction_current.
INFO --  Register aperture as parameter named junction_current.aperture.
INFO --  Register average_count as parameter named junction_current.average_count.
INFO --  Register current as measurement named junction_current.current.
INFO --  Register dc_volt_meter initialiser {mode: VOLT, ACorDC: DC} for junction_voltage.
INFO --  Register aperture as parameter named junction_voltage.aperture.
INFO --  Register average_count as parameter named junction_voltage.average_count.
INFO --  Register voltage as measurement named junction_voltage.voltage.
INFO --  Add completer group for junction_bias : {junction_bias.voltage}.
INFO --  Add completer group for junction_current : {junction_current.average_count, junction_current.aperture}.
INFO --  Add completer group for junction_voltage : {junction_voltage.aperture, junction_voltage.average_count}.And finally the measurement can be described and processed as follow:measurement_loop=meavis.loop.LoopEngine(yaml.safe_load("""parameters:- junction_bias.voltagemeasurements:- junction_current.current- junction_voltage.voltagename: iv_dc_4probes""")).create(meavis.parameters.junction_bias.voltage(numpy.linspace(-1e-3,1e-3,401)),meavis.measurements.junction_current.current(),meavis.measurements.junction_voltage.voltage(),)measurement_loop.trigger(None)measurement_loop.wait(None)In the log output, instruments are created and intialised when required:INFO --  Complete parameters with [junction_current.average_count, junction_current.aperture]
INFO --  Complete parameters with [junction_voltage.aperture, junction_voltage.average_count]
INFO --  Create handler of multimeter.constructor [1ca226d3ca09e4167fbbfa3bd218a8323d76e12f] with {host: 192.168.0.1}.
INFO --  Initialise channel 2 on handler of multimeter.dc_volt_meter.initialiser with {mode: VOLT, ACorDC: DC}.
INFO --  Set junction_voltage.aperture to 0.1 s.
INFO --  Set junction_voltage.average_count to 10.
INFO --  Initialise channel 1 on handler of multimeter.dc_current_meter.initialiser with {mode: CURR, ACorDC: DC}.
INFO --  Set junction_current.aperture to 0.01 s.
INFO --  Set junction_current.average_count to 100.
INFO --  Create handler of power_source.constructor [90e97748d6ea9cbb434602eb177a91c685701667] with {host: 192.168.0.0}.
INFO --  Initialise channel 1 on handler of power_source.voltage_source.initialiser with {mode: VOLT}.
INFO --  Set junction_bias.voltage to -0.001 V.
INFO --  Trigger junction_current.current, waiting for data.
INFO --  Trigger junction_voltage.voltage, waiting for data.
INFO --  Set junction_bias.voltage to -0.000998 V.
INFO --  Trigger junction_current.current, waiting for data.
INFO --  Trigger junction_voltage.voltage, waiting for data.