Qcodes: problem with station and meas.run():
when adding station to the measurement then using the ‘with meas.run( ) as datasaver’ the station does not seem to work. further the station object does not want to return a snapshot either after running the meas.run(), even though it returned it fine earlier in the code.
Here is all the code:
import Qcodes_Keithley213Driver_2 as kd
import qcodes_fluke8842aDriver_2 as fd
import numpy as np
import matplotlib.pyplot as plt
import time
import tempfile
import os
import qcodes
from qcodes import initialise_or_create_database_at, \
load_or_create_experiment, Measurement, Parameter
from qcodes.dataset.plotting import plot_dataset
from qcodes.tests.instrument_mocks import (
DummyInstrument,
DummyInstrumentWithMeasurement
)
keithSource.close()
flukeMeter.close()
keithSource = kd.Keithley213Driver('keithSource','GPIB0::9::INSTR')
flukeMeter = fd.Fluke8842aDriver('fDMMInst1','GPIB0::10::INSTR')
## dac = DummyInstrument('dac', gates=['ch1', 'ch2'])
station = qcodes.Station()
## station.add_component(dac)
## station.add_component(keithSource)
## station.add_component(flukeMeter)
## _=station.snapshot()
## print(_) #returns fine here
initialise_or_create_database_at('C:\\Users\\ehb21173\\Desktop\\transistor test 2\\transistor_tests_2.db')
qcodes.config.core.db_location
exp = load_or_create_experiment(experiment_name='transistor test 1_ IV plots', sample_name='test on 2n7000_2')
meas = Measurement(exp=exp, station=station, name='transistor tests name')
meas.register_parameter(keithSource.ch1.voltage)
meas.register_parameter(keithSource.ch2.voltage)
meas.register_parameter(flukeMeter.voltageDC, setpoints=(keithSource.ch1.voltage, keithSource.ch2.voltage))
keithSource.ch1.maxV(10) # gate
keithSource.ch2.maxV(10) # source
sourceVoltage = np.linspace(0,10,2,endpoint=True)
gateVoltage = np.linspace(1,4,2,endpoint=True)
meas.write_period = 1
with meas.run() as datasaver:
for j in range(len(gateVoltage)):
keithSource.ch1.voltage(gateVoltage[j]) # gate
for i in range(len(sourceVoltage)):
keithSource.ch2.voltage(sourceVoltage[i]) # source
time.sleep(3)
voltage = flukeMeter.voltageDC()
datasaver.add_result((keithSource.ch1.voltage, gateVoltage[j]),
(keithSource.ch2.voltage, sourceVoltage[i]),
(flukeMeter.voltageDC, voltage))
time.sleep(3)
keithSource.ch2.voltage(0)
keithSource.ch1.voltage(0)
time.sleep(3)
dataset = datasaver.dataset
keithSource.ch2.voltage(0)
keithSource.ch1.voltage(0)
keithSource.close()
flukeMeter.close()
####################################################################################################
the error returned is:
RecursionError Traceback (most recent call last)
Input In [138], in <cell line: 9>()
5 # current = np.empty([len(gateVoltage),len(sourceVoltage)])
7 meas.write_period = 1
----> 9 with meas.run() as datasaver:
10 for j in range(len(gateVoltage)):
11 keithSource.ch1.voltage(gateVoltage[j]) # gate
File ~\.conda\envs\drivers\lib\site-packages\qcodes\dataset\measurements.py:601, in Runner.__enter__(self)
598 else:
599 snapshot = {}
--> 601 self.ds.prepare(
602 snapshot=snapshot,
603 interdeps=self._interdependencies,
604 write_in_background=self._write_in_background,
605 shapes=self._shapes,
606 parent_datasets=self._parent_datasets,
607 )
609 # register all subscribers
610 if isinstance(self.ds, DataSet):
File ~\.conda\envs\drivers\lib\site-packages\qcodes\dataset\data_set.py:323, in DataSet.prepare(self, snapshot, interdeps, shapes, parent_datasets, write_in_background)
313 def prepare(
314 self,
315 *,
(...)
320 write_in_background: bool = False,
321 ) -> None:
--> 323 self.add_snapshot(json.dumps({"station": snapshot}, cls=NumpyJSONEncoder))
325 if interdeps == InterDependencies_():
326 raise RuntimeError("No parameters supplied")
File ~\.conda\envs\drivers\lib\json\__init__.py:238, in dumps(obj, skipkeys, ensure_ascii, check_circular, allow_nan, cls, indent, separators, default, sort_keys, **kw)
232 if cls is None:
233 cls = JSONEncoder
234 return cls(
235 skipkeys=skipkeys, ensure_ascii=ensure_ascii,
236 check_circular=check_circular, allow_nan=allow_nan, indent=indent,
237 separators=separators, default=default, sort_keys=sort_keys,
--> 238 **kw).encode(obj)
File ~\.conda\envs\drivers\lib\json\encoder.py:199, in JSONEncoder.encode(self, o)
195 return encode_basestring(o)
196 # This doesn't pass the iterator directly to ''.join() because the
197 # exceptions aren't as detailed. The list call should be roughly
198 # equivalent to the PySequence_Fast that ''.join() would do.
--> 199 chunks = self.iterencode(o, _one_shot=True)
200 if not isinstance(chunks, (list, tuple)):
201 chunks = list(chunks)
File ~\.conda\envs\drivers\lib\json\encoder.py:257, in JSONEncoder.iterencode(self, o, _one_shot)
252 else:
253 _iterencode = _make_iterencode(
254 markers, self.default, _encoder, self.indent, floatstr,
255 self.key_separator, self.item_separator, self.sort_keys,
256 self.skipkeys, _one_shot)
--> 257 return _iterencode(o, 0)
File ~\.conda\envs\drivers\lib\site-packages\qcodes\utils\helpers.py:96, in NumpyJSONEncoder.default(self, obj)
93 elif isinstance(obj, np.ndarray):
94 # for numpy arrays
95 return obj.tolist()
---> 96 elif (isinstance(obj, numbers.Complex) and
97 not isinstance(obj, numbers.Real)):
98 return {
99 '__dtype__': 'complex',
100 're': float(obj.real),
101 'im': float(obj.imag)
102 }
103 elif isinstance(obj, uncertainties.UFloat):
File ~\.conda\envs\drivers\lib\abc.py:119, in ABCMeta.__instancecheck__(cls, instance)
117 def __instancecheck__(cls, instance):
118 """Override for isinstance(instance, cls)."""
--> 119 return _abc_instancecheck(cls, instance)
RecursionError: maximum recursion depth exceeded in comparison
################################################################################################
when not adding station to the measurment everything works fine but, if I try to do station.snapshot() after the meas.run() i get the following error:
AttributeError Traceback (most recent call last)
Input In [145], in <cell line: 1>()
----> 1 flukeMeter.print_readable_snapshot()
File ~\.conda\envs\drivers\lib\site-packages\qcodes\instrument\base.py:296, in InstrumentBase.print_readable_snapshot(self, update, max_chars)
280 """
281 Prints a readable version of the snapshot.
282 The readable snapshot includes the name, value and unit of each
(...)
293 Defaults to 80 to be consistent with default terminal width.
294 """
295 floating_types = (float, np.integer, np.floating)
--> 296 snapshot = self.snapshot(update=update)
298 par_lengths = [len(p) for p in snapshot['parameters']]
300 # Min of 50 is to prevent a super long parameter name to break this
301 # function
File ~\.conda\envs\drivers\lib\site-packages\qcodes\utils\metadata.py:64, in Metadatable.snapshot(self, update)
51 def snapshot(self, update: Optional[bool] = False) -> Dict[Any, Any]:
52 """
53 Decorate a snapshot dictionary with metadata.
54 DO NOT override this method if you want metadata in the snapshot
(...)
61 Base snapshot.
62 """
---> 64 snap = self.snapshot_base(update=update)
66 if len(self.metadata):
67 snap['metadata'] = self.metadata
File ~\.conda\envs\drivers\lib\site-packages\qcodes\instrument\visa.py:261, in VisaInstrument.snapshot_base(self, update, params_to_skip_update)
239 def snapshot_base(self, update: Optional[bool] = True,
240 params_to_skip_update: Optional[Sequence[str]] = None
241 ) -> Dict[Any, Any]:
242 """
243 State of the instrument as a JSON-compatible dict (everything that
244 the custom JSON encoder class :class:`qcodes.utils.helpers.NumpyJSONEncoder`
(...)
259 dict: base snapshot
260 """
--> 261 snap = super().snapshot_base(update=update,
262 params_to_skip_update=params_to_skip_update)
264 snap['address'] = self._address
265 snap['terminator'] = self._terminator
File ~\.conda\envs\drivers\lib\site-packages\qcodes\instrument\base.py:250, in InstrumentBase.snapshot_base(self, update, params_to_skip_update)
245 if params_to_skip_update is None:
246 params_to_skip_update = []
248 snap: Dict[str, Any] = {
249 "functions": {name: func.snapshot(update=update)
--> 250 for name, func in self.functions.items()},
251 "submodules": {name: subm.snapshot(update=update)
252 for name, subm in self.submodules.items()},
253 "parameters": {},
254 "__class__": full_class(self)
255 }
257 for name, param in self.parameters.items():
258 if param.snapshot_exclude:
File ~\.conda\envs\drivers\lib\site-packages\qcodes\utils\helpers.py:417, in DelegateAttributes.__getattr__(self, key)
414 for name in self.delegate_attr_dicts:
415 if key == name:
416 # needed to prevent infinite loops!
--> 417 raise AttributeError(
418 "dict '{}' has not been created in object '{}'".format(
419 key, self.__class__.__name__))
420 try:
421 d = getattr(self, name, None)
AttributeError: dict 'functions' has not been created in object 'Fluke8842aDriver'
################################################################################################
Note that when adding the dummy instrument to the station instead everything works fine so it may be an issue with the driver of the instrument (adding either to the snapshot without the other produces the same issue), here is the driver for the multimeter:
class voltageDC(Parameter):
def __init__(self, name, *args, **kwargs):
# only name is required
super().__init__(name,
docstring='command for measurement of voltage DC', *args, **kwargs)
# you must provide a get method, a set method, or both.
def get_raw(self):
if self.root_instrument.currentMeasConfig != 'V DC':
self.root_instrument.visa_handle.write('F1')
self.root_instrument.currentMeasConfig = 'V DC'
self.root_instrument.visa_handle.write('?')
return self.root_instrument.visa_handle.read_raw()
class CurrentDC(Parameter):
def __init__(self, name, *args, **kwargs):
# only name is required
super().__init__(name,
docstring='command for measurement of voltage DC', *args, **kwargs)
# you must provide a get method, a set method, or both.
def get_raw(self):
if self.root_instrument.currentMeasConfig != 'A DC':
self.root_instrument.visa_handle.write('F5')
self.root_instrument.currentMeasConfig = 'A DC'
self.root_instrument.visa_handle.write('?')
return self.root_instrument.visa_handle.read_raw()
class rate(Parameter):
def __init__(self, name, *args, **kwargs):
# only name is required
super().__init__(name,
docstring='command for measurement of voltage DC', *args, **kwargs)
# you must provide a get method, a set method, or both.
def get_raw(self):
self.root_instrument.visa_handle.write("G0")
config = self.root_instrument.visa_handle.read_raw()
return self.root_instrument.list_of_configs_S[int(str((int(config)))[2])] #change this to dictionary so easier to read
def set_raw(self, speed):
index = self.root_instrument.list_of_configs_S.index(speed)
self.root_instrument.visa_handle.write("S"+str(index))
class Fluke8842aDriver(VisaInstrument):
def __init__(self, name, address, *args,**kwargs):
super().__init__(name, address, terminator="\r\n", *args,**kwargs)
self.currentMeasConfig = 'V DC'
self.list_of_configs_S = ["slow", "med","fast"]
self.add_parameter('voltageDC', parameter_class=voltageDC,get_parser=float, unit='V')
self.add_parameter('currentDC', parameter_class=CurrentDC,get_parser=float, unit='A')
self.add_parameter('rate', parameter_class=rate)
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 37 (7 by maintainers)
I can reproduce this now
Triggers the issue.
The reason is the bytestring in the raw_value. The reason why you are seeing a bytestring here (note the b in from of the string) is that you use visa_handle.read_raw. As @astafan8 suggested above using
instrument.askis a lot better or at the very leastinstrument.visa_handle.readand orinstrument.visa_handle.queryread_rawshould really only be used when you handle the decoding or the raw value in your get_raw your self for strange dataformats that cannot be automatically decoded.That being said qcodes should handle bytestrings in snapshots better.
@jenshnielsen same problem ‘maximum recursion depth exceeded in comparison’.
@jenshnielsen sure, thanks for al the help!
@jenshnielsen here is the code:
and the output:
Could you try json encoding the snapshot of each of the parameters Something like
@astafan8 yep nevermind, same problem after adding the instruments to the station (its both of them btw).
@astafan8 yep still the same problem.
Note that the value of
1.00071e21also shows up as the vendor of the instrument so it seems like there is a potential issue with the instrumets implementation of*IDNtoo