This page was generated from docs/examples/driver_examples/QCoDeS example with Keithley 3706A System Switch.ipynb. Interactive online version: .
QCoDeS example with Keithley 3706A System Switch¶
This is the example notebook that presents the features of the QCoDeS driver for Keithley 3706A-SNFP System Switch with 3730 6x16 High Density Matrix. The model 3706A-SNFP has no DMM capabilities. However, users who are in possession of models with DMM capabilities can use the present driver for switch operations.
Basic Operation¶
Let us, first, import QCoDeS driver for the Keithley System Switch:
[1]:
import qcodes as qc
from qcodes.instrument_drivers.Keithley import Keithley3706A
Now, we create a station to hold our instrument:
[2]:
station = qc.Station()
We finalize the initialization of the instrument by instantiation and then adding it to the station:
[3]:
smatrix = Keithley3706A("smatrix", address="USB0::0x05E6::0x3706::04447336::INSTR")
station.add_component(smatrix)
Connected to: KEITHLEY INSTRUMENTS INC. 3706A-SNFP SYSTEM SWITCH (serial:04447336, firmware:01.56a)
Slot 1- Model:3730, Matrix Type:6x16 High Density Matrix, Firmware:01.40h, Serial:4447332
Slot 2- Model:3730, Matrix Type:6x16 High Density Matrix, Firmware:01.40h, Serial:4398982
Slot 3- Model:3730, Matrix Type:6x16 High Density Matrix, Firmware:01.40h, Serial:4447333
Interlock is disengaged in Slot 1.
Interlock is disengaged in Slot 2.
Interlock is disengaged in Slot 3.
[3]:
'smatrix'
Here, the driver not only shows information about the hardware specifications we have, but also reminds us about the interlocks. The channel relays can continue to operate even if the interlock in the corresponding slot is disengaged, however, one cannot perform measurements through the switching card, as the analog backplanes cannot be energized. Specific warnings shall be issued in related function calls as well. Now, let us continue to examine the properties of our instrument via its snapshot:
[4]:
smatrix.print_readable_snapshot()
smatrix:
parameter value
--------------------------------------------------------------------------------
IDN : {'vendor': 'KEITHLEY INSTRUMENTS INC.', 'model': '3706...
channel_connect_rule : BREAK_BEFORE_MAKE
gpib_address : 12
gpib_enabled : True
lan_enabled : True
timeout : 5 (s)
Connection types¶
System switch can be connected to a setup through USB, LAN as well as GPIB. Depending on the needs, one can enable (disable) LAN and/or GPIB connections.
[5]:
smatrix.gpib_enabled(False)
[6]:
smatrix.lan_enabled(False)
[7]:
smatrix.print_readable_snapshot()
smatrix:
parameter value
--------------------------------------------------------------------------------
IDN : {'vendor': 'KEITHLEY INSTRUMENTS INC.', 'model': '3706...
channel_connect_rule : BREAK_BEFORE_MAKE
gpib_address : 12
gpib_enabled : False
lan_enabled : False
timeout : 5 (s)
[8]:
smatrix.gpib_enabled(True)
[9]:
smatrix.lan_enabled(True)
GPIB connection address can be changed at will. An integer value in between 1
and 30
can be assigned via:
[10]:
smatrix.gpib_address(12)
[11]:
smatrix.print_readable_snapshot()
smatrix:
parameter value
--------------------------------------------------------------------------------
IDN : {'vendor': 'KEITHLEY INSTRUMENTS INC.', 'model': '3706...
channel_connect_rule : BREAK_BEFORE_MAKE
gpib_address : 12
gpib_enabled : True
lan_enabled : True
timeout : 5 (s)
If an invalid address is passed as an argument, QCoDeS shall rise an error and the present address shall be preserved.
[12]:
smatrix.gpib_address(31)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-12-a8e26381bdb1> in <module>
----> 1 smatrix.gpib_address(31)
c:\users\a-alhard\repos\qcodes\qcodes\instrument\parameter.py in __call__(self, *args, **kwargs)
408 else:
409 if hasattr(self, 'set'):
--> 410 self.set(*args, **kwargs)
411 return None
412 else:
c:\users\a-alhard\repos\qcodes\qcodes\instrument\parameter.py in set_wrapper(value, **kwargs)
646 except Exception as e:
647 e.args = e.args + ('setting {} to {}'.format(self, value),)
--> 648 raise e
649
650 return set_wrapper
c:\users\a-alhard\repos\qcodes\qcodes\instrument\parameter.py in set_wrapper(value, **kwargs)
606 def set_wrapper(value: ParamDataType, **kwargs: Any) -> None:
607 try:
--> 608 self.validate(value)
609
610 # In some cases intermediate sweep values must be used.
c:\users\a-alhard\repos\qcodes\qcodes\instrument\parameter.py in validate(self, value)
705 context = self.name
706 if self.vals is not None:
--> 707 self.vals.validate(value, 'Parameter: ' + context)
708
709 @property
c:\users\a-alhard\repos\qcodes\qcodes\utils\validators.py in validate(self, value, context)
340 '{} is invalid: must be between '
341 '{} and {} inclusive; {}'.format(
--> 342 repr(value), self._min_value, self._max_value, context))
343
344 is_numeric = True
ValueError: ('31 is invalid: must be between 1 and 30 inclusive; Parameter: smatrix.gpib_address', 'setting smatrix_gpib_address to 31')
If the preferred connection method is LAN, one can querry the IP address of the instrument through the driver.
[13]:
smatrix.get_ip_address()
[13]:
'0.0.0.0'
Here, the returned address is the default value if there is no LAN connection; indeed in this example we are connected to the instrument via USB. In cases where a reset to the LAN is required, a simple function call is sufficient:
[14]:
smatrix.reset_local_network()
Identifications¶
While QCoDeS prints out the instrument identifications including the installed matrix types upon a successfull connection, these metadata can be queried later on, as well.
[15]:
smatrix.get_idn()
[15]:
{'vendor': 'KEITHLEY INSTRUMENTS INC.',
'model': '3706A-SNFP',
'serial': '04447336',
'firmware': '01.56a'}
[16]:
smatrix.get_switch_cards()
[16]:
({'slot_no': '1',
'model': '3730',
'mtype': '6x16 High Density Matrix',
'firmware': '01.40h',
'serial': '4447332'},
{'slot_no': '2',
'model': '3730',
'mtype': '6x16 High Density Matrix',
'firmware': '01.40h',
'serial': '4398982'},
{'slot_no': '3',
'model': '3730',
'mtype': '6x16 High Density Matrix',
'firmware': '01.40h',
'serial': '4447333'})
Save and load setups, memory management¶
The system switch provides an option for the users to save their current setups to be used later. One can save a configuration either to the non-volatile memory of the instrument or to a USB drive. To this end, we use save_setup()
function which either takes no arguments or a string which represents the path and the file name to which the setup shall be saved on an external drive. If no arguments provided, the setup shall be saved to the intstument. Note that, in the latter case, any
existing saved configurations shall be overwritten.
[17]:
smatrix.save_setup()
We can recall saved setups via load_setup()
function. It takes a single argument: If it is 0
, factory defaults load, if it is 1
, the saved setup from the nonvolatile memory is recalled. Otherwise, a string specifying the relative path to the saved setup on a USB drive should be passed in.
[18]:
smatrix.load_setup(0)
[19]:
smatrix.load_setup(1)
The system switch has limited memory which can be queried via:
[20]:
smatrix.get_available_memory()
[20]:
{'System Memory (%)': '89.64',
'Script Memory (%)': '100.00',
'Pattern Memory (%)': '100.00',
'Config Memory (%)': '100.00'}
The memory usage of a saved setup is depicted by the Config Memory
. User given channel patterns occupy the Pattern Memory
. The system switch is capable of storing and running Lua scripts. This functionality is not explicitly implemented by the QCoDeS driver. However, if desired, one can still send, save and execute Lua scripts through write()
and ask()
methods of the InstrumentBase
class of QCoDeS which is inherited by every instrument driver. If this is the case, the saved
Lua scripts occupy the Script Memory
.
Channel Control and Manipulations¶
Channel Specifiers¶
First, let us call the installed switch cards again:
[21]:
smatrix.get_switch_cards()
[21]:
({'slot_no': '1',
'model': '3730',
'mtype': '6x16 High Density Matrix',
'firmware': '01.40h',
'serial': '4447332'},
{'slot_no': '2',
'model': '3730',
'mtype': '6x16 High Density Matrix',
'firmware': '01.40h',
'serial': '4398982'},
{'slot_no': '3',
'model': '3730',
'mtype': '6x16 High Density Matrix',
'firmware': '01.40h',
'serial': '4447333'})
The system switch has six available slots from which three are currently occupied by 6x16
high density matrices. As implied, these matrices have 6
rows and 16
columns, hence, in total, 96
available channels, each.
Each channel has identical properties but unique names. The properties of the channels can be manipulated via calling them individually, as a group or as a whole slot. The naming of the channels follows a general pattern. In particular, here for the model 3730
which has no bank
, the names starts with the slot number, then the row number and finally follows the cloumn number which should always be two characters. For example, 1101
represents the channel at Slot 1
, Row 1
and
Column 1
. For other models, users should refer to the corresponding instrument manual.
In certain cases manual deduction of the name of the channel could be more efficient. On the other hand, user can easily query the available channels as follows:
[22]:
smatrix.get_channels()
[22]:
['1101',
'1102',
'1103',
'1104',
'1105',
'1106',
'1107',
'1108',
'1109',
'1110',
'1111',
'1112',
'1113',
'1114',
'1115',
'1116',
'1201',
'1202',
'1203',
'1204',
'1205',
'1206',
'1207',
'1208',
'1209',
'1210',
'1211',
'1212',
'1213',
'1214',
'1215',
'1216',
'1301',
'1302',
'1303',
'1304',
'1305',
'1306',
'1307',
'1308',
'1309',
'1310',
'1311',
'1312',
'1313',
'1314',
'1315',
'1316',
'1401',
'1402',
'1403',
'1404',
'1405',
'1406',
'1407',
'1408',
'1409',
'1410',
'1411',
'1412',
'1413',
'1414',
'1415',
'1416',
'1501',
'1502',
'1503',
'1504',
'1505',
'1506',
'1507',
'1508',
'1509',
'1510',
'1511',
'1512',
'1513',
'1514',
'1515',
'1516',
'1601',
'1602',
'1603',
'1604',
'1605',
'1606',
'1607',
'1608',
'1609',
'1610',
'1611',
'1612',
'1613',
'1614',
'1615',
'1616',
'2101',
'2102',
'2103',
'2104',
'2105',
'2106',
'2107',
'2108',
'2109',
'2110',
'2111',
'2112',
'2113',
'2114',
'2115',
'2116',
'2201',
'2202',
'2203',
'2204',
'2205',
'2206',
'2207',
'2208',
'2209',
'2210',
'2211',
'2212',
'2213',
'2214',
'2215',
'2216',
'2301',
'2302',
'2303',
'2304',
'2305',
'2306',
'2307',
'2308',
'2309',
'2310',
'2311',
'2312',
'2313',
'2314',
'2315',
'2316',
'2401',
'2402',
'2403',
'2404',
'2405',
'2406',
'2407',
'2408',
'2409',
'2410',
'2411',
'2412',
'2413',
'2414',
'2415',
'2416',
'2501',
'2502',
'2503',
'2504',
'2505',
'2506',
'2507',
'2508',
'2509',
'2510',
'2511',
'2512',
'2513',
'2514',
'2515',
'2516',
'2601',
'2602',
'2603',
'2604',
'2605',
'2606',
'2607',
'2608',
'2609',
'2610',
'2611',
'2612',
'2613',
'2614',
'2615',
'2616',
'3101',
'3102',
'3103',
'3104',
'3105',
'3106',
'3107',
'3108',
'3109',
'3110',
'3111',
'3112',
'3113',
'3114',
'3115',
'3116',
'3201',
'3202',
'3203',
'3204',
'3205',
'3206',
'3207',
'3208',
'3209',
'3210',
'3211',
'3212',
'3213',
'3214',
'3215',
'3216',
'3301',
'3302',
'3303',
'3304',
'3305',
'3306',
'3307',
'3308',
'3309',
'3310',
'3311',
'3312',
'3313',
'3314',
'3315',
'3316',
'3401',
'3402',
'3403',
'3404',
'3405',
'3406',
'3407',
'3408',
'3409',
'3410',
'3411',
'3412',
'3413',
'3414',
'3415',
'3416',
'3501',
'3502',
'3503',
'3504',
'3505',
'3506',
'3507',
'3508',
'3509',
'3510',
'3511',
'3512',
'3513',
'3514',
'3515',
'3516',
'3601',
'3602',
'3603',
'3604',
'3605',
'3606',
'3607',
'3608',
'3609',
'3610',
'3611',
'3612',
'3613',
'3614',
'3615',
'3616']
The get_channels()
function returns an array of strings each being the name of an available channel in all occupied slots. The return type being string
is intentional as the instrument accepts the channel names as strings and not integers during any manipulation. Thus, any element(s) of this list can be safely passed as an argument to another function which specifies a channel property.
If desired, the available channels in a given slot can be queried, as well.
[23]:
smatrix.get_channels_by_slot(1)
[23]:
['1101',
'1102',
'1103',
'1104',
'1105',
'1106',
'1107',
'1108',
'1109',
'1110',
'1111',
'1112',
'1113',
'1114',
'1115',
'1116',
'1201',
'1202',
'1203',
'1204',
'1205',
'1206',
'1207',
'1208',
'1209',
'1210',
'1211',
'1212',
'1213',
'1214',
'1215',
'1216',
'1301',
'1302',
'1303',
'1304',
'1305',
'1306',
'1307',
'1308',
'1309',
'1310',
'1311',
'1312',
'1313',
'1314',
'1315',
'1316',
'1401',
'1402',
'1403',
'1404',
'1405',
'1406',
'1407',
'1408',
'1409',
'1410',
'1411',
'1412',
'1413',
'1414',
'1415',
'1416',
'1501',
'1502',
'1503',
'1504',
'1505',
'1506',
'1507',
'1508',
'1509',
'1510',
'1511',
'1512',
'1513',
'1514',
'1515',
'1516',
'1601',
'1602',
'1603',
'1604',
'1605',
'1606',
'1607',
'1608',
'1609',
'1610',
'1611',
'1612',
'1613',
'1614',
'1615',
'1616']
Backplane Specifiers¶
Each matrix has typically six analog backplane relays which can be associated which a channel(s). The naming scheme of the relays are similar to that of the channels. Each name start with the slot number, continues with 9
, which is the unique backplane number, and then finishes with backplane relay identifier which can take the values 11
, 12
, …, 16
. That is, we can select the backplane relay 12
on Slot 3
via 3912
.
Unless a backplane is associated with a channel, the instrument does not return the names of the relays. This is overcomed within the QCoDeS driver, so that user can list the available analog backplane relays.
[24]:
smatrix.get_analog_backplane_specifiers()
[24]:
['1911',
'1912',
'1913',
'1914',
'1915',
'1916',
'2911',
'2912',
'2913',
'2914',
'2915',
'2916',
'3911',
'3912',
'3913',
'3914',
'3915',
'3916']
Control and manipulations¶
The switch channels as well as the analog backplane relays can be controlled via a set of well defined functions. First, a channel can be opened and closed, as expected.
[25]:
smatrix.open_channel("1101")
We can provide a list of channels as an argument. In this case, channel names should be provided as a single string, seperated with a comma and no blank spaces.
[26]:
smatrix.open_channel("1103,2111")
We can provide a channel range via slicing. The following call opens the channels from 3101
to 3116
.
[27]:
smatrix.open_channel("3101:3116")
We can open all the channels in a slot by passing slotX
where X=1,...,6
representing the slot id. In our case, X
can be 1
, 2
or 3
.
[28]:
smatrix.open_channel("slot2")
Finally, we can open all channels in all slots via:
[29]:
smatrix.open_channel("allslots")
Let us reset everything to factory defaults.
[30]:
smatrix.reset_channel("allslots")
The reset_channel()
function can take the name of a single channel, a channel list, range or a slot, as well.
We continue with closing the desired channels. In this case, one cannot pass slot ids or allslots
as the argument; it is not possible to close slots all together, simultaneously.
[31]:
smatrix.close_channel("1101")
[32]:
smatrix.close_channel("2111,3216")
We can query the closed channels.
[33]:
smatrix.get_closed_channels("allslots")
[33]:
['1101', '2111', '3216']
[34]:
smatrix.get_closed_channels("slot2")
[34]:
['2111']
We can exclusively close channels, as well. In one of the two ways to achieve exclusive close of channels, we specify channels to be closed in such a way that any presently closed channels in all slots open if they are not included to list.
Currently we know that the channels 1101
, 2111
and 3216
are closed. Now, let us close the channel 3101
exclusively and then query close channels. We expect to only see the latter and the former channels should be opened.
[35]:
smatrix.exclusive_close("3101")
[36]:
smatrix.get_closed_channels("allslots")
[36]:
['3101']
Second way to exclusively close channels is similar to that of our previous example. We now exclusively close the specified channels on the associated slots. Other channels are opened if they are not specified by the parameter within the same slot, while the other slots remain untouched. Currently the only closed channel is 3101
. Let close, exclusively, 2101
and 2216
. Also, let us close the channel 2111
genericaly. We expect the channel 2111
opens while the channel 3101
remains closed.
[37]:
smatrix.close_channel("2111")
[38]:
smatrix.exclusive_slot_close("2101,2216")
[39]:
smatrix.get_closed_channels("allslots")
[39]:
['2101', '2216', '3101']
We can control connection rules for closing and opening channels when using the exclusive_close()
and exlusive_slot_close()
functions. The three valid rules are BREAK_BEFORE_MAKE
, MAKE_BEFORE_BREAK
and OFF
. The default rule is BREAK_BEFORE_MAKE
.
[40]:
smatrix.channel_connect_rule()
[40]:
'BREAK_BEFORE_MAKE'
If the connection rule is set to BREAK_BEFORE_MAKE
, it is ensured that all channels open before any channels close. If it is set to MAKE_BEFORE_BREAK
, it is ensured that all channels close before any channels open. Finally, if it is set to OFF
, channels open and close, simultaneously.
[41]:
smatrix.channel_connect_rule("MAKE_BEFORE_BREAK")
[42]:
smatrix.channel_connect_rule()
[42]:
'MAKE_BEFORE_BREAK'
[43]:
smatrix.channel_connect_rule("OFF")
[44]:
smatrix.channel_connect_rule()
[44]:
'OFF'
Note that, resetting channels to factory defaults will not change the connection rule:
[45]:
smatrix.reset_channel("allslots")
[46]:
smatrix.channel_connect_rule()
[46]:
'OFF'
[47]:
smatrix.channel_connect_rule("BREAK_BEFORE_MAKE")
[48]:
smatrix.channel_connect_rule()
[48]:
'BREAK_BEFORE_MAKE'
In certain cases, we may want to keep certain channels always open. We can achieve desired behavior by setting the specified channels (and analog backplane relays) as forbidden
to close.
[49]:
smatrix.set_forbidden_channels("1101:1105")
[50]:
smatrix.get_forbidden_channels("allslots")
[50]:
'1101,1102,1103,1104,1105'
These channels cannot be closed:
[51]:
smatrix.close_channel("1101")
C:\Users\a-alhard\anaconda3\envs\qcodes\lib\site-packages\ipykernel_launcher.py:1: UserWarning: You are attempting to close channels that are forbidden to close.
"""Entry point for launching an IPython kernel.
[52]:
smatrix.get_closed_channels("slot1")
We can forbid entire slots to be closed. In this case, the analog backplane relays of the corresponding slot shall be flagged as forbidden, as well.
[53]:
smatrix.set_forbidden_channels("slot2")
[54]:
smatrix.get_forbidden_channels("allslots")
[54]:
'1101,1102,1103,1104,1105,2101,2102,2103,2104,2105,2106,2107,2108,2109,2110,2111,2112,2113,2114,2115,2116,2201,2202,2203,2204,2205,2206,2207,2208,2209,2210,2211,2212,2213,2214,2215,2216,2301,2302,2303,2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2401,2402,2403,2404,2405,2406,2407,2408,2409,2410,2411,2412,2413,2414,2415,2416,2501,2502,2503,2504,2505,2506,2507,2508,2509,2510,2511,2512,2513,2514,2515,2516,2601,2602,2603,2604,2605,2606,2607,2608,2609,2610,2611,2612,2613,2614,2615,2616,2911,2912,2913,2914,2915,2916'
We can clear the forbidden list when we desire to do so.
[55]:
smatrix.clear_forbidden_channels("slot1")
[56]:
smatrix.get_forbidden_channels("allslots")
[56]:
'2101,2102,2103,2104,2105,2106,2107,2108,2109,2110,2111,2112,2113,2114,2115,2116,2201,2202,2203,2204,2205,2206,2207,2208,2209,2210,2211,2212,2213,2214,2215,2216,2301,2302,2303,2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2401,2402,2403,2404,2405,2406,2407,2408,2409,2410,2411,2412,2413,2414,2415,2416,2501,2502,2503,2504,2505,2506,2507,2508,2509,2510,2511,2512,2513,2514,2515,2516,2601,2602,2603,2604,2605,2606,2607,2608,2609,2610,2611,2612,2613,2614,2615,2616,2911,2912,2913,2914,2915,2916'
[57]:
smatrix.clear_forbidden_channels("2911,2912,2916")
[58]:
smatrix.get_forbidden_channels("slot2")
[58]:
'2101,2102,2103,2104,2105,2106,2107,2108,2109,2110,2111,2112,2113,2114,2115,2116,2201,2202,2203,2204,2205,2206,2207,2208,2209,2210,2211,2212,2213,2214,2215,2216,2301,2302,2303,2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2401,2402,2403,2404,2405,2406,2407,2408,2409,2410,2411,2412,2413,2414,2415,2416,2501,2502,2503,2504,2505,2506,2507,2508,2509,2510,2511,2512,2513,2514,2515,2516,2601,2602,2603,2604,2605,2606,2607,2608,2609,2610,2611,2612,2613,2614,2615,2616,2913,2914,2915'
[59]:
smatrix.clear_forbidden_channels("slot2")
[60]:
smatrix.get_forbidden_channels("allslots")
[60]:
'nil'
Finally, we can set additional delay times to specified channels. The delays should be provided in seconds.
[61]:
smatrix.set_delay("1101", 1)
[62]:
smatrix.get_delay("1101")
[62]:
[1.0]
[63]:
smatrix.set_delay("slot2", 2)
[64]:
smatrix.get_delay("slot2")
[64]:
[2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0,
2.0]
We can use reset_channel()
function to set delay times to defalult value of 0
[65]:
smatrix.reset_channel("allslots")
[66]:
smatrix.get_delay("allslots")
[66]:
[0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0]
We can, conveniently, connect (disconnect) given rows (columns) of a slot to a column (row) of the same slot via the functions connect_or_disconnect_row_to_columns()
and connect_or_disconnect_column_to_rows()
. Each function takes an action as its first argument. The action should be either connect
or disconnect
. The slot id is provided as the second argument. The connect_or_disconnect_row_to_columns()
takes the row number as the third argument to which the desired cloumns,
specified by the final argument as a list, will be connected. Likewise, the connect_or_disconnect_column_to_rows()
takes the column number as the third argument to which the desired rows, specified by the final argument as a list, will be connected.
Both functions opens (closes) the formed channels automatically and returns their list which can be used for later use, if desired. Let us, first, connect 1
, 2
and 13
columns of slot2
to the row 3
of the same slot.
[67]:
channels = smatrix.connect_or_disconnect_row_to_columns("connect", 2, 3, [1, 2, 13])
[68]:
channels
[68]:
['2301', '2302', '2313']
The channels of the matrix returned are now opened. Let us flag these channels as forbidden to close:
[69]:
for channel in channels:
smatrix.set_forbidden_channels(channel)
[70]:
smatrix.get_forbidden_channels("allslots")
[70]:
'2301,2302,2313'
Similarly, let us disconnect the rows 1
, 2
and 4
of slot1
to the column 16
of the same slot:
[71]:
channels = smatrix.connect_or_disconnect_column_to_rows("disconnect", 1, 16, [1, 2, 4])
[72]:
channels
[72]:
['1116', '1216', '1416']
[73]:
smatrix.get_closed_channels("slot1")
[73]:
['1116', '1216', '1416']
Association of Backplanes¶
We can set specific analog backplane relays to desired channels so that they can be utilized in switching applications. Note that the driver will correctly warn us as the slots are disengaged.
[74]:
smatrix.set_backplane("1101:1109", "1916")
C:\Users\a-alhard\anaconda3\envs\qcodes\lib\site-packages\ipykernel_launcher.py:1: UserWarning: The hardware interlock in Slot 1 is disengaged. The corresponding analog backplane relays cannot be energized.
"""Entry point for launching an IPython kernel.
C:\Users\a-alhard\anaconda3\envs\qcodes\lib\site-packages\ipykernel_launcher.py:1: UserWarning: The hardware interlock in Slot 2 is disengaged. The corresponding analog backplane relays cannot be energized.
"""Entry point for launching an IPython kernel.
C:\Users\a-alhard\anaconda3\envs\qcodes\lib\site-packages\ipykernel_launcher.py:1: UserWarning: The hardware interlock in Slot 3 is disengaged. The corresponding analog backplane relays cannot be energized.
"""Entry point for launching an IPython kernel.
[75]:
smatrix.get_backplane("1101")
[75]:
'1916'
[76]:
smatrix.get_backplane("slot1")
[76]:
'1916;1916;1916;1916;1916;1916;1916;1916;1916'
We can clear the association via resetting the corresponding channels (or all channels).
[77]:
smatrix.reset_channel("1101:1109")
[78]:
smatrix.get_backplane("slot1")
[78]:
'nil'
Exceptions¶
The instrument itself does not return any error messages if it encounters an exception, but, rather silently handles such situations. Thus, QCoDeS driver is equipped with validation and exception handling with informative error messages for probable scenerios.
Here, we note some important cases where errors are generated if:
- A non existing channel or slot passed as an argument to a function
- Slots are passed as arguments of `close_channel()`, `exclusive_close()` and `exclusive_slot_close()`
- A delay time is tried to be set for analog backplane relays
- A channel name is used to set as a backplane instead of a backplane name in `set_backplane()` and vice versa
[ ]: