From 18aa323f1826cb0c798212a15915b49ea2825173 Mon Sep 17 00:00:00 2001 From: Natalie Pearson Date: Tue, 2 Aug 2016 18:47:49 +0200 Subject: [PATCH 001/180] feature: initial commit for ATS9360 alazar driver. Generalise ATS.py and debugging. Changes to example notebook. Add specific ATS9360.py file for board settings. nb in this commit there is no use of the acquisition controller --- docs/examples/Qcodes example ATS_ONWORK.ipynb | 219 +++++++++++--- qcodes/instrument_drivers/AlazarTech/ATS.py | 234 ++++++++++----- .../instrument_drivers/AlazarTech/ATS9360.py | 282 ++++++++++++++++++ .../AlazarTech/ATS_acquisition_controllers.py | 13 +- 4 files changed, 639 insertions(+), 109 deletions(-) create mode 100644 qcodes/instrument_drivers/AlazarTech/ATS9360.py diff --git a/docs/examples/Qcodes example ATS_ONWORK.ipynb b/docs/examples/Qcodes example ATS_ONWORK.ipynb index dd3004c89bb7..206812252a0a 100644 --- a/docs/examples/Qcodes example ATS_ONWORK.ipynb +++ b/docs/examples/Qcodes example ATS_ONWORK.ipynb @@ -7,6 +7,14 @@ "collapsed": false }, "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "C:\\Anaconda3\\lib\\site-packages\\IPython\\kernel\\__init__.py:13: ShimWarning: The `IPython.kernel` package has been deprecated. You should import from ipykernel or jupyter_client instead.\n", + " \"You should import from ipykernel or jupyter_client instead.\", ShimWarning)\n" + ] + }, { "data": { "application/javascript": [ @@ -357,6 +365,8 @@ "import time\n", "import numpy as np\n", "\n", + "from imp import reload\n", + "\n", "import qcodes as qc\n", "\n", "qc.halt_bg()\n", @@ -373,21 +383,32 @@ "metadata": { "collapsed": false }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "import qcodes.instrument_drivers.AlazarTech.ATS9870 as ATSdriver\n", - "import qcodes.instrument_drivers.AlazarTech.ATS_acquisition_controllers as ats_contr" + "import qcodes.instrument_drivers.AlazarTech.ATS9360 as ATSdriver; reload(ATSdriver)\n", + "#import qcodes.instrument_drivers.AlazarTech.ATS_acquisition_controllers as ats_contr" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { - "collapsed": true + "collapsed": false }, "outputs": [], "source": [ - "contr1 = ats_contr.DFT_AcquisitionController(demodulation_frequency=10e6)" + "#contr1 = ats_contr.DFT_AcquisitionController(demodulation_frequency=10e6)" ] }, { @@ -398,7 +419,7 @@ }, "outputs": [], "source": [ - "ats_inst = ATSdriver.AlazarTech_ATS9870(name='Alazar1')" + "ats_inst = ATSdriver.AlazarTech_ATS9360(name='Alazar1', server_name=None)" ] }, { @@ -407,43 +428,143 @@ "metadata": { "collapsed": false }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "AlazarSetCaptureClock\n", + "512\n", + "\n", + "AlazarInputControl\n", + "512\n", + "\n", + "AlazarInputControl\n", + "512\n", + "\n", + "AlazarSetTriggerOperation\n", + "512\n", + "\n", + "AlazarSetExternalTrigger\n", + "512\n", + "\n", + "AlazarSetTriggerDelay\n", + "512\n", + "\n", + "AlazarSetTriggerTimeOut\n", + "512\n" + ] + } + ], "source": [ "ats_inst.config(clock_source='INTERNAL_CLOCK',\n", - " sample_rate=1000000,\n", + " sample_rate=500000000,\n", " clock_edge='CLOCK_EDGE_RISING',\n", " decimation=0,\n", - " coupling=['AC','AC'],\n", - " channel_range=[2.,2.],\n", - " impedance=[50,50],\n", - " bwlimit=['DISABLED','DISABLED'],\n", + " coupling=['DC','DC'],\n", + " channel_range=[0.4, 0.4],\n", " trigger_operation='TRIG_ENGINE_OP_J',\n", " trigger_engine1='TRIG_ENGINE_J',\n", " trigger_source1='EXTERNAL',\n", " trigger_slope1='TRIG_SLOPE_POSITIVE',\n", - " trigger_level1=0,\n", + " trigger_level1=150,\n", " trigger_engine2='TRIG_ENGINE_K',\n", - " trigger_source2='CHANNEL_B',\n", + " trigger_source2='DISABLE',\n", " trigger_slope2='TRIG_SLOPE_POSITIVE',\n", - " trigger_level2=0,\n", - " external_trigger_coupling='AC',\n", - " external_trigger_range='ETR_1V',\n", + " trigger_level2=128,\n", + " external_trigger_coupling='DC',\n", + " external_trigger_range='ETR_5V',\n", " trigger_delay=0,\n", " timeout_ticks=0)" ] }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 6, "metadata": { - "collapsed": false + "collapsed": false, + "scrolled": false }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "AlazarAbortAsyncRead\n", + "512\n", + "\n", + "AlazarSetRecordSize\n", + "512\n", + "\n", + "AlazarBeforeAsyncRead\n", + "512\n", + "\n", + "AlazarGetChannelInfo\n", + "512\n", + "bytes per sample 2\n", + "samples_per_record is 1024\n", + "bytes per record is 2048\n", + "samples_per_buffer is 10240\n", + "bytes_per_buffer is 40960\n", + "buffers cleared\n", + "2allocated buffers\n", + "making DMA buffer\n", + "making DMA buffer\n", + "made buffer list length 2\n", + "138543104\n", + "\n", + "\n", + "AlazarPostAsyncBuffer\n", + "512\n", + "138608640\n", + "\n", + "\n", + "AlazarPostAsyncBuffer\n", + "512\n", + "completed AlazarPostAsyncBuffer\n", + "\n", + "AlazarStartCapture\n", + "512\n", + "Capturing 3 buffers.\n", + "\n", + "AlazarWaitAsyncBufferComplete\n", + "518\n", + "[31136 36320 31360 ..., 28736 32480 28832]\n", + "\n", + "AlazarPostAsyncBuffer\n", + "518\n", + "\n", + "AlazarWaitAsyncBufferComplete\n", + "518\n", + "[31136 36320 31360 ..., 28736 32480 28832]\n", + "\n", + "AlazarPostAsyncBuffer\n", + "518\n", + "\n", + "AlazarWaitAsyncBufferComplete\n", + "518\n", + "[31136 36320 31360 ..., 28736 32480 28832]\n", + "\n", + "AlazarPostAsyncBuffer\n", + "518\n", + "\n", + "AlazarAbortAsyncRead\n", + "512\n", + "buffers cleared\n", + "Capture completed in 0.026781 sec\n", + "Captured 3 buffers (112.018308 buffers per sec)\n", + "Captured 30 records (1120.183076 records per sec)\n", + "Transferred 122880 bytes (4588269.880869 bytes per sec)\n" + ] + } + ], "source": [ - "output = ats_inst.acquire(mode='NPT',\n", + "ats_inst.acquire(mode='NPT',\n", " samples_per_record=1024,\n", - " records_per_buffer=70,\n", - " buffers_per_acquisition=128,\n", + " records_per_buffer=10,\n", + " buffers_per_acquisition=3,\n", " channel_selection='AB',\n", " transfer_offset=0,\n", " external_startcapture='DISABLED',\n", @@ -452,35 +573,59 @@ " fifo_only_streaming='DISABLED',\n", " interleave_samples='DISABLED',\n", " get_processed_data='ENABLED',\n", - " allocated_buffers=None,\n", - " buffer_timeout=1000,\n", - " acquisition_controller=contr1)" + " allocated_buffers=2,\n", + " buffer_timeout=10,\n", + " acquisition_controller=None)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "buffers cleared\n" + ] + } + ], + "source": [ + "ats_inst.clear_buffers()" ] }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "AlazarGetChannelInfo\n", + "512\n" + ] + }, { "data": { "text/plain": [ - "[1.2225695082720591,\n", - " 1.216472639837185,\n", - " -179.9999999998654,\n", - " -179.99999999986107,\n", - " 359.9999999999957]" + "{'bits_per_sample': 12, 'board': 'ATS9360', 'max_samples': 4294967294}" ] }, - "execution_count": 9, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "output" + "ats_inst.get_idn()" ] }, { @@ -496,9 +641,9 @@ "metadata": { "anaconda-cloud": {}, "kernelspec": { - "display_name": "Python [Root]", + "display_name": "Python 3", "language": "python", - "name": "Python [Root]" + "name": "python3" }, "language_info": { "codemirror_mode": { @@ -510,7 +655,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.2" + "version": "3.5.1" } }, "nbformat": 4, diff --git a/qcodes/instrument_drivers/AlazarTech/ATS.py b/qcodes/instrument_drivers/AlazarTech/ATS.py index 53dcb11d24c3..463664163c94 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS.py @@ -1,6 +1,7 @@ import ctypes import logging import numpy as np +import time import os from qcodes.instrument.base import Instrument @@ -10,7 +11,6 @@ # TODO (C) logging # these items are important for generalizing this code to multiple alazar cards -# TODO (W) remove 8 bits per sample requirement # TODO (W) some alazar cards have a different number of channels :( # this driver only works with 2-channel cards @@ -18,6 +18,11 @@ # acquisition that would overflow the board if measurement is not stopped # quickly enough. can this be solved by not reposting the buffers? +# TODO: check 8 bit sample thing works +# TODO: test get_board_info and find_boards +# TODO: remove guerilla debuggung 'print' statements +# TODO: call_dll error handling +# TODO: acquisition_controller class AlazarTech_ATS(Instrument): # override dll_path in your init script or in the board constructor @@ -188,8 +193,13 @@ def get_board_info(cls, dll, system_id, board_id): def __init__(self, name, system_id=1, board_id=1, dll_path=None, **kwargs): super().__init__(name, **kwargs) - self._ATS_dll = ctypes.cdll.LoadLibrary(dll_path or self.dll_path) - + self._ATS_dll = None + + if os.name == 'nt': + self._ATS_dll = ctypes.cdll.LoadLibrary(dll_path or self.dll_path) + else: + raise Exception("Unsupported OS") + # TODO (W) make the board id more general such that more than one card # per system configurations are supported self._handle = self._ATS_dll.AlazarGetBoardBySystemID(system_id, @@ -201,6 +211,14 @@ def __init__(self, name, system_id=1, board_id=1, dll_path=None, **kwargs): # TODO (M) do something with board kind here self.buffer_list = [] + + # TODO use get_board_info for this and make it return better stuff! + def get_idn(self): + board_kind = self._board_names[self._ATS_dll.AlazarGetBoardKind(self._handle)] + max_s, bps = self._get_channel_info(self._handle) + return {'board' : board_kind, + 'max_samples' : max_s, + 'bits_per_sample' : bps} def config(self, clock_source=None, sample_rate=None, clock_edge=None, decimation=None, coupling=None, channel_range=None, @@ -277,9 +295,10 @@ def config(self, clock_source=None, sample_rate=None, clock_edge=None, self.parameters['coupling' + str(i)], self.parameters['channel_range' + str(i)], self.parameters['impedance' + str(i)]) - self._call_dll('AlazarSetBWLimit', - self._handle, i, - self.parameters['bwlimit' + str(i)]) + if bwlimit is not None: + self._call_dll('AlazarSetBWLimit', + self._handle, i, + self.parameters['bwlimit' + str(i)]) self._call_dll('AlazarSetTriggerOperation', self._handle, self.trigger_operation, @@ -339,7 +358,7 @@ def acquire(self, mode=None, samples_per_record=None, self._set_if_present('samples_per_record', samples_per_record) self._set_if_present('records_per_buffer', records_per_buffer) self._set_if_present('buffers_per_acquisition', - buffers_per_acquisition) + buffers_per_acquisition), self._set_if_present('channel_selection', channel_selection) self._set_if_present('transfer_offset', transfer_offset) self._set_if_present('external_startcapture', external_startcapture) @@ -362,12 +381,7 @@ def acquire(self, mode=None, samples_per_record=None, # Abort any previous measurement self._call_dll('AlazarAbortAsyncRead', self._handle) - - # get channel info - max_s, bps = self._get_channel_info(self._handle) - if bps != 8: - raise Exception('Only 8 bits per sample supported at this moment') - + # Set record size for NPT mode if mode == 'NPT': pretriggersize = 0 # pretriggersize is 0 for NPT always @@ -375,11 +389,8 @@ def acquire(self, mode=None, samples_per_record=None, self._handle, pretriggersize, self.samples_per_record) - # set acquisition parameters here for NPT, TS mode - if self.channel_selection._get_byte() == 3: - number_of_channels = 2 - else: - number_of_channels = 1 + + # set acquisition parameters here for NPT, TS mode samples_per_buffer = 0 buffers_per_acquisition = self.buffers_per_acquisition._get_byte() samples_per_record = self.samples_per_record._get_byte() @@ -393,8 +404,7 @@ def acquire(self, mode=None, samples_per_record=None, if mode == 'NPT': records_per_buffer = self.records_per_buffer._get_byte() - records_per_acquisition = ( - records_per_buffer * buffers_per_acquisition) + records_per_acquisition = records_per_buffer * buffers_per_acquisition samples_per_buffer = samples_per_record * records_per_buffer self._call_dll('AlazarBeforeAsyncRead', @@ -435,38 +445,76 @@ def acquire(self, mode=None, samples_per_record=None, self.interleave_samples._set_updated() self.get_processed_data._set_updated() + + # bytes per sample + handle = self._handle + max_s, bps = self._get_channel_info(handle) + bytes_per_sample = (bps + 7) // 8 + print("bytes per sample " +str(bytes_per_sample)) + + # bytes per record + bytes_per_record = bytes_per_sample * samples_per_record + print("samples_per_record is "+str(samples_per_record)) + print("bytes per record is "+str(bytes_per_record)) + + # bytes per buffer + if self.channel_selection._get_byte() == 3: + number_of_channels = 2 + else: + number_of_channels = 1 + + bytes_per_buffer = bytes_per_record * records_per_buffer * number_of_channels + # create buffers for acquisition + # TODO: should this be > 1 (makes sense to me) or > 8 as in alazar sample code? - Natalie + sample_type = ctypes.c_uint8 + if bytes_per_sample > 1: + sample_type = ctypes.c_uint16 + + print("samples_per_buffer is "+str(samples_per_buffer)) + print("bytes_per_buffer is "+str(bytes_per_buffer)) + self.clear_buffers() allocated_buffers = self.allocated_buffers._get_byte() + print(str(allocated_buffers)+"allocated buffers") for k in range(allocated_buffers): try: - self.buffer_list.append(Buffer(bps, samples_per_buffer, - number_of_channels)) + self.buffer_list.append(DMABuffer(sample_type, bytes_per_buffer)) except: self.clear_buffers() raise # post buffers to Alazar + print("made buffer list length "+str(len(self.buffer_list))) for buf in self.buffer_list: + print(buf.addr) + print(type(buf.size_bytes)) + self._ATS_dll.AlazarPostAsyncBuffer.argtypes = [ctypes.c_uint32, ctypes.c_void_p, ctypes.c_uint32] self._call_dll('AlazarPostAsyncBuffer', self._handle, buf.addr, buf.size_bytes) self.allocated_buffers._set_updated() + print("completed AlazarPostAsyncBuffer") # -----start capture here----- - acquisition_controller.pre_start_capture(self) +# acquisition_controller.pre_start_capture(self) + start = time.clock() # Keep track of when acquisition started # call the startcapture method self._call_dll('AlazarStartCapture', self._handle) - - acquisition_controller.pre_acquire(self) + print("Capturing %d buffers." % buffers_per_acquisition) + +# acquisition_controller.pre_acquire(self) # buffer handling from acquisition buffers_completed = 0 + bytes_transferred = 0 buffer_timeout = self.buffer_timeout._get_byte() self.buffer_timeout._set_updated() buffer_recycling = (self.buffers_per_acquisition._get_byte() > self.allocated_buffers._get_byte()) - while buffers_completed < self.buffers_per_acquisition._get_byte(): + while (buffers_completed < self.buffers_per_acquisition._get_byte()): + # Wait for the buffer at the head of the list of available + # buffers to be filled by the board. buf = self.buffer_list[buffers_completed % allocated_buffers] self._call_dll('AlazarWaitAsyncBufferComplete', @@ -478,21 +526,21 @@ def acquire(self, mode=None, samples_per_record=None, # if buffers must be recycled, extract data and repost them # otherwise continue to next buffer - if buffer_recycling: - acquisition_controller.handle_buffer(self, buf.buffer) +# acquisition_controller.handle_buffer(self, buf.buffer) self._call_dll('AlazarPostAsyncBuffer', self._handle, buf.addr, buf.size_bytes) buffers_completed += 1 + bytes_transferred += buf.size_bytes # stop measurement here self._call_dll('AlazarAbortAsyncRead', self._handle) # -----cleanup here----- # extract data if not yet done - if not buffer_recycling: - for buf in self.buffer_list: - acquisition_controller.handle_buffer(self, buf.buffer) +# if not buffer_recycling: +# for buf in self.buffer_list: +# acquisition_controller.handle_buffer(self, buf.buffer) # free up memory self.clear_buffers() @@ -502,7 +550,24 @@ def acquire(self, mode=None, samples_per_record=None, p.get() # return result - return acquisition_controller.post_acquire(self) +# return acquisition_controller.post_acquire(self) + + # Compute the total transfer time, and display performance information. + transfer_time_sec = time.clock() - start + print("Capture completed in %f sec" % transfer_time_sec) + buffers_per_sec = 0 + bytes_per_sec = 0 + records_per_sec = 0 + if transfer_time_sec > 0: + buffers_per_sec = buffers_completed / transfer_time_sec + bytes_per_sec = bytes_transferred / transfer_time_sec + records_per_sec = records_per_buffer * buffers_completed / transfer_time_sec + print("Captured %d buffers (%f buffers per sec)" % + (buffers_completed, buffers_per_sec)) + print("Captured %d records (%f records per sec)" % + (records_per_buffer * buffers_completed, records_per_sec)) + print("Transferred %d bytes (%f bytes per sec)" % + (bytes_transferred, bytes_per_sec)) def _set_if_present(self, param_name, value): if value is not None: @@ -537,7 +602,12 @@ def _call_dll(self, func_name, *args): # run the function func = getattr(self._ATS_dll, func_name) - return_code = func(*args_out) + try: + return_code = func(*args_out) + print(return_code) + except Exception as e: + print(e) + raise # check for errors if (return_code != self._success) and (return_code !=518): @@ -563,6 +633,7 @@ def _call_dll(self, func_name, *args): def clear_buffers(self): for b in self.buffer_list: b.free_mem() + print("buffers cleared") self.buffer_list = [] def signal_to_volt(self, channel, signal): @@ -655,50 +726,75 @@ def _set_updated(self): self._uptodate_flag = True -class Buffer: - def __init__(self, bits_per_sample, samples_per_buffer, - number_of_channels): - if bits_per_sample != 8: - raise Exception("Buffer: only 8 bit per sample supported") - if os.name != 'nt': - raise Exception("Buffer: only Windows supported at this moment") - self._allocated = True - # try to allocate memory - mem_commit = 0x1000 - page_readwrite = 0x4 +class DMABuffer: + '''Buffer suitable for DMA transfers. + + AlazarTech digitizers use direct memory access (DMA) to transfer + data from digitizers to the computer's main memory. This class + abstracts a memory buffer on the host, and ensures that all the + requirements for DMA transfers are met. + + DMABuffers export a 'buffer' member, which is a NumPy array view + of the underlying memory buffer + + Args: + + c_sample_type (ctypes type): The datatype of the buffer to create. + + size_bytes (int): The size of the buffer to allocate, in bytes. - self.size_bytes = samples_per_buffer * number_of_channels + ''' + def __init__(self, c_sample_type, size_bytes): + self.size_bytes = size_bytes - # for documentation please see: - # https://msdn.microsoft.com/en-us/library/windows/desktop/aa366887(v=vs.85).aspx - ctypes.windll.kernel32.VirtualAlloc.argtypes = [ - ctypes.c_void_p, ctypes.c_long, ctypes.c_long, ctypes.c_long] - ctypes.windll.kernel32.VirtualAlloc.restype = ctypes.c_void_p - self.addr = ctypes.windll.kernel32.VirtualAlloc( - 0, ctypes.c_long(self.size_bytes), mem_commit, page_readwrite) - if self.addr is None: + npSampleType = { + ctypes.c_uint8: np.uint8, + ctypes.c_uint16: np.uint16, + ctypes.c_uint32: np.uint32, + ctypes.c_int32: np.int32, + ctypes.c_float: np.float32 + }.get(c_sample_type, 0) + + bytes_per_sample = { + ctypes.c_uint8: 1, + ctypes.c_uint16: 2, + ctypes.c_uint32: 4, + ctypes.c_int32: 4, + ctypes.c_float: 4 + }.get(c_sample_type, 0) + + self._allocated = True + self.addr = None + if os.name == 'nt': + MEM_COMMIT = 0x1000 + PAGE_READWRITE = 0x4 + ctypes.windll.kernel32.VirtualAlloc.argtypes = [ctypes.c_void_p, ctypes.c_long, ctypes.c_long, ctypes.c_long] + ctypes.windll.kernel32.VirtualAlloc.restype = ctypes.c_void_p + self.addr = ctypes.windll.kernel32.VirtualAlloc( + 0, ctypes.c_long(size_bytes), MEM_COMMIT, PAGE_READWRITE) + else: self._allocated = False - e = ctypes.windll.kernel32.GetLastError() - raise Exception("Memory allocation error: " + str(e)) + raise Exception("Unsupported OS") - ctypes_array = (ctypes.c_uint8 * - self.size_bytes).from_address(self.addr) - self.buffer = np.frombuffer(ctypes_array, dtype=np.uint8) + + ctypes_array = (c_sample_type * + (size_bytes // bytes_per_sample)).from_address(self.addr) + self.buffer = np.frombuffer(ctypes_array, dtype=npSampleType) + self.ctypes_buffer = ctypes_array pointer, read_only_flag = self.buffer.__array_interface__['data'] def free_mem(self): - mem_release = 0x8000 - - # for documentation please see: - # https://msdn.microsoft.com/en-us/library/windows/desktop/aa366892(v=vs.85).aspx - ctypes.windll.kernel32.VirtualFree.argtypes = [ - ctypes.c_void_p, ctypes.c_long, ctypes.c_long] - ctypes.windll.kernel32.VirtualFree.restype = ctypes.c_int - ctypes.windll.kernel32.VirtualFree(ctypes.c_void_p(self.addr), 0, - mem_release) self._allocated = False - + if os.name == 'nt': + MEM_RELEASE = 0x8000 + ctypes.windll.kernel32.VirtualFree.argtypes = [ctypes.c_void_p, ctypes.c_long, ctypes.c_long] + ctypes.windll.kernel32.VirtualFree.restype = ctypes.c_int + ctypes.windll.kernel32.VirtualFree(ctypes.c_void_p(self.addr), 0, MEM_RELEASE); + else: + self._allocated = True + raise Exception("Unsupported OS") + def __del__(self): if self._allocated: self.free_mem() @@ -706,7 +802,7 @@ def __del__(self): 'Buffer prevented memory leak; Memory released to Windows.\n' 'Memory should have been released before buffer was deleted.') - + class AcquisitionController: def __init__(self): """ diff --git a/qcodes/instrument_drivers/AlazarTech/ATS9360.py b/qcodes/instrument_drivers/AlazarTech/ATS9360.py new file mode 100644 index 000000000000..0db4a6c071d3 --- /dev/null +++ b/qcodes/instrument_drivers/AlazarTech/ATS9360.py @@ -0,0 +1,282 @@ +from .ATS import AlazarTech_ATS, AlazarParameter +from qcodes.utils import validators + + +class AlazarTech_ATS9360(AlazarTech_ATS): + def __init__(self, name, server_name=None): + dll_path = 'C:\\WINDOWS\\System32\\ATSApi.dll' + super().__init__(name, dll_path=dll_path) + + samplesPerSec = None + # add parameters + + # ----- Parameters for the configuration of the board ----- + self.add_parameter(name='clock_source', + parameter_class=AlazarParameter, + label='Clock Source', + unit=None, + value='INTERNAL_CLOCK', + byte_to_value_dict={1: 'INTERNAL_CLOCK', + 4: 'SLOW_EXTERNAL_CLOCK', + 5: 'EXTERNAL_CLOCK_AC', + 7: 'EXTERNAL_CLOCK_10_MHz_REF'}) + self.add_parameter(name='sample_rate', + parameter_class=AlazarParameter, + label='Sample Rate', + unit='S/s', + value=500000000, + byte_to_value_dict={ + 0x1: 1000, 0x2: 2000, 0x4: 5000, 0x8: 10000, + 0xA: 20000, 0xC: 50000, 0xE: 100000, + 0x10: 200000, 0x12: 500000, 0x14: 1000000, + 0x18: 2000000, 0x1A: 5000000, 0x1C: 10000000, + 0x1E: 20000000, 0x22: 50000000, 0x24: 100000000, + 0x2B: 250000000, 0x30: 500000000, + 0x35: 1000000000, 0x40: 'EXTERNAL_CLOCK', + 1000000000: '1GHz_REFERENCE_CLOCK'}) + self.add_parameter(name='clock_edge', + parameter_class=AlazarParameter, + label='Clock Edge', + unit=None, + value='CLOCK_EDGE_RISING', + byte_to_value_dict={0: 'CLOCK_EDGE_RISING', + 1: 'CLOCK_EDGE_FALLING'}) + + self.add_parameter(name='decimation', + parameter_class=AlazarParameter, + label='Decimation', + unit=None, + value=0, + vals=validators.Ints(0, 100000)) + + for i in ['1', '2']: + self.add_parameter(name='coupling' + i, + parameter_class=AlazarParameter, + label='Coupling channel ' + i, + unit=None, + value='DC', + byte_to_value_dict={1: 'AC', 2: 'DC'}) + self.add_parameter(name='channel_range' + i, + parameter_class=AlazarParameter, + label='Range channel ' + i, + unit='V', + value=0.4, + byte_to_value_dict={ + 2: 0.04, 5: 0.1, 6: 0.2, 7: 0.4, + 10: 1., 11: 2., 12: 4.}) + self.add_parameter(name='impedance' + i, + parameter_class=AlazarParameter, + label='Impedance channel ' + i, + unit='Ohm', + value=50, + byte_to_value_dict={1: 1000000, 2: 50}) + + self.add_parameter(name='trigger_operation', + parameter_class=AlazarParameter, + label='Trigger Operation', + unit=None, + value='TRIG_ENGINE_OP_J', + byte_to_value_dict={ + 0: 'TRIG_ENGINE_OP_J', + 1: 'TRIG_ENGINE_OP_K', + 2: 'TRIG_ENGINE_OP_J_OR_K', + 3: 'TRIG_ENGINE_OP_J_AND_K', + 4: 'TRIG_ENGINE_OP_J_XOR_K', + 5: 'TRIG_ENGINE_OP_J_AND_NOT_K', + 6: 'TRIG_ENGINE_OP_NOT_J_AND_K'}) + for i in ['1', '2']: + self.add_parameter(name='trigger_engine' + i, + parameter_class=AlazarParameter, + label='Trigger Engine ' + i, + unit=None, + value='TRIG_ENGINE_J', + byte_to_value_dict={0: 'TRIG_ENGINE_J', + 1: 'TRIG_ENGINE_K'}) + self.add_parameter(name='trigger_source' + i, + parameter_class=AlazarParameter, + label='Trigger Source ' + i, + unit=None, + value='DISABLE', + byte_to_value_dict={0: 'CHANNEL_A', + 1: 'CHANNEL_B', + 2: 'EXTERNAL', + 3: 'DISABLE'}) + self.add_parameter(name='trigger_slope' + i, + parameter_class=AlazarParameter, + label='Trigger Slope ' + i, + unit=None, + value='TRIG_SLOPE_POSITIVE', + byte_to_value_dict={1: 'TRIG_SLOPE_POSITIVE', + 2: 'TRIG_SLOPE_NEGATIVE'}) + self.add_parameter(name='trigger_level' + i, + parameter_class=AlazarParameter, + label='Trigger Level ' + i, + unit=None, + value=150, + vals=validators.Ints(0, 255)) + + self.add_parameter(name='external_trigger_coupling', + parameter_class=AlazarParameter, + label='External Trigger Coupling', + unit=None, + value='AC', + byte_to_value_dict={1: 'AC', 2: 'DC'}) + self.add_parameter(name='external_trigger_range', + parameter_class=AlazarParameter, + label='External Trigger Range', + unit=None, + value='ETR_5V', + byte_to_value_dict={0: 'ETR_5V', 1: 'ETR_1V'}) + self.add_parameter(name='trigger_delay', + parameter_class=AlazarParameter, + label='Trigger Delay', + unit='Sample clock cycles', + value=0, + vals=validators.Ints(min_value=0)) + + # NOTE: The board will wait for a for this amount of time for a + # trigger event. If a trigger event does not arrive, then the + # board will automatically trigger. Set the trigger timeout value + # to 0 to force the board to wait forever for a trigger event. + # + # IMPORTANT: The trigger timeout value should be set to zero after + # appropriate trigger parameters have been determined, otherwise + # the board may trigger if the timeout interval expires before a + # hardware trigger event arrives. + self.add_parameter(name='timeout_ticks', + parameter_class=AlazarParameter, + label='Timeout Ticks', + unit='10 us', + value=0, + vals=validators.Ints(min_value=0)) + + # TODO: need to confugure AuxIO?? + + # ----- Parameters for the acquire function ----- + self.add_parameter(name='mode', + parameter_class=AlazarParameter, + label='Acquisiton mode', + unit=None, + value='NPT', + byte_to_value_dict={0x200: 'NPT', 0x400: 'TS'}) + + # samples_per_record must be a multiple of 16! + self.add_parameter(name='samples_per_record', + parameter_class=AlazarParameter, + label='Samples per Record', + unit=None, + value=1024, + vals=Multiples(divisor=16, min_value=0)) + # TODO (M) figure out if this also has to be a multiple of something, + # I could not find this in the documentation but somehow I have the + # feeling it still should be a multiple of something + # NOTE by ramiro: At least in previous python implementations(PycQED delft), this is an artifact for compatibility with AWG sequencing, not particular to any ATS architecture. + # ==> this is a construction imposed by the memory strategy implemented on the python driver we are writing, not limited by any actual ATS feature. + + self.add_parameter(name='records_per_buffer', + parameter_class=AlazarParameter, + label='Records per Buffer', + unit=None, + value=10, + vals=validators.Ints(min_value=0)) + self.add_parameter(name='buffers_per_acquisition', + parameter_class=AlazarParameter, + label='Buffers per Acquisition', + unit=None, + value=10, + vals=validators.Ints(min_value=0)) + self.add_parameter(name='channel_selection', + parameter_class=AlazarParameter, + label='Channel Selection', + unit=None, + value='AB', + byte_to_value_dict={1: 'A', 2: 'B', 3: 'AB'}) + self.add_parameter(name='transfer_offset', + parameter_class=AlazarParameter, + label='Transer Offset', + unit='Samples', + value=0, + vals=validators.Ints(min_value=0)) + self.add_parameter(name='external_startcapture', + parameter_class=AlazarParameter, + label='External Startcapture', + unit=None, + value='ENABLED', + byte_to_value_dict={0x0: 'DISABLED', + 0x1: 'ENABLED'}) + self.add_parameter(name='enable_record_headers', + parameter_class=AlazarParameter, + label='Enable Record Headers', + unit=None, + value='DISABLED', + byte_to_value_dict={0x0: 'DISABLED', + 0x8: 'ENABLED'}) + self.add_parameter(name='alloc_buffers', + parameter_class=AlazarParameter, + label='Alloc Buffers', + unit=None, + value='DISABLED', + byte_to_value_dict={0x0: 'DISABLED', + 0x20: 'ENABLED'}) + self.add_parameter(name='fifo_only_streaming', + parameter_class=AlazarParameter, + label='Fifo Only Streaming', + unit=None, + value='DISABLED', + byte_to_value_dict={0x0: 'DISABLED', + 0x800: 'ENABLED'}) + self.add_parameter(name='interleave_samples', + parameter_class=AlazarParameter, + label='Interleave Samples', + unit=None, + value='DISABLED', + byte_to_value_dict={0x0: 'DISABLED', + 0x1000: 'ENABLED'}) + self.add_parameter(name='get_processed_data', + parameter_class=AlazarParameter, + label='Get Processed Data', + unit=None, + value='DISABLED', + byte_to_value_dict={0x0: 'DISABLED', + 0x2000: 'ENABLED'}) + + self.add_parameter(name='allocated_buffers', + parameter_class=AlazarParameter, + label='Allocated Buffers', + unit=None, + value=2, + vals=validators.Ints(min_value=0)) + self.add_parameter(name='buffer_timeout', + parameter_class=AlazarParameter, + label='Buffer Timeout', + unit='ms', + value=1000, + vals=validators.Ints(min_value=0)) + + # TODO (M) make parameter for board type + + # TODO (M) check board kind + + +class Multiples(validators.Ints): + ''' + requires an integer + optional parameters min_value and max_value enforce + min_value <= value <= max_value + divisor enforces that value % divisor == 0 + ''' + + def __init__(self, divisor=1, **kwargs): + super().__init__(**kwargs) + if not isinstance(divisor, int): + raise TypeError('divisor must be an integer') + self._divisor = divisor + + def validate(self, value, context=''): + super().validate(value=value, context=context) + if not value % self._divisor == 0: + raise TypeError('{} is not a multiple of {}; {}'.format( + repr(value), repr(self._divisor), context)) + + def __repr__(self): + return super().__repr__()[:-1] + ', Multiples of {}>'.format(self._divisor) diff --git a/qcodes/instrument_drivers/AlazarTech/ATS_acquisition_controllers.py b/qcodes/instrument_drivers/AlazarTech/ATS_acquisition_controllers.py index 4122d9da583d..0614cb66949b 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS_acquisition_controllers.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS_acquisition_controllers.py @@ -6,17 +6,24 @@ # DFT AcquisitionController class DFT_AcquisitionController(AcquisitionController): def __init__(self, demodulation_frequency): - self.demodulation_frequency = demodulation_frequency + # self.demodulation_frequency = demodulation_frequency self.samples_per_record = None + self.bits_per_sample = None self.records_per_buffer = None self.buffers_per_acquisition = None + self.allocated_buffers = None # TODO (S) this is not very general: self.number_of_channels = 2 - self.cos_list = None - self.sin_list = None + # self.cos_list = None + # self.sin_list = None self.buffer = None def pre_start_capture(self, alazar): + + # allcoate buffers + max_s, bps = alazar._get_channel_info() + self.bits_per_sample = bps + self.samples_per_record = alazar.samples_per_record.get() self.records_per_buffer = alazar.records_per_buffer.get() self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() From 256b35a4fcbeae936ec4cd7766c4c1c082b025e0 Mon Sep 17 00:00:00 2001 From: Natalie Pearson Date: Tue, 2 Aug 2016 19:18:45 +0200 Subject: [PATCH 002/180] style: Remove some print statememnts from ATS.py --- qcodes/instrument_drivers/AlazarTech/ATS.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/ATS.py b/qcodes/instrument_drivers/AlazarTech/ATS.py index 463664163c94..eba15498d61d 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS.py @@ -18,11 +18,13 @@ # acquisition that would overflow the board if measurement is not stopped # quickly enough. can this be solved by not reposting the buffers? -# TODO: check 8 bit sample thing works -# TODO: test get_board_info and find_boards -# TODO: remove guerilla debuggung 'print' statements -# TODO: call_dll error handling -# TODO: acquisition_controller +# TODO: check 8 bit sample thing works - Natalie +# TODO: test get_board_info and find_boards - Natalie +# TODO: remove guerilla debuggung 'print' statements - Natalie +# TODO: call_dll error handling - Natalie +# TODO: acquisition_controller - Natalie +# TODO: fix hacky way I use _ATS_dll anywhere - Natalie +# TODO: make it actually save data! - Natalie class AlazarTech_ATS(Instrument): # override dll_path in your init script or in the board constructor @@ -476,7 +478,7 @@ def acquire(self, mode=None, samples_per_record=None, self.clear_buffers() allocated_buffers = self.allocated_buffers._get_byte() - print(str(allocated_buffers)+"allocated buffers") + print(str(allocated_buffers)+" allocated buffers") for k in range(allocated_buffers): try: self.buffer_list.append(DMABuffer(sample_type, bytes_per_buffer)) @@ -487,8 +489,6 @@ def acquire(self, mode=None, samples_per_record=None, # post buffers to Alazar print("made buffer list length "+str(len(self.buffer_list))) for buf in self.buffer_list: - print(buf.addr) - print(type(buf.size_bytes)) self._ATS_dll.AlazarPostAsyncBuffer.argtypes = [ctypes.c_uint32, ctypes.c_void_p, ctypes.c_uint32] self._call_dll('AlazarPostAsyncBuffer', self._handle, buf.addr, buf.size_bytes) @@ -604,7 +604,6 @@ def _call_dll(self, func_name, *args): func = getattr(self._ATS_dll, func_name) try: return_code = func(*args_out) - print(return_code) except Exception as e: print(e) raise From 9b0d84bd15c625497d8fed5300fce127becba4be Mon Sep 17 00:00:00 2001 From: Natalie Pearson Date: Wed, 3 Aug 2016 18:09:49 +0200 Subject: [PATCH 003/180] tidy up ATS.py comments and create test acquisition conroller for ATS9360 --- docs/examples/Qcodes example ATS_ONWORK.ipynb | 1742 +++++++++++++++-- qcodes/instrument_drivers/AlazarTech/ATS.py | 37 +- .../instrument_drivers/AlazarTech/ATS9360.py | 1 - .../AlazarTech/ATS_acquisition_controllers.py | 112 +- 4 files changed, 1736 insertions(+), 156 deletions(-) diff --git a/docs/examples/Qcodes example ATS_ONWORK.ipynb b/docs/examples/Qcodes example ATS_ONWORK.ipynb index 206812252a0a..54114498186f 100644 --- a/docs/examples/Qcodes example ATS_ONWORK.ipynb +++ b/docs/examples/Qcodes example ATS_ONWORK.ipynb @@ -383,21 +383,10 @@ "metadata": { "collapsed": false }, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "import qcodes.instrument_drivers.AlazarTech.ATS9360 as ATSdriver; reload(ATSdriver)\n", - "#import qcodes.instrument_drivers.AlazarTech.ATS_acquisition_controllers as ats_contr" + "import qcodes.instrument_drivers.AlazarTech.ATS_acquisition_controllers as ats_contr" ] }, { @@ -408,7 +397,7 @@ }, "outputs": [], "source": [ - "#contr1 = ats_contr.DFT_AcquisitionController(demodulation_frequency=10e6)" + "contr1 = ats_contr.Test_AcquisitionController()" ] }, { @@ -428,35 +417,7 @@ "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "AlazarSetCaptureClock\n", - "512\n", - "\n", - "AlazarInputControl\n", - "512\n", - "\n", - "AlazarInputControl\n", - "512\n", - "\n", - "AlazarSetTriggerOperation\n", - "512\n", - "\n", - "AlazarSetExternalTrigger\n", - "512\n", - "\n", - "AlazarSetTriggerDelay\n", - "512\n", - "\n", - "AlazarSetTriggerTimeOut\n", - "512\n" - ] - } - ], + "outputs": [], "source": [ "ats_inst.config(clock_source='INTERNAL_CLOCK',\n", " sample_rate=500000000,\n", @@ -491,91 +452,37 @@ "name": "stdout", "output_type": "stream", "text": [ - "\n", - "AlazarAbortAsyncRead\n", - "512\n", - "\n", - "AlazarSetRecordSize\n", - "512\n", - "\n", - "AlazarBeforeAsyncRead\n", - "512\n", - "\n", - "AlazarGetChannelInfo\n", - "512\n", "bytes per sample 2\n", "samples_per_record is 1024\n", "bytes per record is 2048\n", "samples_per_buffer is 10240\n", "bytes_per_buffer is 40960\n", + "records_per_buffer is 10\n", "buffers cleared\n", - "2allocated buffers\n", - "making DMA buffer\n", - "making DMA buffer\n", "made buffer list length 2\n", - "138543104\n", - "\n", - "\n", - "AlazarPostAsyncBuffer\n", - "512\n", - "138608640\n", - "\n", - "\n", - "AlazarPostAsyncBuffer\n", - "512\n", "completed AlazarPostAsyncBuffer\n", - "\n", - "AlazarStartCapture\n", - "512\n", - "Capturing 3 buffers.\n", - "\n", - "AlazarWaitAsyncBufferComplete\n", - "518\n", - "[31136 36320 31360 ..., 28736 32480 28832]\n", - "\n", - "AlazarPostAsyncBuffer\n", - "518\n", - "\n", - "AlazarWaitAsyncBufferComplete\n", - "518\n", - "[31136 36320 31360 ..., 28736 32480 28832]\n", - "\n", - "AlazarPostAsyncBuffer\n", - "518\n", - "\n", - "AlazarWaitAsyncBufferComplete\n", - "518\n", - "[31136 36320 31360 ..., 28736 32480 28832]\n", - "\n", - "AlazarPostAsyncBuffer\n", - "518\n", - "\n", - "AlazarAbortAsyncRead\n", - "512\n", - "buffers cleared\n", - "Capture completed in 0.026781 sec\n", - "Captured 3 buffers (112.018308 buffers per sec)\n", - "Captured 30 records (1120.183076 records per sec)\n", - "Transferred 122880 bytes (4588269.880869 bytes per sec)\n" + "Capturing 1 buffers.\n", + "not recycling\n", + "buffers cleared\n" ] } ], "source": [ - "ats_inst.acquire(mode='NPT',\n", - " samples_per_record=1024,\n", - " records_per_buffer=10,\n", - " buffers_per_acquisition=3,\n", - " channel_selection='AB',\n", - " transfer_offset=0,\n", - " external_startcapture='DISABLED',\n", - " enable_record_headers='DISABLED',\n", - " alloc_buffers='ENABLED',\n", - " fifo_only_streaming='DISABLED',\n", - " interleave_samples='DISABLED',\n", - " get_processed_data='ENABLED',\n", - " allocated_buffers=2,\n", - " buffer_timeout=10,\n", - " acquisition_controller=None)" + "resA, resB = ats_inst.acquire(mode='NPT',\n", + " samples_per_record=1024,\n", + " records_per_buffer=10,\n", + " buffers_per_acquisition=1,\n", + " channel_selection='AB',\n", + " transfer_offset=0,\n", + " external_startcapture='DISABLED',\n", + " enable_record_headers='DISABLED',\n", + " alloc_buffers='ENABLED',\n", + " fifo_only_streaming='DISABLED',\n", + " interleave_samples='DISABLED',\n", + " get_processed_data='ENABLED',\n", + " allocated_buffers=2,\n", + " buffer_timeout=10,\n", + " acquisition_controller=contr1)" ] }, { @@ -599,31 +506,1610 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "AlazarGetChannelInfo\n", - "512\n" - ] + "data": { + "text/plain": [ + "12" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ats_inst.get_idn()['bits_per_sample']" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "500000000" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ats_inst.get_sample_speed()" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "application/javascript": [ + "/* Put everything inside the global mpl namespace */\n", + "window.mpl = {};\n", + "\n", + "mpl.get_websocket_type = function() {\n", + " if (typeof(WebSocket) !== 'undefined') {\n", + " return WebSocket;\n", + " } else if (typeof(MozWebSocket) !== 'undefined') {\n", + " return MozWebSocket;\n", + " } else {\n", + " alert('Your browser does not have WebSocket support.' +\n", + " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", + " 'Firefox 4 and 5 are also supported but you ' +\n", + " 'have to enable WebSockets in about:config.');\n", + " };\n", + "}\n", + "\n", + "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", + " this.id = figure_id;\n", + "\n", + " this.ws = websocket;\n", + "\n", + " this.supports_binary = (this.ws.binaryType != undefined);\n", + "\n", + " if (!this.supports_binary) {\n", + " var warnings = document.getElementById(\"mpl-warnings\");\n", + " if (warnings) {\n", + " warnings.style.display = 'block';\n", + " warnings.textContent = (\n", + " \"This browser does not support binary websocket messages. \" +\n", + " \"Performance may be slow.\");\n", + " }\n", + " }\n", + "\n", + " this.imageObj = new Image();\n", + "\n", + " this.context = undefined;\n", + " this.message = undefined;\n", + " this.canvas = undefined;\n", + " this.rubberband_canvas = undefined;\n", + " this.rubberband_context = undefined;\n", + " this.format_dropdown = undefined;\n", + "\n", + " this.image_mode = 'full';\n", + "\n", + " this.root = $('
');\n", + " this._root_extra_style(this.root)\n", + " this.root.attr('style', 'display: inline-block');\n", + "\n", + " $(parent_element).append(this.root);\n", + "\n", + " this._init_header(this);\n", + " this._init_canvas(this);\n", + " this._init_toolbar(this);\n", + "\n", + " var fig = this;\n", + "\n", + " this.waiting = false;\n", + "\n", + " this.ws.onopen = function () {\n", + " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", + " fig.send_message(\"send_image_mode\", {});\n", + " fig.send_message(\"refresh\", {});\n", + " }\n", + "\n", + " this.imageObj.onload = function() {\n", + " if (fig.image_mode == 'full') {\n", + " // Full images could contain transparency (where diff images\n", + " // almost always do), so we need to clear the canvas so that\n", + " // there is no ghosting.\n", + " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", + " }\n", + " fig.context.drawImage(fig.imageObj, 0, 0);\n", + " fig.waiting = false;\n", + " };\n", + "\n", + " this.imageObj.onunload = function() {\n", + " this.ws.close();\n", + " }\n", + "\n", + " this.ws.onmessage = this._make_on_message_function(this);\n", + "\n", + " this.ondownload = ondownload;\n", + "}\n", + "\n", + "mpl.figure.prototype._init_header = function() {\n", + " var titlebar = $(\n", + " '
');\n", + " var titletext = $(\n", + " '
');\n", + " titlebar.append(titletext)\n", + " this.root.append(titlebar);\n", + " this.header = titletext[0];\n", + "}\n", + "\n", + "\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._init_canvas = function() {\n", + " var fig = this;\n", + "\n", + " var canvas_div = $('
');\n", + "\n", + " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", + "\n", + " function canvas_keyboard_event(event) {\n", + " return fig.key_event(event, event['data']);\n", + " }\n", + "\n", + " canvas_div.keydown('key_press', canvas_keyboard_event);\n", + " canvas_div.keyup('key_release', canvas_keyboard_event);\n", + " this.canvas_div = canvas_div\n", + " this._canvas_extra_style(canvas_div)\n", + " this.root.append(canvas_div);\n", + "\n", + " var canvas = $('');\n", + " canvas.addClass('mpl-canvas');\n", + " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", + "\n", + " this.canvas = canvas[0];\n", + " this.context = canvas[0].getContext(\"2d\");\n", + "\n", + " var rubberband = $('');\n", + " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", + "\n", + " var pass_mouse_events = true;\n", + "\n", + " canvas_div.resizable({\n", + " start: function(event, ui) {\n", + " pass_mouse_events = false;\n", + " },\n", + " resize: function(event, ui) {\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " stop: function(event, ui) {\n", + " pass_mouse_events = true;\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " });\n", + "\n", + " function mouse_event_fn(event) {\n", + " if (pass_mouse_events)\n", + " return fig.mouse_event(event, event['data']);\n", + " }\n", + "\n", + " rubberband.mousedown('button_press', mouse_event_fn);\n", + " rubberband.mouseup('button_release', mouse_event_fn);\n", + " // Throttle sequential mouse events to 1 every 20ms.\n", + " rubberband.mousemove('motion_notify', mouse_event_fn);\n", + "\n", + " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", + " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", + "\n", + " canvas_div.on(\"wheel\", function (event) {\n", + " event = event.originalEvent;\n", + " event['data'] = 'scroll'\n", + " if (event.deltaY < 0) {\n", + " event.step = 1;\n", + " } else {\n", + " event.step = -1;\n", + " }\n", + " mouse_event_fn(event);\n", + " });\n", + "\n", + " canvas_div.append(canvas);\n", + " canvas_div.append(rubberband);\n", + "\n", + " this.rubberband = rubberband;\n", + " this.rubberband_canvas = rubberband[0];\n", + " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", + " this.rubberband_context.strokeStyle = \"#000000\";\n", + "\n", + " this._resize_canvas = function(width, height) {\n", + " // Keep the size of the canvas, canvas container, and rubber band\n", + " // canvas in synch.\n", + " canvas_div.css('width', width)\n", + " canvas_div.css('height', height)\n", + "\n", + " canvas.attr('width', width);\n", + " canvas.attr('height', height);\n", + "\n", + " rubberband.attr('width', width);\n", + " rubberband.attr('height', height);\n", + " }\n", + "\n", + " // Set the figure to an initial 600x600px, this will subsequently be updated\n", + " // upon first draw.\n", + " this._resize_canvas(600, 600);\n", + "\n", + " // Disable right mouse context menu.\n", + " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", + " return false;\n", + " });\n", + "\n", + " function set_focus () {\n", + " canvas.focus();\n", + " canvas_div.focus();\n", + " }\n", + "\n", + " window.setTimeout(set_focus, 100);\n", + "}\n", + "\n", + "mpl.figure.prototype._init_toolbar = function() {\n", + " var fig = this;\n", + "\n", + " var nav_element = $('
')\n", + " nav_element.attr('style', 'width: 100%');\n", + " this.root.append(nav_element);\n", + "\n", + " // Define a callback function for later on.\n", + " function toolbar_event(event) {\n", + " return fig.toolbar_button_onclick(event['data']);\n", + " }\n", + " function toolbar_mouse_event(event) {\n", + " return fig.toolbar_button_onmouseover(event['data']);\n", + " }\n", + "\n", + " for(var toolbar_ind in mpl.toolbar_items) {\n", + " var name = mpl.toolbar_items[toolbar_ind][0];\n", + " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", + " var image = mpl.toolbar_items[toolbar_ind][2];\n", + " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", + "\n", + " if (!name) {\n", + " // put a spacer in here.\n", + " continue;\n", + " }\n", + " var button = $('');\n", + " button.click(method_name, toolbar_event);\n", + " button.mouseover(tooltip, toolbar_mouse_event);\n", + " nav_element.append(button);\n", + " }\n", + "\n", + " // Add the status bar.\n", + " var status_bar = $('');\n", + " nav_element.append(status_bar);\n", + " this.message = status_bar[0];\n", + "\n", + " // Add the close button to the window.\n", + " var buttongrp = $('
');\n", + " var button = $('');\n", + " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", + " button.mouseover('Close figure', toolbar_mouse_event);\n", + " buttongrp.append(button);\n", + " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", + " titlebar.prepend(buttongrp);\n", + "}\n", + "\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(el){\n", + " // this is important to make the div 'focusable\n", + " el.attr('tabindex', 0)\n", + " // reach out to IPython and tell the keyboard manager to turn it's self\n", + " // off when our div gets focus\n", + "\n", + " // location in version 3\n", + " if (IPython.notebook.keyboard_manager) {\n", + " IPython.notebook.keyboard_manager.register_events(el);\n", + " }\n", + " else {\n", + " // location in version 2\n", + " IPython.keyboard_manager.register_events(el);\n", + " }\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._key_event_extra = function(event, name) {\n", + " var manager = IPython.notebook.keyboard_manager;\n", + " if (!manager)\n", + " manager = IPython.keyboard_manager;\n", + "\n", + " // Check for shift+enter\n", + " if (event.shiftKey && event.which == 13) {\n", + " this.canvas_div.blur();\n", + " event.shiftKey = false;\n", + " // Send a \"J\" for go to next cell\n", + " event.which = 74;\n", + " event.keyCode = 74;\n", + " manager.command_mode();\n", + " manager.handle_keydown(event);\n", + " }\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_save = function(fig, msg) {\n", + " fig.ondownload(fig, null);\n", + "}\n", + "\n", + "\n", + "mpl.find_output_cell = function(html_output) {\n", + " // Return the cell and output element which can be found *uniquely* in the notebook.\n", + " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", + " // IPython event is triggered only after the cells have been serialised, which for\n", + " // our purposes (turning an active figure into a static one), is too late.\n", + " var cells = IPython.notebook.get_cells();\n", + " var ncells = cells.length;\n", + " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", + " data = data.data;\n", + " }\n", + " if (data['text/html'] == html_output) {\n", + " return [cell, data, j];\n", + " }\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + "// Register the function which deals with the matplotlib target/channel.\n", + "// The kernel may be null if the page has been refreshed.\n", + "if (IPython.notebook.kernel != null) {\n", + " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", + "}\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "qc.MatPlot(resB)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "ename": "TypeError", + "evalue": "__init__() got an unexpected keyword argument 'system_id'", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)", + "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mats_inst\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mget_idn\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[1;32ma:\\qcodesfolder\\qcodes\\instrument_drivers\\AlazarTech\\ATS.py\u001b[0m in \u001b[0;36mget_idn\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 216\u001b[0m \u001b[0mboard_kind\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_board_names\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_ATS_dll\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mAlazarGetBoardKind\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_handle\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 217\u001b[0m \u001b[0mmax_s\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mbps\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_get_channel_info\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_handle\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 218\u001b[1;33m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mfind_boards\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 219\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 220\u001b[0m return {'board' : board_kind,\n", + "\u001b[1;32ma:\\qcodesfolder\\qcodes\\instrument_drivers\\AlazarTech\\ATS.py\u001b[0m in \u001b[0;36mfind_boards\u001b[1;34m(cls, dll_path)\u001b[0m\n\u001b[0;32m 170\u001b[0m \u001b[0mboard_count\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mdll\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mAlazarBoardsInSystemBySystemID\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0msystem_id\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 171\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mboard_id\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mboard_count\u001b[0m \u001b[1;33m+\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 172\u001b[1;33m \u001b[0mboards\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mcls\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mget_board_info\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mdll\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0msystem_id\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mboard_id\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 173\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[0mboards\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 174\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[1;32ma:\\qcodesfolder\\qcodes\\instrument_drivers\\AlazarTech\\ATS.py\u001b[0m in \u001b[0;36mget_board_info\u001b[1;34m(cls, dll, system_id, board_id)\u001b[0m\n\u001b[0;32m 178\u001b[0m \u001b[1;31m# to get its info\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 179\u001b[0m board = cls('temp', system_id=system_id, board_id=board_id,\n\u001b[1;32m--> 180\u001b[1;33m server_name=None)\n\u001b[0m\u001b[0;32m 181\u001b[0m \u001b[0mhandle\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mboard\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_handle\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 182\u001b[0m \u001b[0mboard_kind\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mcls\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_board_names\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mdll\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mAlazarGetBoardKind\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mhandle\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[1;31mTypeError\u001b[0m: __init__() got an unexpected keyword argument 'system_id'" + ] + } + ], "source": [ "ats_inst.get_idn()" ] @@ -635,7 +2121,9 @@ "collapsed": true }, "outputs": [], - "source": [] + "source": [ + "import qcodes.instrument_drivers.AlazarTech.ATS" + ] } ], "metadata": { diff --git a/qcodes/instrument_drivers/AlazarTech/ATS.py b/qcodes/instrument_drivers/AlazarTech/ATS.py index eba15498d61d..084ca36d14e9 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS.py @@ -18,13 +18,9 @@ # acquisition that would overflow the board if measurement is not stopped # quickly enough. can this be solved by not reposting the buffers? -# TODO: check 8 bit sample thing works - Natalie -# TODO: test get_board_info and find_boards - Natalie -# TODO: remove guerilla debuggung 'print' statements - Natalie -# TODO: call_dll error handling - Natalie -# TODO: acquisition_controller - Natalie -# TODO: fix hacky way I use _ATS_dll anywhere - Natalie -# TODO: make it actually save data! - Natalie +# TODO(nataliejpg) get_board_info and find_boards are broken?? +# TODO(nataliejpg) call_dll error handling doesnt catch errors in expected way +# TODO(nataliejpg) make use of _ATS_dll uniform class AlazarTech_ATS(Instrument): # override dll_path in your init script or in the board constructor @@ -214,7 +210,6 @@ def __init__(self, name, system_id=1, board_id=1, dll_path=None, **kwargs): self.buffer_list = [] - # TODO use get_board_info for this and make it return better stuff! def get_idn(self): board_kind = self._board_names[self._ATS_dll.AlazarGetBoardKind(self._handle)] max_s, bps = self._get_channel_info(self._handle) @@ -459,26 +454,27 @@ def acquire(self, mode=None, samples_per_record=None, print("samples_per_record is "+str(samples_per_record)) print("bytes per record is "+str(bytes_per_record)) - # bytes per buffer + # channels if self.channel_selection._get_byte() == 3: number_of_channels = 2 else: number_of_channels = 1 - + + # bytes per buffer bytes_per_buffer = bytes_per_record * records_per_buffer * number_of_channels # create buffers for acquisition - # TODO: should this be > 1 (makes sense to me) or > 8 as in alazar sample code? - Natalie + # TODO(nataliejpg) should this be > 1 (makes sense to me) or > 8 as in alazar sample code? - Natalie sample_type = ctypes.c_uint8 if bytes_per_sample > 1: sample_type = ctypes.c_uint16 print("samples_per_buffer is "+str(samples_per_buffer)) print("bytes_per_buffer is "+str(bytes_per_buffer)) + print("records_per_buffer is "+str(records_per_buffer)) self.clear_buffers() allocated_buffers = self.allocated_buffers._get_byte() - print(str(allocated_buffers)+" allocated buffers") for k in range(allocated_buffers): try: self.buffer_list.append(DMABuffer(sample_type, bytes_per_buffer)) @@ -496,13 +492,13 @@ def acquire(self, mode=None, samples_per_record=None, print("completed AlazarPostAsyncBuffer") # -----start capture here----- -# acquisition_controller.pre_start_capture(self) + acquisition_controller.pre_start_capture(self) start = time.clock() # Keep track of when acquisition started # call the startcapture method self._call_dll('AlazarStartCapture', self._handle) print("Capturing %d buffers." % buffers_per_acquisition) -# acquisition_controller.pre_acquire(self) + acquisition_controller.pre_acquire(self) # buffer handling from acquisition buffers_completed = 0 bytes_transferred = 0 @@ -527,7 +523,7 @@ def acquire(self, mode=None, samples_per_record=None, # if buffers must be recycled, extract data and repost them # otherwise continue to next buffer if buffer_recycling: -# acquisition_controller.handle_buffer(self, buf.buffer) + acquisition_controller.handle_buffer(self, buf.buffer) self._call_dll('AlazarPostAsyncBuffer', self._handle, buf.addr, buf.size_bytes) buffers_completed += 1 @@ -538,9 +534,9 @@ def acquire(self, mode=None, samples_per_record=None, # -----cleanup here----- # extract data if not yet done -# if not buffer_recycling: -# for buf in self.buffer_list: -# acquisition_controller.handle_buffer(self, buf.buffer) + if not buffer_recycling: + for buf in self.buffer_list: + acquisition_controller.handle_buffer(self, buf.buffer) # free up memory self.clear_buffers() @@ -550,7 +546,7 @@ def acquire(self, mode=None, samples_per_record=None, p.get() # return result -# return acquisition_controller.post_acquire(self) + return acquisition_controller.post_acquire(self) # Compute the total transfer time, and display performance information. transfer_time_sec = time.clock() - start @@ -640,7 +636,8 @@ def signal_to_volt(self, channel, signal): # TODO (M) use byte value if range{channel} return (((signal - 127.5) / 127.5) * (self.parameters['channel_range' + str(channel)].get())) - + + # TODO(nataliejpg) surely this should be get_sample_rate? def get_sample_speed(self): if self.sample_rate.get() == 'EXTERNAL_CLOCK': raise Exception('External clock is used, alazar driver ' diff --git a/qcodes/instrument_drivers/AlazarTech/ATS9360.py b/qcodes/instrument_drivers/AlazarTech/ATS9360.py index 0db4a6c071d3..5703d92a6bd5 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS9360.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS9360.py @@ -150,7 +150,6 @@ def __init__(self, name, server_name=None): value=0, vals=validators.Ints(min_value=0)) - # TODO: need to confugure AuxIO?? # ----- Parameters for the acquire function ----- self.add_parameter(name='mode', diff --git a/qcodes/instrument_drivers/AlazarTech/ATS_acquisition_controllers.py b/qcodes/instrument_drivers/AlazarTech/ATS_acquisition_controllers.py index 0614cb66949b..359a767624b0 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS_acquisition_controllers.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS_acquisition_controllers.py @@ -3,10 +3,111 @@ import numpy as np +# Heterodyne Measurement Controller +# returns unprocessed data averaged by record for 2 channel use +class HD_Controller(AcquisitionController): + def __init__(self): + self.samples_per_record = None + self.bits_per_sample = None + self.records_per_buffer = None + self.buffers_per_acquisition = None + self.allocated_buffers = None + self.number_of_channels = 2 + self.buffer = None + + def pre_start_capture(self, alazar): + self.bits_per_sample = alazar.get_idn()['bits_per_sample'] + self.samples_per_record = alazar.samples_per_record() + self.records_per_buffer = alazar.records_per_buffer() + self.buffers_per_acquisition = alazar.buffers_per_acquisition() + sample_speed = alazar.get_sample_speed() + self.buffer = np.zeros(self.samples_per_record * + self.records_per_buffer * + self.number_of_channels) + + def pre_acquire(self, alazar): + # gets called after 'AlazarStartCapture' + pass + + def handle_buffer(self, alazar, data): + self.buffer += data + + def post_acquire(self, alazar): + # average over records in buffer: + # for ATS9360 samples are arranged in the buffer as follows: + # S0A, S0B, ..., S1A, S1B, ... + # with SXY the sample number X of channel Y. + records_per_acquisition = (1. * self.buffers_per_acquisition * + self.records_per_buffer) + recordA = np.zeros(self.samples_per_record) + for i in range(self.records_per_buffer): + i0 = i * self.samples_per_record * self.number_of_channels + i1 = i0 + self.samples_per_record * self.number_of_channels + recordA += self.buffer[i0:i1:self.number_of_channels] / records_per_acquisition + + recordB = np.zeros(self.samples_per_record) + for i in range(self.records_per_buffer): + i0 = (i * self.samples_per_record * self.number_of_channels) + 1 + i1 = i0 + self.samples_per_record *self.number_of_channels + recordB += self.buffer[i0:i1:self.number_of_channels] / records_per_acquisition + return recordA, recordB + + +# Test AcquisitionController tested on ATS9360 (nataliejpg) +# returns unprocessed data averaged by record for 2 channel use +class Test_AcquisitionController(AcquisitionController): + def __init__(self): + self.samples_per_record = None + self.bits_per_sample = None + self.records_per_buffer = None + self.buffers_per_acquisition = None + self.allocated_buffers = None + self.number_of_channels = 2 + self.buffer = None + + def pre_start_capture(self, alazar): + self.bits_per_sample = alazar.get_idn()['bits_per_sample'] + self.samples_per_record = alazar.samples_per_record() + self.records_per_buffer = alazar.records_per_buffer() + self.buffers_per_acquisition = alazar.buffers_per_acquisition() + sample_speed = alazar.get_sample_speed() + self.buffer = np.zeros(self.samples_per_record * + self.records_per_buffer * + self.number_of_channels) + + def pre_acquire(self, alazar): + # gets called after 'AlazarStartCapture' + pass + + def handle_buffer(self, alazar, data): + self.buffer += data + + def post_acquire(self, alazar): + # average over records in buffer: + # for ATS9360 samples are arranged in the buffer as follows: + # S0A, S0B, ..., S1A, S1B, ... + # with SXY the sample number X of channel Y. + records_per_acquisition = (1. * self.buffers_per_acquisition * + self.records_per_buffer) + recordA = np.zeros(self.samples_per_record) + for i in range(self.records_per_buffer): + i0 = i * self.samples_per_record * self.number_of_channels + i1 = i0 + self.samples_per_record * self.number_of_channels + recordA += self.buffer[i0:i1:self.number_of_channels] / records_per_acquisition + + recordB = np.zeros(self.samples_per_record) + for i in range(self.records_per_buffer): + i0 = (i * self.samples_per_record * self.number_of_channels) + 1 + i1 = i0 + self.samples_per_record *self.number_of_channels + recordB += self.buffer[i0:i1:self.number_of_channels] / records_per_acquisition + return recordA, recordB + + + # DFT AcquisitionController class DFT_AcquisitionController(AcquisitionController): def __init__(self, demodulation_frequency): - # self.demodulation_frequency = demodulation_frequency + self.demodulation_frequency = demodulation_frequency self.samples_per_record = None self.bits_per_sample = None self.records_per_buffer = None @@ -14,16 +115,11 @@ def __init__(self, demodulation_frequency): self.allocated_buffers = None # TODO (S) this is not very general: self.number_of_channels = 2 - # self.cos_list = None - # self.sin_list = None + self.cos_list = None + self.sin_list = None self.buffer = None def pre_start_capture(self, alazar): - - # allcoate buffers - max_s, bps = alazar._get_channel_info() - self.bits_per_sample = bps - self.samples_per_record = alazar.samples_per_record.get() self.records_per_buffer = alazar.records_per_buffer.get() self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() From 5f02af04b05b62b41b15fe7648d1b1434b7a3aa1 Mon Sep 17 00:00:00 2001 From: Natalie Pearson Date: Thu, 4 Aug 2016 15:23:53 +0200 Subject: [PATCH 004/180] more edits on acquisition_controller --- docs/examples/Qcodes example ATS_ONWORK.ipynb | 83 +++++++++++++------ qcodes/instrument_drivers/AlazarTech/ATS.py | 1 + .../AlazarTech/ATS_acquisition_controllers.py | 34 ++++++-- 3 files changed, 85 insertions(+), 33 deletions(-) diff --git a/docs/examples/Qcodes example ATS_ONWORK.ipynb b/docs/examples/Qcodes example ATS_ONWORK.ipynb index 54114498186f..3b05b49a247e 100644 --- a/docs/examples/Qcodes example ATS_ONWORK.ipynb +++ b/docs/examples/Qcodes example ATS_ONWORK.ipynb @@ -402,13 +402,13 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 19, "metadata": { "collapsed": false }, "outputs": [], "source": [ - "ats_inst = ATSdriver.AlazarTech_ATS9360(name='Alazar1', server_name=None)" + "contr2 = ats_contr.HD_Controller(10e6)" ] }, { @@ -418,6 +418,17 @@ "collapsed": false }, "outputs": [], + "source": [ + "ats_inst = ATSdriver.AlazarTech_ATS9360(name='Alazar1', server_name=None)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [], "source": [ "ats_inst.config(clock_source='INTERNAL_CLOCK',\n", " sample_rate=500000000,\n", @@ -442,7 +453,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 30, "metadata": { "collapsed": false, "scrolled": false @@ -462,7 +473,6 @@ "made buffer list length 2\n", "completed AlazarPostAsyncBuffer\n", "Capturing 1 buffers.\n", - "not recycling\n", "buffers cleared\n" ] } @@ -487,26 +497,51 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 31, "metadata": { "collapsed": false }, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "buffers cleared\n" - ] + "data": { + "text/plain": [ + "4340.0" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "resA[1]-resB[1]+180" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([ 57568., 58080., 58624., ..., 73280., 73248., 73184.])" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ - "ats_inst.clear_buffers()" + "resB" ] }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 33, "metadata": { "collapsed": false }, @@ -517,7 +552,7 @@ "12" ] }, - "execution_count": 8, + "execution_count": 33, "metadata": {}, "output_type": "execute_result" } @@ -528,7 +563,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 34, "metadata": { "collapsed": false }, @@ -539,7 +574,7 @@ "500000000" ] }, - "execution_count": 7, + "execution_count": 34, "metadata": {}, "output_type": "execute_result" } @@ -550,7 +585,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 35, "metadata": { "collapsed": false }, @@ -1294,7 +1329,7 @@ { "data": { "text/html": [ - "" + "" ], "text/plain": [ "" @@ -1306,21 +1341,21 @@ { "data": { "text/plain": [ - "" + "" ] }, - "execution_count": 7, + "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "qc.MatPlot(resA)" + "qc.MatPlot(resB)" ] }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 36, "metadata": { "collapsed": false }, @@ -2064,7 +2099,7 @@ { "data": { "text/html": [ - "" + "" ], "text/plain": [ "" @@ -2076,10 +2111,10 @@ { "data": { "text/plain": [ - "" + "" ] }, - "execution_count": 8, + "execution_count": 36, "metadata": {}, "output_type": "execute_result" } diff --git a/qcodes/instrument_drivers/AlazarTech/ATS.py b/qcodes/instrument_drivers/AlazarTech/ATS.py index 084ca36d14e9..ab9226663ac8 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS.py @@ -21,6 +21,7 @@ # TODO(nataliejpg) get_board_info and find_boards are broken?? # TODO(nataliejpg) call_dll error handling doesnt catch errors in expected way # TODO(nataliejpg) make use of _ATS_dll uniform +# TODO(nataliejpg) error if no trigger class AlazarTech_ATS(Instrument): # override dll_path in your init script or in the board constructor diff --git a/qcodes/instrument_drivers/AlazarTech/ATS_acquisition_controllers.py b/qcodes/instrument_drivers/AlazarTech/ATS_acquisition_controllers.py index 359a767624b0..09a2b2064177 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS_acquisition_controllers.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS_acquisition_controllers.py @@ -6,12 +6,12 @@ # Heterodyne Measurement Controller # returns unprocessed data averaged by record for 2 channel use class HD_Controller(AcquisitionController): - def __init__(self): + def __init__(self, freq_dif): + self.freq_dif = freq_dif self.samples_per_record = None self.bits_per_sample = None self.records_per_buffer = None self.buffers_per_acquisition = None - self.allocated_buffers = None self.number_of_channels = 2 self.buffer = None @@ -24,7 +24,13 @@ def pre_start_capture(self, alazar): self.buffer = np.zeros(self.samples_per_record * self.records_per_buffer * self.number_of_channels) - + sample_speed = alazar.get_sample_speed() + integer_list = np.arange(self.samples_per_record) + angle_list = (2 * np.pi * self.freq_dif / sample_speed * + integer_list) + self.cos_list = np.cos(angle_list) + self.sin_list = np.sin(angle_list) + def pre_acquire(self, alazar): # gets called after 'AlazarStartCapture' pass @@ -50,7 +56,21 @@ def post_acquire(self, alazar): i0 = (i * self.samples_per_record * self.number_of_channels) + 1 i1 = i0 + self.samples_per_record *self.number_of_channels recordB += self.buffer[i0:i1:self.number_of_channels] / records_per_acquisition - return recordA, recordB + + resA = self.fit(recordA) + resB = self.fit(recordB) + + return resA, resB + + def fit(self, rec): + # Discrete Fourier Transform + RePart = np.dot(rec, self.cos_list) / self.samples_per_record + ImPart = np.dot(rec, self.sin_list) / self.samples_per_record + + ampl = np.sqrt(RePart ** 2 + ImPart ** 2) + phase = math.atan2(ImPart, RePart) * 360 / (2 * math.pi) + + return [ampl, phase] # Test AcquisitionController tested on ATS9360 (nataliejpg) @@ -58,19 +78,15 @@ def post_acquire(self, alazar): class Test_AcquisitionController(AcquisitionController): def __init__(self): self.samples_per_record = None - self.bits_per_sample = None self.records_per_buffer = None self.buffers_per_acquisition = None - self.allocated_buffers = None self.number_of_channels = 2 self.buffer = None def pre_start_capture(self, alazar): - self.bits_per_sample = alazar.get_idn()['bits_per_sample'] self.samples_per_record = alazar.samples_per_record() self.records_per_buffer = alazar.records_per_buffer() self.buffers_per_acquisition = alazar.buffers_per_acquisition() - sample_speed = alazar.get_sample_speed() self.buffer = np.zeros(self.samples_per_record * self.records_per_buffer * self.number_of_channels) @@ -101,7 +117,7 @@ def post_acquire(self, alazar): i1 = i0 + self.samples_per_record *self.number_of_channels recordB += self.buffer[i0:i1:self.number_of_channels] / records_per_acquisition return recordA, recordB - + # DFT AcquisitionController From b242aa078d9ea9700d1bdc460ab8d92a2b94e639 Mon Sep 17 00:00:00 2001 From: Natalie Pearson Date: Mon, 8 Aug 2016 18:07:40 +0200 Subject: [PATCH 005/180] First steps to filter acquisition controller and docstrings --- qcodes/instrument_drivers/AlazarTech/ATS.py | 2 +- .../AlazarTech/ATS_acquisition_controllers.py | 53 +++++---- .../AlazarTech/local_test.py | 109 ++++++++++++++++++ .../AlazarTech/local_test2.py | 93 +++++++++++++++ 4 files changed, 236 insertions(+), 21 deletions(-) create mode 100644 qcodes/instrument_drivers/AlazarTech/local_test.py create mode 100644 qcodes/instrument_drivers/AlazarTech/local_test2.py diff --git a/qcodes/instrument_drivers/AlazarTech/ATS.py b/qcodes/instrument_drivers/AlazarTech/ATS.py index ab9226663ac8..04905d5e5a4a 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS.py @@ -638,7 +638,7 @@ def signal_to_volt(self, channel, signal): return (((signal - 127.5) / 127.5) * (self.parameters['channel_range' + str(channel)].get())) - # TODO(nataliejpg) surely this should be get_sample_rate? + # TODO(nataliejpg) some explanation for why this is called speed not rate? def get_sample_speed(self): if self.sample_rate.get() == 'EXTERNAL_CLOCK': raise Exception('External clock is used, alazar driver ' diff --git a/qcodes/instrument_drivers/AlazarTech/ATS_acquisition_controllers.py b/qcodes/instrument_drivers/AlazarTech/ATS_acquisition_controllers.py index 09a2b2064177..fa6daa438ec4 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS_acquisition_controllers.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS_acquisition_controllers.py @@ -2,31 +2,43 @@ import math import numpy as np - -# Heterodyne Measurement Controller -# returns unprocessed data averaged by record for 2 channel use class HD_Controller(AcquisitionController): + """Heterodyne Measurement Controller + Does averaged DFT on 2 channel Alazar measurement + + TODO(nataliejpg) handling of channel number + TODO(nataliejpg) test angle data + """ def __init__(self, freq_dif): self.freq_dif = freq_dif self.samples_per_record = None - self.bits_per_sample = None self.records_per_buffer = None self.buffers_per_acquisition = None self.number_of_channels = 2 self.buffer = None def pre_start_capture(self, alazar): - self.bits_per_sample = alazar.get_idn()['bits_per_sample'] + """Get config data from alazar card and set up DFT""" self.samples_per_record = alazar.samples_per_record() self.records_per_buffer = alazar.records_per_buffer() self.buffers_per_acquisition = alazar.buffers_per_acquisition() - sample_speed = alazar.get_sample_speed() + self.sample_rate = alazar.get_sample_speed() self.buffer = np.zeros(self.samples_per_record * self.records_per_buffer * self.number_of_channels) - sample_speed = alazar.get_sample_speed() + + # TODO(nataliejpg) leave super explicit or save lines? add error/logging? + averaging = self.buffers_per_acquisition * self.records_per_buffer + record_duration = self.samples_per_record/self.sample_rate + time_period_dif = 1/self.freq_dif + cycles_measured = record_duration / time_period_dif + oversampling_rate = self.sample_rate/(2*self.freq_dif) + print("Average over {} records".format(averaging)) + print("Oscillations per record: {} (expect 100+)".format(cycles_measured)) + print("Oversampling rate: {} (expect > 2)".format(oversampling_rate)) + integer_list = np.arange(self.samples_per_record) - angle_list = (2 * np.pi * self.freq_dif / sample_speed * + angle_list = (2 * np.pi * self.freq_dif / self.sample_rate * integer_list) self.cos_list = np.cos(angle_list) self.sin_list = np.sin(angle_list) @@ -39,10 +51,11 @@ def handle_buffer(self, alazar, data): self.buffer += data def post_acquire(self, alazar): - # average over records in buffer: - # for ATS9360 samples are arranged in the buffer as follows: - # S0A, S0B, ..., S1A, S1B, ... - # with SXY the sample number X of channel Y. + """Average over records in buffer and do DFT: + assumes samples are arranged in the buffer as follows: + S0A, S0B, ..., S1A, S1B, ... + with SXY the sample number X of channel Y. + """ records_per_acquisition = (1. * self.buffers_per_acquisition * self.records_per_buffer) recordA = np.zeros(self.samples_per_record) @@ -50,7 +63,6 @@ def post_acquire(self, alazar): i0 = i * self.samples_per_record * self.number_of_channels i1 = i0 + self.samples_per_record * self.number_of_channels recordA += self.buffer[i0:i1:self.number_of_channels] / records_per_acquisition - recordB = np.zeros(self.samples_per_record) for i in range(self.records_per_buffer): i0 = (i * self.samples_per_record * self.number_of_channels) + 1 @@ -63,19 +75,20 @@ def post_acquire(self, alazar): return resA, resB def fit(self, rec): - # Discrete Fourier Transform + """Do Discrete Fourier Transform and return magnitude and phase data""" RePart = np.dot(rec, self.cos_list) / self.samples_per_record ImPart = np.dot(rec, self.sin_list) / self.samples_per_record - - ampl = np.sqrt(RePart ** 2 + ImPart ** 2) - phase = math.atan2(ImPart, RePart) * 360 / (2 * math.pi) + # factor of 2 as amplitude is split between finite term and double frequency term + ampl = 2 * np.sqrt(RePart ** 2 + ImPart ** 2) + phase = math.atan2(ImPart, RePart) * 180 / (2 * math.pi) return [ampl, phase] -# Test AcquisitionController tested on ATS9360 (nataliejpg) -# returns unprocessed data averaged by record for 2 channel use -class Test_AcquisitionController(AcquisitionController): +class Basic_AcquisitionController(AcquisitionController): + """Basic AcquisitionController tested on ATS9360 + returns unprocessed data averaged by record with 2 channels + """ def __init__(self): self.samples_per_record = None self.records_per_buffer = None diff --git a/qcodes/instrument_drivers/AlazarTech/local_test.py b/qcodes/instrument_drivers/AlazarTech/local_test.py new file mode 100644 index 000000000000..6e85961fe531 --- /dev/null +++ b/qcodes/instrument_drivers/AlazarTech/local_test.py @@ -0,0 +1,109 @@ +from .ATS import AcquisitionController +import math +import numpy as np +import matplotlib.pyplot as plt + + +class Controller(): + def __init__(self, dif_freq): + self.dif_freq = dif_freq + self.sample_rate = 500000000 + self.samples_per_record = 1024 + + record_duration = self.samples_per_record/self.sample_rate + dif_time_period = 1/self.dif_freq + cycles_measured = record_duration / dif_time_period + oversampling_rate = self.sample_rate/(2*self.dif_freq) + print("Measuring from "+str(cycles_measured)+" samples should be on the order of 100 at least") + print("Oversampling rate is "+str(oversampling_rate)+" should be > 2") + + def pre_start_capture(self): + self.integer_list = np.arange(self.samples_per_record) + self.angle_list = (2 * np.pi * self.dif_freq / self.sample_rate * + self.integer_list) + + self.cos_list = np.cos(self.angle_list) + self.sin_list = np.sin(self.angle_list) + + def fit(self, rec): + # Discrete Fourier Transform + RePart = np.dot(rec, self.cos_list) / self.samples_per_record + ImPart = np.dot(rec, self.sin_list) / self.samples_per_record + # factor of 2 is because amplitude is split between finite term and + # double frequency term which averages to 0 + ampl = 2 * np.sqrt(RePart ** 2 + ImPart ** 2) + phase = math.atan2(ImPart, RePart) * 180 / (2 * math.pi) + + return [ampl, phase] + + def pre_acquire(self, alazar): + # gets called after 'AlazarStartCapture' + pass + + def handle_buffer(self, alazar, data): + self.buffer += data + + def post_acquire(self, alazar): + # average over records in buffer: + # for ATS9360 samples are arranged in the buffer as follows: + # S0A, S0B, ..., S1A, S1B, ... + # with SXY the sample number X of channel Y. + records_per_acquisition = (1. * self.buffers_per_acquisition * + self.records_per_buffer) + recordA = np.zeros(self.samples_per_record) + for i in range(self.records_per_buffer): + i0 = i * self.samples_per_record * self.number_of_channels + i1 = i0 + self.samples_per_record * self.number_of_channels + recordA += self.buffer[i0:i1:self.number_of_channels] / records_per_acquisition + + recordB = np.zeros(self.samples_per_record) + for i in range(self.records_per_buffer): + i0 = (i * self.samples_per_record * self.number_of_channels) + 1 + i1 = i0 + self.samples_per_record *self.number_of_channels + recordB += self.buffer[i0:i1:self.number_of_channels] / records_per_acquisition + + resA = self.fit(recordA) + resB = self.fit(recordB) + + return resA, resB + + +def make_rec(controller, freq, phase_deg): + phase_rad = phase_deg*2*np.pi/180 + angle_list = (2 * np.pi * freq / controller.sample_rate * + controller.integer_list)+phase_rad + rec = np.cos(angle_list) + return rec + +def main(freq1, phase): + c = Controller(freq1) + c.pre_start_capture() + ran = 100 + l = [[],[]] + for i in range(ran+1): + freq = freq1-0.002*freq1*(ran/2-i) + rec = make_rec(c, freq, phase) + mag, phase = c.fit(rec) + l[0].append(mag) + l[1].append(phase) + plt.figure(1) + plt.subplot(211) + plt.plot(l[0]) + plt.subplot(212) + plt.plot(l[1]) + plt.show() + # cos_rec = np.multiply(c.cos_list, rec) + # sin_rec = np.multiply(c.sin_list, rec) + #print(c.fit(rec)) + # plt.figure(1) + # plt.subplot(511) + # plt.plot(c.cos_list) + # plt.subplot(512) + # plt.plot(c.sin_list) + # plt.subplot(513) + # plt.plot(rec) + # plt.subplot(514) + # plt.plot(cos_rec) + # plt.subplot(515) + # plt.plot(sin_rec) + # plt.show() diff --git a/qcodes/instrument_drivers/AlazarTech/local_test2.py b/qcodes/instrument_drivers/AlazarTech/local_test2.py new file mode 100644 index 000000000000..9ce6f502e193 --- /dev/null +++ b/qcodes/instrument_drivers/AlazarTech/local_test2.py @@ -0,0 +1,93 @@ +from .ATS import AcquisitionController +import math +import numpy as np +import matplotlib.pyplot as plt +from scipy import signal + + +class Controller(): + def __init__(self, dif_freq): + self.dif_freq = dif_freq + self.sample_rate = 5000000 + self.samples_per_record = 10024 + + record_duration = self.samples_per_record/self.sample_rate + dif_time_period = 1/self.dif_freq + cycles_measured = record_duration / dif_time_period + oversampling_rate = self.sample_rate/(2*self.dif_freq) + print("Measuring from "+str(cycles_measured)+" samples should be on the order of 100 at least") + print("Oversampling rate is "+str(oversampling_rate)+" should be > 2") + + def pre_start_capture(self): + self.integer_list = np.arange(self.samples_per_record) + self.angle_list = (2 * np.pi * self.dif_freq / self.sample_rate * + self.integer_list) + + self.cos_list = np.cos(self.angle_list) + self.sin_list = np.sin(self.angle_list) + + def pre_acquire(self, alazar): + # gets called after 'AlazarStartCapture' + pass + + def handle_buffer(self, alazar, data): + self.buffer += data + + def post_acquire(self, alazar): + # average over records in buffer: + # for ATS9360 samples are arranged in the buffer as follows: + # S0A, S0B, ..., S1A, S1B, ... + # with SXY the sample number X of channel Y. + records_per_acquisition = (1. * self.buffers_per_acquisition * + self.records_per_buffer) + recordA = np.zeros(self.samples_per_record) + for i in range(self.records_per_buffer): + i0 = i * self.samples_per_record * self.number_of_channels + i1 = i0 + self.samples_per_record * self.number_of_channels + recordA += self.buffer[i0:i1:self.number_of_channels] / records_per_acquisition + + recordB = np.zeros(self.samples_per_record) + for i in range(self.records_per_buffer): + i0 = (i * self.samples_per_record * self.number_of_channels) + 1 + i1 = i0 + self.samples_per_record *self.number_of_channels + recordB += self.buffer[i0:i1:self.number_of_channels] / records_per_acquisition + + resA = self.fit(recordA) + resB = self.fit(recordB) + + return resA, resB + +def make_rec(controller, freq, phase_deg): + phase_rad = phase_deg*2*np.pi/180 + angle_list = (2 * np.pi * freq / controller.sample_rate * + controller.integer_list)+phase_rad + rec = np.cos(angle_list) + return rec + +def main(freq1, freq2): + c = Controller(freq1) + c.pre_start_capture() + rec1 = make_rec(c, freq2, 0) + rec2 = c.cos_list + plt.figure(1) + plt.subplot(211) + plt.plot(rec1) + plt.subplot(212) + plt.plot(rec1) + plt.show() + s = np.multiply(rec1, rec2) + plt.plot(s) + plt.show() + + +n = 61 +a = signal.firwin(n, cutoff = 0.3, window = "hamming") +#Frequency and phase response +mfreqz(a) +show() +#Impulse and step response +figure(2) +impz(a) +show() + + # import qcodes.instrument_drivers.AlazarTech.local_test2 as cont From 3a27d4396a5362baf99b401351e554bbaa472f11 Mon Sep 17 00:00:00 2001 From: Natalie Pearson Date: Thu, 11 Aug 2016 19:09:32 +0200 Subject: [PATCH 006/180] feat: variety of QDev acquisition controllers created, not complete --- .../QDev_acquisition_controllers.py | 246 ++++++++++++++++++ 1 file changed, 246 insertions(+) create mode 100644 qcodes/instrument_drivers/AlazarTech/QDev_acquisition_controllers.py diff --git a/qcodes/instrument_drivers/AlazarTech/QDev_acquisition_controllers.py b/qcodes/instrument_drivers/AlazarTech/QDev_acquisition_controllers.py new file mode 100644 index 000000000000..c34bc08080c6 --- /dev/null +++ b/qcodes/instrument_drivers/AlazarTech/QDev_acquisition_controllers.py @@ -0,0 +1,246 @@ +from .ATS import AcquisitionController +from scipy import signal +import numpy as np + + +class Filtering_Controller(): + """Filtering Measurement Controller + If 1 channel: + Mixes reference software signal with input hardware signal, + filters out double frequency component and returns magnitude and + phase data for dc component. Throws away channel 2 + If 2 channels: + Uses two hardware channels to find magnitude and + phase data for dc component + + TODO(nataliejpg) test diffrent filters and window types + TODO(nataliejpg) numtaps logic + TODO(nataliejpg) cutoff logic + TODO(nataliejpg) post aqcuire one input stuff?? + """ + + def __init__(self, dif_freq, numtaps, cutoff, number_of_channels): + self.dif_freq = dif_freq + self.sample_rate = 50000000 + self.samples_per_record = 10024 + self.buffers_per_acquisition = None + self.number_of_channels = number_of_channels + self.numtaps = numtaps + self.cutoff = cutoff + self.delay = numtaps - 1 + self.buffer = None + + def pre_start_capture(self): + record_duration = self.samples_per_record / self.sample_rate + time_period_dif = 1 / self.dif_freq + cycles_measured = record_duration / time_period_dif + oversampling_rate = self.sample_rate / (2 * self.dif_freq) + print("Oscillations per record: {:.2f} (expect 100+)" + .format(cycles_measured)) + print("Oversampling rate: {:.2f} (expect > 2)" + .format(oversampling_rate)) + print("Filtering delay is {} samples".format(self.delay)) + + integer_list = np.arange(self.samples_per_record) + if self.number_of_channels == 2: + angle_list = (2 * np.pi * self.freq_dif / self.sample_rate * + integer_list) + self.cos_list = np.cos(angle_list) + self.sin_list = np.sin(angle_list) + elif self.number_of_channels == 1: + angle_shift = 90 + self.sample_shift = (2 * np.pi * self.freq_dif / self.sample_rate * + angle_shift) + + def pre_acquire(self, alazar): + # gets called after 'AlazarStartCapture' + pass + + def handle_buffer(self, alazar, data): + self.buffer += data + + def post_acquire(self, alazar): + """Average over records in buffer, mix and filter double freq + if 1 chan selected recordA is mixed with software signal + if 2 chan selected recordA and recordB are mixed + """ + records_per_acquisition = (1. * self.buffers_per_acquisition * + self.records_per_buffer) + recordA = np.zeros(self.samples_per_record) + for i in range(self.records_per_buffer): + i0 = (i * self.samples_per_record * self.number_of_channels) + i1 = (i0 + self.samples_per_record * self.number_of_channels) + recordA += (self.buffer[i0:i1:self.number_of_channels] / + records_per_acquisition) + recordB = np.zeros(self.samples_per_record) + for i in range(self.records_per_buffer): + i0 = (i * self.samples_per_record * self.number_of_channels + 1) + i1 = (i0 + self.samples_per_record * self.number_of_channels) + recordB += (self.buffer[i0:i1:self.number_of_channels] / + records_per_acquisition) + + if self.number_of_channels == 1: + mixA_re = np.multiply(self.cos_list, recordA) + mixA_im = np.multiply(self.sin_list, recordA) + mixA_re_filtered = filter(mixA_re) + mixA_im_filtered = filter(mixA_im) + mixA_complex = mixA_re_filtered + mixA_im_filtered * 1j + magA = 2 * abs(mixA_complex) + phaseA = 2 * np.angle(mixA_complex, deg=True) + return magA, phaseA + elif self.number_of_channels == 2: + recordB_shifted = np.roll(recordB, self.sample_shift) + mixAB_re = np.multiply(recordA, recordB) + mixAB_im = np.multiply(recordA, recordB_shifted) + mixAB_re_filtered = filter(mixAB_re) + mixAB_im_filtered = filter(mixAB_im) + mixAB_complex = mixAB_re_filtered + mixAB_im_filtered * 1j + magAB = 2 * abs(mixAB_complex) + phaseAB = 2 * np.angle(mixAB_complex, deg=True) + return magAB, phaseAB + + def filter(self, rec): + """FIR window filter applied to filter out high freq components + """ + sample_rate = self.sample_rate + nyq_rate = sample_rate / 2. + fir_coef = signal.firwin(self.numtaps, self.cutoff / nyq_rate) + filtered_rec = signal.lfilter(fir_coef, 1.0, rec) + return filtered_rec + + +class HD_Controller(AcquisitionController): + """Averaging Heterodyne Measurement Controller + Does averaged DFT on 2 channel Alazar measurement + + TODO(nataliejpg) handling of channel number + TODO(nataliejpg) test angle data + """ + + def __init__(self, freq_dif): + self.freq_dif = freq_dif + self.samples_per_record = None + self.records_per_buffer = None + self.buffers_per_acquisition = None + self.number_of_channels = 2 + self.buffer = None + + def pre_start_capture(self, alazar): + """Get config data from alazar card and set up DFT""" + self.samples_per_record = alazar.samples_per_record() + self.records_per_buffer = alazar.records_per_buffer() + self.buffers_per_acquisition = alazar.buffers_per_acquisition() + self.sample_rate = alazar.get_sample_speed() + self.buffer = np.zeros(self.samples_per_record * + self.records_per_buffer * + self.number_of_channels) + # TODO(nataliejpg) leave explicit or save lines? add error/logging? + averaging = self.buffers_per_acquisition * self.records_per_buffer + record_duration = self.samples_per_record / self.sample_rate + time_period_dif = 1 / self.freq_dif + cycles_measured = record_duration / time_period_dif + oversampling_rate = self.sample_rate / (2 * self.freq_dif) + print("Average over {:.2f} records".format(averaging)) + print("Oscillations per record: {:.2f} (expect 100+)" + .format(cycles_measured)) + print("Oversampling rate: {:.2f} (expect > 2)" + .format(oversampling_rate)) + + integer_list = np.arange(self.samples_per_record) + angle_list = (2 * np.pi * self.freq_dif / self.sample_rate * + integer_list) + self.cos_list = np.cos(angle_list) + self.sin_list = np.sin(angle_list) + + def pre_acquire(self, alazar): + # gets called after 'AlazarStartCapture' + pass + + def handle_buffer(self, alazar, data): + self.buffer += data + + def post_acquire(self, alazar): + """Average over records in buffer and do DFT: + assumes samples are arranged in the buffer as follows: + S0A, S0B, ..., S1A, S1B, ... + with SXY the sample number X of channel Y. + """ + records_per_acquisition = (1. * self.buffers_per_acquisition * + self.records_per_buffer) + recordA = np.zeros(self.samples_per_record) + for i in range(self.records_per_buffer): + i0 = (i * self.samples_per_record * self.number_of_channels) + i1 = (i0 + self.samples_per_record * self.number_of_channels) + recordA += (self.buffer[i0:i1:self.number_of_channels] / + records_per_acquisition) + recordB = np.zeros(self.samples_per_record) + for i in range(self.records_per_buffer): + i0 = (i * self.samples_per_record * self.number_of_channels + 1) + i1 = (i0 + self.samples_per_record * self.number_of_channels) + recordB += (self.buffer[i0:i1:self.number_of_channels] / + records_per_acquisition) + + resA = self.fit(recordA) + resB = self.fit(recordB) + + return resA, resB + + def fit(self, rec): + """Do Discrete Fourier Transform and return magnitude and phase data""" + RePart = np.dot(rec, self.cos_list) / self.samples_per_record + ImPart = np.dot(rec, self.sin_list) / self.samples_per_record + complex_num = RePart - ImPart * 1j + # factor of 2 in ampl is due to loss of averaged double frequency term + ampl = 2 * abs(complex_num) + phase = np.angle(complex_num, deg=True) + return [ampl, phase] + + +class Basic_AcquisitionController(AcquisitionController): + """Basic AcquisitionController tested on ATS9360 + returns unprocessed data averaged by record with 2 channels + """ + + def __init__(self): + self.samples_per_record = None + self.records_per_buffer = None + self.buffers_per_acquisition = None + self.number_of_channels = 2 + self.buffer = None + + def pre_start_capture(self, alazar): + self.samples_per_record = alazar.samples_per_record() + self.records_per_buffer = alazar.records_per_buffer() + self.buffers_per_acquisition = alazar.buffers_per_acquisition() + self.buffer = np.zeros(self.samples_per_record * + self.records_per_buffer * + self.number_of_channels) + + def pre_acquire(self, alazar): + # gets called after 'AlazarStartCapture' + pass + + def handle_buffer(self, alazar, data): + self.buffer += data + + def post_acquire(self, alazar): + # average over records in buffer: + # for ATS9360 samples are arranged in the buffer as follows: + # S0A, S0B, ..., S1A, S1B, ... + # with SXY the sample number X of channel Y. + records_per_acquisition = (self.buffers_per_acquisition * + self.records_per_buffer) + recordA = np.zeros(self.samples_per_record) + for i in range(self.records_per_buffer): + i0 = (i * self.samples_per_record * self.number_of_channels) + i1 = (i0 + self.samples_per_record * self.number_of_channels) + recordA += (self.buffer[i0:i1:self.number_of_channels] / + records_per_acquisition) + + recordB = np.zeros(self.samples_per_record) + for i in range(self.records_per_buffer): + i0 = (i * self.samples_per_record * self.number_of_channels + 1) + i1 = (i0 + self.samples_per_record * self.number_of_channels) + recordB += (self.buffer[i0:i1:self.number_of_channels] / + records_per_acquisition) + return recordA, recordB From 23cde4e962878b14fc34edb549e039077b340eb6 Mon Sep 17 00:00:00 2001 From: Natalie Pearson Date: Mon, 15 Aug 2016 09:38:52 +0200 Subject: [PATCH 007/180] refactor/style: comments and docstings tidy up and temporary test refactor --- qcodes/instrument_drivers/AlazarTech/ATS.py | 3 +- .../instrument_drivers/AlazarTech/ATS9360.py | 16 ++- .../AlazarTech/ATS_acquisition_controllers.py | 68 +++++----- .../AlazarTech/HD_test_controller.py | 105 +++++++++++++++ .../AlazarTech/filter1_test_controller.py | 124 +++++++++++++++++ .../AlazarTech/filter2_test_controller.py | 126 ++++++++++++++++++ .../AlazarTech/local_test.py | 109 --------------- .../AlazarTech/local_test2.py | 93 ------------- 8 files changed, 403 insertions(+), 241 deletions(-) create mode 100644 qcodes/instrument_drivers/AlazarTech/HD_test_controller.py create mode 100644 qcodes/instrument_drivers/AlazarTech/filter1_test_controller.py create mode 100644 qcodes/instrument_drivers/AlazarTech/filter2_test_controller.py delete mode 100644 qcodes/instrument_drivers/AlazarTech/local_test.py delete mode 100644 qcodes/instrument_drivers/AlazarTech/local_test2.py diff --git a/qcodes/instrument_drivers/AlazarTech/ATS.py b/qcodes/instrument_drivers/AlazarTech/ATS.py index 04905d5e5a4a..df0940f3a881 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS.py @@ -23,6 +23,7 @@ # TODO(nataliejpg) make use of _ATS_dll uniform # TODO(nataliejpg) error if no trigger + class AlazarTech_ATS(Instrument): # override dll_path in your init script or in the board constructor # if you have it somewhere else @@ -193,7 +194,7 @@ def get_board_info(cls, dll, system_id, board_id): def __init__(self, name, system_id=1, board_id=1, dll_path=None, **kwargs): super().__init__(name, **kwargs) self._ATS_dll = None - + if os.name == 'nt': self._ATS_dll = ctypes.cdll.LoadLibrary(dll_path or self.dll_path) else: diff --git a/qcodes/instrument_drivers/AlazarTech/ATS9360.py b/qcodes/instrument_drivers/AlazarTech/ATS9360.py index 5703d92a6bd5..a564c01a9fbb 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS9360.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS9360.py @@ -6,8 +6,7 @@ class AlazarTech_ATS9360(AlazarTech_ATS): def __init__(self, name, server_name=None): dll_path = 'C:\\WINDOWS\\System32\\ATSApi.dll' super().__init__(name, dll_path=dll_path) - - samplesPerSec = None + # add parameters # ----- Parameters for the configuration of the board ----- @@ -133,7 +132,7 @@ def __init__(self, name, server_name=None): unit='Sample clock cycles', value=0, vals=validators.Ints(min_value=0)) - + # NOTE: The board will wait for a for this amount of time for a # trigger event. If a trigger event does not arrive, then the # board will automatically trigger. Set the trigger timeout value @@ -149,7 +148,6 @@ def __init__(self, name, server_name=None): unit='10 us', value=0, vals=validators.Ints(min_value=0)) - # ----- Parameters for the acquire function ----- self.add_parameter(name='mode', @@ -169,8 +167,12 @@ def __init__(self, name, server_name=None): # TODO (M) figure out if this also has to be a multiple of something, # I could not find this in the documentation but somehow I have the # feeling it still should be a multiple of something - # NOTE by ramiro: At least in previous python implementations(PycQED delft), this is an artifact for compatibility with AWG sequencing, not particular to any ATS architecture. - # ==> this is a construction imposed by the memory strategy implemented on the python driver we are writing, not limited by any actual ATS feature. + # NOTE by ramiro: At least in previous python implementations(PycQED delft), + # this is an artifact for compatibility with AWG sequencing, + # not particular to any ATS architecture. + # ==> this is a construction imposed by the memory strategy + # implemented on the python driver + # we are writing, not limited by any actual ATS feature. self.add_parameter(name='records_per_buffer', parameter_class=AlazarParameter, @@ -255,7 +257,7 @@ def __init__(self, name, server_name=None): # TODO (M) make parameter for board type # TODO (M) check board kind - + class Multiples(validators.Ints): ''' diff --git a/qcodes/instrument_drivers/AlazarTech/ATS_acquisition_controllers.py b/qcodes/instrument_drivers/AlazarTech/ATS_acquisition_controllers.py index fa6daa438ec4..538cc9b93eaf 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS_acquisition_controllers.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS_acquisition_controllers.py @@ -2,13 +2,15 @@ import math import numpy as np + class HD_Controller(AcquisitionController): """Heterodyne Measurement Controller - Does averaged DFT on 2 channel Alazar measurement + Does averaged DFT on 2 channel Alazar measurement TODO(nataliejpg) handling of channel number TODO(nataliejpg) test angle data """ + def __init__(self, freq_dif): self.freq_dif = freq_dif self.samples_per_record = None @@ -24,17 +26,17 @@ def pre_start_capture(self, alazar): self.buffers_per_acquisition = alazar.buffers_per_acquisition() self.sample_rate = alazar.get_sample_speed() self.buffer = np.zeros(self.samples_per_record * - self.records_per_buffer * - self.number_of_channels) - - # TODO(nataliejpg) leave super explicit or save lines? add error/logging? + self.records_per_buffer * + self.number_of_channels) + # TODO(nataliejpg) leave explicit or save lines? add error/logging? averaging = self.buffers_per_acquisition * self.records_per_buffer - record_duration = self.samples_per_record/self.sample_rate - time_period_dif = 1/self.freq_dif + record_duration = self.samples_per_record / self.sample_rate + time_period_dif = 1 / self.freq_dif cycles_measured = record_duration / time_period_dif - oversampling_rate = self.sample_rate/(2*self.freq_dif) + oversampling_rate = self.sample_rate / (2 * self.freq_dif) print("Average over {} records".format(averaging)) - print("Oscillations per record: {} (expect 100+)".format(cycles_measured)) + print("Oscillations per record: {} (expect 100+)" + .format(cycles_measured)) print("Oversampling rate: {} (expect > 2)".format(oversampling_rate)) integer_list = np.arange(self.samples_per_record) @@ -42,7 +44,7 @@ def pre_start_capture(self, alazar): integer_list) self.cos_list = np.cos(angle_list) self.sin_list = np.sin(angle_list) - + def pre_acquire(self, alazar): # gets called after 'AlazarStartCapture' pass @@ -60,28 +62,30 @@ def post_acquire(self, alazar): self.records_per_buffer) recordA = np.zeros(self.samples_per_record) for i in range(self.records_per_buffer): - i0 = i * self.samples_per_record * self.number_of_channels - i1 = i0 + self.samples_per_record * self.number_of_channels - recordA += self.buffer[i0:i1:self.number_of_channels] / records_per_acquisition + i0 = (i * self.samples_per_record * self.number_of_channels) + i1 = (i0 + self.samples_per_record * self.number_of_channels) + recordA += (self.buffer[i0:i1:self.number_of_channels] / + records_per_acquisition) recordB = np.zeros(self.samples_per_record) for i in range(self.records_per_buffer): - i0 = (i * self.samples_per_record * self.number_of_channels) + 1 - i1 = i0 + self.samples_per_record *self.number_of_channels - recordB += self.buffer[i0:i1:self.number_of_channels] / records_per_acquisition - + i0 = (i * self.samples_per_record * self.number_of_channels + 1) + i1 = (i0 + self.samples_per_record * self.number_of_channels) + recordB += (self.buffer[i0:i1:self.number_of_channels] / + records_per_acquisition) + resA = self.fit(recordA) resB = self.fit(recordB) - + return resA, resB - + def fit(self, rec): """Do Discrete Fourier Transform and return magnitude and phase data""" RePart = np.dot(rec, self.cos_list) / self.samples_per_record ImPart = np.dot(rec, self.sin_list) / self.samples_per_record - # factor of 2 as amplitude is split between finite term and double frequency term + # factor of 2 as amplitude is split between finite term + # and double frequency term ampl = 2 * np.sqrt(RePart ** 2 + ImPart ** 2) phase = math.atan2(ImPart, RePart) * 180 / (2 * math.pi) - return [ampl, phase] @@ -89,6 +93,7 @@ class Basic_AcquisitionController(AcquisitionController): """Basic AcquisitionController tested on ATS9360 returns unprocessed data averaged by record with 2 channels """ + def __init__(self): self.samples_per_record = None self.records_per_buffer = None @@ -101,8 +106,8 @@ def pre_start_capture(self, alazar): self.records_per_buffer = alazar.records_per_buffer() self.buffers_per_acquisition = alazar.buffers_per_acquisition() self.buffer = np.zeros(self.samples_per_record * - self.records_per_buffer * - self.number_of_channels) + self.records_per_buffer * + self.number_of_channels) def pre_acquire(self, alazar): # gets called after 'AlazarStartCapture' @@ -116,21 +121,22 @@ def post_acquire(self, alazar): # for ATS9360 samples are arranged in the buffer as follows: # S0A, S0B, ..., S1A, S1B, ... # with SXY the sample number X of channel Y. - records_per_acquisition = (1. * self.buffers_per_acquisition * + records_per_acquisition = (self.buffers_per_acquisition * self.records_per_buffer) recordA = np.zeros(self.samples_per_record) for i in range(self.records_per_buffer): - i0 = i * self.samples_per_record * self.number_of_channels - i1 = i0 + self.samples_per_record * self.number_of_channels - recordA += self.buffer[i0:i1:self.number_of_channels] / records_per_acquisition + i0 = (i * self.samples_per_record * self.number_of_channels) + i1 = (i0 + self.samples_per_record * self.number_of_channels) + recordA += (self.buffer[i0:i1:self.number_of_channels] / + records_per_acquisition) recordB = np.zeros(self.samples_per_record) for i in range(self.records_per_buffer): - i0 = (i * self.samples_per_record * self.number_of_channels) + 1 - i1 = i0 + self.samples_per_record *self.number_of_channels - recordB += self.buffer[i0:i1:self.number_of_channels] / records_per_acquisition + i0 = (i * self.samples_per_record * self.number_of_channels + 1) + i1 = (i0 + self.samples_per_record * self.number_of_channels) + recordB += (self.buffer[i0:i1:self.number_of_channels] / + records_per_acquisition) return recordA, recordB - # DFT AcquisitionController diff --git a/qcodes/instrument_drivers/AlazarTech/HD_test_controller.py b/qcodes/instrument_drivers/AlazarTech/HD_test_controller.py new file mode 100644 index 000000000000..f9b4e751cd16 --- /dev/null +++ b/qcodes/instrument_drivers/AlazarTech/HD_test_controller.py @@ -0,0 +1,105 @@ +from .ATS import AcquisitionController +import math +import numpy as np +import matplotlib.pyplot as plt + +# HD_ test controller +class Controller(): + def __init__(self, dif_freq): + self.dif_freq = dif_freq + self.sample_rate = 10000000 + self.samples_per_record = 2024 + + record_duration = self.samples_per_record / self.sample_rate + time_period_dif = 1 / self.dif_freq + cycles_measured = record_duration / time_period_dif + oversampling_rate = self.sample_rate / (2 * self.dif_freq) + print("Oscillations per record: {:.2f} (expect 100+)".format(cycles_measured)) + print("Oversampling rate: {:.2f} (expect > 2)".format(oversampling_rate)) + + def pre_start_capture(self): + self.integer_list = np.arange(self.samples_per_record) + self.angle_list = (2 * np.pi * self.dif_freq / self.sample_rate * + self.integer_list) + + self.cos_list = np.cos(self.angle_list) + self.sin_list = np.sin(self.angle_list) + + def fit(self, rec): + # Discrete Fourier Transform + RePart = np.dot(rec, self.cos_list) / self.samples_per_record + ImPart = np.dot(rec, self.sin_list) / self.samples_per_record + # factor of 2 is because amplitude is split between finite term and + # double frequency term which averages to 0 + complex_num = RePart - ImPart*1j + ampl = 2 * abs(complex_num) + phase = np.angle(complex_num, deg=True) + + return [ampl, phase] + +def make_rec(controller, freq, phase_deg): + phase_rad = phase_deg*np.pi/180 + angle_list = (2 * np.pi * freq / controller.sample_rate * + controller.integer_list)+phase_rad + rec = np.cos(angle_list) + return rec + +def main(freq, phase_dif): + # make an acqisition controller and set up sin and cos software signals + c = Controller(freq) + c.pre_start_capture() + + # make a 'hardware' signal with same frequency shifted by phase + # mix with software signals to make real and imaginary parts of mixed signal + rec = make_rec(c, freq, phase_dif) + cos_rec = np.multiply(c.cos_list, rec) + sin_rec = np.multiply(c.sin_list, rec) + + # print averaged magnitude and phase of mixed signal + # should give dc part of signal as double frequency part averages out + print(" mag, phase : "+str(c.fit(rec))) + plt.figure(1) + plt.subplot(311) + plt.plot(c.cos_list[:100], "-r") + plt.plot(c.sin_list[:100], "-g") + plt.title('"software" signals') + plt.subplot(312) + plt.plot(rec[:100]) + plt.title('"hardware" signal') + plt.subplot(313) + plt.plot(cos_rec[:100], "-r") + plt.plot(sin_rec[:100], "-g") + plt.title('re and im parts of mixed signal') + plt.show() + + # sweep 'hardware' signal frequency through software signal and + # observe magnitude and phase response + point_ran = 10000 + sweep_mag = [[],[]] + for i in range(point_ran+1): + freq_ran = 0.2*freq + shift_freq = (freq_ran/point_ran)*(-point_ran/2+i) + rec = make_rec(c, freq+shift_freq, 0) + mag, phase = c.fit(rec) + sweep_mag[1].append(mag) + sweep_mag[0].append(shift_freq) + sweep_phase = [[],[]] + for i in range(point_ran+1): + angle_ran = 45 + shift_phase = (angle_ran/point_ran)*(-point_ran/2+i) + rec = make_rec(c, freq, phase_dif+shift_phase) + mag, phase = c.fit(rec) + sweep_phase[1].append(phase) + sweep_phase[0].append(shift_phase) + plt.figure(1) + plt.subplot(211) + plt.title('sweep:magnitude response') + plt.plot(sweep_mag[0], sweep_mag[1]) + plt.subplot(212) + plt.title('sweep:phase response') + plt.plot(sweep_phase[0], sweep_phase[1]) + plt.show() + + + + # import qcodes.instrument_drivers.AlazarTech.HD_test_controller as cont diff --git a/qcodes/instrument_drivers/AlazarTech/filter1_test_controller.py b/qcodes/instrument_drivers/AlazarTech/filter1_test_controller.py new file mode 100644 index 000000000000..6efae1d80321 --- /dev/null +++ b/qcodes/instrument_drivers/AlazarTech/filter1_test_controller.py @@ -0,0 +1,124 @@ +import numpy as np +import matplotlib.pyplot as plt +from scipy import signal + +# one channel filter controller +class Controller(): + def __init__(self, dif_freq): + self.dif_freq = dif_freq + self.sample_rate = 500000000 + self.samples_per_record = 10024 + + record_duration = self.samples_per_record/self.sample_rate + dif_time_period = 1/self.dif_freq + cycles_measured = record_duration / dif_time_period + oversampling_rate = self.sample_rate/(2*self.dif_freq) + print("Measuring from "+str(cycles_measured)+" samples should be on the order of 100 at least") + print("Oversampling rate is "+str(oversampling_rate)+" should be > 2") + + def pre_start_capture(self): + self.integer_list = np.arange(self.samples_per_record) + self.angle_list = (2 * np.pi * self.dif_freq / self.sample_rate * + self.integer_list) + + self.cos_list = np.cos(self.angle_list) + self.sin_list = np.sin(self.angle_list) + +def filter(controller, rec, numtaps, cutoff): + sample_rate = controller.sample_rate + print("sample_rate is "+str(sample_rate)) + nyq_rate = sample_rate / 2. + print("nyq_rate is "+ str(nyq_rate)) + delay = (numtaps-1) + fir_coef = signal.firwin(numtaps, cutoff/nyq_rate, window = "hamming") + filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec) + w, h = signal.freqz(fir_coef) + plt.plot(w*controller.sample_rate/(2*np.pi), 20 * np.log10(abs(h)), 'b') + plt.ylabel('Amplitude [dB]', color='b') + plt.xlabel('Frequency [rad/sample]') + plt.show() + return fir_coef, filtered_rec, delay + +def make_rec(controller, freq, ampdif, phase_deg): + phase_rad = phase_deg*2*np.pi/360 + angle_list = (2 * np.pi * freq * controller.integer_list / controller.sample_rate)+phase_rad + rec = ampdif*np.cos(angle_list) + return rec + +def main(freq1, freq2, phasedif, ampdif, numtaps, cutoff): + # make an acquisition controller (and sampling rate warnings related to + # given freq1) and integer list used for signal making + c = Controller(freq1) + c.pre_start_capture() + + # make one hardware signal with given frequency and phase difference + # make a software signal with real and imaginary parts + # plot first 100 points of each + rec1 = make_rec(c, freq2, phase_deg=phasedif, ampdif=ampdif) + plt.figure(1) + plt.subplot(211) + plt.plot(rec1[:100]) + plt.subplot(212) + plt.plot(rec2[:100]) + plt.show() + + # mix hardware signals and filter out frequencies above cutoff + # should leave only freq_dif component + rec12 = np.multiply(rec1, rec2) + fir_coef, filtered_rec_12 = filter(c, rec12, numtaps, cutoff) + delay = numtaps-1 + + # plot filter + w, h = signal.freqz(fir_coef) + freq_axis = (w/np.pi)*c.sample_rate + fig = plt.figure(1) + ax1 = fig.add_subplot(111) + plt.title('Digital filter frequency response') + plt.plot(freq_axis, 20 * np.log10(abs(h)), 'b') + plt.ylabel('Amplitude [dB]', color='b') + plt.xlabel('Frequency [Hz]') + + ax2 = ax1.twinx() + angles = np.unwrap(np.angle(h)) + plt.plot(freq_axis, angles, 'g') + plt.ylabel('Angle (radians)', color='g') + plt.grid() + plt.axis('tight') + plt.show() + + + # shift first hardware signal by 90 degrees to make + # sin signal for mixing, mix and plot + rec3 = make_rec(c, freq1, sin=True) + rec23 = np.multiply(rec2, rec3) + fir_coef, filtered_rec_23 = filter(c, rec23, numtaps, cutoff) + + # plot filtered signal and magnitude and phase results + plt.figure(1) + plt.subplot(411) + plt.title('Re part') + plt.plot(rec12, '-r') + plt.ylabel('unfiltered record', color='r') + plt.plot(filtered_rec_12, '-g') + plt.ylabel('filtered record', color='g') + plt.subplot(412) + plt.title('Im part') + plt.plot(rec23, '-r') + plt.ylabel('unfiltered record', color='r') + plt.plot(filtered_rec_23, '-g') + plt.ylabel('filtered record', color='g') + + # add to plot magnitude and phase of resulting complex number + complex_rec = filtered_rec_12+filtered_rec_23*1j + magnitude = abs(complex_rec) + phase = np.angle(complex_rec, deg=True) + plt.subplot(413) + plt.title('Magnitude') + plt.plot(magnitude) + plt.ylabel('magnitude') + plt.subplot(414) + plt.title('Phase') + plt.plot(phase) + plt.ylabel('phase') + plt.show() + diff --git a/qcodes/instrument_drivers/AlazarTech/filter2_test_controller.py b/qcodes/instrument_drivers/AlazarTech/filter2_test_controller.py new file mode 100644 index 000000000000..7d0838f16579 --- /dev/null +++ b/qcodes/instrument_drivers/AlazarTech/filter2_test_controller.py @@ -0,0 +1,126 @@ +import numpy as np +import matplotlib.pyplot as plt +from scipy import signal + +# two channel filter controller +class Controller(): + def __init__(self, dif_freq): + self.dif_freq = dif_freq + self.sample_rate = 50000000 + self.samples_per_record = 10024 + + record_duration = self.samples_per_record / self.sample_rate + time_period_dif = 1 / self.dif_freq + cycles_measured = record_duration / time_period_dif + oversampling_rate = self.sample_rate / (2 * self.dif_freq) + print("Oscillations per record: {:.2f} (expect 100+)".format(cycles_measured)) + print("Oversampling rate: {:.2f} (expect > 2)".format(oversampling_rate)) + + def pre_start_capture(self): + self.integer_list = np.arange(self.samples_per_record) + +def filter(controller, rec, numtaps, cutoff): + sample_rate = controller.sample_rate + nyq_rate = sample_rate / 2. + fir_coef = signal.firwin(numtaps, cutoff/nyq_rate) + filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec) + return fir_coef, filtered_rec + +def filterls(controller, rec, numtaps, cutoff): + sample_rate = controller.sample_rate + nyq_rate = sample_rate / 2. + bands = [0, cutoff/nyq_rate, cutoff/nyq_rate, 1] + desired = [1, 1, 0, 0] + fir_coef = signal.firls(numtaps, bands, desired, nyq=nyq_rate) + filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec) + return fir_coef, filtered_rec + +def make_rec(controller, freq, phase_deg=0, ampdif=1, sin=False): + phase_rad = phase_deg*2*np.pi/360 + angle_list = (2 * np.pi * freq * controller.integer_list / controller.sample_rate)+phase_rad + rec = ampdif*np.cos(angle_list) + if sin: + rec = ampdif*np.sin(angle_list) + return rec + + +def main(freq1, freq2, phasedif, ampdif, numtaps, cutoff): + # make an acquisition controller (and sampling rate warnings related to + # given freq1) and integer list used for signal making + c = Controller(freq1) + c.pre_start_capture() + + # make two hardware signals with given frequencies and phase difference + # plot first 100 points of each + rec1 = make_rec(c, freq1) + rec2 = make_rec(c, freq2, phase_deg=phasedif, ampdif=ampdif) + plt.figure(1) + plt.subplot(211) + plt.plot(rec1[:100]) + plt.subplot(212) + plt.plot(rec2[:100]) + plt.show() + + # mix hardware signals and filter out frequencies above cutoff + # should leave only freq_dif component + rec12 = np.multiply(rec1, rec2) + fir_coef, filtered_rec_12 = filterls(c, rec12, numtaps, cutoff) + delay = numtaps-1 + + # plot filter + w, h = signal.freqz(fir_coef) + freq_axis = (w/np.pi)*c.sample_rate + fig = plt.figure(1) + ax1 = fig.add_subplot(111) + plt.title('Digital filter frequency response') + plt.plot(freq_axis, 20 * np.log10(abs(h)), 'b') + plt.ylabel('Amplitude [dB]', color='b') + plt.xlabel('Frequency [Hz]') + + ax2 = ax1.twinx() + angles = np.unwrap(np.angle(h)) + plt.plot(freq_axis, angles, 'g') + plt.ylabel('Angle (radians)', color='g') + plt.grid() + plt.axis('tight') + plt.show() + + + # shift first hardware signal by 90 degrees to make + # sin signal for mixing, mix and plot + rec3 = make_rec(c, freq1, sin=True) + rec23 = np.multiply(rec2, rec3) + fir_coef, filtered_rec_23 = filterls(c, rec23, numtaps, cutoff) + + # plot filtered signal and magnitude and phase results + plt.figure(1) + plt.subplot(411) + plt.title('Re part') + plt.plot(rec12, '-r') + plt.ylabel('unfiltered record', color='r') + plt.plot(filtered_rec_12, '-g') + plt.ylabel('filtered record', color='g') + plt.subplot(412) + plt.title('Im part') + plt.plot(rec23, '-r') + plt.ylabel('unfiltered record', color='r') + plt.plot(filtered_rec_23, '-g') + plt.ylabel('filtered record', color='g') + + # add to plot magnitude and phase of resulting complex number + complex_rec = filtered_rec_12+filtered_rec_23*1j + magnitude = abs(complex_rec) + phase = np.angle(complex_rec, deg=True) + plt.subplot(413) + plt.title('Magnitude') + plt.plot(magnitude) + plt.ylabel('magnitude') + plt.subplot(414) + plt.title('Phase') + plt.plot(phase) + plt.ylabel('phase') + plt.show() + + + + # import qcodes.instrument_drivers.AlazarTech.filter2_test_controller as cont diff --git a/qcodes/instrument_drivers/AlazarTech/local_test.py b/qcodes/instrument_drivers/AlazarTech/local_test.py deleted file mode 100644 index 6e85961fe531..000000000000 --- a/qcodes/instrument_drivers/AlazarTech/local_test.py +++ /dev/null @@ -1,109 +0,0 @@ -from .ATS import AcquisitionController -import math -import numpy as np -import matplotlib.pyplot as plt - - -class Controller(): - def __init__(self, dif_freq): - self.dif_freq = dif_freq - self.sample_rate = 500000000 - self.samples_per_record = 1024 - - record_duration = self.samples_per_record/self.sample_rate - dif_time_period = 1/self.dif_freq - cycles_measured = record_duration / dif_time_period - oversampling_rate = self.sample_rate/(2*self.dif_freq) - print("Measuring from "+str(cycles_measured)+" samples should be on the order of 100 at least") - print("Oversampling rate is "+str(oversampling_rate)+" should be > 2") - - def pre_start_capture(self): - self.integer_list = np.arange(self.samples_per_record) - self.angle_list = (2 * np.pi * self.dif_freq / self.sample_rate * - self.integer_list) - - self.cos_list = np.cos(self.angle_list) - self.sin_list = np.sin(self.angle_list) - - def fit(self, rec): - # Discrete Fourier Transform - RePart = np.dot(rec, self.cos_list) / self.samples_per_record - ImPart = np.dot(rec, self.sin_list) / self.samples_per_record - # factor of 2 is because amplitude is split between finite term and - # double frequency term which averages to 0 - ampl = 2 * np.sqrt(RePart ** 2 + ImPart ** 2) - phase = math.atan2(ImPart, RePart) * 180 / (2 * math.pi) - - return [ampl, phase] - - def pre_acquire(self, alazar): - # gets called after 'AlazarStartCapture' - pass - - def handle_buffer(self, alazar, data): - self.buffer += data - - def post_acquire(self, alazar): - # average over records in buffer: - # for ATS9360 samples are arranged in the buffer as follows: - # S0A, S0B, ..., S1A, S1B, ... - # with SXY the sample number X of channel Y. - records_per_acquisition = (1. * self.buffers_per_acquisition * - self.records_per_buffer) - recordA = np.zeros(self.samples_per_record) - for i in range(self.records_per_buffer): - i0 = i * self.samples_per_record * self.number_of_channels - i1 = i0 + self.samples_per_record * self.number_of_channels - recordA += self.buffer[i0:i1:self.number_of_channels] / records_per_acquisition - - recordB = np.zeros(self.samples_per_record) - for i in range(self.records_per_buffer): - i0 = (i * self.samples_per_record * self.number_of_channels) + 1 - i1 = i0 + self.samples_per_record *self.number_of_channels - recordB += self.buffer[i0:i1:self.number_of_channels] / records_per_acquisition - - resA = self.fit(recordA) - resB = self.fit(recordB) - - return resA, resB - - -def make_rec(controller, freq, phase_deg): - phase_rad = phase_deg*2*np.pi/180 - angle_list = (2 * np.pi * freq / controller.sample_rate * - controller.integer_list)+phase_rad - rec = np.cos(angle_list) - return rec - -def main(freq1, phase): - c = Controller(freq1) - c.pre_start_capture() - ran = 100 - l = [[],[]] - for i in range(ran+1): - freq = freq1-0.002*freq1*(ran/2-i) - rec = make_rec(c, freq, phase) - mag, phase = c.fit(rec) - l[0].append(mag) - l[1].append(phase) - plt.figure(1) - plt.subplot(211) - plt.plot(l[0]) - plt.subplot(212) - plt.plot(l[1]) - plt.show() - # cos_rec = np.multiply(c.cos_list, rec) - # sin_rec = np.multiply(c.sin_list, rec) - #print(c.fit(rec)) - # plt.figure(1) - # plt.subplot(511) - # plt.plot(c.cos_list) - # plt.subplot(512) - # plt.plot(c.sin_list) - # plt.subplot(513) - # plt.plot(rec) - # plt.subplot(514) - # plt.plot(cos_rec) - # plt.subplot(515) - # plt.plot(sin_rec) - # plt.show() diff --git a/qcodes/instrument_drivers/AlazarTech/local_test2.py b/qcodes/instrument_drivers/AlazarTech/local_test2.py deleted file mode 100644 index 9ce6f502e193..000000000000 --- a/qcodes/instrument_drivers/AlazarTech/local_test2.py +++ /dev/null @@ -1,93 +0,0 @@ -from .ATS import AcquisitionController -import math -import numpy as np -import matplotlib.pyplot as plt -from scipy import signal - - -class Controller(): - def __init__(self, dif_freq): - self.dif_freq = dif_freq - self.sample_rate = 5000000 - self.samples_per_record = 10024 - - record_duration = self.samples_per_record/self.sample_rate - dif_time_period = 1/self.dif_freq - cycles_measured = record_duration / dif_time_period - oversampling_rate = self.sample_rate/(2*self.dif_freq) - print("Measuring from "+str(cycles_measured)+" samples should be on the order of 100 at least") - print("Oversampling rate is "+str(oversampling_rate)+" should be > 2") - - def pre_start_capture(self): - self.integer_list = np.arange(self.samples_per_record) - self.angle_list = (2 * np.pi * self.dif_freq / self.sample_rate * - self.integer_list) - - self.cos_list = np.cos(self.angle_list) - self.sin_list = np.sin(self.angle_list) - - def pre_acquire(self, alazar): - # gets called after 'AlazarStartCapture' - pass - - def handle_buffer(self, alazar, data): - self.buffer += data - - def post_acquire(self, alazar): - # average over records in buffer: - # for ATS9360 samples are arranged in the buffer as follows: - # S0A, S0B, ..., S1A, S1B, ... - # with SXY the sample number X of channel Y. - records_per_acquisition = (1. * self.buffers_per_acquisition * - self.records_per_buffer) - recordA = np.zeros(self.samples_per_record) - for i in range(self.records_per_buffer): - i0 = i * self.samples_per_record * self.number_of_channels - i1 = i0 + self.samples_per_record * self.number_of_channels - recordA += self.buffer[i0:i1:self.number_of_channels] / records_per_acquisition - - recordB = np.zeros(self.samples_per_record) - for i in range(self.records_per_buffer): - i0 = (i * self.samples_per_record * self.number_of_channels) + 1 - i1 = i0 + self.samples_per_record *self.number_of_channels - recordB += self.buffer[i0:i1:self.number_of_channels] / records_per_acquisition - - resA = self.fit(recordA) - resB = self.fit(recordB) - - return resA, resB - -def make_rec(controller, freq, phase_deg): - phase_rad = phase_deg*2*np.pi/180 - angle_list = (2 * np.pi * freq / controller.sample_rate * - controller.integer_list)+phase_rad - rec = np.cos(angle_list) - return rec - -def main(freq1, freq2): - c = Controller(freq1) - c.pre_start_capture() - rec1 = make_rec(c, freq2, 0) - rec2 = c.cos_list - plt.figure(1) - plt.subplot(211) - plt.plot(rec1) - plt.subplot(212) - plt.plot(rec1) - plt.show() - s = np.multiply(rec1, rec2) - plt.plot(s) - plt.show() - - -n = 61 -a = signal.firwin(n, cutoff = 0.3, window = "hamming") -#Frequency and phase response -mfreqz(a) -show() -#Impulse and step response -figure(2) -impz(a) -show() - - # import qcodes.instrument_drivers.AlazarTech.local_test2 as cont From 654984a65f195ef368112868bcfd127a6e4e4130 Mon Sep 17 00:00:00 2001 From: Natalie Pearson Date: Wed, 26 Oct 2016 13:55:19 +0200 Subject: [PATCH 008/180] fix: tweak ATS9360.py to work with damaz updates --- .../instrument_drivers/AlazarTech/ATS9360.py | 39 ++++--------------- 1 file changed, 8 insertions(+), 31 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/ATS9360.py b/qcodes/instrument_drivers/AlazarTech/ATS9360.py index a564c01a9fbb..c86abd2457e9 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS9360.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS9360.py @@ -3,9 +3,9 @@ class AlazarTech_ATS9360(AlazarTech_ATS): - def __init__(self, name, server_name=None): + def __init__(self, name, **kwargs): dll_path = 'C:\\WINDOWS\\System32\\ATSApi.dll' - super().__init__(name, dll_path=dll_path) + super().__init__(name, dll_path=dll_path, **kwargs) # add parameters @@ -88,7 +88,7 @@ def __init__(self, name, server_name=None): parameter_class=AlazarParameter, label='Trigger Engine ' + i, unit=None, - value='TRIG_ENGINE_J', + value='TRIG_ENGINE_' + ('J' if i == 0 else 'K'), byte_to_value_dict={0: 'TRIG_ENGINE_J', 1: 'TRIG_ENGINE_K'}) self.add_parameter(name='trigger_source' + i, @@ -163,7 +163,7 @@ def __init__(self, name, server_name=None): label='Samples per Record', unit=None, value=1024, - vals=Multiples(divisor=16, min_value=0)) + vals=Multiples(divisor=64, min_value=256)) # TODO (M) figure out if this also has to be a multiple of something, # I could not find this in the documentation but somehow I have the # feeling it still should be a multiple of something @@ -254,30 +254,7 @@ def __init__(self, name, server_name=None): value=1000, vals=validators.Ints(min_value=0)) - # TODO (M) make parameter for board type - - # TODO (M) check board kind - - -class Multiples(validators.Ints): - ''' - requires an integer - optional parameters min_value and max_value enforce - min_value <= value <= max_value - divisor enforces that value % divisor == 0 - ''' - - def __init__(self, divisor=1, **kwargs): - super().__init__(**kwargs) - if not isinstance(divisor, int): - raise TypeError('divisor must be an integer') - self._divisor = divisor - - def validate(self, value, context=''): - super().validate(value=value, context=context) - if not value % self._divisor == 0: - raise TypeError('{} is not a multiple of {}; {}'.format( - repr(value), repr(self._divisor), context)) - - def __repr__(self): - return super().__repr__()[:-1] + ', Multiples of {}>'.format(self._divisor) + model = self.get_idn()['model'] + if model != 'ATS9360': + raise Exception("The Alazar board kind is not 'ATS9360'," + " found '" + str(model) + "' instead.") From 2d2b82bc57287594c2ee0f8ffc2d58bc5db9e4af Mon Sep 17 00:00:00 2001 From: Natalie Pearson Date: Wed, 26 Oct 2016 14:41:26 +0200 Subject: [PATCH 009/180] fix: tweak ATS.py to hopefully match damaz updates --- qcodes/instrument_drivers/AlazarTech/ATS.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/ATS.py b/qcodes/instrument_drivers/AlazarTech/ATS.py index a933c18a4e8d..d583275aec99 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS.py @@ -467,7 +467,7 @@ def acquire(self, mode=None, samples_per_record=None, self._set_if_present('samples_per_record', samples_per_record) self._set_if_present('records_per_buffer', records_per_buffer) self._set_if_present('buffers_per_acquisition', - buffers_per_acquisition), + buffers_per_acquisition) self._set_if_present('channel_selection', channel_selection) self._set_if_present('transfer_offset', transfer_offset) self._set_if_present('external_startcapture', external_startcapture) @@ -500,6 +500,10 @@ def acquire(self, mode=None, samples_per_record=None, post_trigger_size) # set acquisition parameters here for NPT, TS mode + if self.channel_selection._get_byte() == 3: + number_of_channels = 2 + else: + number_of_channels = 1 samples_per_buffer = 0 buffers_per_acquisition = self.buffers_per_acquisition._get_byte() samples_per_record = self.samples_per_record._get_byte() @@ -513,7 +517,8 @@ def acquire(self, mode=None, samples_per_record=None, if mode == 'NPT': records_per_buffer = self.records_per_buffer._get_byte() - records_per_acquisition = records_per_buffer * buffers_per_acquisition + records_per_acquisition = ( + records_per_buffer * buffers_per_acquisition) samples_per_buffer = samples_per_record * records_per_buffer self._call_dll('AlazarBeforeAsyncRead', @@ -555,8 +560,7 @@ def acquire(self, mode=None, samples_per_record=None, self.get_processed_data._set_updated() # bytes per sample - handle = self._handle - max_s, bps = self._get_channel_info(handle) + max_s, bps = self._get_channel_info(self._handle) bytes_per_sample = (bps + 7) // 8 print("bytes per sample "+str(bytes_per_sample)) @@ -614,13 +618,13 @@ def acquire(self, mode=None, samples_per_record=None, print("completed AlazarPostAsyncBuffer") # -----start capture here----- - acquisition_controller.pre_start_capture(self) + acquisition_controller.pre_start_capture() start = time.clock() # Keep track of when acquisition started # call the startcapture method self._call_dll('AlazarStartCapture', self._handle) print("Capturing %d buffers." % buffers_per_acquisition) - acquisition_controller.pre_acquire(self) + acquisition_controller.pre_acquire() # buffer handling from acquisition buffers_completed = 0 From 2356bd21d8e884a759c2262c33e5773405a51e4d Mon Sep 17 00:00:00 2001 From: Natalie Pearson Date: Wed, 26 Oct 2016 14:45:38 +0200 Subject: [PATCH 010/180] fix: Add mistakenly deleted ATS example notebook back --- docs/examples/Qcodes example ATS_ONWORK.ipynb | 1658 +++++++++++++++++ 1 file changed, 1658 insertions(+) create mode 100644 docs/examples/Qcodes example ATS_ONWORK.ipynb diff --git a/docs/examples/Qcodes example ATS_ONWORK.ipynb b/docs/examples/Qcodes example ATS_ONWORK.ipynb new file mode 100644 index 000000000000..eac33345b0ae --- /dev/null +++ b/docs/examples/Qcodes example ATS_ONWORK.ipynb @@ -0,0 +1,1658 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "application/javascript": [ + "/*\r\n", + " * Qcodes Jupyter/IPython widgets\r\n", + " */\r\n", + "require([\r\n", + " 'nbextensions/widgets/widgets/js/widget',\r\n", + " 'nbextensions/widgets/widgets/js/manager'\r\n", + "], function (widget, manager) {\r\n", + "\r\n", + " var UpdateView = widget.DOMWidgetView.extend({\r\n", + " render: function() {\r\n", + " window.MYWIDGET = this;\r\n", + " this._interval = 0;\r\n", + " this.update();\r\n", + " },\r\n", + " update: function() {\r\n", + " this.display(this.model.get('_message'));\r\n", + " this.setInterval();\r\n", + " },\r\n", + " display: function(message) {\r\n", + " /*\r\n", + " * display method: override this for custom display logic\r\n", + " */\r\n", + " this.el.innerHTML = message;\r\n", + " },\r\n", + " remove: function() {\r\n", + " clearInterval(this._updater);\r\n", + " },\r\n", + " setInterval: function(newInterval) {\r\n", + " var me = this;\r\n", + " if(newInterval===undefined) newInterval = me.model.get('interval');\r\n", + " if(newInterval===me._interval) return;\r\n", + "\r\n", + " me._interval = newInterval;\r\n", + "\r\n", + " if(me._updater) clearInterval(me._updater);\r\n", + "\r\n", + " if(me._interval) {\r\n", + " me._updater = setInterval(function() {\r\n", + " me.send({myupdate: true});\r\n", + " if(!me.model.comm_live) {\r\n", + " console.log('missing comm, canceling widget updates', me);\r\n", + " clearInterval(me._updater);\r\n", + " }\r\n", + " }, me._interval * 1000);\r\n", + " }\r\n", + " }\r\n", + " });\r\n", + " manager.WidgetManager.register_widget_view('UpdateView', UpdateView);\r\n", + "\r\n", + " var HiddenUpdateView = UpdateView.extend({\r\n", + " display: function(message) {\r\n", + " this.$el.hide();\r\n", + " }\r\n", + " });\r\n", + " manager.WidgetManager.register_widget_view('HiddenUpdateView', HiddenUpdateView);\r\n", + "\r\n", + " var SubprocessView = UpdateView.extend({\r\n", + " render: function() {\r\n", + " var me = this;\r\n", + " me._interval = 0;\r\n", + " me._minimize = '';\r\n", + " me._restore = '';\r\n", + "\r\n", + " // max lines of output to show\r\n", + " me.maxOutputLength = 500;\r\n", + "\r\n", + " // in case there is already an outputView present,\r\n", + " // like from before restarting the kernel\r\n", + " $('.qcodes-output-view').not(me.$el).remove();\r\n", + "\r\n", + " me.$el\r\n", + " .addClass('qcodes-output-view')\r\n", + " .attr('qcodes-state', 'docked')\r\n", + " .html(\r\n", + " '
' +\r\n", + " '
' +\r\n", + " '' +\r\n", + " '' +\r\n", + " '' +\r\n", + " '' +\r\n", + " '' +\r\n", + " '' +\r\n", + " '
' +\r\n", + " '
'\r\n",
+       "                );\r\n",
+       "\r\n",
+       "            me.clearButton = me.$el.find('.qcodes-clear-output');\r\n",
+       "            me.minButton = me.$el.find('.qcodes-minimize');\r\n",
+       "            me.outputArea = me.$el.find('pre');\r\n",
+       "            me.subprocessList = me.$el.find('.qcodes-process-list');\r\n",
+       "            me.abortButton = me.$el.find('.qcodes-abort-loop');\r\n",
+       "            me.processLinesButton = me.$el.find('.qcodes-processlines')\r\n",
+       "\r\n",
+       "            me.outputLines = [];\r\n",
+       "\r\n",
+       "            me.clearButton.click(function() {\r\n",
+       "                me.outputArea.html('');\r\n",
+       "                me.clearButton.addClass('disabled');\r\n",
+       "            });\r\n",
+       "\r\n",
+       "            me.abortButton.click(function() {\r\n",
+       "                me.send({abort: true});\r\n",
+       "            });\r\n",
+       "\r\n",
+       "            me.processLinesButton.click(function() {\r\n",
+       "                // toggle multiline process list display\r\n",
+       "                me.subprocessesMultiline = !me.subprocessesMultiline;\r\n",
+       "                me.showSubprocesses();\r\n",
+       "            });\r\n",
+       "\r\n",
+       "            me.$el.find('.js-state').click(function() {\r\n",
+       "                var state = this.className.substr(this.className.indexOf('qcodes'))\r\n",
+       "                        .split('-')[1].split(' ')[0];\r\n",
+       "                me.model.set('_state', state);\r\n",
+       "            });\r\n",
+       "\r\n",
+       "            $(window)\r\n",
+       "                .off('resize.qcodes')\r\n",
+       "                .on('resize.qcodes', function() {me.clipBounds();});\r\n",
+       "\r\n",
+       "            me.update();\r\n",
+       "        },\r\n",
+       "\r\n",
+       "        updateState: function() {\r\n",
+       "            var me = this,\r\n",
+       "                oldState = me.$el.attr('qcodes-state'),\r\n",
+       "                state = me.model.get('_state');\r\n",
+       "\r\n",
+       "            if(state === oldState) return;\r\n",
+       "\r\n",
+       "            setTimeout(function() {\r\n",
+       "                // not sure why I can't pop it out of the widgetarea in render, but it seems that\r\n",
+       "                // some other bit of code resets the parent after render if I do it there.\r\n",
+       "                // To be safe, just do it on every state click.\r\n",
+       "                me.$el.appendTo('body');\r\n",
+       "\r\n",
+       "                if(oldState === 'floated') {\r\n",
+       "                    console.log('here');\r\n",
+       "                    me.$el.draggable('destroy').css({left:'', top: ''});\r\n",
+       "                }\r\n",
+       "\r\n",
+       "                me.$el.attr('qcodes-state', state);\r\n",
+       "\r\n",
+       "                if(state === 'floated') {\r\n",
+       "                    me.$el\r\n",
+       "                        .draggable({stop: function() { me.clipBounds(); }})\r\n",
+       "                        .css({\r\n",
+       "                            left: window.innerWidth - me.$el.width() - 15,\r\n",
+       "                            top: window.innerHeight - me.$el.height() - 10\r\n",
+       "                        });\r\n",
+       "                }\r\n",
+       "\r\n",
+       "                // any previous highlighting is now moot\r\n",
+       "                me.$el.removeClass('qcodes-highlight');\r\n",
+       "            }, 0);\r\n",
+       "\r\n",
+       "        },\r\n",
+       "\r\n",
+       "        clipBounds: function() {\r\n",
+       "            var me = this;\r\n",
+       "            if(me.$el.attr('qcodes-state') === 'floated') {\r\n",
+       "                var bounds = me.$el[0].getBoundingClientRect(),\r\n",
+       "                    minVis = 40,\r\n",
+       "                    maxLeft = window.innerWidth - minVis,\r\n",
+       "                    minLeft = minVis - bounds.width,\r\n",
+       "                    maxTop = window.innerHeight - minVis;\r\n",
+       "\r\n",
+       "                if(bounds.left > maxLeft) me.$el.css('left', maxLeft);\r\n",
+       "                else if(bounds.left < minLeft) me.$el.css('left', minLeft);\r\n",
+       "\r\n",
+       "                if(bounds.top > maxTop) me.$el.css('top', maxTop);\r\n",
+       "                else if(bounds.top < 0) me.$el.css('top', 0);\r\n",
+       "            }\r\n",
+       "        },\r\n",
+       "\r\n",
+       "        display: function(message) {\r\n",
+       "            var me = this;\r\n",
+       "            if(message) {\r\n",
+       "                var initialScroll = me.outputArea.scrollTop();\r\n",
+       "                me.outputArea.scrollTop(me.outputArea.prop('scrollHeight'));\r\n",
+       "                var scrollBottom = me.outputArea.scrollTop();\r\n",
+       "\r\n",
+       "                if(me.$el.attr('qcodes-state') === 'minimized') {\r\n",
+       "                    // if we add text and the box is minimized, highlight the\r\n",
+       "                    // title bar to alert the user that there are new messages.\r\n",
+       "                    // remove then add the class, so we get the animation again\r\n",
+       "                    // if it's already highlighted\r\n",
+       "                    me.$el.removeClass('qcodes-highlight');\r\n",
+       "                    setTimeout(function(){\r\n",
+       "                        me.$el.addClass('qcodes-highlight');\r\n",
+       "                    }, 0);\r\n",
+       "                }\r\n",
+       "\r\n",
+       "                var newLines = message.split('\\n'),\r\n",
+       "                    out = me.outputLines,\r\n",
+       "                    outLen = out.length;\r\n",
+       "                if(outLen) out[outLen - 1] += newLines[0];\r\n",
+       "                else out.push(newLines[0]);\r\n",
+       "\r\n",
+       "                for(var i = 1; i < newLines.length; i++) {\r\n",
+       "                    out.push(newLines[i]);\r\n",
+       "                }\r\n",
+       "\r\n",
+       "                if(out.length > me.maxOutputLength) {\r\n",
+       "                    out.splice(0, out.length - me.maxOutputLength + 1,\r\n",
+       "                        '<<< Output clipped >>>');\r\n",
+       "                }\r\n",
+       "\r\n",
+       "                me.outputArea.text(out.join('\\n'));\r\n",
+       "                me.clearButton.removeClass('disabled');\r\n",
+       "\r\n",
+       "                // if we were scrolled to the bottom initially, make sure\r\n",
+       "                // we stay that way.\r\n",
+       "                me.outputArea.scrollTop(initialScroll === scrollBottom ?\r\n",
+       "                    me.outputArea.prop('scrollHeight') : initialScroll);\r\n",
+       "            }\r\n",
+       "\r\n",
+       "            me.showSubprocesses();\r\n",
+       "            me.updateState();\r\n",
+       "        },\r\n",
+       "\r\n",
+       "        showSubprocesses: function() {\r\n",
+       "            var me = this,\r\n",
+       "                replacer = me.subprocessesMultiline ? '
' : ', ',\r\n", + " processes = (me.model.get('_processes') || '')\r\n", + " .replace(/\\n/g, '>' + replacer + '<');\r\n", + "\r\n", + " if(processes) processes = '<' + processes + '>';\r\n", + " else processes = 'No subprocesses';\r\n", + "\r\n", + " me.abortButton.toggleClass('disabled', processes.indexOf('Measurement')===-1);\r\n", + "\r\n", + " me.subprocessList.html(processes);\r\n", + " }\r\n", + " });\r\n", + " manager.WidgetManager.register_widget_view('SubprocessView', SubprocessView);\r\n", + "});\r\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "No loop running\n" + ] + } + ], + "source": [ + "# import all necessary things\n", + "%matplotlib nbagg\n", + "\n", + "import qcodes as qc\n", + "import qcodes.instrument.parameter as parameter\n", + "import qcodes.instrument_drivers.AlazarTech.ATS9870 as ATSdriver\n", + "import qcodes.instrument_drivers.AlazarTech.ATS_acquisition_controllers as ats_contr\n", + "\n", + "qc.halt_bg()\n", + "qc.set_mp_method('spawn') # force Windows behavior on mac\n", + "\n", + "# this makes a widget in the corner of the window to show and control\n", + "# subprocesses and any output they would print to the terminal\n", + "qc.show_subprocess_widget()" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[{'bits_per_sample': 8,\n", + " 'board_id': 1,\n", + " 'board_kind': 'ATS9870',\n", + " 'max_samples': 4294966272,\n", + " 'system_id': 1}]" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Command to list all alazar boards connected to the system\n", + "ATSdriver.AlazarTech_ATS.find_boards()" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'CPLD_version': '13.8',\n", + " 'SDK_version': '5.10.15',\n", + " 'asopc_type': '2435577968',\n", + " 'driver_version': '5.10.15',\n", + " 'firmware': None,\n", + " 'latest_cal_date': '30-01-13',\n", + " 'memory_size': '4294966272',\n", + " 'model': 'ATS9870',\n", + " 'pcie_link_speed': '0.25GB/s',\n", + " 'pcie_link_width': '8',\n", + " 'serial': '910266',\n", + " 'vendor': 'AlazarTech'}" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Create the ATS9870 instrument on the new server \"alazar_server\"\n", + "ats_inst = ATSdriver.AlazarTech_ATS9870(name='Alazar1', server_name=\"alazar_server\")\n", + "# Print all information about this Alazar card\n", + "ats_inst.get_idn()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Instantiate an acquisition controller (In this case we are doing a simple DFT) on the same server (\"alazar_server\") and \n", + "# provide the name of the name of the alazar card that this controller should control\n", + "acquisition_controller = ats_contr.Demodulation_AcquisitionController(name='acquisition_controller', \n", + " demodulation_frequency=10e6, \n", + " alazar_name='Alazar1', \n", + " server_name=\"alazar_server\")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Configure all settings in the Alazar card\n", + "ats_inst.config(#clock_source='INTERNAL_CLOCK',\n", + " sample_rate=100000000,\n", + " #clock_edge='CLOCK_EDGE_RISING',\n", + " #decimation=0,\n", + " #coupling=['AC','AC'],\n", + " channel_range=[2.,2.],\n", + " #impedance=[50,50],\n", + " #bwlimit=['DISABLED','DISABLED'],\n", + " #trigger_operation='TRIG_ENGINE_OP_J',\n", + " #trigger_engine1='TRIG_ENGINE_J',\n", + " trigger_source1='EXTERNAL',\n", + " #trigger_slope1='TRIG_SLOPE_POSITIVE',\n", + " #trigger_level1=128,\n", + " #trigger_engine2='TRIG_ENGINE_K',\n", + " #trigger_source2='DISABLE',\n", + " #trigger_slope2='TRIG_SLOPE_POSITIVE',\n", + " #trigger_level2=128,\n", + " #external_trigger_coupling='AC',\n", + " #external_trigger_range='ETR_5V',\n", + " #trigger_delay=0,\n", + " #timeout_ticks=0\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# This command is specific to this acquisition controller. The kwargs provided here are being forwarded to ats_inst.acquire\n", + "# This way, it becomes easy to change acquisition specific settings from the ipython notebook\n", + "acquisition_controller.update_acquisitionkwargs(#mode='NPT',\n", + " samples_per_record=1024,\n", + " records_per_buffer=70,\n", + " buffers_per_acquisition=1,\n", + " #channel_selection='AB',\n", + " #transfer_offset=0,\n", + " #external_startcapture='ENABLED',\n", + " #enable_record_headers='DISABLED',\n", + " #alloc_buffers='DISABLED',\n", + " #fifo_only_streaming='DISABLED',\n", + " #interleave_samples='DISABLED',\n", + " #get_processed_data='DISABLED',\n", + " allocated_buffers=1,\n", + " #buffer_timeout=1000\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "0.1205605630942215" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Getting the value of the parameter 'acquisition' of the instrument 'acquisition_controller' performes the entire acquisition \n", + "# protocol. This again depends on the specific implementation of the acquisition controller\n", + "acquisition_controller.acquisition()" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS9870.AlazarTech_ATS9870',\n", + " 'functions': {},\n", + " 'name': 'Alazar1',\n", + " 'parameters': {'IDN': {'__class__': 'qcodes.instrument.parameter.StandardParameter',\n", + " 'instrument': 'qcodes.instrument_drivers.AlazarTech.ATS9870.AlazarTech_ATS9870',\n", + " 'instrument_name': 'Alazar1',\n", + " 'label': 'IDN',\n", + " 'name': 'IDN',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': '',\n", + " 'value': {'CPLD_version': '13.8',\n", + " 'SDK_version': '5.10.15',\n", + " 'asopc_type': '2435577968',\n", + " 'driver_version': '5.10.15',\n", + " 'firmware': None,\n", + " 'latest_cal_date': '30-01-13',\n", + " 'memory_size': '4294966272',\n", + " 'model': 'ATS9870',\n", + " 'pcie_link_speed': '0.25GB/s',\n", + " 'pcie_link_width': '8',\n", + " 'serial': '910266',\n", + " 'vendor': 'AlazarTech'}},\n", + " 'alloc_buffers': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Alloc Buffers',\n", + " 'name': 'alloc_buffers',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': '',\n", + " 'value': 'DISABLED'},\n", + " 'allocated_buffers': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Allocated Buffers',\n", + " 'name': 'allocated_buffers',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': '',\n", + " 'value': 1},\n", + " 'buffer_timeout': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Buffer Timeout',\n", + " 'name': 'buffer_timeout',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': 'ms',\n", + " 'value': 1000},\n", + " 'buffers_per_acquisition': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Buffers per Acquisition',\n", + " 'name': 'buffers_per_acquisition',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': '',\n", + " 'value': 1},\n", + " 'bwlimit1': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Bandwidth limit channel 1',\n", + " 'name': 'bwlimit1',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': '',\n", + " 'value': 'DISABLED'},\n", + " 'bwlimit2': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Bandwidth limit channel 2',\n", + " 'name': 'bwlimit2',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': '',\n", + " 'value': 'DISABLED'},\n", + " 'channel_range1': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Range channel 1',\n", + " 'name': 'channel_range1',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': 'V',\n", + " 'value': 2.0},\n", + " 'channel_range2': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Range channel 2',\n", + " 'name': 'channel_range2',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': 'V',\n", + " 'value': 2.0},\n", + " 'channel_selection': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Channel Selection',\n", + " 'name': 'channel_selection',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': '',\n", + " 'value': 'AB'},\n", + " 'clock_edge': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Clock Edge',\n", + " 'name': 'clock_edge',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': '',\n", + " 'value': 'CLOCK_EDGE_RISING'},\n", + " 'clock_source': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Clock Source',\n", + " 'name': 'clock_source',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': '',\n", + " 'value': 'INTERNAL_CLOCK'},\n", + " 'coupling1': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Coupling channel 1',\n", + " 'name': 'coupling1',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': '',\n", + " 'value': 'AC'},\n", + " 'coupling2': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Coupling channel 2',\n", + " 'name': 'coupling2',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': '',\n", + " 'value': 'AC'},\n", + " 'decimation': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Decimation',\n", + " 'name': 'decimation',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': '',\n", + " 'value': 0},\n", + " 'enable_record_headers': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Enable Record Headers',\n", + " 'name': 'enable_record_headers',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': '',\n", + " 'value': 'DISABLED'},\n", + " 'external_startcapture': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'External Startcapture',\n", + " 'name': 'external_startcapture',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': '',\n", + " 'value': 'ENABLED'},\n", + " 'external_trigger_coupling': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'External Trigger Coupling',\n", + " 'name': 'external_trigger_coupling',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': '',\n", + " 'value': 'AC'},\n", + " 'external_trigger_range': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'External Trigger Range',\n", + " 'name': 'external_trigger_range',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': '',\n", + " 'value': 'ETR_5V'},\n", + " 'fifo_only_streaming': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Fifo Only Streaming',\n", + " 'name': 'fifo_only_streaming',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': '',\n", + " 'value': 'DISABLED'},\n", + " 'get_processed_data': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Get Processed Data',\n", + " 'name': 'get_processed_data',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': '',\n", + " 'value': 'DISABLED'},\n", + " 'impedance1': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Impedance channel 1',\n", + " 'name': 'impedance1',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': 'Ohm',\n", + " 'value': 50},\n", + " 'impedance2': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Impedance channel 2',\n", + " 'name': 'impedance2',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': 'Ohm',\n", + " 'value': 50},\n", + " 'interleave_samples': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Interleave Samples',\n", + " 'name': 'interleave_samples',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': '',\n", + " 'value': 'DISABLED'},\n", + " 'mode': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Acquisiton mode',\n", + " 'name': 'mode',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': '',\n", + " 'value': 'NPT'},\n", + " 'records_per_buffer': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Records per Buffer',\n", + " 'name': 'records_per_buffer',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': '',\n", + " 'value': 70},\n", + " 'sample_rate': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Sample Rate',\n", + " 'name': 'sample_rate',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': 'S/s',\n", + " 'value': 100000000},\n", + " 'samples_per_record': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Samples per Record',\n", + " 'name': 'samples_per_record',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': '',\n", + " 'value': 1024},\n", + " 'timeout_ticks': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Timeout Ticks',\n", + " 'name': 'timeout_ticks',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': '10 us',\n", + " 'value': 0},\n", + " 'transfer_offset': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Transer Offset',\n", + " 'name': 'transfer_offset',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': 'Samples',\n", + " 'value': 0},\n", + " 'trigger_delay': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Trigger Delay',\n", + " 'name': 'trigger_delay',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': 'Sample clock cycles',\n", + " 'value': 0},\n", + " 'trigger_engine1': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Trigger Engine 1',\n", + " 'name': 'trigger_engine1',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': '',\n", + " 'value': 'TRIG_ENGINE_K'},\n", + " 'trigger_engine2': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Trigger Engine 2',\n", + " 'name': 'trigger_engine2',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': '',\n", + " 'value': 'TRIG_ENGINE_K'},\n", + " 'trigger_level1': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Trigger Level 1',\n", + " 'name': 'trigger_level1',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': '',\n", + " 'value': 128},\n", + " 'trigger_level2': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Trigger Level 2',\n", + " 'name': 'trigger_level2',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': '',\n", + " 'value': 128},\n", + " 'trigger_operation': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Trigger Operation',\n", + " 'name': 'trigger_operation',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': '',\n", + " 'value': 'TRIG_ENGINE_OP_J'},\n", + " 'trigger_slope1': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Trigger Slope 1',\n", + " 'name': 'trigger_slope1',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': '',\n", + " 'value': 'TRIG_SLOPE_POSITIVE'},\n", + " 'trigger_slope2': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Trigger Slope 2',\n", + " 'name': 'trigger_slope2',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': '',\n", + " 'value': 'TRIG_SLOPE_POSITIVE'},\n", + " 'trigger_source1': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Trigger Source 1',\n", + " 'name': 'trigger_source1',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': '',\n", + " 'value': 'EXTERNAL'},\n", + " 'trigger_source2': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Trigger Source 2',\n", + " 'name': 'trigger_source2',\n", + " 'ts': '2016-09-21 18:04:30',\n", + " 'units': '',\n", + " 'value': 'DISABLE'}}}" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# make a snapshot of the 'ats_inst' instrument\n", + "ats_inst.snapshot()" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DataSet:\n", + " mode = DataMode.PULL_FROM_SERVER\n", + " location = '2016-09-21/18-04-30_AlazarTest'\n", + " | | | \n", + " Setpoint | dummy_set | dummy | (50,)\n", + " Measured | acquisition_controller_acquisition | acquisition | (50,)\n", + "started at 2016-09-21 18:04:31\n" + ] + }, + { + "data": { + "application/javascript": [ + "/* Put everything inside the global mpl namespace */\n", + "window.mpl = {};\n", + "\n", + "mpl.get_websocket_type = function() {\n", + " if (typeof(WebSocket) !== 'undefined') {\n", + " return WebSocket;\n", + " } else if (typeof(MozWebSocket) !== 'undefined') {\n", + " return MozWebSocket;\n", + " } else {\n", + " alert('Your browser does not have WebSocket support.' +\n", + " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", + " 'Firefox 4 and 5 are also supported but you ' +\n", + " 'have to enable WebSockets in about:config.');\n", + " };\n", + "}\n", + "\n", + "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", + " this.id = figure_id;\n", + "\n", + " this.ws = websocket;\n", + "\n", + " this.supports_binary = (this.ws.binaryType != undefined);\n", + "\n", + " if (!this.supports_binary) {\n", + " var warnings = document.getElementById(\"mpl-warnings\");\n", + " if (warnings) {\n", + " warnings.style.display = 'block';\n", + " warnings.textContent = (\n", + " \"This browser does not support binary websocket messages. \" +\n", + " \"Performance may be slow.\");\n", + " }\n", + " }\n", + "\n", + " this.imageObj = new Image();\n", + "\n", + " this.context = undefined;\n", + " this.message = undefined;\n", + " this.canvas = undefined;\n", + " this.rubberband_canvas = undefined;\n", + " this.rubberband_context = undefined;\n", + " this.format_dropdown = undefined;\n", + "\n", + " this.image_mode = 'full';\n", + "\n", + " this.root = $('
');\n", + " this._root_extra_style(this.root)\n", + " this.root.attr('style', 'display: inline-block');\n", + "\n", + " $(parent_element).append(this.root);\n", + "\n", + " this._init_header(this);\n", + " this._init_canvas(this);\n", + " this._init_toolbar(this);\n", + "\n", + " var fig = this;\n", + "\n", + " this.waiting = false;\n", + "\n", + " this.ws.onopen = function () {\n", + " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", + " fig.send_message(\"send_image_mode\", {});\n", + " fig.send_message(\"refresh\", {});\n", + " }\n", + "\n", + " this.imageObj.onload = function() {\n", + " if (fig.image_mode == 'full') {\n", + " // Full images could contain transparency (where diff images\n", + " // almost always do), so we need to clear the canvas so that\n", + " // there is no ghosting.\n", + " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", + " }\n", + " fig.context.drawImage(fig.imageObj, 0, 0);\n", + " };\n", + "\n", + " this.imageObj.onunload = function() {\n", + " this.ws.close();\n", + " }\n", + "\n", + " this.ws.onmessage = this._make_on_message_function(this);\n", + "\n", + " this.ondownload = ondownload;\n", + "}\n", + "\n", + "mpl.figure.prototype._init_header = function() {\n", + " var titlebar = $(\n", + " '
');\n", + " var titletext = $(\n", + " '
');\n", + " titlebar.append(titletext)\n", + " this.root.append(titlebar);\n", + " this.header = titletext[0];\n", + "}\n", + "\n", + "\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._init_canvas = function() {\n", + " var fig = this;\n", + "\n", + " var canvas_div = $('
');\n", + "\n", + " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", + "\n", + " function canvas_keyboard_event(event) {\n", + " return fig.key_event(event, event['data']);\n", + " }\n", + "\n", + " canvas_div.keydown('key_press', canvas_keyboard_event);\n", + " canvas_div.keyup('key_release', canvas_keyboard_event);\n", + " this.canvas_div = canvas_div\n", + " this._canvas_extra_style(canvas_div)\n", + " this.root.append(canvas_div);\n", + "\n", + " var canvas = $('');\n", + " canvas.addClass('mpl-canvas');\n", + " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", + "\n", + " this.canvas = canvas[0];\n", + " this.context = canvas[0].getContext(\"2d\");\n", + "\n", + " var rubberband = $('');\n", + " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", + "\n", + " var pass_mouse_events = true;\n", + "\n", + " canvas_div.resizable({\n", + " start: function(event, ui) {\n", + " pass_mouse_events = false;\n", + " },\n", + " resize: function(event, ui) {\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " stop: function(event, ui) {\n", + " pass_mouse_events = true;\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " });\n", + "\n", + " function mouse_event_fn(event) {\n", + " if (pass_mouse_events)\n", + " return fig.mouse_event(event, event['data']);\n", + " }\n", + "\n", + " rubberband.mousedown('button_press', mouse_event_fn);\n", + " rubberband.mouseup('button_release', mouse_event_fn);\n", + " // Throttle sequential mouse events to 1 every 20ms.\n", + " rubberband.mousemove('motion_notify', mouse_event_fn);\n", + "\n", + " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", + " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", + "\n", + " canvas_div.on(\"wheel\", function (event) {\n", + " event = event.originalEvent;\n", + " event['data'] = 'scroll'\n", + " if (event.deltaY < 0) {\n", + " event.step = 1;\n", + " } else {\n", + " event.step = -1;\n", + " }\n", + " mouse_event_fn(event);\n", + " });\n", + "\n", + " canvas_div.append(canvas);\n", + " canvas_div.append(rubberband);\n", + "\n", + " this.rubberband = rubberband;\n", + " this.rubberband_canvas = rubberband[0];\n", + " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", + " this.rubberband_context.strokeStyle = \"#000000\";\n", + "\n", + " this._resize_canvas = function(width, height) {\n", + " // Keep the size of the canvas, canvas container, and rubber band\n", + " // canvas in synch.\n", + " canvas_div.css('width', width)\n", + " canvas_div.css('height', height)\n", + "\n", + " canvas.attr('width', width);\n", + " canvas.attr('height', height);\n", + "\n", + " rubberband.attr('width', width);\n", + " rubberband.attr('height', height);\n", + " }\n", + "\n", + " // Set the figure to an initial 600x600px, this will subsequently be updated\n", + " // upon first draw.\n", + " this._resize_canvas(600, 600);\n", + "\n", + " // Disable right mouse context menu.\n", + " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", + " return false;\n", + " });\n", + "\n", + " function set_focus () {\n", + " canvas.focus();\n", + " canvas_div.focus();\n", + " }\n", + "\n", + " window.setTimeout(set_focus, 100);\n", + "}\n", + "\n", + "mpl.figure.prototype._init_toolbar = function() {\n", + " var fig = this;\n", + "\n", + " var nav_element = $('
')\n", + " nav_element.attr('style', 'width: 100%');\n", + " this.root.append(nav_element);\n", + "\n", + " // Define a callback function for later on.\n", + " function toolbar_event(event) {\n", + " return fig.toolbar_button_onclick(event['data']);\n", + " }\n", + " function toolbar_mouse_event(event) {\n", + " return fig.toolbar_button_onmouseover(event['data']);\n", + " }\n", + "\n", + " for(var toolbar_ind in mpl.toolbar_items) {\n", + " var name = mpl.toolbar_items[toolbar_ind][0];\n", + " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", + " var image = mpl.toolbar_items[toolbar_ind][2];\n", + " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", + "\n", + " if (!name) {\n", + " // put a spacer in here.\n", + " continue;\n", + " }\n", + " var button = $('');\n", + " button.click(method_name, toolbar_event);\n", + " button.mouseover(tooltip, toolbar_mouse_event);\n", + " nav_element.append(button);\n", + " }\n", + "\n", + " // Add the status bar.\n", + " var status_bar = $('');\n", + " nav_element.append(status_bar);\n", + " this.message = status_bar[0];\n", + "\n", + " // Add the close button to the window.\n", + " var buttongrp = $('
');\n", + " var button = $('');\n", + " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", + " button.mouseover('Close figure', toolbar_mouse_event);\n", + " buttongrp.append(button);\n", + " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", + " titlebar.prepend(buttongrp);\n", + "}\n", + "\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(el){\n", + " // this is important to make the div 'focusable\n", + " el.attr('tabindex', 0)\n", + " // reach out to IPython and tell the keyboard manager to turn it's self\n", + " // off when our div gets focus\n", + "\n", + " // location in version 3\n", + " if (IPython.notebook.keyboard_manager) {\n", + " IPython.notebook.keyboard_manager.register_events(el);\n", + " }\n", + " else {\n", + " // location in version 2\n", + " IPython.keyboard_manager.register_events(el);\n", + " }\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._key_event_extra = function(event, name) {\n", + " var manager = IPython.notebook.keyboard_manager;\n", + " if (!manager)\n", + " manager = IPython.keyboard_manager;\n", + "\n", + " // Check for shift+enter\n", + " if (event.shiftKey && event.which == 13) {\n", + " this.canvas_div.blur();\n", + " event.shiftKey = false;\n", + " // Send a \"J\" for go to next cell\n", + " event.which = 74;\n", + " event.keyCode = 74;\n", + " manager.command_mode();\n", + " manager.handle_keydown(event);\n", + " }\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_save = function(fig, msg) {\n", + " fig.ondownload(fig, null);\n", + "}\n", + "\n", + "\n", + "mpl.find_output_cell = function(html_output) {\n", + " // Return the cell and output element which can be found *uniquely* in the notebook.\n", + " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", + " // IPython event is triggered only after the cells have been serialised, which for\n", + " // our purposes (turning an active figure into a static one), is too late.\n", + " var cells = IPython.notebook.get_cells();\n", + " var ncells = cells.length;\n", + " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", + " data = data.data;\n", + " }\n", + " if (data['text/html'] == html_output) {\n", + " return [cell, data, j];\n", + " }\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + "// Register the function which deals with the matplotlib target/channel.\n", + "// The kernel may be null if the page has been refreshed.\n", + "if (IPython.notebook.kernel != null) {\n", + " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", + "}\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Finally show that this instrument also works within a loop\n", + "dummy = parameter.ManualParameter(name=\"dummy\")\n", + "data = qc.Loop(dummy[0:50:1]).each(acquisition_controller.acquisition).run(name='AlazarTest')\n", + "qc.MatPlot(data.acquisition_controller_acquisition)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "data" + ] + } + ], + "metadata": { + "anaconda-cloud": {}, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.1" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/qcodes/instrument_drivers/AlazarTech/HD_filter_controller.py b/qcodes/instrument_drivers/AlazarTech/HD_filter_controller.py new file mode 100644 index 000000000000..6e31d604a508 --- /dev/null +++ b/qcodes/instrument_drivers/AlazarTech/HD_filter_controller.py @@ -0,0 +1,84 @@ +class HD_Controller(AcquisitionController): + """Heterodyne Measurement Controller + Does averaged DFT on 2 channel Alazar measurement + + TODO(nataliejpg) handling of channel number + TODO(nataliejpg) test angle data + """ + + def __init__(self, freq_dif): + self.freq_dif = freq_dif + self.samples_per_record = None + self.records_per_buffer = None + self.buffers_per_acquisition = None + self.number_of_channels = 2 + self.buffer = None + + def pre_start_capture(self, alazar): + """Get config data from alazar card and set up DFT""" + self.samples_per_record = alazar.samples_per_record() + self.records_per_buffer = alazar.records_per_buffer() + self.buffers_per_acquisition = alazar.buffers_per_acquisition() + self.sample_rate = alazar.get_sample_speed() + self.buffer = np.zeros(self.samples_per_record * + self.records_per_buffer * + self.number_of_channels) + # TODO(nataliejpg) leave explicit or save lines? add error/logging? + averaging = self.buffers_per_acquisition * self.records_per_buffer + record_duration = self.samples_per_record / self.sample_rate + time_period_dif = 1 / self.freq_dif + cycles_measured = record_duration / time_period_dif + oversampling_rate = self.sample_rate / (2 * self.freq_dif) + print("Average over {} records".format(averaging)) + print("Oscillations per record: {} (expect 100+)" + .format(cycles_measured)) + print("Oversampling rate: {} (expect > 2)".format(oversampling_rate)) + + integer_list = np.arange(self.samples_per_record) + angle_list = (2 * np.pi * self.freq_dif / self.sample_rate * + integer_list) + self.cos_list = np.cos(angle_list) + self.sin_list = np.sin(angle_list) + + def pre_acquire(self, alazar): + # gets called after 'AlazarStartCapture' + pass + + def handle_buffer(self, alazar, data): + self.buffer += data + + def post_acquire(self, alazar): + """Average over records in buffer and do DFT: + assumes samples are arranged in the buffer as follows: + S0A, S0B, ..., S1A, S1B, ... + with SXY the sample number X of channel Y. + """ + records_per_acquisition = (1. * self.buffers_per_acquisition * + self.records_per_buffer) + recordA = np.zeros(self.samples_per_record) + for i in range(self.records_per_buffer): + i0 = (i * self.samples_per_record * self.number_of_channels) + i1 = (i0 + self.samples_per_record * self.number_of_channels) + recordA += (self.buffer[i0:i1:self.number_of_channels] / + records_per_acquisition) + recordB = np.zeros(self.samples_per_record) + for i in range(self.records_per_buffer): + i0 = (i * self.samples_per_record * self.number_of_channels + 1) + i1 = (i0 + self.samples_per_record * self.number_of_channels) + recordB += (self.buffer[i0:i1:self.number_of_channels] / + records_per_acquisition) + + resA = self.fit(recordA) + resB = self.fit(recordB) + + return resA, resB + + def fit(self, rec): + """Do Discrete Fourier Transform and return magnitude and phase data""" + RePart = np.dot(rec, self.cos_list) / self.samples_per_record + ImPart = np.dot(rec, self.sin_list) / self.samples_per_record + # factor of 2 as amplitude is split between finite term + # and double frequency term + ampl = 2 * np.sqrt(RePart ** 2 + ImPart ** 2) + phase = math.atan2(ImPart, RePart) * 180 / (2 * math.pi) + return [ampl, phase] \ No newline at end of file diff --git a/qcodes/instrument_drivers/AlazarTech/basic_controller.py b/qcodes/instrument_drivers/AlazarTech/basic_controller.py new file mode 100644 index 000000000000..da79626b162f --- /dev/null +++ b/qcodes/instrument_drivers/AlazarTech/basic_controller.py @@ -0,0 +1,118 @@ +class Basic_AcquisitionController(AcquisitionController): + """ + This class represents an acquisition controller. It is designed to be used + primarily to check the function of the Alazar driver to do what it should and should be used + with one buffer and one record and will return each of the samples unprocessed + + args: + name: name for this acquisition_conroller as an instrument + alazar_name: the name of the alazar instrument such that this controller + can communicate with the Alazar + **kwargs: kwargs are forwarded to the Instrument base class + """ + def __init__(self, name, alazar_name, **kwargs): + self.acquisitionkwargs = {} + self.samples_per_record = None + self.bits_per_sample = None + self.records_per_buffer = None + self.buffers_per_acquisition = None + self.allocated_buffers = None + # TODO(damazter) (S) this is not very general: + self.number_of_channels = 2 + self.buffer = None + # make a call to the parent class and by extension, create the parameter + # structure of this class + super().__init__(name, alazar_name, **kwargs) + self.add_parameter("acquisition", get_cmd=self.do_acquisition) + + def update_acquisitionkwargs(self, **kwargs): + """ + This method must be used to update the kwargs used for the acquisition + with the alazar_driver.acquire + :param kwargs: + :return: + """ + self.acquisitionkwargs.update(**kwargs) + + def do_acquisition(self): + """ + this method performs an acquisition, which is the get_cmd for the + acquisiion parameter of this instrument + :return: + """ + value = self._get_alazar().acquire(acquisition_controller=self, + **self.acquisitionkwargs) + return value + + def pre_start_capture(self): + """ + See AcquisitionController + :return: + """ + + def pre_acquire(self): + """ + See AcquisitionController + :return: + """ + # this could be used to start an Arbitrary Waveform Generator, etc... + # using this method ensures that the contents are executed AFTER the + # Alazar card starts listening for a trigger pulse + pass + + def handle_buffer(self, data): + """ + See AcquisitionController + :return: + """ + self.buffer += data + + def post_acquire(self): + """ + See AcquisitionController + :return: + """ + alazar = self._get_alazar() + # average all records in a buffer + records_per_acquisition = (1. * self.buffers_per_acquisition * + self.records_per_buffer) + if records_per_acquisition != 1: + raise ValueError('records per acquisition and buffers per acquisition should be + set to 1 for this acquisition controller') + + # one of these two... + # expects S00A, S01A, ...S0B, S1B,... + recordA = np.zeros(self.samples_per_record) + for i in range(self.records_per_buffer): + i0 = i * self.samples_per_record + i1 = i0 + self.samples_per_record + recordA += self.buffer[i0:i1] / records_per_acquisition + + recordB = np.zeros(self.samples_per_record) + for i in range(self.records_per_buffer): + i0 = i * self.samples_per_record + len(self.buffer) // 2 + i1 = i0 + self.samples_per_record + recordB += self.buffer[i0:i1] / records_per_acquisition + + # 1 + # average over records in buffer: + # for ATS9360 samples are arranged in the buffer as follows: + # S00A, S00B, S01A, S01B ..., S10A, S10B, ... + # where SXYZ is record X, sample Y, channel Z. + records_per_acquisition = (self.buffers_per_acquisition * + self.records_per_buffer) + recordA = np.zeros(self.samples_per_record) + for i in range(self.records_per_buffer): + i0 = (i * self.samples_per_record * self.number_of_channels) + i1 = (i0 + self.samples_per_record * self.number_of_channels) + recordA += (self.buffer[i0:i1:self.number_of_channels] / + records_per_acquisition) + + recordB = np.zeros(self.samples_per_record) + for i in range(self.records_per_buffer): + i0 = (i * self.samples_per_record * self.number_of_channels + 1) + i1 = (i0 + self.samples_per_record * self.number_of_channels) + recordB += (self.buffer[i0:i1:self.number_of_channels] / + records_per_acquisition) + + return recordA, recordB From a04a377ca84f73b859c83d217fb4f74e324017ca Mon Sep 17 00:00:00 2001 From: Natalie Pearson Date: Tue, 1 Nov 2016 15:06:31 +0100 Subject: [PATCH 014/180] basic controller done, starting on hd controllers --- .../Qcodes example with Alazar ATS9360.ipynb | 6 +- .../instrument_drivers/AlazarTech/ATS9360.py | 6 +- .../AlazarTech/HD_filter_controller.py | 173 ++++++++++++------ .../AlazarTech/basic_controller.py | 34 ++-- .../AlazarTech/single_shot_controller.py | 90 +++++++++ 5 files changed, 236 insertions(+), 73 deletions(-) create mode 100644 qcodes/instrument_drivers/AlazarTech/single_shot_controller.py diff --git a/docs/examples/Qcodes example with Alazar ATS9360.ipynb b/docs/examples/Qcodes example with Alazar ATS9360.ipynb index 4f025b9e62bf..d5dec7e0566d 100644 --- a/docs/examples/Qcodes example with Alazar ATS9360.ipynb +++ b/docs/examples/Qcodes example with Alazar ATS9360.ipynb @@ -1657,7 +1657,11 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.1" + "version": "3.5.2" + }, + "widgets": { + "state": {}, + "version": "1.0.0" } }, "nbformat": 4, diff --git a/qcodes/instrument_drivers/AlazarTech/ATS9360.py b/qcodes/instrument_drivers/AlazarTech/ATS9360.py index dbb3e6e2929d..4a5d195cf8ca 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS9360.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS9360.py @@ -168,10 +168,10 @@ def __init__(self, name, **kwargs): # I could not find this in the documentation but somehow I have the # feeling it still should be a multiple of something # NOTE by ramiro: At least in previous python implementations(PycQED delft), - # this is an artifact for compatibility with AWG sequencing, + # this is an artifact for compatibility with AWG sequencing, # not particular to any ATS architecture. - # ==> this is a construction imposed by the memory strategy - # implemented on the python driver + # ==> this is a construction imposed by the memory strategy + # implemented on the python driver # we are writing, not limited by any actual ATS feature. self.add_parameter(name='records_per_buffer', diff --git a/qcodes/instrument_drivers/AlazarTech/HD_filter_controller.py b/qcodes/instrument_drivers/AlazarTech/HD_filter_controller.py index 6e31d604a508..67923c006ffd 100644 --- a/qcodes/instrument_drivers/AlazarTech/HD_filter_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/HD_filter_controller.py @@ -1,84 +1,143 @@ -class HD_Controller(AcquisitionController): - """Heterodyne Measurement Controller - Does averaged DFT on 2 channel Alazar measurement +from .ATS import AcquisitionController +import math +import numpy as np - TODO(nataliejpg) handling of channel number - TODO(nataliejpg) test angle data +# seq mode 1, many shots +class HD_Filter_Acquisition_Controller(AcquisitionController): + """Heterodyne Measurement Controller + Mixes signal with demodulation frequency and then uses selected filter + to filter double frequency componenet and return average """ - - def __init__(self, freq_dif): - self.freq_dif = freq_dif + def __init__(self, name, alazar_name, demodulation_frequency, **kwargs): + self.demodulation_frequency = demodulation_frequency + self.acquisitionkwargs = {} self.samples_per_record = None + self.bits_per_sample = None self.records_per_buffer = None self.buffers_per_acquisition = None + self.allocated_buffers = None + # TODO(damazter) (S) this is not very general: self.number_of_channels = 2 + self.cos_list = None + self.sin_list = None self.buffer = None + self.buffer_count = None + # make a call to the parent class and by extension, create the parameter + # structure of this class + super().__init__(name, alazar_name, **kwargs) + self.add_parameter("acquisition", get_cmd=self.do_acquisition) - def pre_start_capture(self, alazar): - """Get config data from alazar card and set up DFT""" - self.samples_per_record = alazar.samples_per_record() - self.records_per_buffer = alazar.records_per_buffer() - self.buffers_per_acquisition = alazar.buffers_per_acquisition() - self.sample_rate = alazar.get_sample_speed() - self.buffer = np.zeros(self.samples_per_record * - self.records_per_buffer * - self.number_of_channels) - # TODO(nataliejpg) leave explicit or save lines? add error/logging? - averaging = self.buffers_per_acquisition * self.records_per_buffer - record_duration = self.samples_per_record / self.sample_rate - time_period_dif = 1 / self.freq_dif - cycles_measured = record_duration / time_period_dif - oversampling_rate = self.sample_rate / (2 * self.freq_dif) - print("Average over {} records".format(averaging)) - print("Oscillations per record: {} (expect 100+)" - .format(cycles_measured)) - print("Oversampling rate: {} (expect > 2)".format(oversampling_rate)) + def update_acquisitionkwargs(self, **kwargs): + """ + This method must be used to update the kwargs used for the acquisition + with the alazar_driver.acquire + :param kwargs: + :return: + """ + self.acquisitionkwargs.update(**kwargs) + + def do_acquisition(self): + """ + this method performs an acquisition, which is the get_cmd for the + acquisiion parameter of this instrument + :return: + """ + value = self._get_alazar().acquire(acquisition_controller=self, + **self.acquisitionkwargs) + return value + def pre_start_capture(self): + """ + See AcquisitionController + :return: + """ + alazar = self._get_alazar() + self.samples_per_record = alazar.samples_per_record.get() + self.records_per_buffer = alazar.records_per_buffer.get() + self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() + self.buffer_count = 0 + sample_speed = alazar.get_sample_rate() integer_list = np.arange(self.samples_per_record) - angle_list = (2 * np.pi * self.freq_dif / self.sample_rate * + angle_list = (2 * np.pi * self.demodulation_frequency / sample_speed * integer_list) + self.cos_list = np.cos(angle_list) self.sin_list = np.sin(angle_list) + self.buffer = np.zeros(self.samples_per_record * + self.records_per_buffer * + self.number_of_channels * + self.buffers_per_acquisition) - def pre_acquire(self, alazar): - # gets called after 'AlazarStartCapture' + def pre_acquire(self): + """ + See AcquisitionController + :return: + """ + # this could be used to start an Arbitrary Waveform Generator, etc... + # using this method ensures that the contents are executed AFTER the + # Alazar card starts listening for a trigger pulse pass - def handle_buffer(self, alazar, data): - self.buffer += data + def handle_buffer(self, data): + """ + See AcquisitionController + :return: + """ + buffer_length = (self.samples_per_record * + self.records_per_buffer * + self.number_of_channels) + i0 = self.buffer_count * buffer_length + i1 = i0 + buffer_length + self.buffer[i0:i1] = data + self.buffer_count += 1 - def post_acquire(self, alazar): - """Average over records in buffer and do DFT: - assumes samples are arranged in the buffer as follows: - S0A, S0B, ..., S1A, S1B, ... - with SXY the sample number X of channel Y. + def post_acquire(self): + """ + See AcquisitionController + :return: """ + alazar = self._get_alazar() + # average all records in a buffer records_per_acquisition = (1. * self.buffers_per_acquisition * self.records_per_buffer) - recordA = np.zeros(self.samples_per_record) + recordA = np.zeros((self.samples_per_record,self.records_per_buffer)) for i in range(self.records_per_buffer): - i0 = (i * self.samples_per_record * self.number_of_channels) - i1 = (i0 + self.samples_per_record * self.number_of_channels) - recordA += (self.buffer[i0:i1:self.number_of_channels] / - records_per_acquisition) + i0 = i * self.samples_per_record + i1 = i0 + self.samples_per_record + recordA[] = self.buffer[i0:i1] / records_per_acquisition + recordB = np.zeros(self.samples_per_record) for i in range(self.records_per_buffer): - i0 = (i * self.samples_per_record * self.number_of_channels + 1) - i1 = (i0 + self.samples_per_record * self.number_of_channels) - recordB += (self.buffer[i0:i1:self.number_of_channels] / - records_per_acquisition) + i0 = i * self.samples_per_record + len(self.buffer) // 2 + i1 = i0 + self.samples_per_record + recordB += self.buffer[i0:i1] / records_per_acquisition - resA = self.fit(recordA) - resB = self.fit(recordB) + if self.number_of_channels == 2: + # fit channel A and channel B + res1 = self.fit(recordA) + res2 = self.fit(recordB) + # return [alazar.signal_to_volt(1, res1[0] + 127.5), + # alazar.signal_to_volt(2, res2[0] + 127.5), + # res1[1], res2[1], + # (res1[1] - res2[1]) % 360] + return alazar.signal_to_volt(1, res1[0] + 127.5) + else: + raise Exception("Could not find CHANNEL_B during data extraction") + return None - return resA, resB + def fit(self, buf): + """ + the DFT is implemented in this method + :param buf: buffer to perform the transform on + :return: return amplitude and phase of the resulted transform + """ + # Discrete Fourier Transform + RePart = np.dot(buf - 127.5, self.cos_list) / self.samples_per_record + ImPart = np.dot(buf - 127.5, self.sin_list) / self.samples_per_record - def fit(self, rec): - """Do Discrete Fourier Transform and return magnitude and phase data""" - RePart = np.dot(rec, self.cos_list) / self.samples_per_record - ImPart = np.dot(rec, self.sin_list) / self.samples_per_record - # factor of 2 as amplitude is split between finite term - # and double frequency term + # the factor of 2 in the amplitude is due to the fact that there is + # a negative frequency as well ampl = 2 * np.sqrt(RePart ** 2 + ImPart ** 2) - phase = math.atan2(ImPart, RePart) * 180 / (2 * math.pi) - return [ampl, phase] \ No newline at end of file + + # see manual page 52!!! (using unsigned data) + return [ampl, math.atan2(ImPart, RePart) * 360 / (2 * math.pi)] \ No newline at end of file diff --git a/qcodes/instrument_drivers/AlazarTech/basic_controller.py b/qcodes/instrument_drivers/AlazarTech/basic_controller.py index da79626b162f..580e6d73eb1b 100644 --- a/qcodes/instrument_drivers/AlazarTech/basic_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/basic_controller.py @@ -1,8 +1,12 @@ -class Basic_AcquisitionController(AcquisitionController): +from .ATS import AcquisitionController +import numpy as np + + +class Basic_Acquisition_Controller(AcquisitionController): """ - This class represents an acquisition controller. It is designed to be used - primarily to check the function of the Alazar driver to do what it should and should be used - with one buffer and one record and will return each of the samples unprocessed + This class represents an acquisition controller. It is designed to be used + primarily to check the function of the Alazar driver and should be used + with one buffer and one record to return each of the samples unprocessed args: name: name for this acquisition_conroller as an instrument @@ -10,13 +14,14 @@ class Basic_AcquisitionController(AcquisitionController): can communicate with the Alazar **kwargs: kwargs are forwarded to the Instrument base class """ + def __init__(self, name, alazar_name, **kwargs): self.acquisitionkwargs = {} self.samples_per_record = None self.bits_per_sample = None self.records_per_buffer = None self.buffers_per_acquisition = None - self.allocated_buffers = None + self.allocated_buffers = None # needed?? # TODO(damazter) (S) this is not very general: self.number_of_channels = 2 self.buffer = None @@ -49,6 +54,13 @@ def pre_start_capture(self): See AcquisitionController :return: """ + alazar = self._get_alazar() + self.samples_per_record = alazar.samples_per_record.get() + self.records_per_buffer = alazar.records_per_buffer.get() + self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() + self.buffer = np.zeros(self.samples_per_record * + self.records_per_buffer * + self.number_of_channels) def pre_acquire(self): """ @@ -72,18 +84,16 @@ def post_acquire(self): See AcquisitionController :return: """ - alazar = self._get_alazar() # average all records in a buffer records_per_acquisition = (1. * self.buffers_per_acquisition * self.records_per_buffer) if records_per_acquisition != 1: - raise ValueError('records per acquisition and buffers per acquisition should be - set to 1 for this acquisition controller') - + raise ValueError( + 'records per acquisition and buffers per acquisition should be set to 1 for this acquisition controller') # one of these two... # expects S00A, S01A, ...S0B, S1B,... recordA = np.zeros(self.samples_per_record) - for i in range(self.records_per_buffer): + for i in range(self.records_per_buffer): i0 = i * self.samples_per_record i1 = i0 + self.samples_per_record recordA += self.buffer[i0:i1] / records_per_acquisition @@ -93,7 +103,7 @@ def post_acquire(self): i0 = i * self.samples_per_record + len(self.buffer) // 2 i1 = i0 + self.samples_per_record recordB += self.buffer[i0:i1] / records_per_acquisition - + # 1 # average over records in buffer: # for ATS9360 samples are arranged in the buffer as follows: @@ -114,5 +124,5 @@ def post_acquire(self): i1 = (i0 + self.samples_per_record * self.number_of_channels) recordB += (self.buffer[i0:i1:self.number_of_channels] / records_per_acquisition) - + return recordA, recordB diff --git a/qcodes/instrument_drivers/AlazarTech/single_shot_controller.py b/qcodes/instrument_drivers/AlazarTech/single_shot_controller.py new file mode 100644 index 000000000000..cad31b79bf4e --- /dev/null +++ b/qcodes/instrument_drivers/AlazarTech/single_shot_controller.py @@ -0,0 +1,90 @@ +from .ATS import AcquisitionController +import math +import numpy as np + + +class Single_Shot_Acquisition_Controller(AcquisitionController): + """Heterodyne Measurement Controller + Mixes signal with demodulation frequency and then uses selected filter to filter + double frequency componenet + + TODO(nataliejpg) handling of channel number + TODO(nataliejpg) test angle data + """ + + def __init__(self, freq_dif): + self.freq_dif = freq_dif + self.samples_per_record = None + self.records_per_buffer = None + self.buffers_per_acquisition = None + self.number_of_channels = 2 + self.buffer = None + + def pre_start_capture(self, alazar): + """Get config data from alazar card and set up DFT""" + self.samples_per_record = alazar.samples_per_record() + self.records_per_buffer = alazar.records_per_buffer() + self.buffers_per_acquisition = alazar.buffers_per_acquisition() + self.sample_rate = alazar.get_sample_speed() + self.buffer = np.zeros(self.samples_per_record * + self.records_per_buffer * + self.number_of_channels) + # TODO(nataliejpg) leave explicit or save lines? add error/logging? + averaging = self.buffers_per_acquisition * self.records_per_buffer + record_duration = self.samples_per_record / self.sample_rate + time_period_dif = 1 / self.freq_dif + cycles_measured = record_duration / time_period_dif + oversampling_rate = self.sample_rate / (2 * self.freq_dif) + print("Average over {} records".format(averaging)) + print("Oscillations per record: {} (expect 100+)" + .format(cycles_measured)) + print("Oversampling rate: {} (expect > 2)".format(oversampling_rate)) + + integer_list = np.arange(self.samples_per_record) + angle_list = (2 * np.pi * self.freq_dif / self.sample_rate * + integer_list) + self.cos_list = np.cos(angle_list) + self.sin_list = np.sin(angle_list) + + def pre_acquire(self, alazar): + # gets called after 'AlazarStartCapture' + pass + + def handle_buffer(self, alazar, data): + self.buffer += data + + def post_acquire(self, alazar): + """Average over records in buffer and do DFT: + assumes samples are arranged in the buffer as follows: + S0A, S0B, ..., S1A, S1B, ... + with SXY the sample number X of channel Y. + """ + records_per_acquisition = (1. * self.buffers_per_acquisition * + self.records_per_buffer) + recordA = np.zeros(self.samples_per_record) + for i in range(self.records_per_buffer): + i0 = (i * self.samples_per_record * self.number_of_channels) + i1 = (i0 + self.samples_per_record * self.number_of_channels) + recordA += (self.buffer[i0:i1:self.number_of_channels] / + records_per_acquisition) + recordB = np.zeros(self.samples_per_record) + for i in range(self.records_per_buffer): + i0 = (i * self.samples_per_record * self.number_of_channels + 1) + i1 = (i0 + self.samples_per_record * self.number_of_channels) + recordB += (self.buffer[i0:i1:self.number_of_channels] / + records_per_acquisition) + + resA = self.fit(recordA) + resB = self.fit(recordB) + + return resA, resB + + def fit(self, rec): + """Do Discrete Fourier Transform and return magnitude and phase data""" + RePart = np.dot(rec, self.cos_list) / self.samples_per_record + ImPart = np.dot(rec, self.sin_list) / self.samples_per_record + # factor of 2 as amplitude is split between finite term + # and double frequency term + ampl = 2 * np.sqrt(RePart ** 2 + ImPart ** 2) + phase = math.atan2(ImPart, RePart) * 180 / (2 * math.pi) + return [ampl, phase] \ No newline at end of file From fc47d1ae1a345d2b7422cb05d4fb355284799eaa Mon Sep 17 00:00:00 2001 From: nataliejpg Date: Tue, 1 Nov 2016 19:10:54 +0100 Subject: [PATCH 015/180] Make changes to ATS9360 and acq contr so that it can be configured correctly and new eg notebook (needs cleaning up) --- ...es example with Alazar ATS9360-Copy1.ipynb | 3534 +++++++++++++++++ .../instrument_drivers/AlazarTech/ATS9360.py | 41 +- .../AlazarTech/basic_controller.py | 21 +- 3 files changed, 3559 insertions(+), 37 deletions(-) create mode 100644 docs/examples/Qcodes example with Alazar ATS9360-Copy1.ipynb diff --git a/docs/examples/Qcodes example with Alazar ATS9360-Copy1.ipynb b/docs/examples/Qcodes example with Alazar ATS9360-Copy1.ipynb new file mode 100644 index 000000000000..b56964d6af63 --- /dev/null +++ b/docs/examples/Qcodes example with Alazar ATS9360-Copy1.ipynb @@ -0,0 +1,3534 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "application/javascript": [ + "/*\r\n", + " * Qcodes Jupyter/IPython widgets\r\n", + " */\r\n", + "require([\r\n", + " 'nbextensions/widgets/widgets/js/widget',\r\n", + " 'nbextensions/widgets/widgets/js/manager'\r\n", + "], function (widget, manager) {\r\n", + "\r\n", + " var UpdateView = widget.DOMWidgetView.extend({\r\n", + " render: function() {\r\n", + " window.MYWIDGET = this;\r\n", + " this._interval = 0;\r\n", + " this.update();\r\n", + " },\r\n", + " update: function() {\r\n", + " this.display(this.model.get('_message'));\r\n", + " this.setInterval();\r\n", + " },\r\n", + " display: function(message) {\r\n", + " /*\r\n", + " * display method: override this for custom display logic\r\n", + " */\r\n", + " this.el.innerHTML = message;\r\n", + " },\r\n", + " remove: function() {\r\n", + " clearInterval(this._updater);\r\n", + " },\r\n", + " setInterval: function(newInterval) {\r\n", + " var me = this;\r\n", + " if(newInterval===undefined) newInterval = me.model.get('interval');\r\n", + " if(newInterval===me._interval) return;\r\n", + "\r\n", + " me._interval = newInterval;\r\n", + "\r\n", + " if(me._updater) clearInterval(me._updater);\r\n", + "\r\n", + " if(me._interval) {\r\n", + " me._updater = setInterval(function() {\r\n", + " me.send({myupdate: true});\r\n", + " if(!me.model.comm_live) {\r\n", + " console.log('missing comm, canceling widget updates', me);\r\n", + " clearInterval(me._updater);\r\n", + " }\r\n", + " }, me._interval * 1000);\r\n", + " }\r\n", + " }\r\n", + " });\r\n", + " manager.WidgetManager.register_widget_view('UpdateView', UpdateView);\r\n", + "\r\n", + " var HiddenUpdateView = UpdateView.extend({\r\n", + " display: function(message) {\r\n", + " this.$el.hide();\r\n", + " }\r\n", + " });\r\n", + " manager.WidgetManager.register_widget_view('HiddenUpdateView', HiddenUpdateView);\r\n", + "\r\n", + " var SubprocessView = UpdateView.extend({\r\n", + " render: function() {\r\n", + " var me = this;\r\n", + " me._interval = 0;\r\n", + " me._minimize = '';\r\n", + " me._restore = '';\r\n", + "\r\n", + " // max lines of output to show\r\n", + " me.maxOutputLength = 500;\r\n", + "\r\n", + " // in case there is already an outputView present,\r\n", + " // like from before restarting the kernel\r\n", + " $('.qcodes-output-view').not(me.$el).remove();\r\n", + "\r\n", + " me.$el\r\n", + " .addClass('qcodes-output-view')\r\n", + " .attr('qcodes-state', 'docked')\r\n", + " .html(\r\n", + " '
' +\r\n", + " '
' +\r\n", + " '' +\r\n", + " '' +\r\n", + " '' +\r\n", + " '' +\r\n", + " '' +\r\n", + " '' +\r\n", + " '
' +\r\n", + " '
'\r\n",
+       "                );\r\n",
+       "\r\n",
+       "            me.clearButton = me.$el.find('.qcodes-clear-output');\r\n",
+       "            me.minButton = me.$el.find('.qcodes-minimize');\r\n",
+       "            me.outputArea = me.$el.find('pre');\r\n",
+       "            me.subprocessList = me.$el.find('.qcodes-process-list');\r\n",
+       "            me.abortButton = me.$el.find('.qcodes-abort-loop');\r\n",
+       "            me.processLinesButton = me.$el.find('.qcodes-processlines')\r\n",
+       "\r\n",
+       "            me.outputLines = [];\r\n",
+       "\r\n",
+       "            me.clearButton.click(function() {\r\n",
+       "                me.outputArea.html('');\r\n",
+       "                me.clearButton.addClass('disabled');\r\n",
+       "            });\r\n",
+       "\r\n",
+       "            me.abortButton.click(function() {\r\n",
+       "                me.send({abort: true});\r\n",
+       "            });\r\n",
+       "\r\n",
+       "            me.processLinesButton.click(function() {\r\n",
+       "                // toggle multiline process list display\r\n",
+       "                me.subprocessesMultiline = !me.subprocessesMultiline;\r\n",
+       "                me.showSubprocesses();\r\n",
+       "            });\r\n",
+       "\r\n",
+       "            me.$el.find('.js-state').click(function() {\r\n",
+       "                var state = this.className.substr(this.className.indexOf('qcodes'))\r\n",
+       "                        .split('-')[1].split(' ')[0];\r\n",
+       "                me.model.set('_state', state);\r\n",
+       "            });\r\n",
+       "\r\n",
+       "            $(window)\r\n",
+       "                .off('resize.qcodes')\r\n",
+       "                .on('resize.qcodes', function() {me.clipBounds();});\r\n",
+       "\r\n",
+       "            me.update();\r\n",
+       "        },\r\n",
+       "\r\n",
+       "        updateState: function() {\r\n",
+       "            var me = this,\r\n",
+       "                oldState = me.$el.attr('qcodes-state'),\r\n",
+       "                state = me.model.get('_state');\r\n",
+       "\r\n",
+       "            if(state === oldState) return;\r\n",
+       "\r\n",
+       "            setTimeout(function() {\r\n",
+       "                // not sure why I can't pop it out of the widgetarea in render, but it seems that\r\n",
+       "                // some other bit of code resets the parent after render if I do it there.\r\n",
+       "                // To be safe, just do it on every state click.\r\n",
+       "                me.$el.appendTo('body');\r\n",
+       "\r\n",
+       "                if(oldState === 'floated') {\r\n",
+       "                    console.log('here');\r\n",
+       "                    me.$el.draggable('destroy').css({left:'', top: ''});\r\n",
+       "                }\r\n",
+       "\r\n",
+       "                me.$el.attr('qcodes-state', state);\r\n",
+       "\r\n",
+       "                if(state === 'floated') {\r\n",
+       "                    me.$el\r\n",
+       "                        .draggable({stop: function() { me.clipBounds(); }})\r\n",
+       "                        .css({\r\n",
+       "                            left: window.innerWidth - me.$el.width() - 15,\r\n",
+       "                            top: window.innerHeight - me.$el.height() - 10\r\n",
+       "                        });\r\n",
+       "                }\r\n",
+       "\r\n",
+       "                // any previous highlighting is now moot\r\n",
+       "                me.$el.removeClass('qcodes-highlight');\r\n",
+       "            }, 0);\r\n",
+       "\r\n",
+       "        },\r\n",
+       "\r\n",
+       "        clipBounds: function() {\r\n",
+       "            var me = this;\r\n",
+       "            if(me.$el.attr('qcodes-state') === 'floated') {\r\n",
+       "                var bounds = me.$el[0].getBoundingClientRect(),\r\n",
+       "                    minVis = 40,\r\n",
+       "                    maxLeft = window.innerWidth - minVis,\r\n",
+       "                    minLeft = minVis - bounds.width,\r\n",
+       "                    maxTop = window.innerHeight - minVis;\r\n",
+       "\r\n",
+       "                if(bounds.left > maxLeft) me.$el.css('left', maxLeft);\r\n",
+       "                else if(bounds.left < minLeft) me.$el.css('left', minLeft);\r\n",
+       "\r\n",
+       "                if(bounds.top > maxTop) me.$el.css('top', maxTop);\r\n",
+       "                else if(bounds.top < 0) me.$el.css('top', 0);\r\n",
+       "            }\r\n",
+       "        },\r\n",
+       "\r\n",
+       "        display: function(message) {\r\n",
+       "            var me = this;\r\n",
+       "            if(message) {\r\n",
+       "                var initialScroll = me.outputArea.scrollTop();\r\n",
+       "                me.outputArea.scrollTop(me.outputArea.prop('scrollHeight'));\r\n",
+       "                var scrollBottom = me.outputArea.scrollTop();\r\n",
+       "\r\n",
+       "                if(me.$el.attr('qcodes-state') === 'minimized') {\r\n",
+       "                    // if we add text and the box is minimized, highlight the\r\n",
+       "                    // title bar to alert the user that there are new messages.\r\n",
+       "                    // remove then add the class, so we get the animation again\r\n",
+       "                    // if it's already highlighted\r\n",
+       "                    me.$el.removeClass('qcodes-highlight');\r\n",
+       "                    setTimeout(function(){\r\n",
+       "                        me.$el.addClass('qcodes-highlight');\r\n",
+       "                    }, 0);\r\n",
+       "                }\r\n",
+       "\r\n",
+       "                var newLines = message.split('\\n'),\r\n",
+       "                    out = me.outputLines,\r\n",
+       "                    outLen = out.length;\r\n",
+       "                if(outLen) out[outLen - 1] += newLines[0];\r\n",
+       "                else out.push(newLines[0]);\r\n",
+       "\r\n",
+       "                for(var i = 1; i < newLines.length; i++) {\r\n",
+       "                    out.push(newLines[i]);\r\n",
+       "                }\r\n",
+       "\r\n",
+       "                if(out.length > me.maxOutputLength) {\r\n",
+       "                    out.splice(0, out.length - me.maxOutputLength + 1,\r\n",
+       "                        '<<< Output clipped >>>');\r\n",
+       "                }\r\n",
+       "\r\n",
+       "                me.outputArea.text(out.join('\\n'));\r\n",
+       "                me.clearButton.removeClass('disabled');\r\n",
+       "\r\n",
+       "                // if we were scrolled to the bottom initially, make sure\r\n",
+       "                // we stay that way.\r\n",
+       "                me.outputArea.scrollTop(initialScroll === scrollBottom ?\r\n",
+       "                    me.outputArea.prop('scrollHeight') : initialScroll);\r\n",
+       "            }\r\n",
+       "\r\n",
+       "            me.showSubprocesses();\r\n",
+       "            me.updateState();\r\n",
+       "        },\r\n",
+       "\r\n",
+       "        showSubprocesses: function() {\r\n",
+       "            var me = this,\r\n",
+       "                replacer = me.subprocessesMultiline ? '
' : ', ',\r\n", + " processes = (me.model.get('_processes') || '')\r\n", + " .replace(/\\n/g, '>' + replacer + '<');\r\n", + "\r\n", + " if(processes) processes = '<' + processes + '>';\r\n", + " else processes = 'No subprocesses';\r\n", + "\r\n", + " me.abortButton.toggleClass('disabled', processes.indexOf('Measurement')===-1);\r\n", + "\r\n", + " me.subprocessList.html(processes);\r\n", + " }\r\n", + " });\r\n", + " manager.WidgetManager.register_widget_view('SubprocessView', SubprocessView);\r\n", + "});\r\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "No loop running\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "a:\\qcodes\\qcodes\\process\\helpers.py:27: UserWarning: Multiprocessing is in beta, use at own risk\n", + " warnings.warn(\"Multiprocessing is in beta, use at own risk\", UserWarning)\n" + ] + } + ], + "source": [ + "# import all necessary things\n", + "%matplotlib nbagg\n", + "\n", + "import qcodes as qc\n", + "import qcodes.instrument.parameter as parameter\n", + "import qcodes.instrument_drivers.AlazarTech.ATS9360 as ATSdriver\n", + "import qcodes.instrument_drivers.AlazarTech.ATS_acquisition_controllers as ats_contr\n", + "\n", + "qc.halt_bg()\n", + "qc.set_mp_method('spawn') # force Windows behavior on mac\n", + "\n", + "# this makes a widget in the corner of the window to show and control\n", + "# subprocesses and any output they would print to the terminal\n", + "qc.show_subprocess_widget()" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[{'bits_per_sample': 12,\n", + " 'board_id': 1,\n", + " 'board_kind': 'ATS9360',\n", + " 'max_samples': 4294967294,\n", + " 'system_id': 1}]" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Command to list all alazar boards connected to the system\n", + "ATSdriver.AlazarTech_ATS.find_boards()" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "a:\\qcodes\\qcodes\\instrument\\metaclass.py:37: UserWarning: Multiprocessing is in beta, use at own risk\n", + " UserWarning)\n" + ] + }, + { + "data": { + "text/plain": [ + "{'CPLD_version': '25.16',\n", + " 'SDK_version': '5.9.25',\n", + " 'asopc_type': '1712554848',\n", + " 'driver_version': '5.9.25',\n", + " 'firmware': None,\n", + " 'latest_cal_date': '13-11-15',\n", + " 'memory_size': '4294967294',\n", + " 'model': 'ATS9360',\n", + " 'pcie_link_speed': '0.5GB/s',\n", + " 'pcie_link_width': '8',\n", + " 'serial': '970344',\n", + " 'vendor': 'AlazarTech'}" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Create the ATS9870 instrument on the new server \"alazar_server\"\n", + "ats_inst = ATSdriver.AlazarTech_ATS9360(name='Alazar1', server_name=\"alazar_server\")\n", + "# Print all information about this Alazar card\n", + "ats_inst.get_idn()" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import qcodes.instrument_drivers.rohde_schwarz.SGS100A as RSdriver" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Connected to: Rohde&Schwarz SGS100A (serial:1416.0505k02/103076, firmware:3.1.19.7-3.20.140.60.1) in 0.05s\n" + ] + } + ], + "source": [ + "localos = RSdriver.RohdeSchwarz_SGS100A('LO', 'TCPIP0::172.20.3.42::inst0::INSTR')" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "1000000.0" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "localos.frequency()" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "localos.power(-25)\n", + "localos.frequency(10e6)\n", + "#localos.status('on')" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "a:\\qcodes\\qcodes\\instrument\\metaclass.py:37: UserWarning: Multiprocessing is in beta, use at own risk\n", + " UserWarning)\n" + ] + } + ], + "source": [ + "# Instantiate an acquisition controller (In this case we are doing a simple DFT) on the same server (\"alazar_server\") and \n", + "# provide the name of the name of the alazar card that this controller should control\n", + "acquisition_controller = ats_contr.Demodulation_AcquisitionController(name='acquisition_controller', \n", + " demodulation_frequency=15e6, \n", + " alazar_name='Alazar1', \n", + " server_name=\"alazar_server\")" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Configure all settings in the Alazar card\n", + "ats_inst.config(clock_source='INTERNAL_CLOCK',\n", + " sample_rate='10MHZ_REF_500MSPS',\n", + " #clock_edge='CLOCK_EDGE_RISING',\n", + " #decimation=0,\n", + " #coupling=['AC','AC'],\n", + " channel_range=[2.,2.],\n", + " #impedance=[50,50],\n", + " #bwlimit=['DISABLED','DISABLED'],\n", + " #trigger_operation='TRIG_ENGINE_OP_J',\n", + " #trigger_engine1='TRIG_ENGINE_J',\n", + " trigger_source1='EXTERNAL',\n", + " #trigger_slope1='TRIG_SLOPE_POSITIVE',\n", + " #trigger_level1=128,\n", + " #trigger_engine2='TRIG_ENGINE_K',\n", + " #trigger_source2='DISABLE',\n", + " #trigger_slope2='TRIG_SLOPE_POSITIVE',\n", + " #trigger_level2=128,\n", + " #external_trigger_coupling='AC',\n", + " #external_trigger_range='ETR_5V',\n", + " #trigger_delay=0,\n", + " #timeout_ticks=0\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# This command is specific to this acquisition controller. The kwargs provided here are being forwarded to ats_inst.acquire\n", + "# This way, it becomes easy to change acquisition specific settings from the ipython notebook\n", + "acquisition_controller.update_acquisitionkwargs(#mode='NPT',\n", + " samples_per_record=1024,\n", + " records_per_buffer=70,\n", + " buffers_per_acquisition=1,\n", + " #channel_selection='AB',\n", + " #transfer_offset=0,\n", + " #external_startcapture='ENABLED',\n", + " #enable_record_headers='DISABLED',\n", + " #alloc_buffers='DISABLED',\n", + " #fifo_only_streaming='DISABLED',\n", + " #interleave_samples='DISABLED',\n", + " #get_processed_data='DISABLED',\n", + " allocated_buffers=1,\n", + " #buffer_timeout=1000\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "2.0976760253919644" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Getting the value of the parameter 'acquisition' of the instrument 'acquisition_controller' performes the entire acquisition \n", + "# protocol. This again depends on the specific implementation of the acquisition controller\n", + "acquisition_controller.acquisition()" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS9360.AlazarTech_ATS9360',\n", + " 'functions': {},\n", + " 'name': 'Alazar1',\n", + " 'parameters': {'IDN': {'__class__': 'qcodes.instrument.parameter.StandardParameter',\n", + " 'instrument': 'qcodes.instrument_drivers.AlazarTech.ATS9360.AlazarTech_ATS9360',\n", + " 'instrument_name': 'Alazar1',\n", + " 'label': 'IDN',\n", + " 'name': 'IDN',\n", + " 'ts': '2016-11-01 16:48:58',\n", + " 'units': '',\n", + " 'value': {'CPLD_version': '25.16',\n", + " 'SDK_version': '5.9.25',\n", + " 'asopc_type': '1712554848',\n", + " 'driver_version': '5.9.25',\n", + " 'firmware': None,\n", + " 'latest_cal_date': '13-11-15',\n", + " 'memory_size': '4294967294',\n", + " 'model': 'ATS9360',\n", + " 'pcie_link_speed': '0.5GB/s',\n", + " 'pcie_link_width': '8',\n", + " 'serial': '970344',\n", + " 'vendor': 'AlazarTech'}},\n", + " 'alloc_buffers': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Alloc Buffers',\n", + " 'name': 'alloc_buffers',\n", + " 'ts': '2016-11-01 16:48:23',\n", + " 'units': '',\n", + " 'value': 'DISABLED'},\n", + " 'allocated_buffers': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Allocated Buffers',\n", + " 'name': 'allocated_buffers',\n", + " 'ts': '2016-11-01 16:48:58',\n", + " 'units': '',\n", + " 'value': 1},\n", + " 'buffer_timeout': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Buffer Timeout',\n", + " 'name': 'buffer_timeout',\n", + " 'ts': '2016-11-01 16:48:23',\n", + " 'units': 'ms',\n", + " 'value': 1000},\n", + " 'buffers_per_acquisition': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Buffers per Acquisition',\n", + " 'name': 'buffers_per_acquisition',\n", + " 'ts': '2016-11-01 16:48:58',\n", + " 'units': '',\n", + " 'value': 1},\n", + " 'channel_range1': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Range channel 1',\n", + " 'name': 'channel_range1',\n", + " 'ts': '2016-11-01 16:48:54',\n", + " 'units': 'V',\n", + " 'value': 2.0},\n", + " 'channel_range2': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Range channel 2',\n", + " 'name': 'channel_range2',\n", + " 'ts': '2016-11-01 16:48:54',\n", + " 'units': 'V',\n", + " 'value': 2.0},\n", + " 'channel_selection': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Channel Selection',\n", + " 'name': 'channel_selection',\n", + " 'ts': '2016-11-01 16:48:23',\n", + " 'units': '',\n", + " 'value': 'AB'},\n", + " 'clock_edge': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Clock Edge',\n", + " 'name': 'clock_edge',\n", + " 'ts': '2016-11-01 16:48:23',\n", + " 'units': '',\n", + " 'value': 'CLOCK_EDGE_RISING'},\n", + " 'clock_source': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Clock Source',\n", + " 'name': 'clock_source',\n", + " 'ts': '2016-11-01 16:48:23',\n", + " 'units': '',\n", + " 'value': 'INTERNAL_CLOCK'},\n", + " 'coupling1': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Coupling channel 1',\n", + " 'name': 'coupling1',\n", + " 'ts': '2016-11-01 16:48:23',\n", + " 'units': '',\n", + " 'value': 'DC'},\n", + " 'coupling2': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Coupling channel 2',\n", + " 'name': 'coupling2',\n", + " 'ts': '2016-11-01 16:48:23',\n", + " 'units': '',\n", + " 'value': 'DC'},\n", + " 'decimation': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Decimation',\n", + " 'name': 'decimation',\n", + " 'ts': '2016-11-01 16:48:23',\n", + " 'units': '',\n", + " 'value': 0},\n", + " 'enable_record_headers': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Enable Record Headers',\n", + " 'name': 'enable_record_headers',\n", + " 'ts': '2016-11-01 16:48:23',\n", + " 'units': '',\n", + " 'value': 'DISABLED'},\n", + " 'external_startcapture': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'External Startcapture',\n", + " 'name': 'external_startcapture',\n", + " 'ts': '2016-11-01 16:48:23',\n", + " 'units': '',\n", + " 'value': 'ENABLED'},\n", + " 'external_trigger_coupling': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'External Trigger Coupling',\n", + " 'name': 'external_trigger_coupling',\n", + " 'ts': '2016-11-01 16:48:23',\n", + " 'units': '',\n", + " 'value': 'AC'},\n", + " 'external_trigger_range': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'External Trigger Range',\n", + " 'name': 'external_trigger_range',\n", + " 'ts': '2016-11-01 16:48:23',\n", + " 'units': '',\n", + " 'value': 'ETR_5V'},\n", + " 'fifo_only_streaming': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Fifo Only Streaming',\n", + " 'name': 'fifo_only_streaming',\n", + " 'ts': '2016-11-01 16:48:23',\n", + " 'units': '',\n", + " 'value': 'DISABLED'},\n", + " 'get_processed_data': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Get Processed Data',\n", + " 'name': 'get_processed_data',\n", + " 'ts': '2016-11-01 16:48:23',\n", + " 'units': '',\n", + " 'value': 'DISABLED'},\n", + " 'impedance1': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Impedance channel 1',\n", + " 'name': 'impedance1',\n", + " 'ts': '2016-11-01 16:48:23',\n", + " 'units': 'Ohm',\n", + " 'value': 50},\n", + " 'impedance2': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Impedance channel 2',\n", + " 'name': 'impedance2',\n", + " 'ts': '2016-11-01 16:48:23',\n", + " 'units': 'Ohm',\n", + " 'value': 50},\n", + " 'interleave_samples': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Interleave Samples',\n", + " 'name': 'interleave_samples',\n", + " 'ts': '2016-11-01 16:48:23',\n", + " 'units': '',\n", + " 'value': 'DISABLED'},\n", + " 'mode': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Acquisiton mode',\n", + " 'name': 'mode',\n", + " 'ts': '2016-11-01 16:48:23',\n", + " 'units': '',\n", + " 'value': 'NPT'},\n", + " 'records_per_buffer': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Records per Buffer',\n", + " 'name': 'records_per_buffer',\n", + " 'ts': '2016-11-01 16:48:58',\n", + " 'units': '',\n", + " 'value': 70},\n", + " 'sample_rate': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Sample Rate',\n", + " 'name': 'sample_rate',\n", + " 'ts': '2016-11-01 16:48:54',\n", + " 'units': 'S/s',\n", + " 'value': 100000000},\n", + " 'samples_per_record': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Samples per Record',\n", + " 'name': 'samples_per_record',\n", + " 'ts': '2016-11-01 16:48:58',\n", + " 'units': '',\n", + " 'value': 1024},\n", + " 'timeout_ticks': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Timeout Ticks',\n", + " 'name': 'timeout_ticks',\n", + " 'ts': '2016-11-01 16:48:23',\n", + " 'units': '10 us',\n", + " 'value': 0},\n", + " 'transfer_offset': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Transer Offset',\n", + " 'name': 'transfer_offset',\n", + " 'ts': '2016-11-01 16:48:23',\n", + " 'units': 'Samples',\n", + " 'value': 0},\n", + " 'trigger_delay': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Trigger Delay',\n", + " 'name': 'trigger_delay',\n", + " 'ts': '2016-11-01 16:48:23',\n", + " 'units': 'Sample clock cycles',\n", + " 'value': 0},\n", + " 'trigger_engine1': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Trigger Engine 1',\n", + " 'name': 'trigger_engine1',\n", + " 'ts': '2016-11-01 16:48:23',\n", + " 'units': '',\n", + " 'value': 'TRIG_ENGINE_K'},\n", + " 'trigger_engine2': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Trigger Engine 2',\n", + " 'name': 'trigger_engine2',\n", + " 'ts': '2016-11-01 16:48:23',\n", + " 'units': '',\n", + " 'value': 'TRIG_ENGINE_K'},\n", + " 'trigger_level1': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Trigger Level 1',\n", + " 'name': 'trigger_level1',\n", + " 'ts': '2016-11-01 16:48:23',\n", + " 'units': '',\n", + " 'value': 150},\n", + " 'trigger_level2': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Trigger Level 2',\n", + " 'name': 'trigger_level2',\n", + " 'ts': '2016-11-01 16:48:23',\n", + " 'units': '',\n", + " 'value': 150},\n", + " 'trigger_operation': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Trigger Operation',\n", + " 'name': 'trigger_operation',\n", + " 'ts': '2016-11-01 16:48:23',\n", + " 'units': '',\n", + " 'value': 'TRIG_ENGINE_OP_J'},\n", + " 'trigger_slope1': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Trigger Slope 1',\n", + " 'name': 'trigger_slope1',\n", + " 'ts': '2016-11-01 16:48:23',\n", + " 'units': '',\n", + " 'value': 'TRIG_SLOPE_POSITIVE'},\n", + " 'trigger_slope2': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Trigger Slope 2',\n", + " 'name': 'trigger_slope2',\n", + " 'ts': '2016-11-01 16:48:23',\n", + " 'units': '',\n", + " 'value': 'TRIG_SLOPE_POSITIVE'},\n", + " 'trigger_source1': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Trigger Source 1',\n", + " 'name': 'trigger_source1',\n", + " 'ts': '2016-11-01 16:48:54',\n", + " 'units': '',\n", + " 'value': 'EXTERNAL'},\n", + " 'trigger_source2': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", + " 'label': 'Trigger Source 2',\n", + " 'name': 'trigger_source2',\n", + " 'ts': '2016-11-01 16:48:23',\n", + " 'units': '',\n", + " 'value': 'DISABLE'}}}" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# make a snapshot of the 'ats_inst' instrument\n", + "ats_inst.snapshot()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "False\n", + "None\n", + "started at 2016-11-01 16:49:46\n" + ] + }, + { + "data": { + "application/javascript": [ + "/* Put everything inside the global mpl namespace */\n", + "window.mpl = {};\n", + "\n", + "mpl.get_websocket_type = function() {\n", + " if (typeof(WebSocket) !== 'undefined') {\n", + " return WebSocket;\n", + " } else if (typeof(MozWebSocket) !== 'undefined') {\n", + " return MozWebSocket;\n", + " } else {\n", + " alert('Your browser does not have WebSocket support.' +\n", + " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", + " 'Firefox 4 and 5 are also supported but you ' +\n", + " 'have to enable WebSockets in about:config.');\n", + " };\n", + "}\n", + "\n", + "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", + " this.id = figure_id;\n", + "\n", + " this.ws = websocket;\n", + "\n", + " this.supports_binary = (this.ws.binaryType != undefined);\n", + "\n", + " if (!this.supports_binary) {\n", + " var warnings = document.getElementById(\"mpl-warnings\");\n", + " if (warnings) {\n", + " warnings.style.display = 'block';\n", + " warnings.textContent = (\n", + " \"This browser does not support binary websocket messages. \" +\n", + " \"Performance may be slow.\");\n", + " }\n", + " }\n", + "\n", + " this.imageObj = new Image();\n", + "\n", + " this.context = undefined;\n", + " this.message = undefined;\n", + " this.canvas = undefined;\n", + " this.rubberband_canvas = undefined;\n", + " this.rubberband_context = undefined;\n", + " this.format_dropdown = undefined;\n", + "\n", + " this.image_mode = 'full';\n", + "\n", + " this.root = $('
');\n", + " this._root_extra_style(this.root)\n", + " this.root.attr('style', 'display: inline-block');\n", + "\n", + " $(parent_element).append(this.root);\n", + "\n", + " this._init_header(this);\n", + " this._init_canvas(this);\n", + " this._init_toolbar(this);\n", + "\n", + " var fig = this;\n", + "\n", + " this.waiting = false;\n", + "\n", + " this.ws.onopen = function () {\n", + " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", + " fig.send_message(\"send_image_mode\", {});\n", + " fig.send_message(\"refresh\", {});\n", + " }\n", + "\n", + " this.imageObj.onload = function() {\n", + " if (fig.image_mode == 'full') {\n", + " // Full images could contain transparency (where diff images\n", + " // almost always do), so we need to clear the canvas so that\n", + " // there is no ghosting.\n", + " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", + " }\n", + " fig.context.drawImage(fig.imageObj, 0, 0);\n", + " };\n", + "\n", + " this.imageObj.onunload = function() {\n", + " this.ws.close();\n", + " }\n", + "\n", + " this.ws.onmessage = this._make_on_message_function(this);\n", + "\n", + " this.ondownload = ondownload;\n", + "}\n", + "\n", + "mpl.figure.prototype._init_header = function() {\n", + " var titlebar = $(\n", + " '
');\n", + " var titletext = $(\n", + " '
');\n", + " titlebar.append(titletext)\n", + " this.root.append(titlebar);\n", + " this.header = titletext[0];\n", + "}\n", + "\n", + "\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._init_canvas = function() {\n", + " var fig = this;\n", + "\n", + " var canvas_div = $('
');\n", + "\n", + " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", + "\n", + " function canvas_keyboard_event(event) {\n", + " return fig.key_event(event, event['data']);\n", + " }\n", + "\n", + " canvas_div.keydown('key_press', canvas_keyboard_event);\n", + " canvas_div.keyup('key_release', canvas_keyboard_event);\n", + " this.canvas_div = canvas_div\n", + " this._canvas_extra_style(canvas_div)\n", + " this.root.append(canvas_div);\n", + "\n", + " var canvas = $('');\n", + " canvas.addClass('mpl-canvas');\n", + " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", + "\n", + " this.canvas = canvas[0];\n", + " this.context = canvas[0].getContext(\"2d\");\n", + "\n", + " var rubberband = $('');\n", + " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", + "\n", + " var pass_mouse_events = true;\n", + "\n", + " canvas_div.resizable({\n", + " start: function(event, ui) {\n", + " pass_mouse_events = false;\n", + " },\n", + " resize: function(event, ui) {\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " stop: function(event, ui) {\n", + " pass_mouse_events = true;\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " });\n", + "\n", + " function mouse_event_fn(event) {\n", + " if (pass_mouse_events)\n", + " return fig.mouse_event(event, event['data']);\n", + " }\n", + "\n", + " rubberband.mousedown('button_press', mouse_event_fn);\n", + " rubberband.mouseup('button_release', mouse_event_fn);\n", + " // Throttle sequential mouse events to 1 every 20ms.\n", + " rubberband.mousemove('motion_notify', mouse_event_fn);\n", + "\n", + " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", + " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", + "\n", + " canvas_div.on(\"wheel\", function (event) {\n", + " event = event.originalEvent;\n", + " event['data'] = 'scroll'\n", + " if (event.deltaY < 0) {\n", + " event.step = 1;\n", + " } else {\n", + " event.step = -1;\n", + " }\n", + " mouse_event_fn(event);\n", + " });\n", + "\n", + " canvas_div.append(canvas);\n", + " canvas_div.append(rubberband);\n", + "\n", + " this.rubberband = rubberband;\n", + " this.rubberband_canvas = rubberband[0];\n", + " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", + " this.rubberband_context.strokeStyle = \"#000000\";\n", + "\n", + " this._resize_canvas = function(width, height) {\n", + " // Keep the size of the canvas, canvas container, and rubber band\n", + " // canvas in synch.\n", + " canvas_div.css('width', width)\n", + " canvas_div.css('height', height)\n", + "\n", + " canvas.attr('width', width);\n", + " canvas.attr('height', height);\n", + "\n", + " rubberband.attr('width', width);\n", + " rubberband.attr('height', height);\n", + " }\n", + "\n", + " // Set the figure to an initial 600x600px, this will subsequently be updated\n", + " // upon first draw.\n", + " this._resize_canvas(600, 600);\n", + "\n", + " // Disable right mouse context menu.\n", + " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", + " return false;\n", + " });\n", + "\n", + " function set_focus () {\n", + " canvas.focus();\n", + " canvas_div.focus();\n", + " }\n", + "\n", + " window.setTimeout(set_focus, 100);\n", + "}\n", + "\n", + "mpl.figure.prototype._init_toolbar = function() {\n", + " var fig = this;\n", + "\n", + " var nav_element = $('
')\n", + " nav_element.attr('style', 'width: 100%');\n", + " this.root.append(nav_element);\n", + "\n", + " // Define a callback function for later on.\n", + " function toolbar_event(event) {\n", + " return fig.toolbar_button_onclick(event['data']);\n", + " }\n", + " function toolbar_mouse_event(event) {\n", + " return fig.toolbar_button_onmouseover(event['data']);\n", + " }\n", + "\n", + " for(var toolbar_ind in mpl.toolbar_items) {\n", + " var name = mpl.toolbar_items[toolbar_ind][0];\n", + " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", + " var image = mpl.toolbar_items[toolbar_ind][2];\n", + " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", + "\n", + " if (!name) {\n", + " // put a spacer in here.\n", + " continue;\n", + " }\n", + " var button = $('');\n", + " button.click(method_name, toolbar_event);\n", + " button.mouseover(tooltip, toolbar_mouse_event);\n", + " nav_element.append(button);\n", + " }\n", + "\n", + " // Add the status bar.\n", + " var status_bar = $('');\n", + " nav_element.append(status_bar);\n", + " this.message = status_bar[0];\n", + "\n", + " // Add the close button to the window.\n", + " var buttongrp = $('
');\n", + " var button = $('');\n", + " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", + " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", + " buttongrp.append(button);\n", + " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", + " titlebar.prepend(buttongrp);\n", + "}\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(el){\n", + " var fig = this\n", + " el.on(\"remove\", function(){\n", + "\tfig.close_ws(fig, {});\n", + " });\n", + "}\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(el){\n", + " // this is important to make the div 'focusable\n", + " el.attr('tabindex', 0)\n", + " // reach out to IPython and tell the keyboard manager to turn it's self\n", + " // off when our div gets focus\n", + "\n", + " // location in version 3\n", + " if (IPython.notebook.keyboard_manager) {\n", + " IPython.notebook.keyboard_manager.register_events(el);\n", + " }\n", + " else {\n", + " // location in version 2\n", + " IPython.keyboard_manager.register_events(el);\n", + " }\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._key_event_extra = function(event, name) {\n", + " var manager = IPython.notebook.keyboard_manager;\n", + " if (!manager)\n", + " manager = IPython.keyboard_manager;\n", + "\n", + " // Check for shift+enter\n", + " if (event.shiftKey && event.which == 13) {\n", + " this.canvas_div.blur();\n", + " event.shiftKey = false;\n", + " // Send a \"J\" for go to next cell\n", + " event.which = 74;\n", + " event.keyCode = 74;\n", + " manager.command_mode();\n", + " manager.handle_keydown(event);\n", + " }\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_save = function(fig, msg) {\n", + " fig.ondownload(fig, null);\n", + "}\n", + "\n", + "\n", + "mpl.find_output_cell = function(html_output) {\n", + " // Return the cell and output element which can be found *uniquely* in the notebook.\n", + " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", + " // IPython event is triggered only after the cells have been serialised, which for\n", + " // our purposes (turning an active figure into a static one), is too late.\n", + " var cells = IPython.notebook.get_cells();\n", + " var ncells = cells.length;\n", + " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", + " data = data.data;\n", + " }\n", + " if (data['text/html'] == html_output) {\n", + " return [cell, data, j];\n", + " }\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + "// Register the function which deals with the matplotlib target/channel.\n", + "// The kernel may be null if the page has been refreshed.\n", + "if (IPython.notebook.kernel != null) {\n", + " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", + "}\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.figure()\n", + "plt.plot(data2[0])\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Configure all settings in the Alazar card\n", + "ats_inst.config(clock_source='EXTERNAL_CLOCK_10MHz_REF',\n", + " sample_rate='10MHZ_REF_500MSPS',\n", + " clock_edge='CLOCK_EDGE_RISING',\n", + " decimation=1,\n", + " coupling=['DC','DC'],\n", + " channel_range=[.4,.4],\n", + " #impedance=[50,50],\n", + " #trigger_operation='TRIG_ENGINE_OP_J',\n", + " #trigger_engine1='TRIG_ENGINE_J',\n", + " #trigger_source1='EXTERNAL',\n", + " #trigger_slope1='TRIG_SLOPE_POSITIVE',\n", + " trigger_level1=140,\n", + " #trigger_engine2='TRIG_ENGINE_K',\n", + " #trigger_source2='DISABLE',\n", + " #trigger_slope2='TRIG_SLOPE_POSITIVE',\n", + " #trigger_level2=128,\n", + " external_trigger_coupling='DC',\n", + " external_trigger_range='ETR_2V5',\n", + " #trigger_delay=0,\n", + " #timeout_ticks=0\n", + ")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'10MHZ_REF_500MSPS'" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ats_inst.sample_rate()" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "data3 = basic_acquisition_controller.acquisition()" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "application/javascript": [ + "/* Put everything inside the global mpl namespace */\n", + "window.mpl = {};\n", + "\n", + "mpl.get_websocket_type = function() {\n", + " if (typeof(WebSocket) !== 'undefined') {\n", + " return WebSocket;\n", + " } else if (typeof(MozWebSocket) !== 'undefined') {\n", + " return MozWebSocket;\n", + " } else {\n", + " alert('Your browser does not have WebSocket support.' +\n", + " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", + " 'Firefox 4 and 5 are also supported but you ' +\n", + " 'have to enable WebSockets in about:config.');\n", + " };\n", + "}\n", + "\n", + "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", + " this.id = figure_id;\n", + "\n", + " this.ws = websocket;\n", + "\n", + " this.supports_binary = (this.ws.binaryType != undefined);\n", + "\n", + " if (!this.supports_binary) {\n", + " var warnings = document.getElementById(\"mpl-warnings\");\n", + " if (warnings) {\n", + " warnings.style.display = 'block';\n", + " warnings.textContent = (\n", + " \"This browser does not support binary websocket messages. \" +\n", + " \"Performance may be slow.\");\n", + " }\n", + " }\n", + "\n", + " this.imageObj = new Image();\n", + "\n", + " this.context = undefined;\n", + " this.message = undefined;\n", + " this.canvas = undefined;\n", + " this.rubberband_canvas = undefined;\n", + " this.rubberband_context = undefined;\n", + " this.format_dropdown = undefined;\n", + "\n", + " this.image_mode = 'full';\n", + "\n", + " this.root = $('
');\n", + " this._root_extra_style(this.root)\n", + " this.root.attr('style', 'display: inline-block');\n", + "\n", + " $(parent_element).append(this.root);\n", + "\n", + " this._init_header(this);\n", + " this._init_canvas(this);\n", + " this._init_toolbar(this);\n", + "\n", + " var fig = this;\n", + "\n", + " this.waiting = false;\n", + "\n", + " this.ws.onopen = function () {\n", + " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", + " fig.send_message(\"send_image_mode\", {});\n", + " fig.send_message(\"refresh\", {});\n", + " }\n", + "\n", + " this.imageObj.onload = function() {\n", + " if (fig.image_mode == 'full') {\n", + " // Full images could contain transparency (where diff images\n", + " // almost always do), so we need to clear the canvas so that\n", + " // there is no ghosting.\n", + " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", + " }\n", + " fig.context.drawImage(fig.imageObj, 0, 0);\n", + " };\n", + "\n", + " this.imageObj.onunload = function() {\n", + " this.ws.close();\n", + " }\n", + "\n", + " this.ws.onmessage = this._make_on_message_function(this);\n", + "\n", + " this.ondownload = ondownload;\n", + "}\n", + "\n", + "mpl.figure.prototype._init_header = function() {\n", + " var titlebar = $(\n", + " '
');\n", + " var titletext = $(\n", + " '
');\n", + " titlebar.append(titletext)\n", + " this.root.append(titlebar);\n", + " this.header = titletext[0];\n", + "}\n", + "\n", + "\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._init_canvas = function() {\n", + " var fig = this;\n", + "\n", + " var canvas_div = $('
');\n", + "\n", + " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", + "\n", + " function canvas_keyboard_event(event) {\n", + " return fig.key_event(event, event['data']);\n", + " }\n", + "\n", + " canvas_div.keydown('key_press', canvas_keyboard_event);\n", + " canvas_div.keyup('key_release', canvas_keyboard_event);\n", + " this.canvas_div = canvas_div\n", + " this._canvas_extra_style(canvas_div)\n", + " this.root.append(canvas_div);\n", + "\n", + " var canvas = $('');\n", + " canvas.addClass('mpl-canvas');\n", + " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", + "\n", + " this.canvas = canvas[0];\n", + " this.context = canvas[0].getContext(\"2d\");\n", + "\n", + " var rubberband = $('');\n", + " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", + "\n", + " var pass_mouse_events = true;\n", + "\n", + " canvas_div.resizable({\n", + " start: function(event, ui) {\n", + " pass_mouse_events = false;\n", + " },\n", + " resize: function(event, ui) {\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " stop: function(event, ui) {\n", + " pass_mouse_events = true;\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " });\n", + "\n", + " function mouse_event_fn(event) {\n", + " if (pass_mouse_events)\n", + " return fig.mouse_event(event, event['data']);\n", + " }\n", + "\n", + " rubberband.mousedown('button_press', mouse_event_fn);\n", + " rubberband.mouseup('button_release', mouse_event_fn);\n", + " // Throttle sequential mouse events to 1 every 20ms.\n", + " rubberband.mousemove('motion_notify', mouse_event_fn);\n", + "\n", + " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", + " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", + "\n", + " canvas_div.on(\"wheel\", function (event) {\n", + " event = event.originalEvent;\n", + " event['data'] = 'scroll'\n", + " if (event.deltaY < 0) {\n", + " event.step = 1;\n", + " } else {\n", + " event.step = -1;\n", + " }\n", + " mouse_event_fn(event);\n", + " });\n", + "\n", + " canvas_div.append(canvas);\n", + " canvas_div.append(rubberband);\n", + "\n", + " this.rubberband = rubberband;\n", + " this.rubberband_canvas = rubberband[0];\n", + " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", + " this.rubberband_context.strokeStyle = \"#000000\";\n", + "\n", + " this._resize_canvas = function(width, height) {\n", + " // Keep the size of the canvas, canvas container, and rubber band\n", + " // canvas in synch.\n", + " canvas_div.css('width', width)\n", + " canvas_div.css('height', height)\n", + "\n", + " canvas.attr('width', width);\n", + " canvas.attr('height', height);\n", + "\n", + " rubberband.attr('width', width);\n", + " rubberband.attr('height', height);\n", + " }\n", + "\n", + " // Set the figure to an initial 600x600px, this will subsequently be updated\n", + " // upon first draw.\n", + " this._resize_canvas(600, 600);\n", + "\n", + " // Disable right mouse context menu.\n", + " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", + " return false;\n", + " });\n", + "\n", + " function set_focus () {\n", + " canvas.focus();\n", + " canvas_div.focus();\n", + " }\n", + "\n", + " window.setTimeout(set_focus, 100);\n", + "}\n", + "\n", + "mpl.figure.prototype._init_toolbar = function() {\n", + " var fig = this;\n", + "\n", + " var nav_element = $('
')\n", + " nav_element.attr('style', 'width: 100%');\n", + " this.root.append(nav_element);\n", + "\n", + " // Define a callback function for later on.\n", + " function toolbar_event(event) {\n", + " return fig.toolbar_button_onclick(event['data']);\n", + " }\n", + " function toolbar_mouse_event(event) {\n", + " return fig.toolbar_button_onmouseover(event['data']);\n", + " }\n", + "\n", + " for(var toolbar_ind in mpl.toolbar_items) {\n", + " var name = mpl.toolbar_items[toolbar_ind][0];\n", + " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", + " var image = mpl.toolbar_items[toolbar_ind][2];\n", + " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", + "\n", + " if (!name) {\n", + " // put a spacer in here.\n", + " continue;\n", + " }\n", + " var button = $('');\n", - " button.click(method_name, toolbar_event);\n", - " button.mouseover(tooltip, toolbar_mouse_event);\n", - " nav_element.append(button);\n", - " }\n", - "\n", - " // Add the status bar.\n", - " var status_bar = $('');\n", - " nav_element.append(status_bar);\n", - " this.message = status_bar[0];\n", - "\n", - " // Add the close button to the window.\n", - " var buttongrp = $('
');\n", - " var button = $('');\n", - " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", - " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", - " buttongrp.append(button);\n", - " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", - " titlebar.prepend(buttongrp);\n", - "}\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(el){\n", - " var fig = this\n", - " el.on(\"remove\", function(){\n", - "\tfig.close_ws(fig, {});\n", - " });\n", - "}\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(el){\n", - " // this is important to make the div 'focusable\n", - " el.attr('tabindex', 0)\n", - " // reach out to IPython and tell the keyboard manager to turn it's self\n", - " // off when our div gets focus\n", - "\n", - " // location in version 3\n", - " if (IPython.notebook.keyboard_manager) {\n", - " IPython.notebook.keyboard_manager.register_events(el);\n", - " }\n", - " else {\n", - " // location in version 2\n", - " IPython.keyboard_manager.register_events(el);\n", - " }\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._key_event_extra = function(event, name) {\n", - " var manager = IPython.notebook.keyboard_manager;\n", - " if (!manager)\n", - " manager = IPython.keyboard_manager;\n", - "\n", - " // Check for shift+enter\n", - " if (event.shiftKey && event.which == 13) {\n", - " this.canvas_div.blur();\n", - " event.shiftKey = false;\n", - " // Send a \"J\" for go to next cell\n", - " event.which = 74;\n", - " event.keyCode = 74;\n", - " manager.command_mode();\n", - " manager.handle_keydown(event);\n", - " }\n", - "}\n", - "\n", - "mpl.figure.prototype.handle_save = function(fig, msg) {\n", - " fig.ondownload(fig, null);\n", - "}\n", - "\n", - "\n", - "mpl.find_output_cell = function(html_output) {\n", - " // Return the cell and output element which can be found *uniquely* in the notebook.\n", - " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", - " // IPython event is triggered only after the cells have been serialised, which for\n", - " // our purposes (turning an active figure into a static one), is too late.\n", - " var cells = IPython.notebook.get_cells();\n", - " var ncells = cells.length;\n", - " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", - " data = data.data;\n", - " }\n", - " if (data['text/html'] == html_output) {\n", - " return [cell, data, j];\n", - " }\n", - " }\n", - " }\n", - " }\n", - "}\n", - "\n", - "// Register the function which deals with the matplotlib target/channel.\n", - "// The kernel may be null if the page has been refreshed.\n", - "if (IPython.notebook.kernel != null) {\n", - " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", - "}\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "loaded_data = qc.load_data(\"data/2016-10-10/#002_testsweep_10-08-32\")\n", - "plot = qc.MatPlot(loaded_data.meter_amplitude)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Example: multiple 2D measurements with live plotting" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "loop = qc.Loop(c1[-15:15:1], 0.01).loop(c0[-15:12:.5], 0.001).each(\n", - " meter.amplitude, # first measurement, at c2=0 -> amplitude_0 bcs it's action 0\n", - " qc.Task(c2.set, 1), # action 1 -> c2.set(1)\n", - " qc.Wait(0.001),\n", - " meter.amplitude, # second measurement, at c2=1 -> amplitude_4 bcs it's action 4\n", - " qc.Task(c2.set, 0)\n", - " )\n", - "data = loop.get_data_set(name='2D_test')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Plot with matplotlib " - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "collapsed": false, - "scrolled": false - }, - "outputs": [ - { - "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "window.mpl = {};\n", - "\n", - "mpl.get_websocket_type = function() {\n", - " if (typeof(WebSocket) !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof(MozWebSocket) !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert('Your browser does not have WebSocket support.' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.');\n", - " };\n", - "}\n", - "\n", - "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = (this.ws.binaryType != undefined);\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById(\"mpl-warnings\");\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent = (\n", - " \"This browser does not support binary websocket messages. \" +\n", - " \"Performance may be slow.\");\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = $('
');\n", - " this._root_extra_style(this.root)\n", - " this.root.attr('style', 'display: inline-block');\n", - "\n", - " $(parent_element).append(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", - " fig.send_message(\"send_image_mode\", {});\n", - " fig.send_message(\"refresh\", {});\n", - " }\n", - "\n", - " this.imageObj.onload = function() {\n", - " if (fig.image_mode == 'full') {\n", - " // Full images could contain transparency (where diff images\n", - " // almost always do), so we need to clear the canvas so that\n", - " // there is no ghosting.\n", - " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", - " }\n", - " fig.context.drawImage(fig.imageObj, 0, 0);\n", - " };\n", - "\n", - " this.imageObj.onunload = function() {\n", - " this.ws.close();\n", - " }\n", - "\n", - " this.ws.onmessage = this._make_on_message_function(this);\n", - "\n", - " this.ondownload = ondownload;\n", - "}\n", - "\n", - "mpl.figure.prototype._init_header = function() {\n", - " var titlebar = $(\n", - " '
');\n", - " var titletext = $(\n", - " '
');\n", - " titlebar.append(titletext)\n", - " this.root.append(titlebar);\n", - " this.header = titletext[0];\n", - "}\n", - "\n", - "\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._init_canvas = function() {\n", - " var fig = this;\n", - "\n", - " var canvas_div = $('
');\n", - "\n", - " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", - "\n", - " function canvas_keyboard_event(event) {\n", - " return fig.key_event(event, event['data']);\n", - " }\n", - "\n", - " canvas_div.keydown('key_press', canvas_keyboard_event);\n", - " canvas_div.keyup('key_release', canvas_keyboard_event);\n", - " this.canvas_div = canvas_div\n", - " this._canvas_extra_style(canvas_div)\n", - " this.root.append(canvas_div);\n", - "\n", - " var canvas = $('');\n", - " canvas.addClass('mpl-canvas');\n", - " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", - "\n", - " this.canvas = canvas[0];\n", - " this.context = canvas[0].getContext(\"2d\");\n", - "\n", - " var rubberband = $('');\n", - " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", - "\n", - " var pass_mouse_events = true;\n", - "\n", - " canvas_div.resizable({\n", - " start: function(event, ui) {\n", - " pass_mouse_events = false;\n", - " },\n", - " resize: function(event, ui) {\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " stop: function(event, ui) {\n", - " pass_mouse_events = true;\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " });\n", - "\n", - " function mouse_event_fn(event) {\n", - " if (pass_mouse_events)\n", - " return fig.mouse_event(event, event['data']);\n", - " }\n", - "\n", - " rubberband.mousedown('button_press', mouse_event_fn);\n", - " rubberband.mouseup('button_release', mouse_event_fn);\n", - " // Throttle sequential mouse events to 1 every 20ms.\n", - " rubberband.mousemove('motion_notify', mouse_event_fn);\n", - "\n", - " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", - " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", - "\n", - " canvas_div.on(\"wheel\", function (event) {\n", - " event = event.originalEvent;\n", - " event['data'] = 'scroll'\n", - " if (event.deltaY < 0) {\n", - " event.step = 1;\n", - " } else {\n", - " event.step = -1;\n", - " }\n", - " mouse_event_fn(event);\n", - " });\n", - "\n", - " canvas_div.append(canvas);\n", - " canvas_div.append(rubberband);\n", - "\n", - " this.rubberband = rubberband;\n", - " this.rubberband_canvas = rubberband[0];\n", - " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", - " this.rubberband_context.strokeStyle = \"#000000\";\n", - "\n", - " this._resize_canvas = function(width, height) {\n", - " // Keep the size of the canvas, canvas container, and rubber band\n", - " // canvas in synch.\n", - " canvas_div.css('width', width)\n", - " canvas_div.css('height', height)\n", - "\n", - " canvas.attr('width', width);\n", - " canvas.attr('height', height);\n", - "\n", - " rubberband.attr('width', width);\n", - " rubberband.attr('height', height);\n", - " }\n", - "\n", - " // Set the figure to an initial 600x600px, this will subsequently be updated\n", - " // upon first draw.\n", - " this._resize_canvas(600, 600);\n", - "\n", - " // Disable right mouse context menu.\n", - " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", - " return false;\n", - " });\n", - "\n", - " function set_focus () {\n", - " canvas.focus();\n", - " canvas_div.focus();\n", - " }\n", - "\n", - " window.setTimeout(set_focus, 100);\n", - "}\n", - "\n", - "mpl.figure.prototype._init_toolbar = function() {\n", - " var fig = this;\n", - "\n", - " var nav_element = $('
')\n", - " nav_element.attr('style', 'width: 100%');\n", - " this.root.append(nav_element);\n", - "\n", - " // Define a callback function for later on.\n", - " function toolbar_event(event) {\n", - " return fig.toolbar_button_onclick(event['data']);\n", - " }\n", - " function toolbar_mouse_event(event) {\n", - " return fig.toolbar_button_onmouseover(event['data']);\n", - " }\n", - "\n", - " for(var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " // put a spacer in here.\n", - " continue;\n", - " }\n", - " var button = $('');\n", + " button.click(method_name, toolbar_event);\n", + " button.mouseover(tooltip, toolbar_mouse_event);\n", + " nav_element.append(button);\n", + " }\n", + "\n", + " // Add the status bar.\n", + " var status_bar = $('');\n", + " nav_element.append(status_bar);\n", + " this.message = status_bar[0];\n", + "\n", + " // Add the close button to the window.\n", + " var buttongrp = $('
');\n", + " var button = $('');\n", + " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", + " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", + " buttongrp.append(button);\n", + " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", + " titlebar.prepend(buttongrp);\n", + "}\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(el){\n", + " var fig = this\n", + " el.on(\"remove\", function(){\n", + "\tfig.close_ws(fig, {});\n", + " });\n", + "}\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(el){\n", + " // this is important to make the div 'focusable\n", + " el.attr('tabindex', 0)\n", + " // reach out to IPython and tell the keyboard manager to turn it's self\n", + " // off when our div gets focus\n", + "\n", + " // location in version 3\n", + " if (IPython.notebook.keyboard_manager) {\n", + " IPython.notebook.keyboard_manager.register_events(el);\n", + " }\n", + " else {\n", + " // location in version 2\n", + " IPython.keyboard_manager.register_events(el);\n", + " }\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._key_event_extra = function(event, name) {\n", + " var manager = IPython.notebook.keyboard_manager;\n", + " if (!manager)\n", + " manager = IPython.keyboard_manager;\n", + "\n", + " // Check for shift+enter\n", + " if (event.shiftKey && event.which == 13) {\n", + " this.canvas_div.blur();\n", + " event.shiftKey = false;\n", + " // Send a \"J\" for go to next cell\n", + " event.which = 74;\n", + " event.keyCode = 74;\n", + " manager.command_mode();\n", + " manager.handle_keydown(event);\n", + " }\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_save = function(fig, msg) {\n", + " fig.ondownload(fig, null);\n", + "}\n", + "\n", + "\n", + "mpl.find_output_cell = function(html_output) {\n", + " // Return the cell and output element which can be found *uniquely* in the notebook.\n", + " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", + " // IPython event is triggered only after the cells have been serialised, which for\n", + " // our purposes (turning an active figure into a static one), is too late.\n", + " var cells = IPython.notebook.get_cells();\n", + " var ncells = cells.length;\n", + " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", + " data = data.data;\n", + " }\n", + " if (data['text/html'] == html_output) {\n", + " return [cell, data, j];\n", + " }\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + "// Register the function which deals with the matplotlib target/channel.\n", + "// The kernel may be null if the page has been refreshed.\n", + "if (IPython.notebook.kernel != null) {\n", + " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", + "}\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "plt.figure()\n", + "plt.plot(data3[1])\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DataSet:\n", + " mode = DataMode.LOCAL\n", + " location = '2016-11-08/10-10-07_AlazarTest'\n", + " | | | \n", + " Setpoint | dummy_set | dummy | (5,)\n", + " Measured | sample_num | sample_num | (5, 1024)\n", + " Measured | samples_controller_magnitude | magnitude | (5, 1024)\n", + " Measured | samples_controller_phase | phase | (5, 1024)\n", + "started at 2016-11-08 10:10:09\n" + ] + } + ], + "source": [ + "dummy = parameter.ManualParameter(name=\"dummy\")\n", + "data4 = qc.Loop(dummy[0:5:1]).each(\n", + " samp_cont.acquisition).run(name='AlazarTest')" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'data4' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)", + "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mqc\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mQtPlot\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mdata4\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msamples_controller_magnitude\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[1;31mNameError\u001b[0m: name 'data4' is not defined" + ] + } + ], + "source": [ + "qc.QtPlot(data4.samples_controller_magnitude)" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "a:\\qcodes\\qcodes\\instrument\\metaclass.py:37: UserWarning: Multiprocessing is in beta, use at own risk\n", + " UserWarning)\n" + ] + } + ], + "source": [ + "import qcodes.instrument_drivers.AlazarTech.Single_controller as single_controller\n", + "\n", + "sing_contr = single_controller.HD_Controller(name='single_controller', \n", + " alazar_name='Alazar1', \n", + " demod_freq = 5e6,\n", + " server_name=\"alazar_server\")" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# This command is specific to this acquisition controller. The kwargs provided here are being forwarded to ats_inst.acquire\n", + "# This way, it becomes easy to change acquisition specific settings from the ipython notebook\n", + "sing_contr.update_acquisitionkwargs(#mode='NPT',\n", + " samples_per_record=2560,\n", + " records_per_buffer=1,\n", + " buffers_per_acquisition=1,\n", + " #channel_selection='AB',\n", + " #transfer_offset=0,\n", + " #external_startcapture='ENABLED',\n", + " #enable_record_headers='DISABLED',\n", + " #alloc_buffers='DISABLED',\n", + " #fifo_only_streaming='DISABLED',\n", + " #interleave_samples='DISABLED',\n", + " #get_processed_data='DISABLED',\n", + " allocated_buffers=1,\n", + " #buffer_timeout=1000\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "data5 = sing_contr.acquisition()" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(3326.8644117553804, 54.301233235582359)" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data5" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DataSet:\n", + " mode = DataMode.LOCAL\n", + " location = '2016-11-08/10-27-15_AlazarTest'\n", + " | | | \n", + " Setpoint | dummy_set | dummy | (5,)\n", + " Measured | single_controller_magnitude | magnitude | (5,)\n", + " Measured | single_controller_phase | phase | (5,)\n", + "started at 2016-11-08 10:27:17\n" + ] + } + ], + "source": [ + "dummy = parameter.ManualParameter(name=\"dummy\")\n", + "data6 = qc.Loop(dummy[0:5:1]).each(\n", + " sing_contr.acquisition).run(name='AlazarTest')" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "qc.QtPlot(data6.single_controller_phase)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "a:\\qcodes\\qcodes\\instrument\\metaclass.py:37: UserWarning: Multiprocessing is in beta, use at own risk\n", + " UserWarning)\n" + ] + } + ], + "source": [ + "import qcodes.instrument_drivers.AlazarTech.Rec_controller as record_controller\n", + "\n", + "rec_contr = record_controller.HD_Records_Controller(name='rec_controller', \n", + " alazar_name='Alazar1', \n", + " demod_freq = 5e6,\n", + " server_name=\"alazar_server\")" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# This command is specific to this acquisition controller. The kwargs provided here are being forwarded to ats_inst.acquire\n", + "# This way, it becomes easy to change acquisition specific settings from the ipython notebook\n", + "rec_contr.update_acquisitionkwargs(#mode='NPT',\n", + " samples_per_record=1024,\n", + " records_per_buffer=20,\n", + " buffers_per_acquisition=1,\n", + " #channel_selection='AB',\n", + " #transfer_offset=0,\n", + " #external_startcapture='ENABLED',\n", + " #enable_record_headers='DISABLED',\n", + " #alloc_buffers='DISABLED',\n", + " #fifo_only_streaming='DISABLED',\n", + " #interleave_samples='DISABLED',\n", + " #get_processed_data='DISABLED',\n", + " allocated_buffers=1,\n", + " #buffer_timeout=1000\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "data7 = rec_contr.acquisition()" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(array([ 3289.96320022, 3286.41234804, 3307.51961298, 3258.31653189,\n", + " 3293.95959593, 3291.98748708, 3260.12595817, 3303.707061 ,\n", + " 3262.98369435, 3297.69539837, 3301.61275188, 3272.2064834 ,\n", + " 3309.53487782, 3264.07853243, 3297.85260115, 3285.39823933,\n", + " 3272.54744985, 3304.02929544, 3273.01252546, 3289.82606187]),\n", + " array([ 59.2785189 , -35.71021399, 23.98720238, 101.76356054,\n", + " 7.88187056, -123.96879121, -64.55449409, 13.57780392,\n", + " 104.73958041, 7.80840739, -123.26288987, -57.18388729,\n", + " 23.95505572, 104.72063281, 8.14861144, -109.83457381,\n", + " -42.96898046, 24.012719 , 83.99967619, 23.67250356]))" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data7" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "application/javascript": [ + "/* Put everything inside the global mpl namespace */\n", + "window.mpl = {};\n", + "\n", + "mpl.get_websocket_type = function() {\n", + " if (typeof(WebSocket) !== 'undefined') {\n", + " return WebSocket;\n", + " } else if (typeof(MozWebSocket) !== 'undefined') {\n", + " return MozWebSocket;\n", + " } else {\n", + " alert('Your browser does not have WebSocket support.' +\n", + " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", + " 'Firefox 4 and 5 are also supported but you ' +\n", + " 'have to enable WebSockets in about:config.');\n", + " };\n", + "}\n", + "\n", + "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", + " this.id = figure_id;\n", + "\n", + " this.ws = websocket;\n", + "\n", + " this.supports_binary = (this.ws.binaryType != undefined);\n", + "\n", + " if (!this.supports_binary) {\n", + " var warnings = document.getElementById(\"mpl-warnings\");\n", + " if (warnings) {\n", + " warnings.style.display = 'block';\n", + " warnings.textContent = (\n", + " \"This browser does not support binary websocket messages. \" +\n", + " \"Performance may be slow.\");\n", + " }\n", + " }\n", + "\n", + " this.imageObj = new Image();\n", + "\n", + " this.context = undefined;\n", + " this.message = undefined;\n", + " this.canvas = undefined;\n", + " this.rubberband_canvas = undefined;\n", + " this.rubberband_context = undefined;\n", + " this.format_dropdown = undefined;\n", + "\n", + " this.image_mode = 'full';\n", + "\n", + " this.root = $('
');\n", + " this._root_extra_style(this.root)\n", + " this.root.attr('style', 'display: inline-block');\n", + "\n", + " $(parent_element).append(this.root);\n", + "\n", + " this._init_header(this);\n", + " this._init_canvas(this);\n", + " this._init_toolbar(this);\n", + "\n", + " var fig = this;\n", + "\n", + " this.waiting = false;\n", + "\n", + " this.ws.onopen = function () {\n", + " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", + " fig.send_message(\"send_image_mode\", {});\n", + " fig.send_message(\"refresh\", {});\n", + " }\n", + "\n", + " this.imageObj.onload = function() {\n", + " if (fig.image_mode == 'full') {\n", + " // Full images could contain transparency (where diff images\n", + " // almost always do), so we need to clear the canvas so that\n", + " // there is no ghosting.\n", + " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", + " }\n", + " fig.context.drawImage(fig.imageObj, 0, 0);\n", + " };\n", + "\n", + " this.imageObj.onunload = function() {\n", + " this.ws.close();\n", + " }\n", + "\n", + " this.ws.onmessage = this._make_on_message_function(this);\n", + "\n", + " this.ondownload = ondownload;\n", + "}\n", + "\n", + "mpl.figure.prototype._init_header = function() {\n", + " var titlebar = $(\n", + " '
');\n", + " var titletext = $(\n", + " '
');\n", + " titlebar.append(titletext)\n", + " this.root.append(titlebar);\n", + " this.header = titletext[0];\n", + "}\n", + "\n", + "\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._init_canvas = function() {\n", + " var fig = this;\n", + "\n", + " var canvas_div = $('
');\n", + "\n", + " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", + "\n", + " function canvas_keyboard_event(event) {\n", + " return fig.key_event(event, event['data']);\n", + " }\n", + "\n", + " canvas_div.keydown('key_press', canvas_keyboard_event);\n", + " canvas_div.keyup('key_release', canvas_keyboard_event);\n", + " this.canvas_div = canvas_div\n", + " this._canvas_extra_style(canvas_div)\n", + " this.root.append(canvas_div);\n", + "\n", + " var canvas = $('');\n", + " canvas.addClass('mpl-canvas');\n", + " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", + "\n", + " this.canvas = canvas[0];\n", + " this.context = canvas[0].getContext(\"2d\");\n", + "\n", + " var rubberband = $('');\n", + " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", + "\n", + " var pass_mouse_events = true;\n", + "\n", + " canvas_div.resizable({\n", + " start: function(event, ui) {\n", + " pass_mouse_events = false;\n", + " },\n", + " resize: function(event, ui) {\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " stop: function(event, ui) {\n", + " pass_mouse_events = true;\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " });\n", + "\n", + " function mouse_event_fn(event) {\n", + " if (pass_mouse_events)\n", + " return fig.mouse_event(event, event['data']);\n", + " }\n", + "\n", + " rubberband.mousedown('button_press', mouse_event_fn);\n", + " rubberband.mouseup('button_release', mouse_event_fn);\n", + " // Throttle sequential mouse events to 1 every 20ms.\n", + " rubberband.mousemove('motion_notify', mouse_event_fn);\n", + "\n", + " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", + " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", + "\n", + " canvas_div.on(\"wheel\", function (event) {\n", + " event = event.originalEvent;\n", + " event['data'] = 'scroll'\n", + " if (event.deltaY < 0) {\n", + " event.step = 1;\n", + " } else {\n", + " event.step = -1;\n", + " }\n", + " mouse_event_fn(event);\n", + " });\n", + "\n", + " canvas_div.append(canvas);\n", + " canvas_div.append(rubberband);\n", + "\n", + " this.rubberband = rubberband;\n", + " this.rubberband_canvas = rubberband[0];\n", + " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", + " this.rubberband_context.strokeStyle = \"#000000\";\n", + "\n", + " this._resize_canvas = function(width, height) {\n", + " // Keep the size of the canvas, canvas container, and rubber band\n", + " // canvas in synch.\n", + " canvas_div.css('width', width)\n", + " canvas_div.css('height', height)\n", + "\n", + " canvas.attr('width', width);\n", + " canvas.attr('height', height);\n", + "\n", + " rubberband.attr('width', width);\n", + " rubberband.attr('height', height);\n", + " }\n", + "\n", + " // Set the figure to an initial 600x600px, this will subsequently be updated\n", + " // upon first draw.\n", + " this._resize_canvas(600, 600);\n", + "\n", + " // Disable right mouse context menu.\n", + " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", + " return false;\n", + " });\n", + "\n", + " function set_focus () {\n", + " canvas.focus();\n", + " canvas_div.focus();\n", + " }\n", + "\n", + " window.setTimeout(set_focus, 100);\n", + "}\n", + "\n", + "mpl.figure.prototype._init_toolbar = function() {\n", + " var fig = this;\n", + "\n", + " var nav_element = $('
')\n", + " nav_element.attr('style', 'width: 100%');\n", + " this.root.append(nav_element);\n", + "\n", + " // Define a callback function for later on.\n", + " function toolbar_event(event) {\n", + " return fig.toolbar_button_onclick(event['data']);\n", + " }\n", + " function toolbar_mouse_event(event) {\n", + " return fig.toolbar_button_onmouseover(event['data']);\n", + " }\n", + "\n", + " for(var toolbar_ind in mpl.toolbar_items) {\n", + " var name = mpl.toolbar_items[toolbar_ind][0];\n", + " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", + " var image = mpl.toolbar_items[toolbar_ind][2];\n", + " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", + "\n", + " if (!name) {\n", + " // put a spacer in here.\n", + " continue;\n", + " }\n", + " var button = $('');\n", + " button.click(method_name, toolbar_event);\n", + " button.mouseover(tooltip, toolbar_mouse_event);\n", + " nav_element.append(button);\n", + " }\n", + "\n", + " // Add the status bar.\n", + " var status_bar = $('');\n", + " nav_element.append(status_bar);\n", + " this.message = status_bar[0];\n", + "\n", + " // Add the close button to the window.\n", + " var buttongrp = $('
');\n", + " var button = $('');\n", + " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", + " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", + " buttongrp.append(button);\n", + " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", + " titlebar.prepend(buttongrp);\n", + "}\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(el){\n", + " var fig = this\n", + " el.on(\"remove\", function(){\n", + "\tfig.close_ws(fig, {});\n", + " });\n", + "}\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(el){\n", + " // this is important to make the div 'focusable\n", + " el.attr('tabindex', 0)\n", + " // reach out to IPython and tell the keyboard manager to turn it's self\n", + " // off when our div gets focus\n", + "\n", + " // location in version 3\n", + " if (IPython.notebook.keyboard_manager) {\n", + " IPython.notebook.keyboard_manager.register_events(el);\n", + " }\n", + " else {\n", + " // location in version 2\n", + " IPython.keyboard_manager.register_events(el);\n", + " }\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._key_event_extra = function(event, name) {\n", + " var manager = IPython.notebook.keyboard_manager;\n", + " if (!manager)\n", + " manager = IPython.keyboard_manager;\n", + "\n", + " // Check for shift+enter\n", + " if (event.shiftKey && event.which == 13) {\n", + " this.canvas_div.blur();\n", + " event.shiftKey = false;\n", + " // Send a \"J\" for go to next cell\n", + " event.which = 74;\n", + " event.keyCode = 74;\n", + " manager.command_mode();\n", + " manager.handle_keydown(event);\n", + " }\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_save = function(fig, msg) {\n", + " fig.ondownload(fig, null);\n", + "}\n", + "\n", + "\n", + "mpl.find_output_cell = function(html_output) {\n", + " // Return the cell and output element which can be found *uniquely* in the notebook.\n", + " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", + " // IPython event is triggered only after the cells have been serialised, which for\n", + " // our purposes (turning an active figure into a static one), is too late.\n", + " var cells = IPython.notebook.get_cells();\n", + " var ncells = cells.length;\n", + " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", + " data = data.data;\n", + " }\n", + " if (data['text/html'] == html_output) {\n", + " return [cell, data, j];\n", + " }\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + "// Register the function which deals with the matplotlib target/channel.\n", + "// The kernel may be null if the page has been refreshed.\n", + "if (IPython.notebook.kernel != null) {\n", + " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", + "}\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "plt.figure()\n", + "plt.plot(data9[1])\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "ename": "ValueError", + "evalue": "nth setpoint array should have shape matching the first n dimensions of shape.", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mValueError\u001b[0m Traceback (most recent call last)", + "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[0mdummy\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mparameter\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mManualParameter\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mname\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m\"dummy\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2\u001b[0m data10 = qc.Loop(dummy[0:5:1]).each(\n\u001b[1;32m----> 3\u001b[1;33m recsamp_contr.acquisition).run(name='AlazarTest')\n\u001b[0m", + "\u001b[1;32ma:\\qcodes\\qcodes\\loops.py\u001b[0m in \u001b[0;36mrun\u001b[1;34m(self, background, use_threads, quiet, data_manager, station, progress_interval, *args, **kwargs)\u001b[0m\n\u001b[0;32m 759\u001b[0m \u001b[0mprev_loop\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 760\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 761\u001b[1;33m \u001b[0mdata_set\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mget_data_set\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mdata_manager\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m*\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 762\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 763\u001b[0m self.set_common_attrs(data_set=data_set, use_threads=use_threads,\n", + "\u001b[1;32ma:\\qcodes\\qcodes\\loops.py\u001b[0m in \u001b[0;36mget_data_set\u001b[1;34m(self, data_manager, *args, **kwargs)\u001b[0m\n\u001b[0;32m 683\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 684\u001b[0m data_set = new_data(arrays=self.containers(), mode=data_mode,\n\u001b[1;32m--> 685\u001b[1;33m data_manager=data_manager, *args, **kwargs)\n\u001b[0m\u001b[0;32m 686\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 687\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdata_set\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mdata_set\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[1;32ma:\\qcodes\\qcodes\\loops.py\u001b[0m in \u001b[0;36mcontainers\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 486\u001b[0m \u001b[1;31m# note that this supports lists (separate output arrays)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 487\u001b[0m \u001b[1;31m# and arrays (nested in one/each output array) of return values\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 488\u001b[1;33m \u001b[0maction_arrays\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_parameter_arrays\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0maction\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 489\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 490\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[1;32ma:\\qcodes\\qcodes\\loops.py\u001b[0m in \u001b[0;36m_parameter_arrays\u001b[1;34m(self, action)\u001b[0m\n\u001b[0;32m 560\u001b[0m \u001b[0msp_def\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m(\u001b[0m\u001b[0mshape\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m:\u001b[0m \u001b[1;36m1\u001b[0m \u001b[1;33m+\u001b[0m \u001b[0mj\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mj\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0msetpoints\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mvij\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mnij\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mlij\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 561\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0msp_def\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mall_setpoints\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 562\u001b[1;33m \u001b[0mall_setpoints\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0msp_def\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_make_setpoint_array\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m*\u001b[0m\u001b[0msp_def\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 563\u001b[0m \u001b[0mout\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mall_setpoints\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0msp_def\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 564\u001b[0m \u001b[0msetpoints\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0msetpoints\u001b[0m \u001b[1;33m+\u001b[0m \u001b[1;33m(\u001b[0m\u001b[0mall_setpoints\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0msp_def\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[1;32ma:\\qcodes\\qcodes\\loops.py\u001b[0m in \u001b[0;36m_make_setpoint_array\u001b[1;34m(self, shape, i, prev_setpoints, vals, name, label)\u001b[0m\n\u001b[0;32m 601\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 602\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mvals\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mshape\u001b[0m \u001b[1;33m!=\u001b[0m \u001b[0mshape\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 603\u001b[1;33m raise ValueError('nth setpoint array should have shape matching '\n\u001b[0m\u001b[0;32m 604\u001b[0m 'the first n dimensions of shape.')\n\u001b[0;32m 605\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[1;31mValueError\u001b[0m: nth setpoint array should have shape matching the first n dimensions of shape." + ] + } + ], + "source": [ + "dummy = parameter.ManualParameter(name=\"dummy\")\n", + "data10 = qc.Loop(dummy[0:5:1]).each(\n", + " recsamp_contr.acquisition).run(name='AlazarTest')" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "((array([0, 1, 2]), array([0, 1])), (array([0, 1, 2]), array([0, 1])))" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "((np.arange(3), np.arange(2)), (np.arange(3), np.arange(2)))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] } ], "metadata": { From 341acfdf90dccdc1a65a311759075249907bbb7e Mon Sep 17 00:00:00 2001 From: nataliejpg Date: Tue, 8 Nov 2016 12:08:24 +0100 Subject: [PATCH 033/180] to dos added --- qcodes/instrument_drivers/AlazarTech/RecSamp_controller.py | 3 +++ qcodes/instrument_drivers/AlazarTech/Rec_controller.py | 2 ++ qcodes/instrument_drivers/AlazarTech/Samp_controller.py | 2 ++ 3 files changed, 7 insertions(+) diff --git a/qcodes/instrument_drivers/AlazarTech/RecSamp_controller.py b/qcodes/instrument_drivers/AlazarTech/RecSamp_controller.py index 53196d356eb1..5b583ed806a7 100644 --- a/qcodes/instrument_drivers/AlazarTech/RecSamp_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/RecSamp_controller.py @@ -9,6 +9,9 @@ class RecSampParam(Parameter): Hardware controlled parameter class for Alazar acquisition. To be used with HD_Samples_Controller (tested with ATS9360 board) for return of an array of sample data from the Alazar, averaged over records and buffers. + + TODO(nataliejpg) fix setpoints/shapes horriblenesss + TODO(nataliejpg) make it actually work... """ def __init__(self, name, instrument): super().__init__(name) diff --git a/qcodes/instrument_drivers/AlazarTech/Rec_controller.py b/qcodes/instrument_drivers/AlazarTech/Rec_controller.py index 792fb4f616b4..ff1cabdd58c1 100644 --- a/qcodes/instrument_drivers/AlazarTech/Rec_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/Rec_controller.py @@ -9,6 +9,8 @@ class RecordsParam(Parameter): Hardware controlled parameter class for Alazar acquisition. To be used with HD_Records_Controller (tested with ATS9360 board) for return of an array of record data from the Alazar, averaged over samples and buffers. + + TODO(nataliejpg) fix setpoints/shapes horriblenesss """ def __init__(self, name, instrument): super().__init__(name) diff --git a/qcodes/instrument_drivers/AlazarTech/Samp_controller.py b/qcodes/instrument_drivers/AlazarTech/Samp_controller.py index a1cf73c9770c..b95d59b6efab 100644 --- a/qcodes/instrument_drivers/AlazarTech/Samp_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/Samp_controller.py @@ -9,6 +9,8 @@ class SamplesParam(Parameter): Hardware controlled parameter class for Alazar acquisition. To be used with HD_Samples_Controller (tested with ATS9360 board) for return of an array of sample data from the Alazar, averaged over records and buffers. + + TODO(nataliejpg) fix setpoints/shapes horriblenesss """ def __init__(self, name, instrument): super().__init__(name) From 8da2b422d6cff8aeb3ceee99b5c7b7929228c45e Mon Sep 17 00:00:00 2001 From: nataliejpg Date: Tue, 8 Nov 2016 14:20:26 +0100 Subject: [PATCH 034/180] start work on signal to volts --- .../AlazarTech/basic_controller.py | 41 ++++++++++++++----- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/basic_controller.py b/qcodes/instrument_drivers/AlazarTech/basic_controller.py index 2727d897bdcf..9b2627c30f5c 100644 --- a/qcodes/instrument_drivers/AlazarTech/basic_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/basic_controller.py @@ -54,6 +54,7 @@ class Basic_Acquisition_Controller(AcquisitionController): **kwargs: kwargs are forwarded to the Instrument base class TODO(nataliejpg) num of channels + TODO(nataliejpg) make dtype general or get from alazar """ def __init__(self, name, alazar_name, **kwargs): @@ -90,7 +91,8 @@ def pre_start_capture(self): self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() self.buffer = np.zeros(self.samples_per_record * self.records_per_buffer * - self.number_of_channels) + self.number_of_channels, + dtype=np.uint16) def pre_acquire(self): """ @@ -114,27 +116,44 @@ def post_acquire(self): See AcquisitionController :return: """ - records_per_acquisition = (1. * self.buffers_per_acquisition * - self.records_per_buffer) + # for ATS9360 samples are arranged in the buffer as follows: # S00A, S00B, S01A, S01B...S10A, S10B, S11A, S11B... # where SXYZ is record X, sample Y, channel Z. - # breaks buffer up into records, averages over them and returns samples + # break buffer up into records, averages over them and returns samples records_per_acquisition = (self.buffers_per_acquisition * - self.records_per_buffer) - recordA = np.zeros(self.samples_per_record) + self.records_per_buffer) + recordA = np.zeros(self.samples_per_record, dtype=np.uint16) for i in range(self.records_per_buffer): i0 = (i * self.samples_per_record * self.number_of_channels) i1 = (i0 + self.samples_per_record * self.number_of_channels) - recordA += (self.buffer[i0:i1:self.number_of_channels] / + recordA += np.uint16(self.buffer[i0:i1:self.number_of_channels] / records_per_acquisition) - recordB = np.zeros(self.samples_per_record) + recordB = np.zeros(self.samples_per_record, dtype=np.uint16) for i in range(self.records_per_buffer): i0 = (i * self.samples_per_record * self.number_of_channels + 1) i1 = (i0 + self.samples_per_record * self.number_of_channels) - recordB += (self.buffer[i0:i1:self.number_of_channels] / + recordB += np.uint16(self.buffer[i0:i1:self.number_of_channels] / records_per_acquisition) - - return recordA, recordB + + volt_rec_A = self.sample_to_volt(recordA) + volt_rec_B = self.sample_to_volt(recordB) + + return volt_rec_A, volt_rec_B + + def sample_to_volt(self, raw_samples): + # right_shift 16-bit sample by 4 to get 12 bit sample + shifted_samples = np.right_shift(raw_samples,4) + + # Alazar calibration + bps = 12 + input_range_volts = 0.8 + code_zero = (1 << (bps - 1)) - 0.5 + code_range = (1 << (bps - 1)) - 0.5 + + # Convert to volts + volt_samples = input_range_volts * (shifted_samples - code_zero) / code_range + + return volt_samples \ No newline at end of file From fcf7fcbb731c652b56eff5953d59c6ca40491f71 Mon Sep 17 00:00:00 2001 From: nataliejpg Date: Tue, 8 Nov 2016 15:22:27 +0100 Subject: [PATCH 035/180] filter testing in samples controller --- qcodes/instrument_drivers/AlazarTech/Samp_controller.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/qcodes/instrument_drivers/AlazarTech/Samp_controller.py b/qcodes/instrument_drivers/AlazarTech/Samp_controller.py index b95d59b6efab..3fbd59477a6b 100644 --- a/qcodes/instrument_drivers/AlazarTech/Samp_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/Samp_controller.py @@ -114,6 +114,9 @@ def pre_start_capture(self): self.cos_list = np.cos(angle_list) self.sin_list = np.sin(angle_list) + + numtaps = round(self.samples_per_record/20) * 2 + 1 + delay = numtaps - 1 def pre_acquire(self): """ @@ -226,3 +229,8 @@ def filter_ls(self, rec, numtaps, cutoff): nyq=nyq_rate) filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec) return filtered_rec + + def filter(self, rec, numtaps, delay): + fir_coef = signal.firwin(numtaps, 0.01) + filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec) + return fir_coef, filtered_rec[delay:] From 61c64198037d14dfc1fc5eba4bb12bfde0cab653 Mon Sep 17 00:00:00 2001 From: Natalie Pearson Date: Tue, 8 Nov 2016 15:37:00 +0100 Subject: [PATCH 036/180] pep8 formatting --- .../AlazarTech/RecBuf_controller.py | 1 + .../AlazarTech/RecSamp_controller.py | 21 ++++++++-------- .../AlazarTech/Rec_controller.py | 5 ++-- .../AlazarTech/Samp_controller.py | 2 +- .../AlazarTech/Single_controller.py | 2 +- .../AlazarTech/basic_controller.py | 24 ++++++++++--------- 6 files changed, 29 insertions(+), 26 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/RecBuf_controller.py b/qcodes/instrument_drivers/AlazarTech/RecBuf_controller.py index c4d5fdd3e390..65ddb9dea4d7 100644 --- a/qcodes/instrument_drivers/AlazarTech/RecBuf_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/RecBuf_controller.py @@ -10,6 +10,7 @@ class RecBufParam(Parameter): HD_Samples_Controller (tested with ATS9360 board) for return of an array of sample data from the Alazar, averaged over records and buffers. """ + def __init__(self, name, instrument): super().__init__(name) self._instrument = instrument diff --git a/qcodes/instrument_drivers/AlazarTech/RecSamp_controller.py b/qcodes/instrument_drivers/AlazarTech/RecSamp_controller.py index 5b583ed806a7..7e86e9ffc211 100644 --- a/qcodes/instrument_drivers/AlazarTech/RecSamp_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/RecSamp_controller.py @@ -9,17 +9,19 @@ class RecSampParam(Parameter): Hardware controlled parameter class for Alazar acquisition. To be used with HD_Samples_Controller (tested with ATS9360 board) for return of an array of sample data from the Alazar, averaged over records and buffers. - + TODO(nataliejpg) fix setpoints/shapes horriblenesss TODO(nataliejpg) make it actually work... """ + def __init__(self, name, instrument): super().__init__(name) self._instrument = instrument self.acquisitionkwargs = {} self.names = ('magnitude', 'phase') self.units = ('', '') - self.setpoint_names = (('rec_num', 'samp_num'), ('rec_num', 'samp_num')) + self.setpoint_names = (('rec_num', 'samp_num'), + ('rec_num', 'samp_num')) self.setpoints = ((1, 1), (1, 1)) self.shapes = ((1, 1), (1, 1)) @@ -148,28 +150,25 @@ def post_acquire(self): # for ATS9360 samples are arranged in the buffer as follows: # S00A, S00B, S01A, S01B...S10A, S10B, S11A, S11B... # where SXYZ is record X, sample Y, channel Z. - full_rec_length = self.number_of_channels * self.samples_per_record - step = self.number_of_channels - averaging = self.buffers_per_acquisition # reshapes date to be (samples * records) recordA = np.zeros((self.samples_per_record, self.records_per_buffer)) - # recordB = np.zeros((self.samples_per_record, self.records_per_buffer))\ for i in range(self.records_per_buffer): i0 = i * self.number_of_channels * self.samples_per_record i1 = i0 + self.number_of_channels * self.samples_per_record recordA[:, i] = (self.buffer[i0:i1:self.number_of_channels] / self.buffers_per_acquisition) - # recordB[:, i] = self.buffer[1:full_rec_length:step] / buffers + # return averaged chan A data (records) magA, phaseA = self.fit(recordA) # same for B # if self.chan_b: - # recordB = np.zeros((self.samples_per_record, self.records_per_buffer)) - # for i in self.records_per_buffer: - # recordB[i, :] = self.buffer[1:full_rec_length:step] / averaging - # magB, phaseB = self.fit(recordB) + # recordB = np.zeros( + # (self.samples_per_record, self.records_per_buffer)) + # for i in self.records_per_buffer: + # recordB[i, :] = self.buffer[1:full_rec_length:step] / averaging + # magB, phaseB = self.fit(recordB) # return data (samples * records) return magA, phaseA diff --git a/qcodes/instrument_drivers/AlazarTech/Rec_controller.py b/qcodes/instrument_drivers/AlazarTech/Rec_controller.py index ff1cabdd58c1..66eb8af1a9b2 100644 --- a/qcodes/instrument_drivers/AlazarTech/Rec_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/Rec_controller.py @@ -9,9 +9,10 @@ class RecordsParam(Parameter): Hardware controlled parameter class for Alazar acquisition. To be used with HD_Records_Controller (tested with ATS9360 board) for return of an array of record data from the Alazar, averaged over samples and buffers. - + TODO(nataliejpg) fix setpoints/shapes horriblenesss """ + def __init__(self, name, instrument): super().__init__(name) self._instrument = instrument @@ -156,7 +157,7 @@ def post_acquire(self): # recordB[:, i] = self.buffer[1:full_rec_length:step] / buffers # return averaged chan A data (records) magA, phaseA = self.fit(recordA) - + return magA, phaseA def fit(self, rec): diff --git a/qcodes/instrument_drivers/AlazarTech/Samp_controller.py b/qcodes/instrument_drivers/AlazarTech/Samp_controller.py index b95d59b6efab..fb8f27e97313 100644 --- a/qcodes/instrument_drivers/AlazarTech/Samp_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/Samp_controller.py @@ -9,7 +9,7 @@ class SamplesParam(Parameter): Hardware controlled parameter class for Alazar acquisition. To be used with HD_Samples_Controller (tested with ATS9360 board) for return of an array of sample data from the Alazar, averaged over records and buffers. - + TODO(nataliejpg) fix setpoints/shapes horriblenesss """ def __init__(self, name, instrument): diff --git a/qcodes/instrument_drivers/AlazarTech/Single_controller.py b/qcodes/instrument_drivers/AlazarTech/Single_controller.py index 3d2a35ec75b7..eb84b087ce2c 100644 --- a/qcodes/instrument_drivers/AlazarTech/Single_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/Single_controller.py @@ -202,4 +202,4 @@ def filter_ls(self, rec, numtaps, cutoff): desired, nyq=nyq_rate) filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec) - return filtered_rec \ No newline at end of file + return filtered_rec diff --git a/qcodes/instrument_drivers/AlazarTech/basic_controller.py b/qcodes/instrument_drivers/AlazarTech/basic_controller.py index 9b2627c30f5c..d0384e243249 100644 --- a/qcodes/instrument_drivers/AlazarTech/basic_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/basic_controller.py @@ -11,6 +11,7 @@ class SampleSweep(Parameter): Instrument returns an buffer of data (channels * samples * records) which is processed by the post_acquire function of the Acquidiyion Controller """ + def __init__(self, name, instrument): super().__init__(name) self._instrument = instrument @@ -116,28 +117,28 @@ def post_acquire(self): See AcquisitionController :return: """ - + # for ATS9360 samples are arranged in the buffer as follows: # S00A, S00B, S01A, S01B...S10A, S10B, S11A, S11B... # where SXYZ is record X, sample Y, channel Z. # break buffer up into records, averages over them and returns samples records_per_acquisition = (self.buffers_per_acquisition * - self.records_per_buffer) + self.records_per_buffer) recordA = np.zeros(self.samples_per_record, dtype=np.uint16) for i in range(self.records_per_buffer): i0 = (i * self.samples_per_record * self.number_of_channels) i1 = (i0 + self.samples_per_record * self.number_of_channels) recordA += np.uint16(self.buffer[i0:i1:self.number_of_channels] / - records_per_acquisition) + records_per_acquisition) recordB = np.zeros(self.samples_per_record, dtype=np.uint16) for i in range(self.records_per_buffer): i0 = (i * self.samples_per_record * self.number_of_channels + 1) i1 = (i0 + self.samples_per_record * self.number_of_channels) recordB += np.uint16(self.buffer[i0:i1:self.number_of_channels] / - records_per_acquisition) - + records_per_acquisition) + volt_rec_A = self.sample_to_volt(recordA) volt_rec_B = self.sample_to_volt(recordB) @@ -145,15 +146,16 @@ def post_acquire(self): def sample_to_volt(self, raw_samples): # right_shift 16-bit sample by 4 to get 12 bit sample - shifted_samples = np.right_shift(raw_samples,4) - + shifted_samples = np.right_shift(raw_samples, 4) + # Alazar calibration bps = 12 input_range_volts = 0.8 code_zero = (1 << (bps - 1)) - 0.5 code_range = (1 << (bps - 1)) - 0.5 - + # Convert to volts - volt_samples = input_range_volts * (shifted_samples - code_zero) / code_range - - return volt_samples \ No newline at end of file + volt_samples = input_range_volts * \ + (shifted_samples - code_zero) / code_range + + return volt_samples From ec757dba748735b3f3c8da3eb6b3afad15ba7cfd Mon Sep 17 00:00:00 2001 From: Natalie Pearson Date: Wed, 9 Nov 2016 15:09:00 +0100 Subject: [PATCH 037/180] make defaults such that getting board info is easier --- qcodes/instrument_drivers/AlazarTech/ATS.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/ATS.py b/qcodes/instrument_drivers/AlazarTech/ATS.py index da63db1eb1d5..6b0c6e1107e5 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS.py @@ -190,7 +190,7 @@ def find_boards(cls, dll_path=None): return boards @classmethod - def get_board_info(cls, dll, system_id, board_id): + def get_board_info(cls, dll, system_id=1, board_id=1): """ Get the information from a connected Alazar board @@ -204,7 +204,6 @@ def get_board_info(cls, dll, system_id, board_id): max_samples bits_per_sample """ - # make a temporary instrument for this board, to make it easier # to get its info board = cls('temp', system_id=system_id, board_id=board_id, @@ -428,8 +427,6 @@ def config(self, clock_source=None, sample_rate=None, clock_edge=None, self._handle, self.aux_io_mode, self.aux_io_param) - # TODO(damazter) (W) config AUXIO - def _get_channel_info(self, handle): bps = np.array([0], dtype=np.uint8) # bps bits per sample max_s = np.array([0], dtype=np.uint32) # max_s memory size in samples From 9276dab8db133fc092c5cead46ce53e41db5bc79 Mon Sep 17 00:00:00 2001 From: Natalie Pearson Date: Wed, 9 Nov 2016 15:10:08 +0100 Subject: [PATCH 038/180] create separate tools file and somewhat clear up fitting and filtering --- .../AlazarTech/Samp_controller.py | 116 +++++++++--------- .../AlazarTech/acquisition_tools.py | 51 ++++++++ .../AlazarTech/basic_controller.py | 28 ++--- 3 files changed, 118 insertions(+), 77 deletions(-) create mode 100644 qcodes/instrument_drivers/AlazarTech/acquisition_tools.py diff --git a/qcodes/instrument_drivers/AlazarTech/Samp_controller.py b/qcodes/instrument_drivers/AlazarTech/Samp_controller.py index a2fa93187f9b..ffdb67ea7490 100644 --- a/qcodes/instrument_drivers/AlazarTech/Samp_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/Samp_controller.py @@ -1,7 +1,7 @@ from .ATS import AcquisitionController import numpy as np from qcodes import Parameter -from scipy import signal +import acquistion_tools as tools class SamplesParam(Parameter): @@ -12,6 +12,7 @@ class SamplesParam(Parameter): TODO(nataliejpg) fix setpoints/shapes horriblenesss """ + def __init__(self, name, instrument): super().__init__(name) self._instrument = instrument @@ -62,23 +63,29 @@ class HD_Samples_Controller(AcquisitionController): TODO(nataliejpg) test filter options TODO(nataliejpg) test mag phase logic TODO(nataliejpg) finish implementation of channel b option - TODO(nataliejpg) make filter settings not hard coded + TODO(nataliejpg) update docstrings :P """ def __init__(self, name, alazar_name, demod_freq, samp_rate=500e6, - filt='win', chan_b=False, **kwargs): + int_delay=None, int_time=None, filt='win', + numtaps=101, chan_b=False, **kwargs): filter_dict = {'win': 0, 'hamming': 1, 'ls': 2} self.demodulation_frequency = demod_freq self.sample_rate = samp_rate self.filter = filter_dict[filt] + self.int_time = int_time + self.int_delay = int_delay + self.numtaps = numtaps self.chan_b = chan_b self.samples_per_record = 0 self.records_per_buffer = 0 self.buffers_per_acquisition = 0 self.number_of_channels = 2 + self.samples_delay = None self.cos_list = None self.sin_list = None self.buffer = None + self.board_info = None # make a call to the parent class and by extension, # create the parameter structure of this class super().__init__(name, alazar_name, **kwargs) @@ -104,6 +111,7 @@ def pre_start_capture(self): self.samples_per_record = alazar.samples_per_record.get() self.records_per_buffer = alazar.records_per_buffer.get() self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() + self.board_info = alazar.get_board_info(alazar.dll_path) self.buffer = np.zeros(self.samples_per_record * self.records_per_buffer * self.number_of_channels) @@ -114,9 +122,16 @@ def pre_start_capture(self): self.cos_list = np.cos(angle_list) self.sin_list = np.sin(angle_list) - - numtaps = round(self.samples_per_record/20) * 2 + 1 - delay = numtaps - 1 + + if self.int_delay: + self.samples_delay = self.int_delay * self.sample_rate + if self.samples_delay < (self.numtaps - 1): + expected_delay = (self.numtaps - 1) / self.sample_rate + Warning( + 'delay is less than recommended for filter choice: ' + '(expect delay >= {}'.format(expected_delay)) + else: + self.samples_delay = self.numtaps - 1 def pre_acquire(self): """ @@ -147,8 +162,7 @@ def post_acquire(self): # S00A, S00B, S01A, S01B...S10A, S10B, S11A, S11B... # where SXYZ is record X, sample Y, channel Z. - # breaks buffer up into records and averages over them - # leaving data in form (samples) + # break buffer up into records and averages over them records_per_acquisition = (self.buffers_per_acquisition * self.records_per_buffer) recordA = np.zeros(self.samples_per_record) @@ -158,13 +172,15 @@ def post_acquire(self): recordA += (self.buffer[i0:i1:self.number_of_channels] / records_per_acquisition) - # demodulate record, data returned (samples) + # do demodulation magA, phaseA = self.fit(recordA) + # same for chan b if self.chan_b: recordB = np.zeros(self.samples_per_record) for i in range(self.records_per_buffer): - i0 = (i * self.samples_per_record * self.number_of_channels + 1) + i0 = (i * self.samples_per_record * + self.number_of_channels + 1) i1 = (i0 + self.samples_per_record * self.number_of_channels) recordB += (self.buffer[i0:i1:self.number_of_channels] / records_per_acquisition) @@ -173,64 +189,46 @@ def post_acquire(self): return magA, phaseA def fit(self, rec): - # center rec around 0 - rec = rec - np.mean(rec) + # convert rec to volts + if self.board_info['bits_per_sample'] == 12: + volt_rec = tools.sample_to_volt_u12(rec) + else: + Warning( + 'sample to volt conversion does not exist for ' + 'bps != 12, raw samples centered and returned') + volt_rec = rec - np.mean(rec) # multiply with software wave - re_wave = np.multiply(rec, self.cos_list) - im_wave = np.multiply(rec, self.sin_list) - cutoff = self.demodulation_frequency - numtaps = 30 + re_wave = np.multiply(volt_rec, self.cos_list) + im_wave = np.multiply(volt_rec, self.sin_list) + cutoff = self.demodulation_frequency / 2 # filter out higher freq component if self.filter == 0: - RePart = self.filter_win(re_wave, numtaps, cutoff) - ImPart = self.filter_win(im_wave, numtaps, cutoff) + re_filtered = tools.filter_win(re_wave, cutoff, + self.samp_rate, self.numtaps) + im_filtered = tools.filter_win(re_wave, cutoff, + self.samp_rate, self.numtaps) elif self.filter == 1: - RePart = self.filter_hamming(re_wave, numtaps, cutoff) - ImPart = self.filter_hamming(im_wave, numtaps, cutoff) + re_filtered = tools.filter_ham(re_wave, cutoff, + self.samp_rate, self.numtaps) + im_filtered = tools.filter_ham(im_wave, cutoff, + self.samp_rate, self.numtaps) elif self.filter == 2: - RePart = self.filter_ls(re_wave, numtaps, cutoff) - ImPart = self.filter_ls(im_wave, numtaps, cutoff) + re_filtered = tools.filter_ls(re_wave, cutoff, + self.samp_rate, self.numtaps) + im_filtered = tools.filter_ls(im_wave, cutoff, + self.samp_rate, self.numtaps) + + # apply int limits + start = self.samples_delay + end = self.int_time * self.samp_rate + start + re_limited = re_filtered[start:end] + im_limited = im_filtered[start:end] # convert to magnitude and phase - # data returnded (samples) - complex_num = RePart + ImPart * 1j - mag = 2 * abs(complex_num) + complex_num = re_limited + im_limited * 1j + mag = abs(complex_num) phase = np.angle(complex_num, deg=True) return mag, phase - - def filter_hamming(self, rec, numtaps, cutoff): - sample_rate = self.sample_rate - nyq_rate = sample_rate / 2. - fir_coef = signal.firwin(numtaps, - cutoff / nyq_rate, - window="hamming") - filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec) - return filtered_rec - - def filter_win(self, rec, numtaps, cutoff): - sample_rate = self.sample_rate - nyq_rate = sample_rate / 2. - fir_coef = signal.firwin(numtaps, - cutoff / nyq_rate) - filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec) - return filtered_rec - - def filter_ls(self, rec, numtaps, cutoff): - sample_rate = self.sample_rate - nyq_rate = sample_rate / 2. - bands = [0, cutoff / nyq_rate, cutoff / nyq_rate, 1] - desired = [1, 1, 0, 0] - fir_coef = signal.firls(numtaps, - bands, - desired, - nyq=nyq_rate) - filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec) - return filtered_rec - - def filter(self, rec, numtaps, delay): - fir_coef = signal.firwin(numtaps, 0.01) - filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec) - return fir_coef, filtered_rec[delay:] diff --git a/qcodes/instrument_drivers/AlazarTech/acquisition_tools.py b/qcodes/instrument_drivers/AlazarTech/acquisition_tools.py new file mode 100644 index 000000000000..c8742e96ae02 --- /dev/null +++ b/qcodes/instrument_drivers/AlazarTech/acquisition_tools.py @@ -0,0 +1,51 @@ +import numpy as np +from scipy import signal + + +def sample_to_volt_u12(self, raw_samples, input_range_volts, bps): + # right_shift 16-bit sample by 4 to get 12 bit sample + shifted_samples = np.right_shift(raw_samples, 4) + + # Alazar calibration + bps = 12 + input_range_volts = 0.8 + code_zero = (1 << (bps - 1)) - 0.5 + code_range = (1 << (bps - 1)) - 0.5 + + # Convert to volts + volt_samples = (input_range_volts * + (shifted_samples - code_zero) / code_range) + + return volt_samples + + +def filter_win(rec, cutoff, sample_rate, numtaps): + nyq_rate = sample_rate / 2. + fir_coef = signal.firwin(numtaps, cutoff / nyq_rate) + filtered_rec = signal.lfilter(fir_coef, 1.0, rec) + return filtered_rec + + +def filter_ham(rec, cutoff, sample_rate, numtaps): + raise NotImplementedError + # sample_rate = self.sample_rate + # nyq_rate = sample_rate / 2. + # fir_coef = signal.firwin(numtaps, + # cutoff / nyq_rate, + # window="hamming") + # filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec) + # return filtered_rec + + +def filter_ls(rec, cutoff, sample_rate, numtaps): + raise NotImplementedError + # sample_rate = self.sample_rate + # nyq_rate = sample_rate / 2. + # bands = [0, cutoff / nyq_rate, cutoff / nyq_rate, 1] + # desired = [1, 1, 0, 0] + # fir_coef = signal.firls(numtaps, + # bands, + # desired, + # nyq=nyq_rate) + # filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec) + # return filtered_rec diff --git a/qcodes/instrument_drivers/AlazarTech/basic_controller.py b/qcodes/instrument_drivers/AlazarTech/basic_controller.py index d0384e243249..3c20c9bcbfd7 100644 --- a/qcodes/instrument_drivers/AlazarTech/basic_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/basic_controller.py @@ -1,6 +1,7 @@ from .ATS import AcquisitionController import numpy as np from qcodes import Parameter +import acquistion_tools class SampleSweep(Parameter): @@ -65,6 +66,7 @@ def __init__(self, name, alazar_name, **kwargs): # TODO(damazter) (S) this is not very general: self.number_of_channels = 2 self.buffer = None + self.board_info = None # make a call to the parent class and by extension, # create the parameter structure of this class super().__init__(name, alazar_name, **kwargs) @@ -90,6 +92,7 @@ def pre_start_capture(self): self.samples_per_record = alazar.samples_per_record.get() self.records_per_buffer = alazar.records_per_buffer.get() self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() + self.board_info = alazar.get_board_info(alazar.dll_path) self.buffer = np.zeros(self.samples_per_record * self.records_per_buffer * self.number_of_channels, @@ -139,23 +142,12 @@ def post_acquire(self): recordB += np.uint16(self.buffer[i0:i1:self.number_of_channels] / records_per_acquisition) - volt_rec_A = self.sample_to_volt(recordA) - volt_rec_B = self.sample_to_volt(recordB) + if self.board_info['bits_per_sample'] == 12: + volt_rec_A = acquistion_tools.sample_to_volt_u12(recordA) + volt_rec_B = acquistion_tools.sample_to_volt_u12(recordB) + else: + Warning('sample to volt conversion does not exist for bps != 12, raw samples returned') + volt_rec_A = recordA + volt_rec_B = recordB return volt_rec_A, volt_rec_B - - def sample_to_volt(self, raw_samples): - # right_shift 16-bit sample by 4 to get 12 bit sample - shifted_samples = np.right_shift(raw_samples, 4) - - # Alazar calibration - bps = 12 - input_range_volts = 0.8 - code_zero = (1 << (bps - 1)) - 0.5 - code_range = (1 << (bps - 1)) - 0.5 - - # Convert to volts - volt_samples = input_range_volts * \ - (shifted_samples - code_zero) / code_range - - return volt_samples From d7a3459462eaa01575ad75f71ef39d7d1998726d Mon Sep 17 00:00:00 2001 From: nataliejpg Date: Wed, 9 Nov 2016 19:43:57 +0100 Subject: [PATCH 039/180] debugging so that limiting int_delay and int_time work as well as sample_to_volt conversion --- qcodes/instrument_drivers/AlazarTech/ATS.py | 7 +- .../AlazarTech/Samp_controller.py | 151 ++++++++++++------ .../AlazarTech/acquisition_tools.py | 4 +- .../AlazarTech/basic_controller.py | 31 +++- 4 files changed, 137 insertions(+), 56 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/ATS.py b/qcodes/instrument_drivers/AlazarTech/ATS.py index 6b0c6e1107e5..cd14d0c00ab1 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS.py @@ -189,8 +189,9 @@ def find_boards(cls, dll_path=None): boards.append(cls.get_board_info(dll, system_id, board_id)) return boards + # TODO(nataliejpg) this needs fixing..., dll can't be a string @classmethod - def get_board_info(cls, dll, system_id=1, board_id=1): + def get_board_info(cls, dll, system_id, board_id): """ Get the information from a connected Alazar board @@ -260,6 +261,8 @@ def get_idn(self): board_kind = self._board_names[ self._ATS_dll.AlazarGetBoardKind(self._handle)] + max_s, bps = self._get_channel_info(self._handle) + major = np.array([0], dtype=np.uint8) minor = np.array([0], dtype=np.uint8) revision = np.array([0], dtype=np.uint8) @@ -309,6 +312,8 @@ def get_idn(self): return {'firmware': None, 'model': board_kind, + 'max_samples': max_s, + 'bits_per_sample': bps, 'serial': serial, 'vendor': 'AlazarTech', 'CPLD_version': cpld_ver, diff --git a/qcodes/instrument_drivers/AlazarTech/Samp_controller.py b/qcodes/instrument_drivers/AlazarTech/Samp_controller.py index ffdb67ea7490..e4be81c6b0cb 100644 --- a/qcodes/instrument_drivers/AlazarTech/Samp_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/Samp_controller.py @@ -1,7 +1,9 @@ from .ATS import AcquisitionController import numpy as np from qcodes import Parameter -import acquistion_tools as tools +from scipy import signal + +#import acquistion_tools as tools class SamplesParam(Parameter): @@ -23,19 +25,24 @@ def __init__(self, name, instrument): self.setpoints = ((1,), (1,)) self.shapes = ((1,), (1,)) - def update_acquisition_kwargs(self, **kwargs): + def update_acquisition_kwargs(self, samp_time=None, **kwargs): # needed to update config of the software parameter on sweep change # freq setpoints tuple as needs to be hashable for look up - if 'samples_per_record' in kwargs: + if samp_time: + npts = samp_time + n = tuple(np.arange(npts)) + self.setpoints = ((n,), (n,)) + self.shapes = ((npts,), (npts,)) + elif 'samples_per_record' in kwargs: npts = kwargs['samples_per_record'] n = tuple(np.arange(npts)) self.setpoints = ((n,), (n,)) self.shapes = ((npts,), (npts,)) else: - raise ValueError('samples_per_record must be specified') + raise ValueError('samples_per_record or sample_num must be specified') # updates dict to be used in acquisition get call self.acquisitionkwargs.update(**kwargs) - + def get(self): mag, phase = self._instrument._get_alazar().acquire( acquisition_controller=self._instrument, @@ -66,15 +73,13 @@ class HD_Samples_Controller(AcquisitionController): TODO(nataliejpg) update docstrings :P """ - def __init__(self, name, alazar_name, demod_freq, samp_rate=500e6, - int_delay=None, int_time=None, filt='win', + def __init__(self, name, alazar_name, demod_freq, samp_rate=500e6, filt='win', numtaps=101, chan_b=False, **kwargs): filter_dict = {'win': 0, 'hamming': 1, 'ls': 2} self.demodulation_frequency = demod_freq self.sample_rate = samp_rate self.filter = filter_dict[filt] - self.int_time = int_time - self.int_delay = int_delay + self.int_time = None self.numtaps = numtaps self.chan_b = chan_b self.samples_per_record = 0 @@ -82,6 +87,7 @@ def __init__(self, name, alazar_name, demod_freq, samp_rate=500e6, self.buffers_per_acquisition = 0 self.number_of_channels = 2 self.samples_delay = None + self.samples_time = None self.cos_list = None self.sin_list = None self.buffer = None @@ -100,7 +106,46 @@ def update_acquisitionkwargs(self, **kwargs): :param kwargs: :return: """ - self.acquisition.update_acquisition_kwargs(**kwargs) + samples_per_record = kwargs['samples_per_record'] + sample_rate = self.sample_rate + + if 'int_delay' in kwargs: + int_delay = kwargs['int_delay'] + samp_delay = int_delay * sample_rate + samples_delay_min = (self.numtaps - 1) + if samp_delay < samples_delay_min: + int_delay_min = samples_delay_min / sample_rate + Warning( + 'delay is less than recommended for filter choice: ' + '(expect delay >= {}'.format(int_delay_min)) + else: + samp_delay = self.numtaps - 1 + + if 'int_time' in kwargs: + int_time = kwargs['int_time'] + samp_time = int_time * sample_rate + samples_time_max = (samples_per_record - samp_delay) + oscilations_measured = int_time / self.demodulation_frequency + oversampling = sample_rate / (2 * self.demodulation_frequency) + if samp_time > samples_time_max: + int_time_max = samples_time_max / sample_rate + Warning( + 'int_time {} is longer than total_time - delay ({})'.format(int_time, int_time_max)) + elif oscilations_measured < 10: + Warning( + '{} oscilations measured, recommend at least 10: ' + 'decrease sampling rate, take more samples or increase demodulation freq'.format(oscilations_measured)) + elif oversampling < 1: + Warning('oversampling rate is {}, recommend > 1: ' + 'increase sampling rate or decrease demodulation frequency'.format(oversampling)) + else: + samp_time = samples_per_record - samp_delay + + + self.samples_time = samp_time + self.samples_delay = samp_delay + + self.acquisition.update_acquisition_kwargs(samp_time, **kwargs) def pre_start_capture(self): """ @@ -111,28 +156,19 @@ def pre_start_capture(self): self.samples_per_record = alazar.samples_per_record.get() self.records_per_buffer = alazar.records_per_buffer.get() self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() - self.board_info = alazar.get_board_info(alazar.dll_path) + self.board_info = alazar.get_idn() self.buffer = np.zeros(self.samples_per_record * self.records_per_buffer * - self.number_of_channels) + self.number_of_channels, + dtype=np.uint16) - integer_list = np.arange(self.samples_per_record) + integer_list = np.arange(self.samples_per_record, dtype=np.uint16) angle_list = (2 * np.pi * self.demodulation_frequency / self.sample_rate * integer_list) self.cos_list = np.cos(angle_list) self.sin_list = np.sin(angle_list) - if self.int_delay: - self.samples_delay = self.int_delay * self.sample_rate - if self.samples_delay < (self.numtaps - 1): - expected_delay = (self.numtaps - 1) / self.sample_rate - Warning( - 'delay is less than recommended for filter choice: ' - '(expect delay >= {}'.format(expected_delay)) - else: - self.samples_delay = self.numtaps - 1 - def pre_acquire(self): """ See AcquisitionController @@ -165,11 +201,11 @@ def post_acquire(self): # break buffer up into records and averages over them records_per_acquisition = (self.buffers_per_acquisition * self.records_per_buffer) - recordA = np.zeros(self.samples_per_record) + recordA = np.zeros(self.samples_per_record, dtype=np.uint16) for i in range(self.records_per_buffer): i0 = (i * self.samples_per_record * self.number_of_channels) i1 = (i0 + self.samples_per_record * self.number_of_channels) - recordA += (self.buffer[i0:i1:self.number_of_channels] / + recordA += np.uint16(self.buffer[i0:i1:self.number_of_channels] / records_per_acquisition) # do demodulation @@ -177,12 +213,12 @@ def post_acquire(self): # same for chan b if self.chan_b: - recordB = np.zeros(self.samples_per_record) + recordB = np.zeros(self.samples_per_record, dtype=np.uint16) for i in range(self.records_per_buffer): i0 = (i * self.samples_per_record * self.number_of_channels + 1) i1 = (i0 + self.samples_per_record * self.number_of_channels) - recordB += (self.buffer[i0:i1:self.number_of_channels] / + recordB += np.uint16(self.buffer[i0:i1:self.number_of_channels] / records_per_acquisition) magB, phaseB = self.fit(recordB) @@ -190,12 +226,12 @@ def post_acquire(self): def fit(self, rec): # convert rec to volts - if self.board_info['bits_per_sample'] == 12: - volt_rec = tools.sample_to_volt_u12(rec) + bps = self.board_info['bits_per_sample'] + if bps == 12: + volt_rec = sample_to_volt_u12(rec, bps) else: - Warning( - 'sample to volt conversion does not exist for ' - 'bps != 12, raw samples centered and returned') + Warning('sample to volt conversion does not exist for' + ' bps != 12, centered raw samples returned') volt_rec = rec - np.mean(rec) # multiply with software wave @@ -205,24 +241,27 @@ def fit(self, rec): # filter out higher freq component if self.filter == 0: - re_filtered = tools.filter_win(re_wave, cutoff, - self.samp_rate, self.numtaps) - im_filtered = tools.filter_win(re_wave, cutoff, - self.samp_rate, self.numtaps) + re_filtered = filter_win(re_wave, cutoff, + self.sample_rate, self.numtaps) + im_filtered = filter_win(re_wave, cutoff, + self.sample_rate, self.numtaps) elif self.filter == 1: - re_filtered = tools.filter_ham(re_wave, cutoff, - self.samp_rate, self.numtaps) - im_filtered = tools.filter_ham(im_wave, cutoff, - self.samp_rate, self.numtaps) + re_filtered = filter_ham(re_wave, cutoff, + self.sample_rate, self.numtaps) + im_filtered = filter_ham(im_wave, cutoff, + self.sample_rate, self.numtaps) elif self.filter == 2: - re_filtered = tools.filter_ls(re_wave, cutoff, - self.samp_rate, self.numtaps) - im_filtered = tools.filter_ls(im_wave, cutoff, - self.samp_rate, self.numtaps) + re_filtered = filter_ls(re_wave, cutoff, + self.sample_rate, self.numtaps) + im_filtered = filter_ls(im_wave, cutoff, + self.sample_rate, self.numtaps) # apply int limits start = self.samples_delay - end = self.int_time * self.samp_rate + start + if self.int_time: + end = self.int_time * self.sample_rate + start + else: + end = None re_limited = re_filtered[start:end] im_limited = im_filtered[start:end] @@ -232,3 +271,25 @@ def fit(self, rec): phase = np.angle(complex_num, deg=True) return mag, phase + +def filter_win(rec, cutoff, sample_rate, numtaps): + nyq_rate = sample_rate / 2. + fir_coef = signal.firwin(numtaps, cutoff / nyq_rate) + filtered_rec = signal.lfilter(fir_coef, 1.0, rec) + return filtered_rec + +def sample_to_volt_u12(raw_samples, bps): + # right_shift 16-bit sample by 4 to get 12 bit sample + shifted_samples = np.right_shift(raw_samples, 4) + + # Alazar calibration + code_zero = (1 << (bps - 1)) - 0.5 + code_range = (1 << (bps - 1)) - 0.5 + + # TODO(nataliejpg) make this not hard coded + input_range_volts = 1 + # Convert to volts + volt_samples = np.float64(input_range_volts * + (shifted_samples - code_zero) / code_range) + + return volt_samples \ No newline at end of file diff --git a/qcodes/instrument_drivers/AlazarTech/acquisition_tools.py b/qcodes/instrument_drivers/AlazarTech/acquisition_tools.py index c8742e96ae02..657f1f3be9f1 100644 --- a/qcodes/instrument_drivers/AlazarTech/acquisition_tools.py +++ b/qcodes/instrument_drivers/AlazarTech/acquisition_tools.py @@ -2,13 +2,11 @@ from scipy import signal -def sample_to_volt_u12(self, raw_samples, input_range_volts, bps): +def sample_to_volt_u12(raw_samples, input_range_volts, bps): # right_shift 16-bit sample by 4 to get 12 bit sample shifted_samples = np.right_shift(raw_samples, 4) # Alazar calibration - bps = 12 - input_range_volts = 0.8 code_zero = (1 << (bps - 1)) - 0.5 code_range = (1 << (bps - 1)) - 0.5 diff --git a/qcodes/instrument_drivers/AlazarTech/basic_controller.py b/qcodes/instrument_drivers/AlazarTech/basic_controller.py index 3c20c9bcbfd7..53ee683fbebe 100644 --- a/qcodes/instrument_drivers/AlazarTech/basic_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/basic_controller.py @@ -1,7 +1,7 @@ from .ATS import AcquisitionController import numpy as np from qcodes import Parameter -import acquistion_tools +#from.acquistion_tools import sample_to_volt_u12 class SampleSweep(Parameter): @@ -92,7 +92,7 @@ def pre_start_capture(self): self.samples_per_record = alazar.samples_per_record.get() self.records_per_buffer = alazar.records_per_buffer.get() self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() - self.board_info = alazar.get_board_info(alazar.dll_path) + self.board_info = alazar.get_idn() self.buffer = np.zeros(self.samples_per_record * self.records_per_buffer * self.number_of_channels, @@ -142,12 +142,29 @@ def post_acquire(self): recordB += np.uint16(self.buffer[i0:i1:self.number_of_channels] / records_per_acquisition) - if self.board_info['bits_per_sample'] == 12: - volt_rec_A = acquistion_tools.sample_to_volt_u12(recordA) - volt_rec_B = acquistion_tools.sample_to_volt_u12(recordB) + bps = self.board_info['bits_per_sample'] + if bps == 12: + volt_rec_A = sample_to_volt_u12(recordA, bps) + volt_rec_B = sample_to_volt_u12(recordA, bps) else: Warning('sample to volt conversion does not exist for bps != 12, raw samples returned') - volt_rec_A = recordA - volt_rec_B = recordB + volt_rec_A = recordA - np.mean(recordA) + volt_rec_B = recordB - np.mean(recordB) return volt_rec_A, volt_rec_B + +def sample_to_volt_u12(raw_samples, bps): + # right_shift 16-bit sample by 4 to get 12 bit sample + shifted_samples = np.right_shift(raw_samples, 4) + + # Alazar calibration + code_zero = (1 << (bps - 1)) - 0.5 + code_range = (1 << (bps - 1)) - 0.5 + + # TODO(nataliejpg) make this not hard coded + input_range_volts = 1 + # Convert to volts + volt_samples = np.float64(input_range_volts * + (shifted_samples - code_zero) / code_range) + + return volt_samples \ No newline at end of file From c4cec943599e71bdceb6e6a6d7e6684804cb16b3 Mon Sep 17 00:00:00 2001 From: nataliejpg Date: Thu, 10 Nov 2016 14:37:23 +0100 Subject: [PATCH 040/180] get filtering to work well --- qcodes/instrument_drivers/AlazarTech/Samp_controller.py | 5 +++-- qcodes/instrument_drivers/AlazarTech/basic_controller.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/Samp_controller.py b/qcodes/instrument_drivers/AlazarTech/Samp_controller.py index e4be81c6b0cb..62bec2d76305 100644 --- a/qcodes/instrument_drivers/AlazarTech/Samp_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/Samp_controller.py @@ -71,6 +71,7 @@ class HD_Samples_Controller(AcquisitionController): TODO(nataliejpg) test mag phase logic TODO(nataliejpg) finish implementation of channel b option TODO(nataliejpg) update docstrings :P + TODO(nataliejpg) make demodulation freq a param """ def __init__(self, name, alazar_name, demod_freq, samp_rate=500e6, filt='win', @@ -237,13 +238,13 @@ def fit(self, rec): # multiply with software wave re_wave = np.multiply(volt_rec, self.cos_list) im_wave = np.multiply(volt_rec, self.sin_list) - cutoff = self.demodulation_frequency / 2 + cutoff = self.demodulation_frequency / 10 # filter out higher freq component if self.filter == 0: re_filtered = filter_win(re_wave, cutoff, self.sample_rate, self.numtaps) - im_filtered = filter_win(re_wave, cutoff, + im_filtered = filter_win(im_wave, cutoff, self.sample_rate, self.numtaps) elif self.filter == 1: re_filtered = filter_ham(re_wave, cutoff, diff --git a/qcodes/instrument_drivers/AlazarTech/basic_controller.py b/qcodes/instrument_drivers/AlazarTech/basic_controller.py index 53ee683fbebe..40adef46d9c1 100644 --- a/qcodes/instrument_drivers/AlazarTech/basic_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/basic_controller.py @@ -145,7 +145,7 @@ def post_acquire(self): bps = self.board_info['bits_per_sample'] if bps == 12: volt_rec_A = sample_to_volt_u12(recordA, bps) - volt_rec_B = sample_to_volt_u12(recordA, bps) + volt_rec_B = sample_to_volt_u12(recordB, bps) else: Warning('sample to volt conversion does not exist for bps != 12, raw samples returned') volt_rec_A = recordA - np.mean(recordA) From aca9a1024f24c502009c73376da22ad9701c435d Mon Sep 17 00:00:00 2001 From: Natalie Pearson Date: Mon, 14 Nov 2016 18:25:30 +0100 Subject: [PATCH 041/180] tidy up sample controller --- qcodes/instrument_drivers/AlazarTech/ATS.py | 2 +- .../instrument_drivers/AlazarTech/ATS9360.py | 2 + .../AlazarTech/Samp_controller.py | 82 ++++++++----------- .../AlazarTech/Single_controller.py | 50 ++++++++++- qcodes/utils/helpers.py | 34 ++++++++ 5 files changed, 119 insertions(+), 51 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/ATS.py b/qcodes/instrument_drivers/AlazarTech/ATS.py index cd14d0c00ab1..0fe74979e39b 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS.py @@ -540,7 +540,7 @@ def acquire(self, mode=None, samples_per_record=None, if (samples_per_record % buffers_per_acquisition != 0): logging.warning('buffers_per_acquisition is not a divisor of ' 'samples per record which it should be in ' - 'TS mode, rounding down in samples per buffer ' + 's mode, rounding down in samples per buffer ' 'calculation') samples_per_buffer = int(samples_per_record / buffers_per_acquisition) diff --git a/qcodes/instrument_drivers/AlazarTech/ATS9360.py b/qcodes/instrument_drivers/AlazarTech/ATS9360.py index 7afbaff1ff3a..448a1ce27a96 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS9360.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS9360.py @@ -266,6 +266,8 @@ def __init__(self, name, **kwargs): value=1000, vals=validators.Ints(min_value=0)) + + model = self.get_idn()['model'] if model != 'ATS9360': raise Exception("The Alazar board kind is not 'ATS9360'," diff --git a/qcodes/instrument_drivers/AlazarTech/Samp_controller.py b/qcodes/instrument_drivers/AlazarTech/Samp_controller.py index 62bec2d76305..ecccca78b027 100644 --- a/qcodes/instrument_drivers/AlazarTech/Samp_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/Samp_controller.py @@ -1,9 +1,8 @@ +import logging from .ATS import AcquisitionController import numpy as np from qcodes import Parameter -from scipy import signal - -#import acquistion_tools as tools +import qcodes.utils.helpers as helpers class SamplesParam(Parameter): @@ -39,10 +38,11 @@ def update_acquisition_kwargs(self, samp_time=None, **kwargs): self.setpoints = ((n,), (n,)) self.shapes = ((npts,), (npts,)) else: - raise ValueError('samples_per_record or sample_num must be specified') + raise ValueError( + 'samples_per_record or sample_num must be specified') # updates dict to be used in acquisition get call self.acquisitionkwargs.update(**kwargs) - + def get(self): mag, phase = self._instrument._get_alazar().acquire( acquisition_controller=self._instrument, @@ -74,13 +74,12 @@ class HD_Samples_Controller(AcquisitionController): TODO(nataliejpg) make demodulation freq a param """ - def __init__(self, name, alazar_name, demod_freq, samp_rate=500e6, filt='win', - numtaps=101, chan_b=False, **kwargs): - filter_dict = {'win': 0, 'hamming': 1, 'ls': 2} + def __init__(self, name, alazar_name, demod_freq, samp_rate=5e8, + filt='win', numtaps=101, chan_b=False, **kwargs): + filter_dict = {'win': 0, 'ls': 1} self.demodulation_frequency = demod_freq self.sample_rate = samp_rate self.filter = filter_dict[filt] - self.int_time = None self.numtaps = numtaps self.chan_b = chan_b self.samples_per_record = 0 @@ -109,7 +108,7 @@ def update_acquisitionkwargs(self, **kwargs): """ samples_per_record = kwargs['samples_per_record'] sample_rate = self.sample_rate - + if 'int_delay' in kwargs: int_delay = kwargs['int_delay'] samp_delay = int_delay * sample_rate @@ -121,7 +120,7 @@ def update_acquisitionkwargs(self, **kwargs): '(expect delay >= {}'.format(int_delay_min)) else: samp_delay = self.numtaps - 1 - + if 'int_time' in kwargs: int_time = kwargs['int_time'] samp_time = int_time * sample_rate @@ -130,22 +129,23 @@ def update_acquisitionkwargs(self, **kwargs): oversampling = sample_rate / (2 * self.demodulation_frequency) if samp_time > samples_time_max: int_time_max = samples_time_max / sample_rate - Warning( - 'int_time {} is longer than total_time - delay ({})'.format(int_time, int_time_max)) + raise ValueError('int_time {} is longer than total_time - ' + 'delay ({})'.format(int_time, int_time_max)) elif oscilations_measured < 10: - Warning( - '{} oscilations measured, recommend at least 10: ' - 'decrease sampling rate, take more samples or increase demodulation freq'.format(oscilations_measured)) + logging.warning('{} oscilations measured, recommend at ' + 'least 10: decrease sampling rate, take ' + 'more samples or increase demodulation ' + 'freq'.format(oscilations_measured)) elif oversampling < 1: - Warning('oversampling rate is {}, recommend > 1: ' - 'increase sampling rate or decrease demodulation frequency'.format(oversampling)) + logging.warning('oversampling rate is {}, recommend > 1: ' + 'increase sampling rate or decrease ' + 'demodulation frequency'.format(oversampling)) else: samp_time = samples_per_record - samp_delay - - + self.samples_time = samp_time self.samples_delay = samp_delay - + self.acquisition.update_acquisition_kwargs(samp_time, **kwargs) def pre_start_capture(self): @@ -207,7 +207,7 @@ def post_acquire(self): i0 = (i * self.samples_per_record * self.number_of_channels) i1 = (i0 + self.samples_per_record * self.number_of_channels) recordA += np.uint16(self.buffer[i0:i1:self.number_of_channels] / - records_per_acquisition) + records_per_acquisition) # do demodulation magA, phaseA = self.fit(recordA) @@ -220,7 +220,7 @@ def post_acquire(self): self.number_of_channels + 1) i1 = (i0 + self.samples_per_record * self.number_of_channels) recordB += np.uint16(self.buffer[i0:i1:self.number_of_channels] / - records_per_acquisition) + records_per_acquisition) magB, phaseB = self.fit(recordB) return magA, phaseA @@ -242,20 +242,15 @@ def fit(self, rec): # filter out higher freq component if self.filter == 0: - re_filtered = filter_win(re_wave, cutoff, - self.sample_rate, self.numtaps) - im_filtered = filter_win(im_wave, cutoff, - self.sample_rate, self.numtaps) + re_filtered = helpers.filter_win(re_wave, cutoff, + self.sample_rate, self.numtaps) + im_filtered = helpers.filter_win(im_wave, cutoff, + self.sample_rate, self.numtaps) elif self.filter == 1: - re_filtered = filter_ham(re_wave, cutoff, - self.sample_rate, self.numtaps) - im_filtered = filter_ham(im_wave, cutoff, - self.sample_rate, self.numtaps) - elif self.filter == 2: - re_filtered = filter_ls(re_wave, cutoff, - self.sample_rate, self.numtaps) - im_filtered = filter_ls(im_wave, cutoff, - self.sample_rate, self.numtaps) + re_filtered = helpers.filter_ls(re_wave, cutoff, + self.sample_rate, self.numtaps) + im_filtered = helpers.filter_ls(im_wave, cutoff, + self.sample_rate, self.numtaps) # apply int limits start = self.samples_delay @@ -272,12 +267,7 @@ def fit(self, rec): phase = np.angle(complex_num, deg=True) return mag, phase - -def filter_win(rec, cutoff, sample_rate, numtaps): - nyq_rate = sample_rate / 2. - fir_coef = signal.firwin(numtaps, cutoff / nyq_rate) - filtered_rec = signal.lfilter(fir_coef, 1.0, rec) - return filtered_rec + def sample_to_volt_u12(raw_samples, bps): # right_shift 16-bit sample by 4 to get 12 bit sample @@ -287,10 +277,10 @@ def sample_to_volt_u12(raw_samples, bps): code_zero = (1 << (bps - 1)) - 0.5 code_range = (1 << (bps - 1)) - 0.5 - # TODO(nataliejpg) make this not hard coded + # TODO(nataliejpg) make this not hard coded input_range_volts = 1 # Convert to volts volt_samples = np.float64(input_range_volts * - (shifted_samples - code_zero) / code_range) - - return volt_samples \ No newline at end of file + (shifted_samples - code_zero) / code_range) + + return volt_samples diff --git a/qcodes/instrument_drivers/AlazarTech/Single_controller.py b/qcodes/instrument_drivers/AlazarTech/Single_controller.py index eb84b087ce2c..ab3ede0a4212 100644 --- a/qcodes/instrument_drivers/AlazarTech/Single_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/Single_controller.py @@ -1,6 +1,7 @@ +import logging from .ATS import AcquisitionController import numpy as np -from scipy import signal +import qcodes.utils.helpers as helpers class HD_Controller(AcquisitionController): @@ -26,9 +27,9 @@ class HD_Controller(AcquisitionController): TODO(nataliejpg) make filter settings not hard coded """ - def __init__(self, name, alazar_name, demod_freq, samp_rate=500e6, - filt='win', chan_b=False, **kwargs): - filter_dict = {'win': 0, 'hamming': 1, 'ls': 2} + def __init__(self, name, alazar_name, demod_freq, samp_rate=5e8, filt='win', + numtaps=101, chan_b=False, **kwargs): + filter_dict = {'win': 0, 'ls': 1, 'dot': 2} self.demodulation_frequency = demod_freq self.sample_rate = samp_rate self.filter = filter_dict[filt] @@ -39,6 +40,8 @@ def __init__(self, name, alazar_name, demod_freq, samp_rate=500e6, self.records_per_buffer = 0 self.buffers_per_acquisition = 0 self.number_of_channels = 2 + self.samples_delay = None + self.samples_time = None self.cos_list = None self.sin_list = None self.buffer = None @@ -58,6 +61,45 @@ def update_acquisitionkwargs(self, **kwargs): :param kwargs: :return: """ + samples_per_record = kwargs['samples_per_record'] + sample_rate = self.sample_rate + + if 'int_delay' in kwargs: + int_delay = kwargs['int_delay'] + samp_delay = int_delay * sample_rate + samples_delay_min = (self.numtaps - 1) + if samp_delay < samples_delay_min: + int_delay_min = samples_delay_min / sample_rate + Warning( + 'delay is less than recommended for filter choice: ' + '(expect delay >= {}'.format(int_delay_min)) + else: + samp_delay = self.numtaps - 1 + + if 'int_time' in kwargs: + int_time = kwargs['int_time'] + samp_time = int_time * sample_rate + samples_time_max = (samples_per_record - samp_delay) + oscilations_measured = int_time / self.demodulation_frequency + oversampling = sample_rate / (2 * self.demodulation_frequency) + if samp_time > samples_time_max: + int_time_max = samples_time_max / sample_rate + raise ValueError('int_time {} is longer than total_time - ' + 'delay ({})'.format(int_time, int_time_max)) + elif oscilations_measured < 10: + logging.warning('{} oscilations measured, recommend at ' + 'least 10: decrease sampling rate, take ' + 'more samples or increase demodulation ' + 'freq'.format(oscilations_measured)) + elif oversampling < 1: + logging.warning('oversampling rate is {}, recommend > 1: ' + 'increase sampling rate or decrease ' + 'demodulation frequency'.format(oversampling)) + else: + samp_time = samples_per_record - samp_delay + + self.samples_time = samp_time + self.samples_delay = samp_delay self.acquisitionkwargs.update(**kwargs) def do_acquisition(self): diff --git a/qcodes/utils/helpers.py b/qcodes/utils/helpers.py index 3afea8cf22bc..7ee83f5ea0af 100644 --- a/qcodes/utils/helpers.py +++ b/qcodes/utils/helpers.py @@ -10,6 +10,7 @@ from copy import deepcopy import numpy as np +from scipy import signal _tprint_times = {} @@ -415,3 +416,36 @@ def compare_dictionaries(dict_1, dict_2, else: dicts_equal = False return dicts_equal, dict_differences + + +def filter_win(rec, cutoff, sample_rate, numtaps, axis=-1): + """ + low pass filter, returns filtered signal using FIR window + filter + + inputs: + record to filter + cutoff frequency + sampling rate + number of frequency comppnents to use in the filer + axis of record to apply filter along + """ + nyq_rate = sample_rate / 2. + fir_coef = signal.firwin(numtaps, cutoff / nyq_rate) + filtered_rec = signal.lfilter(fir_coef, 1.0, rec, axis=axis) + return filtered_rec + + +def filter_ls(rec, cutoff, sample_rate, numtaps, axis=-1): + """ + low pass filter, returns filtered signal using FIR + least squared filter + + inputs: + record to filter + cutoff frequency + sampling rate + number of frequency comppnents to use in the filer + axis of record to apply filter along + """ + raise NotImplementedError From 3d1c76bd3af5ab411ecb2206ffe9935891ffc93e Mon Sep 17 00:00:00 2001 From: nataliejpg Date: Mon, 14 Nov 2016 18:31:54 +0100 Subject: [PATCH 042/180] undoing typos introduces in previous commit --- qcodes/instrument_drivers/AlazarTech/ATS.py | 2 +- qcodes/instrument_drivers/AlazarTech/ATS9360.py | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/ATS.py b/qcodes/instrument_drivers/AlazarTech/ATS.py index 0fe74979e39b..9d648593f1ee 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS.py @@ -540,7 +540,7 @@ def acquire(self, mode=None, samples_per_record=None, if (samples_per_record % buffers_per_acquisition != 0): logging.warning('buffers_per_acquisition is not a divisor of ' 'samples per record which it should be in ' - 's mode, rounding down in samples per buffer ' + 'Ts mode, rounding down in samples per buffer ' 'calculation') samples_per_buffer = int(samples_per_record / buffers_per_acquisition) diff --git a/qcodes/instrument_drivers/AlazarTech/ATS9360.py b/qcodes/instrument_drivers/AlazarTech/ATS9360.py index 448a1ce27a96..7afbaff1ff3a 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS9360.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS9360.py @@ -266,8 +266,6 @@ def __init__(self, name, **kwargs): value=1000, vals=validators.Ints(min_value=0)) - - model = self.get_idn()['model'] if model != 'ATS9360': raise Exception("The Alazar board kind is not 'ATS9360'," From bdb74c3370cdf576a3776ceb749e9f268d05b2b6 Mon Sep 17 00:00:00 2001 From: nataliejpg Date: Mon, 14 Nov 2016 18:58:28 +0100 Subject: [PATCH 043/180] fix int_delay and int_time bug in sample controller --- .../instrument_drivers/AlazarTech/Samp_controller.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/Samp_controller.py b/qcodes/instrument_drivers/AlazarTech/Samp_controller.py index ecccca78b027..4932cac0a1ef 100644 --- a/qcodes/instrument_drivers/AlazarTech/Samp_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/Samp_controller.py @@ -110,7 +110,7 @@ def update_acquisitionkwargs(self, **kwargs): sample_rate = self.sample_rate if 'int_delay' in kwargs: - int_delay = kwargs['int_delay'] + int_delay = kwargs.pop('int_delay') samp_delay = int_delay * sample_rate samples_delay_min = (self.numtaps - 1) if samp_delay < samples_delay_min: @@ -122,7 +122,7 @@ def update_acquisitionkwargs(self, **kwargs): samp_delay = self.numtaps - 1 if 'int_time' in kwargs: - int_time = kwargs['int_time'] + int_time = kwargs.pop('int_time') samp_time = int_time * sample_rate samples_time_max = (samples_per_record - samp_delay) oscilations_measured = int_time / self.demodulation_frequency @@ -145,7 +145,8 @@ def update_acquisitionkwargs(self, **kwargs): self.samples_time = samp_time self.samples_delay = samp_delay - + + self.acquisition.update_acquisition_kwargs(samp_time, **kwargs) def pre_start_capture(self): @@ -254,8 +255,8 @@ def fit(self, rec): # apply int limits start = self.samples_delay - if self.int_time: - end = self.int_time * self.sample_rate + start + if self.samples_time: + end = self.samples_time * self.sample_rate + start else: end = None re_limited = re_filtered[start:end] From e0d0a25919a961e3cca3862d1490eff1180a8935 Mon Sep 17 00:00:00 2001 From: nataliejpg Date: Mon, 14 Nov 2016 19:33:33 +0100 Subject: [PATCH 044/180] debugging silly mistakes --- .../AlazarTech/Samp_controller.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/Samp_controller.py b/qcodes/instrument_drivers/AlazarTech/Samp_controller.py index 4932cac0a1ef..8a109300c1af 100644 --- a/qcodes/instrument_drivers/AlazarTech/Samp_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/Samp_controller.py @@ -115,7 +115,7 @@ def update_acquisitionkwargs(self, **kwargs): samples_delay_min = (self.numtaps - 1) if samp_delay < samples_delay_min: int_delay_min = samples_delay_min / sample_rate - Warning( + logging.warning( 'delay is less than recommended for filter choice: ' '(expect delay >= {}'.format(int_delay_min)) else: @@ -125,7 +125,7 @@ def update_acquisitionkwargs(self, **kwargs): int_time = kwargs.pop('int_time') samp_time = int_time * sample_rate samples_time_max = (samples_per_record - samp_delay) - oscilations_measured = int_time / self.demodulation_frequency + oscilations_measured = int_time * self.demodulation_frequency oversampling = sample_rate / (2 * self.demodulation_frequency) if samp_time > samples_time_max: int_time_max = samples_time_max / sample_rate @@ -143,11 +143,11 @@ def update_acquisitionkwargs(self, **kwargs): else: samp_time = samples_per_record - samp_delay - self.samples_time = samp_time - self.samples_delay = samp_delay + self.samples_time = int(samp_time) + self.samples_delay = int(samp_delay) - self.acquisition.update_acquisition_kwargs(samp_time, **kwargs) + self.acquisition.update_acquisition_kwargs(self.samples_time, **kwargs) def pre_start_capture(self): """ @@ -253,10 +253,10 @@ def fit(self, rec): im_filtered = helpers.filter_ls(im_wave, cutoff, self.sample_rate, self.numtaps) - # apply int limits + # apply integration limits start = self.samples_delay if self.samples_time: - end = self.samples_time * self.sample_rate + start + end = int(self.samples_time * self.sample_rate) + start else: end = None re_limited = re_filtered[start:end] From 85f9f443df187e93d2c754b69e2bdc1c4f05f231 Mon Sep 17 00:00:00 2001 From: nataliejpg Date: Tue, 15 Nov 2016 10:00:56 +0100 Subject: [PATCH 045/180] sample controller working --- .../AlazarTech/Samp_controller.py | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/Samp_controller.py b/qcodes/instrument_drivers/AlazarTech/Samp_controller.py index 8a109300c1af..66b02977d469 100644 --- a/qcodes/instrument_drivers/AlazarTech/Samp_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/Samp_controller.py @@ -24,7 +24,7 @@ def __init__(self, name, instrument): self.setpoints = ((1,), (1,)) self.shapes = ((1,), (1,)) - def update_acquisition_kwargs(self, samp_time=None, **kwargs): + def update_acquisition_kwargs(self, samp_time, **kwargs): # needed to update config of the software parameter on sweep change # freq setpoints tuple as needs to be hashable for look up if samp_time: @@ -32,14 +32,14 @@ def update_acquisition_kwargs(self, samp_time=None, **kwargs): n = tuple(np.arange(npts)) self.setpoints = ((n,), (n,)) self.shapes = ((npts,), (npts,)) - elif 'samples_per_record' in kwargs: - npts = kwargs['samples_per_record'] - n = tuple(np.arange(npts)) - self.setpoints = ((n,), (n,)) - self.shapes = ((npts,), (npts,)) + # elif 'samples_per_record' in kwargs: + # npts = kwargs['samples_per_record'] + # n = tuple(np.arange(npts)) + # self.setpoints = ((n,), (n,)) + # self.shapes = ((npts,), (npts,)) else: raise ValueError( - 'samples_per_record or sample_num must be specified') + 'samp_time not specified') # updates dict to be used in acquisition get call self.acquisitionkwargs.update(**kwargs) @@ -82,9 +82,9 @@ def __init__(self, name, alazar_name, demod_freq, samp_rate=5e8, self.filter = filter_dict[filt] self.numtaps = numtaps self.chan_b = chan_b - self.samples_per_record = 0 - self.records_per_buffer = 0 - self.buffers_per_acquisition = 0 + self.samples_per_record = None + self.records_per_buffer = None + self.buffers_per_acquisition = None self.number_of_channels = 2 self.samples_delay = None self.samples_time = None @@ -130,7 +130,7 @@ def update_acquisitionkwargs(self, **kwargs): if samp_time > samples_time_max: int_time_max = samples_time_max / sample_rate raise ValueError('int_time {} is longer than total_time - ' - 'delay ({})'.format(int_time, int_time_max)) + 'delay: {}'.format(int_time, int_time_max)) elif oscilations_measured < 10: logging.warning('{} oscilations measured, recommend at ' 'least 10: decrease sampling rate, take ' @@ -255,10 +255,8 @@ def fit(self, rec): # apply integration limits start = self.samples_delay - if self.samples_time: - end = int(self.samples_time * self.sample_rate) + start - else: - end = None + end = start + self.samples_time + re_limited = re_filtered[start:end] im_limited = im_filtered[start:end] From 1b9f439718413237312f4da5f9126b3667c627f0 Mon Sep 17 00:00:00 2001 From: Natalie Pearson Date: Tue, 15 Nov 2016 11:13:15 +0100 Subject: [PATCH 046/180] update docstrings and clean up basic controller --- .../AlazarTech/Samp_controller.py | 58 +++++++++++-------- .../AlazarTech/basic_controller.py | 14 +++-- 2 files changed, 42 insertions(+), 30 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/Samp_controller.py b/qcodes/instrument_drivers/AlazarTech/Samp_controller.py index 66b02977d469..ee29f54936e5 100644 --- a/qcodes/instrument_drivers/AlazarTech/Samp_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/Samp_controller.py @@ -11,7 +11,7 @@ class SamplesParam(Parameter): HD_Samples_Controller (tested with ATS9360 board) for return of an array of sample data from the Alazar, averaged over records and buffers. - TODO(nataliejpg) fix setpoints/shapes horriblenesss + TODO(nataliejpg) refactor setpoints/shapes horriblenesss """ def __init__(self, name, instrument): @@ -32,11 +32,6 @@ def update_acquisition_kwargs(self, samp_time, **kwargs): n = tuple(np.arange(npts)) self.setpoints = ((n,), (n,)) self.shapes = ((npts,), (npts,)) - # elif 'samples_per_record' in kwargs: - # npts = kwargs['samples_per_record'] - # n = tuple(np.arange(npts)) - # self.setpoints = ((n,), (n,)) - # self.shapes = ((npts,), (npts,)) else: raise ValueError( 'samp_time not specified') @@ -61,16 +56,15 @@ class HD_Samples_Controller(AcquisitionController): can communicate with the Alazar demod_freq: the frequency of the software wave to be created samp_rate: the rate of sampling - filt: the filter to be used to filter out double freq component + filt: the filter to be used to filter out double freq component (win or ls) + numtaps: number of freq components used in the filter chan_b: whether there is also a second channel of data to be processed and returned **kwargs: kwargs are forwarded to the Instrument base class TODO(nataliejpg) fix sample rate problem TODO(nataliejpg) test filter options - TODO(nataliejpg) test mag phase logic TODO(nataliejpg) finish implementation of channel b option - TODO(nataliejpg) update docstrings :P TODO(nataliejpg) make demodulation freq a param """ @@ -101,8 +95,14 @@ def __init__(self, name, alazar_name, demod_freq, samp_rate=5e8, def update_acquisitionkwargs(self, **kwargs): """ - This method must be used to update the kwargs used for the acquisition - with the alazar_driver.acquire + Updates the kwargs to be used when + alazar_driver.acquire is called via a get call of the + acquisition SamplesParam. + + It is also used to set the limits on the selection of + samples returned (bounded by delay and integration time) + and update this information in the Samples Parameter. + :param kwargs: :return: """ @@ -145,13 +145,13 @@ def update_acquisitionkwargs(self, **kwargs): self.samples_time = int(samp_time) self.samples_delay = int(samp_delay) - - + self.acquisition.update_acquisition_kwargs(self.samples_time, **kwargs) def pre_start_capture(self): """ - See AcquisitionController + Called before capture start to update Acquisition Controller with + alazar acuisition params and set up software wave for demodulation. :return: """ alazar = self._get_alazar() @@ -176,23 +176,21 @@ def pre_acquire(self): See AcquisitionController :return: """ - # this could be used to start an Arbitrary Waveform Generator, etc... - # using this method ensures that the contents are executed AFTER the - # Alazar card starts listening for a trigger pulse pass def handle_buffer(self, data): """ - See AcquisitionController + Adds data from alazar to buffer (effectively averaging) :return: """ - # average over buffers self.buffer += data def post_acquire(self): """ - See AcquisitionController - :return: + Processes the data according to ATS9360 settings, splitting into + records and averaging over them, then applying demodulation fit + nb: currently only channel A + :return: samples_magnitude_array, samples_phase_array """ records_per_acquisition = (1. * self.buffers_per_acquisition * self.records_per_buffer) @@ -227,13 +225,19 @@ def post_acquire(self): return magA, phaseA def fit(self, rec): + """ + Applies volts conversion, demodulation fit, low bandpass filter + and integration limits to samples array + :return: samples_magnitude_array, samples_phase_array + """ + # convert rec to volts bps = self.board_info['bits_per_sample'] if bps == 12: volt_rec = sample_to_volt_u12(rec, bps) else: - Warning('sample to volt conversion does not exist for' - ' bps != 12, centered raw samples returned') + logging.warning('sample to volt conversion does not exist for' + ' bps != 12, centered raw samples returned') volt_rec = rec - np.mean(rec) # multiply with software wave @@ -256,7 +260,7 @@ def fit(self, rec): # apply integration limits start = self.samples_delay end = start + self.samples_time - + re_limited = re_filtered[start:end] im_limited = im_filtered[start:end] @@ -269,6 +273,12 @@ def fit(self, rec): def sample_to_volt_u12(raw_samples, bps): + """ + Applies volts conversion for 12 bit sample data stored + in 2 bytes + :return: samples_magnitude_array, samples_phase_array + """ + # right_shift 16-bit sample by 4 to get 12 bit sample shifted_samples = np.right_shift(raw_samples, 4) diff --git a/qcodes/instrument_drivers/AlazarTech/basic_controller.py b/qcodes/instrument_drivers/AlazarTech/basic_controller.py index 40adef46d9c1..b76309fb8881 100644 --- a/qcodes/instrument_drivers/AlazarTech/basic_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/basic_controller.py @@ -1,7 +1,7 @@ +import logging from .ATS import AcquisitionController import numpy as np from qcodes import Parameter -#from.acquistion_tools import sample_to_volt_u12 class SampleSweep(Parameter): @@ -147,12 +147,14 @@ def post_acquire(self): volt_rec_A = sample_to_volt_u12(recordA, bps) volt_rec_B = sample_to_volt_u12(recordB, bps) else: - Warning('sample to volt conversion does not exist for bps != 12, raw samples returned') + logging.warning('sample to volt conversion does not exist for bps ' + '!= 12, raw samples centered on 0 returned') volt_rec_A = recordA - np.mean(recordA) volt_rec_B = recordB - np.mean(recordB) return volt_rec_A, volt_rec_B + def sample_to_volt_u12(raw_samples, bps): # right_shift 16-bit sample by 4 to get 12 bit sample shifted_samples = np.right_shift(raw_samples, 4) @@ -161,10 +163,10 @@ def sample_to_volt_u12(raw_samples, bps): code_zero = (1 << (bps - 1)) - 0.5 code_range = (1 << (bps - 1)) - 0.5 - # TODO(nataliejpg) make this not hard coded + # TODO(nataliejpg) make this not hard coded input_range_volts = 1 # Convert to volts volt_samples = np.float64(input_range_volts * - (shifted_samples - code_zero) / code_range) - - return volt_samples \ No newline at end of file + (shifted_samples - code_zero) / code_range) + + return volt_samples From c7982049ba1593eb31f65c48eb985bcb64c94169 Mon Sep 17 00:00:00 2001 From: Natalie Pearson Date: Tue, 15 Nov 2016 12:27:29 +0100 Subject: [PATCH 047/180] extend fixes to rec and single controllers --- .../AlazarTech/Rec_controller.py | 240 ++++++++++++------ .../AlazarTech/Samp_controller.py | 23 +- .../AlazarTech/Single_controller.py | 207 ++++++++------- qcodes/utils/helpers.py | 14 + 4 files changed, 299 insertions(+), 185 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/Rec_controller.py b/qcodes/instrument_drivers/AlazarTech/Rec_controller.py index 66eb8af1a9b2..e92de3e40a59 100644 --- a/qcodes/instrument_drivers/AlazarTech/Rec_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/Rec_controller.py @@ -1,7 +1,8 @@ +import logging from .ATS import AcquisitionController import numpy as np -from scipy import signal from qcodes import Parameter +import qcodes.utils.helpers as helpers class RecordsParam(Parameter): @@ -45,8 +46,7 @@ def get(self): class HD_Records_Controller(AcquisitionController): """ - seq 0 - This is the Acquisition Controller class which works with the ATS9360, + This is the Acquisition Controller class which works with the ATS9360, averaging over buffers and records and demodulating with a software reference signal, returning the samples. args: @@ -56,31 +56,35 @@ class HD_Records_Controller(AcquisitionController): demod_freq: the frequency of the software wave to be created samp_rate: the rate of sampling filt: the filter to be used to filter out double freq component + numtaps: number of freq components used in the filter chan_b: whether there is also a second channel of data to be processed and returned **kwargs: kwargs are forwarded to the Instrument base class TODO(nataliejpg) fix sample rate problem - TODO(nataliejpg) add filter options - TODO(nataliejpg) test mag phase logic - TODO(nataliejpg) implement record B thinking + TODO(nataliejpg) test filter options + TODO(nataliejpg) finish implementation of channel b option + TODO(nataliejpg) make demodulation freq a param """ - def __init__(self, name, alazar_name, demod_freq, samp_rate=500e6, - filt='win', chan_b=False, **kwargs): - filter_dict = {'win': 0, 'hamming': 1, 'ls': 2} + def __init__(self, name, alazar_name, demod_freq, samp_rate=5e8, + filt='win', numtaps=101, chan_b=False, **kwargs): + filter_dict = {'win': 0, 'ls': 1, 'dot': 2} self.demodulation_frequency = demod_freq self.sample_rate = samp_rate self.filter = filter_dict[filt] - #self.chan_b = chan_b - self.sample_rate = samp_rate - self.samples_per_record = 0 - self.records_per_buffer = 0 - self.buffers_per_acquisition = 0 + self.numtaps = numtaps + self.chan_b = chan_b + self.samples_per_record = None + self.records_per_buffer = None + self.buffers_per_acquisition = None self.number_of_channels = 2 + self.samples_delay = None + self.samples_time = None self.cos_mat = None self.sin_mat = None self.buffer = None + self.board_info = None # make a call to the parent class and by extension, # create the parameter structure of this class super().__init__(name, alazar_name, **kwargs) @@ -90,32 +94,84 @@ def __init__(self, name, alazar_name, demod_freq, samp_rate=500e6, def update_acquisitionkwargs(self, **kwargs): """ - This method must be used to update the kwargs used for the acquisition - with the alazar_driver.acquire + Updates the kwargs to be used when + alazar_driver.acquire is called via a get call of the + acquisition RecordsParam. + + It is also used to set the limits on the selection of + samples used (bounded by delay and integration time) + :param kwargs: :return: """ + samples_per_record = kwargs['samples_per_record'] + sample_rate = self.sample_rate + + if 'int_delay' in kwargs: + int_delay = kwargs.pop('int_delay') + samp_delay = int_delay * sample_rate + samples_delay_min = (self.numtaps - 1) + if samp_delay < samples_delay_min: + int_delay_min = samples_delay_min / sample_rate + logging.warning( + 'delay is less than recommended for filter choice: ' + '(expect delay >= {}'.format(int_delay_min)) + else: + samp_delay = self.numtaps - 1 + + if 'int_time' in kwargs: + int_time = kwargs.pop('int_time') + samp_time = int_time * sample_rate + samples_time_max = (samples_per_record - samp_delay) + oscilations_measured = int_time * self.demodulation_frequency + oversampling = sample_rate / (2 * self.demodulation_frequency) + if samp_time > samples_time_max: + int_time_max = samples_time_max / sample_rate + raise ValueError('int_time {} is longer than total_time - ' + 'delay: {}'.format(int_time, int_time_max)) + elif oscilations_measured < 10: + logging.warning('{} oscilations measured, recommend at ' + 'least 10: decrease sampling rate, take ' + 'more samples or increase demodulation ' + 'freq'.format(oscilations_measured)) + elif oversampling < 1: + logging.warning('oversampling rate is {}, recommend > 1: ' + 'increase sampling rate or decrease ' + 'demodulation frequency'.format(oversampling)) + else: + samp_time = samples_per_record - samp_delay + + self.samples_time = int(samp_time) + self.samples_delay = int(samp_delay) + self.acquisition.update_acquisition_kwargs(**kwargs) def pre_start_capture(self): """ - See AcquisitionController + Called before capture start to update Acquisition Controller with + alazar acquisition params and set up software wave for demodulation. + + sine and cosine matrices have shape (samples * records). + :return: """ alazar = self._get_alazar() self.samples_per_record = alazar.samples_per_record.get() self.records_per_buffer = alazar.records_per_buffer.get() self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() + self.board_info = alazar.get_idn() self.buffer = np.zeros(self.samples_per_record * self.records_per_buffer * - self.number_of_channels) + self.number_of_channels, + dtype=np.uint16) - integer_list = np.arange(self.samples_per_record) + integer_list = np.arange(self.samples_per_record, dtype=np.uint16) angle_list = (2 * np.pi * self.demodulation_frequency / self.sample_rate * integer_list) cos_list = np.cos(angle_list).reshape(self.samples_per_record, 1) sin_list = np.sin(angle_list).reshape(self.samples_per_record, 1) + self.cos_mat = np.kron(np.ones((1, self.records_per_buffer)), cos_list) self.sin_mat = np.kron(np.ones((1, self.records_per_buffer)), sin_list) @@ -124,97 +180,121 @@ def pre_acquire(self): See AcquisitionController :return: """ - # this could be used to start an Arbitrary Waveform Generator, etc... - # using this method ensures that the contents are executed AFTER the - # Alazar card starts listening for a trigger pulse pass def handle_buffer(self, data): """ - See AcquisitionController + Adds data from alazar to buffer (effectively averaging) :return: """ self.buffer += data def post_acquire(self): """ - See AcquisitionController - :return: + Processes the data according to ATS9360 settings, splitting into + records and averaging over them, then applying demodulation fit + nb: currently only channel A + :return: samples_magnitude_array, samples_phase_array """ + records_per_acquisition = (self.buffers_per_acquisition * + self.records_per_buffer) # for ATS9360 samples are arranged in the buffer as follows: # S00A, S00B, S01A, S01B...S10A, S10B, S11A, S11B... # where SXYZ is record X, sample Y, channel Z. - # reshapes date to be (samples * records) - recordA = np.zeros((self.samples_per_record, self.records_per_buffer)) - # recordB = np.zeros((self.samples_per_record, self.records_per_buffer))\ + # break buffer up into records and shapes to be (samples * records) + recordA = np.zeros((self.samples_per_record, self.records_per_buffer), + dtype=np.uint16) for i in range(self.records_per_buffer): - i0 = i * self.number_of_channels * self.samples_per_record - i1 = i0 + self.number_of_channels * self.samples_per_record - recordA[:, i] = (self.buffer[i0:i1:self.number_of_channels] / - self.buffers_per_acquisition) - # recordB[:, i] = self.buffer[1:full_rec_length:step] / buffers - # return averaged chan A data (records) + i0 = (i * self.samples_per_record * self.number_of_channels) + i1 = (i0 + self.samples_per_record * self.number_of_channels) + recordA += np.uint16(self.buffer[i0:i1:self.number_of_channels] / + records_per_acquisition) + recordA[:, i] = np.uint16((self.buffer[i0:i1:self.number_of_channels] / + self.buffers_per_acquisition)) + + # do demodulation magA, phaseA = self.fit(recordA) + # same for chan b + if self.chan_b: + raise NotImplementedError('chan b code not complete') + return magA, phaseA def fit(self, rec): - # center rec around 0 - rec = rec - np.mean(rec) + """ + Applies volts conversion, demodulation fit, low bandpass filter + and integration limits to samples * records array + :return: records_magnitude_array, records_phase_array + """ + + # convert rec to volts + bps = self.board_info['bits_per_sample'] + if bps == 12: + volt_rec = sample_to_volt_u12(rec, bps) + else: + logging.warning('sample to volt conversion does not exist for' + ' bps != 12, centered raw samples returned') + volt_rec = rec - np.mean(rec, 0) # multiply with software wave - re_wave = np.multiply(rec, self.cos_mat) - im_wave = np.multiply(rec, self.sin_mat) - cutoff = self.demodulation_frequency - numtaps = 30 - axis = 0 + re_wave = np.multiply(volt_rec, self.cos_mat) + im_wave = np.multiply(volt_rec, self.sin_mat) + cutoff = self.demodulation_frequency / 10 + ax = 0 - # filter out double freq component to obtian constant term + # filter out higher freq component if self.filter == 0: - RePart = self.filter_win(re_wave, numtaps, cutoff, axis=axis) - ImPart = self.filter_win(im_wave, numtaps, cutoff, axis=axis) + re_filtered = helpers.filter_win(re_wave, cutoff, self.sample_rate, + self.numtaps, axis=ax) + im_filtered = helpers.filter_win(im_wave, cutoff, self.sample_rate, + self.numtaps, axis=ax) elif self.filter == 1: - RePart = self.filter_hamming(re_wave, numtaps, cutoff, axis=axis) - ImPart = self.filter_hamming(im_wave, numtaps, cutoff, axis=axis) + re_filtered = helpers.filter_ls(re_wave, cutoff, self.sample_rate, + self.numtaps, axis=ax) + im_filtered = helpers.filter_ls(im_wave, cutoff, self.sample_rate, + self.numtaps, axis=ax) elif self.filter == 2: - RePart = self.filter_ls(re_wave, numtaps, cutoff, axis, axis=axis) - ImPart = self.filter_ls(im_wave, numtaps, cutoff, axis, axis=axis) + re_filtered = helpers.filter_dot(re_wave, cutoff, self.sample_rate, + self.numtaps, axis=ax) + im_filtered = helpers.filter_dot(im_wave, cutoff, self.sample_rate, + self.numtaps, axis=ax) + + # apply integration limits + start = self.samples_delay + end = start + self.samples_time - # convert to magnitude and phase data and average over samples - # data returned is (records) - complex_mat = RePart + ImPart * 1j - mag = np.mean(2 * abs(complex_mat), axis=0) - phase = np.mean(np.angle(complex_mat, deg=True), axis=0) + re_limited = re_filtered[start:end, :] + im_limited = im_filtered[start:end, :] + + # convert to magnitude and phase + complex_num = re_limited + im_limited * 1j + mag = np.mean(abs(complex_num), 0) + phase = np.mean(np.angle(complex_num, deg=True), 0) return mag, phase - def filter_hamming(self, rec, numtaps, cutoff, axis=-1): - sample_rate = self.sample_rate - nyq_rate = sample_rate / 2. - fir_coef = signal.firwin(numtaps, - cutoff / nyq_rate, - window="hamming") - filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec, axis=axis) - return filtered_rec - - def filter_win(self, rec, numtaps, cutoff, axis=-1): - sample_rate = self.sample_rate - nyq_rate = sample_rate / 2. - fir_coef = signal.firwin(numtaps, - cutoff / nyq_rate) - filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec, axis=axis) - return filtered_rec - def filter_ls(self, rec, numtaps, cutoff, axis=-1): - sample_rate = self.sample_rate - nyq_rate = sample_rate / 2. - bands = [0, cutoff / nyq_rate, cutoff / nyq_rate, 1] - desired = [1, 1, 0, 0] - fir_coef = signal.firls(numtaps, - bands, - desired, - nyq=nyq_rate) - filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec, axis=axis) - return filtered_rec +def sample_to_volt_u12(raw_samples, bps): + """ + Applies volts conversion for 12 bit sample data stored + in 2 bytes + :return: samples_magnitude_array, samples_phase_array + """ + + # right_shift 16-bit sample by 4 to get 12 bit sample + shifted_samples = np.right_shift(raw_samples, 4) + + # Alazar calibration + code_zero = (1 << (bps - 1)) - 0.5 + code_range = (1 << (bps - 1)) - 0.5 + + # TODO(nataliejpg) make this not hard coded + input_range_volts = 1 + # Convert to volts + volt_samples = np.float64(input_range_volts * + (shifted_samples - code_zero) / code_range) + + return volt_samples diff --git a/qcodes/instrument_drivers/AlazarTech/Samp_controller.py b/qcodes/instrument_drivers/AlazarTech/Samp_controller.py index ee29f54936e5..ab6b15697f10 100644 --- a/qcodes/instrument_drivers/AlazarTech/Samp_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/Samp_controller.py @@ -151,7 +151,7 @@ def update_acquisitionkwargs(self, **kwargs): def pre_start_capture(self): """ Called before capture start to update Acquisition Controller with - alazar acuisition params and set up software wave for demodulation. + alazar acquisition params and set up software wave for demodulation. :return: """ alazar = self._get_alazar() @@ -192,15 +192,13 @@ def post_acquire(self): nb: currently only channel A :return: samples_magnitude_array, samples_phase_array """ - records_per_acquisition = (1. * self.buffers_per_acquisition * + records_per_acquisition = (self.buffers_per_acquisition * self.records_per_buffer) # for ATS9360 samples are arranged in the buffer as follows: # S00A, S00B, S01A, S01B...S10A, S10B, S11A, S11B... # where SXYZ is record X, sample Y, channel Z. # break buffer up into records and averages over them - records_per_acquisition = (self.buffers_per_acquisition * - self.records_per_buffer) recordA = np.zeros(self.samples_per_record, dtype=np.uint16) for i in range(self.records_per_buffer): i0 = (i * self.samples_per_record * self.number_of_channels) @@ -213,14 +211,15 @@ def post_acquire(self): # same for chan b if self.chan_b: - recordB = np.zeros(self.samples_per_record, dtype=np.uint16) - for i in range(self.records_per_buffer): - i0 = (i * self.samples_per_record * - self.number_of_channels + 1) - i1 = (i0 + self.samples_per_record * self.number_of_channels) - recordB += np.uint16(self.buffer[i0:i1:self.number_of_channels] / - records_per_acquisition) - magB, phaseB = self.fit(recordB) + raise NotImplementedError('chan b code not complete') + # recordB = np.zeros(self.samples_per_record, dtype=np.uint16) + # for i in range(self.records_per_buffer): + # i0 = (i * self.samples_per_record * + # self.number_of_channels + 1) + # i1 = (i0 + self.samples_per_record * self.number_of_channels) + # recordB += np.uint16(self.buffer[i0:i1:self.number_of_channels] / + # records_per_acquisition) + # magB, phaseB = self.fit(recordB) return magA, phaseA diff --git a/qcodes/instrument_drivers/AlazarTech/Single_controller.py b/qcodes/instrument_drivers/AlazarTech/Single_controller.py index ab3ede0a4212..bbff68c5267c 100644 --- a/qcodes/instrument_drivers/AlazarTech/Single_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/Single_controller.py @@ -22,29 +22,29 @@ class HD_Controller(AcquisitionController): TODO(nataliejpg) fix sample rate problem TODO(nataliejpg) test filter options - TODO(nataliejpg) test mag phase logic TODO(nataliejpg) finish implementation of channel b option - TODO(nataliejpg) make filter settings not hard coded + TODO(nataliejpg) make demodulation freq a param """ - def __init__(self, name, alazar_name, demod_freq, samp_rate=5e8, filt='win', - numtaps=101, chan_b=False, **kwargs): + def __init__(self, name, alazar_name, demod_freq, samp_rate=5e8, + filt='win', numtaps=101, chan_b=False, **kwargs): filter_dict = {'win': 0, 'ls': 1, 'dot': 2} self.demodulation_frequency = demod_freq self.sample_rate = samp_rate self.filter = filter_dict[filt] - self.chan_b = chan_b + self.numtaps = numtaps self.acquisitionkwargs = {} - self.sample_rate = samp_rate - self.samples_per_record = 0 - self.records_per_buffer = 0 - self.buffers_per_acquisition = 0 + self.chan_b = chan_b + self.samples_per_record = None + self.records_per_buffer = None + self.buffers_per_acquisition = None self.number_of_channels = 2 self.samples_delay = None self.samples_time = None self.cos_list = None self.sin_list = None self.buffer = None + self.board_info = None # make a call to the parent class and by extension, # create the parameter structure of this class super().__init__(name, alazar_name, **kwargs) @@ -56,8 +56,12 @@ def __init__(self, name, alazar_name, demod_freq, samp_rate=5e8, filt='win', def update_acquisitionkwargs(self, **kwargs): """ - This method must be used to update the kwargs used for the acquisition - with the alazar_driver.acquire + Updates the kwargs to be used when + alazar_driver.acquire is called. + + It is also used to set the limits on the selection of + samples used (bounded by delay and integration time) + :param kwargs: :return: """ @@ -65,27 +69,27 @@ def update_acquisitionkwargs(self, **kwargs): sample_rate = self.sample_rate if 'int_delay' in kwargs: - int_delay = kwargs['int_delay'] + int_delay = kwargs.pop('int_delay') samp_delay = int_delay * sample_rate samples_delay_min = (self.numtaps - 1) if samp_delay < samples_delay_min: int_delay_min = samples_delay_min / sample_rate - Warning( + logging.warning( 'delay is less than recommended for filter choice: ' '(expect delay >= {}'.format(int_delay_min)) else: samp_delay = self.numtaps - 1 if 'int_time' in kwargs: - int_time = kwargs['int_time'] + int_time = kwargs.pop('int_time') samp_time = int_time * sample_rate samples_time_max = (samples_per_record - samp_delay) - oscilations_measured = int_time / self.demodulation_frequency + oscilations_measured = int_time * self.demodulation_frequency oversampling = sample_rate / (2 * self.demodulation_frequency) if samp_time > samples_time_max: int_time_max = samples_time_max / sample_rate raise ValueError('int_time {} is longer than total_time - ' - 'delay ({})'.format(int_time, int_time_max)) + 'delay: {}'.format(int_time, int_time_max)) elif oscilations_measured < 10: logging.warning('{} oscilations measured, recommend at ' 'least 10: decrease sampling rate, take ' @@ -98,8 +102,9 @@ def update_acquisitionkwargs(self, **kwargs): else: samp_time = samples_per_record - samp_delay - self.samples_time = samp_time - self.samples_delay = samp_delay + self.samples_time = int(samp_time) + self.samples_delay = int(samp_delay) + self.acquisitionkwargs.update(**kwargs) def do_acquisition(self): @@ -108,24 +113,27 @@ def do_acquisition(self): acquisiion parameter of this instrument :return: """ - value = self._get_alazar().acquire(acquisition_controller=self, - **self.acquisitionkwargs) - return value + values = self._get_alazar().acquire(acquisition_controller=self, + **self.acquisitionkwargs) + return values def pre_start_capture(self): """ - See AcquisitionController + Called before capture start to update Acquisition Controller with + alazar acquisition params and set up software wave for demodulation. :return: """ alazar = self._get_alazar() self.samples_per_record = alazar.samples_per_record.get() self.records_per_buffer = alazar.records_per_buffer.get() self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() + self.board_info = alazar.get_idn() self.buffer = np.zeros(self.samples_per_record * self.records_per_buffer * - self.number_of_channels) + self.number_of_channels, + dtype=np.uint16) - integer_list = np.arange(self.samples_per_record) + integer_list = np.arange(self.samples_per_record, dtype=np.uint16) angle_list = (2 * np.pi * self.demodulation_frequency / self.sample_rate * integer_list) @@ -137,111 +145,124 @@ def pre_acquire(self): See AcquisitionController :return: """ - # this could be used to start an Arbitrary Waveform Generator, etc... - # using this method ensures that the contents are executed AFTER the - # Alazar card starts listening for a trigger pulse pass def handle_buffer(self, data): """ - See AcquisitionController + Adds data from alazar to buffer (effectively averaging) :return: """ - # average over buffers self.buffer += data def post_acquire(self): """ - See AcquisitionController - :return: + Processes the data according to ATS9360 settings, splitting into + records and averaging over them, then applying demodulation fit + nb: currently only channel A + :return: samples_magnitude_array, samples_phase_array """ - records_per_acquisition = (1. * self.buffers_per_acquisition * + records_per_acquisition = (self.buffers_per_acquisition * self.records_per_buffer) # for ATS9360 samples are arranged in the buffer as follows: # S00A, S00B, S01A, S01B...S10A, S10B, S11A, S11B... # where SXYZ is record X, sample Y, channel Z. - # breaks buffer up into records and averages over them - # leaving data in form (samples) - records_per_acquisition = (self.buffers_per_acquisition * - self.records_per_buffer) - recordA = np.zeros(self.samples_per_record) + # break buffer up into records and averages over them + recordA = np.zeros(self.samples_per_record, dtype=np.uint16) for i in range(self.records_per_buffer): i0 = (i * self.samples_per_record * self.number_of_channels) i1 = (i0 + self.samples_per_record * self.number_of_channels) - recordA += (self.buffer[i0:i1:self.number_of_channels] / - records_per_acquisition) + recordA += np.uint16(self.buffer[i0:i1:self.number_of_channels] / + records_per_acquisition) - # demodulate and average data to be single point + # do demodulation magA, phaseA = self.fit(recordA) - # same for B + # same for chan b if self.chan_b: - recordB = np.zeros(self.samples_per_record) - for i in range(self.records_per_buffer): - i0 = (i * self.samples_per_record * self.number_of_channels + 1) - i1 = (i0 + self.samples_per_record * self.number_of_channels) - recordB += (self.buffer[i0:i1:self.number_of_channels] / - records_per_acquisition) - magB, phaseB = self.fit(recordB) - - # return averaged chan A data (1,1) + raise NotImplementedError('chan b code not complete') + # recordB = np.zeros(self.samples_per_record, dtype=np.uint16) + # for i in range(self.records_per_buffer): + # i0 = (i * self.samples_per_record * + # self.number_of_channels + 1) + # i1 = (i0 + self.samples_per_record * self.number_of_channels) + # recordB += np.uint16(self.buffer[i0:i1:self.number_of_channels] / + # records_per_acquisition) + # magB, phaseB = self.fit(recordB) + return magA, phaseA def fit(self, rec): - # center rec around 0 - rec = rec - np.mean(rec) + """ + Applies volts conversion, demodulation fit, low bandpass filter + and integration limits to samples array and averages + :return: magnitude, phase + """ + + # convert rec to volts + bps = self.board_info['bits_per_sample'] + if bps == 12: + volt_rec = sample_to_volt_u12(rec, bps) + else: + logging.warning('sample to volt conversion does not exist for' + ' bps != 12, centered raw samples returned') + volt_rec = rec - np.mean(rec) # multiply with software wave - re_wave = np.multiply(rec, self.cos_list) - im_wave = np.multiply(rec, self.sin_list) - cutoff = self.demodulation_frequency - numtaps = 30 + re_wave = np.multiply(volt_rec, self.cos_list) + im_wave = np.multiply(volt_rec, self.sin_list) + cutoff = self.demodulation_frequency / 10 # filter out higher freq component if self.filter == 0: - RePart = self.filter_win(re_wave, numtaps, cutoff) - ImPart = self.filter_win(im_wave, numtaps, cutoff) + re_filtered = helpers.filter_win(re_wave, cutoff, + self.sample_rate, self.numtaps) + im_filtered = helpers.filter_win(im_wave, cutoff, + self.sample_rate, self.numtaps) elif self.filter == 1: - RePart = self.filter_hamming(re_wave, numtaps, cutoff) - ImPart = self.filter_hamming(im_wave, numtaps, cutoff) + re_filtered = helpers.filter_ls(re_wave, cutoff, + self.sample_rate, self.numtaps) + im_filtered = helpers.filter_ls(im_wave, cutoff, + self.sample_rate, self.numtaps) elif self.filter == 2: - RePart = self.filter_ls(re_wave, numtaps, cutoff) - ImPart = self.filter_ls(im_wave, numtaps, cutoff) + re_filtered = helpers.filter_dot(re_wave, cutoff, + self.sample_rate, self.numtaps) + im_filtered = helpers.filter_dot(im_wave, cutoff, + self.sample_rate, self.numtaps) + + # apply integration limits + start = self.samples_delay + end = start + self.samples_time - # convert to magnitude and phase data and average over samples - # data returned is single point - complex_num = RePart + ImPart * 1j - mag = np.mean(2 * abs(complex_num)) + re_limited = re_filtered[start:end] + im_limited = im_filtered[start:end] + + # convert to magnitude and phase + complex_num = re_limited + im_limited * 1j + mag = np.mean(abs(complex_num)) phase = np.mean(np.angle(complex_num, deg=True)) return mag, phase - def filter_hamming(self, rec, numtaps, cutoff): - sample_rate = self.sample_rate - nyq_rate = sample_rate / 2. - fir_coef = signal.firwin(numtaps, - cutoff / nyq_rate, - window="hamming") - filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec) - return filtered_rec - - def filter_win(self, rec, numtaps, cutoff): - sample_rate = self.sample_rate - nyq_rate = sample_rate / 2. - fir_coef = signal.firwin(numtaps, - cutoff / nyq_rate) - filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec) - return filtered_rec - def filter_ls(self, rec, numtaps, cutoff): - sample_rate = self.sample_rate - nyq_rate = sample_rate / 2. - bands = [0, cutoff / nyq_rate, cutoff / nyq_rate, 1] - desired = [1, 1, 0, 0] - fir_coef = signal.firls(numtaps, - bands, - desired, - nyq=nyq_rate) - filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec) - return filtered_rec +def sample_to_volt_u12(raw_samples, bps): + """ + Applies volts conversion for 12 bit sample data stored + in 2 bytes + :return: samples_magnitude_array, samples_phase_array + """ + + # right_shift 16-bit sample by 4 to get 12 bit sample + shifted_samples = np.right_shift(raw_samples, 4) + + # Alazar calibration + code_zero = (1 << (bps - 1)) - 0.5 + code_range = (1 << (bps - 1)) - 0.5 + + # TODO(nataliejpg) make this not hard coded + input_range_volts = 1 + # Convert to volts + volt_samples = np.float64(input_range_volts * + (shifted_samples - code_zero) / code_range) + + return volt_samples diff --git a/qcodes/utils/helpers.py b/qcodes/utils/helpers.py index 7ee83f5ea0af..12f45675a2f0 100644 --- a/qcodes/utils/helpers.py +++ b/qcodes/utils/helpers.py @@ -449,3 +449,17 @@ def filter_ls(rec, cutoff, sample_rate, numtaps, axis=-1): axis of record to apply filter along """ raise NotImplementedError + +def filter_dot(rec, cutoff, sample_rate, numtaps, axis=-1): + """ + low pass filter, returns filtered signal using FIR + least squared filter + + inputs: + record to filter + cutoff frequency + sampling rate + number of frequency comppnents to use in the filer + axis of record to apply filter along + """ + raise NotImplementedError \ No newline at end of file From fb888a41a258872af542c047580223cca13eb5a8 Mon Sep 17 00:00:00 2001 From: Natalie Pearson Date: Tue, 15 Nov 2016 14:36:32 +0100 Subject: [PATCH 048/180] general tidying --- .../AlazarTech/Rec_controller.py | 29 +++++++++---------- .../AlazarTech/Samp_controller.py | 18 ++++++------ .../AlazarTech/Single_controller.py | 6 ++-- 3 files changed, 25 insertions(+), 28 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/Rec_controller.py b/qcodes/instrument_drivers/AlazarTech/Rec_controller.py index e92de3e40a59..c8220aed56cd 100644 --- a/qcodes/instrument_drivers/AlazarTech/Rec_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/Rec_controller.py @@ -2,7 +2,7 @@ from .ATS import AcquisitionController import numpy as np from qcodes import Parameter -import qcodes.utils.helpers as helpers +from qcodes.utils.helpers import filter_win, filter_ls class RecordsParam(Parameter): @@ -211,8 +211,9 @@ def post_acquire(self): i1 = (i0 + self.samples_per_record * self.number_of_channels) recordA += np.uint16(self.buffer[i0:i1:self.number_of_channels] / records_per_acquisition) - recordA[:, i] = np.uint16((self.buffer[i0:i1:self.number_of_channels] / - self.buffers_per_acquisition)) + recordA[:, i] = np.uint16( + self.buffer[i0:i1:self.number_of_channels] / + self.buffers_per_acquisition) # do demodulation magA, phaseA = self.fit(recordA) @@ -247,20 +248,18 @@ def fit(self, rec): # filter out higher freq component if self.filter == 0: - re_filtered = helpers.filter_win(re_wave, cutoff, self.sample_rate, - self.numtaps, axis=ax) - im_filtered = helpers.filter_win(im_wave, cutoff, self.sample_rate, - self.numtaps, axis=ax) + re_filtered = filter_win(re_wave, cutoff, self.sample_rate, + self.numtaps, axis=ax) + im_filtered = filter_win(im_wave, cutoff, self.sample_rate, + self.numtaps, axis=ax) elif self.filter == 1: - re_filtered = helpers.filter_ls(re_wave, cutoff, self.sample_rate, - self.numtaps, axis=ax) - im_filtered = helpers.filter_ls(im_wave, cutoff, self.sample_rate, - self.numtaps, axis=ax) + re_filtered = filter_ls(re_wave, cutoff, self.sample_rate, + self.numtaps, axis=ax) + im_filtered = filter_ls(im_wave, cutoff, self.sample_rate, + self.numtaps, axis=ax) elif self.filter == 2: - re_filtered = helpers.filter_dot(re_wave, cutoff, self.sample_rate, - self.numtaps, axis=ax) - im_filtered = helpers.filter_dot(im_wave, cutoff, self.sample_rate, - self.numtaps, axis=ax) + re_filtered = re_wave + im_filtered = im_wave # apply integration limits start = self.samples_delay diff --git a/qcodes/instrument_drivers/AlazarTech/Samp_controller.py b/qcodes/instrument_drivers/AlazarTech/Samp_controller.py index ab6b15697f10..17124f4e380e 100644 --- a/qcodes/instrument_drivers/AlazarTech/Samp_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/Samp_controller.py @@ -2,7 +2,7 @@ from .ATS import AcquisitionController import numpy as np from qcodes import Parameter -import qcodes.utils.helpers as helpers +from qcodes.utils.helpers import filter_win, filter_ls class SamplesParam(Parameter): @@ -246,15 +246,15 @@ def fit(self, rec): # filter out higher freq component if self.filter == 0: - re_filtered = helpers.filter_win(re_wave, cutoff, - self.sample_rate, self.numtaps) - im_filtered = helpers.filter_win(im_wave, cutoff, - self.sample_rate, self.numtaps) + re_filtered = filter_win(re_wave, cutoff, + self.sample_rate, self.numtaps) + im_filtered = filter_win(im_wave, cutoff, + self.sample_rate, self.numtaps) elif self.filter == 1: - re_filtered = helpers.filter_ls(re_wave, cutoff, - self.sample_rate, self.numtaps) - im_filtered = helpers.filter_ls(im_wave, cutoff, - self.sample_rate, self.numtaps) + re_filtered = filter_ls(re_wave, cutoff, + self.sample_rate, self.numtaps) + im_filtered = filter_ls(im_wave, cutoff, + self.sample_rate, self.numtaps) # apply integration limits start = self.samples_delay diff --git a/qcodes/instrument_drivers/AlazarTech/Single_controller.py b/qcodes/instrument_drivers/AlazarTech/Single_controller.py index bbff68c5267c..680b83aa9eaf 100644 --- a/qcodes/instrument_drivers/AlazarTech/Single_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/Single_controller.py @@ -225,10 +225,8 @@ def fit(self, rec): im_filtered = helpers.filter_ls(im_wave, cutoff, self.sample_rate, self.numtaps) elif self.filter == 2: - re_filtered = helpers.filter_dot(re_wave, cutoff, - self.sample_rate, self.numtaps) - im_filtered = helpers.filter_dot(im_wave, cutoff, - self.sample_rate, self.numtaps) + re_filtered = re_wave + im_filtered = im_wave # apply integration limits start = self.samples_delay From 75d840baaa45bf3ebaa05bcb402ce5be465e1469 Mon Sep 17 00:00:00 2001 From: nataliejpg Date: Tue, 15 Nov 2016 19:20:06 +0100 Subject: [PATCH 049/180] testing with alazar done --- .../instrument_drivers/AlazarTech/Rec_controller.py | 4 ---- .../instrument_drivers/AlazarTech/Samp_controller.py | 6 +++--- .../AlazarTech/Single_controller.py | 6 +++--- .../AlazarTech/basic_controller.py | 12 ++++++------ 4 files changed, 12 insertions(+), 16 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/Rec_controller.py b/qcodes/instrument_drivers/AlazarTech/Rec_controller.py index c8220aed56cd..806f724c2d20 100644 --- a/qcodes/instrument_drivers/AlazarTech/Rec_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/Rec_controller.py @@ -197,8 +197,6 @@ def post_acquire(self): :return: samples_magnitude_array, samples_phase_array """ - records_per_acquisition = (self.buffers_per_acquisition * - self.records_per_buffer) # for ATS9360 samples are arranged in the buffer as follows: # S00A, S00B, S01A, S01B...S10A, S10B, S11A, S11B... # where SXYZ is record X, sample Y, channel Z. @@ -209,8 +207,6 @@ def post_acquire(self): for i in range(self.records_per_buffer): i0 = (i * self.samples_per_record * self.number_of_channels) i1 = (i0 + self.samples_per_record * self.number_of_channels) - recordA += np.uint16(self.buffer[i0:i1:self.number_of_channels] / - records_per_acquisition) recordA[:, i] = np.uint16( self.buffer[i0:i1:self.number_of_channels] / self.buffers_per_acquisition) diff --git a/qcodes/instrument_drivers/AlazarTech/Samp_controller.py b/qcodes/instrument_drivers/AlazarTech/Samp_controller.py index 17124f4e380e..617ae841b178 100644 --- a/qcodes/instrument_drivers/AlazarTech/Samp_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/Samp_controller.py @@ -199,12 +199,12 @@ def post_acquire(self): # where SXYZ is record X, sample Y, channel Z. # break buffer up into records and averages over them - recordA = np.zeros(self.samples_per_record, dtype=np.uint16) + recA = np.zeros(self.samples_per_record) for i in range(self.records_per_buffer): i0 = (i * self.samples_per_record * self.number_of_channels) i1 = (i0 + self.samples_per_record * self.number_of_channels) - recordA += np.uint16(self.buffer[i0:i1:self.number_of_channels] / - records_per_acquisition) + recA += self.buffer[i0:i1:self.number_of_channels] + recordA = np.uint16(recA / records_per_acquisition) # do demodulation magA, phaseA = self.fit(recordA) diff --git a/qcodes/instrument_drivers/AlazarTech/Single_controller.py b/qcodes/instrument_drivers/AlazarTech/Single_controller.py index 680b83aa9eaf..2c103fbde046 100644 --- a/qcodes/instrument_drivers/AlazarTech/Single_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/Single_controller.py @@ -168,12 +168,12 @@ def post_acquire(self): # where SXYZ is record X, sample Y, channel Z. # break buffer up into records and averages over them - recordA = np.zeros(self.samples_per_record, dtype=np.uint16) + recA = np.zeros(self.samples_per_record) for i in range(self.records_per_buffer): i0 = (i * self.samples_per_record * self.number_of_channels) i1 = (i0 + self.samples_per_record * self.number_of_channels) - recordA += np.uint16(self.buffer[i0:i1:self.number_of_channels] / - records_per_acquisition) + recA += self.buffer[i0:i1:self.number_of_channels] + recordA = np.uint16(recA / records_per_acquisition) # do demodulation magA, phaseA = self.fit(recordA) diff --git a/qcodes/instrument_drivers/AlazarTech/basic_controller.py b/qcodes/instrument_drivers/AlazarTech/basic_controller.py index b76309fb8881..f615f69d7d44 100644 --- a/qcodes/instrument_drivers/AlazarTech/basic_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/basic_controller.py @@ -128,19 +128,19 @@ def post_acquire(self): # break buffer up into records, averages over them and returns samples records_per_acquisition = (self.buffers_per_acquisition * self.records_per_buffer) - recordA = np.zeros(self.samples_per_record, dtype=np.uint16) + recA = np.zeros(self.samples_per_record) for i in range(self.records_per_buffer): i0 = (i * self.samples_per_record * self.number_of_channels) i1 = (i0 + self.samples_per_record * self.number_of_channels) - recordA += np.uint16(self.buffer[i0:i1:self.number_of_channels] / - records_per_acquisition) + recA += self.buffer[i0:i1:self.number_of_channels] + recordA = np.uint16(recA / records_per_acquisition) - recordB = np.zeros(self.samples_per_record, dtype=np.uint16) + recB = np.zeros(self.samples_per_record) for i in range(self.records_per_buffer): i0 = (i * self.samples_per_record * self.number_of_channels + 1) i1 = (i0 + self.samples_per_record * self.number_of_channels) - recordB += np.uint16(self.buffer[i0:i1:self.number_of_channels] / - records_per_acquisition) + recB += self.buffer[i0:i1:self.number_of_channels] + recordB = np.uint16(recB / records_per_acquisition) bps = self.board_info['bits_per_sample'] if bps == 12: From 1eef43612e2eaf41780899222324e3812f16a8db Mon Sep 17 00:00:00 2001 From: nataliejpg Date: Thu, 17 Nov 2016 17:48:14 +0100 Subject: [PATCH 050/180] change buggy buffer dtype requirement in all acq controllers, debugging minutiae --- qcodes/instrument_drivers/AlazarTech/ATS.py | 20 +++++++++---------- .../instrument_drivers/AlazarTech/ATS9360.py | 8 +++++--- .../AlazarTech/Rec_controller.py | 3 +-- .../AlazarTech/Samp_controller.py | 5 ++--- .../AlazarTech/Single_controller.py | 3 +-- .../AlazarTech/basic_controller.py | 4 +--- 6 files changed, 20 insertions(+), 23 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/ATS.py b/qcodes/instrument_drivers/AlazarTech/ATS.py index 9d648593f1ee..6a243082e316 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS.py @@ -571,12 +571,12 @@ def acquire(self, mode=None, samples_per_record=None, # bytes per sample max_s, bps = self._get_channel_info(self._handle) bytes_per_sample = (bps + 7) // 8 - print("bytes per sample "+str(bytes_per_sample)) + #print("bytes per sample "+str(bytes_per_sample)) # bytes per record bytes_per_record = bytes_per_sample * samples_per_record - print("samples_per_record is "+str(samples_per_record)) - print("bytes per record is "+str(bytes_per_record)) + #print("samples_per_record is "+str(samples_per_record)) + #print("bytes per record is "+str(bytes_per_record)) # channels if self.channel_selection._get_byte() == 3: @@ -594,9 +594,9 @@ def acquire(self, mode=None, samples_per_record=None, sample_type = ctypes.c_uint16 # TODO(nataliejpg) get rid of all of thes print statements - print("samples_per_buffer is "+str(samples_per_buffer)) - print("bytes_per_buffer is "+str(bytes_per_buffer)) - print("records_per_buffer is "+str(records_per_buffer)) + #print("samples_per_buffer is "+str(samples_per_buffer)) + #print("bytes_per_buffer is "+str(bytes_per_buffer)) + #print("records_per_buffer is "+str(records_per_buffer)) self.clear_buffers() # make sure that allocated_buffers <= buffers_per_acquisition @@ -624,7 +624,7 @@ def acquire(self, mode=None, samples_per_record=None, self._call_dll('AlazarPostAsyncBuffer', self._handle, buf.addr, buf.size_bytes) self.allocated_buffers._set_updated() - print("completed AlazarPostAsyncBuffer") + #print("completed AlazarPostAsyncBuffer") # -----start capture here----- acquisition_controller.pre_start_capture() @@ -682,9 +682,6 @@ def acquire(self, mode=None, samples_per_record=None, for p in self.parameters.values(): p.get() - # return result - return acquisition_controller.post_acquire() - # Compute the total transfer time, and display performance information. transfer_time_sec = time.clock() - start print("Capture completed in %f sec" % transfer_time_sec) @@ -701,6 +698,9 @@ def acquire(self, mode=None, samples_per_record=None, (records_per_buffer * buffers_completed, records_per_sec)) print("Transferred %d bytes (%f bytes per sec)" % (bytes_transferred, bytes_per_sec)) + + # return result + return acquisition_controller.post_acquire() def _set_if_present(self, param_name, value): if value is not None: diff --git a/qcodes/instrument_drivers/AlazarTech/ATS9360.py b/qcodes/instrument_drivers/AlazarTech/ATS9360.py index 7afbaff1ff3a..cdac0771ece2 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS9360.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS9360.py @@ -18,8 +18,11 @@ def __init__(self, name, **kwargs): unit=None, value='EXTERNAL_CLOCK_10MHz_REF', byte_to_value_dict={1: 'INTERNAL_CLOCK', + 2: 'EXTERNAL_CLOCK', + 3: 'MEDIUM_EXTERNAL_CLOCK', 4: 'SLOW_EXTERNAL_CLOCK', 5: 'EXTERNAL_CLOCK_AC', + 6: 'EXTERNAL_CLOCK_DC', 7: 'EXTERNAL_CLOCK_10MHz_REF'}) self.add_parameter(name='sample_rate', parameter_class=AlazarParameter, @@ -100,7 +103,7 @@ def __init__(self, name, **kwargs): parameter_class=AlazarParameter, label='Trigger Source ' + i, unit=None, - value='DISABLE', + value='EXTERNAL', byte_to_value_dict={0: 'CHANNEL_A', 1: 'CHANNEL_B', 2: 'EXTERNAL', @@ -252,12 +255,11 @@ def __init__(self, name, **kwargs): value='DISABLED', byte_to_value_dict={0x0: 'DISABLED', 0x2000: 'ENABLED'}) - self.add_parameter(name='allocated_buffers', parameter_class=AlazarParameter, label='Allocated Buffers', unit=None, - value=2, + value=4, vals=validators.Ints(min_value=0)) self.add_parameter(name='buffer_timeout', parameter_class=AlazarParameter, diff --git a/qcodes/instrument_drivers/AlazarTech/Rec_controller.py b/qcodes/instrument_drivers/AlazarTech/Rec_controller.py index 806f724c2d20..5513e384264b 100644 --- a/qcodes/instrument_drivers/AlazarTech/Rec_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/Rec_controller.py @@ -162,8 +162,7 @@ def pre_start_capture(self): self.board_info = alazar.get_idn() self.buffer = np.zeros(self.samples_per_record * self.records_per_buffer * - self.number_of_channels, - dtype=np.uint16) + self.number_of_channels) integer_list = np.arange(self.samples_per_record, dtype=np.uint16) angle_list = (2 * np.pi * self.demodulation_frequency / diff --git a/qcodes/instrument_drivers/AlazarTech/Samp_controller.py b/qcodes/instrument_drivers/AlazarTech/Samp_controller.py index 617ae841b178..e5ee0c20dbe4 100644 --- a/qcodes/instrument_drivers/AlazarTech/Samp_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/Samp_controller.py @@ -161,8 +161,7 @@ def pre_start_capture(self): self.board_info = alazar.get_idn() self.buffer = np.zeros(self.samples_per_record * self.records_per_buffer * - self.number_of_channels, - dtype=np.uint16) + self.number_of_channels) integer_list = np.arange(self.samples_per_record, dtype=np.uint16) angle_list = (2 * np.pi * self.demodulation_frequency / @@ -205,7 +204,7 @@ def post_acquire(self): i1 = (i0 + self.samples_per_record * self.number_of_channels) recA += self.buffer[i0:i1:self.number_of_channels] recordA = np.uint16(recA / records_per_acquisition) - + # do demodulation magA, phaseA = self.fit(recordA) diff --git a/qcodes/instrument_drivers/AlazarTech/Single_controller.py b/qcodes/instrument_drivers/AlazarTech/Single_controller.py index 2c103fbde046..d23767c7aeb2 100644 --- a/qcodes/instrument_drivers/AlazarTech/Single_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/Single_controller.py @@ -130,8 +130,7 @@ def pre_start_capture(self): self.board_info = alazar.get_idn() self.buffer = np.zeros(self.samples_per_record * self.records_per_buffer * - self.number_of_channels, - dtype=np.uint16) + self.number_of_channels) integer_list = np.arange(self.samples_per_record, dtype=np.uint16) angle_list = (2 * np.pi * self.demodulation_frequency / diff --git a/qcodes/instrument_drivers/AlazarTech/basic_controller.py b/qcodes/instrument_drivers/AlazarTech/basic_controller.py index f615f69d7d44..025e3b97bd9f 100644 --- a/qcodes/instrument_drivers/AlazarTech/basic_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/basic_controller.py @@ -63,7 +63,6 @@ def __init__(self, name, alazar_name, **kwargs): self.samples_per_record = 0 self.records_per_buffer = 0 self.buffers_per_acquisition = 0 - # TODO(damazter) (S) this is not very general: self.number_of_channels = 2 self.buffer = None self.board_info = None @@ -95,8 +94,7 @@ def pre_start_capture(self): self.board_info = alazar.get_idn() self.buffer = np.zeros(self.samples_per_record * self.records_per_buffer * - self.number_of_channels, - dtype=np.uint16) + self.number_of_channels) def pre_acquire(self): """ From 51462ca13c632c8df6f53addeb0cd9950714c73a Mon Sep 17 00:00:00 2001 From: Natalie Pearson Date: Fri, 18 Nov 2016 13:37:23 +0100 Subject: [PATCH 051/180] removed dot filter frome helpers --- qcodes/utils/helpers.py | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/qcodes/utils/helpers.py b/qcodes/utils/helpers.py index 12f45675a2f0..7ee83f5ea0af 100644 --- a/qcodes/utils/helpers.py +++ b/qcodes/utils/helpers.py @@ -449,17 +449,3 @@ def filter_ls(rec, cutoff, sample_rate, numtaps, axis=-1): axis of record to apply filter along """ raise NotImplementedError - -def filter_dot(rec, cutoff, sample_rate, numtaps, axis=-1): - """ - low pass filter, returns filtered signal using FIR - least squared filter - - inputs: - record to filter - cutoff frequency - sampling rate - number of frequency comppnents to use in the filer - axis of record to apply filter along - """ - raise NotImplementedError \ No newline at end of file From d2376ca51b18aa0469a13b4e2796ac518cf88f52 Mon Sep 17 00:00:00 2001 From: nataliejpg Date: Mon, 21 Nov 2016 14:44:40 +0100 Subject: [PATCH 052/180] add example notebook from experiment --- docs/examples/Alazar Notebook.ipynb | 629 ++++++++++++++++++++++++++++ 1 file changed, 629 insertions(+) create mode 100644 docs/examples/Alazar Notebook.ipynb diff --git a/docs/examples/Alazar Notebook.ipynb b/docs/examples/Alazar Notebook.ipynb new file mode 100644 index 000000000000..d9902d94880f --- /dev/null +++ b/docs/examples/Alazar Notebook.ipynb @@ -0,0 +1,629 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "No loop running\n" + ] + } + ], + "source": [ + "import qcodes as qc\n", + "qc.halt_bg()\n", + "import numpy as np\n", + "\n", + "# Saving parameters\n", + "Samplename = '6QAK3_A2_qcodes';\n", + "loc_provider = qc.data.location.FormatLocation(fmt='A:/TransmonExperiments/GoogleDrive/T2acquisition/Data/%s/data/{counter}' % Samplename)\n", + "qc.data.data_set.DataSet.location_provider=loc_provider\n", + "station = qc.Station()" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "No loop running\n", + "Connected to: Rohde&Schwarz SGS100A (serial:1416.0505k02/103076, firmware:3.1.19.7-3.20.140.60.1) in 0.03s\n", + "Connected to: Rohde&Schwarz SGS100A (serial:1416.0505k02/103079, firmware:3.1.19.7-3.20.140.60.1) in 0.01s\n", + "Connected to: Rohde&Schwarz SGS100A (serial:1416.0505k02/103077, firmware:3.1.19.7-3.20.140.60.1) in 0.01s\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "a:\\qcodes\\qcodes\\instrument\\metaclass.py:37: UserWarning: Multiprocessing is in beta, use at own risk\n", + " UserWarning)\n" + ] + }, + { + "data": { + "text/plain": [ + "'_2'" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import qcodes.instrument_drivers.rohde_schwarz.SGS100A as RSdriver\n", + "localos = RSdriver.RohdeSchwarz_SGS100A('LO', 'TCPIP0::172.20.3.42::inst0::INSTR')\n", + "cavity1 = RSdriver.RohdeSchwarz_SGS100A('C1', 'TCPIP0::172.20.3.28::inst0::INSTR')\n", + "qubit2 = RSdriver.RohdeSchwarz_SGS100A('Q2', 'TCPIP0::172.20.3.168::inst0::INSTR')\n", + "station.add_component(localos, cavity1, qubit2)\n", + "fq = qubit2.frequency,lcavity.power\n", + "\n", + "import qcodes.instrument.parameter as parameter\n", + "import qcodes.instrument_drivers.AlazarTech.ATS9360 as ATSdriver\n", + "import qcodes.instrument_drivers.AlazarTech.ATS_acquisition_controllers as ats_contr\n", + "ats_inst = ATSdriver.AlazarTech_ATS9360(name='Alazar1', server_name=\"alazar_server\")\n", + "station.add_component(ats_inst)\n", + "\n", + "station.add_component(localos, cavity1, qubit2)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'CPLD_version': '25.16',\n", + " 'SDK_version': '5.9.25',\n", + " 'asopc_type': '1712554848',\n", + " 'bits_per_sample': 12,\n", + " 'driver_version': '5.9.25',\n", + " 'firmware': None,\n", + " 'latest_cal_date': '13-11-15',\n", + " 'max_samples': 4294967294,\n", + " 'memory_size': '4294967294',\n", + " 'model': 'ATS9360',\n", + " 'pcie_link_speed': '0.5GB/s',\n", + " 'pcie_link_width': '8',\n", + " 'serial': '970344',\n", + " 'vendor': 'AlazarTech'}" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ats_inst.get_idn()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Configure all settings in the Alazar card\n", + "ats_inst.config(clock_source='EXTERNAL_CLOCK_10MHz_REF',\n", + " sample_rate='10MHZ_REF_500MSPS',\n", + " clock_edge='CLOCK_EDGE_RISING',\n", + " decimation=1,\n", + " coupling=['DC','DC'],\n", + " channel_range=[.4,.4],\n", + " impedance=[50,50],\n", + " trigger_operation='TRIG_ENGINE_OP_J',\n", + " trigger_engine1='TRIG_ENGINE_J',\n", + " trigger_source1='EXTERNAL',\n", + " trigger_slope1='TRIG_SLOPE_POSITIVE',\n", + " trigger_level1=140,\n", + " trigger_engine2='TRIG_ENGINE_K',\n", + " trigger_source2='DISABLE',\n", + " trigger_slope2='TRIG_SLOPE_POSITIVE',\n", + " trigger_level2=128,\n", + " external_trigger_coupling='DC',\n", + " external_trigger_range='ETR_2V5',\n", + " trigger_delay=0,\n", + " timeout_ticks=0,\n", + " aux_io_mode='AUX_IN_AUXILIARY',\n", + " aux_io_param='NONE'\n", + " #aux_io_mode='AUX_IN_TRIGGER_ENABLE', \n", + " #aux_io_param='TRIG_SLOPE_POSITIVE'\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "a:\\qcodes\\qcodes\\instrument\\metaclass.py:37: UserWarning: Multiprocessing is in beta, use at own risk\n", + " UserWarning)\n" + ] + } + ], + "source": [ + "import qcodes.instrument_drivers.AlazarTech.Samp_controller as sample_controller\n", + "\n", + "samp_cont = sample_controller.HD_Samples_Controller(name='samples_controller', \n", + " alazar_name='Alazar1', \n", + " demod_freq = 5e6,\n", + " server_name=\"alazar_server\")" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "a:\\qcodes\\qcodes\\instrument\\metaclass.py:37: UserWarning: Multiprocessing is in beta, use at own risk\n", + " UserWarning)\n" + ] + } + ], + "source": [ + "samp_cont3 = sample_controller.HD_Samples_Controller(name='samples_controller3', \n", + " alazar_name='Alazar1', \n", + " demod_freq = 20e6,\n", + " server_name=\"alazar_server\")" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "samp_cont3.update_acquisitionkwargs(#mode='NPT',\n", + " samples_per_record=2560,\n", + " records_per_buffer=1000,\n", + " buffers_per_acquisition=10,\n", + " int_delay=2e-7,\n", + " int_time =3e-6,\n", + " allocated_buffers=1,\n", + " #buffer_timeout=1000\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "demod_freq = 20e6\n", + "\n", + "cavity1.power(-50)\n", + "cavity1.frequency(7.147e9)\n", + "\n", + "localos.power(15)\n", + "set_localos(demod_freq)\n", + "\n", + "qubit2.power(-60)\n", + "qubit2.frequency(7.5e9)\n", + "\n", + "localos.status('on')\n", + "cavity1.status('on')\n", + "qubit2.status('off')" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": { + "collapsed": false, + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DataSet:\n", + " mode = DataMode.LOCAL\n", + " location = 'A:/TransmonExperiments/GoogleDrive/T2acquisition/Data/6QAK3_A2_qcodes/data/027'\n", + " | | | \n", + " Setpoint | C1_frequency_set | frequency | (81,)\n", + " Measured | sample_num | sample_num | (81, 2560)\n", + " Measured | samples_controller3_magnitude | magnitude | (81, 2560)\n", + " Measured | samples_controller3_phase | phase | (81, 2560)\n", + "started at 2016-11-18 20:11:44\n" + ] + } + ], + "source": [ + "loop = qc.Loop(cavity1.frequency.sweep(7.13e9,7.15e9, 0.25e6)).each(samp_cont3.acquisition,\n", + " qc.Task(localos.frequency.set, (cavity1.frequency+ demod_freq)))\n", + "data = loop.get_data_set()\n", + "plot = qc.QtPlot()\n", + "plot.add(data.samples_controller3_magnitude)\n", + "plot.add(data.samples_controller3_phase, subplot=2)\n", + "_ = loop.with_bg_task(plot.update, plot.save).run()" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "2560" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "2048 + 512" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "7151300000.0" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "localos.frequency()" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "7146300000.0" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "cavity1.frequency()" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "a:\\qcodes\\qcodes\\instrument\\metaclass.py:37: UserWarning: Multiprocessing is in beta, use at own risk\n", + " UserWarning)\n" + ] + } + ], + "source": [ + "import qcodes.instrument_drivers.AlazarTech.Single_controller as single_controller\n", + "\n", + "sing_contr = single_controller.HD_Controller(name='single_controller', \n", + " alazar_name='Alazar1', \n", + " demod_freq = 20e6,\n", + " server_name=\"alazar_server\")" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "sing_contr.update_acquisitionkwargs(#mode='NPT',\n", + " samples_per_record=2560,\n", + " records_per_buffer=1000,\n", + " buffers_per_acquisition=10,\n", + " int_delay=2e-7,\n", + " int_time =3e-6,\n", + " allocated_buffers=1,\n", + " #buffer_timeout=1000\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 68, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DataSet:\n", + " mode = DataMode.LOCAL\n", + " location = 'A:/TransmonExperiments/GoogleDrive/T2acquisition/Data/6QAK3_A2_qcodes/data/031'\n", + " | | | \n", + " Setpoint | C1_frequency_set | frequency | (81,)\n", + " Measured | single_controller_magnitude | magnitude | (81,)\n", + " Measured | single_controller_phase | phase | (81,)\n", + "started at 2016-11-18 20:30:59\n" + ] + } + ], + "source": [ + "loop = qc.Loop(cavity1.frequency.sweep(7.13e9,7.15e9, 0.25e6)).each(sing_contr.acquisition,\n", + " qc.Task(localos.frequency.set, (cavity1.frequency+ demod_freq)))\n", + "data = loop.get_data_set()\n", + "plot = qc.QtPlot()\n", + "plot.add(data.single_controller_magnitude)\n", + "plot.add(data.single_controller_phase, subplot=2)\n", + "_ = loop.with_bg_task(plot.update, plot.save).run()" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "a:\\qcodes\\qcodes\\plots\\pyqtgraph.py:325: UserWarning: nonlinear setpoint array passed to pyqtgraph. ignoring, using default scaling.\n", + " warnings.warn('nonlinear setpoint array passed to pyqtgraph. '\n" + ] + }, + { + "data": { + "image/png": "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\nuhoQeCwMpfZrr4y31VFqijw0mXBBnWpOdK2QCWMGNdGuXSS57KSFPbZ66M7tnhpwCbdo6KMjQdiT\nquk2+sCMZI9iBWPzTTYPs6cmAa3a1GaFBbSKnMUMRZ5DBapepaDBGvBaLPBkDYC8U009UZjSCtDB\nbIpqfnQTxIIlCUpRFFJVD2zvpAVUEeYUSm2toEQIeaRsUG/3irRSe2z0DbvovCTgNVRBL6oOUS1a\ngqujgjiLzLN0r0WzPRe7BqqMxWzqeY1nt8O2y+9d1tJ4ViTVZFQrvzaNx9aJ6tWN1FbziI16I535\naL1THSNrLCFFmHIuow4bcU1hy3ASR7btUTNRe2stzoykbVSrnb2rnxId6prddghfNz3e1NHL6gH5\nTFBaratVcr6IUbb2kxgywVMNlQvS7LkNYNWL3HqHN9A3C+yielhVveXeWgtAnqxBnttYO+PZkhhC\nsV6PrDqE1KkD0mwXRVEFF+22ybPypTfXn3n9TC6VSZIkSZIkSZJvzvPeNOZrSQFTkiRJkiRJknxD\nLs7av52von6RvOOeJEmSJEmSJN+Qz34h9TO33r+1eXxO3JMkSZIkSZLkGfjCrjIP+Dam72lOTZIk\nSZIkSZJn5FJWzuTEPUmSJEmSJEl+Vc6m7N/+SvecuCdJkiRJkiTJN+FL95N5//1ve+6eu8okSZIk\nSZIkydfxIraR+Rx5xz1JkiRJkiRJvo6v2EaGy5nK55dTXyRuUsVqkZxDCxomvipULJSxGQBLmCa1\ngl1Y85jR0FSgVcc2NI3ljLetvjtc8AlatP+tTSGIDMMlMDWrKM3MOp6/1ERvzf1XPWutYGHQnEPm\nGIbFqpAbYGoeOoeRNCSSChWrHabVkL75/G9BqnbVHVrg0qycPRpaDVS/3hCiSZ+G8LU64LxpAldF\n+dU1q90A04V6ENQqWoJbaaemRO1Cslkttr4oea0eQzWRZ1XG1grZwRL1qOARCya0jMaNq+7xjJYw\n401rzbMjVwFq1zy7pdn6agAcx6vUOtx8pvnKGg2cW/M6GFr9O4yzUdVdGFJRE9AKjFbQ4RnW5+rZ\nGgCmiQXHdoRFi+oxlIUR1VWrOIeLMnyoVU044A3qz6W/4Rlc4tMWLdX0V4NqAuE16qNgVdIZFV5f\nWmFPtfXZ4VVR1Tr2MvZU6IskkF1rc1IruqeJoVozBzPhSXSimhTd4qanVo9H2WiBNzWYFGLCXiHj\n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\nu7gFynu4WRVBcuIhdo5yQ+2MqAdBMvyO5Odd/3VJAAAgAElEQVTUnYCIW6TyENmK2km0IDuN1NSd\nAIOdxm8Qu5g6WpCdpHIRImYSwI6pZHqcJvsh8+yTl489+exP2OeJp9d+/GE/tvGD7J0Hp/4f//Sf\nzvyn/9T8F//i3T9pKtyTJEmSJEmS98azT36Jr1y5cuXK01+8+aW3Kt3Xnn7i8uUvff1HH3X5Kb6w\n+ssZ4nvknS8q839+7WtkWfOf/bMTe3vV3/mdd/OkqXBPkiRJkiRJ3hPPPvP1L3zuMYCVy7+1evPO\nj8+grzz+1JWnv/g3a/S1p5946uzTT/3e2V/WIH9mb7kc5DufcT8mjYaZnp742tdmv/tdd+HCzzeS\n1OOeJEmSJEmSvNdWTp+79swarPzEvdaefuKP+KOnHl/h7btknn/+m3/z7qOP/r33ZoTvzs+1GiRm\nctJ86lOz3/3u4E/+pPUHf/CzPjwV7kmSJEmSJMn7Yu3KN65du/b45a+O7j/+BE8/9fiP1PofkEr9\nR/x8hfsxGR+v/sN/uPj7v3/4T/5J91//63f+wNQqkyRJkiRJkrzX1u7cXD37k6fbjxtnRp7+4urq\nF3+8av/AehfBqQCS58DYv/yX8/fvVz7/+Xf4pKlwT5IkSZIkSd4Tj33uC19/5lk4nks/d3qF48tR\nf8IKMx9W77JwPyZjY3ZpafLf//uZZ56xp0791CdNrTJJkiRJkiTJe+OxL3/lmcuXLwN84StXHvvx\nHdaefuLxr14DHr/81S985cqX32KXXzlmair/zd+ce+WV8pVXfvKeqXBPkiRJkiRJ3iuPffnKlS//\nzQ0rjz915W/fe/ytHrfy+FNP/WJH9t56x/lL74yINJvZxz72k/dKhXuSJEmSJEmS/GzezcWpb0cq\nlZ+8Q+pxHylfwi1jJkeBkWYWM4FdeTNtUQDiEbFDPEJqaA+p498gdrAniB1ii3hE7KKRsI5ZRDvo\nIdkD2JPkv4aZpLyOvwsGqRJbhHXiEeKI+5TPIw0Q4j4E9Ag7hw6xJzATo9hIPcRMYcawZzDTxDaV\nz4JimtglsgfRIar425gxzBTDb1PewEwhORT4+5hpxI2iT/1tzBR6BEL5IvEAqVK+TNgdvSb5JwDC\nGuWLSJOwiXsAM83wWbSLO0/YhEj2UTRgZ5Eqdh71hF2kjnsQqUJEh5gxgHAPdxodoAP0iPJl8k/j\n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\nAKbA/wEU7C8+KV12mwAAAABJRU5ErkJggg==\n", + "text/plain": [ + "" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "loaded_data = qc.load_data(loc_provider.formatter.format(loc_provider.fmt,counter='014'))\n", + "plot = qc.QtPlot()\n", + "plot.add(loaded_data.VNA_magnitude)\n", + "plot.add(loaded_data.VNA_phase, subplot=2)\n", + "#plot.save()" + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "demod_freq = 20e6\n", + "\n", + "cavity1.power(-55)\n", + "cavity1.frequency(7.133e9)\n", + "\n", + "localos.power(15)\n", + "set_localos(demod_freq)\n", + "\n", + "qubit2.power(-30)\n", + "qubit2.frequency(7.5e9)\n", + "\n", + "localos.status('on')\n", + "cavity1.status('on')\n", + "qubit2.status('on')" + ] + }, + { + "cell_type": "code", + "execution_count": 75, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DataSet:\n", + " mode = DataMode.LOCAL\n", + " location = 'A:/TransmonExperiments/GoogleDrive/T2acquisition/Data/6QAK3_A2_qcodes/data/034'\n", + " | | | \n", + " Setpoint | Q2_frequency_set | frequency | (251,)\n", + " Measured | single_controller_magnitude | magnitude | (251,)\n", + " Measured | single_controller_phase | phase | (251,)\n", + "started at 2016-11-18 20:50:01\n" + ] + } + ], + "source": [ + "loop = qc.Loop(qubit2.frequency.sweep(8e9,8.5e9, 2e6)).each(sing_contr.acquisition)\n", + "data = loop.get_data_set()\n", + "plot = qc.QtPlot()\n", + "plot.add(data.single_controller_magnitude)\n", + "plot.add(data.single_controller_phase, subplot=2)\n", + "_ = loop.with_bg_task(plot.update, plot.save).run()" + ] + }, + { + "cell_type": "code", + "execution_count": 76, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "a:\\qcodes\\qcodes\\instrument\\metaclass.py:37: UserWarning: Multiprocessing is in beta, use at own risk\n", + " UserWarning)\n" + ] + } + ], + "source": [ + "sing_contr2 = single_controller.HD_Controller(name='single_controller2', \n", + " alazar_name='Alazar1', \n", + " demod_freq = 20e6,\n", + " server_name=\"alazar_server\",\n", + " filt='dot')" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "sing_contr2.update_acquisitionkwargs(#mode='NPT',\n", + " samples_per_record=2560,\n", + " records_per_buffer=1000,\n", + " buffers_per_acquisition=1,\n", + " int_delay=2e-7,\n", + " int_time =3e-6,\n", + " allocated_buffers=1,\n", + " #buffer_timeout=1000\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 80, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DataSet:\n", + " mode = DataMode.LOCAL\n", + " location = 'A:/TransmonExperiments/GoogleDrive/T2acquisition/Data/6QAK3_A2_qcodes/data/036'\n", + " | | | \n", + " Setpoint | Q2_frequency_set | frequency | (251,)\n", + " Measured | single_controller2_magnitude | magnitude | (251,)\n", + " Measured | single_controller2_phase | phase | (251,)\n", + "started at 2016-11-18 20:56:48\n" + ] + } + ], + "source": [ + "loop = qc.Loop(qubit2.frequency.sweep(8e9,8.5e9, 2e6)).each(sing_contr2.acquisition)\n", + "data = loop.get_data_set()\n", + "plot = qc.QtPlot()\n", + "plot.add(data.single_controller2_magnitude)\n", + "plot.add(data.single_controller2_phase, subplot=2)\n", + "_ = loop.with_bg_task(plot.update, plot.save).run()" + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "localos.status('off')\n", + "cavity1.status('off')\n", + "qubit2.status('off')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.2" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} From eed9830f1f07b43e5d60e504d5b3302e6ed689b9 Mon Sep 17 00:00:00 2001 From: Natalie Pearson Date: Mon, 21 Nov 2016 16:32:11 +0100 Subject: [PATCH 053/180] update example notebook, rename acq controllers and delete uneccesary example notebooks --- docs/examples/Alazar Notebook.ipynb | 629 --- ...ORK.ipynb => Qcodes example ATS9870.ipynb} | 6 +- ...es example with Alazar ATS9360-Copy1.ipynb | 3594 ----------------- .../Qcodes example with Alazar ATS9360.ipynb | 3264 +-------------- .../AlazarTech/ATS_acquisition_controllers.py | 136 - ...Single_controller.py => ave_controller.py} | 0 6 files changed, 82 insertions(+), 7547 deletions(-) delete mode 100644 docs/examples/Alazar Notebook.ipynb rename docs/examples/{Qcodes example ATS_ONWORK.ipynb => Qcodes example ATS9870.ipynb} (99%) delete mode 100644 docs/examples/Qcodes example with Alazar ATS9360-Copy1.ipynb rename qcodes/instrument_drivers/AlazarTech/{Single_controller.py => ave_controller.py} (100%) diff --git a/docs/examples/Alazar Notebook.ipynb b/docs/examples/Alazar Notebook.ipynb deleted file mode 100644 index d9902d94880f..000000000000 --- a/docs/examples/Alazar Notebook.ipynb +++ /dev/null @@ -1,629 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "No loop running\n" - ] - } - ], - "source": [ - "import qcodes as qc\n", - "qc.halt_bg()\n", - "import numpy as np\n", - "\n", - "# Saving parameters\n", - "Samplename = '6QAK3_A2_qcodes';\n", - "loc_provider = qc.data.location.FormatLocation(fmt='A:/TransmonExperiments/GoogleDrive/T2acquisition/Data/%s/data/{counter}' % Samplename)\n", - "qc.data.data_set.DataSet.location_provider=loc_provider\n", - "station = qc.Station()" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "No loop running\n", - "Connected to: Rohde&Schwarz SGS100A (serial:1416.0505k02/103076, firmware:3.1.19.7-3.20.140.60.1) in 0.03s\n", - "Connected to: Rohde&Schwarz SGS100A (serial:1416.0505k02/103079, firmware:3.1.19.7-3.20.140.60.1) in 0.01s\n", - "Connected to: Rohde&Schwarz SGS100A (serial:1416.0505k02/103077, firmware:3.1.19.7-3.20.140.60.1) in 0.01s\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "a:\\qcodes\\qcodes\\instrument\\metaclass.py:37: UserWarning: Multiprocessing is in beta, use at own risk\n", - " UserWarning)\n" - ] - }, - { - "data": { - "text/plain": [ - "'_2'" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "import qcodes.instrument_drivers.rohde_schwarz.SGS100A as RSdriver\n", - "localos = RSdriver.RohdeSchwarz_SGS100A('LO', 'TCPIP0::172.20.3.42::inst0::INSTR')\n", - "cavity1 = RSdriver.RohdeSchwarz_SGS100A('C1', 'TCPIP0::172.20.3.28::inst0::INSTR')\n", - "qubit2 = RSdriver.RohdeSchwarz_SGS100A('Q2', 'TCPIP0::172.20.3.168::inst0::INSTR')\n", - "station.add_component(localos, cavity1, qubit2)\n", - "fq = qubit2.frequency,lcavity.power\n", - "\n", - "import qcodes.instrument.parameter as parameter\n", - "import qcodes.instrument_drivers.AlazarTech.ATS9360 as ATSdriver\n", - "import qcodes.instrument_drivers.AlazarTech.ATS_acquisition_controllers as ats_contr\n", - "ats_inst = ATSdriver.AlazarTech_ATS9360(name='Alazar1', server_name=\"alazar_server\")\n", - "station.add_component(ats_inst)\n", - "\n", - "station.add_component(localos, cavity1, qubit2)" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "{'CPLD_version': '25.16',\n", - " 'SDK_version': '5.9.25',\n", - " 'asopc_type': '1712554848',\n", - " 'bits_per_sample': 12,\n", - " 'driver_version': '5.9.25',\n", - " 'firmware': None,\n", - " 'latest_cal_date': '13-11-15',\n", - " 'max_samples': 4294967294,\n", - " 'memory_size': '4294967294',\n", - " 'model': 'ATS9360',\n", - " 'pcie_link_speed': '0.5GB/s',\n", - " 'pcie_link_width': '8',\n", - " 'serial': '970344',\n", - " 'vendor': 'AlazarTech'}" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "ats_inst.get_idn()" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "# Configure all settings in the Alazar card\n", - "ats_inst.config(clock_source='EXTERNAL_CLOCK_10MHz_REF',\n", - " sample_rate='10MHZ_REF_500MSPS',\n", - " clock_edge='CLOCK_EDGE_RISING',\n", - " decimation=1,\n", - " coupling=['DC','DC'],\n", - " channel_range=[.4,.4],\n", - " impedance=[50,50],\n", - " trigger_operation='TRIG_ENGINE_OP_J',\n", - " trigger_engine1='TRIG_ENGINE_J',\n", - " trigger_source1='EXTERNAL',\n", - " trigger_slope1='TRIG_SLOPE_POSITIVE',\n", - " trigger_level1=140,\n", - " trigger_engine2='TRIG_ENGINE_K',\n", - " trigger_source2='DISABLE',\n", - " trigger_slope2='TRIG_SLOPE_POSITIVE',\n", - " trigger_level2=128,\n", - " external_trigger_coupling='DC',\n", - " external_trigger_range='ETR_2V5',\n", - " trigger_delay=0,\n", - " timeout_ticks=0,\n", - " aux_io_mode='AUX_IN_AUXILIARY',\n", - " aux_io_param='NONE'\n", - " #aux_io_mode='AUX_IN_TRIGGER_ENABLE', \n", - " #aux_io_param='TRIG_SLOPE_POSITIVE'\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "a:\\qcodes\\qcodes\\instrument\\metaclass.py:37: UserWarning: Multiprocessing is in beta, use at own risk\n", - " UserWarning)\n" - ] - } - ], - "source": [ - "import qcodes.instrument_drivers.AlazarTech.Samp_controller as sample_controller\n", - "\n", - "samp_cont = sample_controller.HD_Samples_Controller(name='samples_controller', \n", - " alazar_name='Alazar1', \n", - " demod_freq = 5e6,\n", - " server_name=\"alazar_server\")" - ] - }, - { - "cell_type": "code", - "execution_count": 45, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "a:\\qcodes\\qcodes\\instrument\\metaclass.py:37: UserWarning: Multiprocessing is in beta, use at own risk\n", - " UserWarning)\n" - ] - } - ], - "source": [ - "samp_cont3 = sample_controller.HD_Samples_Controller(name='samples_controller3', \n", - " alazar_name='Alazar1', \n", - " demod_freq = 20e6,\n", - " server_name=\"alazar_server\")" - ] - }, - { - "cell_type": "code", - "execution_count": 52, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "samp_cont3.update_acquisitionkwargs(#mode='NPT',\n", - " samples_per_record=2560,\n", - " records_per_buffer=1000,\n", - " buffers_per_acquisition=10,\n", - " int_delay=2e-7,\n", - " int_time =3e-6,\n", - " allocated_buffers=1,\n", - " #buffer_timeout=1000\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 60, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "demod_freq = 20e6\n", - "\n", - "cavity1.power(-50)\n", - "cavity1.frequency(7.147e9)\n", - "\n", - "localos.power(15)\n", - "set_localos(demod_freq)\n", - "\n", - "qubit2.power(-60)\n", - "qubit2.frequency(7.5e9)\n", - "\n", - "localos.status('on')\n", - "cavity1.status('on')\n", - "qubit2.status('off')" - ] - }, - { - "cell_type": "code", - "execution_count": 49, - "metadata": { - "collapsed": false, - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "DataSet:\n", - " mode = DataMode.LOCAL\n", - " location = 'A:/TransmonExperiments/GoogleDrive/T2acquisition/Data/6QAK3_A2_qcodes/data/027'\n", - " | | | \n", - " Setpoint | C1_frequency_set | frequency | (81,)\n", - " Measured | sample_num | sample_num | (81, 2560)\n", - " Measured | samples_controller3_magnitude | magnitude | (81, 2560)\n", - " Measured | samples_controller3_phase | phase | (81, 2560)\n", - "started at 2016-11-18 20:11:44\n" - ] - } - ], - "source": [ - "loop = qc.Loop(cavity1.frequency.sweep(7.13e9,7.15e9, 0.25e6)).each(samp_cont3.acquisition,\n", - " qc.Task(localos.frequency.set, (cavity1.frequency+ demod_freq)))\n", - "data = loop.get_data_set()\n", - "plot = qc.QtPlot()\n", - "plot.add(data.samples_controller3_magnitude)\n", - "plot.add(data.samples_controller3_phase, subplot=2)\n", - "_ = loop.with_bg_task(plot.update, plot.save).run()" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "2560" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "2048 + 512" - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "7151300000.0" - ] - }, - "execution_count": 30, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "localos.frequency()" - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "7146300000.0" - ] - }, - "execution_count": 26, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "cavity1.frequency()" - ] - }, - { - "cell_type": "code", - "execution_count": 53, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "a:\\qcodes\\qcodes\\instrument\\metaclass.py:37: UserWarning: Multiprocessing is in beta, use at own risk\n", - " UserWarning)\n" - ] - } - ], - "source": [ - "import qcodes.instrument_drivers.AlazarTech.Single_controller as single_controller\n", - "\n", - "sing_contr = single_controller.HD_Controller(name='single_controller', \n", - " alazar_name='Alazar1', \n", - " demod_freq = 20e6,\n", - " server_name=\"alazar_server\")" - ] - }, - { - "cell_type": "code", - "execution_count": 55, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "sing_contr.update_acquisitionkwargs(#mode='NPT',\n", - " samples_per_record=2560,\n", - " records_per_buffer=1000,\n", - " buffers_per_acquisition=10,\n", - " int_delay=2e-7,\n", - " int_time =3e-6,\n", - " allocated_buffers=1,\n", - " #buffer_timeout=1000\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 68, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "DataSet:\n", - " mode = DataMode.LOCAL\n", - " location = 'A:/TransmonExperiments/GoogleDrive/T2acquisition/Data/6QAK3_A2_qcodes/data/031'\n", - " | | | \n", - " Setpoint | C1_frequency_set | frequency | (81,)\n", - " Measured | single_controller_magnitude | magnitude | (81,)\n", - " Measured | single_controller_phase | phase | (81,)\n", - "started at 2016-11-18 20:30:59\n" - ] - } - ], - "source": [ - "loop = qc.Loop(cavity1.frequency.sweep(7.13e9,7.15e9, 0.25e6)).each(sing_contr.acquisition,\n", - " qc.Task(localos.frequency.set, (cavity1.frequency+ demod_freq)))\n", - "data = loop.get_data_set()\n", - "plot = qc.QtPlot()\n", - "plot.add(data.single_controller_magnitude)\n", - "plot.add(data.single_controller_phase, subplot=2)\n", - "_ = loop.with_bg_task(plot.update, plot.save).run()" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "a:\\qcodes\\qcodes\\plots\\pyqtgraph.py:325: UserWarning: nonlinear setpoint array passed to pyqtgraph. ignoring, using default scaling.\n", - " warnings.warn('nonlinear setpoint array passed to pyqtgraph. '\n" - ] - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAA+gAAAJYCAIAAAB+fFtyAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAg\nAElEQVR4nOy9wYsf15bn+TkR8UvJr6ooCppmphdpbHCvtChoBmqhBBeGUUMzzLzFrAQFJXrA/4JB\nA6YR6F8wdKGCglzXqpr2wrSGTIbqRUEtDDODwA/nbpih6Ro/ZebvFxH3zOKcE79ISfZLvycrpefv\nB2EyMn6/G/eee+6Nm+GI+Ji7I4QQQgghhHi76W66AkIIIYQQQojfjBbuQgghhBBCvANo4S6EEEII\nIcQ7gBbuQgghhBBCvANo4S6EEEIIIcQ7gBbuQgghhBBCvANo4S6EEEIIIV4Xp4+OgkenP7T3xf2n\nj46OHhyfvaFKvqto4S6EEEIIIV4Pp48+4/HJycnJ8afffPby0v30aew9OTn+9Jsnyzr99NHRE+59\n9Ibr+g6ihbsQQgghhHgtnD798t7HdwEOjz756JtvX7yCfvfhw7vx09mvnn34/iHA2fGDJx8cP/mL\nD95oTd9NhpuuwG/J0dHRycnJTddCCCGEEEK8isP3P3z29AwOX9xxdvzg/hfP7j0+eXgXzo4ffM7n\nT+4f8j13yRwdHf27f/fv1r/58z//85+mxu8A7+rCXQghhBBCvIMc3n9ycp/TR0cPvj3+nK+ePXt2\n/+iL3Hf/AcdP7r+w1v85r9RfQAt3IYQQQgjxujn79puPPviL79199+N7nz09O3z45OR+fn659i6+\nF93jLoQQQgghXgt3P7735dNTgLOTr/Im9rPjB/UGmbPjR/VA6unTLz/6QIv0H4muuAshhBBCiNfD\n3YePnx4dHQHce3xy94W9h+/zRd0Xc+/xia6u/1jM3W+6Dr8NejhVCCGEEOL3Hi351uhWGSGEEEII\nIX4EZnYjx9WtMkIIIYQQQlyXWLX/2LX7a7nJRQt3IYQQQgghfjPLYv3v//7f/qgv/tmf/dVrqYAW\n7kIIIYQQQvwQLyzZX9dC/MeihbsQQgghhBCv5uUlu7vDX7nP1yzh3/yb/+Hv/u7vXktltHAXQggh\nhBDiRV55lX1/q/q171n/D//hP7yuKmnhLoQQQgghxBVi1f7qJfvNoYW7EEIIIYQQybWX7O2NVgvQ\nwl0IIYQQQgiu3htzjavsN3ABXgt3IYQQQgjxs+Z7nkD9YbRwF0IIIYQQ4k3xG55A/SG0cBdCCCGE\nEOKn53dYsgPgusddCCGEEEKIn5i386UxvxEt3IUQQgghxM+FH/kE6g+gK+5CCCGEEEL8BPxWT6D+\nALrH/Qb5v/4ldFgPHcyOA2YbCDNWWG17rAPHp6ub5by1IXvRZ+iwDuIWqAZgG/D6fByLKi0+bPXd\nVjUhC7+yF8yu7jUYoIHnHVdZOPhce3HMGMGcATCiXbaq6nh1c1q1a92QAWx1rG7ZdMyWvVl41YQp\nC4+aE4V3WI87rKPEKqT91c0NtPq8YVWaT2DRUsctal4Nhwk6x8z2QauqNq971CyaWb+phlQcskeW\nZFiaOWWjsqrRLnMbbJUbbhVzn8FWMZywrqLksMSwuu+FZma0I4YNHJZm1mZkWvZXl0HDr2T1Pmg9\nGFilikHvmBFR6pegOWZXQsrqWJ6Zn4VHTahMs/z8fkCtU8XwMVN6390WmZY18aVwi4YYXcWwrWpC\n9iBmDNmc7L6hcm9JvCFj7o512EHV3Kq0bjXwN1klPEOa+dCgxwZsAz20/Nney/rYLbr36H6B3cZ6\n7D2629Az/xee/2/83//r//M//h//0//J/w7/Bv5n+O/h4L9j+JcMh/T/nO6f0f0J/T/Hbht2gN2m\n+wNsk4ezHruVlXHH+tjlWIbdeti4mWGOG4YdVLVjRGwwy+6zzhkMw8y9WaalYYa3ZXyBOa3Kj7As\n00jloTesg3UyrHI+T3U9dJjVtNPXrNVqcxna3Wosz9XdQ+WSr3q/pp394J1fsTdzYz2+1lm9TErr\nrLacus2gZvIXDu1XD70Py5WZYX8iwPet3p9T+v3UemVAtVVNXpiUOphwX2VplDasJvau6tZeKnwJ\n2jIzzC+2y14ZtFXN9x20KtzbizHMD3ereb5dPfR6Unp5xlv08ptVM5dZaL0JtDrVLjPDtOqgSDz2\nM2Q2s8tYMdZUMFTFnCuJt5zHu/p6DRnml3KjXQ3aWJNtBG3c1zzPbqsu8JnhnyF+Z165ZHf/979b\nqVq4CyGEEEIIseI//+f/5bWUs9wb8/d//29fQ5k3cU/827ZwP3304Nu/eHL/MH4++uxLgHuPTx7e\nvdl6CSGEEEKIm2Cz+R0vjfMP//Dv/9W/sj/7s7/6h394Xavtv7qRK+7dmz/k93F2/OAoV+oAp48+\n4/HJycnJ8afffPbo9CZrJoQQQggh3mX+4R/89a3aA7/2v9fGW7RwP7z/5OT4049y6/Tpl/c+vgtw\nePTJR998e3aDNRNCCCGEEOIKN7Bwf9tulXkVh+9/+OzpGRxe/fVf//VfLz//5V/+5RuulBBCCCGE\n+PnycxMwnR0/uP/FM+CjT4/ztvYfgxbrQgghhBDihviZPZx6eP/Jyf1rfO7s228++uAvfvLqCCGE\nEEIIcU1+3g+nXuXux/e+fHoKcHby1bMP3//RF+SFEEIIIYT4qfh53+O+3Dlz/+iLe49PHj58/PTo\n6Ajg3uMTvQ1SCCGEEELcAF9//fWdO3de+vXP7FaZF3jpzpm7D09OHr6po7v1gPkOgN6sc5x2mbst\nzKOTtXnZhJm2je9a/L+LtoVWmzNthJX0tF0CbmaEsHOyvQ+y4fMV6anPRGVCzOZj7d0se93MQvPm\n7lyQisr4+g5w3NLEtnWapfXNzS9W7XJ8LgPrJlWg+2ZGzS9KXtiBR6uvVBUHc8IVerlsghvjypzn\n7tNKyWnQaNv8Pz8h+YuY74O2LcXjAI12Dov0dMankBVbNgTYGaTW1B2ipQPMBusIGx2tghYNaRd1\n6N5wfBtuhZSe+rgYBB03KoYMMDuTXRHiQts52KLKa+cRsor5Be6pG/QZIqQ9dEaYDleWvpYxdBui\nCRby1yXx2K3CgrdtNapbshTrbJUbYG4bcGurDoopyC8sGmK9+VjW0sFCtuvbyASnBzd/njXP7htL\n1xpBHt3dF12rny+JZ6t21aFn2gVm6e8E/NLWVtp2Hu5Gs021a2mm4RHDDtsYDjtaC0ejY+bbq2LL\nzv3SFmGnN3xbqkKr0uK4G5iy8DSkNnzEo9UHMMOMX8CwsiOP2ID9Aozm+Ba7TfdHdB2t4SPzf6Fd\n4M36KxbcBr7FL/FzfMJHfEt7Tofb7dkZrT1325gd0N3Gm9PML7EBO8BDFXlhNmB92pT90qyHzlJd\nOdZg7M2MdpmmZNvgs3mlyj4ZIvE2Zh3N4bIMxOGPjJlh45ilHrL6y2f8soZbJN62Ei8G1DK7hl1y\ndG+2lk22TLzYKlHlkOOonVfNB9zJOW2RTW5rfG2qnovE1PHtFbFlzmCw2HbbWALpmhkWz6UD5ytZ\nstEuwPf6Vb9cDYEYFIs22GoULFHaljp0SFtnG/dZbR3tvPydG/CcoyBFv9kQYEP25hJSr8LZO2vb\ntDeJmlVpy+A9X0bQarQurX5+JcKtrSb2yPqJtW23/Xqla43Bu4hFX7V3nQx5NrSaGcIwXSOd6ILl\nww2er6YCaM+vJt4y90YMz6/UHGjf5YedlQN17axdVL5O+3Vt9uC0VqbziNJUDuNhX5N9MxetbF/j\na1GbL0FbaYOzIYv5Vdwkd+7cedXa/ee9cBdCCCGEEOLd4Of2VhkhhBBCCCHeTfRwqhBCCCGEEOJV\n6Iq7EEIIIYQQPxbdKiOEEEIIIcTbhN4qI4QQQgghfv84fXT02ZcA9x6fPHzpfd7L3tq/vA4cPvr0\n+Mn9d8fc47rHXQghhBBCvLOcPvqMxycnJyfHn37z2aPTl3Y/jb0nJ8effvPk+AzOfvVh/ubxh198\nfnx2E5X+LbkBAZMW7kIIIYQQ4rVw+vTLex/fBTg8+uSjb759cR1+92FdhD/71bMP3z9c/+bwg4/e\nYE1fA+3a/14bulVGCCGEEEK8bg7f//DZ0zN46d6XuDnmpRtpzk6+4pPPX3WnzD/+439ab/7pn/75\na67qu4MW7on5DgyfAJhgCG/n6u36nr8h7moKB96IdZa+QGAmrZb9solbKgxzr+UPlHkubG2pTaTs\ng/F5I0ubX9rbzKFUqUbU3OoPuzkrnDdgNauvu5llM+Pgbu5xLMct/usTmNMsVKnxee9S53bFONDA\nw1lq+0OTm2YrK6GTesUZOrOGWzVwhJDqeRXe7SNMZ1lOOA5zRxzaQqznYfWMvjOv/y2VYbH4jFvI\nFyOwVRrWxUE9mxkeVmDGm2OW5rzZPQLSrCJcETDD0+yYJryUm+LpzKuYVwfl3qwb2X1zKELdm+2D\nBjQPYWrWZMm0q4kXcsQ8lqW+EaL7nN6MdG2mVbL+511UhiWrJ6zDZ7yvzCRyI/d6h3UW/lEmQkNL\nWXiTkDU2y0P5OjeyzOyR+H2fzXTMWnoEfUzhZRoQWyWRO27MTm++WCenSpuW/RLj1JtZVw238iCa\nZRqU8JJWMam0tA7vsCU4oTlcusBzOGA5N1grbWoEcKLrYE6Lagfe02Zsg+9o5/g5zBgHkV4wwg4O\ndrDFd/gWtiVSHWAzWQ/MFq7WhttgMSp9whzrPaS/TPjGrZnHcA6pZFt1eitPpFeW7ucEPNpCfbIz\nZjxiO1moNPcdh/tkGGaZpTbgXXVfxLAUyzk0yo2aKZrj0TLmU+1dfMy27yAf01caClgGfNpPnvtk\nXsbXlJlDZM5QjWqVM9QY6bARj6l7ym4NLStzhs026bHGsA7vMVtNj33WfLF+ZiXmPLnYatpJC2zM\nrpXDV4IWRtgp8y2lvPOqwksMDbZYzzKxL4fep3F0wZhW4DB3xuetx/ssyhvWkR00Xa3n/FLh5WG1\nmqu9S+GrL47evmI+4cCAdftDE4bR1Xk2C5+vmMLzN+yVoj5Dw25lb3rNGCmvrUOH8Nvr7Gm3qyFL\nB9n+BGcHlXWR7X2dGsq47N0+hkuP5GDnioXXy6qbybkkQ2lZvd+f5WOFEEMzs3rpr6jY7+U67fD+\nk5P7nD46evDt/p7200f3v/rk+Mkr73B/S1fqNyFg0q0yQgghhBDidXP27TcfffD9j5re/fjes1/l\nnTSnj46efPAWP5h6586dr7/++qVf6x53IYQQQgjxrnL343tfPj0FODv5Km5i5+z4wVE+pnp2/Kge\nPz19+uVHHxzG3rd61f793MDC/ffyf8EIIYQQQogb4O7Dx0+Pjo4A7j0+efFtkIfv88X9oy/I3fcP\nOTv+6hnPntUv3843Quo97kIIIYQQ4vePuw9PTh6uf3F4/8nJD+68/6aq9lvxqptkAr3HXQghhBBC\niLeGV11rD3SrjBBCCCGEEG8/N2FO1cJdCCGEEEKIH8sNvA5SC3chhBBCCCF+LLriLoQQQgghxDuA\nFu43SNu69eWGHPHRrbdFS+mzY7EZ4kmgbI5zutMW2SezM1kK5ELStruqYWNRo7lPxni18LC+hYZt\nSimpDXg4SqfcJC2Y+01wHwmNZenlnNFSyxfGuMm8TGw+4eu9k/kIbuWusxY1GVIvx5iC1FRLjpBi\nyzKJ7qCvJ55TPejWEy5PHwFPjegYVktP1yDmu/iwYXjDS1YHzmRtTiFfGU89DY59fABGB6ugVQyH\ndNf5KmhMtHkfYZw2YksrOnzEd1jnDBbu1VTlhQlvl/VNYe2cQbChPKBh96yR5ZN7b6nY7PCdu5mV\nCjQL7ytzIsKdLZrDcjSmBDdjuAEMx3eYOf2ilsR3pdxz951hKfDLmAOZ1RZGz/xApPE+8dyntKva\nkGkWauHFKdta5Lzta76Frrp7jM/nZnO4rETqnAnfWRSehw4P4iaduG0XksvS1u7Y61E7byPszDps\nMCY8Wj2UFnTEzemz8DbDDrMs3D160G2z93F61KTLkGLYQShXnWa+w4ZSG17iW2zABujwCd/BgB2k\nQdMvoad7Dw5gpM2wofsFOA18xG7V5jntOe2CxgCbGj+7iOWM7/Bz2m36X8CEnwPwi8k2DTr3Ztaw\nDXbL6dOl6p3ZAdbjHYz4gA0W8sg2YltjqEExQuexN2KeRtLFGTzu9Y0Rt7Q/dlxJhuix7C8Lg2bL\nvR7qXCa8d8xC4emjs7W9S3JMG3QO3jJH5nzo+G4Z2uVdtr1Q07dl01wkwZduvTFA5G202sBoU6o0\ns9UN30LpNtlVM5fBO9c0sozW7V632Za9y+gjLb8hQPXLGlCOO5yXKNRKz1nH8qjJ2hs6lQd0GV99\n6loj8dhWVb0kwdAd4L5vV0hJ2wtSUi+Fbc3Vceilu9sWLvZi0WxFT56DZvxypVPdrZq5FL7Mb0vh\ni4P24mrmXFZ31FnD2XeBz/jF1cKnKxbStj50+VNzqMaH+zprhO92u7erMtHOMYNS0vrFVTMrVwpv\n89Waj9XMxf/NSzbciLBXb67t4OucX8Sua5Pr8nVo54i3g1e9EVJvlRFCCCGEEOKt4euvv/7bv33V\nu2Xcr/vv9aEr7kIIIYQQQvxYdKuMEEIIIYQQbw137tyBVzqY9FYZIYQQQggh3gF0j7sQQgghhBBv\nDV9//crL7TeDrrgLIYQQQgjxIsuS/W//lpefTcV1q4wQQgghhBBvAas3ybzyortulRFCCCGEEOKt\nIV4H+Sr82v9eG7riLoQQQgghxCv4/lU7eh3kzTJa2wGllMPS4UdEyeqlP5ZOOF+8oRD3OZXzz3rD\n8Uu8K9cd+CVuK1HlLro7zJQW9ru9+7OlMY4upZstBHKD5d50XoZVj3aR/rZ94eElHSw0bCtrKWDt\nYm+1TPvjoil1q2OxFG7d4nYN8+vaqWn4Sji3c7y0iA1vFqrR8s/FoUvn6dYuy2wXds9dxjAi7FvA\nMshtZVXsbbHNgWUaZ1jcBsM8CgdscNxSO7rIIL2sex30uDtbc3eLZnbuO9j5vvDZ2dle6TemdzM9\neQ0fbR80p22rcDPmVIFiTvRI+BrxTK3LbEfqV0e8A7Aemnvbp0r2yLkt4kN34yIFfpkqi2y1c6gg\nGAyOG2OG1zYwh2B1n3hAOyedwWZLzG1jcc2gLeLDzHnHys+K+9b2Sb64eBd5ZDoUw2qZtk7ANukD\nbuf7DvLOubB1Vmda9tkjvsPHMqS6twsLO2YoNn23WGYNdzfz59AvMsJK8j4b20oVaT0+uz+PHLZo\nSLtw6827yuodvkvxofUpuLUOu4114LRfY7ewW2DQaBN2i+4Ps5fnHUB7jo8w+0xfEkuHHfgWP4cJ\nJhhp32G3oYMJzuFWY3NhwwGYhR7SBrr3cMq4ObgNxmA20XZY796bbXCHbViBM0rtIqe78M62MUf6\nYlf1yOGNW4zWpYPCxnpes1CHE4JbZ8iOaDtYJMGTMadYNGat8N2WwtaZzLf7wnPSsBp9Xr/poXPM\n2vNyBsfMMFceDoC10WlGVw2pScaGlP5y1ZBKZGbmhvs2rcy28lbuNZbbmrL6CgKrCfCqFDPsntaV\ncXNcjaDI8zh06VT9cl+yUwLUiOEYBugqbXWaWHSekVp7vbGvzKCk4jTFosvmWvbJKix+xSTaLvMQ\nMZZpVfhS84ph+MLr/LVMmPVdW9Wkwwacq4cOOe7VDmoXFYRF9bpEqYKWHzb8ovy4IY4d05u7Vyl7\nVSbsOSs5qy+zZTUzSrtyrExjfKr7m+1KzPelTfugNa8TVtsfmhdSa31yhDZd2StujngX5PdfcX/T\naOEuhBBCCCHEq/ne97i/ViXqNdHCXQghhBBCiB/LDbxVRv8LRgghhBBCiFejh1OFEEIIIYR4p9Gt\nMkIIIYQQQrwDaOEuhBBCCCHE28EPvQ5SD6cKIYQQQgjxLiBzqhBCCCGEEG8Hd+7c+eUvv2+nHk4V\nQgghhBDiHeAGXgephXvi3owZwDss7lsKnVtuOm7M0GGt7mpqQJk4wef8PC1kfrVpy16nXIDzP6UK\nLj2RLfxzbhNgzHkI27g74Tdl7x+NQ7v36e9kSqFgiuWWY03VNAeMCTp8DrmpkWJOw6vabrUX5qr5\nhGOLv81HzAzwocoEhjwCs+2DsKjjShrnrf70HDz0fT7jYL2nOXUC9upTn0vaGpvTyiPo+wFjvnK4\nYmFsBQ8ZbVQpDw17F2PDutTZ1qGt5HyZDPHJiAweXzNfpLlLp6fqz2mG4Q1m6NPmWDF0640GzWll\naW2AM1U/NrsStA15uOiLNCBauFT3Rr0ZxhKptgrLEALAdVpapgpgdZRWSuB5n9VuqdLMrDNb7fVw\nwVa70hfrBmYpD+7T/FodlB0Rut+9ZbBVF0xWca4BsvSIYUtpMxhuIQA2n6Ez68tzPOGWHlO6pUci\nPyMB9k5QsxpxnXtfaWwwxbGMFr7PSHJo5iH1nKHDp0rLhlulU4e1fadYo2t4iCR7rMZvDmGnfUf7\nNb61nttwAMAY5tTL/Ncu4BZdR/sFXegpB2zCbsPtnfVTiCqNgeZ1aMNH627BhPcw470tNc8ZoMNq\n07tUq2LQ3M2sW1oNhuM2WTZz6aBQpcag7twG88X9POAxJcZUMLBMSpGPvilR9NJBMRWsOmg/FS+z\na8MM76HLNPZFhmqeYs6ouVO9UoNiSgWsDzWNR5mb1HyyPnQ4RLvsuFXi1VwdpQ1hXCanrN68i8Tz\nnIUOwImwZEMstaBmeJfm1BiPdlBZNLMfUF1MtjEeM4bE9FxZlFVdpoIJrLrPo/exqcypDQwbVwMK\nsFUzqSQhnaD2wt6Ynbysoiv/KFNpUzMJa6ANVbFKP6i9EWHLZhKbvpzg8NI5M++DsC88ZMBeVe1z\negmNcX6+BMBXtKzkYFxinmlQ3eHRI17tsmWKK8t4X5svlFbO1yxnWUKM+3oC1qp3Iqs3V7+1WHhH\nYNXd4u1E97gLIYQQQgjx9qOHU4UQQgghhLhxvv766/jhe98qo4dThRBCCCGEuFmWVTugh1OFEEII\nIYR4S7lz587y83oRfxXdKiOEEEIIIcTbz/LM8RtEC3chhBBCCCFewQ+ZU3WPuxBCCCGE+P3i9NFR\n8Oj0h/Z+z36xQgt3IYQQQgjxU3H66DMen5ycnBx/+s1nLy/NT5/G3pOT40+/eXJ8dhNVfBVff/11\n3N3+/Q+ntmv/e23oVpnE0itRBoS9z6LDtzAYQIMZH8vEERKK8UUHU+g2fK6u2u81SD1E94vSKzQs\nJE0hqdntS6PhW8vNME1socMsDm3MrLxIdtUSUiKkbm/h8fh8yGuAyenTgpTt2pDOlalkK5bKEp+c\n3iyOHoKnZtZlEFJNFUabyTD3ndmmFCHgU+kzwmAyXdWdTEa3asgE5ZbyrWUrLM0sPu9FHqFx8RHb\nlGWpLceyOtZK2eOxNyUpbSTkKYsmibk8Vl4GqLF60KFZFm745LgxpfjDZ3DzsZrp+GR7TVJsjmGP\nsnDEpMgpUmtMKZINHuVU0Er51JbuI201k9HtpTBMZWUCn9MqUl4nHBidtTPLsMHd04azLxz3ho9m\nQ4q0/Mpe8xkfvZwg5lMlUh0rYmhD6L2yT22zN634SFqWGt5gLI1LM1r010q5tZSG+2ihPVrkNR4K\nodLTRKttqLSM7t6Uf6rhkzNUd4dvaCjdSfhQumrLzt3MKrGz1VM1ZLLsr83KpNPgVrl7drQZuw2p\nBKI53S+g5ZTSvqM9x3fAARyUkWgG3+Ej7Tu6P8Jv4wP+POckux3jExzea9Z7OGvc3bpbOUKZaXPJ\nniwnjRzdHexiHDmDmeGj+2Qpg+vK7TWuTg2R89XdOb6WaWcqrVhOcWV6WhJvjJIdtxYinF19PSal\nZchgkQws+iffa3RwWiv5Wgzu0YjJtkvrmQPbdIdl4YshaMZxLCclGu7YWHogrFxUNWFuU1IXlcm8\n7coxNOK7lT6vBFU57UR3X2IheIqzRpezEEYrZxNDjpecLcmx7Lt9hFsomWw144FfYgdl/wkLWL/M\nzLC2C22BK4YmB4aQYZUhKBqyNgRtqtXRlV1ZsUILuMiJ5iv6J99iliGiTFX02LD3u2VvGowpmbLw\nWLUcGvtzq0dvrlLrqmVp30xKN1anv3a5cr29Uro0YaG0Y6Vw2qwUgedXDE1Z8krwxNIjVzON5WRX\nQchD36oh3vCLVcND/da/1COrr/8+CJhOn3557+OHAIdHn3z01bdn3D1c77/78GH+dParZx9+fPhS\nATfE+vlUeOXzqXo4VQghhBBC/F5y+P6Hz56ewUuL87PjB/e/eHbv8cnDu6/63n/8j3/98i//9b/+\ny9dfw5eIi+5/+7dcWcYnWrgLIYQQQoifF4f3n5zc5/TR0YNvj5/cf2ld/2bW6N/H9z6cehPmVN3j\nLoQQQgghfnrOvv3mow++/16Yux/fe/art+Yed37DK2W4EQGTFu5CCCGEEOIn4u7H9758egpwdvLV\nsw/fPwTOjh/UG2TOjh/VA6mnT7/8oXX924fMqUIIIYQQ4veIuw8fPz06OgK49/jkxZvYD9/ni/tH\nX5C7X75P5ga5c+cO/MBFdwmYhBBCCCHE7xV3H56cPFz/4vD+k5Pv3fnuoIdThRBCCCGEeAuIV8p8\nL3o4VQghhBBCiLeBO696B+QK3eMuhBBCCCHEW8A13irzptHCvfAtNKc3Cz3nFoAu9JvuuxRM7j18\nZRIN71rKREPxOHnbGV4SuIaH/dFSKNh2jgEWdrS2yzrstZdT+hfTCBjSuLAGjrRWHw6H33ovtPMq\nfMDHtCqG0I6rokRvxlhpt6kgzLkZntd0mhrWGTPtssLSm69Ne3HoCTDMbTCcdpGhTXHpDp8x86in\nj+ZTbJoDM36ZgkDvnNE8/IKDGaVgpGKO+0hICm0TitmQdFpKNMcQuIbJz/xy5e0D39ne72jmM4wl\nuqM8phgzbFJ8SEtVnkE7z0bb4GBtG4+nhEw0m4m59UaHz/glKUrsyGMFYWE8z0NnDEdjqarTLmpz\nk37T9Faaeb9KVIPezazt6tD+UubMsMsP20DoUXEwbAMzPkWUbEmtSAbbeMhu98ULFW0AACAASURB\nVKLE3nxXqWL4YIwlVjRsY+6Re0bDbgG0i9zLxnFjW3XbYEa7TFOvddCZT/gYSYwPBhFDo3M7wCdj\nxGe3wWyA2ds2ZajhPvRdHMttA27tEubSQ3bGrkyKvVl0UKhIh9rcEtWwTQbB+5BuRsVSo2gHkUvg\n0JV2cQuO93S3cfBzLML7HnS089JGzrQL2oXPz31LD7dgAyNcRPZtYaT9mq7He3yMAMAMt7M//QLv\n3A4mGzozcMMd67BN+T63EFbLDQZtrDSLaX+HGyETjbT0SoaUYs75dcNzyMQAHFapZealXi6XpDOF\nm9mtD4EuLSaTRck5lYt3AJxmPkLn1psPcIk3Nyubcku7ZBw3DbWAOYMx1yzUrTymraZiw5/nrGtD\nym69VWlUMy0d0jnPdEsueY4vynI64i2M1Fir+RC3AwuFs/viW3Xfmse2YTkzOG502GDRqdYRqmaf\napKxFG/7fkB5DMzUIcd54RyfMhWsx2f3CbBMy+3qJBLnoHCFRt22FTSHDea0Gr/59TmVt/R5gvCW\n7crROlXAff9hMzy6e0wPKENO7Ms8k+1akmHGL0sfPlT859X0OGVDInU9TwS1OZXWtCunbOld84y2\n2+td3WHaG1i9h8sylUY+jHGGqkPPdaweG1abS+H7DgLDL/ZS4b033Svnz/dpnMuAsWrew0Qbs7Ni\nMx2uZNDEDfGbVu3cyMJdt8oIIYQQQghxhTt37vzylz/8Eb3HXQghhBBCiLeA37B293bdf68P3Soj\nhBBCCCHEj0X3uAshhBBCCPEOoIW7EEIIIYQQbwF6q4wQQgghhBBvNaFeegvfKqOFuxBCCCGEEMki\nTI0nU793+X4T5lQt3IUQQgghhEjWwtSvv/76l7/8vrX763xdzDXRwl0IIYQQQohX8/03zOiK+83h\n0wU9Rsj5cJoRfsKwgU4hp4RdCtgwW0R3KTZr5SB0CzkfUGI/Awj5ZW2W2bRMfl2+6bNKK5NcA8c6\nnBKqhVGStF0mA0xRmhG6tS2ANzPD+zRT+mhm7gM0wxdrIOzMrErrnB3hJaWFfs+b1yapkYOqTHd1\ns7dsyBguzNwMH573ln+hzu7N6GyvJ5jxCHJYSx3MnPI4Am5s8Phh8eFtQ/NpAF15/uZ0gtKnlzF9\nqyEgnFZiPyBbDR2E2nB2esNKNbqoGY3me8enu0HaEK0zz0zCDHdLVW0ey0JLmTG0UkKyUk62vfbP\nBg+taRooBwthZ6r7Qmk5OZFLhvXQrOWf/rY2Pngk0lgN72HAd/se2csRp5XYYVHq9jBaltPKXjmu\nLjMMvsolrAr3CTrHjO0+q22D7wzf63uZcEJXaZizMfbOSGcgUzGqOhiXgHsLKW4YCsvKOWR8yiiZ\nvw9hIRMMaS1NP2X1XbiFzXHL4ePhwpzd3XCsMzvAIytmGK5O1q0SaSTyy3prIYZ02OBOt2TCEJ1F\n+475v/o5NH4BtyGkoDvwC9qvsefYbfwAv41f4EN2LT0RUXbYQRyw0e/MR0svJjWUAKO7jc94t4TU\nmNMQbB1sMot8LqdjS2EzYH0MBMtZ0comWzNDjq8JSEesz+azR73YrDI2uns9xfUx9KxNWKTKQHlt\nLZ2v0KbSf272NkoMC18ve82qd0tW70NRpuE0KzOWvHao0RF1D+uq5xRhG3yqeaavtFnm6vquN6xz\nessWTYB7b1YVy9Jz1sJnS6/qWCLPsnKa7QWiPuZsYL1j5pOB08IGXEefAGLTPX6q4LCcF5xNSpSZ\n8Q7rnZ3FTBKFM9csROi0lxiydEGIUR1swus0YV0l5ZQ94jmFxviBHpuqMh1m5RNtlcfT1WQYVzVf\nXKc5n+9jmENvwKeyNZOjbH2GigMt6mivoIVd2PtqptesVVJVr/7Kmjh2gO+qR6KDos5j2sqzISN0\nuOXAT09qzyo3gApaq2QOr2pYe7t0h+d538iTssypN8b1bnN/02jhLoQQQgghxJ7f9D6Z4AZulZE5\nVQghhBBCiD2/wZkauF/33+tDV9yFEEIIIYT4sdzAPe664i6EEEIIIcQVrnHR3a/977WhK+5CCCGE\nEEL8WPRWGSGEEEIIId4BtHAXQgghhBDipln8qd+L38BbZbRwF0IIIYQQYs/1Xgeph1OFEEIIIYS4\naX7z6yD1cOpNMkGHM6XAsMOHcptNpeBcNgHcBnd31upS3zKXGG4AH/O7jg3mPu1FbwPmk7unxrHH\nwsI5efrveswnn0u91xuMuZkfHn32kKxZ3+GT42FYsz69qvEBS21kfCZsbA2ah1QVM0L5Fno2wwYL\n097SMHejOS19hL6FtjJrdqnVhDRr5tc7sw630sj1mK1seSEvHVLS6WkM3etgLSyPW5hjr9vG2KZV\nzgx6T6/tDDh9yl/TzxfuvTF0qUa21L3VZk/2VnUJQCpXbfFrhs+PAeto1S4MD63dSFoew4bYwFOA\n59VSN7cN7CziEKrF7OapCjffe0+NiJpPhpNyWTzVmCyW3HLQDuUIDJmlldsy09RWIsbF+7uXI5rj\n7j6VgbULZyTeUkDoSz0t3YHZ3Y5tMoa+iGyj2Mwls55W4tu9cHey9NRGy6IV5umMnFI0bINlTcK8\nuCkPsZcXsy2KQc8Pk17bKN8XX2m06+WwYDTojL72hlR1Y35ZLkaDDT45vTE5g9kME96lwjZFiWMY\nc90GY+NgfgEbbMI2tCXaG7pb+I72He0732Lv8QdwC4ARLuE7+OPv8P9K22C38T/AL/GuDK07MHyH\n3YoQ49HtnbNx66caSuYMZgPtIrvMBqy3fJ1wWFQ3RjPHc85yiB6c0//qzazRskcsJZ2Lb3KDN3zr\n2ZEH+GWkVsmb5/3EYj0p6YwOisOVQ7d5OVmjbl1obK/ILHO0Uv07r2aSSqdMvK4aMoHhvZsZY00s\nQ4wRp1l4NFOc6WnhzUT1mmc66NzNmMC9dLCLX9nCpLuIos3Du2kRT+ur8HJ8Rhr7jHWV85R7dRPi\n4VLPDjnkfYoOYD9GYuq/hde0Q+c2mO8q4Ob7rG4Vk2nvw47I+zKxx/CPk5AbHd0t2lwe4mU6reHJ\nARlSz3kjaasOMnxXm8uJg5K/WtpG02w6p0E243C5zAwpAl+JpWG6ajadrvRXFLsosb0jziN4GXxL\nVprdvSszdEwU26uK1nEvfPWB0uLWWWapm1UH7UhXt5WidUo9tnWwW323hluJivPzfllZujKzijfO\nnTt3APhhearucRdCCCGEEOKmiXvcf/CGGS3chRBCCCGEuFGudY/7a1WiXhMt3IUQQgghhPix6OFU\nIYQQQgghbpRraFOp5x+u8++1oSvuQgghhBBC/Fh0xV0IIYQQQoib5hoX3fU6SCGEEEIIIW6Ua7xS\nRg+nCiGEEEIIcaPEqv0a6FYZIYQQQgjxDnP66Ch4dPryzrPjB7n36MHx2dXf5C9unDt37pSA6YfR\nrTI3h0+wha6cbmMKPWMTx3dliAuT3Yxv3XroUyLpOyDdcwAT3sr3B23n1oVOFRq+g86J0hq+hc6h\nPjDBiJvT1+fH2mtwSWurQ0/42IAsLRV+U8oE5/ClOkO42fDmMJVb0HHHoWv5R9zksCvza8jmRoBN\nRMmxMYSAqT6cJwzrwxYI0y4MhkYHzduEUb5P9zYCliZLd5/CS2qZh81TSdilv9N3Hr5GgFZqTEs/\nK2O5V8HM/BIndXTRhVFabLYZixYOxkxpSt02hHvVd2ljJRSJhEjSMTPDL/BU37lPloLGoSR8uxQE\nWkcYT92XTXBrOw//H+CjsXP3aheww3vDsC59fg50Zj20iENaSCMb2oiFTdAdN7allozOao5ZiPdw\n80v2yQG+XbykeIMtHgEcHLe2zYZHae3cbbC9UnGG0d3NDnImahdYZ5k6M227cih2MBE+YBvMHb/M\nXSHRbJdZeCpssZDURsXMaBf73qTRzkNMuPSIe18xdPOLNCyGaLZdQrdECXYZadvk0/1tB4YdYF2G\nNPcauPvO6LDB6N2wjEP8xvELvMOGLM0vK202gPmIT2aTd+/BZGlGHOneSwfwvAtJpPuOLb7jPfhD\n2MAO/iv8E/zRr+m2+Ihf4M/hj/ADaPAcZpix99KJ6SO2wW7hYZLtG32zwfDeWAyOQ04W2cweBqy3\ndhH9ZdY7WDvPwWVDJC024LhtzBvWue8Asw05QndgRo/17q2G2ybnjnRJgvWOmU9Yc3qz3sC9me+g\ns8g083rxwiZyKfZWhpQi1zZYZz47DW+WVSX1kzknAq2Ex1HaZG7hgs0OCiGxDW6YN/x8P/VDJJ6b\nhSDZs6icaoyLmoV6o3kbLbPUDJaJpfJ2DOsxduDumTyE1Nbw2Xy7+nDkLdimhKkX+9GKlX83EnXE\nG7bDHTtw3JgtJNEMjpuXWdluQQtlsrMMGUsTs/WLnLVq0lnEcD6HHhtKzkoqinMWOs+hjbnv9vpq\nOgOnhfWZ/QeMmpRo59nkUGW3aSkcD4nsee2N4fkcOl+q2p5nogZ+yeLTTQ0wtj8R7NKqa0taUhOL\nr4SpfU68qV/NPNyL0EPp6udAWcC7cv2WC7aV4tQ22e/pGF6Uw8uHrfziNXUvX7fSPPu6u98xTh99\nxuOTk7ucHT+4/+j05OHdK7vPfvXh45Mnd4HTR0efHx99zudffXJ88uSwfvHk/uHNVPwK13qP+2t9\nXcw1eWuuuL/8F9gP/8UmhBBCCCHeLk6ffnnv47sAh0effPTNty9eQ7/7sFbyhx98dHXXS7+4Ka63\nagf36/57fbw1V9xf/Avsyft/84N/sQkhhBBCiLeWw/c/fPb0DF59Bf3s5Cs++fzw8PDJg0dHR0cA\nH316/OSVH/7Hf/xP680//dM/f+2VXXPnzh243tr9jfPWLNzvPnyYP8UfXKdPv7z38UOIv9i++vaM\nu2/D/zoRQgghhBC/G6eP7n/1yXHcIBMXas+OH9z/4m9O77/qQu1PvVJ/Jb/85W96q8xNPJz61izc\nF/IvMH61/OZ7/mLLP89WnJyc/PT1E0IIIYQQv4mzb7/56IO/eMWO00dHTz44fnL/EM6On3zz6ecP\ngcP7T4558Pnx2d0bv8l9eavMb1q7/8zeKrPc1r56ivj00f2vPvn8Wl128hI/YV2FEEIIIcRv4O7H\n9758egpwdvLVsw/fPyQWfPW84tnxg2XVTlyc/eJvYt/+CzfMnQL4QQfTz+ytMof3n5zcX/9i9RfY\nmu/9i00IIYQQQrxF3H34+GneFHHv8cmL972cnXz1jGfP7h99AcRd7cefPri/v8f9LXmi8VoCpp/1\nrTJnxw/uf/XJftV+9+N7nz09fXj3bvwB9uAt+ANMCCGEEEL8MHcfnpw8XP/i8P6Tk9WP91/4/Ct+\ndYNcb8kO/LzNqa/4C+wH/2ITQgghhBDi9VLqpeu8VeZnvHB/1V9ghy/+xfaTMqf5yKe0i6T6ZrvS\nekxlmClNko+kQIb8gC+bc+pRlr0pguhKk7Sr71p9Mu0ZYDDVZh0ag2312IzHB8LM0FICYAd4K4VT\nlGz19QlafSBlGiuvjq82W0onUlgRBW7LnlGmjkUoxISPvm/IJdbj5XtKkxTQTxAFOkwcVMwb7tOi\niGHCafQlNZhwVntbuFp2+yAz7qPkMDdsoscwx5mhm8w6cG8TDdjRdzHY3B0fzaJXKP3T0isTjIbh\nZT7C8cEAs0XwtBzbaHiH9YbjrTajv8PzEjacjtT0jNhS9RFwz/GYgidfW0Jwt8VF5a2Z7aCMJEz4\ntqrdjBnv99qOSFPr8K5UOJaFuzs7w8232EFZscB3caz0N/mSuM1C8WUbiwmrbTPPUkFyWaKrDJpj\nFnWz3n1rON5jAzTzHd6WmOSNgL5z21jzDItT4hWjjdCZdXhPCJv2Ee4qCENWwEd3g20qfjLVtqRy\nKxJ9cu8jAdwnfBduKVtMZtYbA94sY9hjB9lFvoPe7cCsg8miAvQpfvJmbcJuY0PKudqMHdQQ2uFb\n88kdu8V78B40+DVcwK+h7WjP6cYQvdEu6KLgPyCMPTTsNl4j2uNQfXjJYHCGiR6zEJmN2OA+mJm7\nG2TQQn8T+Rk+KY+JxtwGbGM+Q2fudAeR9PiEz1hIkWIczVFk5q176YQ6fOduljohJ4w/OUbiStWE\n77DBo/AY0tbXRawx9tbMMsOIb8DNejwma/MacaUQ2sSrlS0EchkUBzMfV0a9EWaL/srpfoTeLXxy\ns3nnhqXWZ8762Ab6Gvgd1hlDTsdRT+vzw2HGypo7vi0dm+HN2FXSNnxeTdbh9JlC0gQYuwxpWntC\nu7Wt4RZqqst9kvsV/xo++n4IRGkW/iCL0tYjyKeI0+ocFt2S0w5gNYKi5rFZgr2pZG1W2izDd1hn\n7vtznm32rjfrUhfFHBNcnf9mYv6s06czmntMI6SBa1vNtDKmdelfizTOdlnJqvqyzsVUkFOWY9ZC\nr3hQdrYZLve+Jx+xvirTwi0ViY27MxmeRrZFq+TTFcHTXu8VibeyfZV/cX+m95VyK6adlOiJN8p1\n3+P+sxYwCSGEEEIIcdPcuXPnB59JXbiBh1O1cBdCCCGEEGLP9dbuP7O3ygghhBBCCPG2ca27ZX7O\nD6cKIYQQQgjx7qCFuxBCCCGEEDfHtR9O1cJdCCGEEEKIN0u8vj243qodLdyFEEIIIYR408Tr29fL\n92twA6+D1MJdCCGEEEKIvX2J61x318OpQgghhBBC3BRx0V33uL/ttH/CDkpgdwGUlDS8kw3Kn+pb\nuCzFKdAgXIalDt3v9drsy2AaXkMrdZrjlyU9vVVOtxFYedZ2AITmckyjqg34nEq41FZ2pQ4sTZvv\nUl2XhsQGjfYc0i2Iz3iq61JimjK7oTSU4QeMtjTaee3tV15YK/PgZVkBwlR4CXNZ8EqDSFtl3Hf5\nxdRcbvf2Vo+Q9vt2cVmHDpPdnGVGVTNElKkwBJqdpxVxh9PwfWV82/Y90uFjg5aKvR7fOt2078E5\nxaVZ892Y3+1jF1gDrDcPId804dgQpc8+TXSY1RcmD6trikV9qi4MFehFRbzDOnxMT6ZtCJ9e2xEH\nC5ujbzN8tsFn2K2iMEd3OmkGpV06ljVxIi6ApU03+qAz61Po2MJD2ftiY40omEFn7SK+DD1MuHu6\nIQd8Ij8MlGCVEe/K8zpHn7kNhmXa7ZMefHSwyCfradvctE2odMsq3GEDbXQzwCJNQ96JVR84PuKO\nbbL57RKa05sN+GzsvLnZYOH7bM/LkLqB2dqOsDla75j57KH/tI3bYD6aj1jvdtsyzxfxcvWIbbAD\ny9G+KwHtjM9ugx1gf8h/C38IE1zAP8EFPIc/nvBz/Nf4bZjwSzBao/tDiOF/DrdyNgD8AjYwpNrV\nd9gGNmC3SxZrYNYf5CUid8yxW/ic/0KGbB0+lSl2KJfkeU1DAzjtvJSlYQXeepg44/PtMudK64we\nP8cd65wB3BgzIxa7Z3x+3/uLAzgEtyPM2MbpcTfOAffFGdwsS4tmT+5bw8oVOuJt5SVt+GVMph4G\n0/A8R9Mw2FprbmX2bctEs8nZvMWI20DDL3Cgc+vN53JkNuxWiZm3GfaYr1O/Wo7hvYv3VkmhHRzb\nxM/GCOZsLFrou5VOdVFtxzSHxYBiMOvwOK9Yjn13PCcWpzejam7QxdxoMXelrRN8W/rV2d3jDFea\nUrxdmO2dptlB9Jau0DESrOTKc9iTYVOG1K3FuHbHcfYKVXyuDipFtF/EoS2VtFu8g2YxEVWmRVVp\nuzqb9tDVZpfzjO/IWStqYvglHuOnc5r5pdNbyW1SGp1n0zG9sGAxG/sMF2SUwiF9kYe2oYLgbgfZ\nWdEj1hvmTCtxbO80i9yoqDrN2nltds5kiDfN23yPuwRMQgghhBBCJNfTpiIBkxBCCCGEEDfDj3w4\nVVfchRBCCCGEeOOsV+3Xuuju7br/Xh+64i6EEEIIIX7u1Ctl4Edfen9zaOEuhBBCCCFEInOqEEII\nIYQQby/LVfZrv1VGAiYhhBBCCCHeLNe+yr5GV9yFEEIIIYR4s9y5c+e6wtQFmVOFEEIIIYR489TD\nqde/9K6F+w3S4RPWoAvlWfpT7SBvYQprqVm+QjM3F7/pDCGaHPafT/GZ7QWX9HVD1EzbYSVb9Rnm\nlXl0l/7U0GvScF/11VxO0/D3TcAi30xnpU91rFCHjqVH7eorpQ71LVzsvbBMZQBMb2hWgIMr5sE0\ne9belG+GGXBXAr51TACroHUVw10E70oY3bHbe4OsUw2fq6WLsDYasjR8xKeKoZVONQSOEdItbF4S\ntQ6r+FP23LAcXmKbithcRtuQA27T8Bpd7CN0nhLZULdO7q2+PuOzw8SipHWHKQ2bLf5kbwwY5rPT\nnK6FitUwn5x+i6VJ1MNpaliofX0qh+2AGd7wC/ASSTZjxLvQQxrQ5r27MeLoq07yLd55iic9ZIGW\nBlrPXvHofgvxYQWlA2hbbMZ692bR3zam9RfcJ1IkmZuhHa3CY0gYKS8cM8/cLFMtBtU+mdx6Y4bO\nPBJil0Mig76DPvrbcXwyusyeDAvYLZiNHr/EIyzm3nDMtiEcxSO3Qq0a8lfHJ7OhFMST+Q47yP62\njvYcey+VnD7hI90B3KqMnPGtt63Z0P0J/T/nv4E/gf8XdhB5OpFJ6Dv8Et+Wu3Nx6fb4gG33PWC3\nsA12G3pscwBD6TC78oYCE83Llgw+kl3Q5yYz3pWyeA6ZLt0tfHbciB7vU+PsXpJLs5Tv7tw2Fvkc\nCls7SN2mT7CzSgZ8ChVoWYFH2iXWOxszwy/2QxcWsatlFDDGVZJ7eZ4XR+YYw6wcmZVLMX37iI8p\n76R521VOrpSZ0cz8zRIlHLO2hQtswA5SVe1WDWn4WIlXts6IvJWIm7bPzEWNzOBmFg1JTW8LO7JZ\nCVbdnbFiOGRYmI39oDDfQRfHK0mtGb0zhPnYmGCTcmWfIaTOgLmbxQRqPdab7/AJ2xjumGWErWI+\nwhYGrHOPxNhiHbZxjw5y88uS43beRmNbVuYZZtygz8P7iPcVpbYyRvfmDTPaLnMy8Bnr3CPDd1lB\nqOHfcHeGcutuzR02MWU5bn4e8uPa3C4zHr6t/upXUz/YJjXMzPmZPJHUV/aJCmZOmH0na5eZkzR8\ntnQ8bwg9qs+4W3c7zyXpJx4sym9pI6+GiDdHXHp/ax9O1XvchRBCCCGEgHpE9XryVJlThRBCCCGE\neFO88Mr2H/OIqt4qI4QQQgghxE/My4qlH/1WGT2cKoQQQgghxE/N2pNa7JfyusddCCGEEEKIt5Rl\nKf9j3iqje9yFEEIIIYR4U/x4Z2qgK+5CCCGEEEK8QV5128x10BV3IYQQQggh3iyLfYnrX3fXw6lC\nCCGEEEK8SX7bW2X0Osibw7fYQLvIu4f2Qs0Jn/faO2+47y17IRZMz2jo5MLiuZhB416kAR+zwPxu\nGDTTmgfgHVyW0LTHQx3a9l2UltAoMByll6SMM/aOVVppPnHYlPo0LGyLXbWBpW1z35AQwM3lGe1r\nb8N21fCWBj2vKNFo55iVt26RwlJe2F0pYDfQwpB4RfXqW+jL1Trh/x9swFKxlx+rvayUqNmWoZx6\njp9XDx6UozCiPcCEX+KODXvZatvu/bU4frmqmFUHdavNJeBzSDNLjjtVpwwVlpVTL7SS6V4dyll7\nAQN2UFLYHe4eXkKcdu7W4eYMsAPHhxaNDa+o25ghzXwYAesNzN2ZthjWR+PnspYO4Wv0NmIYQzky\nd2GmxDrHLIWaZvTuGBWFcHD6CM29L43lTNtinWUeT/hligkh89i3MJj1FTXHenN3G6xdVOd10Hk4\nTfey1R1QxtMGhHA08slCSlqbgDPl59NwO0WaWvboJd5XQ2Iwn0PDNtiQGlE6S33j7N6MSPoBRnyH\ndU5v6cu9wHekP9XwHT5iG6zDDmjnWO/01h0AtHPYYRvsICYCa9/RLmx4r/8XF/8C/hj+C0wpfmQH\nfok/hz+CCT/HOzjANvgMu0wz+2O6P8GGsG3CpsSsvjPGmjui5pFJmPX4zn1rVhrhNpZVdHCfbJmn\nMg6Tz1vL/jVoMIUr1GxwmrXzxb3qNHx0sDROGy0E1GHDBaYwn3qofNMzumTLxF70O+Ez3pUU0wyn\n7aK/nN5w/NdgzmDW5TzifRpVPSSXo62nPPeVD3XCB8wsPbtTpOvec0n6kM02i8szUst9spy2BnIu\n9BzPKbks6SxgXWqlfQ6TK2A+7YW1ADtLj6/D6Bm0W3USamFyrRhepj2Wzq231Mo27BY+4g06z3Y5\ngG9TExsDMKbvHCONFtNWZ7ZMx2mozqkAh40zmBk+ujdjLnVrSyGxbVKh6juLSTBWMy2mDsw2NVEM\n0DtmNNjSHOuxIX3gfhEuXne3lPi2cDkD5jOQA9BnS7vqBmZvbsxptGWAyVJXHoZah/MIhmVuOP6c\nHMtmHqeKZnYLJghXa5h3Yz7cYl2OoLD2XnHrNhzHLDzNreUJwww6axfZ6XaAN/fR2K1GRGP+DjN8\nSOuzn2M9Xvbim1gX/mz50e+CBN3jLoQQQggh3mlOHx0Fj05f3nl2/CD3Hj04PnvhG/vfvCm+/vrr\nr7/++rdataN73IUQQgghxDvM6aPPeHxycpez4wf3H52ePLx7ZffZrz58fPLkLnD66Ojz46Mn988e\nHeU3bobfdtWOrrgLIYQQQoh3l9OnX977+C7A4dEnH33z7YuX0O8+rJX84QcfxRe++fT44U2t2n8n\n3K/77/WhK+5CCCGEEOJ1c/j+h8+ensHhK/eenXzFJ58fnv7Nl8++/PLoCwDuPX7xAn3wj//4n9ab\nf/qnf/5aKrg8k/rborfKCCGEEEKI33NOH93/6pPjJ4ec7pfrr763Bl7fSn1NrNp/h/tkuJGnh3Wr\njBBCCCGEeN2cffvNRx+86nL76aOjJx8cP7n/wr5X31vzU3Hnzp07d+788pdv6HCvCy3chRBCCCHE\na+Hux/e+fHoKcHby1bMP3z8k3iRTb5g5O35wZdV+9+N7Xz6Jl8nsv/AmHTnI3QAAIABJREFUiPfJ\n/G5l6K0yQgghhBDineXuw8dPj46OAO49fulVMWcnXz3j2bP7eVP7R58eP3l4/O2D2P7o0+Mnb+Yp\n1d/WuHQVl4BJCCGEEEK8w9x9eHLycP2Lw/tPTlY/3n/xC6/63U/LnTt36sff+iXu6OHUG2Vbgs8Z\nKHlcww+gS6Fb/mt4GD07sDLlheX0oExnDRr2Hj5m4eHjNCvxoYNhAz6noxSgLy3oxF4WOZX69AAL\nQ6eX3bPBXJut5IPhqrN0l/p5NbDDGr4Fh77Mkuch2sMOwtyZOWgDPmETbU7FnhvMOLiHY7HMoGRY\nHLgEYIAe38FUjeqrRdv6TVhmtyuL5QTbGgIDbGEuU2z8X6aIcMhcu70hlfAcTtkjYegD2ncpzmMu\n362lYdPDhrvenMqfWmrCcNjtFaqXZc/twrhX9WyZJ5kbpPCRPt2COO35atNo1SNhh2yXsMhc5+pf\n4KA6K8y1t7EwJF6W9zC6+9flZ+zBaZdug+NZt7Zt1rVM0QH3KfM2zaFTVv4AbEox7bD06OyZjl3J\nWv9/9t4mRq8szfP6/e+97/tG2M6smqF7hubDSaZIRhrlomEYMUgOKYda5GaQyCUyKk0bIWo3bBAq\n4dGkkEWK2cCO3OBBhYxYIBoJJJQjJZNSGIllSxgBY+iaiun5UE93ddmOiPfj3nv+LM5zIiI/KtNZ\ndobtrOenkBzv173nnvOc5xzfOO/5Oa5cvTDlSXs4NAsprVoJiaO6euX2DiPcbJ0bM4R5tHYSj2gh\nmozXG+gVNW6otTYo4n1sMT3g0V4LNRmhW3z0VA+ttxeUxQX1lMlY1dGoobk/B0sCex0NpKoq3cKu\nddcFPo2qV9fcuRvUW0tpYYrmx2iBVjCLkTKbnbqVsSj4FNtY1dPrsf+z/LP7/NNr/mFLP9sa7Gu0\nxad4r51nTSn0Vxn+BbQHq2j08BM3x2J0bcw81t6n2p+9Q+DqGR7wGgvCPYmBnapOmYKjCaylmHEV\nIIN6I4VotlP0RuMNGhSlIdpUA3Rx6uropWvqULtWKQK7HAuhoX4Y09Jr7QJzeJ5bl1JVFmsBFmvK\nZPViUBhSN+3sRNN7Rqvon5HGFlBj8szHqarMNChsvghcTqWzsxvPYtEG6y2clYTWY4UGV9UrUGa6\nZVxRORYYoRXe2kXh1zzLiaU5hqeWC2wtVTNgtWdX5apHKArTssD2VpHcOxl7UtRwzTub1taKnFWm\nc2dtDHLVOF3jaX3mPxaTMcVoIdbQUzbhUdbQshiK1lQIqDW0TjfHANDt2xYWTc4qiYlyeq7ppjAf\nN41rrfCCJJtuiSdRBczER8oIs+LjikMxW/vyCCNlOh9m6CmPmie4g0IZkarL2fTyY+xwBtPhreov\nGlwmsY6MHNU+xt1W9WCBiy/Uw+xSauRIHS4up1IXXmeXNjmobl0iaONhzczjhZInLy25j3uSJEmS\nJEmSXArP9v3UXOOeJEmSJEmSJK8AuVQmSZIkSZIkSb59nnUr9+eqRH1KcuKeJEmSJEmS/DryygmY\ncuKeJEmSJEmS/Hrx4MGz7CdTyTvuSZIkSZIkSfJt8szqpUpO3JMkSZIkSZLkW+D5eJfOyYl7kiRJ\nkiRJknwLVO/SgwcP6haQzzp9zy+nvkC8C8mMqjxogGrw2DUZU7XkVLvLtjmMquukmkm6pk8yntEQ\nRgtP7YMzdhNKdE0sM+GCSjMNze3jqxAzeddsD1NTkVS9zgSCse3FP+AJxqbXEK4eqDNb04S7qklp\n+o56XV27hOmCb2iCuWkuBkxTQVX/VI+I94RaqMSVhmWltM+CqtanxGchNENVd3WmdqLGf0FLcNig\nzrUnpX3WeGiqpgmaYCfMQcJjq6IOl+pPiXJ6bv83rg+bmMiOi9X+hauem79lCr9VVReV0zi1VlGB\nIW+qF9g8UFR9SvN54WbbKK351I5cDyLk8xJqQVUM1eCpkpMzJYvOPt4MHiyavKVrzqZdCznONUS1\nBcMu0uMRddCUVRFRMx4KXYnmBvcFSrynn4QwnrcYDYYBb02JkmvZOszcWmsC5CYT8VytJdLUApEW\nATtkEJ6NYNKFYDKS3A51JgarBy/WQh5DtRM2srNKr73OUYCyg0kMVa6ksqY6fWRZhJSo1ukW1lav\ncLIYJlFsVJ0p1QqmBUieqVqlGlJatXCUZJf6EcOAJJfaz+2Jju77fG/Nteaq2bWfvQ3eRbt3A/1v\nMfzz6CpatB5N9MRzScvQssRZ7wP3kySqYG4oGLE2FkJLu8gj4cY6C9liepiqA8teK14tAlz7SQd9\n0yHR4u8ibo66KbocncIvU5sv3FuiCXHoTQF0fqjZSCHNKXFR0bfPurSEzKSaROgs4VHhESvSoqUG\njMWgSNYh0BEFD3gM4Q4LI0DMwvYgTbbFWB1SUj2yhKuw6DyM6fEs9Xgbnc2j6RW+HksLvIFOHq1F\nTXzySMiYjEefxZIWqgNMSONomX2M4SRUfJZntHR1Fbm6tAjR2JnrJ55xeKmiWmrIWhooa9TVcqIq\ngVM0kHpcrF7lGHW4b8fb4elc7VR7OsWUEKLV8NACz6rdObxsNZmcXXg1f410dcBr7j0hm064Jodt\nbV95vJAxl5TSRF07GOQnrT8BwmfDTy31eXRhRdlcNV4KrZJHtKpiOLyrDSO7Gc7smtkYquTPTAol\nXM1ms2owMGLwJA0xyYvCKAYDnw0emIUiuZdms/psyZNn4OLamOd0u50UMCVJkiRJkiTJc+add96p\nt9uBZzAufY4UMCVJkiRJkiTJt8DZ3B2efUsZcjvIJEmSJEmSJPm2eFbp0mfINe5JkiRJkiRJ8q3x\n3Na455dTkyRJkiRJkuTb4Dlt335GTtyTJEmSJEmS5Ffiq6fmz28/mUpO3JMkSZIkSZLkV+Jsp/bP\nPf+8p+yVnLgnSZIkSZIkyTNwYfeYM77kTvwzC5hewK4yuY97kiRJkiRJ8t3kwYMHX7p+5nd/9zlu\n6H555B33wCNSs/vRfJY0nSRQcGkuuebaDM+gmyOy+TVDklo/ODc33DJOBHiLrlzQW/YXNgOdqRrK\ncLgan4LCTFelrVWYqup27ABUQsgazrUeDSHaBNiiZXg97dBTRmGEeqq40Jv2sG+OT6qHrtXSLt7s\nLVFB4wW3KNWlGL7PWlSfPb+NgkX5a83swj4bp6sqzAm2AF40vWtzL4YMcGy+vLNznSlLaULG7vwS\n6jHDb1qwYUTCPfRxLVKYbsNfWz/aRe2xbCbUqVXF9rz1wwy4d26TZSQUojMMsA3bZbTI3Cq5ai+r\nlO/cWdn+9qZQn57ZcKNaqqtxe2661RjaQUpYKePC5xZF3fmlhap2gLGdVE1CqqhApuZV7Zuhtskx\nPTiknT0ezdCkjFsYsHZnXQABo/rBTEzQN5MieDYdqgLh89DvWscbFQ8X4eP0KC3w2gyAoqYW9Uy2\nBaij1Ggw3llDNURag8K0ugyv6lnot1PLo9kDFMZehaUSFLrjWh41PWp1jlqqnsVVC98RsJZ4LQZj\nhSyzNkPVMlZ15QRSNX4u+R7swzGcwhpOaxtuw5+4+PMM/wysQnPr2knnqrlFBffn7aVVixY3yfEO\nuhoQeCwMpfZrr4y31VFqijw0mXBBnWpOdK2QCWMGNdGuXSS57KSFPbZ66M7tnhpwCbdo6KMjQdiT\nquk2+sCMZI9iBWPzTTYPs6cmAa3a1GaFBbSKnMUMRZ5DBapepaDBGvBaLPBkDYC8U009UZjSCtDB\nbIpqfnQTxIIlCUpRFFJVD2zvpAVUEeYUSm2toEQIeaRsUG/3irRSe2z0DbvovCTgNVRBL6oOUS1a\ngqujgjiLzLN0r0WzPRe7BqqMxWzqeY1nt8O2y+9d1tJ4ViTVZFQrvzaNx9aJ6tWN1FbziI16I535\naL1THSNrLCFFmHIuow4bcU1hy3ASR7btUTNRe2stzoykbVSrnb2rnxId6prddghfNz3e1NHL6gH5\nTFBaratVcr6IUbb2kxgywVMNlQvS7LkNYNWL3HqHN9A3C+yielhVveXeWgtAnqxBnttYO+PZkhhC\nsV6PrDqE1KkD0mwXRVEFF+22ybPypTfXn3n9TC6VSZIkSZIkSZJvzvPeNOZrSQFTkiRJkiRJknxD\nLs7av52von6RvOOeJEmSJEmSJN+Qz34h9TO33r+1eXxO3JMkSZIkSZLkGfjCrjIP+Dam72lOTZIk\nSZIkSZJn5FJWzuTEPUmSJEmSJEl+Vc6m7N/+SvecuCdJkiRJkiTJN+FL95N5//1ve+6eu8okSZIk\nSZIkydfxIraR+Rx5xz1JkiRJkiRJvo6v2EaGy5nK55dTXyRuUsVqkZxDCxomvipULJSxGQBLmCa1\ngl1Y85jR0FSgVcc2NI3ljLetvjtc8AlatP+tTSGIDMMlMDWrKM3MOp6/1ERvzf1XPWutYGHQnEPm\nGIbFqpAbYGoeOoeRNCSSChWrHabVkL75/G9BqnbVHVrg0qycPRpaDVS/3hCiSZ+G8LU64LxpAldF\n+dU1q90A04V6ENQqWoJbaaemRO1Cslkttr4oea0eQzWRZ1XG1grZwRL1qOARCya0jMaNq+7xjJYw\n401rzbMjVwFq1zy7pdn6agAcx6vUOtx8pvnKGg2cW/M6GFr9O4yzUdVdGFJRE9AKjFbQ4RnW5+rZ\nGgCmiQXHdoRFi+oxlIUR1VWrOIeLMnyoVU044A3qz6W/4Rlc4tMWLdX0V4NqAuE16qNgVdIZFV5f\nWmFPtfXZ4VVR1Tr2MvZU6IskkF1rc1IruqeJoVozBzPhSXSimhTd4qanVo9H2WiBNzWYFGLCXiHj\n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\nu7gFynu4WRVBcuIhdo5yQ+2MqAdBMvyO5Odd/3VJAAAgAElEQVTUnYCIW6TyENmK2km0IDuN1NSd\nAIOdxm8Qu5g6WpCdpHIRImYSwI6pZHqcJvsh8+yTl489+exP2OeJp9d+/GE/tvGD7J0Hp/4f//Sf\nzvyn/9T8F//i3T9pKtyTJEmSJEmS98azT36Jr1y5cuXK01+8+aW3Kt3Xnn7i8uUvff1HH3X5Kb6w\n+ssZ4nvknS8q839+7WtkWfOf/bMTe3vV3/mdd/OkqXBPkiRJkiRJ3hPPPvP1L3zuMYCVy7+1evPO\nj8+grzz+1JWnv/g3a/S1p5946uzTT/3e2V/WIH9mb7kc5DufcT8mjYaZnp742tdmv/tdd+HCzzeS\n1OOeJEmSJEmSvNdWTp+79swarPzEvdaefuKP+KOnHl/h7btknn/+m3/z7qOP/r33ZoTvzs+1GiRm\nctJ86lOz3/3u4E/+pPUHf/CzPjwV7kmSJEmSJMn7Yu3KN65du/b45a+O7j/+BE8/9fiP1PofkEr9\nR/x8hfsxGR+v/sN/uPj7v3/4T/5J91//63f+wNQqkyRJkiRJkrzX1u7cXD37k6fbjxtnRp7+4urq\nF3+8av/AehfBqQCS58DYv/yX8/fvVz7/+Xf4pKlwT5IkSZIkSd4Tj33uC19/5lk4nks/d3qF48tR\nf8IKMx9W77JwPyZjY3ZpafLf//uZZ56xp0791CdNrTJJkiRJkiTJe+OxL3/lmcuXLwN84StXHvvx\nHdaefuLxr14DHr/81S985cqX32KXXzlmair/zd+ce+WV8pVXfvKeqXBPkiRJkiRJ3iuPffnKlS//\nzQ0rjz915W/fe/ytHrfy+FNP/WJH9t56x/lL74yINJvZxz72k/dKhXuSJEmSJEmS/GzezcWpb0cq\nlZ+8Q+pxHylfwi1jJkeBkWYWM4FdeTNtUQDiEbFDPEJqaA+p498gdrAniB1ii3hE7KKRsI5ZRDvo\nIdkD2JPkv4aZpLyOvwsGqRJbhHXiEeKI+5TPIw0Q4j4E9Ag7hw6xJzATo9hIPcRMYcawZzDTxDaV\nz4JimtglsgfRIar425gxzBTDb1PewEwhORT4+5hpxI2iT/1tzBR6BEL5IvEAqVK+TNgdvSb5JwDC\nGuWLSJOwiXsAM83wWbSLO0/YhEj2UTRgZ5Eqdh71hF2kjnsQqUJEh5gxgHAPdxodoAP0iPJl8k/j\n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\nAKbA/wEU7C8+KV12mwAAAABJRU5ErkJggg==\n", - "text/plain": [ - "" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "loaded_data = qc.load_data(loc_provider.formatter.format(loc_provider.fmt,counter='014'))\n", - "plot = qc.QtPlot()\n", - "plot.add(loaded_data.VNA_magnitude)\n", - "plot.add(loaded_data.VNA_phase, subplot=2)\n", - "#plot.save()" - ] - }, - { - "cell_type": "code", - "execution_count": 69, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "demod_freq = 20e6\n", - "\n", - "cavity1.power(-55)\n", - "cavity1.frequency(7.133e9)\n", - "\n", - "localos.power(15)\n", - "set_localos(demod_freq)\n", - "\n", - "qubit2.power(-30)\n", - "qubit2.frequency(7.5e9)\n", - "\n", - "localos.status('on')\n", - "cavity1.status('on')\n", - "qubit2.status('on')" - ] - }, - { - "cell_type": "code", - "execution_count": 75, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "DataSet:\n", - " mode = DataMode.LOCAL\n", - " location = 'A:/TransmonExperiments/GoogleDrive/T2acquisition/Data/6QAK3_A2_qcodes/data/034'\n", - " | | | \n", - " Setpoint | Q2_frequency_set | frequency | (251,)\n", - " Measured | single_controller_magnitude | magnitude | (251,)\n", - " Measured | single_controller_phase | phase | (251,)\n", - "started at 2016-11-18 20:50:01\n" - ] - } - ], - "source": [ - "loop = qc.Loop(qubit2.frequency.sweep(8e9,8.5e9, 2e6)).each(sing_contr.acquisition)\n", - "data = loop.get_data_set()\n", - "plot = qc.QtPlot()\n", - "plot.add(data.single_controller_magnitude)\n", - "plot.add(data.single_controller_phase, subplot=2)\n", - "_ = loop.with_bg_task(plot.update, plot.save).run()" - ] - }, - { - "cell_type": "code", - "execution_count": 76, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "a:\\qcodes\\qcodes\\instrument\\metaclass.py:37: UserWarning: Multiprocessing is in beta, use at own risk\n", - " UserWarning)\n" - ] - } - ], - "source": [ - "sing_contr2 = single_controller.HD_Controller(name='single_controller2', \n", - " alazar_name='Alazar1', \n", - " demod_freq = 20e6,\n", - " server_name=\"alazar_server\",\n", - " filt='dot')" - ] - }, - { - "cell_type": "code", - "execution_count": 79, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "sing_contr2.update_acquisitionkwargs(#mode='NPT',\n", - " samples_per_record=2560,\n", - " records_per_buffer=1000,\n", - " buffers_per_acquisition=1,\n", - " int_delay=2e-7,\n", - " int_time =3e-6,\n", - " allocated_buffers=1,\n", - " #buffer_timeout=1000\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 80, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "DataSet:\n", - " mode = DataMode.LOCAL\n", - " location = 'A:/TransmonExperiments/GoogleDrive/T2acquisition/Data/6QAK3_A2_qcodes/data/036'\n", - " | | | \n", - " Setpoint | Q2_frequency_set | frequency | (251,)\n", - " Measured | single_controller2_magnitude | magnitude | (251,)\n", - " Measured | single_controller2_phase | phase | (251,)\n", - "started at 2016-11-18 20:56:48\n" - ] - } - ], - "source": [ - "loop = qc.Loop(qubit2.frequency.sweep(8e9,8.5e9, 2e6)).each(sing_contr2.acquisition)\n", - "data = loop.get_data_set()\n", - "plot = qc.QtPlot()\n", - "plot.add(data.single_controller2_magnitude)\n", - "plot.add(data.single_controller2_phase, subplot=2)\n", - "_ = loop.with_bg_task(plot.update, plot.save).run()" - ] - }, - { - "cell_type": "code", - "execution_count": 81, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "localos.status('off')\n", - "cavity1.status('off')\n", - "qubit2.status('off')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.5.2" - } - }, - "nbformat": 4, - "nbformat_minor": 1 -} diff --git a/docs/examples/Qcodes example ATS_ONWORK.ipynb b/docs/examples/Qcodes example ATS9870.ipynb similarity index 99% rename from docs/examples/Qcodes example ATS_ONWORK.ipynb rename to docs/examples/Qcodes example ATS9870.ipynb index 4f025b9e62bf..d5dec7e0566d 100644 --- a/docs/examples/Qcodes example ATS_ONWORK.ipynb +++ b/docs/examples/Qcodes example ATS9870.ipynb @@ -1657,7 +1657,11 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.1" + "version": "3.5.2" + }, + "widgets": { + "state": {}, + "version": "1.0.0" } }, "nbformat": 4, diff --git a/docs/examples/Qcodes example with Alazar ATS9360-Copy1.ipynb b/docs/examples/Qcodes example with Alazar ATS9360-Copy1.ipynb deleted file mode 100644 index 11ece4bb6e29..000000000000 --- a/docs/examples/Qcodes example with Alazar ATS9360-Copy1.ipynb +++ /dev/null @@ -1,3594 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "application/javascript": [ - "/*\r\n", - " * Qcodes Jupyter/IPython widgets\r\n", - " */\r\n", - "require([\r\n", - " 'nbextensions/widgets/widgets/js/widget',\r\n", - " 'nbextensions/widgets/widgets/js/manager'\r\n", - "], function (widget, manager) {\r\n", - "\r\n", - " var UpdateView = widget.DOMWidgetView.extend({\r\n", - " render: function() {\r\n", - " window.MYWIDGET = this;\r\n", - " this._interval = 0;\r\n", - " this.update();\r\n", - " },\r\n", - " update: function() {\r\n", - " this.display(this.model.get('_message'));\r\n", - " this.setInterval();\r\n", - " },\r\n", - " display: function(message) {\r\n", - " /*\r\n", - " * display method: override this for custom display logic\r\n", - " */\r\n", - " this.el.innerHTML = message;\r\n", - " },\r\n", - " remove: function() {\r\n", - " clearInterval(this._updater);\r\n", - " },\r\n", - " setInterval: function(newInterval) {\r\n", - " var me = this;\r\n", - " if(newInterval===undefined) newInterval = me.model.get('interval');\r\n", - " if(newInterval===me._interval) return;\r\n", - "\r\n", - " me._interval = newInterval;\r\n", - "\r\n", - " if(me._updater) clearInterval(me._updater);\r\n", - "\r\n", - " if(me._interval) {\r\n", - " me._updater = setInterval(function() {\r\n", - " me.send({myupdate: true});\r\n", - " if(!me.model.comm_live) {\r\n", - " console.log('missing comm, canceling widget updates', me);\r\n", - " clearInterval(me._updater);\r\n", - " }\r\n", - " }, me._interval * 1000);\r\n", - " }\r\n", - " }\r\n", - " });\r\n", - " manager.WidgetManager.register_widget_view('UpdateView', UpdateView);\r\n", - "\r\n", - " var HiddenUpdateView = UpdateView.extend({\r\n", - " display: function(message) {\r\n", - " this.$el.hide();\r\n", - " }\r\n", - " });\r\n", - " manager.WidgetManager.register_widget_view('HiddenUpdateView', HiddenUpdateView);\r\n", - "\r\n", - " var SubprocessView = UpdateView.extend({\r\n", - " render: function() {\r\n", - " var me = this;\r\n", - " me._interval = 0;\r\n", - " me._minimize = '';\r\n", - " me._restore = '';\r\n", - "\r\n", - " // max lines of output to show\r\n", - " me.maxOutputLength = 500;\r\n", - "\r\n", - " // in case there is already an outputView present,\r\n", - " // like from before restarting the kernel\r\n", - " $('.qcodes-output-view').not(me.$el).remove();\r\n", - "\r\n", - " me.$el\r\n", - " .addClass('qcodes-output-view')\r\n", - " .attr('qcodes-state', 'docked')\r\n", - " .html(\r\n", - " '
' +\r\n", - " '
' +\r\n", - " '' +\r\n", - " '' +\r\n", - " '' +\r\n", - " '' +\r\n", - " '' +\r\n", - " '' +\r\n", - " '
' +\r\n", - " '
'\r\n",
-       "                );\r\n",
-       "\r\n",
-       "            me.clearButton = me.$el.find('.qcodes-clear-output');\r\n",
-       "            me.minButton = me.$el.find('.qcodes-minimize');\r\n",
-       "            me.outputArea = me.$el.find('pre');\r\n",
-       "            me.subprocessList = me.$el.find('.qcodes-process-list');\r\n",
-       "            me.abortButton = me.$el.find('.qcodes-abort-loop');\r\n",
-       "            me.processLinesButton = me.$el.find('.qcodes-processlines')\r\n",
-       "\r\n",
-       "            me.outputLines = [];\r\n",
-       "\r\n",
-       "            me.clearButton.click(function() {\r\n",
-       "                me.outputArea.html('');\r\n",
-       "                me.clearButton.addClass('disabled');\r\n",
-       "            });\r\n",
-       "\r\n",
-       "            me.abortButton.click(function() {\r\n",
-       "                me.send({abort: true});\r\n",
-       "            });\r\n",
-       "\r\n",
-       "            me.processLinesButton.click(function() {\r\n",
-       "                // toggle multiline process list display\r\n",
-       "                me.subprocessesMultiline = !me.subprocessesMultiline;\r\n",
-       "                me.showSubprocesses();\r\n",
-       "            });\r\n",
-       "\r\n",
-       "            me.$el.find('.js-state').click(function() {\r\n",
-       "                var state = this.className.substr(this.className.indexOf('qcodes'))\r\n",
-       "                        .split('-')[1].split(' ')[0];\r\n",
-       "                me.model.set('_state', state);\r\n",
-       "            });\r\n",
-       "\r\n",
-       "            $(window)\r\n",
-       "                .off('resize.qcodes')\r\n",
-       "                .on('resize.qcodes', function() {me.clipBounds();});\r\n",
-       "\r\n",
-       "            me.update();\r\n",
-       "        },\r\n",
-       "\r\n",
-       "        updateState: function() {\r\n",
-       "            var me = this,\r\n",
-       "                oldState = me.$el.attr('qcodes-state'),\r\n",
-       "                state = me.model.get('_state');\r\n",
-       "\r\n",
-       "            if(state === oldState) return;\r\n",
-       "\r\n",
-       "            setTimeout(function() {\r\n",
-       "                // not sure why I can't pop it out of the widgetarea in render, but it seems that\r\n",
-       "                // some other bit of code resets the parent after render if I do it there.\r\n",
-       "                // To be safe, just do it on every state click.\r\n",
-       "                me.$el.appendTo('body');\r\n",
-       "\r\n",
-       "                if(oldState === 'floated') {\r\n",
-       "                    console.log('here');\r\n",
-       "                    me.$el.draggable('destroy').css({left:'', top: ''});\r\n",
-       "                }\r\n",
-       "\r\n",
-       "                me.$el.attr('qcodes-state', state);\r\n",
-       "\r\n",
-       "                if(state === 'floated') {\r\n",
-       "                    me.$el\r\n",
-       "                        .draggable({stop: function() { me.clipBounds(); }})\r\n",
-       "                        .css({\r\n",
-       "                            left: window.innerWidth - me.$el.width() - 15,\r\n",
-       "                            top: window.innerHeight - me.$el.height() - 10\r\n",
-       "                        });\r\n",
-       "                }\r\n",
-       "\r\n",
-       "                // any previous highlighting is now moot\r\n",
-       "                me.$el.removeClass('qcodes-highlight');\r\n",
-       "            }, 0);\r\n",
-       "\r\n",
-       "        },\r\n",
-       "\r\n",
-       "        clipBounds: function() {\r\n",
-       "            var me = this;\r\n",
-       "            if(me.$el.attr('qcodes-state') === 'floated') {\r\n",
-       "                var bounds = me.$el[0].getBoundingClientRect(),\r\n",
-       "                    minVis = 40,\r\n",
-       "                    maxLeft = window.innerWidth - minVis,\r\n",
-       "                    minLeft = minVis - bounds.width,\r\n",
-       "                    maxTop = window.innerHeight - minVis;\r\n",
-       "\r\n",
-       "                if(bounds.left > maxLeft) me.$el.css('left', maxLeft);\r\n",
-       "                else if(bounds.left < minLeft) me.$el.css('left', minLeft);\r\n",
-       "\r\n",
-       "                if(bounds.top > maxTop) me.$el.css('top', maxTop);\r\n",
-       "                else if(bounds.top < 0) me.$el.css('top', 0);\r\n",
-       "            }\r\n",
-       "        },\r\n",
-       "\r\n",
-       "        display: function(message) {\r\n",
-       "            var me = this;\r\n",
-       "            if(message) {\r\n",
-       "                var initialScroll = me.outputArea.scrollTop();\r\n",
-       "                me.outputArea.scrollTop(me.outputArea.prop('scrollHeight'));\r\n",
-       "                var scrollBottom = me.outputArea.scrollTop();\r\n",
-       "\r\n",
-       "                if(me.$el.attr('qcodes-state') === 'minimized') {\r\n",
-       "                    // if we add text and the box is minimized, highlight the\r\n",
-       "                    // title bar to alert the user that there are new messages.\r\n",
-       "                    // remove then add the class, so we get the animation again\r\n",
-       "                    // if it's already highlighted\r\n",
-       "                    me.$el.removeClass('qcodes-highlight');\r\n",
-       "                    setTimeout(function(){\r\n",
-       "                        me.$el.addClass('qcodes-highlight');\r\n",
-       "                    }, 0);\r\n",
-       "                }\r\n",
-       "\r\n",
-       "                var newLines = message.split('\\n'),\r\n",
-       "                    out = me.outputLines,\r\n",
-       "                    outLen = out.length;\r\n",
-       "                if(outLen) out[outLen - 1] += newLines[0];\r\n",
-       "                else out.push(newLines[0]);\r\n",
-       "\r\n",
-       "                for(var i = 1; i < newLines.length; i++) {\r\n",
-       "                    out.push(newLines[i]);\r\n",
-       "                }\r\n",
-       "\r\n",
-       "                if(out.length > me.maxOutputLength) {\r\n",
-       "                    out.splice(0, out.length - me.maxOutputLength + 1,\r\n",
-       "                        '<<< Output clipped >>>');\r\n",
-       "                }\r\n",
-       "\r\n",
-       "                me.outputArea.text(out.join('\\n'));\r\n",
-       "                me.clearButton.removeClass('disabled');\r\n",
-       "\r\n",
-       "                // if we were scrolled to the bottom initially, make sure\r\n",
-       "                // we stay that way.\r\n",
-       "                me.outputArea.scrollTop(initialScroll === scrollBottom ?\r\n",
-       "                    me.outputArea.prop('scrollHeight') : initialScroll);\r\n",
-       "            }\r\n",
-       "\r\n",
-       "            me.showSubprocesses();\r\n",
-       "            me.updateState();\r\n",
-       "        },\r\n",
-       "\r\n",
-       "        showSubprocesses: function() {\r\n",
-       "            var me = this,\r\n",
-       "                replacer = me.subprocessesMultiline ? '
' : ', ',\r\n", - " processes = (me.model.get('_processes') || '')\r\n", - " .replace(/\\n/g, '>' + replacer + '<');\r\n", - "\r\n", - " if(processes) processes = '<' + processes + '>';\r\n", - " else processes = 'No subprocesses';\r\n", - "\r\n", - " me.abortButton.toggleClass('disabled', processes.indexOf('Measurement')===-1);\r\n", - "\r\n", - " me.subprocessList.html(processes);\r\n", - " }\r\n", - " });\r\n", - " manager.WidgetManager.register_widget_view('SubprocessView', SubprocessView);\r\n", - "});\r\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "No loop running\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "a:\\qcodes\\qcodes\\process\\helpers.py:27: UserWarning: Multiprocessing is in beta, use at own risk\n", - " warnings.warn(\"Multiprocessing is in beta, use at own risk\", UserWarning)\n" - ] - } - ], - "source": [ - "# import all necessary things\n", - "%matplotlib nbagg\n", - "\n", - "import qcodes as qc\n", - "import qcodes.instrument.parameter as parameter\n", - "import qcodes.instrument_drivers.AlazarTech.ATS9360 as ATSdriver\n", - "import qcodes.instrument_drivers.AlazarTech.ATS_acquisition_controllers as ats_contr\n", - "\n", - "qc.halt_bg()\n", - "qc.set_mp_method('spawn') # force Windows behavior on mac\n", - "\n", - "# this makes a widget in the corner of the window to show and control\n", - "# subprocesses and any output they would print to the terminal\n", - "#qc.show_subprocess_widget()" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "[{'bits_per_sample': 12,\n", - " 'board_id': 1,\n", - " 'board_kind': 'ATS9360',\n", - " 'max_samples': 4294967294,\n", - " 'system_id': 1}]" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Command to list all alazar boards connected to the system\n", - "ATSdriver.AlazarTech_ATS.find_boards()" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "a:\\qcodes\\qcodes\\instrument\\metaclass.py:37: UserWarning: Multiprocessing is in beta, use at own risk\n", - " UserWarning)\n" - ] - }, - { - "data": { - "text/plain": [ - "{'CPLD_version': '25.16',\n", - " 'SDK_version': '5.9.25',\n", - " 'asopc_type': '1712554848',\n", - " 'driver_version': '5.9.25',\n", - " 'firmware': None,\n", - " 'latest_cal_date': '13-11-15',\n", - " 'memory_size': '4294967294',\n", - " 'model': 'ATS9360',\n", - " 'pcie_link_speed': '0.5GB/s',\n", - " 'pcie_link_width': '8',\n", - " 'serial': '970344',\n", - " 'vendor': 'AlazarTech'}" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Create the ATS9870 instrument on the new server \"alazar_server\"\n", - "ats_inst = ATSdriver.AlazarTech_ATS9360(name='Alazar1', server_name=\"alazar_server\")\n", - "# Print all information about this Alazar card\n", - "ats_inst.get_idn()" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "import qcodes.instrument_drivers.rohde_schwarz.SGS100A as RSdriver" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Connected to: Rohde&Schwarz SGS100A (serial:1416.0505k02/103076, firmware:3.1.19.7-3.20.140.60.1) in 0.05s\n" - ] - } - ], - "source": [ - "localos = RSdriver.RohdeSchwarz_SGS100A('LO', 'TCPIP0::172.20.3.42::inst0::INSTR')" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "10000000.0" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "localos.frequency()" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "localos.power(-25)\n", - "localos.frequency(10e6)\n", - "localos.status('on')" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "a:\\qcodes\\qcodes\\instrument\\metaclass.py:37: UserWarning: Multiprocessing is in beta, use at own risk\n", - " UserWarning)\n" - ] - } - ], - "source": [ - "# Instantiate an acquisition controller (In this case we are doing a simple DFT) on the same server (\"alazar_server\") and \n", - "# provide the name of the name of the alazar card that this controller should control\n", - "acquisition_controller = ats_contr.Demodulation_AcquisitionController(name='acquisition_controller', \n", - " demodulation_frequency=15e6, \n", - " alazar_name='Alazar1', \n", - " server_name=\"alazar_server\")" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "ename": "ValueError", - "evalue": "*** error on alazar_server ***\nwhile executing query: ('ASK', 'cmd', (0, 'config'), {'trigger_source1': 'EXTERNAL', 'channel_range': [2.0, 2.0], 'sample_rate': 100000000})\n\n(>, (0, 'config'), {'sample_rate': 100000000, 'trigger_source1': 'EXTERNAL', 'channel_range': [2.0, 2.0]})\nTraceback (most recent call last):\n File \"a:\\qcodes\\qcodes\\process\\server.py\", line 347, in _process_ask\n response = func(*args, **kwargs)\n File \"a:\\qcodes\\qcodes\\instrument\\server.py\", line 189, in handle_cmd\n return func(*args, **kwargs)\n File \"a:\\qcodes\\qcodes\\instrument_drivers\\AlazarTech\\ATS.py\", line 364, in config\n self._set_if_present('sample_rate', sample_rate)\n File \"a:\\qcodes\\qcodes\\instrument_drivers\\AlazarTech\\ATS.py\", line 698, in _set_if_present\n self.parameters[param_name]._set(value)\n File \"a:\\qcodes\\qcodes\\instrument_drivers\\AlazarTech\\ATS.py\", line 883, in _set\n self.validate(value)\n File \"a:\\qcodes\\qcodes\\instrument\\parameter.py\", line 365, in validate\n self._vals.validate(value, 'Parameter: ' + context)\n File \"a:\\qcodes\\qcodes\\utils\\validators.py\", line 234, in validate\n repr(value), repr(self._values), context))\nValueError: 100000000 is not in {'5KSPS', '100MSPS', '1000MSPS', '50MSPS', '500MSPS', '10MSPS', '1KSPS', '2KSPS', '100KSPS', '50KSPS', '800MSPS', '500KSPS', '1MSPS', '5MSPS', '20MSPS', '200KSPS', '1500MSPS', '2MSPS', 'EXTERNAL_CLOCK', '250MSPS', '1200MSPS', '20KSPS', '10KSPS', '125MSPS', '1800MSPS', '10MHZ_REF_500MSPS'}; Parameter: sample_rate\n", - "output_type": "error", - "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mValueError\u001b[0m Traceback (most recent call last)", - "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 10\u001b[0m \u001b[1;31m#trigger_operation='TRIG_ENGINE_OP_J',\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 11\u001b[0m \u001b[1;31m#trigger_engine1='TRIG_ENGINE_J',\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 12\u001b[1;33m \u001b[0mtrigger_source1\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m'EXTERNAL'\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 13\u001b[0m \u001b[1;31m#trigger_slope1='TRIG_SLOPE_POSITIVE',\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 14\u001b[0m \u001b[1;31m#trigger_level1=128,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[1;32ma:\\qcodes\\qcodes\\instrument\\remote.py\u001b[0m in \u001b[0;36m__call__\u001b[1;34m(self, *args, **kwargs)\u001b[0m\n\u001b[0;32m 366\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0m__call__\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m*\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 367\u001b[0m \u001b[1;34m\"\"\"Call the method on the server, passing on any args and kwargs.\"\"\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 368\u001b[1;33m \u001b[1;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_instrument\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_ask_server\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mname\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m*\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 369\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 370\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[1;32ma:\\qcodes\\qcodes\\instrument\\remote.py\u001b[0m in \u001b[0;36m_ask_server\u001b[1;34m(self, func_name, *args, **kwargs)\u001b[0m\n\u001b[0;32m 124\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0m_ask_server\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mfunc_name\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m*\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 125\u001b[0m \u001b[1;34m\"\"\"Query the server copy of this instrument, expecting a response.\"\"\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 126\u001b[1;33m \u001b[1;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_manager\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mask\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'cmd'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_id\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mfunc_name\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m*\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 127\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 128\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0m_write_server\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mfunc_name\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m*\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[1;32ma:\\qcodes\\qcodes\\process\\server.py\u001b[0m in \u001b[0;36mask\u001b[1;34m(self, func_name, timeout, *args, **kwargs)\u001b[0m\n\u001b[0;32m 126\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_query_queue\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mput\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mquery\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 127\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 128\u001b[1;33m \u001b[0mvalue\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_get_response\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mtimeout\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mtimeout\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mquery\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mquery\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 129\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 130\u001b[0m \u001b[1;32mwhile\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_response_queue\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mempty\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[1;32ma:\\qcodes\\qcodes\\process\\server.py\u001b[0m in \u001b[0;36m_get_response\u001b[1;34m(self, timeout, query)\u001b[0m\n\u001b[0;32m 147\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[0mvalue\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 148\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 149\u001b[1;33m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_handle_error\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mcode\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mvalue\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mquery\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 150\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 151\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0m_handle_error\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mcode\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0merror_str\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mquery\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mNone\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[1;32ma:\\qcodes\\qcodes\\process\\server.py\u001b[0m in \u001b[0;36m_handle_error\u001b[1;34m(self, code, error_str, query)\u001b[0m\n\u001b[0;32m 166\u001b[0m \u001b[0merr_type\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mRuntimeError\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 167\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 168\u001b[1;33m \u001b[1;32mraise\u001b[0m \u001b[0merr_type\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0merror_head\u001b[0m \u001b[1;33m+\u001b[0m \u001b[1;34m'\\n\\n'\u001b[0m \u001b[1;33m+\u001b[0m \u001b[0merror_str\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 169\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 170\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mhalt\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtimeout\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m2\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[1;31mValueError\u001b[0m: *** error on alazar_server ***\nwhile executing query: ('ASK', 'cmd', (0, 'config'), {'trigger_source1': 'EXTERNAL', 'channel_range': [2.0, 2.0], 'sample_rate': 100000000})\n\n(>, (0, 'config'), {'sample_rate': 100000000, 'trigger_source1': 'EXTERNAL', 'channel_range': [2.0, 2.0]})\nTraceback (most recent call last):\n File \"a:\\qcodes\\qcodes\\process\\server.py\", line 347, in _process_ask\n response = func(*args, **kwargs)\n File \"a:\\qcodes\\qcodes\\instrument\\server.py\", line 189, in handle_cmd\n return func(*args, **kwargs)\n File \"a:\\qcodes\\qcodes\\instrument_drivers\\AlazarTech\\ATS.py\", line 364, in config\n self._set_if_present('sample_rate', sample_rate)\n File \"a:\\qcodes\\qcodes\\instrument_drivers\\AlazarTech\\ATS.py\", line 698, in _set_if_present\n self.parameters[param_name]._set(value)\n File \"a:\\qcodes\\qcodes\\instrument_drivers\\AlazarTech\\ATS.py\", line 883, in _set\n self.validate(value)\n File \"a:\\qcodes\\qcodes\\instrument\\parameter.py\", line 365, in validate\n self._vals.validate(value, 'Parameter: ' + context)\n File \"a:\\qcodes\\qcodes\\utils\\validators.py\", line 234, in validate\n repr(value), repr(self._values), context))\nValueError: 100000000 is not in {'5KSPS', '100MSPS', '1000MSPS', '50MSPS', '500MSPS', '10MSPS', '1KSPS', '2KSPS', '100KSPS', '50KSPS', '800MSPS', '500KSPS', '1MSPS', '5MSPS', '20MSPS', '200KSPS', '1500MSPS', '2MSPS', 'EXTERNAL_CLOCK', '250MSPS', '1200MSPS', '20KSPS', '10KSPS', '125MSPS', '1800MSPS', '10MHZ_REF_500MSPS'}; Parameter: sample_rate\n" - ] - } - ], - "source": [ - "# Configure all settings in the Alazar card\n", - "ats_inst.config(#clock_source='INTERNAL_CLOCK',\n", - " sample_rate='100000000',\n", - " #clock_edge='CLOCK_EDGE_RISING',\n", - " #decimation=0,\n", - " #coupling=['AC','AC'],\n", - " channel_range=[2.,2.],\n", - " #impedance=[50,50],\n", - " #bwlimit=['DISABLED','DISABLED'],\n", - " #trigger_operation='TRIG_ENGINE_OP_J',\n", - " #trigger_engine1='TRIG_ENGINE_J',\n", - " trigger_source1='EXTERNAL',\n", - " #trigger_slope1='TRIG_SLOPE_POSITIVE',\n", - " #trigger_level1=128,\n", - " #trigger_engine2='TRIG_ENGINE_K',\n", - " #trigger_source2='DISABLE',\n", - " #trigger_slope2='TRIG_SLOPE_POSITIVE',\n", - " #trigger_level2=128,\n", - " #external_trigger_coupling='AC',\n", - " #external_trigger_range='ETR_5V',\n", - " #trigger_delay=0,\n", - " #timeout_ticks=0\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "# This command is specific to this acquisition controller. The kwargs provided here are being forwarded to ats_inst.acquire\n", - "# This way, it becomes easy to change acquisition specific settings from the ipython notebook\n", - "acquisition_controller.update_acquisitionkwargs(#mode='NPT',\n", - " samples_per_record=1024,\n", - " records_per_buffer=70,\n", - " buffers_per_acquisition=1,\n", - " #channel_selection='AB',\n", - " #transfer_offset=0,\n", - " #external_startcapture='ENABLED',\n", - " #enable_record_headers='DISABLED',\n", - " #alloc_buffers='DISABLED',\n", - " #fifo_only_streaming='DISABLED',\n", - " #interleave_samples='DISABLED',\n", - " #get_processed_data='DISABLED',\n", - " allocated_buffers=1,\n", - " #buffer_timeout=1000\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "2.0976760253919644" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Getting the value of the parameter 'acquisition' of the instrument 'acquisition_controller' performes the entire acquisition \n", - "# protocol. This again depends on the specific implementation of the acquisition controller\n", - "acquisition_controller.acquisition()" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "{'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS9360.AlazarTech_ATS9360',\n", - " 'functions': {},\n", - " 'name': 'Alazar1',\n", - " 'parameters': {'IDN': {'__class__': 'qcodes.instrument.parameter.StandardParameter',\n", - " 'instrument': 'qcodes.instrument_drivers.AlazarTech.ATS9360.AlazarTech_ATS9360',\n", - " 'instrument_name': 'Alazar1',\n", - " 'label': 'IDN',\n", - " 'name': 'IDN',\n", - " 'ts': '2016-11-01 16:48:58',\n", - " 'units': '',\n", - " 'value': {'CPLD_version': '25.16',\n", - " 'SDK_version': '5.9.25',\n", - " 'asopc_type': '1712554848',\n", - " 'driver_version': '5.9.25',\n", - " 'firmware': None,\n", - " 'latest_cal_date': '13-11-15',\n", - " 'memory_size': '4294967294',\n", - " 'model': 'ATS9360',\n", - " 'pcie_link_speed': '0.5GB/s',\n", - " 'pcie_link_width': '8',\n", - " 'serial': '970344',\n", - " 'vendor': 'AlazarTech'}},\n", - " 'alloc_buffers': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'Alloc Buffers',\n", - " 'name': 'alloc_buffers',\n", - " 'ts': '2016-11-01 16:48:23',\n", - " 'units': '',\n", - " 'value': 'DISABLED'},\n", - " 'allocated_buffers': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'Allocated Buffers',\n", - " 'name': 'allocated_buffers',\n", - " 'ts': '2016-11-01 16:48:58',\n", - " 'units': '',\n", - " 'value': 1},\n", - " 'buffer_timeout': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'Buffer Timeout',\n", - " 'name': 'buffer_timeout',\n", - " 'ts': '2016-11-01 16:48:23',\n", - " 'units': 'ms',\n", - " 'value': 1000},\n", - " 'buffers_per_acquisition': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'Buffers per Acquisition',\n", - " 'name': 'buffers_per_acquisition',\n", - " 'ts': '2016-11-01 16:48:58',\n", - " 'units': '',\n", - " 'value': 1},\n", - " 'channel_range1': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'Range channel 1',\n", - " 'name': 'channel_range1',\n", - " 'ts': '2016-11-01 16:48:54',\n", - " 'units': 'V',\n", - " 'value': 2.0},\n", - " 'channel_range2': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'Range channel 2',\n", - " 'name': 'channel_range2',\n", - " 'ts': '2016-11-01 16:48:54',\n", - " 'units': 'V',\n", - " 'value': 2.0},\n", - " 'channel_selection': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'Channel Selection',\n", - " 'name': 'channel_selection',\n", - " 'ts': '2016-11-01 16:48:23',\n", - " 'units': '',\n", - " 'value': 'AB'},\n", - " 'clock_edge': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'Clock Edge',\n", - " 'name': 'clock_edge',\n", - " 'ts': '2016-11-01 16:48:23',\n", - " 'units': '',\n", - " 'value': 'CLOCK_EDGE_RISING'},\n", - " 'clock_source': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'Clock Source',\n", - " 'name': 'clock_source',\n", - " 'ts': '2016-11-01 16:48:23',\n", - " 'units': '',\n", - " 'value': 'INTERNAL_CLOCK'},\n", - " 'coupling1': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'Coupling channel 1',\n", - " 'name': 'coupling1',\n", - " 'ts': '2016-11-01 16:48:23',\n", - " 'units': '',\n", - " 'value': 'DC'},\n", - " 'coupling2': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'Coupling channel 2',\n", - " 'name': 'coupling2',\n", - " 'ts': '2016-11-01 16:48:23',\n", - " 'units': '',\n", - " 'value': 'DC'},\n", - " 'decimation': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'Decimation',\n", - " 'name': 'decimation',\n", - " 'ts': '2016-11-01 16:48:23',\n", - " 'units': '',\n", - " 'value': 0},\n", - " 'enable_record_headers': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'Enable Record Headers',\n", - " 'name': 'enable_record_headers',\n", - " 'ts': '2016-11-01 16:48:23',\n", - " 'units': '',\n", - " 'value': 'DISABLED'},\n", - " 'external_startcapture': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'External Startcapture',\n", - " 'name': 'external_startcapture',\n", - " 'ts': '2016-11-01 16:48:23',\n", - " 'units': '',\n", - " 'value': 'ENABLED'},\n", - " 'external_trigger_coupling': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'External Trigger Coupling',\n", - " 'name': 'external_trigger_coupling',\n", - " 'ts': '2016-11-01 16:48:23',\n", - " 'units': '',\n", - " 'value': 'AC'},\n", - " 'external_trigger_range': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'External Trigger Range',\n", - " 'name': 'external_trigger_range',\n", - " 'ts': '2016-11-01 16:48:23',\n", - " 'units': '',\n", - " 'value': 'ETR_5V'},\n", - " 'fifo_only_streaming': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'Fifo Only Streaming',\n", - " 'name': 'fifo_only_streaming',\n", - " 'ts': '2016-11-01 16:48:23',\n", - " 'units': '',\n", - " 'value': 'DISABLED'},\n", - " 'get_processed_data': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'Get Processed Data',\n", - " 'name': 'get_processed_data',\n", - " 'ts': '2016-11-01 16:48:23',\n", - " 'units': '',\n", - " 'value': 'DISABLED'},\n", - " 'impedance1': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'Impedance channel 1',\n", - " 'name': 'impedance1',\n", - " 'ts': '2016-11-01 16:48:23',\n", - " 'units': 'Ohm',\n", - " 'value': 50},\n", - " 'impedance2': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'Impedance channel 2',\n", - " 'name': 'impedance2',\n", - " 'ts': '2016-11-01 16:48:23',\n", - " 'units': 'Ohm',\n", - " 'value': 50},\n", - " 'interleave_samples': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'Interleave Samples',\n", - " 'name': 'interleave_samples',\n", - " 'ts': '2016-11-01 16:48:23',\n", - " 'units': '',\n", - " 'value': 'DISABLED'},\n", - " 'mode': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'Acquisiton mode',\n", - " 'name': 'mode',\n", - " 'ts': '2016-11-01 16:48:23',\n", - " 'units': '',\n", - " 'value': 'NPT'},\n", - " 'records_per_buffer': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'Records per Buffer',\n", - " 'name': 'records_per_buffer',\n", - " 'ts': '2016-11-01 16:48:58',\n", - " 'units': '',\n", - " 'value': 70},\n", - " 'sample_rate': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'Sample Rate',\n", - " 'name': 'sample_rate',\n", - " 'ts': '2016-11-01 16:48:54',\n", - " 'units': 'S/s',\n", - " 'value': 100000000},\n", - " 'samples_per_record': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'Samples per Record',\n", - " 'name': 'samples_per_record',\n", - " 'ts': '2016-11-01 16:48:58',\n", - " 'units': '',\n", - " 'value': 1024},\n", - " 'timeout_ticks': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'Timeout Ticks',\n", - " 'name': 'timeout_ticks',\n", - " 'ts': '2016-11-01 16:48:23',\n", - " 'units': '10 us',\n", - " 'value': 0},\n", - " 'transfer_offset': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'Transer Offset',\n", - " 'name': 'transfer_offset',\n", - " 'ts': '2016-11-01 16:48:23',\n", - " 'units': 'Samples',\n", - " 'value': 0},\n", - " 'trigger_delay': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'Trigger Delay',\n", - " 'name': 'trigger_delay',\n", - " 'ts': '2016-11-01 16:48:23',\n", - " 'units': 'Sample clock cycles',\n", - " 'value': 0},\n", - " 'trigger_engine1': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'Trigger Engine 1',\n", - " 'name': 'trigger_engine1',\n", - " 'ts': '2016-11-01 16:48:23',\n", - " 'units': '',\n", - " 'value': 'TRIG_ENGINE_K'},\n", - " 'trigger_engine2': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'Trigger Engine 2',\n", - " 'name': 'trigger_engine2',\n", - " 'ts': '2016-11-01 16:48:23',\n", - " 'units': '',\n", - " 'value': 'TRIG_ENGINE_K'},\n", - " 'trigger_level1': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'Trigger Level 1',\n", - " 'name': 'trigger_level1',\n", - " 'ts': '2016-11-01 16:48:23',\n", - " 'units': '',\n", - " 'value': 150},\n", - " 'trigger_level2': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'Trigger Level 2',\n", - " 'name': 'trigger_level2',\n", - " 'ts': '2016-11-01 16:48:23',\n", - " 'units': '',\n", - " 'value': 150},\n", - " 'trigger_operation': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'Trigger Operation',\n", - " 'name': 'trigger_operation',\n", - " 'ts': '2016-11-01 16:48:23',\n", - " 'units': '',\n", - " 'value': 'TRIG_ENGINE_OP_J'},\n", - " 'trigger_slope1': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'Trigger Slope 1',\n", - " 'name': 'trigger_slope1',\n", - " 'ts': '2016-11-01 16:48:23',\n", - " 'units': '',\n", - " 'value': 'TRIG_SLOPE_POSITIVE'},\n", - " 'trigger_slope2': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'Trigger Slope 2',\n", - " 'name': 'trigger_slope2',\n", - " 'ts': '2016-11-01 16:48:23',\n", - " 'units': '',\n", - " 'value': 'TRIG_SLOPE_POSITIVE'},\n", - " 'trigger_source1': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'Trigger Source 1',\n", - " 'name': 'trigger_source1',\n", - " 'ts': '2016-11-01 16:48:54',\n", - " 'units': '',\n", - " 'value': 'EXTERNAL'},\n", - " 'trigger_source2': {'__class__': 'qcodes.instrument_drivers.AlazarTech.ATS.AlazarParameter',\n", - " 'label': 'Trigger Source 2',\n", - " 'name': 'trigger_source2',\n", - " 'ts': '2016-11-01 16:48:23',\n", - " 'units': '',\n", - " 'value': 'DISABLE'}}}" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# make a snapshot of the 'ats_inst' instrument\n", - "ats_inst.snapshot()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "False\n", - "None\n", - "started at 2016-11-01 16:49:46\n" - ] - }, - { - "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "window.mpl = {};\n", - "\n", - "mpl.get_websocket_type = function() {\n", - " if (typeof(WebSocket) !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof(MozWebSocket) !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert('Your browser does not have WebSocket support.' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.');\n", - " };\n", - "}\n", - "\n", - "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = (this.ws.binaryType != undefined);\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById(\"mpl-warnings\");\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent = (\n", - " \"This browser does not support binary websocket messages. \" +\n", - " \"Performance may be slow.\");\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = $('
');\n", - " this._root_extra_style(this.root)\n", - " this.root.attr('style', 'display: inline-block');\n", - "\n", - " $(parent_element).append(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", - " fig.send_message(\"send_image_mode\", {});\n", - " fig.send_message(\"refresh\", {});\n", - " }\n", - "\n", - " this.imageObj.onload = function() {\n", - " if (fig.image_mode == 'full') {\n", - " // Full images could contain transparency (where diff images\n", - " // almost always do), so we need to clear the canvas so that\n", - " // there is no ghosting.\n", - " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", - " }\n", - " fig.context.drawImage(fig.imageObj, 0, 0);\n", - " };\n", - "\n", - " this.imageObj.onunload = function() {\n", - " this.ws.close();\n", - " }\n", - "\n", - " this.ws.onmessage = this._make_on_message_function(this);\n", - "\n", - " this.ondownload = ondownload;\n", - "}\n", - "\n", - "mpl.figure.prototype._init_header = function() {\n", - " var titlebar = $(\n", - " '
');\n", - " var titletext = $(\n", - " '
');\n", - " titlebar.append(titletext)\n", - " this.root.append(titlebar);\n", - " this.header = titletext[0];\n", - "}\n", - "\n", - "\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._init_canvas = function() {\n", - " var fig = this;\n", - "\n", - " var canvas_div = $('
');\n", - "\n", - " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", - "\n", - " function canvas_keyboard_event(event) {\n", - " return fig.key_event(event, event['data']);\n", - " }\n", - "\n", - " canvas_div.keydown('key_press', canvas_keyboard_event);\n", - " canvas_div.keyup('key_release', canvas_keyboard_event);\n", - " this.canvas_div = canvas_div\n", - " this._canvas_extra_style(canvas_div)\n", - " this.root.append(canvas_div);\n", - "\n", - " var canvas = $('');\n", - " canvas.addClass('mpl-canvas');\n", - " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", - "\n", - " this.canvas = canvas[0];\n", - " this.context = canvas[0].getContext(\"2d\");\n", - "\n", - " var rubberband = $('');\n", - " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", - "\n", - " var pass_mouse_events = true;\n", - "\n", - " canvas_div.resizable({\n", - " start: function(event, ui) {\n", - " pass_mouse_events = false;\n", - " },\n", - " resize: function(event, ui) {\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " stop: function(event, ui) {\n", - " pass_mouse_events = true;\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " });\n", - "\n", - " function mouse_event_fn(event) {\n", - " if (pass_mouse_events)\n", - " return fig.mouse_event(event, event['data']);\n", - " }\n", - "\n", - " rubberband.mousedown('button_press', mouse_event_fn);\n", - " rubberband.mouseup('button_release', mouse_event_fn);\n", - " // Throttle sequential mouse events to 1 every 20ms.\n", - " rubberband.mousemove('motion_notify', mouse_event_fn);\n", - "\n", - " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", - " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", - "\n", - " canvas_div.on(\"wheel\", function (event) {\n", - " event = event.originalEvent;\n", - " event['data'] = 'scroll'\n", - " if (event.deltaY < 0) {\n", - " event.step = 1;\n", - " } else {\n", - " event.step = -1;\n", - " }\n", - " mouse_event_fn(event);\n", - " });\n", - "\n", - " canvas_div.append(canvas);\n", - " canvas_div.append(rubberband);\n", - "\n", - " this.rubberband = rubberband;\n", - " this.rubberband_canvas = rubberband[0];\n", - " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", - " this.rubberband_context.strokeStyle = \"#000000\";\n", - "\n", - " this._resize_canvas = function(width, height) {\n", - " // Keep the size of the canvas, canvas container, and rubber band\n", - " // canvas in synch.\n", - " canvas_div.css('width', width)\n", - " canvas_div.css('height', height)\n", - "\n", - " canvas.attr('width', width);\n", - " canvas.attr('height', height);\n", - "\n", - " rubberband.attr('width', width);\n", - " rubberband.attr('height', height);\n", - " }\n", - "\n", - " // Set the figure to an initial 600x600px, this will subsequently be updated\n", - " // upon first draw.\n", - " this._resize_canvas(600, 600);\n", - "\n", - " // Disable right mouse context menu.\n", - " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", - " return false;\n", - " });\n", - "\n", - " function set_focus () {\n", - " canvas.focus();\n", - " canvas_div.focus();\n", - " }\n", - "\n", - " window.setTimeout(set_focus, 100);\n", - "}\n", - "\n", - "mpl.figure.prototype._init_toolbar = function() {\n", - " var fig = this;\n", - "\n", - " var nav_element = $('
')\n", - " nav_element.attr('style', 'width: 100%');\n", - " this.root.append(nav_element);\n", - "\n", - " // Define a callback function for later on.\n", - " function toolbar_event(event) {\n", - " return fig.toolbar_button_onclick(event['data']);\n", - " }\n", - " function toolbar_mouse_event(event) {\n", - " return fig.toolbar_button_onmouseover(event['data']);\n", - " }\n", - "\n", - " for(var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " // put a spacer in here.\n", - " continue;\n", - " }\n", - " var button = $('');\n", - " button.click(method_name, toolbar_event);\n", - " button.mouseover(tooltip, toolbar_mouse_event);\n", - " nav_element.append(button);\n", - " }\n", - "\n", - " // Add the status bar.\n", - " var status_bar = $('');\n", - " nav_element.append(status_bar);\n", - " this.message = status_bar[0];\n", - "\n", - " // Add the close button to the window.\n", - " var buttongrp = $('
');\n", - " var button = $('');\n", - " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", - " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", - " buttongrp.append(button);\n", - " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", - " titlebar.prepend(buttongrp);\n", - "}\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(el){\n", - " var fig = this\n", - " el.on(\"remove\", function(){\n", - "\tfig.close_ws(fig, {});\n", - " });\n", - "}\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(el){\n", - " // this is important to make the div 'focusable\n", - " el.attr('tabindex', 0)\n", - " // reach out to IPython and tell the keyboard manager to turn it's self\n", - " // off when our div gets focus\n", - "\n", - " // location in version 3\n", - " if (IPython.notebook.keyboard_manager) {\n", - " IPython.notebook.keyboard_manager.register_events(el);\n", - " }\n", - " else {\n", - " // location in version 2\n", - " IPython.keyboard_manager.register_events(el);\n", - " }\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._key_event_extra = function(event, name) {\n", - " var manager = IPython.notebook.keyboard_manager;\n", - " if (!manager)\n", - " manager = IPython.keyboard_manager;\n", - "\n", - " // Check for shift+enter\n", - " if (event.shiftKey && event.which == 13) {\n", - " this.canvas_div.blur();\n", - " event.shiftKey = false;\n", - " // Send a \"J\" for go to next cell\n", - " event.which = 74;\n", - " event.keyCode = 74;\n", - " manager.command_mode();\n", - " manager.handle_keydown(event);\n", - " }\n", - "}\n", - "\n", - "mpl.figure.prototype.handle_save = function(fig, msg) {\n", - " fig.ondownload(fig, null);\n", - "}\n", - "\n", - "\n", - "mpl.find_output_cell = function(html_output) {\n", - " // Return the cell and output element which can be found *uniquely* in the notebook.\n", - " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", - " // IPython event is triggered only after the cells have been serialised, which for\n", - " // our purposes (turning an active figure into a static one), is too late.\n", - " var cells = IPython.notebook.get_cells();\n", - " var ncells = cells.length;\n", - " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", - " data = data.data;\n", - " }\n", - " if (data['text/html'] == html_output) {\n", - " return [cell, data, j];\n", - " }\n", - " }\n", - " }\n", - " }\n", - "}\n", - "\n", - "// Register the function which deals with the matplotlib target/channel.\n", - "// The kernel may be null if the page has been refreshed.\n", - "if (IPython.notebook.kernel != null) {\n", - " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", - "}\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.figure()\n", - "plt.plot(data2[0])\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "DataSet:\n", - " mode = DataMode.LOCAL\n", - " location = '2016-11-02/14-12-03_AlazarTest'\n", - " | | | \n", - " Setpoint | LO_frequency_set | frequency | (5,)\n", - " Measured | basic_acquisition_controller_acquisition | acquisition | (5,)\n", - "started at 2016-11-02 14:12:03\n" - ] - }, - { - "ename": "ValueError", - "evalue": "setting an array element with a sequence.", - "output_type": "error", - "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mValueError\u001b[0m Traceback (most recent call last)", - "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m data = qc.Loop(localos.frequency.sweep(1e6, 5e6, 1e6)).each(\n\u001b[1;32m----> 2\u001b[1;33m basic_acquisition_controller.acquisition).run(name='AlazarTest')\n\u001b[0m", - "\u001b[1;32ma:\\qcodes\\qcodes\\loops.py\u001b[0m in \u001b[0;36mrun\u001b[1;34m(self, background, use_threads, quiet, data_manager, station, progress_interval, *args, **kwargs)\u001b[0m\n\u001b[0;32m 816\u001b[0m \u001b[1;32mdel\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mprocess\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 817\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 818\u001b[1;33m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_run_wrapper\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 819\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 820\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdata_set\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mmode\u001b[0m \u001b[1;33m!=\u001b[0m \u001b[0mDataMode\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mLOCAL\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[1;32ma:\\qcodes\\qcodes\\loops.py\u001b[0m in \u001b[0;36m_run_wrapper\u001b[1;34m(self, *args, **kwargs)\u001b[0m\n\u001b[0;32m 869\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0m_run_wrapper\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m*\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 870\u001b[0m \u001b[1;32mtry\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 871\u001b[1;33m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_run_loop\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m*\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 872\u001b[0m \u001b[1;32mexcept\u001b[0m \u001b[0m_QuietInterrupt\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 873\u001b[0m \u001b[1;32mpass\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[1;32ma:\\qcodes\\qcodes\\loops.py\u001b[0m in \u001b[0;36m_run_loop\u001b[1;34m(self, first_delay, action_indices, loop_indices, current_values, **ignore_kwargs)\u001b[0m\n\u001b[0;32m 940\u001b[0m f(first_delay=delay,\n\u001b[0;32m 941\u001b[0m \u001b[0mloop_indices\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mnew_indices\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 942\u001b[1;33m current_values=new_values)\n\u001b[0m\u001b[0;32m 943\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 944\u001b[0m \u001b[1;31m# after the first action, no delay is inherited\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[1;32ma:\\qcodes\\qcodes\\actions.py\u001b[0m in \u001b[0;36m__call__\u001b[1;34m(self, loop_indices, **ignore_kwargs)\u001b[0m\n\u001b[0;32m 144\u001b[0m \u001b[0mout_dict\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mparam_id\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mparam_out\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 145\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 146\u001b[1;33m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mstore\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mloop_indices\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mout_dict\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 147\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 148\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[1;32ma:\\qcodes\\qcodes\\data\\data_set.py\u001b[0m in \u001b[0;36mstore\u001b[1;34m(self, loop_indices, ids_values)\u001b[0m\n\u001b[0;32m 605\u001b[0m \u001b[1;31m# on the server (if you hit the if statement above) or else here\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 606\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0marray_id\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mvalue\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mids_values\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mitems\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 607\u001b[1;33m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0marrays\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0marray_id\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mloop_indices\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mvalue\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 608\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mlast_store\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mtime\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mtime\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 609\u001b[0m if (self.write_period is not None and\n", - "\u001b[1;32ma:\\qcodes\\qcodes\\data\\data_array.py\u001b[0m in \u001b[0;36m__setitem__\u001b[1;34m(self, loop_indices, value)\u001b[0m\n\u001b[0;32m 333\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_update_modified_range\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mmin_li\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mmax_li\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 334\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 335\u001b[1;33m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mndarray\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m__setitem__\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mloop_indices\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mvalue\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 336\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 337\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0m__getitem__\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mloop_indices\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[1;31mValueError\u001b[0m: setting an array element with a sequence." - ] - } - ], - "source": [ - "data = qc.Loop(localos.frequency.sweep(1e6, 5e6, 1e6)).each(\n", - " basic_acquisition_controller.acquisition).run(name='AlazarTest')" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "# Configure all settings in the Alazar card\n", - "ats_inst.config(clock_source='EXTERNAL_CLOCK_10MHz_REF',\n", - " sample_rate='10MHZ_REF_500MSPS',\n", - " clock_edge='CLOCK_EDGE_RISING',\n", - " decimation=1,\n", - " coupling=['DC','DC'],\n", - " channel_range=[.4,.4],\n", - " #impedance=[50,50],\n", - " #trigger_operation='TRIG_ENGINE_OP_J',\n", - " #trigger_engine1='TRIG_ENGINE_J',\n", - " #trigger_source1='EXTERNAL',\n", - " #trigger_slope1='TRIG_SLOPE_POSITIVE',\n", - " trigger_level1=140,\n", - " #trigger_engine2='TRIG_ENGINE_K',\n", - " #trigger_source2='DISABLE',\n", - " #trigger_slope2='TRIG_SLOPE_POSITIVE',\n", - " #trigger_level2=128,\n", - " external_trigger_coupling='DC',\n", - " external_trigger_range='ETR_2V5',\n", - " #trigger_delay=0,\n", - " #timeout_ticks=0\n", - ")\n" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "'10MHZ_REF_500MSPS'" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "ats_inst.sample_rate()" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "data3 = basic_acquisition_controller.acquisition()" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "window.mpl = {};\n", - "\n", - "mpl.get_websocket_type = function() {\n", - " if (typeof(WebSocket) !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof(MozWebSocket) !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert('Your browser does not have WebSocket support.' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.');\n", - " };\n", - "}\n", - "\n", - "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = (this.ws.binaryType != undefined);\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById(\"mpl-warnings\");\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent = (\n", - " \"This browser does not support binary websocket messages. \" +\n", - " \"Performance may be slow.\");\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = $('
');\n", - " this._root_extra_style(this.root)\n", - " this.root.attr('style', 'display: inline-block');\n", - "\n", - " $(parent_element).append(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", - " fig.send_message(\"send_image_mode\", {});\n", - " fig.send_message(\"refresh\", {});\n", - " }\n", - "\n", - " this.imageObj.onload = function() {\n", - " if (fig.image_mode == 'full') {\n", - " // Full images could contain transparency (where diff images\n", - " // almost always do), so we need to clear the canvas so that\n", - " // there is no ghosting.\n", - " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", - " }\n", - " fig.context.drawImage(fig.imageObj, 0, 0);\n", - " };\n", - "\n", - " this.imageObj.onunload = function() {\n", - " this.ws.close();\n", - " }\n", - "\n", - " this.ws.onmessage = this._make_on_message_function(this);\n", - "\n", - " this.ondownload = ondownload;\n", - "}\n", - "\n", - "mpl.figure.prototype._init_header = function() {\n", - " var titlebar = $(\n", - " '
');\n", - " var titletext = $(\n", - " '
');\n", - " titlebar.append(titletext)\n", - " this.root.append(titlebar);\n", - " this.header = titletext[0];\n", - "}\n", - "\n", - "\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._init_canvas = function() {\n", - " var fig = this;\n", - "\n", - " var canvas_div = $('
');\n", - "\n", - " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", - "\n", - " function canvas_keyboard_event(event) {\n", - " return fig.key_event(event, event['data']);\n", - " }\n", - "\n", - " canvas_div.keydown('key_press', canvas_keyboard_event);\n", - " canvas_div.keyup('key_release', canvas_keyboard_event);\n", - " this.canvas_div = canvas_div\n", - " this._canvas_extra_style(canvas_div)\n", - " this.root.append(canvas_div);\n", - "\n", - " var canvas = $('');\n", - " canvas.addClass('mpl-canvas');\n", - " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", - "\n", - " this.canvas = canvas[0];\n", - " this.context = canvas[0].getContext(\"2d\");\n", - "\n", - " var rubberband = $('');\n", - " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", - "\n", - " var pass_mouse_events = true;\n", - "\n", - " canvas_div.resizable({\n", - " start: function(event, ui) {\n", - " pass_mouse_events = false;\n", - " },\n", - " resize: function(event, ui) {\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " stop: function(event, ui) {\n", - " pass_mouse_events = true;\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " });\n", - "\n", - " function mouse_event_fn(event) {\n", - " if (pass_mouse_events)\n", - " return fig.mouse_event(event, event['data']);\n", - " }\n", - "\n", - " rubberband.mousedown('button_press', mouse_event_fn);\n", - " rubberband.mouseup('button_release', mouse_event_fn);\n", - " // Throttle sequential mouse events to 1 every 20ms.\n", - " rubberband.mousemove('motion_notify', mouse_event_fn);\n", - "\n", - " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", - " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", - "\n", - " canvas_div.on(\"wheel\", function (event) {\n", - " event = event.originalEvent;\n", - " event['data'] = 'scroll'\n", - " if (event.deltaY < 0) {\n", - " event.step = 1;\n", - " } else {\n", - " event.step = -1;\n", - " }\n", - " mouse_event_fn(event);\n", - " });\n", - "\n", - " canvas_div.append(canvas);\n", - " canvas_div.append(rubberband);\n", - "\n", - " this.rubberband = rubberband;\n", - " this.rubberband_canvas = rubberband[0];\n", - " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", - " this.rubberband_context.strokeStyle = \"#000000\";\n", - "\n", - " this._resize_canvas = function(width, height) {\n", - " // Keep the size of the canvas, canvas container, and rubber band\n", - " // canvas in synch.\n", - " canvas_div.css('width', width)\n", - " canvas_div.css('height', height)\n", - "\n", - " canvas.attr('width', width);\n", - " canvas.attr('height', height);\n", - "\n", - " rubberband.attr('width', width);\n", - " rubberband.attr('height', height);\n", - " }\n", - "\n", - " // Set the figure to an initial 600x600px, this will subsequently be updated\n", - " // upon first draw.\n", - " this._resize_canvas(600, 600);\n", - "\n", - " // Disable right mouse context menu.\n", - " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", - " return false;\n", - " });\n", - "\n", - " function set_focus () {\n", - " canvas.focus();\n", - " canvas_div.focus();\n", - " }\n", - "\n", - " window.setTimeout(set_focus, 100);\n", - "}\n", - "\n", - "mpl.figure.prototype._init_toolbar = function() {\n", - " var fig = this;\n", - "\n", - " var nav_element = $('
')\n", - " nav_element.attr('style', 'width: 100%');\n", - " this.root.append(nav_element);\n", - "\n", - " // Define a callback function for later on.\n", - " function toolbar_event(event) {\n", - " return fig.toolbar_button_onclick(event['data']);\n", - " }\n", - " function toolbar_mouse_event(event) {\n", - " return fig.toolbar_button_onmouseover(event['data']);\n", - " }\n", - "\n", - " for(var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " // put a spacer in here.\n", - " continue;\n", - " }\n", - " var button = $('');\n", - " button.click(method_name, toolbar_event);\n", - " button.mouseover(tooltip, toolbar_mouse_event);\n", - " nav_element.append(button);\n", - " }\n", - "\n", - " // Add the status bar.\n", - " var status_bar = $('');\n", - " nav_element.append(status_bar);\n", - " this.message = status_bar[0];\n", - "\n", - " // Add the close button to the window.\n", - " var buttongrp = $('
');\n", - " var button = $('');\n", - " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", - " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", - " buttongrp.append(button);\n", - " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", - " titlebar.prepend(buttongrp);\n", - "}\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(el){\n", - " var fig = this\n", - " el.on(\"remove\", function(){\n", - "\tfig.close_ws(fig, {});\n", - " });\n", - "}\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(el){\n", - " // this is important to make the div 'focusable\n", - " el.attr('tabindex', 0)\n", - " // reach out to IPython and tell the keyboard manager to turn it's self\n", - " // off when our div gets focus\n", - "\n", - " // location in version 3\n", - " if (IPython.notebook.keyboard_manager) {\n", - " IPython.notebook.keyboard_manager.register_events(el);\n", - " }\n", - " else {\n", - " // location in version 2\n", - " IPython.keyboard_manager.register_events(el);\n", - " }\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._key_event_extra = function(event, name) {\n", - " var manager = IPython.notebook.keyboard_manager;\n", - " if (!manager)\n", - " manager = IPython.keyboard_manager;\n", - "\n", - " // Check for shift+enter\n", - " if (event.shiftKey && event.which == 13) {\n", - " this.canvas_div.blur();\n", - " event.shiftKey = false;\n", - " // Send a \"J\" for go to next cell\n", - " event.which = 74;\n", - " event.keyCode = 74;\n", - " manager.command_mode();\n", - " manager.handle_keydown(event);\n", - " }\n", - "}\n", - "\n", - "mpl.figure.prototype.handle_save = function(fig, msg) {\n", - " fig.ondownload(fig, null);\n", - "}\n", - "\n", - "\n", - "mpl.find_output_cell = function(html_output) {\n", - " // Return the cell and output element which can be found *uniquely* in the notebook.\n", - " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", - " // IPython event is triggered only after the cells have been serialised, which for\n", - " // our purposes (turning an active figure into a static one), is too late.\n", - " var cells = IPython.notebook.get_cells();\n", - " var ncells = cells.length;\n", - " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", - " data = data.data;\n", - " }\n", - " if (data['text/html'] == html_output) {\n", - " return [cell, data, j];\n", - " }\n", - " }\n", - " }\n", - " }\n", - "}\n", - "\n", - "// Register the function which deals with the matplotlib target/channel.\n", - "// The kernel may be null if the page has been refreshed.\n", - "if (IPython.notebook.kernel != null) {\n", - " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", - "}\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "import matplotlib.pyplot as plt\n", - "plt.figure()\n", - "plt.plot(data9[1])\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "ename": "ValueError", - "evalue": "nth setpoint array should have shape matching the first n dimensions of shape.", - "output_type": "error", - "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mValueError\u001b[0m Traceback (most recent call last)", - "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[0mdummy\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mparameter\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mManualParameter\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mname\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m\"dummy\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2\u001b[0m data10 = qc.Loop(dummy[0:5:1]).each(\n\u001b[1;32m----> 3\u001b[1;33m recsamp_contr.acquisition).run(name='AlazarTest')\n\u001b[0m", - "\u001b[1;32ma:\\qcodes\\qcodes\\loops.py\u001b[0m in \u001b[0;36mrun\u001b[1;34m(self, background, use_threads, quiet, data_manager, station, progress_interval, *args, **kwargs)\u001b[0m\n\u001b[0;32m 759\u001b[0m \u001b[0mprev_loop\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 760\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 761\u001b[1;33m \u001b[0mdata_set\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mget_data_set\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mdata_manager\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m*\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 762\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 763\u001b[0m self.set_common_attrs(data_set=data_set, use_threads=use_threads,\n", - "\u001b[1;32ma:\\qcodes\\qcodes\\loops.py\u001b[0m in \u001b[0;36mget_data_set\u001b[1;34m(self, data_manager, *args, **kwargs)\u001b[0m\n\u001b[0;32m 683\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 684\u001b[0m data_set = new_data(arrays=self.containers(), mode=data_mode,\n\u001b[1;32m--> 685\u001b[1;33m data_manager=data_manager, *args, **kwargs)\n\u001b[0m\u001b[0;32m 686\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 687\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdata_set\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mdata_set\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[1;32ma:\\qcodes\\qcodes\\loops.py\u001b[0m in \u001b[0;36mcontainers\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 486\u001b[0m \u001b[1;31m# note that this supports lists (separate output arrays)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 487\u001b[0m \u001b[1;31m# and arrays (nested in one/each output array) of return values\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 488\u001b[1;33m \u001b[0maction_arrays\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_parameter_arrays\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0maction\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 489\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 490\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[1;32ma:\\qcodes\\qcodes\\loops.py\u001b[0m in \u001b[0;36m_parameter_arrays\u001b[1;34m(self, action)\u001b[0m\n\u001b[0;32m 560\u001b[0m \u001b[0msp_def\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m(\u001b[0m\u001b[0mshape\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m:\u001b[0m \u001b[1;36m1\u001b[0m \u001b[1;33m+\u001b[0m \u001b[0mj\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mj\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0msetpoints\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mvij\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mnij\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mlij\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 561\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0msp_def\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mall_setpoints\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 562\u001b[1;33m \u001b[0mall_setpoints\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0msp_def\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_make_setpoint_array\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m*\u001b[0m\u001b[0msp_def\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 563\u001b[0m \u001b[0mout\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mall_setpoints\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0msp_def\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 564\u001b[0m \u001b[0msetpoints\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0msetpoints\u001b[0m \u001b[1;33m+\u001b[0m \u001b[1;33m(\u001b[0m\u001b[0mall_setpoints\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0msp_def\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[1;32ma:\\qcodes\\qcodes\\loops.py\u001b[0m in \u001b[0;36m_make_setpoint_array\u001b[1;34m(self, shape, i, prev_setpoints, vals, name, label)\u001b[0m\n\u001b[0;32m 601\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 602\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mvals\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mshape\u001b[0m \u001b[1;33m!=\u001b[0m \u001b[0mshape\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 603\u001b[1;33m raise ValueError('nth setpoint array should have shape matching '\n\u001b[0m\u001b[0;32m 604\u001b[0m 'the first n dimensions of shape.')\n\u001b[0;32m 605\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[1;31mValueError\u001b[0m: nth setpoint array should have shape matching the first n dimensions of shape." - ] - } - ], - "source": [ - "dummy = parameter.ManualParameter(name=\"dummy\")\n", - "data10 = qc.Loop(dummy[0:5:1]).each(\n", - " recsamp_contr.acquisition).run(name='AlazarTest')" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "((array([0, 1, 2]), array([0, 1])), (array([0, 1, 2]), array([0, 1])))" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "((np.arange(3), np.arange(2)), (np.arange(3), np.arange(2)))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [] } ], "metadata": { diff --git a/qcodes/instrument_drivers/AlazarTech/ATS_acquisition_controllers.py b/qcodes/instrument_drivers/AlazarTech/ATS_acquisition_controllers.py index f4653cf1776d..a1d4a055c8c8 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS_acquisition_controllers.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS_acquisition_controllers.py @@ -3,142 +3,6 @@ import numpy as np -class HD_Controller(AcquisitionController): - """Heterodyne Measurement Controller - Does averaged DFT on 2 channel Alazar measurement - - TODO(nataliejpg) handling of channel number - TODO(nataliejpg) test angle data - """ - - def __init__(self, freq_dif): - self.freq_dif = freq_dif - self.samples_per_record = None - self.records_per_buffer = None - self.buffers_per_acquisition = None - self.number_of_channels = 2 - self.buffer = None - - def pre_start_capture(self, alazar): - """Get config data from alazar card and set up DFT""" - self.samples_per_record = alazar.samples_per_record() - self.records_per_buffer = alazar.records_per_buffer() - self.buffers_per_acquisition = alazar.buffers_per_acquisition() - self.sample_rate = alazar.get_sample_speed() - self.buffer = np.zeros(self.samples_per_record * - self.records_per_buffer * - self.number_of_channels) - # TODO(nataliejpg) leave explicit or save lines? add error/logging? - averaging = self.buffers_per_acquisition * self.records_per_buffer - record_duration = self.samples_per_record / self.sample_rate - time_period_dif = 1 / self.freq_dif - cycles_measured = record_duration / time_period_dif - oversampling_rate = self.sample_rate / (2 * self.freq_dif) - print("Average over {} records".format(averaging)) - print("Oscillations per record: {} (expect 100+)" - .format(cycles_measured)) - print("Oversampling rate: {} (expect > 2)".format(oversampling_rate)) - - integer_list = np.arange(self.samples_per_record) - angle_list = (2 * np.pi * self.freq_dif / self.sample_rate * - integer_list) - self.cos_list = np.cos(angle_list) - self.sin_list = np.sin(angle_list) - - def pre_acquire(self, alazar): - # gets called after 'AlazarStartCapture' - pass - - def handle_buffer(self, alazar, data): - self.buffer += data - - def post_acquire(self, alazar): - """Average over records in buffer and do DFT: - assumes samples are arranged in the buffer as follows: - S0A, S0B, ..., S1A, S1B, ... - with SXY the sample number X of channel Y. - """ - records_per_acquisition = (1. * self.buffers_per_acquisition * - self.records_per_buffer) - recordA = np.zeros(self.samples_per_record) - for i in range(self.records_per_buffer): - i0 = (i * self.samples_per_record * self.number_of_channels) - i1 = (i0 + self.samples_per_record * self.number_of_channels) - recordA += (self.buffer[i0:i1:self.number_of_channels] / - records_per_acquisition) - recordB = np.zeros(self.samples_per_record) - for i in range(self.records_per_buffer): - i0 = (i * self.samples_per_record * self.number_of_channels + 1) - i1 = (i0 + self.samples_per_record * self.number_of_channels) - recordB += (self.buffer[i0:i1:self.number_of_channels] / - records_per_acquisition) - - resA = self.fit(recordA) - resB = self.fit(recordB) - - return resA, resB - - def fit(self, rec): - """Do Discrete Fourier Transform and return magnitude and phase data""" - RePart = np.dot(rec, self.cos_list) / self.samples_per_record - ImPart = np.dot(rec, self.sin_list) / self.samples_per_record - # factor of 2 as amplitude is split between finite term - # and double frequency term - ampl = 2 * np.sqrt(RePart ** 2 + ImPart ** 2) - phase = math.atan2(ImPart, RePart) * 180 / (2 * math.pi) - return [ampl, phase] - - -class Basic_AcquisitionController(AcquisitionController): - """Basic AcquisitionController tested on ATS9360 - returns unprocessed data averaged by record with 2 channels - """ - - def __init__(self): - self.samples_per_record = None - self.records_per_buffer = None - self.buffers_per_acquisition = None - self.number_of_channels = 2 - self.buffer = None - - def pre_start_capture(self, alazar): - self.samples_per_record = alazar.samples_per_record() - self.records_per_buffer = alazar.records_per_buffer() - self.buffers_per_acquisition = alazar.buffers_per_acquisition() - self.buffer = np.zeros(self.samples_per_record * - self.records_per_buffer * - self.number_of_channels) - - def pre_acquire(self, alazar): - # gets called after 'AlazarStartCapture' - pass - - def handle_buffer(self, alazar, data): - self.buffer += data - - def post_acquire(self, alazar): - # average over records in buffer: - # for ATS9360 samples are arranged in the buffer as follows: - # S0A, S0B, ..., S1A, S1B, ... - # with SXY the sample number X of channel Y. - records_per_acquisition = (self.buffers_per_acquisition * - self.records_per_buffer) - recordA = np.zeros(self.samples_per_record) - for i in range(self.records_per_buffer): - i0 = (i * self.samples_per_record * self.number_of_channels) - i1 = (i0 + self.samples_per_record * self.number_of_channels) - recordA += (self.buffer[i0:i1:self.number_of_channels] / - records_per_acquisition) - - recordB = np.zeros(self.samples_per_record) - for i in range(self.records_per_buffer): - i0 = (i * self.samples_per_record * self.number_of_channels + 1) - i1 = (i0 + self.samples_per_record * self.number_of_channels) - recordB += (self.buffer[i0:i1:self.number_of_channels] / - records_per_acquisition) - return recordA, recordB - - # DFT AcquisitionController class Demodulation_AcquisitionController(AcquisitionController): """ diff --git a/qcodes/instrument_drivers/AlazarTech/Single_controller.py b/qcodes/instrument_drivers/AlazarTech/ave_controller.py similarity index 100% rename from qcodes/instrument_drivers/AlazarTech/Single_controller.py rename to qcodes/instrument_drivers/AlazarTech/ave_controller.py From e42200e6a4437bb7cdb5bddb640c1a01708cf997 Mon Sep 17 00:00:00 2001 From: Natalie Pearson Date: Mon, 21 Nov 2016 16:39:50 +0100 Subject: [PATCH 054/180] update to dos lists --- qcodes/instrument_drivers/AlazarTech/ATS.py | 3 +-- qcodes/instrument_drivers/AlazarTech/ATS9360.py | 10 ++++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/ATS.py b/qcodes/instrument_drivers/AlazarTech/ATS.py index 6a243082e316..4cff51bea787 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS.py @@ -11,14 +11,13 @@ # TODO(damazter) (C) logging # these items are important for generalizing this code to multiple alazar cards -# TODO(damazter) (W) remove 8 bits per sample requirement # TODO(damazter) (W) some alazar cards have a different number of channels :( # TODO(damazter) (S) tests to do: # acquisition that would overflow the board if measurement is not stopped # quickly enough. can this be solved by not reposting the buffers? -# TODO(nataliejpg) test!! +# TODO(nataliejpg) fix get_damples function which I have broken for ATS9360 class AlazarTech_ATS(Instrument): diff --git a/qcodes/instrument_drivers/AlazarTech/ATS9360.py b/qcodes/instrument_drivers/AlazarTech/ATS9360.py index cdac0771ece2..7d58397fa760 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS9360.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS9360.py @@ -3,8 +3,14 @@ class AlazarTech_ATS9360(AlazarTech_ATS): - # TODO(nataliejpg) add more options for the sample rate set using 10MHz ref - # including so that the 'get sample rate' function in ATS.py works + """ + This class is the driver for the ATS9360 board + it inherits from the ATS base class + + TODO(nataliejpg): + - add more options for the sample rate set using 10MHz ref + including so that the 'get sample rate' function in ATS.py works + """ def __init__(self, name, **kwargs): dll_path = 'C:\\WINDOWS\\System32\\ATSApi.dll' super().__init__(name, dll_path=dll_path, **kwargs) From efb0733b80c97eb841e870ccf37314c9657cbdbb Mon Sep 17 00:00:00 2001 From: Natalie Pearson Date: Mon, 21 Nov 2016 16:43:57 +0100 Subject: [PATCH 055/180] rename acq controllers --- .../AlazarTech/{RecBuf_controller.py => rec_buf_controller.py} | 0 .../AlazarTech/{RecSamp_controller.py => rec_samp_controller.py} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename qcodes/instrument_drivers/AlazarTech/{RecBuf_controller.py => rec_buf_controller.py} (100%) rename qcodes/instrument_drivers/AlazarTech/{RecSamp_controller.py => rec_samp_controller.py} (100%) diff --git a/qcodes/instrument_drivers/AlazarTech/RecBuf_controller.py b/qcodes/instrument_drivers/AlazarTech/rec_buf_controller.py similarity index 100% rename from qcodes/instrument_drivers/AlazarTech/RecBuf_controller.py rename to qcodes/instrument_drivers/AlazarTech/rec_buf_controller.py diff --git a/qcodes/instrument_drivers/AlazarTech/RecSamp_controller.py b/qcodes/instrument_drivers/AlazarTech/rec_samp_controller.py similarity index 100% rename from qcodes/instrument_drivers/AlazarTech/RecSamp_controller.py rename to qcodes/instrument_drivers/AlazarTech/rec_samp_controller.py From 569c1f079c507a252067f98ec1f40c91448968bf Mon Sep 17 00:00:00 2001 From: Natalie Pearson Date: Mon, 21 Nov 2016 16:54:52 +0100 Subject: [PATCH 056/180] actually renaming acq controllers --- .../AlazarTech/{Rec_controller.py => rec_controller.py} | 0 .../AlazarTech/{Samp_controller.py => samp_controller.py} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename qcodes/instrument_drivers/AlazarTech/{Rec_controller.py => rec_controller.py} (100%) rename qcodes/instrument_drivers/AlazarTech/{Samp_controller.py => samp_controller.py} (100%) diff --git a/qcodes/instrument_drivers/AlazarTech/Rec_controller.py b/qcodes/instrument_drivers/AlazarTech/rec_controller.py similarity index 100% rename from qcodes/instrument_drivers/AlazarTech/Rec_controller.py rename to qcodes/instrument_drivers/AlazarTech/rec_controller.py diff --git a/qcodes/instrument_drivers/AlazarTech/Samp_controller.py b/qcodes/instrument_drivers/AlazarTech/samp_controller.py similarity index 100% rename from qcodes/instrument_drivers/AlazarTech/Samp_controller.py rename to qcodes/instrument_drivers/AlazarTech/samp_controller.py From 779d11941a75d3087b34ba6ddbbb5965a7a07ef5 Mon Sep 17 00:00:00 2001 From: Natalie Pearson Date: Wed, 23 Nov 2016 19:42:35 +0100 Subject: [PATCH 057/180] attempt to fix sample_rate bug --- qcodes/instrument_drivers/AlazarTech/ATS9360.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/ATS9360.py b/qcodes/instrument_drivers/AlazarTech/ATS9360.py index 7d58397fa760..411b43cc83ea 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS9360.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS9360.py @@ -35,7 +35,7 @@ def __init__(self, name, **kwargs): label='Sample Rate', unit='S/s', value='10MHZ_REF_500MSPS', - byte_to_value_dict={ + byte_to_value_dict=(None if self.clock_source() != 'EXTERNAL_CLOCK_10MHz_REF' else { 0x1: '1KSPS', 0x2: '2KSPS', 0x4: '5KSPS', 0x8: '10KSPS', 0xA: '20KSPS', 0xC: '50KSPS', @@ -48,8 +48,7 @@ def __init__(self, name, **kwargs): 0x30: '500MSPS', 0x32: '800MSPS', 0x35: '1000MSPS', 0x37: '1200MSPS', 0x3A: '1500MSPS', 0x3D: '1800MSPS', - 0x40: 'EXTERNAL_CLOCK', - 500000000: '10MHZ_REF_500MSPS'}) + 0x40: 'EXTERNAL_CLOCK'})) self.add_parameter(name='clock_edge', parameter_class=AlazarParameter, label='Clock Edge', From 9199a217d727fd89770cd7f98159d56ee71d8f35 Mon Sep 17 00:00:00 2001 From: nataliejpg Date: Thu, 24 Nov 2016 17:57:10 +0100 Subject: [PATCH 058/180] begin refactor of sample controller --- .../instrument_drivers/AlazarTech/ATS9360.py | 27 +-- .../AlazarTech/samp_controller.py | 164 ++++++++++-------- 2 files changed, 97 insertions(+), 94 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/ATS9360.py b/qcodes/instrument_drivers/AlazarTech/ATS9360.py index 411b43cc83ea..4fe1add7ee05 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS9360.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS9360.py @@ -8,8 +8,7 @@ class AlazarTech_ATS9360(AlazarTech_ATS): it inherits from the ATS base class TODO(nataliejpg): - - add more options for the sample rate set using 10MHz ref - including so that the 'get sample rate' function in ATS.py works + - add clock source options and sample rate options """ def __init__(self, name, **kwargs): dll_path = 'C:\\WINDOWS\\System32\\ATSApi.dll' @@ -23,32 +22,12 @@ def __init__(self, name, **kwargs): label='Clock Source', unit=None, value='EXTERNAL_CLOCK_10MHz_REF', - byte_to_value_dict={1: 'INTERNAL_CLOCK', - 2: 'EXTERNAL_CLOCK', - 3: 'MEDIUM_EXTERNAL_CLOCK', - 4: 'SLOW_EXTERNAL_CLOCK', - 5: 'EXTERNAL_CLOCK_AC', - 6: 'EXTERNAL_CLOCK_DC', - 7: 'EXTERNAL_CLOCK_10MHz_REF'}) + byte_to_value_dict={7: 'EXTERNAL_CLOCK_10MHz_REF'}) self.add_parameter(name='sample_rate', parameter_class=AlazarParameter, label='Sample Rate', unit='S/s', - value='10MHZ_REF_500MSPS', - byte_to_value_dict=(None if self.clock_source() != 'EXTERNAL_CLOCK_10MHz_REF' else { - 0x1: '1KSPS', 0x2: '2KSPS', - 0x4: '5KSPS', 0x8: '10KSPS', - 0xA: '20KSPS', 0xC: '50KSPS', - 0xE: '100KSPS', 0x10: '200KSPS', - 0x12: '500KSPS', 0x14: '1MSPS', - 0x18: '2MSPS', 0x1A: '5MSPS', - 0x1C: '10MSPS', 0x1E: '20MSPS', - 0x22: '50MSPS', 0x24: '100MSPS', - 0x25: '125MSPS', 0x2B: '250MSPS', - 0x30: '500MSPS', 0x32: '800MSPS', - 0x35: '1000MSPS', 0x37: '1200MSPS', - 0x3A: '1500MSPS', 0x3D: '1800MSPS', - 0x40: 'EXTERNAL_CLOCK'})) + value=500000000) self.add_parameter(name='clock_edge', parameter_class=AlazarParameter, label='Clock Edge', diff --git a/qcodes/instrument_drivers/AlazarTech/samp_controller.py b/qcodes/instrument_drivers/AlazarTech/samp_controller.py index e5ee0c20dbe4..e37acc16d8b5 100644 --- a/qcodes/instrument_drivers/AlazarTech/samp_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/samp_controller.py @@ -3,6 +3,8 @@ import numpy as np from qcodes import Parameter from qcodes.utils.helpers import filter_win, filter_ls +from qcodes.instrument.parameter import ManualParameter +from qcodes.utils import validators class SamplesParam(Parameter): @@ -12,6 +14,7 @@ class SamplesParam(Parameter): sample data from the Alazar, averaged over records and buffers. TODO(nataliejpg) refactor setpoints/shapes horriblenesss + TODO(nataliejpg) setpoint units """ def __init__(self, name, instrument): @@ -20,24 +23,19 @@ def __init__(self, name, instrument): self.acquisitionkwargs = {} self.names = ('magnitude', 'phase') self.units = ('', '') - self.setpoint_names = (('sample_num',), ('sample_num',)) + self.setpoint_names = (('acq_time (s)',), ('acq_time (s)',)) self.setpoints = ((1,), (1,)) self.shapes = ((1,), (1,)) - def update_acquisition_kwargs(self, samp_time, **kwargs): - # needed to update config of the software parameter on sweep change - # freq setpoints tuple as needs to be hashable for look up - if samp_time: - npts = samp_time - n = tuple(np.arange(npts)) - self.setpoints = ((n,), (n,)) - self.shapes = ((npts,), (npts,)) - else: - raise ValueError( - 'samp_time not specified') - # updates dict to be used in acquisition get call - self.acquisitionkwargs.update(**kwargs) - +# def update_acquisition_kwargs(self, **kwargs): +# # updates dict to be used in acquisition get call +# self.acquisitionkwargs.update(**kwargs) + + def update_sweep(self, start, stop, npts): + n = tuple(np.linspace(start, stop, num=npts)) + self.setpoints = ((n,), (n,)) + self.shapes = ((npts,), (npts,)) + def get(self): mag, phase = self._instrument._get_alazar().acquire( acquisition_controller=self._instrument, @@ -62,26 +60,24 @@ class HD_Samples_Controller(AcquisitionController): and returned **kwargs: kwargs are forwarded to the Instrument base class - TODO(nataliejpg) fix sample rate problem TODO(nataliejpg) test filter options TODO(nataliejpg) finish implementation of channel b option - TODO(nataliejpg) make demodulation freq a param + TODO(nataliejpg) validators for int_time and int_delay """ - def __init__(self, name, alazar_name, demod_freq, samp_rate=5e8, + def __init__(self, name, alazar_name, samp_rate=5e8, filt='win', numtaps=101, chan_b=False, **kwargs): filter_dict = {'win': 0, 'ls': 1} - self.demodulation_frequency = demod_freq self.sample_rate = samp_rate self.filter = filter_dict[filt] self.numtaps = numtaps self.chan_b = chan_b - self.samples_per_record = None - self.records_per_buffer = None - self.buffers_per_acquisition = None + self.samples_per_record = 0 + self.records_per_buffer = 0 + self.buffers_per_acquisition = 0 self.number_of_channels = 2 - self.samples_delay = None - self.samples_time = None + self.samples_delay = 0 + self.samples_time = 0 self.cos_list = None self.sin_list = None self.buffer = None @@ -92,8 +88,17 @@ def __init__(self, name, alazar_name, demod_freq, samp_rate=5e8, self.add_parameter(name='acquisition', parameter_class=SamplesParam) - - def update_acquisitionkwargs(self, **kwargs): + self.add_parameter(name='demodulation_frequency', + initial_value=20e6, + parameter_class=ManualParameter) + self.add_parameter(name='int_time', + initial_value=None, + parameter_class=ManualParameter) + self.add_parameter(name='int_delay', + initial_value=None, + parameter_class=ManualParameter) + + def update_acquisition_settings(self, **kwargs): """ Updates the kwargs to be used when alazar_driver.acquire is called via a get call of the @@ -106,47 +111,32 @@ def update_acquisitionkwargs(self, **kwargs): :param kwargs: :return: """ + alazar = self._get_alazar() samples_per_record = kwargs['samples_per_record'] - sample_rate = self.sample_rate - - if 'int_delay' in kwargs: - int_delay = kwargs.pop('int_delay') - samp_delay = int_delay * sample_rate - samples_delay_min = (self.numtaps - 1) - if samp_delay < samples_delay_min: - int_delay_min = samples_delay_min / sample_rate - logging.warning( - 'delay is less than recommended for filter choice: ' - '(expect delay >= {}'.format(int_delay_min)) - else: + self.sample_rate = alazar.get_sample_rate() + time_available = samples_per_record / self.sample_rate + + if self.int_delay() == 0: samp_delay = self.numtaps - 1 - - if 'int_time' in kwargs: - int_time = kwargs.pop('int_time') - samp_time = int_time * sample_rate - samples_time_max = (samples_per_record - samp_delay) - oscilations_measured = int_time * self.demodulation_frequency - oversampling = sample_rate / (2 * self.demodulation_frequency) - if samp_time > samples_time_max: - int_time_max = samples_time_max / sample_rate - raise ValueError('int_time {} is longer than total_time - ' - 'delay: {}'.format(int_time, int_time_max)) - elif oscilations_measured < 10: - logging.warning('{} oscilations measured, recommend at ' - 'least 10: decrease sampling rate, take ' - 'more samples or increase demodulation ' - 'freq'.format(oscilations_measured)) - elif oversampling < 1: - logging.warning('oversampling rate is {}, recommend > 1: ' - 'increase sampling rate or decrease ' - 'demodulation frequency'.format(oversampling)) + self.int_delay(samp_delay / self.sample_rate) else: - samp_time = samples_per_record - samp_delay - - self.samples_time = int(samp_time) - self.samples_delay = int(samp_delay) + self.check_delay(time_available) +# except ValueError as e: +# self.int_delay(0) + + time_available -= self.int_delay() + + if self.int_time() == 0: + self.int_time(time_available) + else: + self.check_time(time_available) + + start = self.int_delay() + stop = self.int_delay() + self.int_time() + npts = int(self.int_time() * self.sample_rate) - self.acquisition.update_acquisition_kwargs(self.samples_time, **kwargs) + self.acquisition.acquisitionkwargs.update(**kwargs) + self.acquisition.update_sweep(start, stop, npts) def pre_start_capture(self): """ @@ -162,9 +152,12 @@ def pre_start_capture(self): self.buffer = np.zeros(self.samples_per_record * self.records_per_buffer * self.number_of_channels) + if self.sample_rate != alazar.get_sample_rate(): + raise Exception('acq controller sample rate does not match instrument' + 'value, most likely need to call update_acquisition_settings' ) integer_list = np.arange(self.samples_per_record, dtype=np.uint16) - angle_list = (2 * np.pi * self.demodulation_frequency / + angle_list = (2 * np.pi * self.demodulation_frequency() / self.sample_rate * integer_list) self.cos_list = np.cos(angle_list) @@ -223,6 +216,7 @@ def post_acquire(self): return magA, phaseA def fit(self, rec): + print('got to fit, ave %s' % np.mean(rec)) """ Applies volts conversion, demodulation fit, low bandpass filter and integration limits to samples array @@ -238,10 +232,13 @@ def fit(self, rec): ' bps != 12, centered raw samples returned') volt_rec = rec - np.mean(rec) + print(self.cos_list) + print(self.demodulation_frequency()) + # multiply with software wave re_wave = np.multiply(volt_rec, self.cos_list) im_wave = np.multiply(volt_rec, self.sin_list) - cutoff = self.demodulation_frequency / 10 + cutoff = self.demodulation_frequency() / 10 # filter out higher freq component if self.filter == 0: @@ -256,11 +253,11 @@ def fit(self, rec): self.sample_rate, self.numtaps) # apply integration limits - start = self.samples_delay - end = start + self.samples_time + beginning = int(self.int_delay() / self.sample_rate) + end = beginning + int(self.int_time() / self.sample_rate) - re_limited = re_filtered[start:end] - im_limited = im_filtered[start:end] + re_limited = re_filtered[beginning:end] + im_limited = im_filtered[beginning:end] # convert to magnitude and phase complex_num = re_limited + im_limited * 1j @@ -269,7 +266,34 @@ def fit(self, rec): return mag, phase - + def check_delay(self, time_available): + samples_delay_min = (self.numtaps - 1) + int_delay_min = samples_delay_min / self.sample_rate + if self.int_delay() > time_available: + raise ValueError('int_delay {} is longer than total_time ' + '{}'.format(self.int_delay(), time_available)) + elif self.int_delay() < int_delay_min: + logging.warning( + 'delay is less than recommended for filter choice: ' + '(expect delay >= {}'.format(int_delay_min)) + + def check_time(self, time_available): + oscilations_measured = self.int_time() * self.demodulation_frequency() + oversampling = self.sample_rate / (2 * self.demodulation_frequency()) + if self.int_time() > time_available: + raise ValueError('int_time {} is longer than total_time - ' + 'delay = {}'.format(self.int_time(), time_available)) + elif oscilations_measured < 10: + logging.warning('{} oscilations measured, recommend at ' + 'least 10: decrease sampling rate, take ' + 'more samples or increase demodulation ' + 'freq'.format(oscilations_measured)) + elif oversampling < 1: + logging.warning('oversampling rate is {}, recommend > 1: ' + 'increase sampling rate or decrease ' + 'demodulation frequency'.format(oversampling)) + + def sample_to_volt_u12(raw_samples, bps): """ Applies volts conversion for 12 bit sample data stored From 5e9ab450c870be852760c1533aac36882ed04176 Mon Sep 17 00:00:00 2001 From: Natalie Pearson Date: Wed, 30 Nov 2016 14:51:44 +0100 Subject: [PATCH 059/180] delete detailed excess aqc controllers --- .../AlazarTech/ave_controller.py | 265 --------------- .../AlazarTech/rec_buf_controller.py | 220 ------------ .../AlazarTech/rec_controller.py | 294 ---------------- .../AlazarTech/rec_samp_controller.py | 233 ------------- .../AlazarTech/samp_controller.py | 317 ------------------ 5 files changed, 1329 deletions(-) delete mode 100644 qcodes/instrument_drivers/AlazarTech/ave_controller.py delete mode 100644 qcodes/instrument_drivers/AlazarTech/rec_buf_controller.py delete mode 100644 qcodes/instrument_drivers/AlazarTech/rec_controller.py delete mode 100644 qcodes/instrument_drivers/AlazarTech/rec_samp_controller.py delete mode 100644 qcodes/instrument_drivers/AlazarTech/samp_controller.py diff --git a/qcodes/instrument_drivers/AlazarTech/ave_controller.py b/qcodes/instrument_drivers/AlazarTech/ave_controller.py deleted file mode 100644 index d23767c7aeb2..000000000000 --- a/qcodes/instrument_drivers/AlazarTech/ave_controller.py +++ /dev/null @@ -1,265 +0,0 @@ -import logging -from .ATS import AcquisitionController -import numpy as np -import qcodes.utils.helpers as helpers - - -class HD_Controller(AcquisitionController): - """ - This is the Acquisition Controller class which works with the ATS9360, - averaging over buffers and records, demodulating with a software - reference signal, averaging over the samples. - args: - name: name for this acquisition_conroller as an instrument - alazar_name: the name of the alazar instrument such that this controller - can communicate with the Alazar - demod_freq: the frequency of the software wave to be created - samp_rate: the rate of sampling - filt: the filter to be used to filter out double freq component - chan_b: whether there is also a second channel of data to be processed - and returned - **kwargs: kwargs are forwarded to the Instrument base class - - TODO(nataliejpg) fix sample rate problem - TODO(nataliejpg) test filter options - TODO(nataliejpg) finish implementation of channel b option - TODO(nataliejpg) make demodulation freq a param - """ - - def __init__(self, name, alazar_name, demod_freq, samp_rate=5e8, - filt='win', numtaps=101, chan_b=False, **kwargs): - filter_dict = {'win': 0, 'ls': 1, 'dot': 2} - self.demodulation_frequency = demod_freq - self.sample_rate = samp_rate - self.filter = filter_dict[filt] - self.numtaps = numtaps - self.acquisitionkwargs = {} - self.chan_b = chan_b - self.samples_per_record = None - self.records_per_buffer = None - self.buffers_per_acquisition = None - self.number_of_channels = 2 - self.samples_delay = None - self.samples_time = None - self.cos_list = None - self.sin_list = None - self.buffer = None - self.board_info = None - # make a call to the parent class and by extension, - # create the parameter structure of this class - super().__init__(name, alazar_name, **kwargs) - - self.add_parameter(name='acquisition', - names=('magnitude', 'phase'), - units=('', ''), - get_cmd=self.do_acquisition) - - def update_acquisitionkwargs(self, **kwargs): - """ - Updates the kwargs to be used when - alazar_driver.acquire is called. - - It is also used to set the limits on the selection of - samples used (bounded by delay and integration time) - - :param kwargs: - :return: - """ - samples_per_record = kwargs['samples_per_record'] - sample_rate = self.sample_rate - - if 'int_delay' in kwargs: - int_delay = kwargs.pop('int_delay') - samp_delay = int_delay * sample_rate - samples_delay_min = (self.numtaps - 1) - if samp_delay < samples_delay_min: - int_delay_min = samples_delay_min / sample_rate - logging.warning( - 'delay is less than recommended for filter choice: ' - '(expect delay >= {}'.format(int_delay_min)) - else: - samp_delay = self.numtaps - 1 - - if 'int_time' in kwargs: - int_time = kwargs.pop('int_time') - samp_time = int_time * sample_rate - samples_time_max = (samples_per_record - samp_delay) - oscilations_measured = int_time * self.demodulation_frequency - oversampling = sample_rate / (2 * self.demodulation_frequency) - if samp_time > samples_time_max: - int_time_max = samples_time_max / sample_rate - raise ValueError('int_time {} is longer than total_time - ' - 'delay: {}'.format(int_time, int_time_max)) - elif oscilations_measured < 10: - logging.warning('{} oscilations measured, recommend at ' - 'least 10: decrease sampling rate, take ' - 'more samples or increase demodulation ' - 'freq'.format(oscilations_measured)) - elif oversampling < 1: - logging.warning('oversampling rate is {}, recommend > 1: ' - 'increase sampling rate or decrease ' - 'demodulation frequency'.format(oversampling)) - else: - samp_time = samples_per_record - samp_delay - - self.samples_time = int(samp_time) - self.samples_delay = int(samp_delay) - - self.acquisitionkwargs.update(**kwargs) - - def do_acquisition(self): - """ - this method performs an acquisition, which is the get_cmd for the - acquisiion parameter of this instrument - :return: - """ - values = self._get_alazar().acquire(acquisition_controller=self, - **self.acquisitionkwargs) - return values - - def pre_start_capture(self): - """ - Called before capture start to update Acquisition Controller with - alazar acquisition params and set up software wave for demodulation. - :return: - """ - alazar = self._get_alazar() - self.samples_per_record = alazar.samples_per_record.get() - self.records_per_buffer = alazar.records_per_buffer.get() - self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() - self.board_info = alazar.get_idn() - self.buffer = np.zeros(self.samples_per_record * - self.records_per_buffer * - self.number_of_channels) - - integer_list = np.arange(self.samples_per_record, dtype=np.uint16) - angle_list = (2 * np.pi * self.demodulation_frequency / - self.sample_rate * integer_list) - - self.cos_list = np.cos(angle_list) - self.sin_list = np.sin(angle_list) - - def pre_acquire(self): - """ - See AcquisitionController - :return: - """ - pass - - def handle_buffer(self, data): - """ - Adds data from alazar to buffer (effectively averaging) - :return: - """ - self.buffer += data - - def post_acquire(self): - """ - Processes the data according to ATS9360 settings, splitting into - records and averaging over them, then applying demodulation fit - nb: currently only channel A - :return: samples_magnitude_array, samples_phase_array - """ - records_per_acquisition = (self.buffers_per_acquisition * - self.records_per_buffer) - # for ATS9360 samples are arranged in the buffer as follows: - # S00A, S00B, S01A, S01B...S10A, S10B, S11A, S11B... - # where SXYZ is record X, sample Y, channel Z. - - # break buffer up into records and averages over them - recA = np.zeros(self.samples_per_record) - for i in range(self.records_per_buffer): - i0 = (i * self.samples_per_record * self.number_of_channels) - i1 = (i0 + self.samples_per_record * self.number_of_channels) - recA += self.buffer[i0:i1:self.number_of_channels] - recordA = np.uint16(recA / records_per_acquisition) - - # do demodulation - magA, phaseA = self.fit(recordA) - - # same for chan b - if self.chan_b: - raise NotImplementedError('chan b code not complete') - # recordB = np.zeros(self.samples_per_record, dtype=np.uint16) - # for i in range(self.records_per_buffer): - # i0 = (i * self.samples_per_record * - # self.number_of_channels + 1) - # i1 = (i0 + self.samples_per_record * self.number_of_channels) - # recordB += np.uint16(self.buffer[i0:i1:self.number_of_channels] / - # records_per_acquisition) - # magB, phaseB = self.fit(recordB) - - return magA, phaseA - - def fit(self, rec): - """ - Applies volts conversion, demodulation fit, low bandpass filter - and integration limits to samples array and averages - :return: magnitude, phase - """ - - # convert rec to volts - bps = self.board_info['bits_per_sample'] - if bps == 12: - volt_rec = sample_to_volt_u12(rec, bps) - else: - logging.warning('sample to volt conversion does not exist for' - ' bps != 12, centered raw samples returned') - volt_rec = rec - np.mean(rec) - - # multiply with software wave - re_wave = np.multiply(volt_rec, self.cos_list) - im_wave = np.multiply(volt_rec, self.sin_list) - cutoff = self.demodulation_frequency / 10 - - # filter out higher freq component - if self.filter == 0: - re_filtered = helpers.filter_win(re_wave, cutoff, - self.sample_rate, self.numtaps) - im_filtered = helpers.filter_win(im_wave, cutoff, - self.sample_rate, self.numtaps) - elif self.filter == 1: - re_filtered = helpers.filter_ls(re_wave, cutoff, - self.sample_rate, self.numtaps) - im_filtered = helpers.filter_ls(im_wave, cutoff, - self.sample_rate, self.numtaps) - elif self.filter == 2: - re_filtered = re_wave - im_filtered = im_wave - - # apply integration limits - start = self.samples_delay - end = start + self.samples_time - - re_limited = re_filtered[start:end] - im_limited = im_filtered[start:end] - - # convert to magnitude and phase - complex_num = re_limited + im_limited * 1j - mag = np.mean(abs(complex_num)) - phase = np.mean(np.angle(complex_num, deg=True)) - - return mag, phase - - -def sample_to_volt_u12(raw_samples, bps): - """ - Applies volts conversion for 12 bit sample data stored - in 2 bytes - :return: samples_magnitude_array, samples_phase_array - """ - - # right_shift 16-bit sample by 4 to get 12 bit sample - shifted_samples = np.right_shift(raw_samples, 4) - - # Alazar calibration - code_zero = (1 << (bps - 1)) - 0.5 - code_range = (1 << (bps - 1)) - 0.5 - - # TODO(nataliejpg) make this not hard coded - input_range_volts = 1 - # Convert to volts - volt_samples = np.float64(input_range_volts * - (shifted_samples - code_zero) / code_range) - - return volt_samples diff --git a/qcodes/instrument_drivers/AlazarTech/rec_buf_controller.py b/qcodes/instrument_drivers/AlazarTech/rec_buf_controller.py deleted file mode 100644 index 65ddb9dea4d7..000000000000 --- a/qcodes/instrument_drivers/AlazarTech/rec_buf_controller.py +++ /dev/null @@ -1,220 +0,0 @@ -from .ATS import AcquisitionController -import numpy as np -from qcodes import Parameter -from scipy import signal - - -class RecBufParam(Parameter): - """ - Hardware controlled parameter class for Alazar acquisition. To be used with - HD_Samples_Controller (tested with ATS9360 board) for return of an array of - sample data from the Alazar, averaged over records and buffers. - """ - - def __init__(self, name, instrument): - super().__init__(name) - self._instrument = instrument - self.acquisitionkwargs = {} - self.names = ('magnitude', 'phase') - self.units = ('', '') - self.setpoint_names = (('rec_num', 'buf_num'), ('rec_num', 'buf_num')) - self.setpoints = ((1, 1), (1, 1)) - self.shapes = ((1, 1), (1, 1)) - - def update_acquisition_kwargs(self, **kwargs): - # needed to update config of the software parameter on sweep change - # freq setpoints tuple as needs to be hashable for look up - if 'records_per_buffer' and 'buffers_per_acquisition' in kwargs: - rpts = kwargs['records_per_buffer'] - bpts = kwargs['buffers_per_acquisition'] - r = tuple(np.arange(rpts)) - b = tuple(np.arange(bpts)) - self.setpoints = ((r, b), (r, b)) - self.shapes = ((rpts, bpts), (rpts, bpts)) - else: - raise ValueError( - 'records_per_buffer and buffers_per_acquisition must be specified') - # updates dict to be used in acquisition get call - self.acquisitionkwargs.update(**kwargs) - - def get(self): - mag, phase = self._instrument._get_alazar().acquire( - acquisition_controller=self._instrument, - **self.acquisitionkwargs) - return mag, phase - - -class HD_RecBuf_Controller(AcquisitionController): - """ - This is the Acquisition Controller class which works with the ATS9360, - averaging over buffers and records and demodulating with a software - reference signal, returning the samples. - args: - name: name for this acquisition_conroller as an instrument - alazar_name: the name of the alazar instrument such that this controller - can communicate with the Alazar - demod_freq: the frequency of the software wave to be created - samp_rate: the rate of sampling - filt: the filter to be used to filter out double freq component - chan_b: whether there is also a second channel of data to be processed - and returned - **kwargs: kwargs are forwarded to the Instrument base class - - TODO(nataliejpg) fix sample rate problem - TODO(nataliejpg) test filter options - TODO(nataliejpg) test mag phase logic - TODO(nataliejpg) finish implementation of channel b option - TODO(nataliejpg) make filter settings not hard coded - """ - - def __init__(self, name, alazar_name, demod_freq, samp_rate=500e6, - filt='win', chan_b=False, **kwargs): - filter_dict = {'win': 0, 'hamming': 1, 'ls': 2} - self.demodulation_frequency = demod_freq - self.sample_rate = samp_rate - self.filter = filter_dict[filt] - self.chan_b = chan_b - self.samples_per_record = 0 - self.records_per_buffer = 0 - self.buffers_per_acquisition = 0 - self.number_of_channels = 2 - self.cos_list = None - self.sin_list = None - self.buffer = None - self.buf_count = 0 - # make a call to the parent class and by extension, - # create the parameter structure of this class - super().__init__(name, alazar_name, **kwargs) - - self.add_parameter(name='acquisition', - parameter_class=RecBufParam) - - def update_acquisitionkwargs(self, **kwargs): - """ - This method must be used to update the kwargs used for the acquisition - with the alazar_driver.acquire - :param kwargs: - :return: - """ - self.acquisition.update_acquisition_kwargs(**kwargs) - - def pre_start_capture(self): - """ - See AcquisitionController - :return: - """ - alazar = self._get_alazar() - self.samples_per_record = alazar.samples_per_record.get() - self.records_per_buffer = alazar.records_per_buffer.get() - self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() - self.buf_count = 0 - self.samples_per_buffer = (self.samples_per_record * - self.records_per_buffer * - self.buffers_per_acquisition * - self.number_of_channels) - self.buffer = np.zeros(self.samples_per_buffer) - - integer_list = np.arange(self.samples_per_record) - angle_list = (2 * np.pi * self.demodulation_frequency / - self.sample_rate * integer_list) - - cos_list = np.cos(angle_list) - sin_list = np.sin(angle_list) - self.cos_mat = np.kron(np.ones((1, self.records_per_buffer)), cos_list) - self.sin_mat = np.kron(np.ones((1, self.records_per_buffer)), sin_list) - - def pre_acquire(self): - """ - See AcquisitionController - :return: - """ - # this could be used to start an Arbitrary Waveform Generator, etc... - # using this method ensures that the contents are executed AFTER the - # Alazar card starts listening for a trigger pulse - pass - - def handle_buffer(self, data): - """ - See AcquisitionController - :return: - """ - i0 = self.bufcount * self.samples_per_buffer - i1 = i0 + self.samples_per_buffer - self.buffer[i0:i1] = data - self.buf_count += 1 - - def post_acquire(self): - """ - See AcquisitionController - :return: - """ - # for ATS9360 samples are arranged in the buffer as follows: - # S00A, S00B, S01A, S01B...S10A, S10B, S11A, S11B... - # where SXYZ is record X, sample Y, channel Z. - - # reshapes data to be (samples * records * buffers) - - # TODO!! - - magA, phaseA = 0, 0 - - return magA, phaseA - - def fit(self, rec): - # center rec around 0 - rec = rec - np.mean(rec) - - # multiply with software wave - re_wave = np.multiply(rec, self.cos_mat) - im_wave = np.multiply(rec, self.sin_mat) - cutoff = self.demodulation_frequency - numtaps = 30 - axis = 0 - - # filter out double freq component to obtian constant term - if self.filter == 0: - RePart = self.filter_win(re_wave, numtaps, cutoff, axis=axis) - ImPart = self.filter_win(im_wave, numtaps, cutoff, axis=axis) - elif self.filter == 1: - RePart = self.filter_hamming(re_wave, numtaps, cutoff, axis=axis) - ImPart = self.filter_hamming(im_wave, numtaps, cutoff, axis=axis) - elif self.filter == 2: - RePart = self.filter_ls(re_wave, numtaps, cutoff, axis, axis=axis) - ImPart = self.filter_ls(im_wave, numtaps, cutoff, axis, axis=axis) - - # convert to magnitude and phase data and average over samples - # data returned is (records * buffers) - complex_mat = RePart + ImPart * 1j - mag = np.mean(2 * abs(complex_mat), axis=0) - phase = np.mean(np.angle(complex_mat, axis=0, deg=True)) - - return mag, phase - - def filter_hamming(self, rec, numtaps, cutoff, axis=-1): - sample_rate = self.sample_rate - nyq_rate = sample_rate / 2. - fir_coef = signal.firwin(numtaps, - cutoff / nyq_rate, - window="hamming") - filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec, axis=axis) - return filtered_rec - - def filter_win(self, rec, numtaps, cutoff, axis=-1): - sample_rate = self.sample_rate - nyq_rate = sample_rate / 2. - fir_coef = signal.firwin(numtaps, - cutoff / nyq_rate) - filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec, axis=axis) - return filtered_rec - - def filter_ls(self, rec, numtaps, cutoff, axis=-1): - sample_rate = self.sample_rate - nyq_rate = sample_rate / 2. - bands = [0, cutoff / nyq_rate, cutoff / nyq_rate, 1] - desired = [1, 1, 0, 0] - fir_coef = signal.firls(numtaps, - bands, - desired, - nyq=nyq_rate) - filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec, axis=axis) - return filtered_rec diff --git a/qcodes/instrument_drivers/AlazarTech/rec_controller.py b/qcodes/instrument_drivers/AlazarTech/rec_controller.py deleted file mode 100644 index 5513e384264b..000000000000 --- a/qcodes/instrument_drivers/AlazarTech/rec_controller.py +++ /dev/null @@ -1,294 +0,0 @@ -import logging -from .ATS import AcquisitionController -import numpy as np -from qcodes import Parameter -from qcodes.utils.helpers import filter_win, filter_ls - - -class RecordsParam(Parameter): - """ - Hardware controlled parameter class for Alazar acquisition. To be used with - HD_Records_Controller (tested with ATS9360 board) for return of an array of - record data from the Alazar, averaged over samples and buffers. - - TODO(nataliejpg) fix setpoints/shapes horriblenesss - """ - - def __init__(self, name, instrument): - super().__init__(name) - self._instrument = instrument - self.acquisitionkwargs = {} - self.names = ('magnitude', 'phase') - self.units = ('', '') - self.setpoint_names = (('record_num',), ('record_num',)) - self.setpoints = ((1,), (1,)) - self.shapes = ((1,), (1,)) - - def update_acquisition_kwargs(self, **kwargs): - # needed to update config of the software parameter on sweep change - # freq setpoints tuple as needs to be hashable for look up - if 'records_per_buffer' in kwargs: - npts = kwargs['records_per_buffer'] - n = tuple(np.arange(npts)) - self.setpoints = ((n,), (n,)) - self.shapes = ((npts,), (npts,)) - else: - raise ValueError('records_per_buffer must be specified') - # updates dict to be used in acquisition get call - self.acquisitionkwargs.update(**kwargs) - - def get(self): - mag, phase = self._instrument._get_alazar().acquire( - acquisition_controller=self._instrument, - **self.acquisitionkwargs) - return mag, phase - - -class HD_Records_Controller(AcquisitionController): - """ - This is the Acquisition Controller class which works with the ATS9360, - averaging over buffers and records and demodulating with a software - reference signal, returning the samples. - args: - name: name for this acquisition_conroller as an instrument - alazar_name: the name of the alazar instrument such that this controller - can communicate with the Alazar - demod_freq: the frequency of the software wave to be created - samp_rate: the rate of sampling - filt: the filter to be used to filter out double freq component - numtaps: number of freq components used in the filter - chan_b: whether there is also a second channel of data to be processed - and returned - **kwargs: kwargs are forwarded to the Instrument base class - - TODO(nataliejpg) fix sample rate problem - TODO(nataliejpg) test filter options - TODO(nataliejpg) finish implementation of channel b option - TODO(nataliejpg) make demodulation freq a param - """ - - def __init__(self, name, alazar_name, demod_freq, samp_rate=5e8, - filt='win', numtaps=101, chan_b=False, **kwargs): - filter_dict = {'win': 0, 'ls': 1, 'dot': 2} - self.demodulation_frequency = demod_freq - self.sample_rate = samp_rate - self.filter = filter_dict[filt] - self.numtaps = numtaps - self.chan_b = chan_b - self.samples_per_record = None - self.records_per_buffer = None - self.buffers_per_acquisition = None - self.number_of_channels = 2 - self.samples_delay = None - self.samples_time = None - self.cos_mat = None - self.sin_mat = None - self.buffer = None - self.board_info = None - # make a call to the parent class and by extension, - # create the parameter structure of this class - super().__init__(name, alazar_name, **kwargs) - - self.add_parameter(name='acquisition', - parameter_class=RecordsParam) - - def update_acquisitionkwargs(self, **kwargs): - """ - Updates the kwargs to be used when - alazar_driver.acquire is called via a get call of the - acquisition RecordsParam. - - It is also used to set the limits on the selection of - samples used (bounded by delay and integration time) - - :param kwargs: - :return: - """ - samples_per_record = kwargs['samples_per_record'] - sample_rate = self.sample_rate - - if 'int_delay' in kwargs: - int_delay = kwargs.pop('int_delay') - samp_delay = int_delay * sample_rate - samples_delay_min = (self.numtaps - 1) - if samp_delay < samples_delay_min: - int_delay_min = samples_delay_min / sample_rate - logging.warning( - 'delay is less than recommended for filter choice: ' - '(expect delay >= {}'.format(int_delay_min)) - else: - samp_delay = self.numtaps - 1 - - if 'int_time' in kwargs: - int_time = kwargs.pop('int_time') - samp_time = int_time * sample_rate - samples_time_max = (samples_per_record - samp_delay) - oscilations_measured = int_time * self.demodulation_frequency - oversampling = sample_rate / (2 * self.demodulation_frequency) - if samp_time > samples_time_max: - int_time_max = samples_time_max / sample_rate - raise ValueError('int_time {} is longer than total_time - ' - 'delay: {}'.format(int_time, int_time_max)) - elif oscilations_measured < 10: - logging.warning('{} oscilations measured, recommend at ' - 'least 10: decrease sampling rate, take ' - 'more samples or increase demodulation ' - 'freq'.format(oscilations_measured)) - elif oversampling < 1: - logging.warning('oversampling rate is {}, recommend > 1: ' - 'increase sampling rate or decrease ' - 'demodulation frequency'.format(oversampling)) - else: - samp_time = samples_per_record - samp_delay - - self.samples_time = int(samp_time) - self.samples_delay = int(samp_delay) - - self.acquisition.update_acquisition_kwargs(**kwargs) - - def pre_start_capture(self): - """ - Called before capture start to update Acquisition Controller with - alazar acquisition params and set up software wave for demodulation. - - sine and cosine matrices have shape (samples * records). - - :return: - """ - alazar = self._get_alazar() - self.samples_per_record = alazar.samples_per_record.get() - self.records_per_buffer = alazar.records_per_buffer.get() - self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() - self.board_info = alazar.get_idn() - self.buffer = np.zeros(self.samples_per_record * - self.records_per_buffer * - self.number_of_channels) - - integer_list = np.arange(self.samples_per_record, dtype=np.uint16) - angle_list = (2 * np.pi * self.demodulation_frequency / - self.sample_rate * integer_list) - - cos_list = np.cos(angle_list).reshape(self.samples_per_record, 1) - sin_list = np.sin(angle_list).reshape(self.samples_per_record, 1) - - self.cos_mat = np.kron(np.ones((1, self.records_per_buffer)), cos_list) - self.sin_mat = np.kron(np.ones((1, self.records_per_buffer)), sin_list) - - def pre_acquire(self): - """ - See AcquisitionController - :return: - """ - pass - - def handle_buffer(self, data): - """ - Adds data from alazar to buffer (effectively averaging) - :return: - """ - self.buffer += data - - def post_acquire(self): - """ - Processes the data according to ATS9360 settings, splitting into - records and averaging over them, then applying demodulation fit - nb: currently only channel A - :return: samples_magnitude_array, samples_phase_array - """ - - # for ATS9360 samples are arranged in the buffer as follows: - # S00A, S00B, S01A, S01B...S10A, S10B, S11A, S11B... - # where SXYZ is record X, sample Y, channel Z. - - # break buffer up into records and shapes to be (samples * records) - recordA = np.zeros((self.samples_per_record, self.records_per_buffer), - dtype=np.uint16) - for i in range(self.records_per_buffer): - i0 = (i * self.samples_per_record * self.number_of_channels) - i1 = (i0 + self.samples_per_record * self.number_of_channels) - recordA[:, i] = np.uint16( - self.buffer[i0:i1:self.number_of_channels] / - self.buffers_per_acquisition) - - # do demodulation - magA, phaseA = self.fit(recordA) - - # same for chan b - if self.chan_b: - raise NotImplementedError('chan b code not complete') - - return magA, phaseA - - def fit(self, rec): - """ - Applies volts conversion, demodulation fit, low bandpass filter - and integration limits to samples * records array - :return: records_magnitude_array, records_phase_array - """ - - # convert rec to volts - bps = self.board_info['bits_per_sample'] - if bps == 12: - volt_rec = sample_to_volt_u12(rec, bps) - else: - logging.warning('sample to volt conversion does not exist for' - ' bps != 12, centered raw samples returned') - volt_rec = rec - np.mean(rec, 0) - - # multiply with software wave - re_wave = np.multiply(volt_rec, self.cos_mat) - im_wave = np.multiply(volt_rec, self.sin_mat) - cutoff = self.demodulation_frequency / 10 - ax = 0 - - # filter out higher freq component - if self.filter == 0: - re_filtered = filter_win(re_wave, cutoff, self.sample_rate, - self.numtaps, axis=ax) - im_filtered = filter_win(im_wave, cutoff, self.sample_rate, - self.numtaps, axis=ax) - elif self.filter == 1: - re_filtered = filter_ls(re_wave, cutoff, self.sample_rate, - self.numtaps, axis=ax) - im_filtered = filter_ls(im_wave, cutoff, self.sample_rate, - self.numtaps, axis=ax) - elif self.filter == 2: - re_filtered = re_wave - im_filtered = im_wave - - # apply integration limits - start = self.samples_delay - end = start + self.samples_time - - re_limited = re_filtered[start:end, :] - im_limited = im_filtered[start:end, :] - - # convert to magnitude and phase - complex_num = re_limited + im_limited * 1j - mag = np.mean(abs(complex_num), 0) - phase = np.mean(np.angle(complex_num, deg=True), 0) - - return mag, phase - - -def sample_to_volt_u12(raw_samples, bps): - """ - Applies volts conversion for 12 bit sample data stored - in 2 bytes - :return: samples_magnitude_array, samples_phase_array - """ - - # right_shift 16-bit sample by 4 to get 12 bit sample - shifted_samples = np.right_shift(raw_samples, 4) - - # Alazar calibration - code_zero = (1 << (bps - 1)) - 0.5 - code_range = (1 << (bps - 1)) - 0.5 - - # TODO(nataliejpg) make this not hard coded - input_range_volts = 1 - # Convert to volts - volt_samples = np.float64(input_range_volts * - (shifted_samples - code_zero) / code_range) - - return volt_samples diff --git a/qcodes/instrument_drivers/AlazarTech/rec_samp_controller.py b/qcodes/instrument_drivers/AlazarTech/rec_samp_controller.py deleted file mode 100644 index 7e86e9ffc211..000000000000 --- a/qcodes/instrument_drivers/AlazarTech/rec_samp_controller.py +++ /dev/null @@ -1,233 +0,0 @@ -from .ATS import AcquisitionController -import numpy as np -from qcodes import Parameter -from scipy import signal - - -class RecSampParam(Parameter): - """ - Hardware controlled parameter class for Alazar acquisition. To be used with - HD_Samples_Controller (tested with ATS9360 board) for return of an array of - sample data from the Alazar, averaged over records and buffers. - - TODO(nataliejpg) fix setpoints/shapes horriblenesss - TODO(nataliejpg) make it actually work... - """ - - def __init__(self, name, instrument): - super().__init__(name) - self._instrument = instrument - self.acquisitionkwargs = {} - self.names = ('magnitude', 'phase') - self.units = ('', '') - self.setpoint_names = (('rec_num', 'samp_num'), - ('rec_num', 'samp_num')) - self.setpoints = ((1, 1), (1, 1)) - self.shapes = ((1, 1), (1, 1)) - - def update_acquisition_kwargs(self, **kwargs): - # needed to update config of the software parameter on sweep change - # freq setpoints tuple as needs to be hashable for look up - if 'samples_per_record' and 'records_per_buffer' in kwargs: - spts = kwargs['samples_per_record'] - rpts = kwargs['records_per_buffer'] - s = tuple(np.arange(spts)) - r = tuple(np.arange(rpts)) - self.setpoints = ((s, r), (s, r)) - self.shapes = ((spts, rpts), (spts, rpts)) - else: - raise ValueError( - 'records_per_buffer and samples_per_record must be specified') - # updates dict to be used in acquisition get call - self.acquisitionkwargs.update(**kwargs) - - def get(self): - mag, phase = self._instrument._get_alazar().acquire( - acquisition_controller=self._instrument, - **self.acquisitionkwargs) - return mag, phase - - -class HD_RecSamp_Controller(AcquisitionController): - """ - This is the Acquisition Controller class which works with the ATS9360, - averaging over buffers and records and demodulating with a software - reference signal, returning the samples. - args: - name: name for this acquisition_conroller as an instrument - alazar_name: the name of the alazar instrument such that this controller - can communicate with the Alazar - demod_freq: the frequency of the software wave to be created - samp_rate: the rate of sampling - filt: the filter to be used to filter out double freq component - chan_b: whether there is also a second channel of data to be processed - and returned - **kwargs: kwargs are forwarded to the Instrument base class - - TODO(nataliejpg) fix sample rate problem - TODO(nataliejpg) test filter options - TODO(nataliejpg) test mag phase logic - TODO(nataliejpg) finish implementation of channel b option - TODO(nataliejpg) make filter settings not hard coded - """ - - def __init__(self, name, alazar_name, demod_freq, samp_rate=500e6, - filt='win', chan_b=False, **kwargs): - filter_dict = {'win': 0, 'hamming': 1, 'ls': 2} - self.demodulation_frequency = demod_freq - self.sample_rate = samp_rate - self.filter = filter_dict[filt] - self.chan_b = chan_b - self.samples_per_record = 0 - self.records_per_buffer = 0 - self.buffers_per_acquisition = 0 - self.number_of_channels = 2 - self.cos_list = None - self.sin_list = None - self.buffer = None - # make a call to the parent class and by extension, - # create the parameter structure of this class - super().__init__(name, alazar_name, **kwargs) - - self.add_parameter(name='acquisition', - parameter_class=RecSampParam) - - def update_acquisitionkwargs(self, **kwargs): - """ - This method must be used to update the kwargs used for the acquisition - with the alazar_driver.acquire - :param kwargs: - :return: - """ - self.acquisition.update_acquisition_kwargs(**kwargs) - - def pre_start_capture(self): - """ - See AcquisitionController - :return: - """ - alazar = self._get_alazar() - self.samples_per_record = alazar.samples_per_record.get() - self.records_per_buffer = alazar.records_per_buffer.get() - self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() - self.buffer = np.zeros(self.samples_per_record * - self.records_per_buffer * - self.number_of_channels) - - integer_list = np.arange(self.samples_per_record) - angle_list = (2 * np.pi * self.demodulation_frequency / - self.sample_rate * integer_list) - - cos_list = np.cos(angle_list).reshape(self.samples_per_record, 1) - sin_list = np.sin(angle_list).reshape(self.samples_per_record, 1) - self.cos_mat = np.kron(np.ones((1, self.records_per_buffer)), cos_list) - self.sin_mat = np.kron(np.ones((1, self.records_per_buffer)), sin_list) - - def pre_acquire(self): - """ - See AcquisitionController - :return: - """ - # this could be used to start an Arbitrary Waveform Generator, etc... - # using this method ensures that the contents are executed AFTER the - # Alazar card starts listening for a trigger pulse - pass - - def handle_buffer(self, data): - """ - See AcquisitionController - :return: - """ - # average over buffers - self.buffer += data - - def post_acquire(self): - """ - See AcquisitionController - :return: - """ - - # for ATS9360 samples are arranged in the buffer as follows: - # S00A, S00B, S01A, S01B...S10A, S10B, S11A, S11B... - # where SXYZ is record X, sample Y, channel Z. - - # reshapes date to be (samples * records) - recordA = np.zeros((self.samples_per_record, self.records_per_buffer)) - for i in range(self.records_per_buffer): - i0 = i * self.number_of_channels * self.samples_per_record - i1 = i0 + self.number_of_channels * self.samples_per_record - recordA[:, i] = (self.buffer[i0:i1:self.number_of_channels] / - self.buffers_per_acquisition) - - # return averaged chan A data (records) - magA, phaseA = self.fit(recordA) - - # same for B - # if self.chan_b: - # recordB = np.zeros( - # (self.samples_per_record, self.records_per_buffer)) - # for i in self.records_per_buffer: - # recordB[i, :] = self.buffer[1:full_rec_length:step] / averaging - # magB, phaseB = self.fit(recordB) - - # return data (samples * records) - return magA, phaseA - - def fit(self, rec): - # center rec around 0 - rec = rec - np.mean(rec) - - # multiply with software wave - re_wave = np.multiply(rec, self.cos_mat) - im_wave = np.multiply(rec, self.sin_mat) - cutoff = self.demodulation_frequency - numtaps = 30 - axis = 0 - - # filter out double freq component to obtian constant term - if self.filter == 0: - RePart = self.filter_win(re_wave, numtaps, cutoff, axis=axis) - ImPart = self.filter_win(im_wave, numtaps, cutoff, axis=axis) - elif self.filter == 1: - RePart = self.filter_hamming(re_wave, numtaps, cutoff, axis=axis) - ImPart = self.filter_hamming(im_wave, numtaps, cutoff, axis=axis) - elif self.filter == 2: - RePart = self.filter_ls(re_wave, numtaps, cutoff, axis, axis=axis) - ImPart = self.filter_ls(im_wave, numtaps, cutoff, axis, axis=axis) - - # convert to magnitude and phase data - # data returned is (samples * records) - complex_num = RePart + ImPart * 1j - mag = 2 * abs(complex_num) - phase = np.angle(complex_num, deg=True) - - return mag, phase - - def filter_hamming(self, rec, numtaps, cutoff, axis=-1): - sample_rate = self.sample_rate - nyq_rate = sample_rate / 2. - fir_coef = signal.firwin(numtaps, - cutoff / nyq_rate, - window="hamming") - filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec, axis=axis) - return filtered_rec - - def filter_win(self, rec, numtaps, cutoff, axis=-1): - sample_rate = self.sample_rate - nyq_rate = sample_rate / 2. - fir_coef = signal.firwin(numtaps, - cutoff / nyq_rate) - filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec, axis=axis) - return filtered_rec - - def filter_ls(self, rec, numtaps, cutoff, axis=-1): - sample_rate = self.sample_rate - nyq_rate = sample_rate / 2. - bands = [0, cutoff / nyq_rate, cutoff / nyq_rate, 1] - desired = [1, 1, 0, 0] - fir_coef = signal.firls(numtaps, - bands, - desired, - nyq=nyq_rate) - filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec, axis=axis) - return filtered_rec diff --git a/qcodes/instrument_drivers/AlazarTech/samp_controller.py b/qcodes/instrument_drivers/AlazarTech/samp_controller.py deleted file mode 100644 index e37acc16d8b5..000000000000 --- a/qcodes/instrument_drivers/AlazarTech/samp_controller.py +++ /dev/null @@ -1,317 +0,0 @@ -import logging -from .ATS import AcquisitionController -import numpy as np -from qcodes import Parameter -from qcodes.utils.helpers import filter_win, filter_ls -from qcodes.instrument.parameter import ManualParameter -from qcodes.utils import validators - - -class SamplesParam(Parameter): - """ - Hardware controlled parameter class for Alazar acquisition. To be used with - HD_Samples_Controller (tested with ATS9360 board) for return of an array of - sample data from the Alazar, averaged over records and buffers. - - TODO(nataliejpg) refactor setpoints/shapes horriblenesss - TODO(nataliejpg) setpoint units - """ - - def __init__(self, name, instrument): - super().__init__(name) - self._instrument = instrument - self.acquisitionkwargs = {} - self.names = ('magnitude', 'phase') - self.units = ('', '') - self.setpoint_names = (('acq_time (s)',), ('acq_time (s)',)) - self.setpoints = ((1,), (1,)) - self.shapes = ((1,), (1,)) - -# def update_acquisition_kwargs(self, **kwargs): -# # updates dict to be used in acquisition get call -# self.acquisitionkwargs.update(**kwargs) - - def update_sweep(self, start, stop, npts): - n = tuple(np.linspace(start, stop, num=npts)) - self.setpoints = ((n,), (n,)) - self.shapes = ((npts,), (npts,)) - - def get(self): - mag, phase = self._instrument._get_alazar().acquire( - acquisition_controller=self._instrument, - **self.acquisitionkwargs) - return mag, phase - - -class HD_Samples_Controller(AcquisitionController): - """ - This is the Acquisition Controller class which works with the ATS9360, - averaging over buffers and records and demodulating with a software - reference signal, returning the samples. - args: - name: name for this acquisition_conroller as an instrument - alazar_name: the name of the alazar instrument such that this controller - can communicate with the Alazar - demod_freq: the frequency of the software wave to be created - samp_rate: the rate of sampling - filt: the filter to be used to filter out double freq component (win or ls) - numtaps: number of freq components used in the filter - chan_b: whether there is also a second channel of data to be processed - and returned - **kwargs: kwargs are forwarded to the Instrument base class - - TODO(nataliejpg) test filter options - TODO(nataliejpg) finish implementation of channel b option - TODO(nataliejpg) validators for int_time and int_delay - """ - - def __init__(self, name, alazar_name, samp_rate=5e8, - filt='win', numtaps=101, chan_b=False, **kwargs): - filter_dict = {'win': 0, 'ls': 1} - self.sample_rate = samp_rate - self.filter = filter_dict[filt] - self.numtaps = numtaps - self.chan_b = chan_b - self.samples_per_record = 0 - self.records_per_buffer = 0 - self.buffers_per_acquisition = 0 - self.number_of_channels = 2 - self.samples_delay = 0 - self.samples_time = 0 - self.cos_list = None - self.sin_list = None - self.buffer = None - self.board_info = None - # make a call to the parent class and by extension, - # create the parameter structure of this class - super().__init__(name, alazar_name, **kwargs) - - self.add_parameter(name='acquisition', - parameter_class=SamplesParam) - self.add_parameter(name='demodulation_frequency', - initial_value=20e6, - parameter_class=ManualParameter) - self.add_parameter(name='int_time', - initial_value=None, - parameter_class=ManualParameter) - self.add_parameter(name='int_delay', - initial_value=None, - parameter_class=ManualParameter) - - def update_acquisition_settings(self, **kwargs): - """ - Updates the kwargs to be used when - alazar_driver.acquire is called via a get call of the - acquisition SamplesParam. - - It is also used to set the limits on the selection of - samples returned (bounded by delay and integration time) - and update this information in the Samples Parameter. - - :param kwargs: - :return: - """ - alazar = self._get_alazar() - samples_per_record = kwargs['samples_per_record'] - self.sample_rate = alazar.get_sample_rate() - time_available = samples_per_record / self.sample_rate - - if self.int_delay() == 0: - samp_delay = self.numtaps - 1 - self.int_delay(samp_delay / self.sample_rate) - else: - self.check_delay(time_available) -# except ValueError as e: -# self.int_delay(0) - - time_available -= self.int_delay() - - if self.int_time() == 0: - self.int_time(time_available) - else: - self.check_time(time_available) - - start = self.int_delay() - stop = self.int_delay() + self.int_time() - npts = int(self.int_time() * self.sample_rate) - - self.acquisition.acquisitionkwargs.update(**kwargs) - self.acquisition.update_sweep(start, stop, npts) - - def pre_start_capture(self): - """ - Called before capture start to update Acquisition Controller with - alazar acquisition params and set up software wave for demodulation. - :return: - """ - alazar = self._get_alazar() - self.samples_per_record = alazar.samples_per_record.get() - self.records_per_buffer = alazar.records_per_buffer.get() - self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() - self.board_info = alazar.get_idn() - self.buffer = np.zeros(self.samples_per_record * - self.records_per_buffer * - self.number_of_channels) - if self.sample_rate != alazar.get_sample_rate(): - raise Exception('acq controller sample rate does not match instrument' - 'value, most likely need to call update_acquisition_settings' ) - - integer_list = np.arange(self.samples_per_record, dtype=np.uint16) - angle_list = (2 * np.pi * self.demodulation_frequency() / - self.sample_rate * integer_list) - - self.cos_list = np.cos(angle_list) - self.sin_list = np.sin(angle_list) - - def pre_acquire(self): - """ - See AcquisitionController - :return: - """ - pass - - def handle_buffer(self, data): - """ - Adds data from alazar to buffer (effectively averaging) - :return: - """ - self.buffer += data - - def post_acquire(self): - """ - Processes the data according to ATS9360 settings, splitting into - records and averaging over them, then applying demodulation fit - nb: currently only channel A - :return: samples_magnitude_array, samples_phase_array - """ - records_per_acquisition = (self.buffers_per_acquisition * - self.records_per_buffer) - # for ATS9360 samples are arranged in the buffer as follows: - # S00A, S00B, S01A, S01B...S10A, S10B, S11A, S11B... - # where SXYZ is record X, sample Y, channel Z. - - # break buffer up into records and averages over them - recA = np.zeros(self.samples_per_record) - for i in range(self.records_per_buffer): - i0 = (i * self.samples_per_record * self.number_of_channels) - i1 = (i0 + self.samples_per_record * self.number_of_channels) - recA += self.buffer[i0:i1:self.number_of_channels] - recordA = np.uint16(recA / records_per_acquisition) - - # do demodulation - magA, phaseA = self.fit(recordA) - - # same for chan b - if self.chan_b: - raise NotImplementedError('chan b code not complete') - # recordB = np.zeros(self.samples_per_record, dtype=np.uint16) - # for i in range(self.records_per_buffer): - # i0 = (i * self.samples_per_record * - # self.number_of_channels + 1) - # i1 = (i0 + self.samples_per_record * self.number_of_channels) - # recordB += np.uint16(self.buffer[i0:i1:self.number_of_channels] / - # records_per_acquisition) - # magB, phaseB = self.fit(recordB) - - return magA, phaseA - - def fit(self, rec): - print('got to fit, ave %s' % np.mean(rec)) - """ - Applies volts conversion, demodulation fit, low bandpass filter - and integration limits to samples array - :return: samples_magnitude_array, samples_phase_array - """ - - # convert rec to volts - bps = self.board_info['bits_per_sample'] - if bps == 12: - volt_rec = sample_to_volt_u12(rec, bps) - else: - logging.warning('sample to volt conversion does not exist for' - ' bps != 12, centered raw samples returned') - volt_rec = rec - np.mean(rec) - - print(self.cos_list) - print(self.demodulation_frequency()) - - # multiply with software wave - re_wave = np.multiply(volt_rec, self.cos_list) - im_wave = np.multiply(volt_rec, self.sin_list) - cutoff = self.demodulation_frequency() / 10 - - # filter out higher freq component - if self.filter == 0: - re_filtered = filter_win(re_wave, cutoff, - self.sample_rate, self.numtaps) - im_filtered = filter_win(im_wave, cutoff, - self.sample_rate, self.numtaps) - elif self.filter == 1: - re_filtered = filter_ls(re_wave, cutoff, - self.sample_rate, self.numtaps) - im_filtered = filter_ls(im_wave, cutoff, - self.sample_rate, self.numtaps) - - # apply integration limits - beginning = int(self.int_delay() / self.sample_rate) - end = beginning + int(self.int_time() / self.sample_rate) - - re_limited = re_filtered[beginning:end] - im_limited = im_filtered[beginning:end] - - # convert to magnitude and phase - complex_num = re_limited + im_limited * 1j - mag = abs(complex_num) - phase = np.angle(complex_num, deg=True) - - return mag, phase - - def check_delay(self, time_available): - samples_delay_min = (self.numtaps - 1) - int_delay_min = samples_delay_min / self.sample_rate - if self.int_delay() > time_available: - raise ValueError('int_delay {} is longer than total_time ' - '{}'.format(self.int_delay(), time_available)) - elif self.int_delay() < int_delay_min: - logging.warning( - 'delay is less than recommended for filter choice: ' - '(expect delay >= {}'.format(int_delay_min)) - - def check_time(self, time_available): - oscilations_measured = self.int_time() * self.demodulation_frequency() - oversampling = self.sample_rate / (2 * self.demodulation_frequency()) - if self.int_time() > time_available: - raise ValueError('int_time {} is longer than total_time - ' - 'delay = {}'.format(self.int_time(), time_available)) - elif oscilations_measured < 10: - logging.warning('{} oscilations measured, recommend at ' - 'least 10: decrease sampling rate, take ' - 'more samples or increase demodulation ' - 'freq'.format(oscilations_measured)) - elif oversampling < 1: - logging.warning('oversampling rate is {}, recommend > 1: ' - 'increase sampling rate or decrease ' - 'demodulation frequency'.format(oversampling)) - - -def sample_to_volt_u12(raw_samples, bps): - """ - Applies volts conversion for 12 bit sample data stored - in 2 bytes - :return: samples_magnitude_array, samples_phase_array - """ - - # right_shift 16-bit sample by 4 to get 12 bit sample - shifted_samples = np.right_shift(raw_samples, 4) - - # Alazar calibration - code_zero = (1 << (bps - 1)) - 0.5 - code_range = (1 << (bps - 1)) - 0.5 - - # TODO(nataliejpg) make this not hard coded - input_range_volts = 1 - # Convert to volts - volt_samples = np.float64(input_range_volts * - (shifted_samples - code_zero) / code_range) - - return volt_samples From d955535cfcaf884fd38745c0d4ace4b2329adc9a Mon Sep 17 00:00:00 2001 From: nataliejpg Date: Fri, 25 Nov 2016 19:26:40 +0100 Subject: [PATCH 060/180] fuuuuuck --- .../AlazarTech/samp_controller.py | 317 ++++++++++++++++++ 1 file changed, 317 insertions(+) create mode 100644 qcodes/instrument_drivers/AlazarTech/samp_controller.py diff --git a/qcodes/instrument_drivers/AlazarTech/samp_controller.py b/qcodes/instrument_drivers/AlazarTech/samp_controller.py new file mode 100644 index 000000000000..5919e04d48ac --- /dev/null +++ b/qcodes/instrument_drivers/AlazarTech/samp_controller.py @@ -0,0 +1,317 @@ +import logging +from .ATS import AcquisitionController +import numpy as np +from qcodes import Parameter +from qcodes.utils.helpers import filter_win, filter_ls +from qcodes.instrument.parameter import ManualParameter +from qcodes.utils import validators + + +class SamplesParam(Parameter): + """ + Hardware controlled parameter class for Alazar acquisition. To be used with + HD_Samples_Controller (tested with ATS9360 board) for return of an array of + sample data from the Alazar, averaged over records and buffers. + + TODO(nataliejpg) refactor setpoints/shapes horriblenesss + TODO(nataliejpg) setpoint units + """ + + def __init__(self, name, instrument): + super().__init__(name) + self._instrument = instrument + self.acquisitionkwargs = {} + self.names = ('magnitude', 'phase') + self.units = ('', '') + self.setpoint_names = (('acq_time (s)',), ('acq_time (s)',)) + self.setpoints = ((1,), (1,)) + self.shapes = ((1,), (1,)) + + def update_sweep(self, start, stop, npts): + n = tuple(np.linspace(start, stop, num=npts)) + self.setpoints = ((n,), (n,)) + self.shapes = ((npts,), (npts,)) + + def get(self): + mag, phase = self._instrument._get_alazar().acquire( + acquisition_controller=self._instrument, + **self.acquisitionkwargs) + print(mag) + return mag, phase + + +class HD_Samples_Controller(AcquisitionController): + """ + This is the Acquisition Controller class which works with the ATS9360, + averaging over buffers and records and demodulating with a software + reference signal, returning the samples. + args: + name: name for this acquisition_conroller as an instrument + alazar_name: the name of the alazar instrument such that this controller + can communicate with the Alazar + demod_freq: the frequency of the software wave to be created + samp_rate: the rate of sampling + filt: the filter to be used to filter out double freq component (win or ls) + numtaps: number of freq components used in the filter + chan_b: whether there is also a second channel of data to be processed + and returned + **kwargs: kwargs are forwarded to the Instrument base class + + TODO(nataliejpg) test filter options + TODO(nataliejpg) finish implementation of channel b option + TODO(nataliejpg) validators for int_time and int_delay + """ + + def __init__(self, name, alazar_name, samp_rate=5e8, + filt='win', numtaps=101, chan_b=False, **kwargs): + filter_dict = {'win': 0, 'ls': 1} + self.sample_rate = samp_rate + self.filter = filter_dict[filt] + self.numtaps = numtaps + self.chan_b = chan_b + self.samples_per_record = 0 + self.records_per_buffer = 0 + self.buffers_per_acquisition = 0 + self.number_of_channels = 2 + self.samples_delay = 0 + self.samples_time = 0 + self.cos_list = None + self.sin_list = None + self.buffer = None + self.board_info = None + # make a call to the parent class and by extension, + # create the parameter structure of this class + super().__init__(name, alazar_name, **kwargs) + + self.add_parameter(name='acquisition', + parameter_class=SamplesParam) + self.add_parameter(name='demodulation_frequency', + initial_value=20e6, + parameter_class=ManualParameter) + self.add_parameter(name='int_time', + initial_value=None, + parameter_class=ManualParameter) + self.add_parameter(name='int_delay', + initial_value=None, + parameter_class=ManualParameter) + + def update_acquisition_settings(self, **kwargs): + """ + Updates the kwargs to be used when + alazar_driver.acquire is called via a get call of the + acquisition SamplesParam. + + It is also used to set the limits on the selection of + samples returned (bounded by delay and integration time) + and update this information in the Samples Parameter. + + :param kwargs: + :return: + """ + alazar = self._get_alazar() + self.samples_per_record = kwargs['samples_per_record'] + self.sample_rate = alazar.get_sample_rate() + time_available = self.samples_per_record / self.sample_rate + + if self.int_delay() is None: + samp_delay = self.numtaps - 1 + self.int_delay(samp_delay / self.sample_rate) + else: + self.check_delay(time_available) + + time_available -= self.int_delay() + + if self.int_time() is None: + self.int_time(time_available) + else: + self.check_time(time_available) + + start = self.int_delay() + stop = self.int_delay() + self.int_time() + npts = int(self.int_time() * self.sample_rate) + + self.acquisition.acquisitionkwargs.update(**kwargs) + self.acquisition.update_sweep(start, stop, npts) + + def pre_start_capture(self): + """ + Called before capture start to update Acquisition Controller with + alazar acquisition params and set up software wave for demodulation. + :return: + """ + alazar = self._get_alazar() + self.samples_per_record = alazar.samples_per_record.get() + self.records_per_buffer = alazar.records_per_buffer.get() + self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() + self.board_info = alazar.get_idn() + self.buffer = np.zeros(self.samples_per_record * + self.records_per_buffer * + self.number_of_channels) + if self.sample_rate != alazar.get_sample_rate(): + raise Exception('acq controller sample rate does not match instrument' + 'value, most likely need to call update_acquisition_settings' ) + + integer_list = np.arange(self.samples_per_record, dtype=np.uint16) + angle_list = (2 * np.pi * self.demodulation_frequency() / + self.sample_rate * integer_list) + + self.cos_list = np.cos(angle_list) + self.sin_list = np.sin(angle_list) + + def pre_acquire(self): + """ + See AcquisitionController + :return: + """ + pass + + def handle_buffer(self, data): + """ + Adds data from alazar to buffer (effectively averaging) + :return: + """ + self.buffer += data + + def post_acquire(self): + """ + Processes the data according to ATS9360 settings, splitting into + records and averaging over them, then applying demodulation fit + nb: currently only channel A + :return: samples_magnitude_array, samples_phase_array + """ + records_per_acquisition = (self.buffers_per_acquisition * + self.records_per_buffer) + # for ATS9360 samples are arranged in the buffer as follows: + # S00A, S00B, S01A, S01B...S10A, S10B, S11A, S11B... + # where SXYZ is record X, sample Y, channel Z. + + # break buffer up into records and averages over them + recA = np.zeros(self.samples_per_record) + for i in range(self.records_per_buffer): + i0 = (i * self.samples_per_record * self.number_of_channels) + i1 = (i0 + self.samples_per_record * self.number_of_channels) + recA += self.buffer[i0:i1:self.number_of_channels] + recordA = np.uint16(recA / records_per_acquisition) + + # do demodulation + magA, phaseA = self.fit(recordA) + + # same for chan b + if self.chan_b: + raise NotImplementedError('chan b code not complete') + # recordB = np.zeros(self.samples_per_record, dtype=np.uint16) + # for i in range(self.records_per_buffer): + # i0 = (i * self.samples_per_record * + # self.number_of_channels + 1) + # i1 = (i0 + self.samples_per_record * self.number_of_channels) + # recordB += np.uint16(self.buffer[i0:i1:self.number_of_channels] / + # records_per_acquisition) + # magB, phaseB = self.fit(recordB) + + return magA, phaseA + + def fit(self, rec): + """ + Applies volts conversion, demodulation fit, low bandpass filter + and integration limits to samples array + :return: samples_magnitude_array, samples_phase_array + """ + + # convert rec to volts + bps = self.board_info['bits_per_sample'] + if bps == 12: + volt_rec = sample_to_volt_u12(rec, bps) + else: + logging.warning('sample to volt conversion does not exist for' + ' bps != 12, centered raw samples returned') + volt_rec = rec - np.mean(rec) + + # multiply with software wave + re_wave = np.multiply(volt_rec, self.cos_list) + im_wave = np.multiply(volt_rec, self.sin_list) + cutoff = self.demodulation_frequency() / 10 + + # filter out higher freq component + if self.filter == 0: + re_filtered = filter_win(re_wave, cutoff, + self.sample_rate, self.numtaps) + im_filtered = filter_win(im_wave, cutoff, + self.sample_rate, self.numtaps) + elif self.filter == 1: + re_filtered = filter_ls(re_wave, cutoff, + self.sample_rate, self.numtaps) + im_filtered = filter_ls(im_wave, cutoff, + self.sample_rate, self.numtaps) + + # print('re_filtered') + # print(re_filtered) + # # apply integration limits + beginning = int(self.int_delay() * self.sample_rate) + end = beginning + int(self.int_time() * self.sample_rate) + + # print(beginning) + # print(self.int_delay()) + # print() + + re_limited = re_filtered[beginning:end] + im_limited = im_filtered[beginning:end] + + # convert to magnitude and phase + complex_num = re_limited + im_limited * 1j + mag = abs(complex_num) + phase = np.angle(complex_num, deg=True) + + return mag, phase + + def check_delay(self, time_available): + samples_delay_min = (self.numtaps - 1) + int_delay_min = samples_delay_min / self.sample_rate + if self.int_delay() > time_available: + raise ValueError('int_delay {} is longer than total_time ' + '{}'.format(self.int_delay(), time_available)) + elif self.int_delay() < int_delay_min: + logging.warning( + 'delay is less than recommended for filter choice: ' + '(expect delay >= {}'.format(int_delay_min)) + + def check_time(self, time_available): + oscilations_measured = self.int_time() * self.demodulation_frequency() + oversampling = self.sample_rate / (2 * self.demodulation_frequency()) + if self.int_time() > time_available: + raise ValueError('int_time {} is longer than total_time - ' + 'delay = {}'.format(self.int_time(), time_available)) + elif oscilations_measured < 10: + logging.warning('{} oscilations measured, recommend at ' + 'least 10: decrease sampling rate, take ' + 'more samples or increase demodulation ' + 'freq'.format(oscilations_measured)) + elif oversampling < 1: + logging.warning('oversampling rate is {}, recommend > 1: ' + 'increase sampling rate or decrease ' + 'demodulation frequency'.format(oversampling)) + + def get_max_total_sample_time(self): + time_available = self.samples_per_record / self.sample_rate + return time_available + +def sample_to_volt_u12(raw_samples, bps): + """ + Applies volts conversion for 12 bit sample data stored + in 2 bytes + :return: samples_magnitude_array, samples_phase_array + """ + + # right_shift 16-bit sample by 4 to get 12 bit sample + shifted_samples = np.right_shift(raw_samples, 4) + + # Alazar calibration + code_zero = (1 << (bps - 1)) - 0.5 + code_range = (1 << (bps - 1)) - 0.5 + + # TODO(nataliejpg) make this not hard coded + input_range_volts = 1 + # Convert to volts + volt_samples = np.float64(input_range_volts * + (shifted_samples - code_zero) / code_range) + + return volt_samples From 44e0326e5dd5af9e1cb1ef4a408093783aa7d319 Mon Sep 17 00:00:00 2001 From: Documentation Bot Date: Sun, 27 Nov 2016 22:32:42 +0100 Subject: [PATCH 061/180] fix: Add missing __init__ --- qcodes/instrument_drivers/Harvard/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 qcodes/instrument_drivers/Harvard/__init__.py diff --git a/qcodes/instrument_drivers/Harvard/__init__.py b/qcodes/instrument_drivers/Harvard/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 From c7490e6b5560aa554e7d23acf7fd5ffcfba32565 Mon Sep 17 00:00:00 2001 From: Giulio Ungaretti Date: Sun, 27 Nov 2016 23:18:48 +0100 Subject: [PATCH 062/180] feat: Add makefile option to build locally --- docs/Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/Makefile b/docs/Makefile index 45982336eef6..bb0274ee7351 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -226,6 +226,10 @@ dummy: @echo @echo "Build finished. Dummy builder generates no files." +html-api: + sphinx-apidoc -o docs/auto qcodes -d 10 + cd docs && make html + gh-pages: git config --global user.email "bot@travics.com" git config --global user.name "Documentation Bot" From 2d7fbec194a6fdf1a3e96ba85f64258bc0e4dd4b Mon Sep 17 00:00:00 2001 From: Giulio Ungaretti Date: Sun, 27 Nov 2016 23:23:12 +0100 Subject: [PATCH 063/180] docs: Polish decadac --- qcodes/instrument_drivers/Harvard/Decadac.py | 23 +++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/qcodes/instrument_drivers/Harvard/Decadac.py b/qcodes/instrument_drivers/Harvard/Decadac.py index 4fc62a80d1e1..6f8f2a5cabbe 100644 --- a/qcodes/instrument_drivers/Harvard/Decadac.py +++ b/qcodes/instrument_drivers/Harvard/Decadac.py @@ -16,24 +16,15 @@ class Decadac(VisaInstrument): that self.visa_handle.ask(XXX) will return the answer to XXX and not some previous event. - The class comes with the following methods and attributes: - - Methods: - - set_ramping(state:bool, time:float): a shortcut to set - self.ramp_state and self.ramp_time - - get_ramping: Queries the value of self.ramp_state and - self.ramp_time. Returns a string. Attributes: ramp_state (bool): If True, ramp state is ON. Default False. - ramp_time (num): The ramp time in ms. Default 100 ms. + ramp_time (int): The ramp time in ms. Default 100 ms. voltranges (list): The voltranges for each channel. Can be read and - set (using a screwdriver) on the front of the physical instrument. + set (using a screwdriver) on the front of the physical instrument. """ def __init__(self, name, port, slot, timeout=2, baudrate=9600, @@ -160,6 +151,7 @@ def _setvoltage(self, voltage, channel): self.visa_handle.write('U 65535;') self.visa_handle.read() + def set_ramping(self, state, time=None): """ Function to set ramp_state and ramp_time. @@ -167,14 +159,19 @@ def set_ramping(self, state, time=None): Args: state (bool): True sets ramping ON. - time (int): the ramp time in ms + time (Optiona[int]): the ramp time in ms """ self.ramp_state = state if time is not None: self.ramp_time = time def get_ramping(self): - """Returns a string with ramp state information""" + """ + Queries the value of self.ramp_state and self.ramp_time. + + Returns: + str: ramp state information + """ switch = {True: 'ON', False: 'OFF'} mssg = 'Ramp state: ' + switch[self.ramp_state] From 8892e31b68889ace1c22dc0f26d9678eeeee9b34 Mon Sep 17 00:00:00 2001 From: Giulio Ungaretti Date: Mon, 5 Dec 2016 21:24:07 +0100 Subject: [PATCH 064/180] fix: Don't append if file does not exist. (#408) FileNotFoundError is not raised, if the directory exists (very much like Linux). So safer to check for the file we actually want to check for existence. Closes #407 --- qcodes/tests/test_format.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/qcodes/tests/test_format.py b/qcodes/tests/test_format.py index c6cf87fbfce0..d20b75ebd5f3 100644 --- a/qcodes/tests/test_format.py +++ b/qcodes/tests/test_format.py @@ -282,10 +282,18 @@ def test_format_options(self): self.assertEqual(f.read(), odd_format) def add_star(self, path): - try: + """ + Args: + path(str): path to gnu plot data file + + Write a start to file at path if exists. Else record that the file + does not exist, in the obscure counter self.stars_before_write, starts + are written only if a file exists, i.e. "after_write" + """ + if os.path.isfile(path): with open(path, 'a') as f: f.write('*') - except FileNotFoundError: + else: self.stars_before_write += 1 def test_incremental_write(self): From d66c6094ff3dc7a866e173a23491c1aa62dec33a Mon Sep 17 00:00:00 2001 From: "William H.P. Nielsen" Date: Wed, 7 Dec 2016 09:03:33 +0100 Subject: [PATCH 065/180] Update CONTRIBUTING.rst Add comment about elpy for Emacs. --- CONTRIBUTING.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 0b0e396e76b5..63aef9e7e31d 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -393,6 +393,7 @@ NOTE(giulioungaretti): is this enough ? - A lot of editors have plugins that will check this for you automatically as you type. Sublime Text for example has sublimelinter-pep8 and the even more powerful sublimelinter-flake8. + For Emacs, the elpy package is strongly recommended (https://github.com/jorgenschaefer/elpy). - BUT: do not change someone else's code to make it pep8-compliant unless that code is fully tested. - BUT: remove all trailing spaces. From 0b650337686ccd81de6116a8b78f55dbacd0915a Mon Sep 17 00:00:00 2001 From: peendebak Date: Wed, 7 Dec 2016 13:55:00 +0100 Subject: [PATCH 066/180] feature: Write metadata by default Formatter writes metadata by default, but data_set does not. --- qcodes/data/data_set.py | 21 ++++++++++++++------- qcodes/data/format.py | 5 +++-- qcodes/data/gnuplot_format.py | 7 ++++++- qcodes/data/hdf5_format.py | 11 +++++++---- qcodes/tests/data_mocks.py | 2 +- 5 files changed, 31 insertions(+), 15 deletions(-) diff --git a/qcodes/data/data_set.py b/qcodes/data/data_set.py index b1786438fcc8..31c5a0bb1a4e 100644 --- a/qcodes/data/data_set.py +++ b/qcodes/data/data_set.py @@ -610,16 +610,16 @@ def store(self, loop_indices, ids_values): time.time() > self.last_write + self.write_period): self.write() self.last_write = time.time() - else: # in PULL_FROM_SERVER mode; store() isn't legal + else: # in PULL_FROM_SERVER mode; store() isn't legal raise RuntimeError('This object is pulling from a DataServer, ' 'so data insertion is not allowed.') def default_parameter_name(self, paramname='amplitude'): """ Return name of default parameter for plotting - The default parameter is determined by looking into metdata['default_parameter_name']. - If this variable is not present, then the closest match to the argument - paramname is tried. + The default parameter is determined by looking into + metdata['default_parameter_name']. If this variable is not present, + then the closest match to the argument paramname is tried. Args: paramname (str): Name to match to parameter name @@ -660,7 +660,8 @@ def default_parameter_array(self, paramname='amplitude'): """ Return default parameter array Args: - paramname (str): Name to match to parameter name. Defaults to 'amplitude' + paramname (str): Name to match to parameter name. + Defaults to 'amplitude' Returns: array (DataArray): array corresponding to the default parameter @@ -684,11 +685,14 @@ def read_metadata(self): return self.formatter.read_metadata(self) - def write(self): + def write(self, write_metadata=False): """ Writes updates to the DataSet to storage. N.B. it is recommended to call data_set.finalize() when a DataSet is no longer expected to change to ensure files get closed + + Args: + write_metadata (bool): write the metadata to disk """ if self.mode != DataMode.LOCAL: raise RuntimeError('This object is connected to a DataServer, ' @@ -697,7 +701,10 @@ def write(self): if self.location is False: return - self.formatter.write(self, self.io, self.location) + self.formatter.write(self, + self.io, + self.location, + write_metadata=False) def write_copy(self, path=None, io_manager=None, location=None): """ diff --git a/qcodes/data/format.py b/qcodes/data/format.py index 7f0e0ffda8dc..9a58b30dca40 100644 --- a/qcodes/data/format.py +++ b/qcodes/data/format.py @@ -12,7 +12,7 @@ class Formatter: Each Formatter is expected to implement writing methods: - ``write``: to write the ``DataArray``s - - ``write_metadata``: to write the metadata JSON structure + - ``write_metadata``: to write the metadata structure Optionally, if this Formatter keeps the data file(s) open between write calls, it may implement: @@ -42,7 +42,7 @@ class Formatter: """ ArrayGroup = namedtuple('ArrayGroup', 'shape set_arrays data name') - def write(self, data_set, io_manager, location): + def write(self, data_set, io_manager, location, write_metadata=True): """ Write the DataSet to storage. @@ -55,6 +55,7 @@ def write(self, data_set, io_manager, location): data_set (DataSet): the data we are writing. io_manager (io_manager): base physical location to write to. location (str): the file location within the io_manager. + write_metadata (bool): if True, then the metadata is written to disk """ raise NotImplementedError diff --git a/qcodes/data/gnuplot_format.py b/qcodes/data/gnuplot_format.py index 47a08639d0a3..2aa43dd76650 100644 --- a/qcodes/data/gnuplot_format.py +++ b/qcodes/data/gnuplot_format.py @@ -62,6 +62,7 @@ class GNUPlotFormat(Formatter): use 2 blank lines sometimes, to denote a whole new dataset, which sort of corresponds to our situation.) """ + def __init__(self, extension='dat', terminator='\n', separator='\t', comment='# ', number_format='g', metadata_file=None): self.metadata_file = metadata_file or 'snapshot.json' @@ -234,7 +235,7 @@ def _get_labels(self, labelstr): parts = re.split('"\s+"', labelstr[1:-1]) return [l.replace('\\"', '"').replace('\\\\', '\\') for l in parts] - def write(self, data_set, io_manager, location, force_write=False): + def write(self, data_set, io_manager, location, force_write=False, write_metadata=True): """ Write updates in this DataSet to storage. @@ -298,6 +299,10 @@ def write(self, data_set, io_manager, location, force_write=False): for array in group.data + (group.set_arrays[-1],): array.mark_saved(save_range[1]) + if write_metadata: + self.write_metadata( + data_set, io_manager=io_manager, location=location) + def write_metadata(self, data_set, io_manager, location, read_first=True): """ Write all metadata in this DataSet to storage. diff --git a/qcodes/data/hdf5_format.py b/qcodes/data/hdf5_format.py index 77e5b4b32dbe..4d943491d76e 100644 --- a/qcodes/data/hdf5_format.py +++ b/qcodes/data/hdf5_format.py @@ -13,6 +13,7 @@ class HDF5Format(Formatter): Capable of storing (write) and recovering (read) qcodes datasets. """ + def close_file(self, data_set): """ Closes the hdf5 file open in the dataset. @@ -118,7 +119,7 @@ def _create_data_object(self, data_set, io_manager=None, return data_set._h5_base_group def write(self, data_set, io_manager=None, location=None, - force_write=False, flush=True): + force_write=False, flush=True, write_metadata=True): """ Writes a data_set to an hdf5 file. Input arguments: @@ -172,13 +173,15 @@ def write(self, data_set, io_manager=None, location=None, new_datasetshape = (new_dlen, datasetshape[1]) dset.resize(new_datasetshape) - new_data_shape = (new_dlen-old_dlen, datasetshape[1]) + new_data_shape = (new_dlen - old_dlen, datasetshape[1]) dset[old_dlen:new_dlen] = x[old_dlen:new_dlen].reshape( new_data_shape) # allow resizing extracted data, here so it gets written for # incremental writes aswell dset.attrs['shape'] = x.shape - self.write_metadata(data_set) + if write_metadata: + self.write_metadata( + data_set, io_manager=io_manager, location=location) # flush ensures buffers are written to disk # (useful for ensuring openable by other files) @@ -231,7 +234,7 @@ def _create_dataarray_dset(self, array, group): return dset - def write_metadata(self, data_set, io=None, location=None): + def write_metadata(self, data_set, io_manager=None, location=None): """ Writes metadata of dataset to file using write_dict_to_hdf5 method diff --git a/qcodes/tests/data_mocks.py b/qcodes/tests/data_mocks.py index 42e5418401ba..9a35ce2219cb 100644 --- a/qcodes/tests/data_mocks.py +++ b/qcodes/tests/data_mocks.py @@ -33,7 +33,7 @@ class MockFormatter: def read(self, data_set): data_set.has_read_data = True - def write(self, data_set, io_manager, location): + def write(self, data_set, io_manager, location, write_metadata=False): data_set.has_written_data = True def read_metadata(self, data_set): From 8cae1ac1a5cf073a98ee61a34b91d5737891fd03 Mon Sep 17 00:00:00 2001 From: Giulio Ungaretti Date: Tue, 13 Dec 2016 15:19:30 +0100 Subject: [PATCH 067/180] chore: Update requirements and simlify readme (#417) * fix: Update requirements. Remove old and pretty much useless version of widgets because not needed, only multiprocessing uses it and it's really b0rken. Remove basic * develop duality. Basic install and or Windows install (due to h5py) goes with conda. * docs: Slimify readme * fix: Update travis requirement Exclude plots from being tested on travis. --- .travis.yml | 10 ++++++++-- README.rst | 36 +--------------------------------- basic_requirements.txt | 14 ------------- develop_requirements.txt | 40 -------------------------------------- qcodes/tests/test_plots.py | 27 ++++++++++++++++++++----- requirements.txt | 8 ++++++++ setup.py | 1 - 7 files changed, 39 insertions(+), 97 deletions(-) delete mode 100644 basic_requirements.txt delete mode 100644 develop_requirements.txt create mode 100644 requirements.txt diff --git a/.travis.yml b/.travis.yml index a59bd4b3549a..bd0a5d494591 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,11 +10,17 @@ python: branches: only: - master + +# singal that we are on travis +# to disable things that expect an +# X Display +# +env: + - TRAVISCI=true # command to install dependencies install: - pip install --upgrade pip - - pip install ipython - - pip install -r develop_requirements.txt + - pip install -r requirements.txt - python setup.py develop # command to run tests script: diff --git a/README.rst b/README.rst index 6a6b99ad5b26..423dfab85e8e 100644 --- a/README.rst +++ b/README.rst @@ -70,7 +70,7 @@ $QCODES_INSTALL_DIR is the folder where you want to have the source code. cd $QCODES_INSTALL_DIR pyenv install 3.5.2 pyenv virtualenv 3.5.2 qcodes-dev - pip install -r develop_requirements.txt + pip install -r requirements.txt pip install -e . python qcodes/test.py -f @@ -78,40 +78,6 @@ If the tests pass you are ready to hack! This is the reference setup one needs to have to contribute, otherwise too many non-reproducible environments will show up. -If all of this sounds too complicated, use anaconda! - -Anaconda --------- - -One can also use anaconda: - -- First clone the repo - - `` git clone https://github.com/QCoDeS/Qcodes.git $QCODES_INSTALL_DIR `` - -- Open the 'navigator' app that was installed with anaconda. -- On the left side click on "Environments". -- Then on the "import" icon, on the bottom. -- Pick a name, and click on the folder icon next to file to import - from. -- Make sure you select "Pip requirement files" from the "Files of type" - dialog then navigate to the qcodes folder (QCODES_INSTALL_DIR) and select - ``basic_requirements.txt``. -- Finally click import, and wait until done. -- The enviroment is now created, click on the green arrow to open a - terminal inside it. -- Navigate again with the terminal (or drag and drop the the folder on - OsX) -- Most likely you will want to plot stuff, so type: - -``conda install matplotlib`` - -and after if you want qtplot - -``conda install pyqtgraph`` - -- Then type ``pip install -e .`` - Updating QCoDeS =============== diff --git a/basic_requirements.txt b/basic_requirements.txt deleted file mode 100644 index f5702ca9452f..000000000000 --- a/basic_requirements.txt +++ /dev/null @@ -1,14 +0,0 @@ -ipykernel==4.2.2 -ipython==4.1.0 -ipython-genutils==0.1.0 -ipywidgets==4.1.1 -jupyter==1.0.0 -jupyter-client==4.1.1 -jupyter-console==4.1.0 -jupyter-core==4.0.6 -notebook==4.1.0 -numpy==1.10.4 -python-dateutil==2.4.2 -PyVISA==1.8 -coverage==4.1 -h5py==2.6.0 diff --git a/develop_requirements.txt b/develop_requirements.txt deleted file mode 100644 index 91a2f52a7935..000000000000 --- a/develop_requirements.txt +++ /dev/null @@ -1,40 +0,0 @@ -coverage==4.1 -decorator==4.0.9 -docutils==0.12 -gnureadline==6.3.3 -greenlet==0.4.9 -h5py==2.6.0 -imagesize==0.7.1 -ipykernel==4.3.1 -ipython==4.2.0 -ipython-genutils==0.1.0 -ipywidgets==5.1.5 -Jinja2==2.8 -jupyter-client==4.2.2 -jupyter-core==4.1.0 -MarkupSafe==0.23 -msgpack-python==0.4.7 -nbconvert==4.2.0 -nbformat==4.0.1 -neovim==0.1.8 -nose==1.3.7 -notebook==4.2.0 -numpy==1.11.0 -pexpect==4.1.0 -pickleshare==0.7.2 -ptyprocess==0.5.1 -Pygments==2.1.3 -pytz==2016.4 -PyVISA==1.8 -pyzmq==15.2.0 -simplegeneric==0.8.1 -six==1.10.0 -snowballstemmer==1.2.1 -Sphinx==1.4.2 -sphinx-rtd-theme==0.1.9 -terminado==0.6 -tornado==4.3 -traitlets==4.2.1 -widgetsnbextension==1.2.3 -jsonschema==2.5.1 -sphinxcontrib-jsonschema==0.9.0 diff --git a/qcodes/tests/test_plots.py b/qcodes/tests/test_plots.py index 1099fb04c325..c67aa3221214 100644 --- a/qcodes/tests/test_plots.py +++ b/qcodes/tests/test_plots.py @@ -1,15 +1,28 @@ +""" +Tests for plotting system. +Legacy in many ways: + - assume X server running + - just test "window creation" +""" from unittest import TestCase, skipIf +import os try: from qcodes.plots.pyqtgraph import QtPlot - noQtPlot = False + if os.environ.get("TRAVISCI"): + noQtPlot = True + else: + noQtPlot = False except Exception: noQtPlot = True try: from qcodes.plots.qcmatplotlib import MatPlot import matplotlib.pyplot as plt - noMatPlot = False + if os.environ.get("TRAVISCI"): + noMatPlot = True + else: + noMatPlot = False except Exception: noMatPlot = True @@ -24,9 +37,11 @@ def tearDown(self): pass def test_creation(self): - ''' Simple test function which created a QtPlot window ''' + """ + Simple test function which created a QtPlot window + """ plotQ = QtPlot(remote=False, show_window=False, interval=0) - _ = plotQ.add_subplot() + plotQ.add_subplot() @skipIf(noMatPlot, '***matplotlib plotting cannot be tested***') @@ -39,6 +54,8 @@ def tearDown(self): pass def test_creation(self): - ''' Simple test function which created a QtPlot window ''' + """ + Simple test function which created a QtPlot window + """ plotM = MatPlot(interval=0) plt.close(plotM.fig) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 000000000000..ace996ad9542 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,8 @@ +jupyter==1.0.0 +numpy==1.11.2 +matplotlib==1.5.3 +pyqtgraph==0.10.0 +PyVISA==1.8 +PyQt5==5.7 +QtPy==1.1.2 +h5py==2.6.0 diff --git a/setup.py b/setup.py index 0e18ae98aa4d..db4c5dda8a99 100644 --- a/setup.py +++ b/setup.py @@ -59,7 +59,6 @@ def readme(): 'pyvisa>=1.8', 'ipython>=4.1.0', 'jupyter>=1.0.0', - 'ipywidgets>=4.1', 'h5py>=2.6' ], From e2de376b03879cb4246f771a13c80dbd5708ce56 Mon Sep 17 00:00:00 2001 From: Adriaan Date: Fri, 16 Dec 2016 14:00:34 +0100 Subject: [PATCH 068/180] driver: enhancement to support setting external reference (#412) * R&S driver enhancement to support setting reference * Double quote and removed blank line --- .../rohde_schwarz/SGS100A.py | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/qcodes/instrument_drivers/rohde_schwarz/SGS100A.py b/qcodes/instrument_drivers/rohde_schwarz/SGS100A.py index f6f758675f74..48eda76f1cac 100644 --- a/qcodes/instrument_drivers/rohde_schwarz/SGS100A.py +++ b/qcodes/instrument_drivers/rohde_schwarz/SGS100A.py @@ -2,7 +2,7 @@ class RohdeSchwarz_SGS100A(VisaInstrument): - ''' + """ This is the qcodes driver for the Rohde & Schwarz SGS100A signal generator Status: beta-version. @@ -19,7 +19,8 @@ class RohdeSchwarz_SGS100A(VisaInstrument): - RS_SMB100A This driver does not contain all commands available for the RS_SGS100A but only the ones most commonly used. - ''' + """ + def __init__(self, name, address, **kwargs): super().__init__(name, address, **kwargs) @@ -58,6 +59,24 @@ def __init__(self, name, address, **kwargs): get_cmd='SOUR:PULM:SOUR?', set_cmd=self.set_pulsemod_source, vals=vals.Strings()) + self.add_parameter('ref_osc_source', + label='Reference oscillator source', + get_cmd='SOUR:ROSC:SOUR?', + set_cmd='SOUR:ROSC:SOUR {}', + vals=vals.Enum('INT', 'EXT')) + # Frequency mw_source outputs when used as a reference + self.add_parameter('ref_osc_output_freq', + label='Reference oscillator output frequency', + get_cmd='SOUR:ROSC:OUTP:FREQ?', + set_cmd='SOUR:ROSC:OUTP:FREQ {}', + vals=vals.Enum('10MHz', '100MHz', '1000MHz')) + # Frequency of the external reference mw_source uses + self.add_parameter('ref_osc_external_freq', + label='Reference oscillator external frequency', + get_cmd='SOUR:ROSC:EXT:FREQ?', + set_cmd='SOUR:ROSC:EXT:FREQ {}', + vals=vals.Enum('10MHz', '100MHz', '1000MHz')) + self.add_function('reset', call_cmd='*RST') self.add_function('run_self_tests', call_cmd='*TST?') From 1a4508b6873039b86637e61b55d7c16f30365cfc Mon Sep 17 00:00:00 2001 From: eendebakpt Date: Mon, 19 Dec 2016 11:05:51 +0100 Subject: [PATCH 069/180] driver: Add Microwave source driver SMR40 (#419) * adding microwave source driver SMR40 * autopep8 * format docstring * use named logger * update docstrings --- .../instrument_drivers/rohde_schwarz/SMR40.py | 371 ++++++++++++++++++ 1 file changed, 371 insertions(+) create mode 100644 qcodes/instrument_drivers/rohde_schwarz/SMR40.py diff --git a/qcodes/instrument_drivers/rohde_schwarz/SMR40.py b/qcodes/instrument_drivers/rohde_schwarz/SMR40.py new file mode 100644 index 000000000000..13189c99bfb3 --- /dev/null +++ b/qcodes/instrument_drivers/rohde_schwarz/SMR40.py @@ -0,0 +1,371 @@ +# Driver for microwave source RS_SMR40 +# +# Written by Takafumi Fujita (t.fujita@tudelft.nl) +# This program is based on RS_SMR40.py in QTlab +# + +import logging + +from qcodes import VisaInstrument +from qcodes import validators as vals + +log = logging.getLogger(__name__) + +class RohdeSchwarz_SMR40(VisaInstrument): + """This is the qcodes driver for the Rohde & Schwarz SMR40 signal generator + Status: beta-version. TODO: + + - Add all parameters that are in the manual + - Add test suite + - See if there can be a common driver for RS mw sources from which + different models inherit + This driver does not contain all commands available for the SMR40 but + only the ones most commonly used. + + """ + + def __init__(self, name, address, verbose=1, reset=False, **kwargs): + self.verbose = verbose + log.debug(__name__ + ' : Initializing instrument') + super().__init__(name, address, **kwargs) + + # TODO(TF): check what parser parameters can do + # check what 'tags=['sweep']' and 'types' do in qtlab + # fix format types + self.add_parameter('frequency', + label='Frequency', + get_cmd=self.do_get_frequency, + set_cmd=self.do_set_frequency, + vals=vals.Numbers(10e6, 40e9), + units='Hz') + self.add_parameter('power', + label='Power', + get_cmd=self.do_get_power, + set_cmd=self.do_set_power, + vals=vals.Numbers(-30, 25), + units='dBm') + self.add_parameter('status', + get_cmd=self.do_get_status, + set_cmd=self.do_set_status, + vals=vals.Strings()) + + # TODO(TF): check how to fix the get functions + self.add_parameter('status_of_modulation', + get_cmd=self.do_get_status_of_modulation, + set_cmd=self.do_set_status_of_modulation, + vals=vals.Strings()) + self.add_parameter('status_of_ALC', + get_cmd=self.do_get_status_of_ALC, + set_cmd=self.do_set_status_of_ALC, + vals=vals.Strings()) + self.add_parameter('pulse_delay', + get_cmd=self.do_get_pulse_delay, + set_cmd=self.do_set_pulse_delay) + + # TODO(TF): check the way of defining this type of functions, where logging is added + # self.add_function('reset') + # self.add_function('get_all') + + if reset: + self.reset() + else: + self.get_all() + + self.connect_message() + + # Functions + def reset(self): + """Resets the instrument to default values. + + Args: + None + + Output: + None + + """ + log.info(__name__ + ' : Resetting instrument') + self.write('*RST') + # TODO: make it printable + self.get_all() + + def get_all(self): + """Reads all implemented parameters from the instrument, and updates + the wrapper. + + Args: + None + + Output: + None + + """ + log.info(__name__ + ' : reading all settings from instrument') + # TODO: make it printable + self.frequency.get() + self.power.get() + self.status.get() + + # Communication functions + def do_get_frequency(self): + """Get frequency from device. + + Args: + None + + Output: + frequency (float) : frequency in Hz + + """ + log.debug(__name__ + ' : reading frequency from instrument') + return float(self.ask('SOUR:FREQ?')) + + def do_set_frequency(self, frequency): + """Set frequency of device. + + Args: + frequency (float) : frequency in Hz + + Output: + None + + """ + log.debug(__name__ + ' : setting frequency to %s GHz' % frequency) + self.write('SOUR:FREQ %e' % frequency) + + def do_get_power(self): + """Get output power from device. + + Args: + None + + Output: + power (float) : output power in dBm + + """ + log.debug(__name__ + ' : reading power from instrument') + return float(self.ask('SOUR:POW?')) + + def do_set_power(self, power): + """Set output power of device. + + Args: + power (float) : output power in dBm + + Output: + None + + """ + log.debug(__name__ + ' : setting power to %s dBm' % power) + self.write('SOUR:POW %e' % power) + + def do_get_status(self): + """Get status from instrument. + + Args: + None + + Output: + status (string) : 'on or 'off' + + """ + log.debug(__name__ + ' : reading status from instrument') + stat = self.ask(':OUTP:STAT?') + + # TODO: fix + if stat == '1\n': + return 'ON' + elif stat == '0\n': + return 'OFF' + else: + raise ValueError('Output status not specified : %s' % stat) + + def do_set_status(self, status): + """Set status of instrument. + + Args: + status (string) : 'on or 'off' + + Output: + None + + """ + log.debug(__name__ + ' : setting status to "%s"' % status) + if status.upper() in ('ON', 'OFF'): + status = status.upper() + else: + raise ValueError('set_status(): can only set on or off') + self.write(':OUTP:STAT %s' % status) + + def do_get_status_of_modulation(self): + """Get status from instrument. + + Args: + None + + Output: + status (string) : 'on' or 'off' + + """ + log.debug(__name__ + ' : reading status from instrument') + stat = self.ask(':SOUR:PULM:STAT?') + + # TODO: fix + # if stat == '1': + # return 'ON' + # elif stat == '0': + # return 'OFF' + if stat == '1\n': + return 'ON' + elif stat == '0\n': + return 'OFF' + else: + raise ValueError('Output status not specified : %s' % stat) + + def do_set_status_of_modulation(self, status): + """Set status of modulation. + + Args: + status (string) : 'on' or 'off' + + Output: + None + + """ + log.debug(__name__ + ' : setting status to "%s"' % status) + if status.upper() in ('ON', 'OFF'): + status = status.upper() + else: + raise ValueError('set_status(): can only set on or off') + self.write(':SOUR:PULM:STAT %s' % status) + + def do_get_status_of_ALC(self): + """Get status from instrument. + + Args: + None + + Output: + status (string) : 'on or 'off' + + """ + log.debug(__name__ + ' : reading ALC status from instrument') + stat = self.ask(':SOUR:POW:ALC?') + + # TODO: fix + # if stat == '1': + # return 'ON' + # elif stat == '0': + # return 'OFF' + if stat == '1\n': + return 'ON' + elif stat == '0\n': + return 'OFF' + else: + raise ValueError('Output status not specified : %s' % stat) + + def do_set_status_of_ALC(self, status): + """Set status of instrument. + + Args: + status (string) : 'on or 'off' + + Output: + None + + """ + log.debug(__name__ + ' : setting ALC status to "%s"' % status) + if status.upper() in ('ON', 'OFF'): + status = status.upper() + else: + raise ValueError('set_status(): can only set on or off') + self.write(':SOUR:POW:ALC %s' % status) + + def do_get_pulse_delay(self): + """Get output power from device. + + Args: + None + + Output: + power (float) : output power in dBm + + """ + log.debug(__name__ + ' : reading pulse delay from instrument') + return float(self.ask('SOUR:PULS:DEL?')) + + def do_set_pulse_delay(self, delay): + """Set output power of device. + + Args: + power (float) : output power in dBm + + Output: + None + + """ + log.debug( + __name__ + ' : setting pulse delay to %s seconds' % str(delay)) + self.write('SOUR:PULS:DEL 1us') + + # Shortcuts + def off(self): + """Set status to 'off'. + + Args: + None + + Output: + None + + """ + self.status.set('off') + + def on(self): + """Set status to 'on'. + + Args: + None + + Output: + None + + """ + self.status.set('on') + + def off_modulation(self): + """Set status of modulation to 'off'. + + Args: + None + + Output: + None + + """ + self.set_status_of_modulation('off') + + def on_modulation(self): + """Set status of modulation to 'on'. + + Args: + None + + Output: + None + + """ + self.set_status_of_modulation('on') + + def set_ext_trig(self): + """Set to the external trigger mode. + + Args: + None + + Output: + None + + """ + log.debug(__name__ + ' : setting to the external trigger mode') + self.write('TRIG:PULS:SOUR EXT_TRIG') From fb2c40ff9bb00a576637b896d523d3260d10e18c Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Mon, 19 Dec 2016 15:10:14 +0100 Subject: [PATCH 070/180] Doc: RST fixes (#420) * docs: fix rst syntax in roadmap * docs: fix rst syntax in intro * docs: fix rst syntax in tutuorial * docs: fix rst syntax in start/index * docs: typo in mock comment * docs: fix rst syntax in dataset.py * docs: fix rst syntax in format.py * docs: mock instument correct rst * docs: parameter correct rst --- docs/roadmap.rst | 2 ++ docs/start/index.rst | 2 +- docs/user/intro.rst | 9 +++++++++ docs/user/tutorial.rst | 10 +++++----- qcodes/data/data_set.py | 36 ++++++++++++++++++++-------------- qcodes/data/format.py | 25 +++++++++++++---------- qcodes/instrument/mock.py | 18 +++++++++-------- qcodes/instrument/parameter.py | 4 +++- 8 files changed, 66 insertions(+), 40 deletions(-) diff --git a/docs/roadmap.rst b/docs/roadmap.rst index 916ee3a84977..535ef8de1e36 100644 --- a/docs/roadmap.rst +++ b/docs/roadmap.rst @@ -38,11 +38,13 @@ Broader adoption within stationQ - raw data (as raw as feasible) - analyzed data - metadata, including both: + - experiment data: all electronic settings and any available manual settings, timestamp - information on the code state: git commit id and/or version of this package, traceback at the point of execution, and potentially information about the other scripts involved in the sweep? + - automatic logging of monitor parameters (eg fridge and magnet information) as a function of time - Instrument drivers: all drivers group members have used in their diff --git a/docs/start/index.rst b/docs/start/index.rst index 6ad8f9743474..b58a29e2fe88 100644 --- a/docs/start/index.rst +++ b/docs/start/index.rst @@ -17,7 +17,7 @@ Make sure to download the latest version with python 3.5. Once you download, install anaconda according to the instructions on screen. -If you use *nix, you really should use the source. +If you use \*nix, you really should use the source. The next section will guide you through the installation of qcodes on windows, although most of the things also work for osx and Linux. diff --git a/docs/user/intro.rst b/docs/user/intro.rst index 42e1285a1c62..5a1bab383198 100644 --- a/docs/user/intro.rst +++ b/docs/user/intro.rst @@ -43,17 +43,20 @@ Instruments come in several flavors: An instrument can exist as local instrument or remote instrument. A local instrument is instantiated in the main process, and you interact with it directly. This is convenient for testing and debugging, but a local instrument cannot be used with a measurement loop in a separate process (ie a background loop). For that purpose you need a remote instrument. A remote instrument starts (or connects to) a server process, instantiates the instrument in that process, and returns a proxy object that mimicks the API of the instrument. This proxy holds no state or hardware connection, so it can be freely copied to other processes, in particular background loops and composite-instrument servers. .. responsibilities + Instruments are responsible for: - Holding connections to hardware, be it VISA, some other communication protocol, or a specific DLL or lower-level driver. - Creating a parameter_, ref:`function`, or method for each piece of functionality we support. These objects may be used independent of the instrument, but they make use of the instrument's hardware connection in order to do their jobs. - Describing their complete current state ("snapshot") when asked, as a JSON-compatible dictionary. .. state + Instruments hold state of: - The communication address, and in many cases the open communication channel. - A list of references to parameters added to the instrument. .. failures + Instruments can fail: - When a VisaInstrument has been instantiated before, particularly with TCPIP, sometimes it will complain "VI_ERROR_RSRC_NFOUND: Insufficient location information or the requested device or resource is not present in the system" and not allow you to open the instrument until either the hardware has been power cycled or the network cable disconnected and reconnected. Are we using visa/pyvisa in a brittle way? - If you try to use a background loop with a local instrument, because that would require copying the local instrument and there may only be one local copy of the instrument (if you make a remote instrument, the server instance is the one local copy). @@ -77,6 +80,7 @@ Responsibilities ~~~~~~~~~~~~~~~~ .. responsibilities + Parameters are responsible for: - (if part of an Instrument) generating the commands to pass to the Instrument and interpreting its response - (if not part of an Instrument) providing get and/or set methods @@ -88,10 +92,12 @@ Parameters are responsible for: - and more if multi-valued or array-valued .. state + Parameters hold onto their latest set or measured value, as well as the timestamp of the latest update. Thus, snapshots need not always query the hardware for this information, but can update it intelligently when it has gotten stale. .. failures + A Parameter that is part of an Instrument, even though it can be used as an independent object without directly referencing the Instrument, is subject to the same local/remote limitations as the Instrument. @@ -168,17 +174,20 @@ The key loop running conditions are: - where and how to save the data to disk .. responsibilities + The Loop is responsible for: - creating the dataset_ that will be needed to store its data - generating all the metadata for the DataSet. Metadata is intended to describe the system and software configuration to give it context, help reproduce and troubleshoot the experiment, and to aid searching and datamining later. The Loop generates its own metadata, regarding when and how it was run and the Parameters and other actions involved, as well as asking all the Instruments, via a :ref:`station` if possible, for their own metadata and including it. - sequencing actions: the Loop should have the highest priority and the least overhead of extra responsibilities so that setpoints and actions occur with as fast and reliable timing as possible. .. state + Before the Loop is run, it holds the setpoint and action definitions you are building up. You can actually keep a loop at any level of definition and reuse it later. Loop methods chain by creating entirely new objects, so that you can hold onto the Loop at any stage of definition and reuse just what has been defined up to that point. After the Loop is run, it returns a dataset_ and the executed loop itself, along with the process it starts if it's a background Loop, only hold state (such as the current indices within the potentially nested Loops) while it is running. .. failures + Loops can fail: - If you try to use a (parameter of a) local instrument in a background loop diff --git a/docs/user/tutorial.rst b/docs/user/tutorial.rst index 23dff2a13291..33798d39ce77 100644 --- a/docs/user/tutorial.rst +++ b/docs/user/tutorial.rst @@ -13,10 +13,10 @@ Writing a Driver Write a simple driver example with commented code - - add parameter - - add validator - - add custom stuff - - add doccstrings f.ex +- add parameter +- add validator +- add custom stuff +- add doccstrings f.ex .. todo:: missing @@ -36,7 +36,7 @@ Explain the mock mock Combined Parameters Sweep ------------------------- +------------------------- If you want to sweep multiple parameters at once qcodes offers the combine function. You can combine any number of any kind paramter. diff --git a/qcodes/data/data_set.py b/qcodes/data/data_set.py index 31c5a0bb1a4e..9db025860dd3 100644 --- a/qcodes/data/data_set.py +++ b/qcodes/data/data_set.py @@ -36,10 +36,12 @@ def new_data(location=None, loc_record=None, name=None, overwrite=False, Args: location (str or callable or False, optional): If you provide a string, it must be an unused location in the io manager. Can also be: + - a callable ``location provider`` with one required parameter (the io manager), and one optional (``record`` dict), which returns a location string when called - ``False`` - denotes an only-in-memory temporary DataSet. + Note that the full path to or physical location of the data is a combination of io + location. the default ``DiskIO`` sets the base directory, which this location is a relative path inside. @@ -66,13 +68,15 @@ def new_data(location=None, loc_record=None, name=None, overwrite=False, ``get_data_manager()``. mode (DataMode, optional): connection type to the ``DataServer``. - ``DataMode.LOCAL``: this DataSet doesn't communicate across - processes. - ``DataMode.PUSH_TO_SERVER``: no local copy of data, just pushes - each measurement to a ``DataServer``. - ``DataMode.PULL_FROM_SERVER``: pulls changes from the - ``DataServer`` on calling ``self.sync()``. Reverts to local if - and when it stops being the live measurement. + + - ``DataMode.LOCAL``: this DataSet doesn't communicate across + processes. + - ``DataMode.PUSH_TO_SERVER``: no local copy of data, just pushes + each measurement to a ``DataServer``. + - ``DataMode.PULL_FROM_SERVER``: pulls changes from the + ``DataServer`` on calling ``self.sync()``. Reverts to local if + and when it stops being the live measurement. + Default ``DataMode.LOCAL``. arrays (Optional[List[qcodes.DataArray]): arrays to add to the DataSet. @@ -215,14 +219,16 @@ class DataSet(DelegateAttributes): ``get_data_manager()``. mode (DataMode, optional): connection type to the ``DataServer``. - ``DataMode.LOCAL``: this DataSet doesn't communicate across - processes. - ``DataMode.PUSH_TO_SERVER``: no local copy of data, just pushes - each measurement to a ``DataServer``. - ``DataMode.PULL_FROM_SERVER``: pulls changes from the - ``DataServer`` on calling ``self.sync()``. Reverts to local if - and when it stops being the live measurement. - Default ``DataMode.LOCAL``. + + - ``DataMode.LOCAL``: this DataSet doesn't communicate across + processes. + - ``DataMode.PUSH_TO_SERVER``: no local copy of data, just pushes + each measurement to a ``DataServer``. + - ``DataMode.PULL_FROM_SERVER``: pulls changes from the + ``DataServer`` on calling ``self.sync()``. Reverts to local if + and when it stops being the live measurement. + + Default to ``DataMode.LOCAL``. arrays (Optional[List[qcodes.DataArray]): arrays to add to the DataSet. Can be added later with ``self.add_array(array)``. diff --git a/qcodes/data/format.py b/qcodes/data/format.py index 9a58b30dca40..0caf9c80e453 100644 --- a/qcodes/data/format.py +++ b/qcodes/data/format.py @@ -11,16 +11,19 @@ class Formatter: Formatters translate between DataSets and data files. Each Formatter is expected to implement writing methods: - - ``write``: to write the ``DataArray``s + + - ``write``: to write the ``DataArray``\s - ``write_metadata``: to write the metadata structure Optionally, if this Formatter keeps the data file(s) open between write calls, it may implement: + - ``close_file``: to perform any final cleanup and release the file and any other resources. and reading methods: - - ``read`` or ``read_one_file`` to reconstruct the ``DataArray``s, either + + - ``read`` or ``read_one_file`` to reconstruct the ``DataArray``\s, either all at once (``read``) or one file at a time, supplied by the base class ``read`` method that loops over all data files at the correct location. @@ -31,14 +34,16 @@ class Formatter: All of these methods accept a ``data_set`` argument, which should be a ``DataSet`` object. Even if you are loading a new data set from disk, this object should already have attributes: - io: an IO manager (see qcodes.data.io) - location: a string, like a file path, that identifies the DataSet and - tells the IO manager where to store it - arrays: a dict of ``{array_id:DataArray}`` to read into. - - read will create entries that don't yet exist. - - write will write ALL DataArrays in the DataSet, using - last_saved_index and modified_range, as well as whether or not - it found the specified file, to determine how much to write. + + - io: an IO manager (see qcodes.data.io) + location: a string, like a file path, that identifies the DataSet and + tells the IO manager where to store it + - arrays: a dict of ``{array_id:DataArray}`` to read into. + + - read will create entries that don't yet exist. + - write will write ALL DataArrays in the DataSet, using + last_saved_index and modified_range, as well as whether or not + it found the specified file, to determine how much to write. """ ArrayGroup = namedtuple('ArrayGroup', 'shape set_arrays data name') diff --git a/qcodes/instrument/mock.py b/qcodes/instrument/mock.py index 60c84c142fd9..4b77bf7dd290 100644 --- a/qcodes/instrument/mock.py +++ b/qcodes/instrument/mock.py @@ -12,17 +12,19 @@ class MockInstrument(Instrument): """ Create a software instrument, mostly for testing purposes. - Also works for simulatoins, but usually this will be simpler, easier to + Also works for simulations, but usually this will be simpler, easier to use, and faster if made as a single ``Instrument`` subclass. - ``MockInstrument``s have extra overhead as they serialize all commands + ``MockInstrument``\s have extra overhead as they serialize all commands (to mimic a network communication channel) and use at least two processes (instrument server and model server) both of which must be involved in any given query. parameters to pass to model should be declared with: - get_cmd = param_name + '?' - set_cmd = param_name + ':{:.3f}' (specify the format & precision) + + - get_cmd = param_name + '?' + - set_cmd = param_name + ':{:.3f}' (specify the format & precision) + alternatively independent set/get functions may still be provided. Args: @@ -56,7 +58,7 @@ class MockInstrument(Instrument): history (List[tuple]): All commands and responses while keep_history is enabled, as tuples: - (timestamp, 'ask' or 'write', param_name[, value]) + (timestamp, 'ask' or 'write', param_name[, value]) """ shared_kwargs = ['model'] @@ -175,9 +177,9 @@ class MockModel(ServerManager, BaseServer): # pragma: no cover the server's uuid. for every instrument that connects to this model, create two methods: - ``_set(param, value)``: set a parameter on the model - ``_get(param)``: returns the value of a parameter - ``param`` and the set/return values should all be strings + - ``_set(param, value)``: set a parameter on the model + - ``_get(param)``: returns the value of a parameter + ``param`` and the set/return values should all be strings If ``param`` and/or ``value`` is not recognized, the method should raise an error. diff --git a/qcodes/instrument/parameter.py b/qcodes/instrument/parameter.py index bed24bb2c714..f0f63a09b087 100644 --- a/qcodes/instrument/parameter.py +++ b/qcodes/instrument/parameter.py @@ -91,6 +91,7 @@ class Parameter(Metadatable, DeferredOperations): Parameters have a .get_latest method that simply returns the most recent set or measured value. This can either be called ( param.get_latest() ) or used in a Loop as if it were a (gettable-only) parameter itself: + Loop(...).each(param.get_latest) @@ -121,7 +122,7 @@ class Parameter(Metadatable, DeferredOperations): setpoints: (3,4,5) the setpoints for the returned array of values. 3&4 - a tuple of arrays. The first array is be 1D, the second 2D, - etc. + etc. 5 - a tuple of tuples of arrays Defaults to integers from zero in each respective direction Each may be either a DataArray, a numpy array, or a sequence @@ -448,6 +449,7 @@ class StandardParameter(Parameter): set_cmd (Optional[Union[string, function]]): command to set this parameter, either: + - a string (containing one field to .format, like "{}" etc) you can only use a string if an instrument is provided, this string will be passed to instrument.write From 7c27a0608237ab85ac52824494affea17c8d1fea Mon Sep 17 00:00:00 2001 From: Ruben van Gulik Date: Tue, 20 Dec 2016 13:59:30 +0100 Subject: [PATCH 071/180] fix: Improved IVVI driver speed (#320) * fix: remove DAC value checking and improve timing * feature: DAC setpoints are checked again * feature: Added constructor flag for checking setpoints * feature: Adjustable sleep time in _set_dac * fix: setpoints check and set sleep now ManualParameter * fix: remove doc line * feature: merged PR #288 * feature: added buffer reading time variable * refactor: changes based on comments in the PR - Units and docstring for added parameters - Placed the DAC set sleeping command in the setpoint checking code, as it is only needed when first sending a get command. * Ivvi (#413) * to get_all after setting connection parameters * to get_all after setting connection parameters 2 * autopep * updates to IVVI driver (#423) * better variable name * replace version function with dummy; add extra setting of term characters * add safe_version option --- qcodes/instrument_drivers/QuTech/IVVI.py | 195 ++++++++++++++++++----- 1 file changed, 154 insertions(+), 41 deletions(-) diff --git a/qcodes/instrument_drivers/QuTech/IVVI.py b/qcodes/instrument_drivers/QuTech/IVVI.py index 69a39a31f9b6..4a57989611b1 100644 --- a/qcodes/instrument_drivers/QuTech/IVVI.py +++ b/qcodes/instrument_drivers/QuTech/IVVI.py @@ -5,6 +5,8 @@ import traceback from qcodes import VisaInstrument, validators as vals +from qcodes.instrument.parameter import ManualParameter +from qcodes.utils.validators import Bool, Numbers class IVVI(VisaInstrument): @@ -29,7 +31,7 @@ class IVVI(VisaInstrument): Halfrange = Fullrange / 2 def __init__(self, name, address, reset=False, numdacs=16, dac_step=10, - dac_delay=.1, dac_max_delay=0.2, **kwargs): + dac_delay=.1, dac_max_delay=0.2, safe_version=True, **kwargs): # polarity=['BIP', 'BIP', 'BIP', 'BIP']): # commented because still on the todo list ''' @@ -45,10 +47,14 @@ def __init__(self, name, address, reset=False, numdacs=16, dac_step=10, dac_step (float) : max step size for dac parameter dac_delay (float) : delay (in seconds) for dac dac_max_delay (float) : maximum delay before emitting a warning + safe_version (bool) : if True then do not send version commands + to the IVVI controller ''' t0 = time.time() super().__init__(name, address, **kwargs) + self.safe_version = safe_version + if numdacs % 4 == 0 and numdacs > 0: self._numdacs = int(numdacs) else: @@ -58,10 +64,45 @@ def __init__(self, name, address, reset=False, numdacs=16, dac_step=10, # values based on descriptor self.visa_handle.baud_rate = 115200 self.visa_handle.parity = visa.constants.Parity(1) # odd parity + self.visa_handle.write_termination = '' + self.visa_handle.read_termination = '' self.add_parameter('version', get_cmd=self._get_version) - + + self.add_parameter('check_setpoints', + parameter_class=ManualParameter, + initial_value=False, + label='Check setpoints', + vals=Bool(), + docstring=('Whether to check if the setpoint is the' + ' same as the current DAC value to ' + 'prevent an unnecessary set command.')) + + # Time to wait before sending a set DAC command to the IVVI + self.add_parameter('dac_set_sleep', + parameter_class=ManualParameter, + initial_value=0.05, + label='DAC set sleep', + units='s', + vals=Numbers(0), + docstring=('When check_setpoints is set to True, ' + 'this is the waiting time between the' + 'command that checks the current DAC ' + 'values and the final set DAC command')) + + # Minimum time to wait before the read buffer contains data + self.add_parameter('dac_read_buffer_sleep', + parameter_class=ManualParameter, + initial_value=0.025, + label='DAC read buffer sleep', + units='s', + vals=Numbers(0), + docstring=('While recieving bytes from the IVVI, ' + 'sleeping is done in multiples of this ' + 'value. Change to a lower value for ' + 'a shorter minimum time to wait.')) + self.add_parameter('dac voltages', label='Dac voltages', get_cmd=self._get_dacs) @@ -81,12 +122,21 @@ def __init__(self, name, address, reset=False, numdacs=16, dac_step=10, self._update_time = 5 # seconds self._time_last_update = 0 # ensures first call will always update - + self.pol_num = np.zeros(self._numdacs) # corresponds to POS polarity self.set_pol_dacrack('BIP', range(self._numdacs), get_all=False) t1 = time.time() + # make sure we ignore termination characters + # See http://www.ni.com/tutorial/4256/en/#toc2 on Termination Character + # Enabled + v = self.visa_handle + v.set_visa_attribute(visa.constants.VI_ATTR_TERMCHAR_EN, 0) + v.set_visa_attribute(visa.constants.VI_ATTR_ASRL_END_IN, 0) + v.set_visa_attribute(visa.constants.VI_ATTR_ASRL_END_OUT, 0) + v.set_visa_attribute(visa.constants.VI_ATTR_SEND_END_EN, 0) + # basic test to confirm we are properly connected try: self.get_all() @@ -94,28 +144,36 @@ def __init__(self, name, address, reset=False, numdacs=16, dac_step=10, print('IVVI: get_all() failed, maybe connected to wrong port?') print(traceback.format_exc()) - print('Initialized IVVI-rack in %.2fs' % (t1-t0)) + print('Initialized IVVI-rack in %.2fs' % (t1 - t0)) def get_idn(self): """ Overwrites the get_idn function using constants as the hardware does not have a proper *IDN function. """ + # not all IVVI racks support the version command, so return a dummy + return -1 + idparts = ['QuTech', 'IVVI', 'None', self.version()] return dict(zip(('vendor', 'model', 'serial', 'firmware'), idparts)) def _get_version(self): - mes = self.ask(bytes([3, 4])) - v = mes[2] - return v + if self.safe_version: + return -1 + else: + # ask for the version of more recent modules + # some of the older modules cannot handle this command + mes = self.ask(bytes([3, 4])) + ver = mes[2] + return ver def get_all(self): return self.snapshot(update=True) def set_dacs_zero(self): for i in range(self._numdacs): - self._set_dac(i+1, 0) + self._set_dac(i + 1, 0) # Conversion of data def _mvoltage_to_bytes(self, mvoltage): @@ -131,7 +189,7 @@ def _mvoltage_to_bytes(self, mvoltage): Output: (dataH, dataL) (int, int) : The high and low value byte equivalent ''' - bytevalue = int(round(mvoltage/self.Fullrange*65535)) + bytevalue = int(round(mvoltage / self.Fullrange * 65535)) return bytevalue.to_bytes(length=2, byteorder='big') def _bytes_to_mvoltages(self, byte_mess): @@ -143,8 +201,8 @@ def _bytes_to_mvoltages(self, byte_mess): for i in range(self._numdacs): # takes two bytes, converts it to a 16 bit int and then divides by # the range and adds the offset due to the polarity - values[i] = ((byte_mess[2 + 2*i]*256 + byte_mess[3 + 2*i]) / - 65535.0*self.Fullrange) + self.pol_num[i] + values[i] = ((byte_mess[2 + 2 * i] * 256 + byte_mess[3 + 2 * i]) / + 65535.0 * self.Fullrange) + self.pol_num[i] return values # Communication with device @@ -156,13 +214,13 @@ def _get_dac(self, channel): this version is a wrapper around the IVVI get function. it only updates ''' - return self._get_dacs()[channel-1] + return self._get_dacs()[channel - 1] def _set_dac(self, channel, mvoltage): ''' Sets the specified dac to the specified voltage. - Will only send a command to the IVVI if the next value is different - than the current value within byte resolution. + A check to prevent setting the same value is performed if + the check_setpoints flag was set. Input: mvoltage (float) : output voltage in mV @@ -172,25 +230,37 @@ def _set_dac(self, channel, mvoltage): reply (string) : errormessage Private version of function ''' - cur_val = self.get('dac{}'.format(channel)) - # dac range in mV / 16 bits FIXME make range depend on polarity - byte_res = self.Fullrange/2**16 - eps = 0.0001 - # eps is a magic number to correct for an offset in the values the IVVI - # returns (i.e. setting 0 returns byte_res/2 = 0.030518 with rounding + proceed = True + + if self.check_setpoints(): + cur_val = self.get('dac{}'.format(channel)) + # dac range in mV / 16 bits FIXME make range depend on polarity + byte_res = self.Fullrange / 2**16 + # eps is a magic number to correct for an offset in the values + # the IVVI returns (i.e. setting 0 returns byte_res/2 = 0.030518 + # with rounding + eps = 0.0001 + + proceed = False + + if (mvoltage > (cur_val + byte_res / 2 + eps) or + mvoltage < (cur_val - byte_res / 2 - eps)): + proceed = True + + if self.dac_set_sleep() > 0.0: + time.sleep(self.dac_set_sleep()) # only update the value if it is different from the previous one # this saves time in setting values, set cmd takes ~650ms - if (mvoltage > (cur_val+byte_res/2+eps) or - mvoltage < (cur_val - byte_res/2-eps)): - byte_val = self._mvoltage_to_bytes(mvoltage - - self.pol_num[channel-1]) + if proceed: + polarity_corrected = mvoltage - self.pol_num[channel - 1] + byte_val = self._mvoltage_to_bytes(polarity_corrected) message = bytes([2, 1, channel]) + byte_val - time.sleep(.05) + reply = self.ask(message) self._time_last_update = 0 # ensures get command will update + return reply - return def _get_dacs(self): ''' @@ -205,7 +275,7 @@ def _get_dacs(self): get dacs command takes ~450ms according to ipython timeit ''' if (time.time() - self._time_last_update) > self._update_time: - message = bytes([self._numdacs*2+2, 2]) + message = bytes([self._numdacs * 2 + 2, 2]) # workaround for an error in the readout that occurs sometimes max_tries = 10 for i in range(max_tries): @@ -216,7 +286,7 @@ def _get_dacs(self): break except Exception as ex: logging.warning('IVVI communication error trying again') - if i+1 == max_tries: # +1 because range goes stops before end + if i + 1 == max_tries: # +1 because range goes stops before end raise('IVVI Communication error') return self._mvoltages @@ -228,9 +298,12 @@ def write(self, message, raw=False): returns message_len ''' # This is used when write is used in the ask command - expected_answer_length = message[0] + expected_answer_length = None + if not raw: - message_len = len(message)+2 + expected_answer_length = message[0] + message_len = len(message) + 2 + error_code = bytes([0]) message = bytes([message_len]) + error_code + message self.visa_handle.write_raw(message) @@ -247,6 +320,44 @@ def ask(self, message, raw=False): message_len = self.write(message, raw=raw) return self.read(message_len=message_len) + def _read_raw_bytes_direct(self, size): + """ Read raw data using the visa lib """ + with(self.visa_handle.ignore_warning(visa.constants.VI_SUCCESS_MAX_CNT)): + data, statuscode = self.visa_handle.visalib.read( + self.visa_handle.session, size) + + return data + + def _read_raw_bytes_multiple(self, size, maxread=512, verbose=0): + """ Read raw data in blocks using the visa lib + Arguments: + size (int) : number of bytes to read + maxread (int) : maximum size of block to read + verbose (int): verbosity level + Returns: + ret (bytes): bytes read from the device + The pyvisa visalib.read does not always terminate at a newline, this + is a workaround. + Also see: https://github.com/qdev-dk/Qcodes/issues/276 + https://github.com/hgrecco/pyvisa/issues/225 + Setting both VI_ATTR_TERMCHAR_EN and VI_ATTR_ASRL_END_IN to zero + should allow the driver to ignore termination characters, this + function is an additional safety mechanism. + """ + ret = [] + instr = self.visa_handle + with self.visa_handle.ignore_warning(visa.constants.VI_SUCCESS_MAX_CNT): + nread = 0 + while nread < size: + nn = min(maxread, size - nread) + chunk, status = instr.visalib.read(instr.session, nn) + ret += [chunk] + nread += len(chunk) + if verbose: + print('_read_raw: %d/%d bytes' % (len(chunk), nread)) + ret = b''.join(ret) + return ret + def read(self, message_len=None): # because protocol has no termination chars the read reads the number # of bytes in the buffer @@ -260,17 +371,18 @@ def read(self, message_len=None): while bytes_in_buffer < message_len: t1 = time.time() - time.sleep(.05) + + if self.dac_read_buffer_sleep() > 0.0: + time.sleep(self.dac_read_buffer_sleep()) + bytes_in_buffer = self.visa_handle.bytes_in_buffer - if t1-t0 > timeout: + if t1 - t0 > timeout: raise TimeoutError() # a workaround for a timeout error in the pyvsia read_raw() function - with(self.visa_handle.ignore_warning(visa.constants.VI_SUCCESS_MAX_CNT)): - mes = self.visa_handle.visalib.read( - self.visa_handle.session, bytes_in_buffer) - mes = mes[0] # cannot be done on same line for some reason + mes = self._read_raw_bytes_multiple(bytes_in_buffer) + # if mes[1] != 0: - # # see protocol descriptor for error codes + # see protocol descriptor for error codes # raise Exception('IVVI rack exception "%s"' % mes[1]) return mes @@ -292,8 +404,9 @@ def set_pol_dacrack(self, flag, channels, get_all=True): val = flagmap[flag.upper()] for ch in channels: - self.pol_num[ch-1] = val - # self.set_parameter_bounds('dac%d' % (i+1), val, val + self.Fullrange.0) + self.pol_num[ch - 1] = val + # self.set_parameter_bounds('dac%d' % (i+1), val, val + + # self.Fullrange.0) if get_all: self.get_all() @@ -308,7 +421,7 @@ def get_pol_dac(self, channel): Output: polarity (string) : 'BIP', 'POS' or 'NEG' ''' - val = self.pol_num[channel-1] + val = self.pol_num[channel - 1] if (val == -self.Fullrange): return 'NEG' @@ -387,4 +500,4 @@ def get_func(): .. 32 DAC16 Value of DAC16 2 -------------------------------------------------------------------------------------------------------- -''' \ No newline at end of file +''' From b8c50598245aaef979fe64f054c4f59b375b79af Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Tue, 3 Jan 2017 10:11:01 +0100 Subject: [PATCH 072/180] Fix: Limit sip to 4.18.1 4.19 seems to segfault during setup.py develop --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index ace996ad9542..a3c8d27ebee3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,5 +4,6 @@ matplotlib==1.5.3 pyqtgraph==0.10.0 PyVISA==1.8 PyQt5==5.7 +sip==4.18.1 QtPy==1.1.2 h5py==2.6.0 From 450976d0bc04c7f481ed11a817f6933c3336d410 Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Tue, 3 Jan 2017 12:49:39 +0100 Subject: [PATCH 073/180] Travis: install sphinx for docs build --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index bd0a5d494591..75640405c463 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,7 +28,7 @@ script: after_success: # install codacy coverage plugin only on traivs - - pip install codacy-coverage + - pip install codacy-coverage sphinx - cd qcodes - coverage xml - python-codacy-coverage -r coverage.xml From ca555b2d1757aea56893a49a320b1c6a9ae7a862 Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Tue, 3 Jan 2017 12:55:41 +0100 Subject: [PATCH 074/180] travis: also install read the docs theme --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 75640405c463..9ebe4157f864 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,7 +28,7 @@ script: after_success: # install codacy coverage plugin only on traivs - - pip install codacy-coverage sphinx + - pip install codacy-coverage sphinx sphinx_rtd_theme - cd qcodes - coverage xml - python-codacy-coverage -r coverage.xml From 56f3182188fd215d7e2619123dccd4fe4706e999 Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Tue, 3 Jan 2017 13:01:02 +0100 Subject: [PATCH 075/180] Travis: also add jsonschema and sphinx package --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 9ebe4157f864..ef9544d39b64 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,7 +28,7 @@ script: after_success: # install codacy coverage plugin only on traivs - - pip install codacy-coverage sphinx sphinx_rtd_theme + - pip install codacy-coverage sphinx sphinx_rtd_theme jsonschema sphinxcontrib-jsonschema - cd qcodes - coverage xml - python-codacy-coverage -r coverage.xml From c01ba932a1d8e1b4f0d37e5eda10a6b7f7022f54 Mon Sep 17 00:00:00 2001 From: nataliejpg Date: Tue, 3 Jan 2017 14:19:42 +0100 Subject: [PATCH 076/180] made a mess of branches, rebase and add back in various acq controllers --- .../AlazarTech/ave_controller.py | 265 ++++++++++++++++ .../AlazarTech/rec_buf_controller.py | 220 +++++++++++++ .../AlazarTech/rec_controller.py | 294 ++++++++++++++++++ .../AlazarTech/rec_samp_controller.py | 233 ++++++++++++++ 4 files changed, 1012 insertions(+) create mode 100644 qcodes/instrument_drivers/AlazarTech/ave_controller.py create mode 100644 qcodes/instrument_drivers/AlazarTech/rec_buf_controller.py create mode 100644 qcodes/instrument_drivers/AlazarTech/rec_controller.py create mode 100644 qcodes/instrument_drivers/AlazarTech/rec_samp_controller.py diff --git a/qcodes/instrument_drivers/AlazarTech/ave_controller.py b/qcodes/instrument_drivers/AlazarTech/ave_controller.py new file mode 100644 index 000000000000..d23767c7aeb2 --- /dev/null +++ b/qcodes/instrument_drivers/AlazarTech/ave_controller.py @@ -0,0 +1,265 @@ +import logging +from .ATS import AcquisitionController +import numpy as np +import qcodes.utils.helpers as helpers + + +class HD_Controller(AcquisitionController): + """ + This is the Acquisition Controller class which works with the ATS9360, + averaging over buffers and records, demodulating with a software + reference signal, averaging over the samples. + args: + name: name for this acquisition_conroller as an instrument + alazar_name: the name of the alazar instrument such that this controller + can communicate with the Alazar + demod_freq: the frequency of the software wave to be created + samp_rate: the rate of sampling + filt: the filter to be used to filter out double freq component + chan_b: whether there is also a second channel of data to be processed + and returned + **kwargs: kwargs are forwarded to the Instrument base class + + TODO(nataliejpg) fix sample rate problem + TODO(nataliejpg) test filter options + TODO(nataliejpg) finish implementation of channel b option + TODO(nataliejpg) make demodulation freq a param + """ + + def __init__(self, name, alazar_name, demod_freq, samp_rate=5e8, + filt='win', numtaps=101, chan_b=False, **kwargs): + filter_dict = {'win': 0, 'ls': 1, 'dot': 2} + self.demodulation_frequency = demod_freq + self.sample_rate = samp_rate + self.filter = filter_dict[filt] + self.numtaps = numtaps + self.acquisitionkwargs = {} + self.chan_b = chan_b + self.samples_per_record = None + self.records_per_buffer = None + self.buffers_per_acquisition = None + self.number_of_channels = 2 + self.samples_delay = None + self.samples_time = None + self.cos_list = None + self.sin_list = None + self.buffer = None + self.board_info = None + # make a call to the parent class and by extension, + # create the parameter structure of this class + super().__init__(name, alazar_name, **kwargs) + + self.add_parameter(name='acquisition', + names=('magnitude', 'phase'), + units=('', ''), + get_cmd=self.do_acquisition) + + def update_acquisitionkwargs(self, **kwargs): + """ + Updates the kwargs to be used when + alazar_driver.acquire is called. + + It is also used to set the limits on the selection of + samples used (bounded by delay and integration time) + + :param kwargs: + :return: + """ + samples_per_record = kwargs['samples_per_record'] + sample_rate = self.sample_rate + + if 'int_delay' in kwargs: + int_delay = kwargs.pop('int_delay') + samp_delay = int_delay * sample_rate + samples_delay_min = (self.numtaps - 1) + if samp_delay < samples_delay_min: + int_delay_min = samples_delay_min / sample_rate + logging.warning( + 'delay is less than recommended for filter choice: ' + '(expect delay >= {}'.format(int_delay_min)) + else: + samp_delay = self.numtaps - 1 + + if 'int_time' in kwargs: + int_time = kwargs.pop('int_time') + samp_time = int_time * sample_rate + samples_time_max = (samples_per_record - samp_delay) + oscilations_measured = int_time * self.demodulation_frequency + oversampling = sample_rate / (2 * self.demodulation_frequency) + if samp_time > samples_time_max: + int_time_max = samples_time_max / sample_rate + raise ValueError('int_time {} is longer than total_time - ' + 'delay: {}'.format(int_time, int_time_max)) + elif oscilations_measured < 10: + logging.warning('{} oscilations measured, recommend at ' + 'least 10: decrease sampling rate, take ' + 'more samples or increase demodulation ' + 'freq'.format(oscilations_measured)) + elif oversampling < 1: + logging.warning('oversampling rate is {}, recommend > 1: ' + 'increase sampling rate or decrease ' + 'demodulation frequency'.format(oversampling)) + else: + samp_time = samples_per_record - samp_delay + + self.samples_time = int(samp_time) + self.samples_delay = int(samp_delay) + + self.acquisitionkwargs.update(**kwargs) + + def do_acquisition(self): + """ + this method performs an acquisition, which is the get_cmd for the + acquisiion parameter of this instrument + :return: + """ + values = self._get_alazar().acquire(acquisition_controller=self, + **self.acquisitionkwargs) + return values + + def pre_start_capture(self): + """ + Called before capture start to update Acquisition Controller with + alazar acquisition params and set up software wave for demodulation. + :return: + """ + alazar = self._get_alazar() + self.samples_per_record = alazar.samples_per_record.get() + self.records_per_buffer = alazar.records_per_buffer.get() + self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() + self.board_info = alazar.get_idn() + self.buffer = np.zeros(self.samples_per_record * + self.records_per_buffer * + self.number_of_channels) + + integer_list = np.arange(self.samples_per_record, dtype=np.uint16) + angle_list = (2 * np.pi * self.demodulation_frequency / + self.sample_rate * integer_list) + + self.cos_list = np.cos(angle_list) + self.sin_list = np.sin(angle_list) + + def pre_acquire(self): + """ + See AcquisitionController + :return: + """ + pass + + def handle_buffer(self, data): + """ + Adds data from alazar to buffer (effectively averaging) + :return: + """ + self.buffer += data + + def post_acquire(self): + """ + Processes the data according to ATS9360 settings, splitting into + records and averaging over them, then applying demodulation fit + nb: currently only channel A + :return: samples_magnitude_array, samples_phase_array + """ + records_per_acquisition = (self.buffers_per_acquisition * + self.records_per_buffer) + # for ATS9360 samples are arranged in the buffer as follows: + # S00A, S00B, S01A, S01B...S10A, S10B, S11A, S11B... + # where SXYZ is record X, sample Y, channel Z. + + # break buffer up into records and averages over them + recA = np.zeros(self.samples_per_record) + for i in range(self.records_per_buffer): + i0 = (i * self.samples_per_record * self.number_of_channels) + i1 = (i0 + self.samples_per_record * self.number_of_channels) + recA += self.buffer[i0:i1:self.number_of_channels] + recordA = np.uint16(recA / records_per_acquisition) + + # do demodulation + magA, phaseA = self.fit(recordA) + + # same for chan b + if self.chan_b: + raise NotImplementedError('chan b code not complete') + # recordB = np.zeros(self.samples_per_record, dtype=np.uint16) + # for i in range(self.records_per_buffer): + # i0 = (i * self.samples_per_record * + # self.number_of_channels + 1) + # i1 = (i0 + self.samples_per_record * self.number_of_channels) + # recordB += np.uint16(self.buffer[i0:i1:self.number_of_channels] / + # records_per_acquisition) + # magB, phaseB = self.fit(recordB) + + return magA, phaseA + + def fit(self, rec): + """ + Applies volts conversion, demodulation fit, low bandpass filter + and integration limits to samples array and averages + :return: magnitude, phase + """ + + # convert rec to volts + bps = self.board_info['bits_per_sample'] + if bps == 12: + volt_rec = sample_to_volt_u12(rec, bps) + else: + logging.warning('sample to volt conversion does not exist for' + ' bps != 12, centered raw samples returned') + volt_rec = rec - np.mean(rec) + + # multiply with software wave + re_wave = np.multiply(volt_rec, self.cos_list) + im_wave = np.multiply(volt_rec, self.sin_list) + cutoff = self.demodulation_frequency / 10 + + # filter out higher freq component + if self.filter == 0: + re_filtered = helpers.filter_win(re_wave, cutoff, + self.sample_rate, self.numtaps) + im_filtered = helpers.filter_win(im_wave, cutoff, + self.sample_rate, self.numtaps) + elif self.filter == 1: + re_filtered = helpers.filter_ls(re_wave, cutoff, + self.sample_rate, self.numtaps) + im_filtered = helpers.filter_ls(im_wave, cutoff, + self.sample_rate, self.numtaps) + elif self.filter == 2: + re_filtered = re_wave + im_filtered = im_wave + + # apply integration limits + start = self.samples_delay + end = start + self.samples_time + + re_limited = re_filtered[start:end] + im_limited = im_filtered[start:end] + + # convert to magnitude and phase + complex_num = re_limited + im_limited * 1j + mag = np.mean(abs(complex_num)) + phase = np.mean(np.angle(complex_num, deg=True)) + + return mag, phase + + +def sample_to_volt_u12(raw_samples, bps): + """ + Applies volts conversion for 12 bit sample data stored + in 2 bytes + :return: samples_magnitude_array, samples_phase_array + """ + + # right_shift 16-bit sample by 4 to get 12 bit sample + shifted_samples = np.right_shift(raw_samples, 4) + + # Alazar calibration + code_zero = (1 << (bps - 1)) - 0.5 + code_range = (1 << (bps - 1)) - 0.5 + + # TODO(nataliejpg) make this not hard coded + input_range_volts = 1 + # Convert to volts + volt_samples = np.float64(input_range_volts * + (shifted_samples - code_zero) / code_range) + + return volt_samples diff --git a/qcodes/instrument_drivers/AlazarTech/rec_buf_controller.py b/qcodes/instrument_drivers/AlazarTech/rec_buf_controller.py new file mode 100644 index 000000000000..65ddb9dea4d7 --- /dev/null +++ b/qcodes/instrument_drivers/AlazarTech/rec_buf_controller.py @@ -0,0 +1,220 @@ +from .ATS import AcquisitionController +import numpy as np +from qcodes import Parameter +from scipy import signal + + +class RecBufParam(Parameter): + """ + Hardware controlled parameter class for Alazar acquisition. To be used with + HD_Samples_Controller (tested with ATS9360 board) for return of an array of + sample data from the Alazar, averaged over records and buffers. + """ + + def __init__(self, name, instrument): + super().__init__(name) + self._instrument = instrument + self.acquisitionkwargs = {} + self.names = ('magnitude', 'phase') + self.units = ('', '') + self.setpoint_names = (('rec_num', 'buf_num'), ('rec_num', 'buf_num')) + self.setpoints = ((1, 1), (1, 1)) + self.shapes = ((1, 1), (1, 1)) + + def update_acquisition_kwargs(self, **kwargs): + # needed to update config of the software parameter on sweep change + # freq setpoints tuple as needs to be hashable for look up + if 'records_per_buffer' and 'buffers_per_acquisition' in kwargs: + rpts = kwargs['records_per_buffer'] + bpts = kwargs['buffers_per_acquisition'] + r = tuple(np.arange(rpts)) + b = tuple(np.arange(bpts)) + self.setpoints = ((r, b), (r, b)) + self.shapes = ((rpts, bpts), (rpts, bpts)) + else: + raise ValueError( + 'records_per_buffer and buffers_per_acquisition must be specified') + # updates dict to be used in acquisition get call + self.acquisitionkwargs.update(**kwargs) + + def get(self): + mag, phase = self._instrument._get_alazar().acquire( + acquisition_controller=self._instrument, + **self.acquisitionkwargs) + return mag, phase + + +class HD_RecBuf_Controller(AcquisitionController): + """ + This is the Acquisition Controller class which works with the ATS9360, + averaging over buffers and records and demodulating with a software + reference signal, returning the samples. + args: + name: name for this acquisition_conroller as an instrument + alazar_name: the name of the alazar instrument such that this controller + can communicate with the Alazar + demod_freq: the frequency of the software wave to be created + samp_rate: the rate of sampling + filt: the filter to be used to filter out double freq component + chan_b: whether there is also a second channel of data to be processed + and returned + **kwargs: kwargs are forwarded to the Instrument base class + + TODO(nataliejpg) fix sample rate problem + TODO(nataliejpg) test filter options + TODO(nataliejpg) test mag phase logic + TODO(nataliejpg) finish implementation of channel b option + TODO(nataliejpg) make filter settings not hard coded + """ + + def __init__(self, name, alazar_name, demod_freq, samp_rate=500e6, + filt='win', chan_b=False, **kwargs): + filter_dict = {'win': 0, 'hamming': 1, 'ls': 2} + self.demodulation_frequency = demod_freq + self.sample_rate = samp_rate + self.filter = filter_dict[filt] + self.chan_b = chan_b + self.samples_per_record = 0 + self.records_per_buffer = 0 + self.buffers_per_acquisition = 0 + self.number_of_channels = 2 + self.cos_list = None + self.sin_list = None + self.buffer = None + self.buf_count = 0 + # make a call to the parent class and by extension, + # create the parameter structure of this class + super().__init__(name, alazar_name, **kwargs) + + self.add_parameter(name='acquisition', + parameter_class=RecBufParam) + + def update_acquisitionkwargs(self, **kwargs): + """ + This method must be used to update the kwargs used for the acquisition + with the alazar_driver.acquire + :param kwargs: + :return: + """ + self.acquisition.update_acquisition_kwargs(**kwargs) + + def pre_start_capture(self): + """ + See AcquisitionController + :return: + """ + alazar = self._get_alazar() + self.samples_per_record = alazar.samples_per_record.get() + self.records_per_buffer = alazar.records_per_buffer.get() + self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() + self.buf_count = 0 + self.samples_per_buffer = (self.samples_per_record * + self.records_per_buffer * + self.buffers_per_acquisition * + self.number_of_channels) + self.buffer = np.zeros(self.samples_per_buffer) + + integer_list = np.arange(self.samples_per_record) + angle_list = (2 * np.pi * self.demodulation_frequency / + self.sample_rate * integer_list) + + cos_list = np.cos(angle_list) + sin_list = np.sin(angle_list) + self.cos_mat = np.kron(np.ones((1, self.records_per_buffer)), cos_list) + self.sin_mat = np.kron(np.ones((1, self.records_per_buffer)), sin_list) + + def pre_acquire(self): + """ + See AcquisitionController + :return: + """ + # this could be used to start an Arbitrary Waveform Generator, etc... + # using this method ensures that the contents are executed AFTER the + # Alazar card starts listening for a trigger pulse + pass + + def handle_buffer(self, data): + """ + See AcquisitionController + :return: + """ + i0 = self.bufcount * self.samples_per_buffer + i1 = i0 + self.samples_per_buffer + self.buffer[i0:i1] = data + self.buf_count += 1 + + def post_acquire(self): + """ + See AcquisitionController + :return: + """ + # for ATS9360 samples are arranged in the buffer as follows: + # S00A, S00B, S01A, S01B...S10A, S10B, S11A, S11B... + # where SXYZ is record X, sample Y, channel Z. + + # reshapes data to be (samples * records * buffers) + + # TODO!! + + magA, phaseA = 0, 0 + + return magA, phaseA + + def fit(self, rec): + # center rec around 0 + rec = rec - np.mean(rec) + + # multiply with software wave + re_wave = np.multiply(rec, self.cos_mat) + im_wave = np.multiply(rec, self.sin_mat) + cutoff = self.demodulation_frequency + numtaps = 30 + axis = 0 + + # filter out double freq component to obtian constant term + if self.filter == 0: + RePart = self.filter_win(re_wave, numtaps, cutoff, axis=axis) + ImPart = self.filter_win(im_wave, numtaps, cutoff, axis=axis) + elif self.filter == 1: + RePart = self.filter_hamming(re_wave, numtaps, cutoff, axis=axis) + ImPart = self.filter_hamming(im_wave, numtaps, cutoff, axis=axis) + elif self.filter == 2: + RePart = self.filter_ls(re_wave, numtaps, cutoff, axis, axis=axis) + ImPart = self.filter_ls(im_wave, numtaps, cutoff, axis, axis=axis) + + # convert to magnitude and phase data and average over samples + # data returned is (records * buffers) + complex_mat = RePart + ImPart * 1j + mag = np.mean(2 * abs(complex_mat), axis=0) + phase = np.mean(np.angle(complex_mat, axis=0, deg=True)) + + return mag, phase + + def filter_hamming(self, rec, numtaps, cutoff, axis=-1): + sample_rate = self.sample_rate + nyq_rate = sample_rate / 2. + fir_coef = signal.firwin(numtaps, + cutoff / nyq_rate, + window="hamming") + filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec, axis=axis) + return filtered_rec + + def filter_win(self, rec, numtaps, cutoff, axis=-1): + sample_rate = self.sample_rate + nyq_rate = sample_rate / 2. + fir_coef = signal.firwin(numtaps, + cutoff / nyq_rate) + filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec, axis=axis) + return filtered_rec + + def filter_ls(self, rec, numtaps, cutoff, axis=-1): + sample_rate = self.sample_rate + nyq_rate = sample_rate / 2. + bands = [0, cutoff / nyq_rate, cutoff / nyq_rate, 1] + desired = [1, 1, 0, 0] + fir_coef = signal.firls(numtaps, + bands, + desired, + nyq=nyq_rate) + filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec, axis=axis) + return filtered_rec diff --git a/qcodes/instrument_drivers/AlazarTech/rec_controller.py b/qcodes/instrument_drivers/AlazarTech/rec_controller.py new file mode 100644 index 000000000000..5513e384264b --- /dev/null +++ b/qcodes/instrument_drivers/AlazarTech/rec_controller.py @@ -0,0 +1,294 @@ +import logging +from .ATS import AcquisitionController +import numpy as np +from qcodes import Parameter +from qcodes.utils.helpers import filter_win, filter_ls + + +class RecordsParam(Parameter): + """ + Hardware controlled parameter class for Alazar acquisition. To be used with + HD_Records_Controller (tested with ATS9360 board) for return of an array of + record data from the Alazar, averaged over samples and buffers. + + TODO(nataliejpg) fix setpoints/shapes horriblenesss + """ + + def __init__(self, name, instrument): + super().__init__(name) + self._instrument = instrument + self.acquisitionkwargs = {} + self.names = ('magnitude', 'phase') + self.units = ('', '') + self.setpoint_names = (('record_num',), ('record_num',)) + self.setpoints = ((1,), (1,)) + self.shapes = ((1,), (1,)) + + def update_acquisition_kwargs(self, **kwargs): + # needed to update config of the software parameter on sweep change + # freq setpoints tuple as needs to be hashable for look up + if 'records_per_buffer' in kwargs: + npts = kwargs['records_per_buffer'] + n = tuple(np.arange(npts)) + self.setpoints = ((n,), (n,)) + self.shapes = ((npts,), (npts,)) + else: + raise ValueError('records_per_buffer must be specified') + # updates dict to be used in acquisition get call + self.acquisitionkwargs.update(**kwargs) + + def get(self): + mag, phase = self._instrument._get_alazar().acquire( + acquisition_controller=self._instrument, + **self.acquisitionkwargs) + return mag, phase + + +class HD_Records_Controller(AcquisitionController): + """ + This is the Acquisition Controller class which works with the ATS9360, + averaging over buffers and records and demodulating with a software + reference signal, returning the samples. + args: + name: name for this acquisition_conroller as an instrument + alazar_name: the name of the alazar instrument such that this controller + can communicate with the Alazar + demod_freq: the frequency of the software wave to be created + samp_rate: the rate of sampling + filt: the filter to be used to filter out double freq component + numtaps: number of freq components used in the filter + chan_b: whether there is also a second channel of data to be processed + and returned + **kwargs: kwargs are forwarded to the Instrument base class + + TODO(nataliejpg) fix sample rate problem + TODO(nataliejpg) test filter options + TODO(nataliejpg) finish implementation of channel b option + TODO(nataliejpg) make demodulation freq a param + """ + + def __init__(self, name, alazar_name, demod_freq, samp_rate=5e8, + filt='win', numtaps=101, chan_b=False, **kwargs): + filter_dict = {'win': 0, 'ls': 1, 'dot': 2} + self.demodulation_frequency = demod_freq + self.sample_rate = samp_rate + self.filter = filter_dict[filt] + self.numtaps = numtaps + self.chan_b = chan_b + self.samples_per_record = None + self.records_per_buffer = None + self.buffers_per_acquisition = None + self.number_of_channels = 2 + self.samples_delay = None + self.samples_time = None + self.cos_mat = None + self.sin_mat = None + self.buffer = None + self.board_info = None + # make a call to the parent class and by extension, + # create the parameter structure of this class + super().__init__(name, alazar_name, **kwargs) + + self.add_parameter(name='acquisition', + parameter_class=RecordsParam) + + def update_acquisitionkwargs(self, **kwargs): + """ + Updates the kwargs to be used when + alazar_driver.acquire is called via a get call of the + acquisition RecordsParam. + + It is also used to set the limits on the selection of + samples used (bounded by delay and integration time) + + :param kwargs: + :return: + """ + samples_per_record = kwargs['samples_per_record'] + sample_rate = self.sample_rate + + if 'int_delay' in kwargs: + int_delay = kwargs.pop('int_delay') + samp_delay = int_delay * sample_rate + samples_delay_min = (self.numtaps - 1) + if samp_delay < samples_delay_min: + int_delay_min = samples_delay_min / sample_rate + logging.warning( + 'delay is less than recommended for filter choice: ' + '(expect delay >= {}'.format(int_delay_min)) + else: + samp_delay = self.numtaps - 1 + + if 'int_time' in kwargs: + int_time = kwargs.pop('int_time') + samp_time = int_time * sample_rate + samples_time_max = (samples_per_record - samp_delay) + oscilations_measured = int_time * self.demodulation_frequency + oversampling = sample_rate / (2 * self.demodulation_frequency) + if samp_time > samples_time_max: + int_time_max = samples_time_max / sample_rate + raise ValueError('int_time {} is longer than total_time - ' + 'delay: {}'.format(int_time, int_time_max)) + elif oscilations_measured < 10: + logging.warning('{} oscilations measured, recommend at ' + 'least 10: decrease sampling rate, take ' + 'more samples or increase demodulation ' + 'freq'.format(oscilations_measured)) + elif oversampling < 1: + logging.warning('oversampling rate is {}, recommend > 1: ' + 'increase sampling rate or decrease ' + 'demodulation frequency'.format(oversampling)) + else: + samp_time = samples_per_record - samp_delay + + self.samples_time = int(samp_time) + self.samples_delay = int(samp_delay) + + self.acquisition.update_acquisition_kwargs(**kwargs) + + def pre_start_capture(self): + """ + Called before capture start to update Acquisition Controller with + alazar acquisition params and set up software wave for demodulation. + + sine and cosine matrices have shape (samples * records). + + :return: + """ + alazar = self._get_alazar() + self.samples_per_record = alazar.samples_per_record.get() + self.records_per_buffer = alazar.records_per_buffer.get() + self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() + self.board_info = alazar.get_idn() + self.buffer = np.zeros(self.samples_per_record * + self.records_per_buffer * + self.number_of_channels) + + integer_list = np.arange(self.samples_per_record, dtype=np.uint16) + angle_list = (2 * np.pi * self.demodulation_frequency / + self.sample_rate * integer_list) + + cos_list = np.cos(angle_list).reshape(self.samples_per_record, 1) + sin_list = np.sin(angle_list).reshape(self.samples_per_record, 1) + + self.cos_mat = np.kron(np.ones((1, self.records_per_buffer)), cos_list) + self.sin_mat = np.kron(np.ones((1, self.records_per_buffer)), sin_list) + + def pre_acquire(self): + """ + See AcquisitionController + :return: + """ + pass + + def handle_buffer(self, data): + """ + Adds data from alazar to buffer (effectively averaging) + :return: + """ + self.buffer += data + + def post_acquire(self): + """ + Processes the data according to ATS9360 settings, splitting into + records and averaging over them, then applying demodulation fit + nb: currently only channel A + :return: samples_magnitude_array, samples_phase_array + """ + + # for ATS9360 samples are arranged in the buffer as follows: + # S00A, S00B, S01A, S01B...S10A, S10B, S11A, S11B... + # where SXYZ is record X, sample Y, channel Z. + + # break buffer up into records and shapes to be (samples * records) + recordA = np.zeros((self.samples_per_record, self.records_per_buffer), + dtype=np.uint16) + for i in range(self.records_per_buffer): + i0 = (i * self.samples_per_record * self.number_of_channels) + i1 = (i0 + self.samples_per_record * self.number_of_channels) + recordA[:, i] = np.uint16( + self.buffer[i0:i1:self.number_of_channels] / + self.buffers_per_acquisition) + + # do demodulation + magA, phaseA = self.fit(recordA) + + # same for chan b + if self.chan_b: + raise NotImplementedError('chan b code not complete') + + return magA, phaseA + + def fit(self, rec): + """ + Applies volts conversion, demodulation fit, low bandpass filter + and integration limits to samples * records array + :return: records_magnitude_array, records_phase_array + """ + + # convert rec to volts + bps = self.board_info['bits_per_sample'] + if bps == 12: + volt_rec = sample_to_volt_u12(rec, bps) + else: + logging.warning('sample to volt conversion does not exist for' + ' bps != 12, centered raw samples returned') + volt_rec = rec - np.mean(rec, 0) + + # multiply with software wave + re_wave = np.multiply(volt_rec, self.cos_mat) + im_wave = np.multiply(volt_rec, self.sin_mat) + cutoff = self.demodulation_frequency / 10 + ax = 0 + + # filter out higher freq component + if self.filter == 0: + re_filtered = filter_win(re_wave, cutoff, self.sample_rate, + self.numtaps, axis=ax) + im_filtered = filter_win(im_wave, cutoff, self.sample_rate, + self.numtaps, axis=ax) + elif self.filter == 1: + re_filtered = filter_ls(re_wave, cutoff, self.sample_rate, + self.numtaps, axis=ax) + im_filtered = filter_ls(im_wave, cutoff, self.sample_rate, + self.numtaps, axis=ax) + elif self.filter == 2: + re_filtered = re_wave + im_filtered = im_wave + + # apply integration limits + start = self.samples_delay + end = start + self.samples_time + + re_limited = re_filtered[start:end, :] + im_limited = im_filtered[start:end, :] + + # convert to magnitude and phase + complex_num = re_limited + im_limited * 1j + mag = np.mean(abs(complex_num), 0) + phase = np.mean(np.angle(complex_num, deg=True), 0) + + return mag, phase + + +def sample_to_volt_u12(raw_samples, bps): + """ + Applies volts conversion for 12 bit sample data stored + in 2 bytes + :return: samples_magnitude_array, samples_phase_array + """ + + # right_shift 16-bit sample by 4 to get 12 bit sample + shifted_samples = np.right_shift(raw_samples, 4) + + # Alazar calibration + code_zero = (1 << (bps - 1)) - 0.5 + code_range = (1 << (bps - 1)) - 0.5 + + # TODO(nataliejpg) make this not hard coded + input_range_volts = 1 + # Convert to volts + volt_samples = np.float64(input_range_volts * + (shifted_samples - code_zero) / code_range) + + return volt_samples diff --git a/qcodes/instrument_drivers/AlazarTech/rec_samp_controller.py b/qcodes/instrument_drivers/AlazarTech/rec_samp_controller.py new file mode 100644 index 000000000000..7e86e9ffc211 --- /dev/null +++ b/qcodes/instrument_drivers/AlazarTech/rec_samp_controller.py @@ -0,0 +1,233 @@ +from .ATS import AcquisitionController +import numpy as np +from qcodes import Parameter +from scipy import signal + + +class RecSampParam(Parameter): + """ + Hardware controlled parameter class for Alazar acquisition. To be used with + HD_Samples_Controller (tested with ATS9360 board) for return of an array of + sample data from the Alazar, averaged over records and buffers. + + TODO(nataliejpg) fix setpoints/shapes horriblenesss + TODO(nataliejpg) make it actually work... + """ + + def __init__(self, name, instrument): + super().__init__(name) + self._instrument = instrument + self.acquisitionkwargs = {} + self.names = ('magnitude', 'phase') + self.units = ('', '') + self.setpoint_names = (('rec_num', 'samp_num'), + ('rec_num', 'samp_num')) + self.setpoints = ((1, 1), (1, 1)) + self.shapes = ((1, 1), (1, 1)) + + def update_acquisition_kwargs(self, **kwargs): + # needed to update config of the software parameter on sweep change + # freq setpoints tuple as needs to be hashable for look up + if 'samples_per_record' and 'records_per_buffer' in kwargs: + spts = kwargs['samples_per_record'] + rpts = kwargs['records_per_buffer'] + s = tuple(np.arange(spts)) + r = tuple(np.arange(rpts)) + self.setpoints = ((s, r), (s, r)) + self.shapes = ((spts, rpts), (spts, rpts)) + else: + raise ValueError( + 'records_per_buffer and samples_per_record must be specified') + # updates dict to be used in acquisition get call + self.acquisitionkwargs.update(**kwargs) + + def get(self): + mag, phase = self._instrument._get_alazar().acquire( + acquisition_controller=self._instrument, + **self.acquisitionkwargs) + return mag, phase + + +class HD_RecSamp_Controller(AcquisitionController): + """ + This is the Acquisition Controller class which works with the ATS9360, + averaging over buffers and records and demodulating with a software + reference signal, returning the samples. + args: + name: name for this acquisition_conroller as an instrument + alazar_name: the name of the alazar instrument such that this controller + can communicate with the Alazar + demod_freq: the frequency of the software wave to be created + samp_rate: the rate of sampling + filt: the filter to be used to filter out double freq component + chan_b: whether there is also a second channel of data to be processed + and returned + **kwargs: kwargs are forwarded to the Instrument base class + + TODO(nataliejpg) fix sample rate problem + TODO(nataliejpg) test filter options + TODO(nataliejpg) test mag phase logic + TODO(nataliejpg) finish implementation of channel b option + TODO(nataliejpg) make filter settings not hard coded + """ + + def __init__(self, name, alazar_name, demod_freq, samp_rate=500e6, + filt='win', chan_b=False, **kwargs): + filter_dict = {'win': 0, 'hamming': 1, 'ls': 2} + self.demodulation_frequency = demod_freq + self.sample_rate = samp_rate + self.filter = filter_dict[filt] + self.chan_b = chan_b + self.samples_per_record = 0 + self.records_per_buffer = 0 + self.buffers_per_acquisition = 0 + self.number_of_channels = 2 + self.cos_list = None + self.sin_list = None + self.buffer = None + # make a call to the parent class and by extension, + # create the parameter structure of this class + super().__init__(name, alazar_name, **kwargs) + + self.add_parameter(name='acquisition', + parameter_class=RecSampParam) + + def update_acquisitionkwargs(self, **kwargs): + """ + This method must be used to update the kwargs used for the acquisition + with the alazar_driver.acquire + :param kwargs: + :return: + """ + self.acquisition.update_acquisition_kwargs(**kwargs) + + def pre_start_capture(self): + """ + See AcquisitionController + :return: + """ + alazar = self._get_alazar() + self.samples_per_record = alazar.samples_per_record.get() + self.records_per_buffer = alazar.records_per_buffer.get() + self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() + self.buffer = np.zeros(self.samples_per_record * + self.records_per_buffer * + self.number_of_channels) + + integer_list = np.arange(self.samples_per_record) + angle_list = (2 * np.pi * self.demodulation_frequency / + self.sample_rate * integer_list) + + cos_list = np.cos(angle_list).reshape(self.samples_per_record, 1) + sin_list = np.sin(angle_list).reshape(self.samples_per_record, 1) + self.cos_mat = np.kron(np.ones((1, self.records_per_buffer)), cos_list) + self.sin_mat = np.kron(np.ones((1, self.records_per_buffer)), sin_list) + + def pre_acquire(self): + """ + See AcquisitionController + :return: + """ + # this could be used to start an Arbitrary Waveform Generator, etc... + # using this method ensures that the contents are executed AFTER the + # Alazar card starts listening for a trigger pulse + pass + + def handle_buffer(self, data): + """ + See AcquisitionController + :return: + """ + # average over buffers + self.buffer += data + + def post_acquire(self): + """ + See AcquisitionController + :return: + """ + + # for ATS9360 samples are arranged in the buffer as follows: + # S00A, S00B, S01A, S01B...S10A, S10B, S11A, S11B... + # where SXYZ is record X, sample Y, channel Z. + + # reshapes date to be (samples * records) + recordA = np.zeros((self.samples_per_record, self.records_per_buffer)) + for i in range(self.records_per_buffer): + i0 = i * self.number_of_channels * self.samples_per_record + i1 = i0 + self.number_of_channels * self.samples_per_record + recordA[:, i] = (self.buffer[i0:i1:self.number_of_channels] / + self.buffers_per_acquisition) + + # return averaged chan A data (records) + magA, phaseA = self.fit(recordA) + + # same for B + # if self.chan_b: + # recordB = np.zeros( + # (self.samples_per_record, self.records_per_buffer)) + # for i in self.records_per_buffer: + # recordB[i, :] = self.buffer[1:full_rec_length:step] / averaging + # magB, phaseB = self.fit(recordB) + + # return data (samples * records) + return magA, phaseA + + def fit(self, rec): + # center rec around 0 + rec = rec - np.mean(rec) + + # multiply with software wave + re_wave = np.multiply(rec, self.cos_mat) + im_wave = np.multiply(rec, self.sin_mat) + cutoff = self.demodulation_frequency + numtaps = 30 + axis = 0 + + # filter out double freq component to obtian constant term + if self.filter == 0: + RePart = self.filter_win(re_wave, numtaps, cutoff, axis=axis) + ImPart = self.filter_win(im_wave, numtaps, cutoff, axis=axis) + elif self.filter == 1: + RePart = self.filter_hamming(re_wave, numtaps, cutoff, axis=axis) + ImPart = self.filter_hamming(im_wave, numtaps, cutoff, axis=axis) + elif self.filter == 2: + RePart = self.filter_ls(re_wave, numtaps, cutoff, axis, axis=axis) + ImPart = self.filter_ls(im_wave, numtaps, cutoff, axis, axis=axis) + + # convert to magnitude and phase data + # data returned is (samples * records) + complex_num = RePart + ImPart * 1j + mag = 2 * abs(complex_num) + phase = np.angle(complex_num, deg=True) + + return mag, phase + + def filter_hamming(self, rec, numtaps, cutoff, axis=-1): + sample_rate = self.sample_rate + nyq_rate = sample_rate / 2. + fir_coef = signal.firwin(numtaps, + cutoff / nyq_rate, + window="hamming") + filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec, axis=axis) + return filtered_rec + + def filter_win(self, rec, numtaps, cutoff, axis=-1): + sample_rate = self.sample_rate + nyq_rate = sample_rate / 2. + fir_coef = signal.firwin(numtaps, + cutoff / nyq_rate) + filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec, axis=axis) + return filtered_rec + + def filter_ls(self, rec, numtaps, cutoff, axis=-1): + sample_rate = self.sample_rate + nyq_rate = sample_rate / 2. + bands = [0, cutoff / nyq_rate, cutoff / nyq_rate, 1] + desired = [1, 1, 0, 0] + fir_coef = signal.firls(numtaps, + bands, + desired, + nyq=nyq_rate) + filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec, axis=axis) + return filtered_rec From 05eba59838a0a8add3f14856abb26b6c8efdabf6 Mon Sep 17 00:00:00 2001 From: Natalie Pearson Date: Thu, 12 Jan 2017 15:57:11 +0100 Subject: [PATCH 077/180] tidy up a bit and move demof filter halpers to own folder --- .../Qcodes example with Alazar ATS9360.ipynb | 147 +++++++++++------- qcodes/instrument_drivers/AlazarTech/ATS.py | 48 +++--- .../instrument_drivers/AlazarTech/ATS9360.py | 1 + .../AlazarTech/acq_helpers.py | 34 ++++ .../AlazarTech/basic_controller.py | 50 +++--- .../AlazarTech/samp_controller.py | 16 +- qcodes/utils/helpers.py | 33 ---- 7 files changed, 180 insertions(+), 149 deletions(-) create mode 100644 qcodes/instrument_drivers/AlazarTech/acq_helpers.py diff --git a/docs/examples/Qcodes example with Alazar ATS9360.ipynb b/docs/examples/Qcodes example with Alazar ATS9360.ipynb index 581171d9681c..9366165c2a92 100644 --- a/docs/examples/Qcodes example with Alazar ATS9360.ipynb +++ b/docs/examples/Qcodes example with Alazar ATS9360.ipynb @@ -370,7 +370,8 @@ "import qcodes as qc\n", "import qcodes.instrument.parameter as parameter\n", "import qcodes.instrument_drivers.AlazarTech.ATS9360 as ATSdriver\n", - "import qcodes.instrument_drivers.AlazarTech.ATS_acquisition_controllers as ats_contr\n", + "import qcodes.instrument_drivers.AlazarTech.basic_controller as basic_aqc_contr\n", + "import qcodes.instrument_drivers.AlazarTech.samp_controller as samp_acq_contr\n", "\n", "qc.halt_bg()" ] @@ -420,10 +421,53 @@ } ], "source": [ - "# Create the ATS9870 instrument on the new server \"alazar_server\"\n", - "ats_inst = ATSdriver.AlazarTech_ATS9360(name='Alazar1', server_name=\"alazar_server\")\n", + "# Create the ATS9360 instrument\n", + "alazar = ATSdriver.AlazarTech_ATS9360(name='Alazar')\n", "# Print all information about this Alazar card\n", - "ats_inst.get_idn()" + "alazar.get_idn()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Configure all settings in the Alazar card\n", + "alazar.config(clock_source='EXTERNAL_CLOCK_10MHz_REF',\n", + " sample_rate='10MHZ_REF_500MSPS',\n", + " clock_edge='CLOCK_EDGE_RISING',\n", + " decimation=1,\n", + " coupling=['DC','DC'],\n", + " channel_range=[.4,.4],\n", + " impedance=[50,50],\n", + " trigger_operation='TRIG_ENGINE_OP_J',\n", + " trigger_engine1='TRIG_ENGINE_J',\n", + " trigger_source1='EXTERNAL',\n", + " trigger_slope1='TRIG_SLOPE_POSITIVE',\n", + " trigger_level1=140,\n", + " trigger_engine2='TRIG_ENGINE_K',\n", + " trigger_source2='DISABLE',\n", + " trigger_slope2='TRIG_SLOPE_POSITIVE',\n", + " trigger_level2=128,\n", + " external_trigger_coupling='DC',\n", + " external_trigger_range='ETR_2V5',\n", + " trigger_delay=0,\n", + " timeout_ticks=0,\n", + " aux_io_mode='AUX_IN_AUXILIARY', # AUX_IN_TRIGGER_ENABLE for seq mode on\n", + " aux_io_param='NONE' # TRIG_SLOPE_POSITIVE for seq mode on\n", + " )" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Basic Acquisition\n", + "\n", + "Pulls the raw data the alazar acquires averaged over number of records buffers." ] }, { @@ -443,45 +487,10 @@ } ], "source": [ - "import qcodes.instrument_drivers.AlazarTech.basic_controller as basic_contr\n", - "\n", - "basic_acquisition_controller = basic_contr.Basic_Acquisition_Controller(name='basic_acquisition_controller', \n", - " alazar_name='Alazar1', \n", - " server_name=\"alazar_server\")" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "# Configure all settings in the Alazar card\n", - "ats_inst.config(clock_source='EXTERNAL_CLOCK_10MHz_REF',\n", - " sample_rate='10MHZ_REF_500MSPS',\n", - " clock_edge='CLOCK_EDGE_RISING',\n", - " decimation=1,\n", - " coupling=['DC','DC'],\n", - " channel_range=[.4,.4],\n", - " impedance=[50,50],\n", - " trigger_operation='TRIG_ENGINE_OP_J',\n", - " trigger_engine1='TRIG_ENGINE_J',\n", - " trigger_source1='EXTERNAL',\n", - " trigger_slope1='TRIG_SLOPE_POSITIVE',\n", - " trigger_level1=140,\n", - " trigger_engine2='TRIG_ENGINE_K',\n", - " trigger_source2='DISABLE',\n", - " trigger_slope2='TRIG_SLOPE_POSITIVE',\n", - " trigger_level2=128,\n", - " external_trigger_coupling='DC',\n", - " external_trigger_range='ETR_2V5',\n", - " trigger_delay=0,\n", - " timeout_ticks=0,\n", - " aux_io_mode='AUX_IN_AUXILIARY', \n", - " aux_io_param='NONE'\n", - ")" + "# Create the acquisition controller which will take care of the data handling and tell it which \n", + "# alazar instrument to talk to.\n", + "basic_acq_controller = basic_aqc_contr.Basic_Acquisition_Controller(name='basic_acq_controller', \n", + " alazar_name='Alazar')" ] }, { @@ -492,12 +501,13 @@ }, "outputs": [], "source": [ - "basic_acquisition_controller.update_acquisitionkwargs(#mode='NPT',\n", - " samples_per_record=1024,\n", - " records_per_buffer=1,\n", - " buffers_per_acquisition=1,\n", - " allocated_buffers=1,\n", - ")" + "# Configure settings in the controller to be used in an acquisition\n", + "# nb this must be done before the first acquisition \n", + "basic_acq_controller.update_acquisition_kwargs(samples_per_record=1024,\n", + " records_per_buffer=1,\n", + " buffers_per_acquisition=1,\n", + " allocated_buffers=1\n", + " )" ] }, { @@ -1285,10 +1295,24 @@ } ], "source": [ - "data1 = basic_acquisition_controller.acquisition()\n", + "# Pull data from the card by calling get of the controllers acquisition parameter\n", + "data1 = basic_acq_controller.acquisition()\n", "qc.Matplot(data1[0])" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Do this in as measurement (effactively the same but saves the data)\n", + "data2 = qc.Measure(basic_acq_controller.acquisition)\n", + "qc.MatPlot(data2)" + ] + }, { "cell_type": "code", "execution_count": 10, @@ -1325,10 +1349,20 @@ "source": [ "# Finally show that this instrument also works within a loop\n", "dummy = parameter.ManualParameter(name=\"dummy\")\n", - "data2 = qc.Loop(dummy[0:5:1]).each(basic_acquisition_controller.acquisition).run(name='AlazarTest')\n", + "\n", + "data3 = qc.Loop(dummy[0:5:1]).each(basic_acq_controller.acquisition).run(name='AlazarTest')\n", "qc.QtPlot(data2.basic_acquisition_controller_A )" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Samples Acquisition\n", + "\n", + "This is the same as above except that it does some demodulation at the freqiencies specified" + ] + }, { "cell_type": "code", "execution_count": 19, @@ -1346,12 +1380,9 @@ } ], "source": [ - "import qcodes.instrument_drivers.AlazarTech.samp_controller as sample_controller\n", - "\n", - "samp_cont = sample_controller.HD_Samples_Controller(name='samples_controller', \n", - " alazar_name='Alazar1', \n", - " demod_freq = 5e6,\n", - " server_name=\"alazar_server\")" + "samp_acq_controller = samp_acq_contr.HD_Samples_Controller(name='samp_acq_controller', \n", + " alazar_name='Alazar1', \n", + " demod_freq = 5e6)" ] }, { @@ -3247,7 +3278,7 @@ }, "widgets": { "state": {}, - "version": "1.0.0" + "version": "1.1.2" } }, "nbformat": 4, diff --git a/qcodes/instrument_drivers/AlazarTech/ATS.py b/qcodes/instrument_drivers/AlazarTech/ATS.py index 4cff51bea787..c689d50693dc 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS.py @@ -17,8 +17,6 @@ # acquisition that would overflow the board if measurement is not stopped # quickly enough. can this be solved by not reposting the buffers? -# TODO(nataliejpg) fix get_damples function which I have broken for ATS9360 - class AlazarTech_ATS(Instrument): """ @@ -261,7 +259,7 @@ def get_idn(self): self._ATS_dll.AlazarGetBoardKind(self._handle)] max_s, bps = self._get_channel_info(self._handle) - + major = np.array([0], dtype=np.uint8) minor = np.array([0], dtype=np.uint8) revision = np.array([0], dtype=np.uint8) @@ -269,7 +267,7 @@ def get_idn(self): self._handle, major.ctypes.data, minor.ctypes.data) - cpld_ver = str(major[0])+"."+str(minor[0]) + cpld_ver = str(major[0]) + "." + str(minor[0]) self._call_dll('AlazarGetDriverVersion', major.ctypes.data, @@ -304,7 +302,7 @@ def get_idn(self): # about the encoding of the link speed self._call_dll('AlazarQueryCapability', self._handle, 0x10000030, 0, value.ctypes.data) - pcie_link_speed = str(value[0]*2.5/10)+"GB/s" + pcie_link_speed = str(value[0] * 2.5 / 10) + "GB/s" self._call_dll('AlazarQueryCapability', self._handle, 0x10000031, 0, value.ctypes.data) pcie_link_width = str(value[0]) @@ -570,12 +568,9 @@ def acquire(self, mode=None, samples_per_record=None, # bytes per sample max_s, bps = self._get_channel_info(self._handle) bytes_per_sample = (bps + 7) // 8 - #print("bytes per sample "+str(bytes_per_sample)) # bytes per record bytes_per_record = bytes_per_sample * samples_per_record - #print("samples_per_record is "+str(samples_per_record)) - #print("bytes per record is "+str(bytes_per_record)) # channels if self.channel_selection._get_byte() == 3: @@ -584,7 +579,8 @@ def acquire(self, mode=None, samples_per_record=None, number_of_channels = 1 # bytes per buffer - bytes_per_buffer = bytes_per_record * records_per_buffer * number_of_channels + bytes_per_buffer = (bytes_per_record * + records_per_buffer * number_of_channels) # create buffers for acquisition # TODO(nataliejpg) should this be > 1 (as intuitive) or > 8 as in alazar sample code? @@ -592,18 +588,13 @@ def acquire(self, mode=None, samples_per_record=None, if bytes_per_sample > 1: sample_type = ctypes.c_uint16 - # TODO(nataliejpg) get rid of all of thes print statements - #print("samples_per_buffer is "+str(samples_per_buffer)) - #print("bytes_per_buffer is "+str(bytes_per_buffer)) - #print("records_per_buffer is "+str(records_per_buffer)) - self.clear_buffers() # make sure that allocated_buffers <= buffers_per_acquisition if (self.allocated_buffers._get_byte() > self.buffers_per_acquisition._get_byte()): - print("'allocated_buffers' should be smaller than or equal to" - "'buffers_per_acquisition'. Defaulting 'allocated_buffers' to" - "" + str(self.buffers_per_acquisition._get_byte())) + logging.warn("'allocated_buffers' should be <= " + "'buffers_per_acquisition'. Defaulting 'allocated_buffers'" + " to " + str(self.buffers_per_acquisition._get_byte())) self.allocated_buffers._set( self.buffers_per_acquisition._get_byte()) @@ -617,13 +608,12 @@ def acquire(self, mode=None, samples_per_record=None, raise # post buffers to Alazar - print("made buffer list length "+str(len(self.buffer_list))) + print("made buffer list length " + str(len(self.buffer_list))) for buf in self.buffer_list: self._ATS_dll.AlazarPostAsyncBuffer.argtypes = [ctypes.c_uint32, ctypes.c_void_p, ctypes.c_uint32] self._call_dll('AlazarPostAsyncBuffer', self._handle, buf.addr, buf.size_bytes) self.allocated_buffers._set_updated() - #print("completed AlazarPostAsyncBuffer") # -----start capture here----- acquisition_controller.pre_start_capture() @@ -690,14 +680,17 @@ def acquire(self, mode=None, samples_per_record=None, if transfer_time_sec > 0: buffers_per_sec = buffers_completed / transfer_time_sec bytes_per_sec = bytes_transferred / transfer_time_sec - records_per_sec = records_per_buffer * buffers_completed / transfer_time_sec - print("Captured %d buffers (%f buffers per sec)" % - (buffers_completed, buffers_per_sec)) - print("Captured %d records (%f records per sec)" % - (records_per_buffer * buffers_completed, records_per_sec)) - print("Transferred %d bytes (%f bytes per sec)" % - (bytes_transferred, bytes_per_sec)) - + records_per_sec = (records_per_buffer * + buffers_completed / transfer_time_sec) + logging.info("Captured %d buffers (%f buffers per sec)" % + (buffers_completed, buffers_per_sec)) + logging.info("Captured %d records (%f records per sec)" % + (records_per_buffer * buffers_completed, records_per_sec)) + logging.info("Transferred %d bytes (%f bytes per sec)" % + (bytes_transferred, bytes_per_sec)) + + + # return result return acquisition_controller.post_acquire() @@ -798,7 +791,6 @@ def get_sample_rate(self): rate = self.sample_rate.get() if rate == '1GHz_REFERENCE_CLOCK': rate = 1e9 - # TODO(nataliejpg) this breaks for ATS9360 because of changes to rate decimation = self.decimation.get() if decimation > 0: diff --git a/qcodes/instrument_drivers/AlazarTech/ATS9360.py b/qcodes/instrument_drivers/AlazarTech/ATS9360.py index 4fe1add7ee05..1ac2c3cbde5f 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS9360.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS9360.py @@ -245,6 +245,7 @@ def __init__(self, name, **kwargs): unit=None, value=4, vals=validators.Ints(min_value=0)) + self.add_parameter(name='buffer_timeout', parameter_class=AlazarParameter, label='Buffer Timeout', diff --git a/qcodes/instrument_drivers/AlazarTech/acq_helpers.py b/qcodes/instrument_drivers/AlazarTech/acq_helpers.py new file mode 100644 index 000000000000..572bf451ca0d --- /dev/null +++ b/qcodes/instrument_drivers/AlazarTech/acq_helpers.py @@ -0,0 +1,34 @@ +from scipy import signal + + +def filter_win(rec, cutoff, sample_rate, numtaps, axis=-1): + """ + low pass filter, returns filtered signal using FIR window + filter + + inputs: + record to filter + cutoff frequency + sampling rate + number of frequency comppnents to use in the filer + axis of record to apply filter along + """ + nyq_rate = sample_rate / 2. + fir_coef = signal.firwin(numtaps, cutoff / nyq_rate) + filtered_rec = signal.lfilter(fir_coef, 1.0, rec, axis=axis) + return filtered_rec + + +def filter_ls(rec, cutoff, sample_rate, numtaps, axis=-1): + """ + low pass filter, returns filtered signal using FIR + least squared filter + + inputs: + record to filter + cutoff frequency + sampling rate + number of frequency comppnents to use in the filer + axis of record to apply filter along + """ + raise NotImplementedError diff --git a/qcodes/instrument_drivers/AlazarTech/basic_controller.py b/qcodes/instrument_drivers/AlazarTech/basic_controller.py index 025e3b97bd9f..2e77699cc769 100644 --- a/qcodes/instrument_drivers/AlazarTech/basic_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/basic_controller.py @@ -18,23 +18,27 @@ def __init__(self, name, instrument): self._instrument = instrument self.acquisitionkwargs = {} self.names = ('A', 'B') - self.units = ('', '') - self.setpoint_names = (('sample_num',), ('sample_num',)) - self.setpoints = ((1,), (1,)) - self.shapes = ((1,), (1,)) - - def update_acquisition_kwargs(self, **kwargs): - # needed to update config of the software parameter on sweep change - # freq setpoints tuple as needs to be hashable for look up - if 'samples_per_record' in kwargs: - npts = kwargs['samples_per_record'] - n = tuple(np.arange(npts)) - self.setpoints = ((n,), (n,)) - self.shapes = ((npts,), (npts,)) - else: - raise ValueError('samples_per_record must be specified') - # updates dict to be used in acquisition get call - self.acquisitionkwargs.update(**kwargs) + # self.units = ('', '') + # self.setpoint_names = (('sample_num',), ('sample_num',)) + # self.setpoints = ((1,), (1,)) + # self.shapes = ((1,), (1,)) + + # def update_acquisition_kwargs(self, **kwargs): + # npts = kwargs['samples_per_record'] + # self.shapes = ((npts,), (npts,)) + # self.acquisitionkwargs.update(**kwargs) + + # # needed to update config of the software parameter on sweep change + # # freq setpoints tuple as needs to be hashable for look up + # if 'samples_per_record' in kwargs: + # npts = kwargs['samples_per_record'] + # # n = tuple(np.arange(npts)) + # # self.setpoints = ((n,), (n,)) + # self.shapes = ((npts,), (npts,)) + # else: + # raise ValueError('samples_per_record must be specified') + # # updates dict to be used in acquisition get call + # self.acquisitionkwargs.update(**kwargs) def get(self): recordA, recordB = self._instrument._get_alazar().acquire( @@ -55,7 +59,6 @@ class Basic_Acquisition_Controller(AcquisitionController): can communicate with the Alazar **kwargs: kwargs are forwarded to the Instrument base class - TODO(nataliejpg) num of channels TODO(nataliejpg) make dtype general or get from alazar """ @@ -64,8 +67,8 @@ def __init__(self, name, alazar_name, **kwargs): self.records_per_buffer = 0 self.buffers_per_acquisition = 0 self.number_of_channels = 2 - self.buffer = None self.board_info = None + self.buffer = None # make a call to the parent class and by extension, # create the parameter structure of this class super().__init__(name, alazar_name, **kwargs) @@ -73,14 +76,16 @@ def __init__(self, name, alazar_name, **kwargs): self.add_parameter(name='acquisition', parameter_class=SampleSweep) - def update_acquisitionkwargs(self, **kwargs): + def update_acquisition_kwargs(self, **kwargs): """ This method must be used to update the kwargs used for the acquisition with the alazar_driver.acquire :param kwargs: :return: """ - self.acquisition.update_acquisition_kwargs(**kwargs) + npts = kwargs['samples_per_record'] + self.acquisition.shapes = ((npts,), (npts,)) + self.acquisition.acquisition_kwargs.update(**kwargs) def pre_start_capture(self): """ @@ -126,6 +131,7 @@ def post_acquire(self): # break buffer up into records, averages over them and returns samples records_per_acquisition = (self.buffers_per_acquisition * self.records_per_buffer) + recA = np.zeros(self.samples_per_record) for i in range(self.records_per_buffer): i0 = (i * self.samples_per_record * self.number_of_channels) @@ -146,7 +152,7 @@ def post_acquire(self): volt_rec_B = sample_to_volt_u12(recordB, bps) else: logging.warning('sample to volt conversion does not exist for bps ' - '!= 12, raw samples centered on 0 returned') + '!= 12, raw samples centered on 0 and returned') volt_rec_A = recordA - np.mean(recordA) volt_rec_B = recordB - np.mean(recordB) diff --git a/qcodes/instrument_drivers/AlazarTech/samp_controller.py b/qcodes/instrument_drivers/AlazarTech/samp_controller.py index 5919e04d48ac..cf4d8df4c9e6 100644 --- a/qcodes/instrument_drivers/AlazarTech/samp_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/samp_controller.py @@ -2,9 +2,9 @@ from .ATS import AcquisitionController import numpy as np from qcodes import Parameter -from qcodes.utils.helpers import filter_win, filter_ls +from qcodes.instrument_drivers.AlazarTech.acq_helpers import filter_win, filter_ls from qcodes.instrument.parameter import ManualParameter -from qcodes.utils import validators +# from qcodes.utils import validators class SamplesParam(Parameter): @@ -26,12 +26,12 @@ def __init__(self, name, instrument): self.setpoint_names = (('acq_time (s)',), ('acq_time (s)',)) self.setpoints = ((1,), (1,)) self.shapes = ((1,), (1,)) - + def update_sweep(self, start, stop, npts): n = tuple(np.linspace(start, stop, num=npts)) self.setpoints = ((n,), (n,)) self.shapes = ((npts,), (npts,)) - + def get(self): mag, phase = self._instrument._get_alazar().acquire( acquisition_controller=self._instrument, @@ -112,20 +112,20 @@ def update_acquisition_settings(self, **kwargs): self.samples_per_record = kwargs['samples_per_record'] self.sample_rate = alazar.get_sample_rate() time_available = self.samples_per_record / self.sample_rate - + if self.int_delay() is None: samp_delay = self.numtaps - 1 self.int_delay(samp_delay / self.sample_rate) else: self.check_delay(time_available) - + time_available -= self.int_delay() - + if self.int_time() is None: self.int_time(time_available) else: self.check_time(time_available) - + start = self.int_delay() stop = self.int_delay() + self.int_time() npts = int(self.int_time() * self.sample_rate) diff --git a/qcodes/utils/helpers.py b/qcodes/utils/helpers.py index e50bde4e7ff5..e0cfe85a2dcc 100644 --- a/qcodes/utils/helpers.py +++ b/qcodes/utils/helpers.py @@ -10,7 +10,6 @@ from copy import deepcopy import numpy as np -from scipy import signal _tprint_times = {} @@ -423,35 +422,3 @@ def compare_dictionaries(dict_1, dict_2, dicts_equal = False return dicts_equal, dict_differences - -def filter_win(rec, cutoff, sample_rate, numtaps, axis=-1): - """ - low pass filter, returns filtered signal using FIR window - filter - - inputs: - record to filter - cutoff frequency - sampling rate - number of frequency comppnents to use in the filer - axis of record to apply filter along - """ - nyq_rate = sample_rate / 2. - fir_coef = signal.firwin(numtaps, cutoff / nyq_rate) - filtered_rec = signal.lfilter(fir_coef, 1.0, rec, axis=axis) - return filtered_rec - - -def filter_ls(rec, cutoff, sample_rate, numtaps, axis=-1): - """ - low pass filter, returns filtered signal using FIR - least squared filter - - inputs: - record to filter - cutoff frequency - sampling rate - number of frequency comppnents to use in the filer - axis of record to apply filter along - """ - raise NotImplementedError From 8ea8d1cf518146d08a2e14dab7937a169fea34b1 Mon Sep 17 00:00:00 2001 From: nataliejpg Date: Fri, 13 Jan 2017 11:10:26 +0100 Subject: [PATCH 078/180] testing basic controller --- .../Qcodes example with Alazar ATS9360.ipynb | 1204 +---------------- .../AlazarTech/basic_controller.py | 6 +- 2 files changed, 65 insertions(+), 1145 deletions(-) diff --git a/docs/examples/Qcodes example with Alazar ATS9360.ipynb b/docs/examples/Qcodes example with Alazar ATS9360.ipynb index 9366165c2a92..f9ebe09d2e73 100644 --- a/docs/examples/Qcodes example with Alazar ATS9360.ipynb +++ b/docs/examples/Qcodes example with Alazar ATS9360.ipynb @@ -14,356 +14,12 @@ "collapsed": false }, "outputs": [ - { - "data": { - "application/javascript": [ - "/*\r\n", - " * Qcodes Jupyter/IPython widgets\r\n", - " */\r\n", - "require([\r\n", - " 'nbextensions/widgets/widgets/js/widget',\r\n", - " 'nbextensions/widgets/widgets/js/manager'\r\n", - "], function (widget, manager) {\r\n", - "\r\n", - " var UpdateView = widget.DOMWidgetView.extend({\r\n", - " render: function() {\r\n", - " window.MYWIDGET = this;\r\n", - " this._interval = 0;\r\n", - " this.update();\r\n", - " },\r\n", - " update: function() {\r\n", - " this.display(this.model.get('_message'));\r\n", - " this.setInterval();\r\n", - " },\r\n", - " display: function(message) {\r\n", - " /*\r\n", - " * display method: override this for custom display logic\r\n", - " */\r\n", - " this.el.innerHTML = message;\r\n", - " },\r\n", - " remove: function() {\r\n", - " clearInterval(this._updater);\r\n", - " },\r\n", - " setInterval: function(newInterval) {\r\n", - " var me = this;\r\n", - " if(newInterval===undefined) newInterval = me.model.get('interval');\r\n", - " if(newInterval===me._interval) return;\r\n", - "\r\n", - " me._interval = newInterval;\r\n", - "\r\n", - " if(me._updater) clearInterval(me._updater);\r\n", - "\r\n", - " if(me._interval) {\r\n", - " me._updater = setInterval(function() {\r\n", - " me.send({myupdate: true});\r\n", - " if(!me.model.comm_live) {\r\n", - " console.log('missing comm, canceling widget updates', me);\r\n", - " clearInterval(me._updater);\r\n", - " }\r\n", - " }, me._interval * 1000);\r\n", - " }\r\n", - " }\r\n", - " });\r\n", - " manager.WidgetManager.register_widget_view('UpdateView', UpdateView);\r\n", - "\r\n", - " var HiddenUpdateView = UpdateView.extend({\r\n", - " display: function(message) {\r\n", - " this.$el.hide();\r\n", - " }\r\n", - " });\r\n", - " manager.WidgetManager.register_widget_view('HiddenUpdateView', HiddenUpdateView);\r\n", - "\r\n", - " var SubprocessView = UpdateView.extend({\r\n", - " render: function() {\r\n", - " var me = this;\r\n", - " me._interval = 0;\r\n", - " me._minimize = '';\r\n", - " me._restore = '';\r\n", - "\r\n", - " // max lines of output to show\r\n", - " me.maxOutputLength = 500;\r\n", - "\r\n", - " // in case there is already an outputView present,\r\n", - " // like from before restarting the kernel\r\n", - " $('.qcodes-output-view').not(me.$el).remove();\r\n", - "\r\n", - " me.$el\r\n", - " .addClass('qcodes-output-view')\r\n", - " .attr('qcodes-state', 'docked')\r\n", - " .html(\r\n", - " '
' +\r\n", - " '
' +\r\n", - " '' +\r\n", - " '' +\r\n", - " '' +\r\n", - " '' +\r\n", - " '' +\r\n", - " '' +\r\n", - " '
' +\r\n", - " '
'\r\n",
-       "                );\r\n",
-       "\r\n",
-       "            me.clearButton = me.$el.find('.qcodes-clear-output');\r\n",
-       "            me.minButton = me.$el.find('.qcodes-minimize');\r\n",
-       "            me.outputArea = me.$el.find('pre');\r\n",
-       "            me.subprocessList = me.$el.find('.qcodes-process-list');\r\n",
-       "            me.abortButton = me.$el.find('.qcodes-abort-loop');\r\n",
-       "            me.processLinesButton = me.$el.find('.qcodes-processlines')\r\n",
-       "\r\n",
-       "            me.outputLines = [];\r\n",
-       "\r\n",
-       "            me.clearButton.click(function() {\r\n",
-       "                me.outputArea.html('');\r\n",
-       "                me.clearButton.addClass('disabled');\r\n",
-       "            });\r\n",
-       "\r\n",
-       "            me.abortButton.click(function() {\r\n",
-       "                me.send({abort: true});\r\n",
-       "            });\r\n",
-       "\r\n",
-       "            me.processLinesButton.click(function() {\r\n",
-       "                // toggle multiline process list display\r\n",
-       "                me.subprocessesMultiline = !me.subprocessesMultiline;\r\n",
-       "                me.showSubprocesses();\r\n",
-       "            });\r\n",
-       "\r\n",
-       "            me.$el.find('.js-state').click(function() {\r\n",
-       "                var state = this.className.substr(this.className.indexOf('qcodes'))\r\n",
-       "                        .split('-')[1].split(' ')[0];\r\n",
-       "                me.model.set('_state', state);\r\n",
-       "            });\r\n",
-       "\r\n",
-       "            $(window)\r\n",
-       "                .off('resize.qcodes')\r\n",
-       "                .on('resize.qcodes', function() {me.clipBounds();});\r\n",
-       "\r\n",
-       "            me.update();\r\n",
-       "        },\r\n",
-       "\r\n",
-       "        updateState: function() {\r\n",
-       "            var me = this,\r\n",
-       "                oldState = me.$el.attr('qcodes-state'),\r\n",
-       "                state = me.model.get('_state');\r\n",
-       "\r\n",
-       "            if(state === oldState) return;\r\n",
-       "\r\n",
-       "            setTimeout(function() {\r\n",
-       "                // not sure why I can't pop it out of the widgetarea in render, but it seems that\r\n",
-       "                // some other bit of code resets the parent after render if I do it there.\r\n",
-       "                // To be safe, just do it on every state click.\r\n",
-       "                me.$el.appendTo('body');\r\n",
-       "\r\n",
-       "                if(oldState === 'floated') {\r\n",
-       "                    console.log('here');\r\n",
-       "                    me.$el.draggable('destroy').css({left:'', top: ''});\r\n",
-       "                }\r\n",
-       "\r\n",
-       "                me.$el.attr('qcodes-state', state);\r\n",
-       "\r\n",
-       "                if(state === 'floated') {\r\n",
-       "                    me.$el\r\n",
-       "                        .draggable({stop: function() { me.clipBounds(); }})\r\n",
-       "                        .css({\r\n",
-       "                            left: window.innerWidth - me.$el.width() - 15,\r\n",
-       "                            top: window.innerHeight - me.$el.height() - 10\r\n",
-       "                        });\r\n",
-       "                }\r\n",
-       "\r\n",
-       "                // any previous highlighting is now moot\r\n",
-       "                me.$el.removeClass('qcodes-highlight');\r\n",
-       "            }, 0);\r\n",
-       "\r\n",
-       "        },\r\n",
-       "\r\n",
-       "        clipBounds: function() {\r\n",
-       "            var me = this;\r\n",
-       "            if(me.$el.attr('qcodes-state') === 'floated') {\r\n",
-       "                var bounds = me.$el[0].getBoundingClientRect(),\r\n",
-       "                    minVis = 40,\r\n",
-       "                    maxLeft = window.innerWidth - minVis,\r\n",
-       "                    minLeft = minVis - bounds.width,\r\n",
-       "                    maxTop = window.innerHeight - minVis;\r\n",
-       "\r\n",
-       "                if(bounds.left > maxLeft) me.$el.css('left', maxLeft);\r\n",
-       "                else if(bounds.left < minLeft) me.$el.css('left', minLeft);\r\n",
-       "\r\n",
-       "                if(bounds.top > maxTop) me.$el.css('top', maxTop);\r\n",
-       "                else if(bounds.top < 0) me.$el.css('top', 0);\r\n",
-       "            }\r\n",
-       "        },\r\n",
-       "\r\n",
-       "        display: function(message) {\r\n",
-       "            var me = this;\r\n",
-       "            if(message) {\r\n",
-       "                var initialScroll = me.outputArea.scrollTop();\r\n",
-       "                me.outputArea.scrollTop(me.outputArea.prop('scrollHeight'));\r\n",
-       "                var scrollBottom = me.outputArea.scrollTop();\r\n",
-       "\r\n",
-       "                if(me.$el.attr('qcodes-state') === 'minimized') {\r\n",
-       "                    // if we add text and the box is minimized, highlight the\r\n",
-       "                    // title bar to alert the user that there are new messages.\r\n",
-       "                    // remove then add the class, so we get the animation again\r\n",
-       "                    // if it's already highlighted\r\n",
-       "                    me.$el.removeClass('qcodes-highlight');\r\n",
-       "                    setTimeout(function(){\r\n",
-       "                        me.$el.addClass('qcodes-highlight');\r\n",
-       "                    }, 0);\r\n",
-       "                }\r\n",
-       "\r\n",
-       "                var newLines = message.split('\\n'),\r\n",
-       "                    out = me.outputLines,\r\n",
-       "                    outLen = out.length;\r\n",
-       "                if(outLen) out[outLen - 1] += newLines[0];\r\n",
-       "                else out.push(newLines[0]);\r\n",
-       "\r\n",
-       "                for(var i = 1; i < newLines.length; i++) {\r\n",
-       "                    out.push(newLines[i]);\r\n",
-       "                }\r\n",
-       "\r\n",
-       "                if(out.length > me.maxOutputLength) {\r\n",
-       "                    out.splice(0, out.length - me.maxOutputLength + 1,\r\n",
-       "                        '<<< Output clipped >>>');\r\n",
-       "                }\r\n",
-       "\r\n",
-       "                me.outputArea.text(out.join('\\n'));\r\n",
-       "                me.clearButton.removeClass('disabled');\r\n",
-       "\r\n",
-       "                // if we were scrolled to the bottom initially, make sure\r\n",
-       "                // we stay that way.\r\n",
-       "                me.outputArea.scrollTop(initialScroll === scrollBottom ?\r\n",
-       "                    me.outputArea.prop('scrollHeight') : initialScroll);\r\n",
-       "            }\r\n",
-       "\r\n",
-       "            me.showSubprocesses();\r\n",
-       "            me.updateState();\r\n",
-       "        },\r\n",
-       "\r\n",
-       "        showSubprocesses: function() {\r\n",
-       "            var me = this,\r\n",
-       "                replacer = me.subprocessesMultiline ? '
' : ', ',\r\n", - " processes = (me.model.get('_processes') || '')\r\n", - " .replace(/\\n/g, '>' + replacer + '<');\r\n", - "\r\n", - " if(processes) processes = '<' + processes + '>';\r\n", - " else processes = 'No subprocesses';\r\n", - "\r\n", - " me.abortButton.toggleClass('disabled', processes.indexOf('Measurement')===-1);\r\n", - "\r\n", - " me.subprocessList.html(processes);\r\n", - " }\r\n", - " });\r\n", - " manager.WidgetManager.register_widget_view('SubprocessView', SubprocessView);\r\n", - "});\r\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, { "name": "stdout", "output_type": "stream", "text": [ "No loop running\n" ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "a:\\qcodes\\qcodes\\process\\helpers.py:27: UserWarning: Multiprocessing is in beta, use at own risk\n", - " warnings.warn(\"Multiprocessing is in beta, use at own risk\", UserWarning)\n" - ] } ], "source": [ @@ -385,28 +41,22 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "a:\\qcodes\\qcodes\\instrument\\metaclass.py:37: UserWarning: Multiprocessing is in beta, use at own risk\n", - " UserWarning)\n" - ] - }, { "data": { "text/plain": [ "{'CPLD_version': '25.16',\n", " 'SDK_version': '5.9.25',\n", " 'asopc_type': '1712554848',\n", + " 'bits_per_sample': 12,\n", " 'driver_version': '5.9.25',\n", " 'firmware': None,\n", " 'latest_cal_date': '13-11-15',\n", + " 'max_samples': 4294967294,\n", " 'memory_size': '4294967294',\n", " 'model': 'ATS9360',\n", " 'pcie_link_speed': '0.5GB/s',\n", @@ -415,7 +65,7 @@ " 'vendor': 'AlazarTech'}" ] }, - "execution_count": 3, + "execution_count": 2, "metadata": {}, "output_type": "execute_result" } @@ -429,7 +79,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 3, "metadata": { "collapsed": false }, @@ -437,7 +87,7 @@ "source": [ "# Configure all settings in the Alazar card\n", "alazar.config(clock_source='EXTERNAL_CLOCK_10MHz_REF',\n", - " sample_rate='10MHZ_REF_500MSPS',\n", + " sample_rate=500000000,\n", " clock_edge='CLOCK_EDGE_RISING',\n", " decimation=1,\n", " coupling=['DC','DC'],\n", @@ -476,16 +126,7 @@ "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "a:\\qcodes\\qcodes\\instrument\\metaclass.py:37: UserWarning: Multiprocessing is in beta, use at own risk\n", - " UserWarning)\n" - ] - } - ], + "outputs": [], "source": [ "# Create the acquisition controller which will take care of the data handling and tell it which \n", "# alazar instrument to talk to.\n", @@ -495,7 +136,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 5, "metadata": { "collapsed": false }, @@ -512,801 +153,78 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "buffers cleared\n", + "made buffer list length 1\n", + "Capturing 1 buffers.\n", + "buffer handled\n", + "buffers cleared\n", + "Capture completed in 0.386047 sec\n", + "post_acquire\n", + "(array([-0.0017094 , -0.0046398 , -0.00757021, ..., -0.00952381,\n", + " -0.00659341, -0.0026862 ]), array([ 0.0002442, 0.0031746, 0.001221 , ..., 0.0021978, -0.0007326,\n", + " 0.0041514]))\n" + ] + } + ], + "source": [ + "# Pull data from the card by calling get of the controllers acquisition parameter\n", + "data1 = basic_acq_controller.acquisition()\n", + "print(data1)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, "metadata": { "collapsed": false }, "outputs": [ { "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "window.mpl = {};\n", - "\n", - "mpl.get_websocket_type = function() {\n", - " if (typeof(WebSocket) !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof(MozWebSocket) !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert('Your browser does not have WebSocket support.' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.');\n", - " };\n", - "}\n", - "\n", - "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = (this.ws.binaryType != undefined);\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById(\"mpl-warnings\");\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent = (\n", - " \"This browser does not support binary websocket messages. \" +\n", - " \"Performance may be slow.\");\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = $('
');\n", - " this._root_extra_style(this.root)\n", - " this.root.attr('style', 'display: inline-block');\n", - "\n", - " $(parent_element).append(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", - " fig.send_message(\"send_image_mode\", {});\n", - " fig.send_message(\"refresh\", {});\n", - " }\n", - "\n", - " this.imageObj.onload = function() {\n", - " if (fig.image_mode == 'full') {\n", - " // Full images could contain transparency (where diff images\n", - " // almost always do), so we need to clear the canvas so that\n", - " // there is no ghosting.\n", - " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", - " }\n", - " fig.context.drawImage(fig.imageObj, 0, 0);\n", - " };\n", - "\n", - " this.imageObj.onunload = function() {\n", - " this.ws.close();\n", - " }\n", - "\n", - " this.ws.onmessage = this._make_on_message_function(this);\n", - "\n", - " this.ondownload = ondownload;\n", - "}\n", - "\n", - "mpl.figure.prototype._init_header = function() {\n", - " var titlebar = $(\n", - " '
');\n", - " var titletext = $(\n", - " '
');\n", - " titlebar.append(titletext)\n", - " this.root.append(titlebar);\n", - " this.header = titletext[0];\n", - "}\n", - "\n", - "\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._init_canvas = function() {\n", - " var fig = this;\n", - "\n", - " var canvas_div = $('
');\n", - "\n", - " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", - "\n", - " function canvas_keyboard_event(event) {\n", - " return fig.key_event(event, event['data']);\n", - " }\n", - "\n", - " canvas_div.keydown('key_press', canvas_keyboard_event);\n", - " canvas_div.keyup('key_release', canvas_keyboard_event);\n", - " this.canvas_div = canvas_div\n", - " this._canvas_extra_style(canvas_div)\n", - " this.root.append(canvas_div);\n", - "\n", - " var canvas = $('');\n", - " canvas.addClass('mpl-canvas');\n", - " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", - "\n", - " this.canvas = canvas[0];\n", - " this.context = canvas[0].getContext(\"2d\");\n", - "\n", - " var rubberband = $('');\n", - " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", - "\n", - " var pass_mouse_events = true;\n", - "\n", - " canvas_div.resizable({\n", - " start: function(event, ui) {\n", - " pass_mouse_events = false;\n", - " },\n", - " resize: function(event, ui) {\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " stop: function(event, ui) {\n", - " pass_mouse_events = true;\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " });\n", - "\n", - " function mouse_event_fn(event) {\n", - " if (pass_mouse_events)\n", - " return fig.mouse_event(event, event['data']);\n", - " }\n", - "\n", - " rubberband.mousedown('button_press', mouse_event_fn);\n", - " rubberband.mouseup('button_release', mouse_event_fn);\n", - " // Throttle sequential mouse events to 1 every 20ms.\n", - " rubberband.mousemove('motion_notify', mouse_event_fn);\n", - "\n", - " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", - " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", - "\n", - " canvas_div.on(\"wheel\", function (event) {\n", - " event = event.originalEvent;\n", - " event['data'] = 'scroll'\n", - " if (event.deltaY < 0) {\n", - " event.step = 1;\n", - " } else {\n", - " event.step = -1;\n", - " }\n", - " mouse_event_fn(event);\n", - " });\n", - "\n", - " canvas_div.append(canvas);\n", - " canvas_div.append(rubberband);\n", - "\n", - " this.rubberband = rubberband;\n", - " this.rubberband_canvas = rubberband[0];\n", - " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", - " this.rubberband_context.strokeStyle = \"#000000\";\n", - "\n", - " this._resize_canvas = function(width, height) {\n", - " // Keep the size of the canvas, canvas container, and rubber band\n", - " // canvas in synch.\n", - " canvas_div.css('width', width)\n", - " canvas_div.css('height', height)\n", - "\n", - " canvas.attr('width', width);\n", - " canvas.attr('height', height);\n", - "\n", - " rubberband.attr('width', width);\n", - " rubberband.attr('height', height);\n", - " }\n", - "\n", - " // Set the figure to an initial 600x600px, this will subsequently be updated\n", - " // upon first draw.\n", - " this._resize_canvas(600, 600);\n", - "\n", - " // Disable right mouse context menu.\n", - " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", - " return false;\n", - " });\n", - "\n", - " function set_focus () {\n", - " canvas.focus();\n", - " canvas_div.focus();\n", - " }\n", - "\n", - " window.setTimeout(set_focus, 100);\n", - "}\n", - "\n", - "mpl.figure.prototype._init_toolbar = function() {\n", - " var fig = this;\n", - "\n", - " var nav_element = $('
')\n", - " nav_element.attr('style', 'width: 100%');\n", - " this.root.append(nav_element);\n", - "\n", - " // Define a callback function for later on.\n", - " function toolbar_event(event) {\n", - " return fig.toolbar_button_onclick(event['data']);\n", - " }\n", - " function toolbar_mouse_event(event) {\n", - " return fig.toolbar_button_onmouseover(event['data']);\n", - " }\n", - "\n", - " for(var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " // put a spacer in here.\n", - " continue;\n", - " }\n", - " var button = $('');\n", - " button.click(method_name, toolbar_event);\n", - " button.mouseover(tooltip, toolbar_mouse_event);\n", - " nav_element.append(button);\n", - " }\n", - "\n", - " // Add the status bar.\n", - " var status_bar = $('');\n", - " nav_element.append(status_bar);\n", - " this.message = status_bar[0];\n", - "\n", - " // Add the close button to the window.\n", - " var buttongrp = $('
');\n", - " var button = $('');\n", - " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", - " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", - " buttongrp.append(button);\n", - " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", - " titlebar.prepend(buttongrp);\n", - "}\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(el){\n", - " var fig = this\n", - " el.on(\"remove\", function(){\n", - "\tfig.close_ws(fig, {});\n", - " });\n", - "}\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(el){\n", - " // this is important to make the div 'focusable\n", - " el.attr('tabindex', 0)\n", - " // reach out to IPython and tell the keyboard manager to turn it's self\n", - " // off when our div gets focus\n", - "\n", - " // location in version 3\n", - " if (IPython.notebook.keyboard_manager) {\n", - " IPython.notebook.keyboard_manager.register_events(el);\n", - " }\n", - " else {\n", - " // location in version 2\n", - " IPython.keyboard_manager.register_events(el);\n", - " }\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._key_event_extra = function(event, name) {\n", - " var manager = IPython.notebook.keyboard_manager;\n", - " if (!manager)\n", - " manager = IPython.keyboard_manager;\n", - "\n", - " // Check for shift+enter\n", - " if (event.shiftKey && event.which == 13) {\n", - " this.canvas_div.blur();\n", - " event.shiftKey = false;\n", - " // Send a \"J\" for go to next cell\n", - " event.which = 74;\n", - " event.keyCode = 74;\n", - " manager.command_mode();\n", - " manager.handle_keydown(event);\n", - " }\n", - "}\n", - "\n", - "mpl.figure.prototype.handle_save = function(fig, msg) {\n", - " fig.ondownload(fig, null);\n", - "}\n", - "\n", - "\n", - "mpl.find_output_cell = function(html_output) {\n", - " // Return the cell and output element which can be found *uniquely* in the notebook.\n", - " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", - " // IPython event is triggered only after the cells have been serialised, which for\n", - " // our purposes (turning an active figure into a static one), is too late.\n", - " var cells = IPython.notebook.get_cells();\n", - " var ncells = cells.length;\n", - " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", - " data = data.data;\n", - " }\n", - " if (data['text/html'] == html_output) {\n", - " return [cell, data, j];\n", - " }\n", - " }\n", - " }\n", - " }\n", - "}\n", - "\n", - "// Register the function which deals with the matplotlib target/channel.\n", - "// The kernel may be null if the page has been refreshed.\n", - "if (IPython.notebook.kernel != null) {\n", - " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", - "}\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" + "ename": "TypeError", + "evalue": "unsupported operand type(s) for *: 'NoneType' and 'float'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mdata3\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0msamp_acq_controller\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0macquisition\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0mqc\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mQtPlot\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mdata3\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[0;32ma:\\qcodes\\qcodes\\instrument\\parameter.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, *args)\u001b[0m\n\u001b[1;32m 264\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mlen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m==\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 265\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mhas_get\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m--> 266\u001b[0;31m \u001b[1;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mget\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 267\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 268\u001b[0m raise NoCommandError('no get cmd found in' +\n", + "\u001b[0;32ma:\\qcodes\\qcodes\\instrument_drivers\\AlazarTech\\samp.py\u001b[0m in \u001b[0;36mget\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 36\u001b[0m mag, phase = self._instrument._get_alazar().acquire(\n\u001b[1;32m 37\u001b[0m \u001b[0macquisition_controller\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_instrument\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m---> 38\u001b[0;31m **self.acquisition_kwargs)\n\u001b[0m\u001b[1;32m 39\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[0mmag\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mphase\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 40\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[0;32ma:\\qcodes\\qcodes\\instrument_drivers\\AlazarTech\\ATS.py\u001b[0m in \u001b[0;36macquire\u001b[0;34m(self, mode, samples_per_record, records_per_buffer, buffers_per_acquisition, channel_selection, transfer_offset, external_startcapture, enable_record_headers, alloc_buffers, fifo_only_streaming, interleave_samples, get_processed_data, allocated_buffers, buffer_timeout, acquisition_controller)\u001b[0m\n\u001b[1;32m 639\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 640\u001b[0m \u001b[1;31m# -----start capture here-----\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m--> 641\u001b[0;31m \u001b[0macquisition_controller\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpre_start_capture\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 642\u001b[0m \u001b[0mstart\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mtime\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mclock\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;31m# Keep track of when acquisition started\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 643\u001b[0m \u001b[1;31m# call the startcapture method\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[0;32ma:\\qcodes\\qcodes\\instrument_drivers\\AlazarTech\\samp.py\u001b[0m in \u001b[0;36mpre_start_capture\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 191\u001b[0m raise Exception('acq controller sample rate does not match instrument'\n\u001b[1;32m 192\u001b[0m 'value, most likely need to call update_acquisition_settings' ) \n\u001b[0;32m--> 193\u001b[0;31m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcheck_time_values\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 194\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 195\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mrecords_per_buffer\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0malazar\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mrecords_per_buffer\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mget\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[0;32ma:\\qcodes\\qcodes\\instrument_drivers\\AlazarTech\\samp.py\u001b[0m in \u001b[0;36mcheck_time_values\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 90\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 91\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mcheck_time_values\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m---> 92\u001b[0;31m \u001b[0moscilations_measured\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mint_time\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m*\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdemodulation_frequency\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 93\u001b[0m \u001b[0mtotal_time\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msamples_per_record\u001b[0m \u001b[1;33m/\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msample_rate\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 94\u001b[0m \u001b[0mtime_used\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mint_time\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m+\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mint_delay\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[0;31mTypeError\u001b[0m: unsupported operand type(s) for *: 'NoneType' and 'float'" + ] } ], "source": [ - "data3 = samp_cont.acquisition()\n", - "qc.Matplot(data3[1])" + "data3 = samp_acq_controller.acquisition()\n", + "qc.QtPlot(data3[1])" ] }, { diff --git a/docs/examples/Qcodes example with Tektronix AWG5014C.ipynb b/docs/examples/Qcodes example with Tektronix AWG5014C.ipynb new file mode 100644 index 000000000000..fbd09310add5 --- /dev/null +++ b/docs/examples/Qcodes example with Tektronix AWG5014C.ipynb @@ -0,0 +1,1325 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib nbagg\n", + "\n", + "import os\n", + "import time\n", + "import logging\n", + "\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "\n", + "logger = logging.getLogger()\n", + "logger.setLevel(logging.INFO)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import numpy as np\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "6.0" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.ceil(26/5)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "ename": "VisaIOError", + "evalue": "VI_ERROR_RSRC_NFOUND (-1073807343): Insufficient location information or the requested device or resource is not present in the system.", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mVisaIOError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mqcodes\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0minstrument_drivers\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mtektronix\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mAWGFileParser\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mparse_awg_file\u001b[0m \u001b[1;31m# <--- A helper function\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0mawg1\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mawg\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mTektronix_AWG5014\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'AWG1'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'TCPIP0::192.168.137.182::inst0::INSTR'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtimeout\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m40\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32ma:\\qcodes\\qcodes\\instrument\\metaclass.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(cls, server_name, *args, **kwargs)\u001b[0m\n\u001b[1;32m 32\u001b[0m \"\"\"\n\u001b[1;32m 33\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mserver_name\u001b[0m \u001b[1;32mis\u001b[0m \u001b[1;32mNone\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m---> 34\u001b[0;31m \u001b[0minstrument\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0msuper\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m__call__\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m*\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 35\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 36\u001b[0m warnings.warn('Multiprocessing is in beta, use at own risk',\n", + "\u001b[0;32ma:\\qcodes\\qcodes\\instrument_drivers\\tektronix\\AWG5014.py\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, name, address, timeout, **kwargs)\u001b[0m\n\u001b[1;32m 137\u001b[0m \u001b[1;32mNone\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 138\u001b[0m \"\"\"\n\u001b[0;32m--> 139\u001b[0;31m \u001b[0msuper\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m__init__\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mname\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0maddress\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtimeout\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mtimeout\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 140\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 141\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[0;32ma:\\qcodes\\qcodes\\instrument\\visa.py\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, name, address, timeout, terminator, **kwargs)\u001b[0m\n\u001b[1;32m 54\u001b[0m vals.Enum(None)))\n\u001b[1;32m 55\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m---> 56\u001b[0;31m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mset_address\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0maddress\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 57\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mset_terminator\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mterminator\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 58\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mtimeout\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mset\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mtimeout\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[0;32ma:\\qcodes\\qcodes\\instrument\\visa.py\u001b[0m in \u001b[0;36mset_address\u001b[0;34m(self, address)\u001b[0m\n\u001b[1;32m 101\u001b[0m \u001b[0mresource_manager\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mvisa\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mResourceManager\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 102\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m--> 103\u001b[0;31m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mvisa_handle\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mresource_manager\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mopen_resource\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0maddress\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 104\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 105\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mvisa_handle\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mclear\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[0;32mc:\\users\\triton2acq\\anaconda3\\envs\\qcodes-master\\lib\\site-packages\\pyvisa\\highlevel.py\u001b[0m in \u001b[0;36mopen_resource\u001b[0;34m(self, resource_name, access_mode, open_timeout, resource_pyclass, **kwargs)\u001b[0m\n\u001b[1;32m 1642\u001b[0m \u001b[1;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'%r is not a valid attribute for type %s'\u001b[0m \u001b[1;33m%\u001b[0m \u001b[1;33m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mres\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m__class__\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m__name__\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 1643\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1644\u001b[0;31m \u001b[0mres\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mopen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0maccess_mode\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mopen_timeout\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1645\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 1646\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mkey\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mvalue\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mitems\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[0;32mc:\\users\\triton2acq\\anaconda3\\envs\\qcodes-master\\lib\\site-packages\\pyvisa\\resources\\resource.py\u001b[0m in \u001b[0;36mopen\u001b[0;34m(self, access_mode, open_timeout)\u001b[0m\n\u001b[1;32m 201\u001b[0m \u001b[0mlogger\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdebug\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'%s - opening ...'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_resource_name\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mextra\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_logging_extra\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 202\u001b[0m \u001b[1;32mwith\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_resource_manager\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mignore_warning\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mconstants\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mVI_SUCCESS_DEV_NPRESENT\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m--> 203\u001b[0;31m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msession\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mstatus\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_resource_manager\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mopen_bare_resource\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_resource_name\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0maccess_mode\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mopen_timeout\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 204\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 205\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mstatus\u001b[0m \u001b[1;33m==\u001b[0m \u001b[0mconstants\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mVI_SUCCESS_DEV_NPRESENT\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[0;32mc:\\users\\triton2acq\\anaconda3\\envs\\qcodes-master\\lib\\site-packages\\pyvisa\\highlevel.py\u001b[0m in \u001b[0;36mopen_bare_resource\u001b[0;34m(self, resource_name, access_mode, open_timeout)\u001b[0m\n\u001b[1;32m 1599\u001b[0m \u001b[1;33m:\u001b[0m\u001b[1;32mreturn\u001b[0m\u001b[1;33m:\u001b[0m \u001b[0mUnique\u001b[0m \u001b[0mlogical\u001b[0m \u001b[0midentifier\u001b[0m \u001b[0mreference\u001b[0m \u001b[0mto\u001b[0m \u001b[0ma\u001b[0m \u001b[0msession\u001b[0m\u001b[1;33m.\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 1600\u001b[0m \"\"\"\n\u001b[0;32m-> 1601\u001b[0;31m \u001b[1;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mvisalib\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mopen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msession\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mresource_name\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0maccess_mode\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mopen_timeout\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1602\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 1603\u001b[0m def open_resource(self, resource_name,\n", + "\u001b[0;32mc:\\users\\triton2acq\\anaconda3\\envs\\qcodes-master\\lib\\site-packages\\pyvisa\\ctwrapper\\functions.py\u001b[0m in \u001b[0;36mopen\u001b[0;34m(library, session, resource_name, access_mode, open_timeout)\u001b[0m\n\u001b[1;32m 1209\u001b[0m \u001b[1;31m# [ViSession, ViRsrc, ViAccessMode, ViUInt32, ViPSession]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 1210\u001b[0m \u001b[1;31m# ViRsrc converts from (str, unicode, bytes) to bytes\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1211\u001b[0;31m \u001b[0mret\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mlibrary\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mviOpen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0msession\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mresource_name\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0maccess_mode\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mopen_timeout\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mbyref\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mout_session\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1212\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[0mout_session\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mvalue\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mret\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 1213\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[0;32mc:\\users\\triton2acq\\anaconda3\\envs\\qcodes-master\\lib\\site-packages\\pyvisa\\ctwrapper\\highlevel.py\u001b[0m in \u001b[0;36m_return_handler\u001b[0;34m(self, ret_value, func, arguments)\u001b[0m\n\u001b[1;32m 186\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 187\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mret_value\u001b[0m \u001b[1;33m<\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m--> 188\u001b[0;31m \u001b[1;32mraise\u001b[0m \u001b[0merrors\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mVisaIOError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mret_value\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 189\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 190\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mret_value\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0missue_warning_on\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[0;31mVisaIOError\u001b[0m: VI_ERROR_RSRC_NFOUND (-1073807343): Insufficient location information or the requested device or resource is not present in the system." + ] + } + ], + "source": [ + "import qcodes.instrument_drivers.tektronix.AWG5014 as awg # <--- The instrument driver\n", + "from qcodes.instrument_drivers.tektronix.AWGFileParser import parse_awg_file # <--- A helper function\n", + "\n", + "awg1 = awg.Tektronix_AWG5014('AWG1', 'TCPIP0::192.168.137.182::inst0::INSTR', timeout=40)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Note: if you have had any initialisation problems, the VISA message queue of the instrument could be fouled up\n", + "#(e.g. if the cell above gave you back something like 'Connected to: 1.20000000E+009 ...')\n", + "# in that case, run the following command to reset the message queue\n", + "awg1.clear_message_queue()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As with any other QCoDeS instrument, parameters can be set and get (gotten)." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "\n", + "0.0\n", + "0.1\n" + ] + } + ], + "source": [ + "print(awg1.ch3_state.get())\n", + "print(awg1.ch2_offset.get())\n", + "awg1.ch2_offset.set(0.1)\n", + "print(awg1.ch2_offset.get())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A list of all available parameters can be found in the following manner:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DC_output : DC Output (ON/OFF)\n", + "IDN : IDN\n", + "ch1_DC_out : DC output level channel 1\n", + "ch1_add_input : Add input channel {}\n", + "ch1_amp : Amplitude channel 1 (Vpp)\n", + "ch1_direct_output : Direct output channel 1\n", + "ch1_filter : Low pass filter channel 1\n", + "ch1_m1_del : Channel 1 Marker 1 delay (ns)\n", + "ch1_m1_high : Channel 1 Marker 1 high level (V)\n", + "ch1_m1_low : Channel 1 Marker 1 low level (V)\n", + "ch1_m2_del : Channel 1 Marker 2 delay (ns)\n", + "ch1_m2_high : Channel 1 Marker 2 high level (V)\n", + "ch1_m2_low : Channel 1 Marker 2 low level (V)\n", + "ch1_offset : Offset channel 1 (V)\n", + "ch1_state : Status channel 1\n", + "ch1_waveform : Waveform channel 1\n", + "ch2_DC_out : DC output level channel 2\n", + "ch2_add_input : Add input channel {}\n", + "ch2_amp : Amplitude channel 2 (Vpp)\n", + "ch2_direct_output : Direct output channel 2\n", + "ch2_filter : Low pass filter channel 2\n", + "ch2_m1_del : Channel 2 Marker 1 delay (ns)\n", + "ch2_m1_high : Channel 2 Marker 1 high level (V)\n", + "ch2_m1_low : Channel 2 Marker 1 low level (V)\n", + "ch2_m2_del : Channel 2 Marker 2 delay (ns)\n", + "ch2_m2_high : Channel 2 Marker 2 high level (V)\n", + "ch2_m2_low : Channel 2 Marker 2 low level (V)\n", + "ch2_offset : Offset channel 2 (V)\n", + "ch2_state : Status channel 2\n", + "ch2_waveform : Waveform channel 2\n", + "ch3_DC_out : DC output level channel 3\n", + "ch3_add_input : Add input channel {}\n", + "ch3_amp : Amplitude channel 3 (Vpp)\n", + "ch3_direct_output : Direct output channel 3\n", + "ch3_filter : Low pass filter channel 3\n", + "ch3_m1_del : Channel 3 Marker 1 delay (ns)\n", + "ch3_m1_high : Channel 3 Marker 1 high level (V)\n", + "ch3_m1_low : Channel 3 Marker 1 low level (V)\n", + "ch3_m2_del : Channel 3 Marker 2 delay (ns)\n", + "ch3_m2_high : Channel 3 Marker 2 high level (V)\n", + "ch3_m2_low : Channel 3 Marker 2 low level (V)\n", + "ch3_offset : Offset channel 3 (V)\n", + "ch3_state : Status channel 3\n", + "ch3_waveform : Waveform channel 3\n", + "ch4_DC_out : DC output level channel 4\n", + "ch4_add_input : Add input channel {}\n", + "ch4_amp : Amplitude channel 4 (Vpp)\n", + "ch4_direct_output : Direct output channel 4\n", + "ch4_filter : Low pass filter channel 4\n", + "ch4_m1_del : Channel 4 Marker 1 delay (ns)\n", + "ch4_m1_high : Channel 4 Marker 1 high level (V)\n", + "ch4_m1_low : Channel 4 Marker 1 low level (V)\n", + "ch4_m2_del : Channel 4 Marker 2 delay (ns)\n", + "ch4_m2_high : Channel 4 Marker 2 high level (V)\n", + "ch4_m2_low : Channel 4 Marker 2 low level (V)\n", + "ch4_offset : Offset channel 4 (V)\n", + "ch4_state : Status channel 4\n", + "ch4_waveform : Waveform channel 4\n", + "clock_freq : Clock frequency (Hz)\n", + "event_impedance : Event impedance (Ohm)\n", + "event_jump_timing : event_jump_timing\n", + "event_level : Event level (V)\n", + "event_polarity : event_polarity\n", + "ref_clock_source : Reference clock source\n", + "run_mode : run_mode\n", + "sequence_length : Sequence length\n", + "setup_filename : setup_filename\n", + "state : state\n", + "timeout : timeout\n", + "trigger_impedance : Trigger impedance (Ohm)\n", + "trigger_level : Trigger level (V)\n", + "trigger_mode : trigger_mode\n", + "trigger_slope : trigger_slope\n", + "trigger_source : trigger_source\n" + ] + } + ], + "source": [ + "pars = np.sort(list(awg1.parameters.keys()))\n", + "for param in pars:\n", + " print(param, ': ', awg1.parameters[param].label)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": false + }, + "source": [ + "## SENDING WAVEFORMS\n", + "\n", + "There are two supported ways of sending waveforms to the AWG; by making an .awg file, sending and loading that, or by sending waveforms to the User Defined list one by one and putting them in the sequencer. The first method is generally faster." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": false + }, + "source": [ + "### MAKING SOME WAVEFORMS\n", + "\n", + "First, we make a handful of pulse shapes and marker signals to send to the AWG. This should be done with numpy arrays.\n", + "\n", + "Please note that the waveforms must **not** have values exceeding -1 to 1, and that the markers must **only** have values 0 or 1. Otherwise the AWG misinterprets the signals.\n", + "\n", + "In this example, we only use two channels of the AWG, namely channel 1 and 3. Extending to one or more should be straightforward." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false, + "scrolled": true + }, + "outputs": [], + "source": [ + "noofseqelems = 6\n", + "noofpoints = 1200\n", + "waveforms = [[], []] # one list for each channel\n", + "m1s = [[], []]\n", + "m2s = [[], []]\n", + "for ii in range(noofseqelems):\n", + " # waveform and markers for channel 1\n", + " waveforms[0].append(np.sin(np.pi*(ii+1)*np.linspace(0, 1, noofpoints))*np.hanning(noofpoints))\n", + " m1 = np.zeros(noofpoints)\n", + " m1[:int(noofpoints/(ii+1))] = 1\n", + " m1s[0].append(m1)\n", + " m2 = np.zeros(noofpoints)\n", + " m2s[0].append(m2)\n", + " \n", + " # waveform and markers for channel two\n", + " wf = np.sin(np.pi*(ii+1)*np.linspace(0, 1, noofpoints))\n", + " wf *= np.arctan(np.linspace(-20, 20, noofpoints))/np.pi*2\n", + " waveforms[1].append(wf)\n", + " m1 = np.zeros(noofpoints)\n", + " m1[:int(noofpoints/(ii+1))] = 1\n", + " m1s[1].append(m1)\n", + " m2 = np.zeros(noofpoints)\n", + " m2s[1].append(m2)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false, + "scrolled": true + }, + "outputs": [ + { + "data": { + "application/javascript": [ + "/* Put everything inside the global mpl namespace */\n", + "window.mpl = {};\n", + "\n", + "mpl.get_websocket_type = function() {\n", + " if (typeof(WebSocket) !== 'undefined') {\n", + " return WebSocket;\n", + " } else if (typeof(MozWebSocket) !== 'undefined') {\n", + " return MozWebSocket;\n", + " } else {\n", + " alert('Your browser does not have WebSocket support.' +\n", + " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", + " 'Firefox 4 and 5 are also supported but you ' +\n", + " 'have to enable WebSockets in about:config.');\n", + " };\n", + "}\n", + "\n", + "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", + " this.id = figure_id;\n", + "\n", + " this.ws = websocket;\n", + "\n", + " this.supports_binary = (this.ws.binaryType != undefined);\n", + "\n", + " if (!this.supports_binary) {\n", + " var warnings = document.getElementById(\"mpl-warnings\");\n", + " if (warnings) {\n", + " warnings.style.display = 'block';\n", + " warnings.textContent = (\n", + " \"This browser does not support binary websocket messages. \" +\n", + " \"Performance may be slow.\");\n", + " }\n", + " }\n", + "\n", + " this.imageObj = new Image();\n", + "\n", + " this.context = undefined;\n", + " this.message = undefined;\n", + " this.canvas = undefined;\n", + " this.rubberband_canvas = undefined;\n", + " this.rubberband_context = undefined;\n", + " this.format_dropdown = undefined;\n", + "\n", + " this.image_mode = 'full';\n", + "\n", + " this.root = $('
');\n", + " this._root_extra_style(this.root)\n", + " this.root.attr('style', 'display: inline-block');\n", + "\n", + " $(parent_element).append(this.root);\n", + "\n", + " this._init_header(this);\n", + " this._init_canvas(this);\n", + " this._init_toolbar(this);\n", + "\n", + " var fig = this;\n", + "\n", + " this.waiting = false;\n", + "\n", + " this.ws.onopen = function () {\n", + " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", + " fig.send_message(\"send_image_mode\", {});\n", + " fig.send_message(\"refresh\", {});\n", + " }\n", + "\n", + " this.imageObj.onload = function() {\n", + " if (fig.image_mode == 'full') {\n", + " // Full images could contain transparency (where diff images\n", + " // almost always do), so we need to clear the canvas so that\n", + " // there is no ghosting.\n", + " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", + " }\n", + " fig.context.drawImage(fig.imageObj, 0, 0);\n", + " };\n", + "\n", + " this.imageObj.onunload = function() {\n", + " this.ws.close();\n", + " }\n", + "\n", + " this.ws.onmessage = this._make_on_message_function(this);\n", + "\n", + " this.ondownload = ondownload;\n", + "}\n", + "\n", + "mpl.figure.prototype._init_header = function() {\n", + " var titlebar = $(\n", + " '
');\n", + " var titletext = $(\n", + " '
');\n", + " titlebar.append(titletext)\n", + " this.root.append(titlebar);\n", + " this.header = titletext[0];\n", + "}\n", + "\n", + "\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._init_canvas = function() {\n", + " var fig = this;\n", + "\n", + " var canvas_div = $('
');\n", + "\n", + " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", + "\n", + " function canvas_keyboard_event(event) {\n", + " return fig.key_event(event, event['data']);\n", + " }\n", + "\n", + " canvas_div.keydown('key_press', canvas_keyboard_event);\n", + " canvas_div.keyup('key_release', canvas_keyboard_event);\n", + " this.canvas_div = canvas_div\n", + " this._canvas_extra_style(canvas_div)\n", + " this.root.append(canvas_div);\n", + "\n", + " var canvas = $('');\n", + " canvas.addClass('mpl-canvas');\n", + " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", + "\n", + " this.canvas = canvas[0];\n", + " this.context = canvas[0].getContext(\"2d\");\n", + "\n", + " var rubberband = $('');\n", + " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", + "\n", + " var pass_mouse_events = true;\n", + "\n", + " canvas_div.resizable({\n", + " start: function(event, ui) {\n", + " pass_mouse_events = false;\n", + " },\n", + " resize: function(event, ui) {\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " stop: function(event, ui) {\n", + " pass_mouse_events = true;\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " });\n", + "\n", + " function mouse_event_fn(event) {\n", + " if (pass_mouse_events)\n", + " return fig.mouse_event(event, event['data']);\n", + " }\n", + "\n", + " rubberband.mousedown('button_press', mouse_event_fn);\n", + " rubberband.mouseup('button_release', mouse_event_fn);\n", + " // Throttle sequential mouse events to 1 every 20ms.\n", + " rubberband.mousemove('motion_notify', mouse_event_fn);\n", + "\n", + " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", + " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", + "\n", + " canvas_div.on(\"wheel\", function (event) {\n", + " event = event.originalEvent;\n", + " event['data'] = 'scroll'\n", + " if (event.deltaY < 0) {\n", + " event.step = 1;\n", + " } else {\n", + " event.step = -1;\n", + " }\n", + " mouse_event_fn(event);\n", + " });\n", + "\n", + " canvas_div.append(canvas);\n", + " canvas_div.append(rubberband);\n", + "\n", + " this.rubberband = rubberband;\n", + " this.rubberband_canvas = rubberband[0];\n", + " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", + " this.rubberband_context.strokeStyle = \"#000000\";\n", + "\n", + " this._resize_canvas = function(width, height) {\n", + " // Keep the size of the canvas, canvas container, and rubber band\n", + " // canvas in synch.\n", + " canvas_div.css('width', width)\n", + " canvas_div.css('height', height)\n", + "\n", + " canvas.attr('width', width);\n", + " canvas.attr('height', height);\n", + "\n", + " rubberband.attr('width', width);\n", + " rubberband.attr('height', height);\n", + " }\n", + "\n", + " // Set the figure to an initial 600x600px, this will subsequently be updated\n", + " // upon first draw.\n", + " this._resize_canvas(600, 600);\n", + "\n", + " // Disable right mouse context menu.\n", + " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", + " return false;\n", + " });\n", + "\n", + " function set_focus () {\n", + " canvas.focus();\n", + " canvas_div.focus();\n", + " }\n", + "\n", + " window.setTimeout(set_focus, 100);\n", + "}\n", + "\n", + "mpl.figure.prototype._init_toolbar = function() {\n", + " var fig = this;\n", + "\n", + " var nav_element = $('
')\n", + " nav_element.attr('style', 'width: 100%');\n", + " this.root.append(nav_element);\n", + "\n", + " // Define a callback function for later on.\n", + " function toolbar_event(event) {\n", + " return fig.toolbar_button_onclick(event['data']);\n", + " }\n", + " function toolbar_mouse_event(event) {\n", + " return fig.toolbar_button_onmouseover(event['data']);\n", + " }\n", + "\n", + " for(var toolbar_ind in mpl.toolbar_items) {\n", + " var name = mpl.toolbar_items[toolbar_ind][0];\n", + " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", + " var image = mpl.toolbar_items[toolbar_ind][2];\n", + " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", + "\n", + " if (!name) {\n", + " // put a spacer in here.\n", + " continue;\n", + " }\n", + " var button = $('');\n", - " button.click(method_name, toolbar_event);\n", - " button.mouseover(tooltip, toolbar_mouse_event);\n", - " nav_element.append(button);\n", - " }\n", - "\n", - " // Add the status bar.\n", - " var status_bar = $('');\n", - " nav_element.append(status_bar);\n", - " this.message = status_bar[0];\n", - "\n", - " // Add the close button to the window.\n", - " var buttongrp = $('
');\n", - " var button = $('');\n", - " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", - " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", - " buttongrp.append(button);\n", - " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", - " titlebar.prepend(buttongrp);\n", - "}\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(el){\n", - " var fig = this\n", - " el.on(\"remove\", function(){\n", - "\tfig.close_ws(fig, {});\n", - " });\n", - "}\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(el){\n", - " // this is important to make the div 'focusable\n", - " el.attr('tabindex', 0)\n", - " // reach out to IPython and tell the keyboard manager to turn it's self\n", - " // off when our div gets focus\n", - "\n", - " // location in version 3\n", - " if (IPython.notebook.keyboard_manager) {\n", - " IPython.notebook.keyboard_manager.register_events(el);\n", - " }\n", - " else {\n", - " // location in version 2\n", - " IPython.keyboard_manager.register_events(el);\n", - " }\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._key_event_extra = function(event, name) {\n", - " var manager = IPython.notebook.keyboard_manager;\n", - " if (!manager)\n", - " manager = IPython.keyboard_manager;\n", - "\n", - " // Check for shift+enter\n", - " if (event.shiftKey && event.which == 13) {\n", - " this.canvas_div.blur();\n", - " event.shiftKey = false;\n", - " // Send a \"J\" for go to next cell\n", - " event.which = 74;\n", - " event.keyCode = 74;\n", - " manager.command_mode();\n", - " manager.handle_keydown(event);\n", - " }\n", - "}\n", - "\n", - "mpl.figure.prototype.handle_save = function(fig, msg) {\n", - " fig.ondownload(fig, null);\n", - "}\n", - "\n", - "\n", - "mpl.find_output_cell = function(html_output) {\n", - " // Return the cell and output element which can be found *uniquely* in the notebook.\n", - " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", - " // IPython event is triggered only after the cells have been serialised, which for\n", - " // our purposes (turning an active figure into a static one), is too late.\n", - " var cells = IPython.notebook.get_cells();\n", - " var ncells = cells.length;\n", - " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", - " data = data.data;\n", - " }\n", - " if (data['text/html'] == html_output) {\n", - " return [cell, data, j];\n", - " }\n", - " }\n", - " }\n", - " }\n", - "}\n", - "\n", - "// Register the function which deals with the matplotlib target/channel.\n", - "// The kernel may be null if the page has been refreshed.\n", - "if (IPython.notebook.kernel != null) {\n", - " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", - "}\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "data7 = rec_contr.acquisition()\n", - "qc.MatPlot(data7[1])" + ")\n", + "\n", + "# set integration time and delay (nb this replaces need to set samples_per record)\n", + "# if int_delay is unset it will default to a value corresponding to the about needed for the filter to work well\n", + "rec_controller.int_time(2e-6)\n", + "rec_controller.int_delay.to_default()" ] }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 19, "metadata": { "collapsed": false }, @@ -1458,42 +677,29 @@ "text": [ "DataSet:\n", " mode = DataMode.LOCAL\n", - " location = '2016-11-08/11-29-47_AlazarTest'\n", + " location = '2017-01-23/10-58-35'\n", " | | | \n", - " Setpoint | dummy_set | dummy | (5,)\n", - " Measured | record_num | record_num | (5, 20)\n", - " Measured | rec_controller_magnitude | magnitude | (5, 20)\n", - " Measured | rec_controller_phase | phase | (5, 20)\n", - "started at 2016-11-08 11:29:49\n" + " Measured | index1 | index1 | (4, 20)\n", + " Measured | rec_controller_magnitude | magnitude | (4, 20)\n", + " Measured | rec_controller_phase | phase | (4, 20)\n", + "acquired at 2017-01-23 10:58:36\n" ] - } - ], - "source": [ - "dummy = parameter.ManualParameter(name=\"dummy\")\n", - "data8 = qc.Loop(dummy[0:5:1]).each(\n", - " rec_contr.acquisition).run(name='AlazarTest')" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": { - "collapsed": false - }, - "outputs": [ + }, { "data": { + "image/png": "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\nepea3q5na9WBe4uSrwN+Ny4wKdKK+2im5MLQKTkNoNSazeakTwEovdMySZZdvAt8sOraxs5h1eWN\nrH8a5MC9hzNkImrJZm9I5Mkt43VJs2gmEtznut2J1AUAgCGSJDlHj/sZYf18S+x9rTLXr899JPdz\n/1PEuPJ2iVfcAQDgpDNbZXItwA/N93rcAQDgEg1tf++t1vfdbHVKpsq4AdP5tBpJT6M16VMZs05a\nP/zSknraGX58ObUas/jl3fupnLWv7P7P5Ix9Za3G/S9o9t5Sjn11s/aucvwbd7RpNr62B7+0mXpL\nGfgDWfKvbMCfrNl7J7l0u4Mcvx/T0eNk3HcDptI4+wa/5da5Pb+RNasR0Wok62nSrBV5EXghWo2k\nGct57tBWJq1GcvhTOWM66fr2jTRrVmbqR7Lv/t4z9pbSf/fyGXpXGXhj9tl4S+n/0mboLeXBL22G\n3lJO/Mm6+uJMvZMU45TV9wG9NFOy4i64n0NrZ2t5aS2idwvf7f1OVMv6x/6k6tra4UeVa2X/i2iQ\nTlpvXkubSVZfn/SpjFVrZ28lbc74m/QM/UhWas0sSe/9EM7aW8qDX91Mvav0f2kz9JbS96XN0lvK\nye/avR0l/3ns/5M1a+8klyfnkJm+Hndz3GfCxW7hO9U62XbcWJ+tL6yT1tdjvVmrRKl/PTpAa2er\nvbWVbEZExGXM0pqcSq1ZbxxOE1tYSZuz9SN5wgy/pcQMvqt4SymhWXxLufcn6/bRltl+J8ln7FNl\npoTgzkCtRm37xmy8o93Xybbb7Xbt8O+iiFo90vL+krTfvb9bZ+5XpPfaSDppvbb5Yqs2O1/Zw2b2\n3lW8pZTSzL2lHP3J0tb+gONtLX0hvu+q0yOjBnor7iVU+C18C9FqJM1rM/T3zz2VWjOr9T68v1A2\nc2bsV6SdtLm3sr4WEZVaM436etqpzuK37Z7ZfEuJGX1X8ZZSQrP2lnLKn6yZfSc5p3x3UY2zx0Se\n7HGfSHA3VeYcqkvLWzutiN56y/zVEv+RP6mT1mfw79eZV11a3mr2pgrM2A9l5ep8e/PF3kLSjH1p\n9830W0p4Vykjbyll0P8na9bfSS7f4pkmfXaHrLifx9k3+C21Trbdjvu/+11Y8ZdtOVTX0v1679u2\nMDOXlEVERHUtXanX7jekzsaX1n9/79l6S+n76m7uz867ymXfmH2CTvxMzs5bSv+XNitvKQP+vp6t\nd5LpN5EV97lx3YIVAADGK0mSW7eyi7/O9etzX/nK+UNvX6vM9etzP5j7uX8VMa68bcUdAIDZd/36\nXEQMjO85Z0QeZ447AAA84M6df3rBV3jmmecj4pVXPhP34nvv4yMf+Uie03jg04kEd60yAABMqSRJ\nsmwMrTJzc3O9D1555TO9HH+RDDw3N/e3ch/8Da0yAACQUy86z83NPfPM873l9l6UP3ek1ioDAACX\n5Si+x71umXPHd8EdAAAuV198f+aZ588R3905FQAAitDtdo93zvTie/7sLrgDAEBBxtg5MxZ37959\n5JFHzjhAcAcA4OF1vvg+9mj/xhtv/OVf/uWP//iPn3HMlXEXBQCAkul2u91u95lnnj8+duZoiORJ\nB7kfQ33rW9/64z/+449//OO/9Vu/dfaRgjsAAETcW2XvZffjq+8Djsz9OMPbb7/93e9+97Of/exT\nTz31h3/4h0NPT6sMAAAcytk5c8GLUw8ODr73ve/9+q//+i/+4i/mf5bgDgAADxga3y8S3F9//fUv\nf/nLn/rUp/76r/96pCcK7gCj66T19Vhv1iqTPhEALs9pE9/jvBenvvnmm9/85jdv3rz5+7//++d4\nuh53gAd10no97Yz/dVuNS3lZAC7Xycb3iHg39yMi5ubmvve97929e3d1dfXDH/7w+VJ7WHEH6Fep\nNZtjfslOWq9ttmNh5eaYXxiAIpzsnBnJM888/+KLL/7cz/3cBU9DcAd4UK8NZj3W1+PG/ObmVkTE\n8ka2Vj0K4BERsbByePDhloWVtFmrtBrJ6t5K2qxVopPWa9s30matEpVaM0vS+vqEviIAxuF4fB/V\nxVN7aJUBOFV78/ZSlmVZtrG81Uw70WrUNuc3sizLsnRlISKi1ajdrme9LTe219NOVNfSldh8sRWd\ndP0wtQMwS3rxvZvbwcHBm2+++Ru/8RsXLy24A5xiYeVmNSIiKtcWIqKzv3e0paezvxdbq0mSJElS\n22y3b3ciolJbX9lbTWrbN9aldoCZdPZNVfvMzc09/vjjn/70p999993PfvazF6mrVQbgAnoNMg9u\nq1ydj2hP5nwAmErvec97IuJXfuVXPve5z928efP3fu/3zvEiVtwB8qlcnW9vZ52IiE623T7csvli\nq++4VmM1NrKN+c11Q2QAOO6JJ56oVCpf+MIXXn755Q996EOjPl1wB8ipurYxv1lLkiRZvz2/0NuS\nruwd9sokST3tRKuRrMbGWvXw4EYv1XfSelLbbLc3a0nS6A/6ADxcnnzyyY9//ON/9md/9qu/+qsj\nPXFupB4dAAAoTJIkWZZN+iwuy9tvvx0RP//zP//5z38+In75l395fX39jOOtuAMAwAS8733ve9/7\n3nfr1q0/+ZM/+ehHPzr0eBenAgDAxHzwgx/84Ac/+PLLL3/9618/+0itMgAAMHl379595JFHzjhA\ncAcAgBLQ4w4AACUguAMAQAkI7gAAUAKCOwAAlIDgDgAAJSC4AwBACQjuAABQAv8/BROcwhcddQgA\nAAAASUVORK5CYII=\n", "text/plain": [ - "" + "" ] }, - "execution_count": 17, + "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "qc.QtPlot(data8.rec_controller_magnitude)" + "data7 = qc.Measure(rec_controller.acquisition).run()\n", + "qc.QtPlot(data7.rec_controller_magnitude)" ] } ], diff --git a/qcodes/instrument_drivers/AlazarTech/samp_controller.py b/qcodes/instrument_drivers/AlazarTech/samp_controller.py index a85b1ea9ae23..9fb3be199c9e 100644 --- a/qcodes/instrument_drivers/AlazarTech/samp_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/samp_controller.py @@ -57,8 +57,8 @@ def update_sweep(self, start, stop, npts): self.shapes = ((demod_length, npts), (demod_length, npts)) def get(self): - self._instr.int_time.check() - self._instr.int_delay.check() + self._instrument.int_time.check() + self._instrument.int_delay.check() mag, phase = self._instrument._get_alazar().acquire( acquisition_controller=self._instrument, **self.acquisition_kwargs) From f1b92adceabd4a3db5fc4f52916aa9480fade799 Mon Sep 17 00:00:00 2001 From: nataliejpg Date: Tue, 24 Jan 2017 10:39:50 +0100 Subject: [PATCH 091/180] tweaks while testing on actual setup --- .../Qcodes example with Alazar ATS9360.ipynb | 298 ++++++++++++------ .../instrument_drivers/AlazarTech/ATS9360.py | 2 +- .../AlazarTech/ave_controller_test.py | 5 +- .../AlazarTech/basic_controller.py | 8 +- .../AlazarTech/rec_controller_test.py | 5 +- .../AlazarTech/samp_controller.py | 18 +- 6 files changed, 226 insertions(+), 110 deletions(-) diff --git a/docs/examples/Qcodes example with Alazar ATS9360.ipynb b/docs/examples/Qcodes example with Alazar ATS9360.ipynb index 0c7b247d4bbf..905fd7081d53 100644 --- a/docs/examples/Qcodes example with Alazar ATS9360.ipynb +++ b/docs/examples/Qcodes example with Alazar ATS9360.ipynb @@ -28,7 +28,8 @@ "import qcodes.instrument_drivers.AlazarTech.ATS9360 as ATSdriver\n", "import qcodes.instrument_drivers.AlazarTech.basic_controller as basic_aqc_contr\n", "import qcodes.instrument_drivers.AlazarTech.samp_controller as samp_acq_contr\n", - "import qcodes.instrument_drivers.AlazarTech.samp as samp\n", + "import qcodes.instrument_drivers.AlazarTech.ave_controller_test as ave_acq_controller\n", + "import qcodes.instrument_drivers.AlazarTech.rec_controller_test as record_acq_controller\n", "\n", "import logging\n", "# logging.basicConfig(filename='example.log',level=logging.INFO)\n", @@ -40,7 +41,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "NB: See ATS9870 example notebook for general commands " + "NB: See ATS9360 example notebook for general commands " ] }, { @@ -148,8 +149,8 @@ "source": [ "# Configure settings in the controller to be used in an acquisition\n", "# nb this must be done before the first acquisition \n", - "basic_acq_controller.update_acquisition_kwargs(samples_per_record=1024,\n", - " records_per_buffer=1,\n", + "basic_acq_controller.update_acquisition_kwargs(samples_per_record=128*11,\n", + " records_per_buffer=100,\n", " buffers_per_acquisition=1,\n", " allocated_buffers=1\n", " )" @@ -166,9 +167,9 @@ "name": "stdout", "output_type": "stream", "text": [ - "(array([-0.0007326 , 0.001221 , 0.0002442 , ..., -0.00561661,\n", - " -0.02515263, -0.01147741]), array([ 0.0021978, 0.0021978, 0.001221 , ..., 0.001221 , 0.001221 ,\n", - " 0.0002442]))\n" + "(array([-0.00903541, -0.00757021, 0.0002442 , ..., 0.2014652 ,\n", + " 0.197558 , 0.1965812 ]), array([-0.0002442, 0.0007326, -0.0002442, ..., 0.0007326, -0.0002442,\n", + " 0.0007326]))\n" ] } ], @@ -180,7 +181,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 11, "metadata": { "collapsed": false }, @@ -191,66 +192,91 @@ "text": [ "DataSet:\n", " mode = DataMode.LOCAL\n", - " location = '2017-01-23/10-40-23'\n", + " location = '2017-01-23/18-17-17'\n", " | | | \n", - " Measured | index0 | index0 | (1024,)\n", - " Measured | basic_acq_controller_A | A | (1024,)\n", - " Measured | basic_acq_controller_B | B | (1024,)\n", - "acquired at 2017-01-23 10:40:24\n" + " Measured | index0 | index0 | (1408,)\n", + " Measured | basic_acq_controller_A | A | (1408,)\n", + " Measured | basic_acq_controller_B | B | (1408,)\n", + "acquired at 2017-01-23 18:17:18\n" ] - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" } ], "source": [ "# Do this in as qcodes measurement (ie the same but makes a data set)\n", "data2 = qc.Measure(basic_acq_controller.acquisition).run()\n", - "qc.QtPlot(data2.basic_acq_controller_A)" + "plot = qc.MatPlot(data2.basic_acq_controller_A)" ] }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 17, "metadata": { "collapsed": false }, "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "DataSet:\n", - " mode = DataMode.LOCAL\n", - " location = '2017-01-20/15-59-19_AlazarTest'\n", - " | | | \n", - " Setpoint | dummy_set | dummy | (5,)\n", - " Measured | index0 | index0 | (5, 1024)\n", - " Measured | basic_acq_controller_A | A | (5, 1024)\n", - " Measured | basic_acq_controller_B | B | (5, 1024)\n", - "started at 2017-01-20 15:59:23\n" - ] - }, { "data": { - "image/png": "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\nVIcqwy9lcG+rKe67e4yFxmK7wVdHyrftEzKSjCTXkj33Hlp5Vm9mcG+W38/AZ1JZupFdh7J0s7ys\nqkOpDqc61DqrC2ksts9t9VNPL1//aGBfWVC7UtJqD/PJgVbF3WotLNrSwP5Unn62/Ob2lxdFJ+Wf\ng/vSWGwO7qtUr2TFZ9O6ikeSF1rvX1hxgGnV43Dr3FSeerpY2Fy6Wdl18O6pKxrk7XfSWGhWhyqD\n+7J0szic5fdTHU5zpGgpd6+ptNpDcT95sbVw+XoGnivfV1aesWIPimu5OHtFs6kOFXVUFDewP8vX\n72l18/cey60Vl0B1OJWRLL+fgUNDKa6dwb1lI991qDy6VmtsNhYr1aFmY/HO75S30Mpwnv6OjPzH\ne5rHrVb1XWstLBphZSSN62kutO6xuw6WJ619dyqKKwvdW1m62UxSHV6+/lFxaCubQVq3i2Lhu8nn\nWlfc8vXyMlm+nuqnFu62jfa1XDTyOwsZ3Js7l9unujqSRrJ8Pcvvl99cVM2eVlMZaZ3DPa3DfL71\nfc2FNAf3VRoLGXwpSe5cya6D5Y29sVg2uKKmGotpLDa//lFxg2oslDWSe2/17ZvhntaSzwxn+f3y\nxtusDlWKm2FxiygPbaisr6UbrXa4t1kdSj5Yfr+8ua0sqDiQ95IXks8l7ybXkheT5Q8zOJwUv1rX\n89SzrUZe3DHa1VQU11jI4L5KUe6d8voaeC7VkRy4WRZX/JQcSC4kI8nLrXY4kizdzMAzabZrqTqU\nFHePg2U7KRa2frDKdthYrAzubX5rbvn9NBfuNvgXW7+S8yuu63eTF1s3+aIhNRby1FirSRT3oqWb\nZR01FsuiGwspLoeieQxn+Uaa8+V5e6/VGK6tePPCihNbVs715DNZfj+Df7JoEodWtPOFNIbuOY2t\na5lttEEm1C3rRuBe7UKZAACw4zrO0f6AH2xs+rV99LgDAPCkeLDYvUcyp+pxBwCAPqDHHQAAtqZp\nVhkAAOgD3QjcDZUBAIA+oMcdAAC2yDzuAADQB4xxBwCAHfCwyZgE7gAAsO22FKafO7d6yeuvP2Dm\npu0lcAcA4DG3xbxLq6P8tQmYTAcJAABdtjbK79BhbzpIAACgIz3uAACwRaaDBACAPmCMOwAA9AE9\n7gAA0PuaAncAAOgDAncAAOgF98nZZIw7AADspPUC9JX5UztkTtXjDgAAO2lVuqV2HH/s2D0LV2dl\n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\nQmCC\n", + "image/png": "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\nbZkkw0sNkQAAAABJRU5ErkJggg==\n", "text/plain": [ - "" + "" ] }, - "execution_count": 12, + "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], + "source": [ + "plot.fig\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": true + }, + "outputs": [ + { + "ename": "gaierror", + "evalue": "[Errno 11004] getaddrinfo failed", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mgaierror\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[1;31m# Do this in as qcodes measurement (ie the same but makes a data set)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[1;31m#data3 = qc.Measure(basic_acq_controller.acquisition).run()\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mplot\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mqc\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mQtPlot\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mdata2\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mbasic_acq_controller_B\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32ma:\\qcodes\\qcodes\\plots\\pyqtgraph.py\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, figsize, interval, window_title, theme, show_window, remote, *args, **kwargs)\u001b[0m\n\u001b[1;32m 52\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mremote\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 53\u001b[0m \u001b[1;32mif\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m__class__\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mproc\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m---> 54\u001b[0;31m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_init_qt\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 55\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 56\u001b[0m \u001b[1;31m# overrule the remote pyqtgraph class\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[0;32ma:\\qcodes\\qcodes\\plots\\pyqtgraph.py\u001b[0m in \u001b[0;36m_init_qt\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 72\u001b[0m \u001b[1;31m# run, so this only starts once and stores the process in the class\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 73\u001b[0m \u001b[0mpg\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mmkQApp\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m---> 74\u001b[0;31m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m__class__\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mproc\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mpgmp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mQtProcess\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;31m# pyqtgraph multiprocessing\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 75\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m__class__\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mrpg\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mproc\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_import\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'pyqtgraph'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 76\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[0;32mc:\\users\\triton2acq\\anaconda3\\envs\\qcodes-master\\lib\\site-packages\\pyqtgraph\\multiprocess\\processes.py\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, **kwds)\u001b[0m\n\u001b[1;32m 389\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_processRequests\u001b[0m \u001b[1;32mand\u001b[0m \u001b[0mQtGui\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mQApplication\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0minstance\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mis\u001b[0m \u001b[1;32mNone\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 390\u001b[0m \u001b[1;32mraise\u001b[0m \u001b[0mException\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"Must create QApplication before starting QtProcess, or use QtProcess(processRequests=False)\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m--> 391\u001b[0;31m \u001b[0mProcess\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m__init__\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwds\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 392\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mstartEventTimer\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 393\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[0;32mc:\\users\\triton2acq\\anaconda3\\envs\\qcodes-master\\lib\\site-packages\\pyqtgraph\\multiprocess\\processes.py\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, name, target, executable, copySysPath, debug, timeout, wrapStdout)\u001b[0m\n\u001b[1;32m 79\u001b[0m \u001b[1;31m#print \"key:\", ' '.join([str(ord(x)) for x in authkey])\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 80\u001b[0m \u001b[1;31m## Listen for connection from remote process (and find free port number)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m---> 81\u001b[0;31m \u001b[0ml\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mmultiprocessing\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mconnection\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mListener\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'localhost'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mauthkey\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mauthkey\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 82\u001b[0m \u001b[0mport\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0ml\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0maddress\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 83\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[0;32mc:\\users\\triton2acq\\anaconda3\\envs\\qcodes-master\\lib\\multiprocessing\\connection.py\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, address, family, backlog, authkey)\u001b[0m\n\u001b[1;32m 436\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_listener\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mPipeListener\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0maddress\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mbacklog\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 437\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m--> 438\u001b[0;31m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_listener\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mSocketListener\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0maddress\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mfamily\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mbacklog\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 439\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 440\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mauthkey\u001b[0m \u001b[1;32mis\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[1;32mNone\u001b[0m \u001b[1;32mand\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[0misinstance\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mauthkey\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mbytes\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[0;32mc:\\users\\triton2acq\\anaconda3\\envs\\qcodes-master\\lib\\multiprocessing\\connection.py\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, address, family, backlog)\u001b[0m\n\u001b[1;32m 574\u001b[0m socket.SO_REUSEADDR, 1)\n\u001b[1;32m 575\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_socket\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msetblocking\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;32mTrue\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m--> 576\u001b[0;31m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_socket\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mbind\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0maddress\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 577\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_socket\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mlisten\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mbacklog\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 578\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_address\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_socket\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mgetsockname\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[0;31mgaierror\u001b[0m: [Errno 11004] getaddrinfo failed" + ] + } + ], + "source": [ + "# Do this in as qcodes measurement (ie the same but makes a data set)\n", + "#data3 = qc.Measure(basic_acq_controller.acquisition).run()\n", + "plot = qc.QtPlot(data2.basic_acq_controller_B)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], "source": [ "# Finally show that this instrument also works within a loop\n", "dummy = parameter.ManualParameter(name=\"dummy\")\n", @@ -259,6 +285,15 @@ "qc.QtPlot(data3.basic_acq_controller_A)" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + }, { "cell_type": "markdown", "metadata": {}, @@ -270,7 +305,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 18, "metadata": { "collapsed": false }, @@ -279,12 +314,12 @@ "# make a list of the frequencies to demodulate at (nb these values can be changed later, if unset the default is [20e6])\n", "# NB the number of demodulation frequencies cannot currently be changed once an acq controller is created, this sucks:\n", "# lets have channels :)\n", - "demod_list = [95e6, 98e6, 100e6, 105e6]" + "demod_list = [5e6,1e6]" ] }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 19, "metadata": { "collapsed": false }, @@ -299,7 +334,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 25, "metadata": { "collapsed": false }, @@ -315,13 +350,13 @@ "source": [ "# set integration time and delay (nb this replaces need to set samples_per record)\n", "# if int_delay is unset it will default to a value corresponding to the about needed for the filter to work well\n", - "samp_acq_controller.int_time(2e-6)\n", + "samp_acq_controller.int_time(10e-6)\n", "samp_acq_controller.int_delay(0)" ] }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 40, "metadata": { "collapsed": true }, @@ -335,7 +370,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 22, "metadata": { "collapsed": false }, @@ -343,30 +378,28 @@ "source": [ "# update_acquisition_kwargs now should not be used with samples_per_record but instead just for changing averaging values\n", "samp_acq_controller.update_acquisition_kwargs(\n", - " records_per_buffer=1,\n", - " buffers_per_acquisition=1,\n", + " records_per_buffer=100,\n", + " buffers_per_acquisition=100,\n", " allocated_buffers=1\n", ")" ] }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 43, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# demodulation _frequencies can be changed\n", - "samp_acq_controller.demod_freq_0(90e6)\n", - "samp_acq_controller.demod_freq_1(98e6)\n", - "samp_acq_controller.demod_freq_2(100e6)\n", - "samp_acq_controller.demod_freq_3(110e6)" + "samp_acq_controller.demod_freq_0(10e6)\n", + "samp_acq_controller.demod_freq_1(20e6)" ] }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 31, "metadata": { "collapsed": false }, @@ -374,28 +407,48 @@ { "data": { "text/plain": [ - "{'allocated_buffers': 1,\n", - " 'buffers_per_acquisition': 1,\n", - " 'records_per_buffer': 1,\n", - " 'samples_per_record': 1120}" + "8.192e-06" ] }, - "execution_count": 14, + "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], + "source": [ + "4096 / samp_acq_controller.sample_rate #samples_per_record" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": { + "collapsed": false + }, + "outputs": [], "source": [ "# check the acquisition kwargs\n", - "samp_acq_controller.acquisition.acquisition_kwargs" + "samp_acq_controller.acquisition.acquisition_kwargs.update({'samples_per_record':5184})" ] }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 54, "metadata": { "collapsed": false }, + "outputs": [], + "source": [ + "samp_acq_controller.samples_per_record=5184" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": { + "collapsed": false, + "scrolled": false + }, "outputs": [ { "name": "stdout", @@ -403,22 +456,22 @@ "text": [ "DataSet:\n", " mode = DataMode.LOCAL\n", - " location = '2017-01-23/10-42-57'\n", + " location = '2017-01-23/18-25-22'\n", " | | | \n", - " Measured | index1 | index1 | (4, 1020)\n", - " Measured | samp_acq_controller_magnitude | magnitude | (4, 1020)\n", - " Measured | samp_acq_controller_phase | phase | (4, 1020)\n", - "acquired at 2017-01-23 10:42:57\n" + " Measured | index1 | index1 | (2, 5000)\n", + " Measured | samp_acq_controller_magnitude | magnitude | (2, 5000)\n", + " Measured | samp_acq_controller_phase | phase | (2, 5000)\n", + "acquired at 2017-01-23 18:25:23\n" ] }, { "data": { - "image/png": "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\n", + "image/png": "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\nAABJRU5ErkJggg==\n", "text/plain": [ - "" + "" ] }, - "execution_count": 17, + "execution_count": 48, "metadata": {}, "output_type": "execute_result" } @@ -427,12 +480,60 @@ "# as with basic...\n", "# nb: index1 is actually the list demodulation frequency index but setpoints are ind of broken\n", "data4 = qc.Measure(samp_acq_controller.acquisition).run()\n", - "qc.QtPlot(data4.samp_acq_controller_magnitude)" + "plot = qc.MatPlot(data4.samp_acq_controller_magnitude[0])\n", + "plot.add(data4.samp_acq_controller_magnitude[1])\n", + "plot.fig" ] }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 35, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([ 3.59998900e-07, 7.23784543e-07, 1.81824540e-06, ...,\n", + " 3.18445386e-04, 3.15040241e-04, 3.14722229e-04])" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data4.samp_acq_controller_magnitude[0]" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAr8AAAGyCAYAAADtb6ytAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAAPYQAAD2EBqD+naQAAIABJREFUeJzs3XmYHFXZ/vH7JCSBgWQSCCaEVUQgqCyJKGFRBAKyCL6C\nYlD25UX2uKD4KkvEH4tCBDGigIQtQSSiiGyCssgikEAQCTskAbKTTPbJLOf3x9PHqq6p6umeTCZM\n1fdzXXP1TE11dfVSXXc9/dRp570XAAAAUAQ91vYKAAAAAF2F8AsAAIDCIPwCAACgMAi/AAAAKAzC\nLwAAAAqD8AsAAIDCIPwCAACgMAi/AAAAKAzCLwAAAAqD8AsAAIDC6FD4dc6d7px72zm3wjn3tHNu\n13bm39s5N9k5t9I595pz7tjE/3dwzt1ZWmarc+6slGWc55x7xjm32Dk3xzl3l3Nu246sPwAAAIqp\n5vDrnDtS0hWSLpC0i6Spkh5wzg3MmH8rSfdIeljSTpKuknS9c25kbLY6SW9K+r6kWRk3vZekX0r6\nrKT9JPWS9KBzbr1a7wMAAACKyXnva7uCc09L+pf3/uzS307STElXe+8vT5n/MkkHeu93jE2bKKne\ne39QyvxvSxrrvb+6nfUYKGmupM957/9Z050AAABAIdVU+XXO9ZI0XFbFlSR5S88PSRqRcbXdSv+P\ne6DC/NXqL8lL+mA1lwMAAICCqLXtYaCknpLmJKbPkTQ44zqDM+bv55zrU+PtS/pvtfkXkv7pvX+5\nI8sAAABA8ayztlegg8ZJ2kHSHlkzOOc2knSApHckreya1QIAAEAN1pW0laQHvPcLuuIGaw2/8yW1\nSBqUmD5I0uyM68zOmH+x976xxtuXc+4aSQdJ2st7n3VynGTB97Zalw8AAIAu9w1JE7rihmoKv977\nJufcZEn7Srpb+m8Lwr6Ssk5Qe0rSgYlp+5em16QUfA+T9Hnv/Yx2Zn9Hkm699VYNHTq01ptCNzR6\n9GiNHTt2ba8GugjPd7HwfBcLz3dxTJs2Td/85jelUm7rCh1pe7hS0vhSCH5G0mjZUGXjJck5d4mk\nId77MJbvtZJOL4368DtZUD5CVr1V6Tq9ZG0MTlJvSZs653aStNR7/2ZpnnGSRkk6VNIy51yoJjd4\n79PaGlZK0tChQzVs2LAO3E10N/X19TzXBcLzXSw838XC811IXdaiWnP49d7fURpmbIysfeEFSQd4\n7+eVZhksafPY/O845w6WNFbSWZLelXSi9z4+AsQQSc/LRm+QpO+Wfh6VtE9p2qml/z+SWKXjJd1c\n6/0AAABA8XTohDfv/TjZSWdp/zs+ZdpjsiHSspY3Xe2MPOG956uYAQAAsFoIlAAAACgMwi9yY9So\nUWt7FdCFeL6Lhee7WHi+sSbV/PXG3YVzbpikyZMnT6ZpHgAA4ENoypQpGj58uCQN995P6YrbpPIL\nAACAwiD8AgAAoDAIvwAAACgMwi8AAAAKg/ALAACAwiD8AgAAoDAIvwAAACgMwi8AAAAKg/ALAACA\nwiD8AgAAoDAIvwAAACgMwi8AAAAKg/ALAACAwiD8AgAAoDAIvwAAACgMwi8AAAAKg/DbjiuvlN57\nb22vBQAAADoD4beCJUuk73xH+vrX1/aaAAAAoDMQfitYssQuGxrW7noAAACgcxB+KwjhtwePEgAA\nQC4Q6ypYutQuCb8AAAD5QKyrIFR+e/Zcu+sBAACAzkH4rWDFCrv0fu2uBwAAADoH4beCpqbySwAA\nAHRvhN8KmpvtksovAABAPhB+K6DiC+TbggUc3AJA0RB+K6DyC+RXU5M0cKB03nlre00AAF2J8FsB\nlV8gv5Yvt8vbb1+76wEA6FqE3wqo/AL51dhol2FUFwBAMRB+K2C0ByC/Qvjl4BYAioXwW0Go/BJ+\ngfwJ4RcAUCyE3wqo/AL5RfgFgGIi/FZA5RfIL8IvABQT4bcCKr9Afq1cubbXAACwNhB+KwiV33AJ\nID+o/AJAMRF+K6DyC+QX4RcAionwWwE9v0B+EX4BoJgIvxWE0NvczFigQN4QfgGgmAi/FcR7fen7\nBfIlhN911lm76wEA6FqE3wri7Q60PgD5EsJvD94FAaBQeNuvIF7tJfwC+RLCb0vL2l0PAEDXIvxW\nQOUXyK8QfmlpAoBiIfxWQOUXyC/CLwAUE+G3gnjgZQcJ5AvhFwCKifBbQXOz1KuX/U7lF8iX8PXG\nhF8AKBbCbwVNTdJ660W/A8gPTngDgGIi/FbQ3ByFX6pDQL7Q9gAAxUT4rYDKL5BfIfx6L7W2rt11\nAQB0HcJvBVR+gfyKf70x2zcAFAfht4J4+KXyC+QL4RcAionwW0FTk1RXF/0OID8IvwBQTB0Kv865\n051zbzvnVjjnnnbO7drO/Hs75yY751Y6515zzh2b+P8Ozrk7S8tsdc6d1Rm3u7poewDyq7FR6lF6\nB2T7BoDiqDn8OueOlHSFpAsk7SJpqqQHnHMDM+bfStI9kh6WtJOkqyRd75wbGZutTtKbkr4vaVZn\n3G5n4IQ3IL8aG6X117ffCb8AUBwdqfyOlvQb7/3N3vtXJJ0qabmkEzLm/5akt7z353rvX/Xe/0rS\nnaXlSJK8989577/vvb9D0qpOut3VRs8vkF+NjdIGG9jvhF8AKI6awq9zrpek4bIqriTJe+8lPSRp\nRMbVdiv9P+6BCvN31u2utnjll50jkC8rV1L5BYAiqrXyO1BST0lzEtPnSBqccZ3BGfP3c871WYO3\nu9qo/AL5RdsDABQToz1UQOUXyC/CLwAU0zo1zj9fUoukQYnpgyTNzrjO7Iz5F3vvG1Pm76zblSSN\nHj1a9fX1ZdNGjRqlUaNGtXujVH6B/GpsjIYyJPwCwJo3ceJETZw4sWxaQ0NDl69HTeHXe9/knJss\naV9Jd0uSc86V/r4642pPSTowMW3/0vQ1ebuSpLFjx2rYsGHV3lQZRnsA8ite+W1pWbvrAgBFkFZ8\nnDJlioYPH96l61Fr5VeSrpQ0vhRGn5GNwlAnabwkOecukTTEex/G8r1W0unOucsk/U4WWI+QdFBY\nYOmEth0kOUm9JW3qnNtJ0lLv/ZvV3O6a0Nws9eljY4FSGQLyhbYHACimmsOv9/6O0ti6Y2RtBy9I\nOsB7P680y2BJm8fmf8c5d7CksZLOkvSupBO99/ERIIZIel6SL/393dLPo5L2qfJ2O11Tk7TOOvZD\n5RfIF8IvABRTRyq/8t6PkzQu43/Hp0x7TDZUWdbypquKk+8q3e6a0Nws9eplP4RfID+8l1atIvwC\nQBEx2kMF8covO0cgP1aVvkqH8AsAxUP4zdDaaj9UfoH8aSyNM0P4BYDiIfxmCDvDddax8MvOEcgP\nwi8AFBfhN0PYGfbqxQlvQN6sXGmXhF8AKB7Cb4YQdkPll/AL5AeVXwAoLsJvhnjll7YHIF844Q0A\niovwmyFe+aXtAcgXwi8AFBfhN0Oy8kv4BfIjtD3U1dkl2zcAFAfhN0Oy8ktlCMiPUPkN4belZe2t\nCwCgaxF+M1D5BfKL8AsAxUX4zZAc7YHKL5Afoe1h3XXtku0bAIqD8JshhF/G+QXyJ1R++/ShrQkA\niobwmyH5DW+EXyA/CL8AUFyE3wy0PQD5Fdoeevcm/AJA0RB+M/D1xkB+hcov4RcAiofwm4GvNwby\na9Uq27Z79CD8AkDREH4zJCu/7ByB/GhstKqvJPXsyfYNAEVC+M1A5RfIr1Wr7GQ3iYNbACgawm+G\n5JdcsHME8mPVqqjyS/gFgGIh/GZIfr0xlV8gP+JtD4RfACgWwm8Gvt4YyK9k2wNfbwwAxUH4zcA4\nv0B+0fYAAMVF+M3AOL9AftH2AADFRfjNEMJuz560PQB5w2gPAFBchN8Mzc22U3SOtgcgb6j8AkBx\nEX4zNDXZTlGi7QHIm3jPL19yAQDFQvjN0NxsFV+Jyi+QN7Q9AEBxEX4zUPkF8ou2BwAoLsJvhmTl\nl/AL5AdDnQFAcRF+M8Qrv7Q9APlC+AWA4iL8ZohXfsPO0fu1u04AOkdTU/n2zTe8AUBxEH4zJCu/\nEtUhIC9aW6UepXc/Kr8AUCyE3wzJnt8wDUD319JiQ5xJhF8AKBrCb4bkaA9hGoDuLx5+GecXAIqF\n8JuByi+QX62tVH4BoKgIvxmo/AL51dJCzy8AFBXhN0Na5ZfwC+QDPb8AUFyE3wyM9gDkF+EXAIqL\n8JshOc6vROUXyAuGOgOA4iL8Zmhublv5JfwC+UDlFwCKi/CbIS38soME8iEZfvmGNwAoDsJvhnj4\npe0ByBeGOgOA4iL8ZqDtAciv+FBnfMkFABQL4TdD2ji/fDQK5AM9vwBQXITfDPHKb9hJsoME8oHw\nCwDFRfjNkDbUGZVfIB8Y6gwAiovwm4HKL5BfVH4BoLgIvxnSRnug8gvkA+EXAIqL8JuByi+QXwx1\nBgDFRfjNQOUXyK/4UGeEXwAoFsJvhvhQZ1R+gXyJtz307GmVYO/X7joBALoG4TcDlV8gn7xv2/Yg\nsX0DQFEQfjPEhzqj8gvkR6jwxtseJLZvACiKDoVf59zpzrm3nXMrnHNPO+d2bWf+vZ1zk51zK51z\nrznnjk2Z56vOuWmlZU51zh2Y+H8P59xPnHNvOeeWO+fecM79qCPrXw0qv0A+he04Wfkl/AJAMdQc\nfp1zR0q6QtIFknaRNFXSA865gRnzbyXpHkkPS9pJ0lWSrnfOjYzNs7ukCZKuk7SzpD9L+pNzbofY\non4g6X8lnSZpe0nnSjrXOXdGrfehGoz2AOQT4RcAiq0jld/Rkn7jvb/Ze/+KpFMlLZd0Qsb835L0\nlvf+XO/9q977X0m6s7Sc4CxJ93nvryzNc76kKZLiwXaEpD977+/33s/w3v9R0oOSPtOB+9CuePgN\nH49S+QW6v9ZWuyT8AkAx1RR+nXO9JA2XVXElSd57L+khWThNs1vp/3EPJOYfUcU8T0ra1zn38dK6\n7CRpD0n31nIfqhUPv87ZjpKdI9D9hYPYZM9vU9PaWR8AQNdap8b5B0rqKWlOYvocSdtlXGdwxvz9\nnHN9vPeNFeYZHPv7Ukn9JL3inGuRBff/897fXuN9qEp8qDPJfqfyC3R/WW0PbN8AUAy1ht+16UhJ\nR0n6uqSXZb3BVznn3vfe39LZNxYf7UGi8gvkBT2/AFBstYbf+ZJaJA1KTB8kaXbGdWZnzL+4VPWt\nNE98mZdLusR7/4fS3/8pnUx3nqTM8Dt69GjV19eXTRs1apRGjRqVdRV5X972IFH5BfIi9PzS9gAA\nXWvixImaOHFi2bSGhoYuX4+awq/3vsk5N1nSvpLuliTnnCv9fXXG1Z6SdGBi2v6l6fF5kssYmZin\nTha841rVTt/y2LFjNWzYsEqztBF2jvHwS+UXyIdk5Td8wsP2DQBrVlrxccqUKRo+fHiXrkdH2h6u\nlDS+FIKfkY3aUCdpvCQ55y6RNMR7H8byvVbS6c65yyT9ThZyj5B0UGyZV0l6xDn3bUl/lTRKdmLd\nybF5/iLpR865dyX9R9Kw0m1f34H7UFHYCVL5BfKHtgcAKLaaw6/3/o7SmL5jZK0JL0g6wHs/rzTL\nYEmbx+Z/xzl3sKSxsiHN3pV0ovf+odg8TznnjpL009LP65IO896/HLvpMyT9RNKvJH1E0vuSfl2a\n1qnSwi+VXyAfsoY6o+0BAIqhQye8ee/HSRqX8b/jU6Y9JqvkVlrmJEmTKvx/maRvl37WqLATpPIL\n5E/WUGcc3AJAMXTo643zjsovkF/0/AJAsRF+U4SdYHyos3XWYecI5AE9vwBQbITfFFmVX9oegO6P\noc4AoNgIvymyRnugMgR0f1R+AaDYCL8pwk4w7BzD71R+ge6Pnl8AKDbCb4rkzlGi8gvkRdZQZ2zf\nAFAMhN8UyZ2jxFBnQF5kDXVGzy8AFAPhN0Vy5ygx1BmQF7Q9AECxEX5TUPkF8osT3gCg2Ai/Kaj8\nAvmVNdQZ2zcAFAPhNwWVXyC/kpXfcEnPLwAUA+E3BZVfIL+S4dc5RnMBgCIh/Kag8gvkV9b2TfgF\ngGIg/KZI9gRKVH6BvEj7ZIfwCwDFQfhNwZdcAPmVtX3T8wsAxUD4TZFV+Q3TAXRfaeG3Vy8ObgGg\nKAi/KdJ2jj160PML5EHawS2f7ABAcRB+U2RVfgm/QPdHWxMAFBvhN0XazpHwC+QDPb8AUGyE3xRU\nfoH8ShvqjJ5fACgOwm8KKr9AfjHUGQAUG+E3BaM9APlF2wMAFBvhNwWjPQD5xQlvAFBshN8U9PwC\n+ZW2fdPzCwDFQfhNQc8vkF9UfgGg2Ai/Kaj8AvnV0iI5Zz8BPb8AUByE3xRpZ4NzwhuQD62t5VVf\nibYHACgSwm+KtHFAqfwC+dDSUn5gK9H2AABFQvhNkVb5ZbQHIB9aWtpWfgm/AFAchN8UVH6B/MoK\nv/T8AkAxEH5ThJAbPyGG8AvkQ2tretsD2zcAFAPhN0XYORJ+gfxJq/zS1gQAxUH4TZF2QgyjPQD5\nkBZ+ObgFgOIg/KZIGwqJnSOQD2zfAFBshN8UaZVfPhYF8iHrkx22bwAoBsJvCipDQH7R9gAAxUb4\nTUFlCMivrINbevoBoBgIvymo/AL5xcEtABQb4TcFoz0A+cVQZwBQbITfFGmVX3aOQD7Q8wsAxUb4\nTZH2DVCh8uv92lknAJ2DtiYAKDbCb4qsypBE6wPQ3dHzCwDFRvhNkVX5ldhBAt1d1sEtB7YAUAyE\n3xRUfoH8ou0BAIqN8JuCyi+QX7Q9AECxEX5TZA2FFP4HoPtiqDMAKDbCbwoqv0B+MdQZABQb4TdF\npZ5fdpBA90bPLwAUG+E3BZVfIL/4BkcAKDbCbwpGewDyi7YHACg2wm8KKr9AftH2AADFRvhNwWgP\nQH6ltT0w2gMAFAfhNwWVXyC/aHsAgGIj/KZgtAcgvwi/AFBsHQq/zrnTnXNvO+dWOOeeds7t2s78\nezvnJjvnVjrnXnPOHZsyz1edc9NKy5zqnDswZZ4hzrlbnHPznXPLS/MN68h9qITKL5Bf9PwCQLHV\nHH6dc0dKukLSBZJ2kTRV0gPOuYEZ828l6R5JD0vaSdJVkq53zo2MzbO7pAmSrpO0s6Q/S/qTc26H\n2Dz9JT0hqVHSAZKGSvqOpIW13of2MNoDkF9ZQ515bz8AgHzrSOV3tKTfeO9v9t6/IulUScslnZAx\n/7ckveW9P9d7/6r3/leS7iwtJzhL0n3e+ytL85wvaYqkM2Lz/EDSDO/9Sd77yd776d77h7z3b3fg\nPlRE5RfILw5uAaDYagq/zrlekobLqriSJO+9l/SQpBEZV9ut9P+4BxLzj6hini9Jes45d4dzbo5z\nbopz7qRa1r9ajPYA5FdW24PE9g0ARVBr5XegpJ6S5iSmz5E0OOM6gzPm7+ec69POPPFlbi2rIr8q\naX9Jv5Z0tXPu6FruQDWo/AL5lTXUWfgfACDf1lnbK1CDHpKe8d7/uPT3VOfcJ2VtF7d05g0x2gOQ\nX2zfAFBstYbf+ZJaJA1KTB8kaXbGdWZnzL/Ye9/YzjzxZc6SNC0xzzRJX6m0wqNHj1Z9fX3ZtFGj\nRmnUqFGZ16lU+aUnEOjeCL8AsHZMnDhREydOLJvW0NDQ5etRU/j13jc55yZL2lfS3ZLknHOlv6/O\nuNpTkpLDlu1fmh6fJ7mMkYl5npC0XWI520maXmmdx44dq2HDahsNjZ0jkF+Ven45uAWANSet+Dhl\nyhQNHz68S9ejI6M9XCnpZOfcMc657SVdK6lO0nhJcs5d4py7KTb/tZK2ds5d5pzbzjl3mqQjSssJ\nrpL0Refct0vzXCg7se6a2DxjJe3mnDvPOfcx59xRkk5KzNMp6PkF8itrqLPwPwBAvtXc8+u9v6M0\npu8YWWvCC5IO8N7PK80yWNLmsfnfcc4dLAuvZ0l6V9KJ3vuHYvM8VQqzPy39vC7pMO/9y7F5nnPO\n/Y+kSyX9WNLbks723t9e631oT0uL1KdP+TROiAHygU92AKDYOnTCm/d+nKRxGf87PmXaY7JKbqVl\nTpI0qZ157pV0b/Vr2jFUfoH8YqgzACi2Dn29cd6xcwTyi6HOAKDYCL8pKvUEckIM0L3R9gAAxUb4\nTUHlF8gvvt4YAIqN8JuCs8GB/OLgFgCKjfCbIm3nSE8gkA8c3AJAsRF+U7BzBPKLnl8AKDbCbwq+\nAQrIL9oeAKDYCL8pqPwC+cVQZwBQbITfFFSGgPxitAcAKDbCbwoqQ0B+0fMLAMVG+E1B5RfIL7Zv\nACg2wm8KKr9AftHTDwDFRvhNkVYZkmwaPYFA90bbAwAUG+E3RVplSLIdJDtHoHuj7QEAio3wm6JS\n5ZedI9C9VWpr4pMdAMg/wm+KrMpvjx6EX6C7o+0BAIqN8JuCyi+QX4RfACg2wm8Ken6BfPLeLgm/\nAFBchN8UjPYA5FMItwx1BgDFRfhNQeUXyKew/VL5BYDiIvymoOcXyKfwyQ3hFwCKi/CbgtEegHzK\nantgqDMAKA7Cbwoqv0A+0fYAACD8pqjU80tlCOi+CL8AAMJvCiq/QD7R8wsAIPymYLQHIJ/a6/ll\n+waA/CP8pqDyC+RTVtuDc5zQCgBFQfhNwWgPQD5ltT2EaWzfAJB/hN+E8PWntD0A+ZPV9iCxfQNA\nURB+E9qrDDHaA9B9ZbU9SHyyAwBFQfhNoDIE5Fel8MvBLQAUA+E3gZ5AIL+am+1ynXXa/o/tGwCK\ngfCbQOUXyK/2Kr9s3wCQf4TfhEqVX3oCge6N8AsAIPwmUPkF8itsv7Q9AEBxEX4TGO0ByK/Q80vl\nFwCKi/CbQOUXyC/aHgAAhN8ERnsA8qtS2wM9/QBQDITfBCq/QH7R9gAAIPwmMNoDkF98yQUAgPCb\n0F7ll50j0H0x2gMAgPCbQM8vkF+0PQAACL8J9PwC+cVoDwAAwm8ClV8gv2h7AAAQfhMqVX454Q3o\n3mh7AAAQfhOo/AL5RdsDAIDwm8BoD0B+VQq/fLIDAMVA+E2g8gvkV2h7oOcXAIqL8JvAaA9AftH2\nAAAg/CZQ+QXyi294AwAQfhMY7QHIr5YW246da/s/Dm4BoBgIvwntVX6pDAHdV3Nz+rYtEX4BoCgI\nvwn0/AL51dJC+AWAoutQ+HXOne6ce9s5t8I597Rzbtd25t/bOTfZObfSOfeac+7YlHm+6pybVlrm\nVOfcgRWW9wPnXKtz7sqOrH8l9PwC+dXSkj7Sg8T2DQBFUXP4dc4dKekKSRdI2kXSVEkPOOcGZsy/\nlaR7JD0saSdJV0m63jk3MjbP7pImSLpO0s6S/izpT865HVKWt6ukU0q32+mo/AL5VantgZ5+ACiG\njlR+R0v6jff+Zu/9K5JOlbRc0gkZ839L0lve+3O99696738l6c7ScoKzJN3nvb+yNM/5kqZIOiO+\nIOfcBpJulXSSpEUdWPd2UfkF8ou2BwBATeHXOddL0nBZFVeS5L33kh6SNCLjaruV/h/3QGL+EVXM\nI0m/kvQX7/3fa1nvWjDaA5BftD0AADJ2A5kGSuopaU5i+hxJ22VcZ3DG/P2cc328940V5hkc/nDO\nfV3WEvHpGte5Joz2AOQXoz0AAGoNv2uFc25zSb+QtJ/3vmlN3hY9v0B+tdf2wMEtAORfreF3vqQW\nSYMS0wdJmp1xndkZ8y8uVX0rzROWOUzSxpKmOPff4el7Svqcc+4MSX1K7RdtjB49WvX19WXTRo0a\npVGjRqWubNj5EX6B/KHnFwDWnokTJ2rixIll0xoaGrp8PWoKv977JufcZEn7SrpbkkphdF9JV2dc\n7SlJyWHL9i9Nj8+TXMbI2DwPSfpUYhnjJU2TdGlW8JWksWPHatiwYVn/boMT3oD8am6m5xcA1pa0\n4uOUKVM0fPjwLl2PjrQ9XClpfCkEPyMbtaFOFkblnLtE0hDvfRjL91pJpzvnLpP0O1nIPULSQbFl\nXiXpEefctyX9VdIo2Yl1J0uS936ZpJfjK+GcWyZpgfd+WgfuQybaHoD8ovILAKg5/Hrv7yiN6TtG\n1prwgqQDvPfzSrMMlrR5bP53nHMHSxorG9LsXUkneu8fis3zlHPuKEk/Lf28Lukw731Z4E2uSq3r\nXo1KlV9GewC6t0rhl+0bAIqhQye8ee/HSRqX8b/jU6Y9JqvkVlrmJEmTaliHfaqdtxbtVX45IQbo\nvhjqDADQoa83zjN6foH8YqgzAADhN4GeXyC/6PkFABB+E9qr/HpvPwC6H9oeAACE34TmZrvMqvxK\n7CCB7oq2BwAA4Tehqcl2gmnhN0zjpDege2pvnF+2bQDIP8JvQlOT1KtX+v+o/ALdW3vbN9s2AOQf\n4TeB8AvkV6XKL+P8AkAxEH4TCL9AflH5BQAQfhMIv0B+NTcTfgGg6Ai/CYRfIL+amhjqDACKjvCb\nUCn8MtoD0L3R9gAAIPwmUPkF8ou2BwAA4TeB8AvkF20PAADCbwLhF8iv9rZvWpoAIP8IvwmEXyC/\naHsAABB+Ewi/QH5Vanvo0cMqv9537ToBALoW4TeB0R6A/Krm4JbtGwDyjfCbQOUXyK/22h4ktm8A\nyDvCbwLhF8iv9kZ7kNi+ASDvCL8JhF8gv6j8AgAIvwmEXyC/2L4BAITfBE54A/KLtgcAAOE3gcoQ\nkF+0PQAACL8JhF8gvypVfsP05uauWx8AQNcj/CYQfoF88t623aztu3dvu1y1quvWCQDQ9Qi/CYRf\nIJ9CRTdr+w7Tm5q6Zn0AAGsH4TeB8AvkUwi1WW0PhF8AKAbCbwKjPQD5FEJte20PhF8AyDfCbwKV\nXyCfqm17oOcXAPKN8JtA+AXyibYHAIBE+G2D8AvkU3ttD4RfACgGwm8C4RfIp/baHhjqDACKgfCb\nUCn8UhkCui/aHgAAEuG3jUrht08fu2xs7Lr1AdA5GOcXACARftuoFH7XWUdyjvALdEcMdQYAkAi/\nZVpa7CtQs3aOzln1l/ALdD/Vtj3Q8wsA+Ub4jWmvMiQRfoHuirYHAIBE+C1D+AXyi6HOAAAS4bdM\nex+LSoRfoLtqb/vu0cOGM6TtAQDyjfAbU03lt3dvwi/QHbXX9hD+R+UXAPKN8BtD2wOQX9Ue3FL5\nBYB8I/zdWFDpAAAgAElEQVTGEH6B/KqmrWnddaWVK7tmfQAAawfhN4bwC+RXNW0PdXXS8uVdsz4A\ngLWD8BtTzc6R8At0T9VUftdbT1qxomvWBwCwdhB+Y6j8AvlF5RcAIBF+yxB+gfyqZvuuq6PyCwB5\nR/iNIfwC+dXUZF9R3qPCu95661H5BYC8I/zGEH6B/GpurrxtS1R+AaAICL8xhF8gv5qa2g+/VH4B\nIP8IvzGEXyC/mpoqj/QgccIbABQB4TeG8AvkVzVtDwx1BgD5R/iNIfwC+VVN2wOVXwDIP8JvDOEX\nyK9q2x6o/AJAvhF+Ywi/QH5V2/ZA5RcA8q1D4dc5d7pz7m3n3Arn3NPOuV3bmX9v59xk59xK59xr\nzrljU+b5qnNuWmmZU51zByb+f55z7hnn3GLn3Bzn3F3OuW07sv5ZCL9AftH2AACQOhB+nXNHSrpC\n0gWSdpE0VdIDzrmBGfNvJekeSQ9L2knSVZKud86NjM2zu6QJkq6TtLOkP0v6k3Nuh9ii9pL0S0mf\nlbSfpF6SHnTOrVfrfcgSBsHv2TN7nnXX5WNRoDtqbm6/7WG99aRVq6SWlq5ZJwBA1+tI5Xe0pN94\n72/23r8i6VRJyyWdkDH/tyS95b0/13v/qvf+V5LuLC0nOEvSfd77K0vznC9piqQzwgze+4O897d4\n76d57/8t6ThJW0ga3oH7kKracUCbm+0HQPdRbeVX4gAXAPKspvDrnOslC5sPh2neey/pIUkjMq62\nW+n/cQ8k5h9RxTxJ/SV5SR+0u+JVqjb8StLKlZ11qwC6Qi3bN+EXAPKr1srvQEk9Jc1JTJ8jaXDG\ndQZnzN/POdennXlSl+mcc5J+Iemf3vuXq1v19rFzBPKr2rYHie0bAPKsnV3Bh9Y4STtI2qMzF0r4\nBfKrmu173XXtkk92ACC/ag2/8yW1SBqUmD5I0uyM68zOmH+x976xnXnaLNM5d42kgyTt5b2f1d4K\njx49WvX19WXTRo0apVGjRrWZl/AL5BfbNwCsXRMnTtTEiRPLpjU0NHT5etQUfr33Tc65yZL2lXS3\n9N8WhH0lXZ1xtackHZiYtn9penye5DJGJuYJwfcwSZ/33s+oZp3Hjh2rYcOGVTMrlSEgx2h7AIC1\nK634OGXKFA0f3mljF1SlI20PV0oaXwrBz8hGbaiTNF6SnHOXSBrivQ9j+V4r6XTn3GWSficLuUfI\nqrfBVZIecc59W9JfJY2SnVh3cpjBOTeuNP1QScucc6FS3OC975QoSmUIyC9OaAUASB0Iv977O0pj\n+o6RtSa8IOkA7/280iyDJW0em/8d59zBksbKhjR7V9KJ3vuHYvM85Zw7StJPSz+vSzoscTLbqbLR\nHR5JrNLxkm6u9X6kIfwC+dXUZF9SU0n4ZIftGwDyq0MnvHnvx8lOOkv73/Ep0x5TO+Pxeu8nSZpU\n4f9r/KuYCb9AfjU3SxtsUHketm8AyL81Hii7Ez4WBfKL7RsAIBF+y9RywhuVIaB7qeaEN7ZvAMg/\nwm8M4RfIr2q27x49pN692b4BIM8IvzHV7hz79GHnCHQ31WzfkrU+0PYAAPlF+I2pZedI+AW6l2ra\nHiT7dIftGwDyi/AbQ2UIyC+2bwCARPgtQ+UXyC+2bwCARPgtU+3OkY9Fge6HtgcAgET4LUNlCMgv\n2h4AABLhtwzhF8gvtm8AgET4LUNlCMgv2h4AABLhtwyVISC/OLgFAEiE3zKEXyC/mpvZvgEAhN8y\njPYA5FdTE20PAADCbxkqv0A+eU/lFwBgCL8x1Ybf9deXli1b8+sDoHO0tNhlNZVfwi8A5BvhN6ba\n8Nu3r7RkyZpfHwCdo6nJLqn8AgAIvzGEXyCfCL8AgIDwG1NL+F26VGptXfPrBGD1NTfbZTVtD3V1\nhF8AyDPCb0y14bdfP7tcunTNrg+AzlFr5bexkYNbAMgrwm9MLZVfidYHoLuoNfxKfNEFAOQV4bfE\nezsjnPCLogktAXlWS9tDCL+0PgBAPhF+S0JlqJqdY1eH37vvZmg11G7xYunCCyuHuPfeswO+u+/u\nstVaKzpS+SX8AkA+EX5Latk5dmX4feMN6bDDpDFj1vxtoXtYulTadVfp2WcrzzdhgnTRRdJ992XP\nM3WqXd57b+et34cR4RcAEBB+S2rZOYYT3hoa1tz6BO++a5cvvbTmbwvdw+uvS889J/3855Xnc84u\n33gje54ZM+wy760PHWl7WL58za0PAGDtIfyW1BJ+N9xQ6tlTev556cEH1+x6zZtnl42Na/Z20H3M\nnWuX7b0mwsHZggXZ84RPL8Iy41580Xrh84DKLwAgIPyW1LJz7NlT2mQT6Sc/kQ44wCpxa0oIJR2t\nzHVmeHn4YWn+/M5bHjpm9my7bG8orkWL7LLScxbC75w55dP//W9pp52kX/+6Y+vYFd54o/rWo7D9\nEH4BAITfklrCryRtumn0++OPS08+uWbGBQ2V3470F7/yirTxxtI//7n66/H++9J++0lnn736y8Lq\nCUG1vcrv6oTfd96xy8mTa169LrFkifTxj0unnVbd/LWc0Er4BYB8I/yW1FIZkmzHG/zoR9Iee6yZ\nk4ZC+F28uPJ8N94oDR1aHoief94+8v7b31Z/PV57zS5ffHH1l/X449L06au/nKIKld/2es7D/6sJ\nv3Pnln9KEG7jwzrWbfi05YEHqpt/1Sq77N27/XkJvwCQb4Tfklorv7/6lXT77dKXviTNmmXT/vOf\nzl+vasPv5ZdbpfeVV6JpoZr3wQervx4hQLW0rN5yvJc+9znpoIMqzzdjhs0Xvz9d6fnnO+eEp7lz\npTff7Pj105678Ly295qopfK7YkX5NxaG13RaL3BXaK9dp9b1CgeFffq0P29dnV0SfgEgnwi/JbWG\n3379pCOPlHbcMZr23nudv15Z4behQbrrrujvMA5wfB3WRPgNj1NHLVxoly+/XHm+J5+0CvGdd67e\n7XXEggXSsGHSGWes/rIOOUTaZpuOXfc//5E22kj6wx/Kp1db+Q3hN7yG0ixdGo1eEm99CLexNnq8\n77/f1untt7PnCevao8p3sFoqv3362EgZhF8AyCfCb0mt4Tf4xCei30NgqNayZdJbb1WeZ948G1d4\n5cpoBy5J55wjfeUr0VBVoVoVhkaTooAQQtDqCCGoljD0/vtt2yTef7+226t2/s40bZpdtjeObjXC\nMtqrIqcdoDz1lF0++WT59PC8VhN+6+vtgCOrP3jJEuljHytfrrT2w+/SpdK//pU9T6j8xqvVldRS\n+XVOWnddhjoDgLwi/JZ0NPyOHCkdfri02261j/t7+ukWPCrtZOfNi8JJvPobTkgKX1IQljFzZjRP\nCAidMR5xCEGLFlVf/d1tNxsxIP4RdrVhNlQrK1Ut15QQ/KqtKlYj/rwkhQrv7benXyd5UDV7tr0m\nli2rPApIQ4O0/fb2e1abwJIlUWU6Pk9oe5g3b80Nd/bSS1ZdT7bShNdXeI2nCUF92bLqhgGspfIr\n2UFDV4zjDQDoeoTfko6G34ED7aP5oUPb78EMWlps2LCbbrK/s3qFW1vtI/gQfkN/5sKFbT/SDjvq\ne+6RvvxlCzJrovKb/L2SEN7SQpVUObSE+7U2Ko/heay2qliN5GgKca++apePPlo+PTwG8cesqcle\nE9tu2/46LloUhd8QoFetkk49NTphbMkSacstbfi+ZOV3yy3tOUp+tfacOe1/YhG3YoX1xj/zTPn0\nc8+13vlkC0xYj0rjE8dfU5XmC8Jrrdrwu+GGndMuBAD48CH8loTKUDUfi6appVI0frwNGxZkjXww\nf74F5VCZW7LEqmUbbii98EI0T2trFIxfeEH685+lm2/ODr+trdJVV9XWUjB/vjRkSPR7LeKhKn6b\n4fGaM6dtdbEjbRYd8fbbth7bbBONaRvWq72DhnhP6L/+JR14YHkVP16VrVTBDiErGbZCwIs/fuH3\nEH6zDriamiy0hvAb2mNeeUX6zW9shBLJXjf19TYkXli29xZ+P/Wp9HXfddfogKwaU6faQdl555VP\nD/3fYSSR5H2s9NzPnSsNGlS+nEpWrbJhzqqt5g8YUN1yAQDdD+G3pNbKUFIt4fe558r/zqpchf7d\n0Fe8eHHUBxrMm2fVP++jMCBZFXHOHOmjH20b4qZMsZ7h73+/uvWVLIgMHRr9Xot4lS4Zft94Qxo8\nWLrhhvLrhMDVXlVv0SK7P+++K/3iF7V9RL9ihbT11hYQ33xTuuIKmx4C5cKF2aNbtLZan3UIkVdc\nYb2q8TGV4+GpI+E3XCf++IWguMsu5euaFKZvu620xRbSZZdZGA8hOAT3pUutp3zjjaXf/96mNTRY\nj3kIv8nnO1T0kxXhuG99S7r1Vvs9jHaR9alKsq2jmsrvvHnRAUClg5QZM+xAsLGxtgNbKr8AkF+E\n35JaewKT+vWrvu0hBMBvftN6PbN28lOn2sk3O+1kfy9eXP4ReI8eFkzC7Q4bZpc77ST99a92nz7+\ncQsp8RAXPrKOnxzXnnj4raYPN94XnAy/H/mI/d7QEIW5e+4pv/68efZR/Pz5lQPt6NHS8OHSySfb\n7+EEs6lT7fGo1GsbHocQvtZdN1ovyW43q/oXnrOrrrLLUPGNt7DEn9dKBwxhvmRf7vz59rr64IPo\n8bzhBmu1ib8m0oRAOGCAdM019rg8/ngUfnv0sNfE8uXSBhtIRxxhJ/rNmhW9xtIqv/Fxf5M9uXfd\nZZ88fPCBdO210imn2PTweCYfy6zqfrXhN4y1vXChNGmSdNxxbb9o5qSTpGOPtftdy7ZN5RcA8ovw\nW1LL2eBp6uutilbNOLizZkknnCDdcotV3LKC0e2321i3H/2o/b1kSbRDPuQQad99LSCEAPS971mV\n6+c/jwJj2sfjoc2ilhN65s+3KmmvXtWF33hwiX9sP316NDzcokVRdS1ZvZs3z8J2U1Plb7cLofn+\n++0y9M/++c82Vu9991W+T3Hh27/ij1VWAAuBOfTchvvx2GNRKAzXda66ym9yngULyg84mptt2LNz\nz7UALJU/h889ZwGwpSV6PPv3lw4+2CqZjzxSXrUN696vn3Toofb79OnSMcfY77vuapfxxyleDY1X\n8RcvttFHvvzlttXl8HgmD0TS+rpXrrT5K1VevW9b+T3nHOuhT/Yih/ag55+vbdseOHDtnGwJoPvw\nfs2dEIw1i/BbsrqV3/p6u6ym+jt7trTJJvZ7fCc7aZJ9dC9ZBevxxy3krr9+tOxFi6Tdd5f+8hdr\nc1i4MApAH/mIdPTR0ogR0W2lVQhDOKnmRCHJQsyyZbauAwe2DY3jx0t77lke/OPBIdzOxRfb1+XG\n1ymE+fgyw4l+1bRZJE+aC8E+XP7739KYMen9zclwEx7HhoaovznrMQrV0RCYwzr+6U9RS0KYtv32\nlYNUuI1586LKpfc2fYcd7O85c+w2m5qsDSb+eluwwNoMRo+2APj661H4ra+3Ku+ee0oPPRQ994sX\nR6+Jvn2jr+t+9NGoLWfrra0qHF/3eCCNjykdljt9ennI9T66ndmzo+1s1aro8U47UNp+++zK65w5\nFpI//nELtAsXRusSTuQLwre1vfVWbdv24MHln7IAQFxTk/TFL1pbWbIdER9+hN+Szgq/7VVTw8lE\ngwfb3xtuGO3kjzjCAoz31pKwYoUFwB49LKCEsNi/v80/YICFnBAuwpcVrL9+9HvoF25osI11zJho\n3NhqexpDlXPw4PSK2GWXSU88EVXZpGie/v2jEHj99XYZKotLlkTrEA9Modc2rPsNN9jJZMke02XL\n2laFQ5AK63zNNdIFF0hXXtn2fiVDdQiMixdb8IvPkzy6D8vv2TO63XCQsmiR3YewLttu237lt3dv\nq+yG18KSJfZ3OACYOzdqU9l8c7st52xd77rL2gxCv3E4iU+KXivHH2/P+4QJ0X0Mj13fvvY6lKLX\nxnPP2esu+clEVuU3/vzFv9FuxYro9em9dOGFUbCXrNUkvvx4+M3q5f3ud+3y05+2+7dwYXQiW/Lk\n0XAfZ86srfK7ySZ23Up9zVgzli6Vfvc7ady41f9GyUrmzbP3ls4YDQfF88c/Sg8+aO9n3/zmmn2t\novMRfksaG2s7Gzyp2vAb+jdD5bd//7Zvvu+9F4WAUJHr1892xosWlYffeOU3BF7JRoV44gmbR4pO\nlrvgAjtBrK7OdjLxL87IEqpqm25q4TfZmxpCRWg5kKJ5hg6Nws2SJdIll1jbQ+/e5W0c8UpkCIoh\n/P6//2dtDQ8/XH674TEKoXOddaJwlqwavvSSXY4ZI/3f/0W3M2iQjYDws5/Z49jaapeh1WTBAvtI\nfcSI8gAcwm9jowW8hQulffYp//+CBfa62GSTtkH7ueeiZSQrvGGaFI3WMGdOeR9v/IAo+VH/7NnR\nvOE1cdhh0l57RfMkw2/PnvaaCM91WJ+BA6VLL5X+9rfy9RoyJDv8xoc0++ADu63Q533JJXbfw3O8\n3XblgTo8JtttFz22jY3lQ7o98oh01FFWcRkwwE6aDDueUIGWyg8mvK+98htfH3SN5cvtoOakk2wc\n9B//ePWWN3++9I9/tA0m3luLzkknWdGhFq2tbXvLUTy33SZ99rM21Olbb9nrDN0H4bdk1aqOV32l\nKJC2F37jVVQpCrDxN+cZM6JAECpy4YS6hQujQBuCc/zj62Dzza09IoSfhobyk7FCP2c1rQ9PPmkB\nd8stLRT94Q/lASdUx+JfRztvnj2eH/2o7YAaG+0+hfvdt295+JWk006zwBKCUQh+QfhCjyB8LB1O\nrtpvv/KRE+KVvnfesR3eBRdYmG5psdvZeGMLWltsYf9futQez4EDbR3nz7eT2v71L2vvCCEwHope\nf92ue/zx0r33Ro/rggV2QuPGG5dXfpua7PE/8shoXUOFNxl+N93U1mPu3Oi1FQ60wmsiGawbGuxx\n7ds3astwTvr61+33nXdu2/YQLmfNsiAcTv4L20ToCQ6P7w47ZIff+DfjhYOzXXaxx0Kyb/0L67zt\nttF9nTbNQroUPfcLF9oXyXz+8/Z3Y6MF9JEj7e/+/aMDm969y9cj+dqutfIr5Tv8vvJK5X76jpg7\n11q1Lr+8Y72QV11l2+oLL0g/+IGNA93Rb9prarLXzT772LYZN2WKva+dcIIdVD//fHXLnDbNPhXq\n2dPeX7v69bF8eeWv/UbXWLDAzif5xjcsAA8ebG1l6D4IvyWrG35DIGnvI7QQ2JKV33gInDkz+juE\n31DlS1Z+ly2zING3b3rVOl6Rjr9R7767XVbT+jB+vFVH1l/fqjFSNCyYFAW2J56wo2EpCpbhY/Mw\nT7jfIfx+8EF0Atxtt9kywnqGvlvJdjbxqp4UzXfQQTZ27aBB5ZXf3XaL5p0+vfwxfv99W69w4lj8\n+WtosGA5cGB54D7hBGn//aPWlRAQQ8V74EAbeUKyN8ew/BB+QxgI9+Oxx+wyHn5DxTzcj402svs1\nZ46tl3PWhytF4Tf5HDY02Pzxoe8kOxnuiissCCxd2vYTg7597XHp29duR7JWlU98wg5KVq2y+9W/\nvx0sxHt+Z860++6cVWJD5TxUfjfc0O7bxhvbY5dW+b3rLrusq4uC8sKF1vs+ZUp5m0x43gYMiA7q\nRoyQJk601gopuo3w6Ul4vqoRXqdrou/3iScqf+lJV3juOXvNhQOwzvLTn9pIM9//fvQ8VMt7e6/5\n6lftPeHkk+21c+edHVuX666zsHrccXZycbwf/C9/sW3+mmvs9V7pxNhg9mwL03V10tVXW0j/0pcq\nf8tiZ1qwwA5ct97aTm7+MGpp6brHY236wx/s9fq1r9l73j77tP1ksihaWmxbHT7cPkHtLicAEn5L\nah0HNKma8LtggVW9pKgCGsJvPMC8+6793atX9JF+aHuIV37D5fTp0e0n1dVZcAwVwm23tfFXv/GN\naJ1aWqytIK1nac4c24GEyt/QodJZZ0X3Y8WKqHp0333W+zRligWPj3wkOkEuWfGOV7JDe4Nk/aIz\nZljAGzDAdi6bbWaXaeG3V6/ocQgjBIQhyr70Jel//9dOIly5srwn+d13o4AuRdXPUPnt188C2COP\ntH1MZsyw2w6tAWG4to02ig5WQvjdaCN7DFatsmW//LKFnyCMqfvRj9rrL6zjjBn2pjpokE3/+c+t\nOtWvXxRMw2O4YIF9VHz88VadDwc6yfBbVyd9+9tRC0J4TuKVXykK15JVYK+4wnZos2ZFPeebbmrV\n/8mTbb6ZM+2LL0JojFduw+PZo4fddvj2wfDJwOLFVqV75x1pq63svofnNN7S8fbbbT8R6d/fHtse\nPewxaGmRLrrIrhfC7yc/GT1e1RowwNavM8Ov9/Y47bmn9IUvdN5yOyL0wN93X21fdlPJqlV2APu9\n79nP2LHVffV08Oyzti2FcwK23tpCRXIM8Go0NNinPMcdZ19e07dv+deH33efdMABdkLk7rtXd8LS\n5ZfbfXz0UenMM+3k1smTLUB3hdNOs+3pnHPs/eDpp7vmdqu1eLGdzLzVVm2/zTFvJkywTxrDe+y+\n+9proYhfiX777VYkGTDARiL64x/X9hpVh/BbsrqV33XXtZ9KL/5ddpG+8x0LRHV1Nm3AAPsoK16V\nnTnTdvIbbhgFnf79bWe+ZElU+Q2XM2Zk79ids/81NFhI2mwzC74hAC1YYKNMHHigHc0mhfARgp5k\nVb+ZM21nHipYn/509P/HHouC5UYbWQgMISKt7eEjH7FgM2CAfRT7ox/ZbThnX7zw739HoSguBLzw\nGIUWkuXLLUwNGWItEeEj83jonDmzvPIbAl9Dg4XU+npb9/feswOQeCCcNs1uO4T2EH4HDrQ2g379\n7HENJzaGgD1njo09fOyx0bLCR/YbbWQB7tJLbbi6k0+2aeuuKx1+uM3zpz+VH+TU10eV3912s5OE\nBg+2x+Cxx8oPKuLCfXnjDXsNhdd9vAIcF6+CNjTYdUJVfp99rGL7z3/aayucKBgfhmzx4mi9QxV8\n1ixbRqjwLlpk4XfYMJsWXtvxj6PffLNt+A0hedNN7faD//wnCr9hvOJawq9z9lh2VjBcvtxC+BZb\n2N+hVWZteO0129YvvNAOHu+4o3OWO2mSve6PO85GnVmyJP3gMcstt9hrIt47f+KJ9lpOjuLRnhtu\nsNu/+GLbhg4+2NZPsumTJ1tgkey967nnKj8fCxfae8lZZ0Xb82c+Y5+EnXde+fkOa8Lrr9tzdvHF\ndjC67bbln759GJx+ur2nrLeevecmv7kxaeVKe31UO+pQV2pszB5tZvp0+zQqFJAkO5/C+w/vqA9z\n5rTdf3aG5mYrNnzpS9YSOHKknQDfHRB+SxobVy/8SraDT6v8PvOMhZzQjxg/WSLs5MMZ8p/4RFT5\nDTt4yXaaodqaVvmttGMPISke9sJ1Fy6M3qReesneiEaOjIJi+Bg+XkXcYgtrt1i0KArtoY1Csv7Y\n8BH3wIFWjZs2zcJduP1428OAARZuN9vMdnQrV1q/n2RvpKHSGP+YPaxbfL2SVfRwH7fayi7DSAY9\ne9qy4pXfEAjDbdTXR+0Yu+1mvYhf+5odtLz8st3v7be3kBQev/B8bbhh9Nhsskl0G0891bYSFtoq\nNtww6ic+4wy7vOQSu7zoIrsPc+aUh9945Tfcdn29PYbTp9tJYWnCpwkvvxyFMaltBTiIn/wVwu+R\nR1oFM4zvu2qVVX5DxXeLLeyxCuE3vD433tiet+nTLejEK+Vvvx21S4TnLt528tZb6ZVfySreIeRK\ntj3Nm2fhbrvtbFoY9qxan/iEfYrRGR5+2B7vujrpf/7Hdhqhd3PyZOnss21M7/AaXZNOPNFeT9/9\nrh30hhFAKmkvqHtvld799rMD5U9+0l771X4UvGqVVZCOOioaQUWy11b//lE7VbXuuMPuWzhIO/xw\ney29+aZthy0t9nhL1n8/e3blA50JE+yA+rTTyqdfdpkdrF19dW3rV6trrrFt59hj7X109GirsH1Y\n+n9vucU+UbzhBnucBw+O3sPT3H+/vXd/4Qv2mol/ec7adtNN0Qg4RxxRfrKtZK1V661nJ0wG22xj\nRZzHH+/ada3Gs8/a+m25pfXQd6YJE+zA7MILbV/4v/8bfYLzYUf4LVm1avXaHiR7k05WfltarCE+\nvmOO74ST4XennayKNm9eefjdcsvoCDne8ytVbnuQyiu/odIWKpQffBB9KcNrr1n18KGHouA1d669\n2cbXZfPN7XLmzKjy++1vW9/tGWdY+H33XQusofr461/bm13YscUrv/HQ+PLL9ns4oSkYMsTmj5+g\nM3duVMEOj0tjY1Rljp8Y2K+fBYuBA+2xDH2nyfAbjo432sg+XvzJT2wDP+EEq0IPHWrVyIUL7f71\n72+PW//+0cll/fvbG0JoBQgBffz4aF3D4xDC3UYbSXvsYTvkJUusf/Wkk6L5w/2MB9ONN7YddvxA\nqb4+qtaHj/uTQvj929+iHuX4suNVbimqaM+aZWG2vt4e25tuKp/vM5+JKr877hgdjIQe6rDOTz9t\nO5Ddd4/We/58ex2HA5X11rPt8cUX7fJTn7KwdvPN9v/kAeCWW1olb9kyC1+h7WHgwKhyXesOdp99\nbCijiy5K/39ra9tQ+Pvf27aQdP/99tgsWxbtgMLB7OjRFp4ef1y68cba1rFWr71m7y+XXmqvg6OP\ntp3VtGnp8zc1SXvvbWHmxhvtk5k0Tz9tyznnHPvbOXs+/v736tbrgQfsNXD00eXT113XnodaKsjv\nvGPvQV/7WjTtwAPtNTVpkrUthBNdpWgbSH7tfNwtt1j1OBwIBnV1diA4adKaG+qqqcm2l6OPjvrW\njznGtq9x49bMbdbijTfsoODoo60aWlcnnX++fSIUXuNxN91klcI997Tt+ZVXpFNP7fr1TrNihW2P\nBx9sj+0DD9hjHS9YTZxobYDx92Ln7P7Ev97+w2DGDDvw+/jH7ROZs86KWtVWV3OzjZ705S9H3y4b\ntjy61UsAACAASURBVLNw/saHGeG3ZHXbHqT0YctCmAvOP9++fSyI9zbW1dlHcHPm2FF0PHCGUBG/\nTgjBS5dWV/ldsCCqvEpRj2w8/N56q/0ednJz59p14tWYZPjt0cOqtqecYgHu7bftZ8stLSzuvbdt\nhCGESNEIBo2N5T27S5ZE48vGhZOW3n/f+mIvvdRuOx5+w3JCNST++G21lT0GQ4bYDuyNN+w5T7Y9\nxMPvkCHWghG/jaFDo7N6N9kkegzj69u/v31E2bu3vRkMHmwVrL//Papkn3ee3WbYOYR1DYE13mYS\nv2/xYLrddlatX7EiOqiJ94jH739cfBnxg7Jw3WTlt0cPC/DxtgcpqtJK9vr99KetF/K3v7WPPfv3\nt+eosbE8/IbRQX7wg2gdX3rJdvLxZYZhzLbYInqe/vhHW1avXvZ3eC2Gloe6OnvdzZgRHdxss439\nL3wdcrVOOcUC3IUXWutNnPf2UecBB5TvGEeNsgpoMkw+8IDNK0XjZU+datedMiXqT13TfZx33WWP\n0UEH2d+HHGJ/J79eXLL7+L3vWVjs2dMOAHfayUY0SQ71dfPN9rgfeGA0bZ997L4lPz6eN896BOMj\noEyYYK/F8GlL3Oc+Z49Ltf3Df/iDhcQvfSmatv76tm6TJtlB3777Ru1Sm25q209aUJPsPf3ZZ+2x\nSvPVr9rrvL2q32OPWUA655zaTgp78EF7rOIHBnV19vdNN1V/UBcOejqzj72pyar1gwaVVxW/+U3b\nli+4wP6ePt22p5Ej7XV+/PG2Hzz6aLveTTd1zacewdKl9qlE8nV81132er38cvvioNtus3azMWPs\n//fea6+T0Jcet9de9ilvLX3ua9Irr1hBYtUqu1/XXWc5IhS2Vtctt1jRLn5ia12dvc/dfXfn3Maa\nRPgtWVNtD8lKyUUXlffHxiu/G25o4SH50a8UfWuYVB7YQiiNz5vUr5+tV/zjcSkKbuGLAaZOtQ17\nv/0szFx1le304+FPsp33OutEJ35tvHG0Hp//fBSi9tjDdjCnnGJ/xyvrfftGQTMefqXy5QUh/P79\n77bc886zjy+TlV8pCr/hb8l2zFIUfkOYCaF1vfUs5IUKfPwgIW7o0KjV42Mfi0JnPNiH2x02LJp+\n8sl26Zxdf8wYC27PP2+3Gyr3IaiFqlRymeGxlcqHgguPXfj/ZptFO/ek+DLij18IxcnwK0VtJ6Hy\nG+7Lgw/afQiv2Q02sPvaq5etc2j1iYffsO4bbRQ9ft/6ll1+7GNt79N225Xfl/hr+ItftI8m45Wj\nLbaw19Z779l6b7edBZ7vfz/98cjSr5/t7AYMKD9ZSrIDxieftOWeeqrtYFasiCrBYSSPlhab5803\no/DrnIW8p56y1+qyZVbp33lnC/thh/zqq7bN1tqrd9tt9ngmK5E/+5mNxrDfftGnT+uua9vTo4+2\nXc53vmPvAddcYwfG995r1z34YGsVCEOQtbZaQPjKV8pHnNlnH3s84lXbt96y97KTT7awsGSJBZG7\n77YDhzR77WXvz5Uqs4H3FqQOPbTtJxiHH27h5Nln7XUTOGfBOyv8PvKI3cfQI5z02c/atpx2zkQw\na5aNFDN3rvTLX9ZWsb3rLnsNh2/GDE47zarloWARfPCBHSyE19HKlfYp0l572bjJe+yR3c9aq/PO\ns+1/woTy941evexTsz/9ybbH7baz53j99e3g8De/iT4pO+44e+2fc07XfFFEQ4O9fvfbz9Yxbvx4\ne5zCgfKhh9o8F10UjT09cmT5QV6w5572WHdWZXV13H+/teuFg7ott7THO5yQlizK1aqpyR6Xr3yl\n7evy0EPtvS35fQAfNoTfkuXLo5PQOiqt7eH996ONPIytm7yOZDvHjTayecNOIB5M4sN+hWDmXHT9\nrCqfZCdHPP203ccQNsJ1wsfN8TaDs86yncg559jHuMkqbM+eFnZef90qHvGPAjfZxJY3e3a0UYSd\nRvwM9759owOFeNuD1Pajxfj9P+208h1steE3hKqttrLlhxNo4o/lBhtYBWzAgPIwGxcCzPrr2xtK\nWOf4/PGTsILPf94etyOOsIMA52yH2dhY3g6y77627HjVKr7M+A49fkJbsvIbv+9JHQm/m21mrSzx\nyq9kr5udd06/nf79o+AWAnN4vEN7Q+/e5a0X8fAbDgSGDbMdZqhSx7fT+noLHWF5ku1sn3/eKkvh\ntbTffm3DUDV697bn4p577HV13nkWcsPB0xlnWEXlhhvKq72hZ/7MMy301NfbOgRHHmnV4FCB/dSn\nbIe7cqWF9sWL7QAhtOlU20vovQXLa68tD7RTp9qOb8mS6GA0+Oxn257wNW+ehd6LL7Yd/gYb2A4/\nfJvgSy9FBxNPP23b+1e+Ur7cLbe0SlO89eHMM+097h//sNfTMcfYTnTlyuwe9R13tNuv5iPlp56y\nkx1PPLHt/w491LaZ3Xdve1s77pgdfh9+2N7v4p9KxDlnwfquu7K//OL6620bf+YZe3+/6qrqTnhs\nbbVh2cL413HbbmvTL700GobwoIPsvWDECHvd3Xyz/X7bbfa8vfqqBd8f/rD9227PHXfYSXc/+5lV\nGJOOOsrC5De+YQddb7xhYficc8oPZnv0sNfas8/adt6e5cttGZ/6lL3WV6yobb0vvNAOyvff39qN\nQuX8/fftuU5WdX/4Qxtd4+677SBm3Lj0wsLOO9t7a2e1Prz4ou0Pjj8++wB4/vyoDU+yTxR+/nM7\nQN1rr7YFomOOsffYM89cvRNub77Z3g9DZT/u4IPt8q9/7fjyu4T3Ppc/koZJ8pMnT/bVOPRQ7w8+\nuKpZM515pvfbb18+7dxzvf/Yx7z/xz+8f+edttdpbfW+Rw/vJe+/8AWbdtNN9vf555fPay/X8mnb\nbGPTLrsse70efTS67j33RNO/9jVbX8n7Sy+N5lm2LPpd8v6rX227zEMOscfr8MO933//7NsO3nnH\n+1Wror8vuyxa/rRpNi2swwEHpC8jzP/cc95/7nP2++23R/+fOdOmjRzp/QYblF93wgT73wUXeD9m\nTLSsWbOieTbZxKademrl+7Jsmffvv2+/f+Mbdp1zzon+P3q0TTv77PLrzZzp/fLl0d9nnGHzDRtW\n+fa89/6889quW2trdD/eeMOmXXSR/f3FL2Yva/ny6HrPPx9ND4//977X9jpnneX9DjvY43rFFe2v\nr/feH3WU9/X1tsxnn7Vpf/+7/f2Nb0TzzZnj/W9/6/1tt5Vf/8Ybvd900+j18be/2XW33rry7d56\na3T/rr++unWtZnlf/KJdXn659xdf7H3//vYc7LOPbQvjx9v/TzzRLl991dZ/2DDvX365fJmtrdHz\n36eP/f3qq/b3ww97f8cd9vt++9nld75T3bpOnhzd9zPPjKZffLE9d42Nba9z1102/7vvRtNuuMF7\n5+y5SXP11XadX/zC3rc239z75ua28518sr1uvPf+pZfsOuF5/s1vonX90Y8q368DDmj/faa11fs9\n9vD+k59MXxfvvW9psfmSrrvO3ofj22cwdKj3J51U+bYfe8zux5NPpt/m5pvbY+F99Dp+7rlonkWL\nvP/9772fO7f8uk8+afM+/nj67b74oq33XnvZa23gQO/HjbP707+/XfeTn/T+X/+KrnPBBd6vv773\nixdXvk9Zliyx/VrfvrZvSHs8O+J73/O+Z097LLO0tHj/la94X1fn/QkneL/eevZ+n/a8pZkyxW7j\nkku8f+UVe3xuvdX+N26c9+us4/0HH6Rfd+lS799+u/Ly99139XOE997Pnu39kCHeb7ml94MG2b7p\n9dej/7e22nbUp4/dh549vf/4x+0nvIdnbQN//avNc+WVHVu3hQttvdJyQfDZz3p/5JGVl/PGG/ZY\nbbCB9zvuONlL8pKG+a7KiF11Q139U2v43XdfC4OrI2w8P/uZ98OHW9j75jftjamSDTe0Z+KII+zv\nf/7T/r7wwvL5Jk1qu5MYNszmve667OW3tEQ7maeeiqafemo0/Zln7DJsuPHwmxYGv/1tC/V77OH9\nMcdUvn9pfv3raPlhB3v99W2DUdy669r/W1ujMPjvf0f/X7rUpm2zjfebbVZ+3YULvT/uOO+nT7eg\nFW47/gYxeLBNmzCh+vvx/e/bda6+OpoWAmilAxLvvb/vvsr3N+7yy23e7363fHq4HwsX2t8//7n9\nXem1HA/N770XTf/lL23amDHpt9+rl/1//Pj219d77087LbqdV1+1aQ0N9pp58cXqlhH38su2rM03\nrzzfBx94/z//Y9tRZ5g9u3x7+Pzn7Y09bNfnn+/9RhvZNvHRj0bP6/rr2+Wdd6Yv94037P8DBtjf\njY0WZK67zrb9j3zEpn/9696PGFHduv7gB/Z+csop3m+1VRRMdt01en9JmjHD1uPPf46mHXKI93vu\nmX07ra02j2T3/d570+ebONHmef992/422SQK4K2t3j/xhPdvvtn+/bryStv+K4Wchx6y2/rrX9tf\nXtK//uXbBFLvbfuQ7H5U0tzs/cYbpx84hgO+8N7b1GQh9dxz7e/WVu93283/N6jGiwRnn22PWVaQ\n8d77n/zE+2239f7448sLLC0ttv4tLeXzz5hhr7Nrr618n5IWLbKDsu22s/B54onR+05nWLXKtqlw\ngPuHP7Sd54Ybyl+r//iHBeCvfz09hP/733bQcfbZ9t5z1FG2fwiP8d57R9vxF79oOWB1XHqprc+y\nZau3nDFj7P1j1ix7/9l+ewucb75pr6MvfMEeh8MPtwOkX//ano9jjsk+UIo791x7DdxxR23rtXSp\n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\n", + "text/plain": [ + "" + ] + }, + "execution_count": 45, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "qc.MatPlot(data4.samp_acq_controller_magnitude[1]).fig" + ] + }, + { + "cell_type": "code", + "execution_count": 30, "metadata": { "collapsed": false }, @@ -443,40 +544,47 @@ "text": [ "DataSet:\n", " mode = DataMode.LOCAL\n", - " location = '2017-01-23/10-43-04_AlazarTest'\n", + " location = '2017-01-23/15-55-55_AlazarTest'\n", " | | | \n", - " Setpoint | samp_acq_controller_demod_freq_0_set | demod_freq_0 | (9,)\n", - " Measured | index1 | index1 | (9, 4, 1020)\n", - " Measured | samp_acq_controller_magnitude | magnitude | (9, 4, 1020)\n", - " Measured | samp_acq_controller_phase | phase | (9, 4, 1020)\n", - "started at 2017-01-23 10:43:11\n" + " Setpoint | samp_acq_controller_demod_freq_0_set | demod_freq_0 | (11,)\n", + " Measured | index1 | index1 | (11, 1, 3000)\n", + " Measured | samp_acq_controller_magnitude | magnitude | (11, 1, 3000)\n", + " Measured | samp_acq_controller_phase | phase | (11, 1, 3000)\n", + "started at 2017-01-23 15:56:04\n" ] } ], "source": [ "# in a loop\n", "\n", - "data5 = qc.Loop(samp_acq_controller.demod_freq_0.sweep(80e6, 120e6, 5e6)).each(\n", + "data5 = qc.Loop(samp_acq_controller.demod_freq_0.sweep(1e6, 21e6, 2e6)).each(\n", " samp_acq_controller.acquisition).run(name='AlazarTest')" ] }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 33, "metadata": { "collapsed": false }, "outputs": [ { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAA+gAAAJYCAIAAAB+fFtyAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAg\nAElEQVR4nO3dbYwk6X0Y9n91z+698O54JE8UKVuz2o02dpSmTEkQcEimrTsfjDXgGNbGn4SxjrqJ\noqwAIYYDG9YCw3AdTrROYAiWPwgLm5lzGDUMfzrCiB2tifUt3BOHZkCDiDu0pYmW2pFkyXw53vF4\nt3e701350FM11V3VM90zs/0y+/uhMaiut+ep56mq+c8zTz2VpGkaAADAfKvNOgMAAMDhBO4AALAA\nBO4AALAABO4AALAABO4AALAABO4AALAABO4AALAABO4AALAABO4AALAA5iVwbzabs84CAADzRYhY\nNC+BOwAAcACBOwAALACBOwAALACBOwAALACBOwAALACBOwAATCBJkpmkuzSTVAEAYBH1o/ZJY/c0\nTY+ftMAdAAAOlwfrX/rSz0+04fPPf+5EMiBwBwCAgwyF7CcViE9K4A4AANXKIXuaphGfS9PumHv4\n83/+L/yTf/JPTiQzAncAABhW2cq+31V97D7r//Sf/tOTypLAHQAABvSj9uqQfXYE7gAAsGfskL03\n1WxFhMAdAABisG/MGK3sM2iAF7gDAPBIG/EE6sEE7gAAMC2HPIF6EIE7AAA8fMcI2SMiIj3Nfdy3\nNppXb0ZEXLreXl+ZVqoAADBkPgeNOdR0Aved1trVuN5ur0RsbTTXWq3N1eWpJAwAALkJn0A9wKlt\ncd/5+valF/rN7CsvXLp6eydC4A4AwNQc6QnUA5zmPu537u7EynJELJ+/mE8PeP311/sTL7744rRy\nBQDAKVcZsqfp3z/eXk9t4L6y3rq7ttq8sff10vWq9vaTjdf/dpKciTgbkUSkEQ8idiPuR7wVcS/i\nXsS3sok3I+5HvBPRjehG7Eb0ItLsa68wJ4moRdRLafX/U5Jmq+VzatkKSbZ5Wlg5IuoRSbZmkq1c\n3ENaSLq/2tB/ZWpZrqKQseKueqWfxRWG1LMd1ge/5mnluepmmUyr/lE0dAjFPRyQenmdcgGWVyuu\nU7m3oaLLy+FBdiAPSuU8Kku1wsxixQ397BtKrjc6ldrg116phPvr1wvrl8s2BpMuVkEUqrJWOpCh\nIxrKT7HG+9PdLG9pqZqGUk+qajPJth3aJJeW1q+NqOjylRKlE7LylMs3HKrZpLRON/vZ32c922d9\ncMPigdQKJRCD03luyyUcgweeDJ66Udpn8eiKM9Oqq7J4wuTZHnUIlSdeue56Ed0soTzDS4V70VCd\nDpXG0L2onuXnTDazXrhnFjOWZ68b4xpKsVe6FpLBW2taqrWi4mq58pnTKxVO+VYfWboH3BhHneR5\nuvkdu7yTfhHtZsWVl1jxkGuDJROjD3xIMdH64Lla3FV38GsUViieAEO/WMu/K6OURJRO8nIehn4d\nL2Vn2tls4kyW+eJu6xEfjHgy4pmI8xEfiXgu4k9GPBfxoYj6uag9FcmTkTy1l2T6TqT3ovvvo/dW\nfPdB/NuIb0Z8M+K3It6IeDvijSwPZwoXUTfivYjdiAcR7xZClF5WGsWqfG8ROl4/bP/qX/3XJ7Kf\nvG/Ml7708yewz1lUzbRa3JdXN9urERE7rbVr+skAADCWM2eO2TQeX/nK3/+Jn0ief/5zX/nKSUXb\nn5tJi3tl09vDs9O6diNeagrcAQCYmq98JT1y1N7pdKpmp2N/Tsy0Wtyz0SAvXjGiDAAAC6PRaHQ6\nnUajMTj7FHeVWVlvt9enlBYAADxUp/oFTAAAcGqc4hZ3AAA4PQTuAAAwT6o6uIfAHQAAFsLpHw4S\nAAAWSX9UmdLsUzwcJAAALKDqrjJGlQEAgEWgqwwAAFBF4A4AACON6OPeG/tzYnSVAQCASRkOEgAA\n5l8qcAcAgAUgcAcAgHky4s2pMxgO0sOpAAAw0oiHU2dAizsAAEzIC5gAAGAR6OMOAADzZEQfd29O\nBQCAeTKij3s69ufEaHEHAIAKebw+Jy3uAncAABjQD9lfe23va0XcLnAHAIDZGmvwR29OBQCAeZA3\nt49gOEgAAJidvLn98uW9OSMieC3uAAAwO/3nUIu9ZfIIfpDAHQAAZmfosdQ+D6cCAMB8yUZ+7BzS\nx93DqQAAMEOVLe5VBO4AADAjY0ftYVQZAACYtvxR1PFC9j4t7gAAMC2TNLHPnsAdAAAmlOoqAwAA\n05KPIRMTt7vPoKtMbfpJAgDA/GhUjdN+mHTsz4nR4g4AwKOu0WhM2O7u4VQAAJiFYreZODyCF7gD\nAMDs9MP3fIDIkbw5FQAAZqvT6YzRYcaoMgAAMDvjRe2hqwwAACwEgTsAAMzU5cv706Nb3wXuAAAs\njK2N5tWbERGXrrfXV8ZdurWxdvflzdXliNhpra3e2I6IiItXWv15s1Ua031Ez5lZPJzqBUwAABzF\n1sbVuN5ut9utK3eubmyNs3Sntdbci+b7379+4Xq73W6329cv3LjW2ple5sfUaDSKDfAFM3gBk8Ad\nAIAj2Lp989ILKxERy82XLt65uzPG0uXVzXbrysV8rZX1rCl++fzFWCjenAoAwMJZPndh+/ZORHVP\nl4OX9u20b8VL16rW+OpXXy9+/eQnXzxGRifWH2RmuPtMhOEgAQB4BG1trN56qbVZGdlPOVIf0mg0\n8nepDtLHHQCAhbNz987F8yMb1A9eGlsbzc3zc/Fg6iTSdNzPyRG4AwBwBCsvXLp5eysiYqd9a/vC\nub1RYpr9B1GrlpbttNYWMWqP0McdAICFsbJ+/Xaz2YyIuHS9PTwaZOXSfPjH1eaNS9fbL9+9tR3b\n26vNGxExNyNCDmk0Gp1OpzRMpHHcAQBYGCvr7fZ6ccby6mZ79NL+8tXiDga/zplOZ693eylqj1Md\nuO+Prj+ff0oBAMCw/tuXquL2UzuqzE7r2q2XWu3N5Yitjea1VlPoDgDAvOq3tVe/M3XPKW5xzy3c\n4PoAADwa8r4xB4bsMzOdwH15dXNtY+/phItXRgzS+eqrr/YnXnnlleMn+VMRT0U8W4/ksYizkfQP\ntBu9dyPej/civhnxTsS7Ed+JuB9xL6IbkWaD6acR3YhuRC/ifva1F5FGJIMJ5Yu6hb+8liJqEWcj\n6hH17GuSrdDfZ3//+cRutv+ISCLq2SZnsp3UI5LCMEC9LLdDP6NwCEXFfdYPPIT+ARZT709E4di7\nhSLqFjLQz1698DPPz27Eg4g04n6hJGsRSxGPRyxF1LMSy8tqqAqK5d9fLS+ToUqJQlF0swz38/xg\ncCKyfeapn4l4ImKpkJn+gXcLO7lfOvZc5b/N8p3kE/2ZvSzzlT/zHabZgeTHEoN1nR9yr1B3taxU\n+wdVLKJuYZ955oslWcvSzY9xt1CYMZjVYl3E4E6GDjYGL6UHhWz01UsnXn4yFPMThU2Gym3oGLtZ\nKlEonPyq7J+iQ+d2scqisGEMnkXFPESp1vINi9dFXin5yr1CgewWSnuoNM4WNixmNa/H3UJ+eoMn\nQG2wGGMw0e7glVXZdlTPEq2XCjkKt6woZS8tFFrxRK0V7mnFu0R+P9wdvEvE4OVZruvKayEvol7h\nZOivlp+xQ7fovHDuZ2fO/cI1MnTnKR9pDBZFvVBoUajxKNRaLzve7uBVkN+RzmQTSVUO38u2fVDY\ntjZYtsXLJwo5WcpWXhosz/zOtjt4iygWez07xiidTjHiuqgPXtHFmuoN1k7xQIq/rYpnb/4zBou3\nXthk6BYahStxKTuXHstK+LEsxccizkZ8OOKZiA9GPH4u6s9F7aNxphH1j0b9uVj64Uieiag9mdSf\n6ldp2v1epO9270bvW/Hst+Lj/ya634juN2L338a9e/GdiG8WTuzIfvV0I96NeBCxm4UfxStlqMqY\nvrFD9lPbVSa2Nq7G9XZ7Zae1tnrj81ur68PPHccJxesAAHAEeXP7eE5rV5md1uadK9fWI2J5dbMV\na9daOys6uQMAMHNH7R5zWgP35XMXtq/utbPvtG9tX1gTtQMAMHXlZvUjdmc/0Veijmk6XWVW1ltX\n1lb3+7hXdJQBAICHphiyn8Szp6c2cC+Ptg8AACdvnK7qly8fP3Y/xYE7AAA8BEOR+rRGcjy9o8oA\nAMDD0Gg0YuIxYY5PizsAAEyuH75HRMTJ9mUf4fQ+nAoAANNQiODjYQbxAncAADghDzOIF7gDAMBD\nMCqIjyPG8QJ3AAB4yIpB/FGfahW4AwDAw5fH60d9c6rhIAEA4OHLB5G8fHl/5iRBvBZ3AACYlsGO\n7zHJA6wCdwAAmJGhB1gPjN0F7gAAMAtDT6lqcQcAgLlTHlsm7/teHcF7cyoAAExfqbP7fihffHq1\nwKgyAAAwU8XW935zeymqD11lAABgxg54x+ps1WadAQAAmEf9pvcRT6n2xv6cGC3uAABQIWt6r2p0\nn8XDqVrcAQBgpEajUR5zJiId+3NitLgDAMBInU6nPOaMh1MBAGAh6CoDAADzRFcZAABYANVdZVIv\nYAIAgAWgjzsAACwAfdwBAGCe6OMOAAALwHCQAACwsLw5FQAA5oquMgAAsLgMBwkAAAtAH3cAAFgA\nAncAAJgnI96cKnAHAIAFYFQZAACYJ0aVAQCAxWVUGQAAmH9ewAQAAFTS4g4AAJMyqgwAACwAgTsA\nACwAgTsAACwAgTsAAMyT+XlzqlFlAABgJC9gAgCAxeUFTAAAsAD0cQcAgAUgcAcAgPk3i4dTpxS4\n77TWVm9s73+/dL29vjKdpAEA4KSd3sB9eXWzvbo3vbXR3Dy/PJ10AQDgITi9gfu+ndbmzUtrbYE7\nAACL6xEI3Lc+fyOutCp7ybz++uv9iRdffHGaWQIAgAmd+uEgD2xuP9l4/YcuRu374swPR+1DUftg\n1P94JE9E8mTUnoqoR9RjOY3oRbob8X6ku5G+H5FGdLPtk4h6JPWIesRSJElELSLJlvb/xCrXV62w\nef9nLSIi6c+vZztJIinuLSLSSPtJ70b0Iu1lOSn+LZdE1At7y9PqZU9H5Jukg3mrDWYp9rIxcFD1\nqlz1M9aLSLOM9YuomETxkEvb9lfLH95I+issRdQiqUWcySaWCnvId55GupsdVzfSwvzhkolC0klp\naWVl1YbraC/ppLB+vpNkYKskGSj8iEh72frdiMGHVfZXrmUHWxtMdKjE8qwOpV7bL+GkPrB+2t1L\nOu0O1k4x3aXCKd0/kfJU0sKGvexYSgWVJJGmez8jP9+yDA9UcX5og4e5t+3QwcaI+96oV8NlJbZX\nCMneqTtQLFE4b9OIB9l5Wz60rHz2qjXfOi/D3YiIdHfw3ItCpUThRKrKdrlA9s+B4kU3eDfYO4T8\niu5P5JmvVZwVA5vnV1DpNjKcer1QTX3ZJmm3sMO8hPMCL94Mu9n6DwqnUJoddX7I9f374X7t9M/b\n3ewa7xZy0t82Sy5ZynYSVcU1dNUUKnr/rDugaSwpzRl1k69HkuzfzPfPw6RQcfndoFsojeLJUyqW\n4r037Q6eusXbb76P/L6dFVTxEIonc/WtJvbv4Wk6WG755ZAf41KWRG1w890sq/ez31ndvUzu/3JZ\nyna1lB3v4M1z4BYag1dZZfkX81C8M+drFn/pjKrxPKv3B3/h1iJ5PJLHovZsJE9GcuZs1J+L2pNR\nezLqH06Ts0nyWNSeiKhnFZamaZqk99PYXfpP34n0/ei9/8RfeCPS96L3btr9dvpuLN+L3nciHkR6\nf+9+Etl1lJwt3J9HKVccc+UUP5zad0BzOwAALI7THbjr3Q4AwClxmgP3ndY1ze0AAJwOpzlwLw4I\nCQAAC+00B+4AAHBapDMYVWbU2A0AAMAc0eIOAAAjdTqdRqNRmj2DrjJa3AEAYKRGo9HpdEqze2N/\nTowWdwAAGEmLOwAALIDqFvc0HfdzcgTuAACclK2NZt/G1gRLtzbWWjvTyeCJScf+nBiBOwAAJ2Nr\n42pcb7fb7daVO1dLoXvl0p3WWrN59ebUszq+0V1lBO4AACykrds3L72wEhGx3Hzp4p27O2MsXV7d\nbLeuXJx2Vicw4uHUGQTuHk4FAOCkLZ+7sH17J2L5CEsH/eZvvlqe+ef+3CvHy9/xzeAFTAJ3AADm\n1xzE6FVO9KnTMekqAwDASdu5e+fi+ZEN6gcvXQz6uAMAsKhWXrh08/ZWRMRO+9b2hXPL0X/4tP8g\natXSBaaPOwAAC2tl/frtZrMZEXHpentlnKU7rbXVG9sRsdq8cel6e314o9mbnxcwCdwBADgpK+vt\n9npxxvLqZnv00v7y1alk7aj6o8qUYneBOwAAzL9ZPJwqcAcAgEkZDhIAAObJ/PRxN6oMAACM5M2p\nAACwuPRxBwCA+efhVAAAWAQCdwAAWAAzGFXGw6kAALAAtLgDAMCkdJUBAID5l3oBEwAALAAt7gAA\nsAAE7gAAsAAE7gAAME86nU6j0SjNFrgDAMD88+ZUAABYBF7ABAAA86TRaHQ6ndLsdOzPidHiDgAA\nk9JVBgAA5omHUwEAYN5VdZKJCA+nAgDAPOm3tVc1ugvcAQBgAQjcAQBgnozo4244SAAAmCeGgwQA\ngIXl4VQAAFgEAncAAFgAAncAAFgAAncAAJh/qVFlAACAKlrcAQBgUrrKAADAAjjdXWW2NprNZrPZ\nXGvtTC9RAAA4eaf4BUxbG82rcb3dXplSegAA8PCc3q4yW7fvXGltitoBADgNTu+bU7du39y+ebN5\nIyIiLl1vr1eF8K+++mp/4pVXXplKrgAA4GhObeAe++H6TmttdWOrKnQ/4Xi9FslS1D4S9Y9F/WNx\n5kcjOfuhqH8kPXshqT+b1p5Jlj4WtccjeSLqT0VyJpLHI5JI6hFJtousPvbG6UyH5x9UYUnhZ2Ei\nKT9UMLROkuW+OD8prF8bfBhi/MwMTdcioiqVUY895ImmI5JLSnPyAkwjeodltbz5AZIs/7Xsaz07\nlnppb/3ksgyk6fCcYn4q/no++NGTrLiSykIekmcg321aml9OcSiJwfNkP82kaieDZd5fOryf/slW\nPAGG8t/fSbcqqwVJ6aj36j3LzP5pUOzwlyfaz0Y+sRSRZBnLjzQ7qDSN6O7tZ2C3AxkaPMA48BiL\nR9or7LlbSqJfAlkd7Z+Byei0juaAE6948Q7daooHElnmD9jbmKdQ8VourDwyA0M5yU+bfJ9paZ3y\nPfPQwxxl1OFX3rvSihv1BHVXWbDFfZZK+JBbZeVuy7frSgfeYYbSGjbezveSyO8Gg5fD/s6y+/De\nr9T8Fr2UXdT5RD270vNLKU+rl92u04helmjxkizeWHJDZZVnP7+K+7vqRdqL6JZS6UV0o/d+pPcj\nfT/tvpH03o7u2/Hgd5Pud6L7Rvc/fKf3rei9Gd3/EPEgIiJ5JmrPxNKFqH0kkjMfTM/+R0n9B6P+\nwWTpY8lzT0byRL3+VMRSJLXsqPNfUsne16SWlcNSVmi1UkDCfJpB4D71cdyXmy9dvHPX46kAACyw\n3tifEzOdwH3lhUs3N/uDyey0b21fOLc8lWQBAOChOL2jyqyst+6urTZvRMRFT6kCALAoOp1Oo9EY\nnnt6H06NiOXVzfbqtBIDAIAT0Wg0qmL30xy4AwDAqSFwBwCABSBwBwCABSBwBwCA+Vd+icHDJ3AH\nAIBJaXEHAIAFIHAHAIAFIHAHAIAFIHAHAID5d6rfnAoAAKfGDEaVqU0/SQAAYFJa3AEAYFK6ygAA\nwALwAiYAAJgnnU6n0WgMz/VwKgAALAKBOwAALIAZBO5GlQEAgJEajUan0ynNTsf+nBgt7gAAMCld\nZQAAYJ6MeDjVC5gAAGBudDqd116rXKKrDAAAzI1GoxFR7uAeHk4FAID54uFUAABYXB5OBQCAeTI/\nb07VVQYAAEbSVQYAABaX4SABAIAqWtwBAGBSJ93i3vtepLtRf/aAVbS4AwDAhNJ03M/hu7ofaTf+\n8G/Et/7OwSsK3AEAYFIn8nBqGr3vxXf+QXSW4o1fPzRJgTsAAEeztdHs29gaa2lpzk5rbW/OWmtn\nWrk+GccO3Ltvxbv/V2x/Iv7gvxkzSYE7AABHsbVxNa632+1268qdq6XQvby0NGende3WS612u91u\nX79w49pihe69sT/lTd+J3W/E7/1M/M5/Hvd/d/wkBe4AABzB1u2bl15YiYhYbr508c7dnUOWHrj+\n8vmLU8r2TKW7EWl843+If/v98fb/MenWRpUBAOB4ls9d2L69E7F80NJzpTmrq5trG81mMyLi4pXW\nZuXmX/3q68Wvn/zkiyeW7WOZ/M1Kve/Gd//3+P2XI+0eLUmBOwAAs7HXeWZlp7W2euPzW6vrK+V1\n5iZSH5SOOxzkxz/+8eh+Nx7ciZ3VeP9rx0lTVxkAAI5n5+6di+erm9srl/bn7LQ271x5eSUillc3\nW1fubC5UJ/dxH0793a//dvzBfxXbP3bMqD0E7gAAHMnKC5du3t6KiNhp39q+cG45+qPE9B9TLS8t\nzVk+d2H7xuf7D7Xu72JBjP1s6v/8P12PH/zf4kM/d/w0dZUBAOAoVtav397roX7penu4l0t5aXnO\neuvK2up+H/eKjjKL79Of+ZX1//5/jI//nfi+X47f+9m4938feVcCdwAAjmZlvd1eL85YXt1sj15a\nvf7qw8zhCeh0Oo1GY3jupM+m1j8Y9Q/G+X8W79yO33s5em8fISe6ygAAwEiNRqPT6QzNTHvjfgbU\nn42n/4v4kW/FR68dIScCdwAAmNCRX5yaLEVyNr7vr8ePfCee+S8nSlPgDgAAI43sKnO0wL2v9mTU\nn40//r/ED38lHvtPxsyJwB0AAEaq7Coz/qgyB6k/G0/8ePzwl+KP/68RyaE5EbgDAMBID6XFvaj2\nTDz7M/GJXjz5nx28olFlAABgQpOOKnOw5ExExAcOGQ9TizsAAFTrdDqvvVa14ARb3HO1Jw9ersUd\nAAAmMzzO41QI3AEAYF/xUdTq5vY46a4y4xG4AwDwSBsaNGZksF50qgP3rY3m1Zt70xevtDZXl6eV\nMgAAjNYfNKYfvo8VtccpD9wj4tL19vohz8oCAMAsZGM+jngadchpD9wBAOBUOO0Pp9682rwZozvK\nvP766/2JF1988fiJpe9G+iAiIs5E8ngkZ56K+nPp0vcnZy9E/bmk/qE4+0NRfyZqT0f9w5E8HrUP\nRLIUkURSj4iIXqS9iG6kvYjdbHo3It37GcXHifOJoT++DvhbLClNxIjROYd2nhZSL8+pTDSJiEhq\nheSSqpn5ysU9ZNMDOx+dh35u03Rg2+GcJNmRZqkntSxL+XRh/YGJrIiSoUWjXjaW5SRNs5JMC3ke\n8Uz4cLEM7Xxo88EdFveZ5BVaPrpCCSSD+08LJTmU3KgiHfg5tM9yyeT5LO4tT26ohLN8JtkhRPmc\nyXfb29vVXmnnE6Ui2s9bts+9/deH060u/MGzcbjE+osOf//cYFUOnSFpoXKHzvahQ4iBak2KOR8s\nt2Tw6hs5Gu/QtTZ0Sowxf+RlO0qyX1z7xzLqykoLE+nwJXB4iuUdVtVUUhuxTmli5JqTJLcvLd0D\nS7foJBnMRq1iTrVR5+1QrWUTA1dx/0yrF74Wro7+mmmxanqF8zYiuoVER/3CKh/vkHRworK6S7fB\ngX0P3RKLR5TfaorXTmHNqEX0sp/FPHQLR9otzEn3c7iXbj2SWkQtkrORLEUsRe2xiKVIlvZ++0ca\n6YNIH0T3jeh9L7pvJe//Vuz+UcS/T9/vJPd3Hvx/D979h3H//4nv/lb8LxF3InoRPx3xExHf/5fi\n7CfiTOOtM42306Xnov6R5PEfjaWPRv3DceYHo/aBqD0RtScjapHUI+3fHh9EuhvRi/T9SLsR3Ugf\nDOQ/PeCa5eFqNBoRh/eZmUkVTS1wX1lvt9cjIrY2mtdazYrQ/UTidQAAOI5Go9HpdC5fPjB2P9WB\ne275/MWppwkAACVD48nkDu/mfpoD962NjVhfX4nYad/avrBmSBkAAGYkj9fHHUOm7DT3cV8+f2e1\n2YyIiEvX28aWAQBgJoqt7Jcv701MHMGf5hb35dXN9uqU0gIAgBGyYR/3jOotc4jTHLgDAMA8meyN\nS0Nm0VVm1KhVAABwauUN7XlvmYmk6bifE6TFHQCAR85gh5ljNL1PkcAdAIBH1BE7uMfpHlUGAADm\nTLndPXdIA7zAHQAAZmJotJk57D8jcAcAgGFZHN+pjt21uAMAwAIwjjsAAMyPRqMx1Pe9L9XiDgAA\ncyJ/Q9Nw7/cZ8QImAACoUHpctaA39ufkaHEHAIBqo7rKzOThVC3uAABQrdMZMarMLGhxBwCACgdF\n7bMYVUaLOwAAVLt8ecSCWfRxF7gDAECF/sOplbF7mo77OUG6ygAAQIW8q0zF6DJewAQAAPPgkMdS\nvYAJAABm7vDBZLS4AwDArPRflRoRhw8BKXAHAIApy+P1vrEGbhe4AwDAlDWGHz49vN091ccdAABm\npdj0ro87AADMkQmC9SJvTgUAgGnK+8lMELVHRDr25+QI3AEAeKSV+riPYRaBu64yAAA8io7YSabP\nw6kAADBNE4fsffq4AwDAw9bpdPLm9suXj7KHNB33c4K0uAMA8Egrxu7jNsAbDhIAAB62A59G7YwV\nu8+ij7uuMgAAEJE9rjpW5xmjygAAwPQVR5gZi64yAAAwfaXOM504uL+7rjIAADBzh7+SSVcZAACY\nB41G4/B29+kSuAMAwIB+l/cDQvbUm1MBAGDmsq4yo8N3gTsAAMyJYvg+DwTuAAAwoVkMB2lUGQAA\nGKnRaFSM8t4b+3NytLgDAMCE9HEHAID5N4ueMgJ3AAAYrdPpVLyPyZtTAQBgrsxPH3eBOwAAjFTd\n4j4LAncAABipusU9HftzcvRxBwCAkR7dPu5bG83mWmtnyqkCAMCRPKIt7lsbzc24dHGaSQIAwElL\nT/ebU3daa5vnW5svn59aigAA8FCc4hb3ndbatbi2uboco3vJvPrqq/2JV155ZTq5AgCAozi9b07d\nad/a3t5ebd7Y+766Fq3N1eXBlU42Xq99JOofidqzUXs6kqciksfSpB4R0buXJtYa0OAAAB6uSURB\nVN9NIuLBUnQfj+SxSB6PpBaRRESk3YhupP1RN7uRDv6hlPT/QVHvf9nbpNLemtk6SXGTJKIWSTK4\nk6E5tf2dJ6MSSrPs9fb+oEu72URhZsUfeslgxpKIZH8i8pyXkosopFX8WlwhT2Jo4uD/7fQKe0gj\norD/GF5UIamarkUUSy87tP2qyQo5KR1sWkyuKg8D/x474MLN8xAjKjGqjrfyMKtKsr/n4f/VjVlo\nQ7kYqtDytnlJ1vdKNVkaOF3zYty/arrZqdIdPC3Lx1UbLKVk/zCT8rlU+bWQ5+pjGTqQWnZuFPOf\nDO4qBi+x4s6HdjmU+REZi8qKPqC6C5VePktjqNb6+++O2Oeoch7KZAwW4FAmyxdafk0N3k/2irSW\nrXPw/aR4zgydvYXp4VwV62joWPOjq2fZi+H7anVO8oQqL+riLSU//KR0gedXaJbVNL8cspyPOpaR\nKm9xo5T3llbfk8u/hkbuv5Thves6sl+XvYgo/A7qljLTP0NqhXMvn3PoQaVZQkP7HHWBD/0sr5wO\nrpMMxgC96L0TvXuRvhsPfi9234jut5Ldb/befRD3I3km6j8QT78fP/O78b2IJOKHnoj6ctS/vx9p\nRHTfTHb/KNJuJEtR/2AkH4ilD0WcieRMds8sV1Aty0Atu4j6t9nsCnr8Tx5YPszO6e0qs7y62d7T\nunLx4pVy1A4AwKLZ2mj2bWyNtbRq/Wzegg1fMouuMsZxBwDgKLY2rsb1fsPsnaul0L28tGL9rY3m\n3rz2grXrenMqAAALYuv2zUsvrERELDdfunjn7s4hSyvW37p950prfWXqWT++NB33c4Km/gKm5dXN\nzWmnCQDAQ7R87sL27Z2I6jbzvaXnSnO2bt/cvnlz7ynIS9fblSH8V7/6evHrJz/54oll+zhm0cfd\nm1MBAJiVLFzfaa2tbmxVhe7zEqkPOb0PpwIAcHrt3L1z8fzILurlpeU5Vb1t5pqHUwEAWBArL1y6\neXsroj/y94VzyxGx01rbGzGmvLR6zmZ/MJn9XSyIWTycqqsMAABHsbJ+/Xaz2YyIuHS9PdzJpby0\nak7r7lr/VT8Xr7Q2F+kpVX3cAQBYHCvr7fZ6ccby6mZ79NKKOcurm+3Vh5jDh0bgDgAA8+9kx3kc\nk8AdAAAmdKKd18ckcAcAgAlpcQcAgAUgcAcAgAWgqwwAACwAb04FAAAqaXEHAIDJpLrKAADAAphF\n4K6rDAAALAAt7gAAMCHDQQIAwALQxx0AABaAPu4AAEAlLe4AADAZw0ECAMAi0FUGAACopMUdAAAm\nZDhIAABYAPq4AwDAAtDiDgAA8y8VuAMAwAIQuAMAwPzodDoR0Wg0hhcYDhIAAOZHRcjel479OTla\n3AEAYEKz6CqjxR0AAEZqNBr9DjMDemN/To4WdwAAmJCHUwEAYP4ZDhIAAOZLp9OpeERVH3cAAJgr\n1X3cjSoDAAALYBbjuAvcAQBgQvq4AwDAAhC4AwDAAhC4AwDA/Ev1cQcAgAWgxR0AABaAwB0AAOZK\n9QuYZtFVxguYAABgpPl5AZPAHQAAFoCuMgAAMCGjygAAwPwzHCQAACyCWYwqo487AAAsgKm1uG9t\nNK/e7E9eut5eX5lWugAAcHSP3nCQW7fjervdbrfbrSt3Nls7U0oWAACOo3o4yN7Yn5MzrRb3lfX1\nvamdr29feGF5SskCAMDpMM2HU3daa6s3tkd2lHn99df7Ey+++OIJpLYbvXei+0eRvh+9NyP93reT\np76dPBm1Z7ZiKdIkohvRi/R+pN+L9L3ovRnp/Ujfj/TdvUV7koiliFokSUQ9m9mLyJ8m7lU9nZDs\n/TMjSbKvByv+5+OAlYuL8v3XCouGtu1nrBtpmuUzLWW4v0l9L897Gc7zk5XD3h7yfaaDm+cT+R6K\nuSilvj+n+GdoLctDbW86Wcpm1vf2X9x5mr/UoPAXbdodPsx0KJU85wf8BVyPiEjqe+kOZaMiD92s\nkLuDxzgoSbITI4moZ2dUPTveWlYIMVBc6e5eEgOHViyxvPDzqulF2i+QfJP9TGQH0i/nvN7rhf0M\nlVWvVIxDOyye6rXBnWR72Ns8v2Ty/EeWn+Ie8hQjO4Ru9nVw2/0ijRGXwJBa1VFUXr8jzuf9XMWI\nq6mWlWe/Tuulss1OlfRBRC/iQVazuxHZXSXJj6hfO0uFq6CWXfXFYy/q7Z8Jabd06Q3l/IBjrxfu\ne0lEUjio2K/ofvmkQ4XZGzhX08rketl+Kgt86DQYdfvK83yA2v4RDRRdlEqvUHTFTA6ce0MrlGWr\n7R11t1Adg/ec/RMjvx6LJ08SsZRleLDM9xRKNe3uJZTuZhdaN8v50I2ufMiDkvr+aTxwAhS37RWu\nyvz2m59dhbT2r9Clwu/QpLSrKGS4eIr2J5L9He79LFxiyVK2z/w2mGb3nKFfW9nEXnH1r8H+rXU3\ny/DZSM5G7dlInojkiah9JJInIjlTi9pTtac/VPvE0pkf7V+N8dH9/Xb3dtrfUfc76e4303vRe/NW\n+l6k70bvjUjvR7wf6b3sHOj/Hnls77dMcmawwEuV9dgvzOIRSMZw6keVWV7dbK/G1kZz7W5rc7XU\n6H4y8ToAADxsp7mP+76VFy5tf10fdwAAmMSUAved1kb2QOrW7ZsXz+vjDgDAIqgeVSYd+3NyptRV\nZvlc3Fht3oiIiEvX2+V+MgAAsDBOcx/3lfV2e/3w1QAAYJ70h4McbnSfxWPD03w4FQAAFszIrjJT\nN/2HUwEAYGFUvoApTcf9nCAt7gAAMKHT3McdAAAW0Px0lRG4AwDAhATuAACwAB6NN6cCAAAT0+IO\nAAAT0uIOAABzxXCQAACwsDycCgAAC8A47gAAMFeM4w4AAAtL4A4AAHOi/0zqa69FucFd4A4AAPMi\n6yHTqegtYzhIAACYKxUd3A0HCQAAi0FXGQAAWAACdwAAWAD6uAMAsDi2Npp9G1tjLR25/tZGs7nW\n2nnY+T2S6nHcZ0HgDgDAUWxtXI3r7Xa73bpy52opdC8vHbX+1kZzMy5dnGreJ9BoNPrjQg7ojf05\nOQJ3AACOYOv2zUsvrERELDdfunjn7s4hS6vX32mtbZ5vbb58frqZP660N+7nBOnjDgDA8Syfu7B9\neydi+aCl58rrR2vtWlzbXF2O0b1kvvrV14tfP/nJF08ky8fl4VQAAB4ZO+1b29vbq80be99X16K1\nuToU/c88Up9OH/fem2+m77xT/2N/7IB1BO4AABzPzt07F8+/PP7SvTnLK5vt1b05edv7gji5PjDp\nO++k77331tra0o/92NPXrh2wpj7uAAAcwcoLl27e3orot5xfOLccETuttb0RY8pLq9ZfBA/v4dR0\ndzd2d7/3t/7Wf3juuff+8T8+NCda3AEAOIqV9eu3m81mRMSl6+2VQ5cevP6jpvfWW+//s3/21ssv\np++9N+YmAncAAI5mZb3dXi/OWF7dbI9eWjGnsOHmQ8jgw3OMrjLpW291f//33/zLf/nBV7860YYC\ndwAAmEx6pFFl0nv3ott96xd/8d4//IdH2FzgDgAAE5o0cO920wcP3vm7f/ftX/7lI6cpcAcAgAmN\nHbj/2I/9WO/NNx/8y3/55s/+bO+NN46TpsAdAAAmNHYf9//zi1/8zl/6S/f/+T8/fpqGgwQAgMmk\nY3/+27/+1z/ym7/51Kc/ffxEBe4AADBS5ZtTxx/G/XOvvhpnzjz1N/7G93/724//9E8fJycCdwAA\nGKnyBUzjt7j3JR/4QO3DH/7gq68+9+UvL/2JP3G0nAjcAQBgMpMG7n21Z58985M/+dyXv/zsP/gH\nR0hU4A4AAJM5WuDelzzzzOM/8zMfT9MP/NW/OlGiAncAAJjM+H3cKyVnz0bE03/zb370D/7gsT/7\nZ8dMVOAOAACTOWbg3pc8/XT9B37g2X/0jz5y+3b9B3/w0ESN4w4AACNVjipzgmof+tDZP/2nv+9r\nX3vwta8dsubDywQAACy6ylFlTqTFfV+SJE89deZP/amD19LiDgAAk6l86vSYksceO3gFgTsAAEzm\nYQTuhxK4AwDAZMbtA3OiBO4AADAZgTsAACwAXWUAAGC+VA4HOZPA3XCQAAAw0jSGgxzPtFrcd1pr\nqze2IyLi4pXW5urylNIFAICTdqpb3He+fuF6u91ut9vXL9y41tqZUrIAAHAco7rKjPk5QdMK3FfW\n11f6U8vnL04pTQAAOKbKrjIzCdyn/nDqTvtWvHStqqfMq6++2p945ZVXppolAAAYobLF/VEYDnJr\nY/XWS63Nyh7uJxuv/1Ennok4+5VIHtv79KX3Ir0f6b145514O+KtiJ2I70T8fsR3I96NeCviQUQa\nkUTUIpKI+uA/JnrZH0/dwtehyqtlmw9t1Y3oRvSybYtrLmU/+zPr2QpJNpGnshvRi7if7a2b5aee\n5fZMYbqW7aT4B19SmJ9nspftqr/zdDCfUbVJDB54bTAb9cFyyAtqN9vzbrb5UCHUS0e9O1jO+Tpn\nCtVUK1RN8Vgq/9JNCtO10py8fntZCUd2SkSWz3ohG6MKJEr/0upmWXqQ5fDBiAIs/y8sTz0/5DMj\najk/ze5nqXRLRT1U9eWyKp5CQ9VRuc+8xpcKmwyVZDpik6H9p4WCystzqJrSA7M9dBYNrV88q4s7\nLxf10uAR5at1C+dw+YouKp6TUchYfp3Wq46rPJEOnpDFczI/IesRZwdvI+WLrrztkG4huShUUz3i\n8SyJoYv6Qbb+g1IV52VSvHf1y62/eX+1s4P5r5eSKJ51UTgryornzNBNL1crzCze5OuFOfkehi6l\nB6XTMinsM6+yGJFEMSfd7OfQb5A8M0Mnc/lenZd88WKMqttCb/BnMfND12D5zpmfsWcLectzUrxa\ny/kZOh/y301nS8WSr98t7KF4ug6VbfHsKhZ1FK6perZCvzCXBs/kfn7yo+4fQn+174/4YMRHIj4R\n8cwHov7R3pkf/W79+6L2fbH0w1F7OpIPRO2Dewmk9yJ9N7p/EL3vRPfb8eD/jd43o/tH8e3fi29E\nfCvi6xHvRrwXcb9Qy2nE/YgHEbsR72R3kvuDx5If4xd+IZhPp344yK2N5uZ5D6YCALDgZtLiPrWH\nU1tronYAABbNI9fHfad9azu2t1ebNyLCiJAAACyy09xVZnl1s706naQAAODhOs2BOwAAnBqPwqgy\nAACw8ATuAAAwX0a9OXX6BO4AAFCtPJ5M36keDhIAABZNo9GoHA5yJrS4AwDAZHSVAQCABeDhVAAA\nWAACdwAAWAC6ygAAwHypHA7SqDIAADBfKkeVScf+nCAt7gAAMBldZQAAYAEI3AEAYAEYVQYAABaA\nh1MBAIBqWtwBAGAyusoAAMB8qRzHfSYPp+oqAwAAIxnHHQAAFsD8vDlV4A4AANXKbe19AncAAJgj\n/bb2cqO7FzABAMACELgDAMAc6XeVMaoMAADMtXLI3tcb+3OCBO4AADCS4SABAGDe6SoDAAALQFcZ\nAABYDLrKAADAovICJgAAmC/lty+FcdwBAGCulDvJ9Hk4FQAA5o4+7gAAML86nc5rr0VEfPrTw11l\nZtLHXYs7AAAM67eyX75cvXQmw0FqcQcAgGGFB1Irurnr4w4AAHMk7y0zRB93AACYF6Oi9jAcJAAA\nzFw+hsyoqD0E7gAAMEP9kP2AeD3nzakAADAD44fsfQJ3AACYqklD9j6jygAAwFT1h328fHnkkO2V\njCoDAABTkj+E2jdRo7sWdwAAFsjWRrNvY2uspaU5O621vTnNtdbOtLK9J3/F0muvTdxVZiZvThW4\nAwBwFFsbV+N6u91ut67cuVoK3ctLK9bf+fqF6+12u91uX79w49rUQ/doNBqNRqPfT0ZXGQAATqWt\n2zcvvbAeEbHcfOnirbs7sbJ80NKoWH9lfX1v/eXzF6ec/31503uE4SABADjFls9d2L69E7F80NJz\nB62/074VL12r2v6rX329+PWTn3zxRLJcNNTZfRyPQuC+tbF29+XN1epKBQDgUbS1sXrrpdZmZYj4\nMCL1ok6nM2kH91mZXh/3ndZas3n15tTSAwBgOnbu3rl4fmTLbHnpwJytjebm+dYsW3aP0Mf9lD+c\nury62W5dmV3nJQAATtDKC5du3u4/Ytq+tX3h3HL0W2r7j52Wl45af8ZRe6Ng/Nj9UX849fXX9zow\nvfjiw/2HCAAAx7eyfv12s9mMiLh0vb1y6NLynJ32re3Y3l5t3oiIiItXZhbC593c+7H7oZ1nZjKO\ne5KmU0x3p7V2La5VVUiz2Wy32yeY1K8mydmIJyKS7N8KvYhuxL2I+xHvR7wVcS/iXsR3Iu5FvBlx\nL+K9iO9F3I/YjXgvohsREbVsJ/VsIt9nEhFZzfUGJ3qDNTr0j5LKTfId9tMqfi3uJK3acCiJYtLF\n3BazHYP/cMl3Xs5tlDYcmh+DJZNnO99POlgsxbSSwUNISzuM0j+GeqV8FrN36H+RDvinVXG3oy6M\nfoaTsa/YcqEVkxsqiigcdWRfD9ht+cCHkhsqqGJRD9VdZW7T0vk8VOZRmFk+J0cZVSb10vVVrvry\ngfSnu9l0f6ulwROyVnW19rINY0SeD62IXnae10pzoupqGrow80OO7PYShWMfdTaOc/1WHk45V3kh\n1EqnX/l4e4PnWH0wt0XlK73ytMl3W66U8hVR+bPy6Cqv3/K9KLKqjwPPtPLNs1Z1Ag/dhw89nUZt\nXk56KFfly/CAW2WMPhVjcP7QjTcO22EMbhJVeUhKNZsX+Kh6LJ/b9dKiodSH0orCIQ/dE85G1CPq\n2URSuPryq+CxiMcjPhbxdMSHIi5EfDjiwxH/ccSzEbVnov4DUftAJI9H8uRentJ7kb4f3W9E+t3o\nvRW/241vRXw74rci3oh4I+LrEd+LeCfi/Yh6xGNZNoqRSf9zP5vYzSb63p9mnDaXms3mr/3aSYaI\nY+rH8Xn4/ulPN4pLf+InkvXyNiNsRJxUvG0cdwAAGNAfIPKAnjOPelcZAACYE41Go9PpjIrdT/lw\nkDuttdUb2xGx2rxx6Xp7fbgfFAAAzF7e3z3vKtNoDK8zkz5M0wvcl1c326tTSw0AAI6i308mb26v\nfFD1lAfuAACwKBr7zewV71U95V1lAADgdJhJi7tRZQAAYKT+U6pDM40qAwAAC0BXGQAAmC+dTqdR\nGlZGVxkAAJgvusoAAMCi0lUGAAAWgHHcAQBgXuQ9ZOakj7vAHQAAhnU6nfydqaW4fTZdZTycCgAA\nwxqNxuXLI5f2xv6cIC3uAAAwrNjiXqarDAAALACBOwAAzN7Bze0hcAcAgFkpvmXp4Kg9BO4AADBN\nEwXrRV7ABAAA05MP0N7pdIpjyBwaxBsOEgAAZqD4iqVxmt7TsT8nSIs7AACPukOfRh2ijzsAACwA\ngTsAACwAD6cCAMBUFQeWGZ8WdwAAmIY8Xp+oa3tOizsAADx0R2tlLxK4AwDAQ1cc/DGiE0dtd58y\ngTsAAI+uLIifrOeMPu4AADADhTb4sSJ4XWUAAGCWhiL4UeG7FncAAJgLeReayth9Ji3utVkkCgAA\nC6DRaFy+XDEKTTr25wRpcQcAgGr9kH1wFJoILe4AADBXyiF730xa3AXuAAAwUqPR0FUGAAAWkuEg\nAQBgjozq4244SAAAWAAzCdz1cQcAgGr9tvZyH/fe2J8TpMUdAACq6SoDAAALIG9xH4rdBe4AALAA\njCoDAAALQIs7AADMl3I/mTCqDAAAzJvKN6caVQYAAOZLZYu7Pu4AADAv+g3tr70WpbhdH3cAAJgb\nWUN7x3CQAACwADycCgAA867y4dR07M8J0uIOAACTmcnDqVNrcd/aaPZtbE0rSQAAeBhmMhzklAL3\nrY2rcb3dbrdbV+5cFboDALDIZtJVZjqB+9btm5deWImIWG6+dPHO3Z2ppAoAAMdUOY77TEy9j/vy\nuQvbt3cilktLms1m8Wu73T5OOv9dOpOHfQGAR9THZ50BHoZOp1M5jvuj/gKmY0bqAABwshqNRsTw\nkDJx2h9OzezcvXPxfLm5HQAAFsUp7uO+8sKlm7e3IiJ22re2L5wTuAMAMP/6XWXKZjKqzJS6yqys\nX7+914f90vX2ynQSBQCAh2EmD1NOrY/7ynq7vT6txAAA4OE53YE7AAAshk5n74HUyn4yIXAHAIBZ\nyYP1GB2v5x714SABAGDKDm1cr6TFHQAApqTYxD4pLe4AAHDyKmP0iZrYh2hxBwCAEzAUqR8nRq+k\nxR0AAMZ1QF+XE4/U54HAHQCARXK0x0lPlhZ3AAAYqR+yz0NrusAdAACqdTqdRqPR6XQuX65YOg/R\n/MMmcAcAYFa2NppXb0ZEXLreXl85cNVGo5H/rDLV/jNa3E9Ss9lst9uzzgUAwAAhStHWxtW43m6v\nxE5rbXVj67DQ/SCFgH74idXXXosvfOETP/3T/+bIOy+bSeBem0WiMNKrr7466yxwFCpucam7BaXi\nOBW2bt+89MJKRMRy86WLd+7unMROGyX9rjVf+MInvvCFT1y+HP3PMaVjf07QqW1xP8Vef/31F198\ncda54CjU3YJScYtL3S0oFfcoWj53Yfv2TsRyaclf+SvNA7b723/7Tx6670996nMR8aUv/fzzz3/u\nU5/6xJe+9PMR8cu/PEHuHjwYnuMFTAAAMOD4PYvS9O8nSfL885/rh+zPP/+5iEjT48Ten9PHHQCA\nR9LO3TsXz7/80HbfD9OTJImIfvjenz5y+D6TFvfkeH9tnJhm86B/ggAAcHzz9lzs1kbz9gvt9f7D\nqV9fKz+c+jCe5S2G70drfU+S5ENjr/yd47bu75uXFvd5O40AAHjYVtav395rvr10vX30IWUmkqZp\nv+dMZB3fk2TituyZdJWZlxZ3AAAY8lBHzzxy03uSJE+Pncrbp6/FHQAApunEO74fU7fbrdfrB6xw\n+sZx39po9m1szTorjLTTWturpuZaqz9ma7niVOX82trIa07FLY6sZlx0i2T/bpnVm4pbDFsbeY2N\nVWUqcZbSNE3T9PnnP9cfduZLX/r5JEn6EfxBW530OO5vvfXWb//2b4+V11Oj/dmVz7bTNE3v/sYr\ne1PMofZns8ppf3blld+4W1FxqnJutT+78spnP/vKK79xt6qaVNycan92ZbA+1N0iuPsb/SstzW+W\nKm4B3P2NV1ZWVlYKVXdolanEA6ysrEwtrTw87re+HxAnR8STY38Ojbffeuutr33taz/+4z/+mc98\n5uA1T1mL+0N5/xYnb2U9e2p8+fzFqKo4VTmndlprm+dbmy+fjwgVt0C2bt+50ioO1qDuFk3/Zqni\nFsHy6ma7deXi3rdxqkwlzos8KB+n6f1EWtzfe++9d99995d+6Zd+5Ed+5F//6399aA5Pbx/30e/f\nYo7stG/FS9eW4+v5nL2KOxfDc1Tl7O201q7Ftc3V5Sj/VlFxc23r9s3tmzebNyIi4tL1wfHW1N38\nWl7dXNvYG3Dj4pXW5nIUulGouIUzsspU4nxJx+v4fsxRZXq93vvvv//rv/7rf+2v/bXxtzq9gTsL\nYGtj9dZLQ7+KmF877Vvb29ure9FfxOrapSkN3MUJyML1ndba6sZW+4VZ54exbG1cjevt9spOa231\nxue3VtdnnSF4ZBwavh8ncH/zzTe//OUv/+zP/uw3vvGNiTY8ZV1lCnbu3rl43h+sc2xro7l5vrW5\nOlRJ5YpTlfNieXWzvad15eLFK63NFz6QL1Rxi6L8n3h1N7d2Wpt3rry8EhHLq5utK3c2WypuoY1T\nZSpxzuQ9Z/qdZyIi7zxztK4yb7/99t27d//iX/yLly5dmjRqj1MXuK+8cOnm7a2IftvghXNO/Tm1\n01obiNrLFacqF4KKWxQrL1y6uRf07VWMulsEy+cubN/4fP9fkipuUY1TZSpxrpU7vvfn7479iYgk\nSd5///1ut3v16tUf+qEf+hf/4l8cLTOnravMTN6/xaR22re2Y7/PxcUrrc1SxanKhVCuJhU3n1bW\nW3fX+pfcxSutzZWIUHcLYGW9dWVtdb+Pu4pbCDuttdUb2xGx2rxx6Xp7fYwqU4nzr9xzZiLPP/+5\nz3/+87/wC79wzGx4cyoAAHPqob459WgOHeL9yD7zmc9cu3btgBVOWVcZAAB4iPqt3mOMC7+n1+u9\n/fbbf+/v/b3jJy1wBwCACUzUYyVJkqeeeupTn/rU7u7uL/3SLx0nXYE7AAA8XGfPnq3X67/yK79y\n9+7dn/qpnzraTgTuAAAwDU8//fTy8vIXvvCFL37xix/72Mcm3VzgDgAA0/Pss8/+mT/zZ37nd37n\nV3/1VyfaUOAOAABTVavVnnzyyV/8xV+8d+/ez/3cz4271cPMEgAAUO3xxx9//PHHf+3Xfu3f/bt/\n95M/+ZOHrn/aXsAEAAAL5JlnnnnmmWe++MUv/uEf/uHBa3oBEwAAzF63263X6wesIHAHAIAFoI87\nAAAsAIE7AAAsAIE7AAAsAIE7AAAsAIE7AAAsAIE7AAAsAIE7AAAsgP8fJUS+521Sw3wAAAAASUVO\nRK5CYII=\n", - "text/plain": [ - "" - ] - }, - "execution_count": 19, - "metadata": {}, - "output_type": "execute_result" + "ename": "ConnectionResetError", + "evalue": "[WinError 10054] An existing connection was forcibly closed by the remote host", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mConnectionResetError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[1;31m# plotting the measured demodulated amplitude (samples on y axis, different freqs on x), only looking at the one we swept\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mqc\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mQtPlot\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mdata5\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msamp_acq_controller_magnitude\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32ma:\\qcodes\\qcodes\\plots\\pyqtgraph.py\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, figsize, interval, window_title, theme, show_window, remote, *args, **kwargs)\u001b[0m\n\u001b[1;32m 56\u001b[0m \u001b[1;31m# overrule the remote pyqtgraph class\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 57\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mrpg\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mpg\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m---> 58\u001b[0;31m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mwin\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mrpg\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mGraphicsWindow\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mtitle\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mwindow_title\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 59\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mwin\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msetBackground\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mtheme\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 60\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mwin\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mresize\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m*\u001b[0m\u001b[0mfigsize\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[0;32mc:\\users\\triton2acq\\anaconda3\\envs\\qcodes-master\\lib\\site-packages\\pyqtgraph\\multiprocess\\remoteproxy.py\u001b[0m in \u001b[0;36m__getattr__\u001b[0;34m(self, attr, **kwds)\u001b[0m\n\u001b[1;32m 895\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 896\u001b[0m \u001b[1;31m#opts = self._getProxyOptions()\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m--> 897\u001b[0;31m \u001b[1;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_handler\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mgetObjAttr\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mattr\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mopts\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 898\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 899\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0m_deferredAttr\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mattr\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[0;32mc:\\users\\triton2acq\\anaconda3\\envs\\qcodes-master\\lib\\site-packages\\pyqtgraph\\multiprocess\\remoteproxy.py\u001b[0m in \u001b[0;36mgetObjAttr\u001b[0;34m(self, obj, attr, **kwds)\u001b[0m\n\u001b[1;32m 530\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 531\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mgetObjAttr\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mobj\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mattr\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwds\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m--> 532\u001b[0;31m \u001b[1;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msend\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mrequest\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m'getObjAttr'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mopts\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mdict\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mobj\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mobj\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mattr\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mattr\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwds\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 533\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 534\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mgetObjValue\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mobj\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwds\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[0;32mc:\\users\\triton2acq\\anaconda3\\envs\\qcodes-master\\lib\\site-packages\\pyqtgraph\\multiprocess\\remoteproxy.py\u001b[0m in \u001b[0;36msend\u001b[0;34m(self, request, opts, reqId, callSync, timeout, returnType, byteData, **kwds)\u001b[0m\n\u001b[1;32m 450\u001b[0m \u001b[0mrequest\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m(\u001b[0m\u001b[0mrequest\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mreqId\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mnByteMsgs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0moptStr\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 451\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdebugMsg\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'send request: cmd=%s nByteMsgs=%d id=%s opts=%s'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mrequest\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mnByteMsgs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mreqId\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mopts\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m--> 452\u001b[0;31m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mconn\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msend\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mrequest\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 453\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 454\u001b[0m \u001b[1;31m## follow up by sending byte messages\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[0;32mc:\\users\\triton2acq\\anaconda3\\envs\\qcodes-master\\lib\\multiprocessing\\connection.py\u001b[0m in \u001b[0;36msend\u001b[0;34m(self, obj)\u001b[0m\n\u001b[1;32m 204\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_check_closed\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 205\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_check_writable\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m--> 206\u001b[0;31m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_send_bytes\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mForkingPickler\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdumps\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mobj\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 207\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 208\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mrecv_bytes\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mmaxlength\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mNone\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[0;32mc:\\users\\triton2acq\\anaconda3\\envs\\qcodes-master\\lib\\multiprocessing\\connection.py\u001b[0m in \u001b[0;36m_send_bytes\u001b[0;34m(self, buf)\u001b[0m\n\u001b[1;32m 402\u001b[0m \u001b[1;31m# Also note we want to avoid sending a 0-length buffer separately,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 403\u001b[0m \u001b[1;31m# to avoid \"broken pipe\" errors if the other end closed the pipe.\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m--> 404\u001b[0;31m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_send\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mheader\u001b[0m \u001b[1;33m+\u001b[0m \u001b[0mbuf\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 405\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 406\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0m_recv_bytes\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mmaxsize\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mNone\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[0;32mc:\\users\\triton2acq\\anaconda3\\envs\\qcodes-master\\lib\\multiprocessing\\connection.py\u001b[0m in \u001b[0;36m_send\u001b[0;34m(self, buf, write)\u001b[0m\n\u001b[1;32m 366\u001b[0m \u001b[0mremaining\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mlen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mbuf\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 367\u001b[0m \u001b[1;32mwhile\u001b[0m \u001b[1;32mTrue\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m--> 368\u001b[0;31m \u001b[0mn\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mwrite\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_handle\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mbuf\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 369\u001b[0m \u001b[0mremaining\u001b[0m \u001b[1;33m-=\u001b[0m \u001b[0mn\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 370\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mremaining\u001b[0m \u001b[1;33m==\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[0;31mConnectionResetError\u001b[0m: [WinError 10054] An existing connection was forcibly closed by the remote host" + ] } ], "source": [ @@ -501,8 +609,6 @@ }, "outputs": [], "source": [ - "import qcodes.instrument_drivers.AlazarTech.ave_controller_test as ave_controller\n", - "\n", "demod_list = [80e6, 85e6, 90e6, 95e6, 100e6, 105e6, 110e6, 115e6]\n", "ave_controller = ave_controller.HD_Averaging_Controller(name='ave_controller', \n", " alazar_name='Alazar', \n", @@ -634,8 +740,6 @@ }, "outputs": [], "source": [ - "import qcodes.instrument_drivers.AlazarTech.rec_controller_test as record_controller\n", - "\n", "demod_list = [95e6, 98e6, 100e6, 105e6]\n", "rec_controller = record_controller.HD_Records_Controller(name='rec_controller', \n", " alazar_name='Alazar', \n", diff --git a/qcodes/instrument_drivers/AlazarTech/ATS9360.py b/qcodes/instrument_drivers/AlazarTech/ATS9360.py index 4d8ca45cbc32..5ffe33f03699 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS9360.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS9360.py @@ -10,7 +10,7 @@ class AlazarTech_ATS9360(AlazarTech_ATS): TODO(nataliejpg): - add clock source options and sample rate options """ - samples_divisor = 32 + samples_divisor = 128 def __init__(self, name, **kwargs): dll_path = 'C:\\WINDOWS\\System32\\ATSApi.dll' diff --git a/qcodes/instrument_drivers/AlazarTech/ave_controller_test.py b/qcodes/instrument_drivers/AlazarTech/ave_controller_test.py index 855ba2d3453d..5ad362524813 100644 --- a/qcodes/instrument_drivers/AlazarTech/ave_controller_test.py +++ b/qcodes/instrument_drivers/AlazarTech/ave_controller_test.py @@ -44,7 +44,10 @@ def __init__(self, name, instrument, demod_length): self._instrument = instrument self.acquisition_kwargs = {} self.names = ('magnitude', 'phase') - self.shapes = ((demod_length, ), (demod_length, )) + if demod_length > 1: + self.shapes = ((demod_length, ), (demod_length, )) + else: + self.shapes = ((), ()) def get(self): mag, phase = self._instrument._get_alazar().acquire( diff --git a/qcodes/instrument_drivers/AlazarTech/basic_controller.py b/qcodes/instrument_drivers/AlazarTech/basic_controller.py index 1afcf25a2357..7b172f070a7e 100644 --- a/qcodes/instrument_drivers/AlazarTech/basic_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/basic_controller.py @@ -1,6 +1,7 @@ import logging from .ATS import AcquisitionController import numpy as np +import qcodes.instrument_drivers.AlazarTech.acq_helpers as helpers from qcodes import Parameter @@ -125,8 +126,8 @@ def post_acquire(self): bps = self.board_info['bits_per_sample'] if bps == 12: - volt_rec_A = sample_to_volt_u12(recordA, bps) - volt_rec_B = sample_to_volt_u12(recordB, bps) + volt_rec_A = helpers.sample_to_volt_u12(recordA, bps) + volt_rec_B = helpers.sample_to_volt_u12(recordB, bps) else: logging.warning('sample to volt conversion does not exist for bps ' '!= 12, raw samples centered on 0 and returned') @@ -135,7 +136,7 @@ def post_acquire(self): return volt_rec_A, volt_rec_B - +""" def sample_to_volt_u12(raw_samples, bps): # right_shift 16-bit sample by 4 to get 12 bit sample shifted_samples = np.right_shift(raw_samples, 4) @@ -151,3 +152,4 @@ def sample_to_volt_u12(raw_samples, bps): (shifted_samples - code_zero) / code_range) return volt_samples +""" \ No newline at end of file diff --git a/qcodes/instrument_drivers/AlazarTech/rec_controller_test.py b/qcodes/instrument_drivers/AlazarTech/rec_controller_test.py index 75d160f1d2f6..9fb3d1b2b54d 100644 --- a/qcodes/instrument_drivers/AlazarTech/rec_controller_test.py +++ b/qcodes/instrument_drivers/AlazarTech/rec_controller_test.py @@ -51,7 +51,10 @@ def update_sweep(self, npts, start=None, stop=None): demod_length = self._instrument._demod_length # rec_list = tuple(np.linspace(start, stop, num=npts)) # demod_index = tuple(range(demod_length)) - self.shapes = ((demod_length, npts), (demod_length, npts)) + if demod_length > 1: + self.shapes = ((demod_length, npts), (demod_length, npts)) + else: + self.shapes = ((npts,), (npts,)) def get(self): mag, phase = self._instrument._get_alazar().acquire( diff --git a/qcodes/instrument_drivers/AlazarTech/samp_controller.py b/qcodes/instrument_drivers/AlazarTech/samp_controller.py index 9fb3be199c9e..a6a0f79c705a 100644 --- a/qcodes/instrument_drivers/AlazarTech/samp_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/samp_controller.py @@ -54,11 +54,14 @@ def update_sweep(self, start, stop, npts): demod_length = self._instrument._demod_length # freq = tuple(np.linspace(start, stop, num=npts)) # demod_index = tuple(range(demod_length)) - self.shapes = ((demod_length, npts), (demod_length, npts)) + if demod_length > 1: + self.shapes = ((demod_length, npts), (demod_length, npts)) + else: + self.shapes = ((npts,), (npts,)) def get(self): - self._instrument.int_time.check() - self._instrument.int_delay.check() + # self._instrument.int_time.check() + # self._instrument.int_delay.check() mag, phase = self._instrument._get_alazar().acquire( acquisition_controller=self._instrument, **self.acquisition_kwargs) @@ -315,7 +318,7 @@ def post_acquire(self): Returns: magnitude (numpy array): shape = (demod_length, samples_used) phase (numpy array): shape = (demod_length, samples_used) - """ + """ records_per_acquisition = (self.buffers_per_acquisition * self.records_per_buffer) # for ATS9360 samples are arranged in the buffer as follows: @@ -375,9 +378,9 @@ def _fit(self, rec): volt_rec_mat = np.outer(np.ones(self._demod_length), volt_rec) re_mat = np.multiply(volt_rec_mat, self.cos_mat) im_mat = np.multiply(volt_rec_mat, self.sin_mat) - + # filter out higher freq component - cutoff = self.get_max_demod_freq() / 10 + cutoff = self.get_max_demod_freq() / 20 if self.filter_settings['filter'] == 0: re_filtered = helpers.filter_win(re_mat, cutoff, self.sample_rate, @@ -403,7 +406,8 @@ def _fit(self, rec): re_limited = re_filtered[:, beginning:end] im_limited = im_filtered[:, beginning:end] - + #return re_limited, volt_rec_mat[:, beginning:end] + # convert to magnitude and phase complex_mat = re_limited + im_limited * 1j magnitude = abs(complex_mat) From fa219ec56a33fc9f1505ce693ce00eb34a365e21 Mon Sep 17 00:00:00 2001 From: nataliejpg Date: Tue, 24 Jan 2017 10:43:09 +0100 Subject: [PATCH 092/180] change init with demod freqs to init with number of demod_freqs --- .../instrument_drivers/AlazarTech/ave_controller_test.py | 7 +++---- .../instrument_drivers/AlazarTech/rec_controller_test.py | 7 +++---- qcodes/instrument_drivers/AlazarTech/samp_controller.py | 7 +++---- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/ave_controller_test.py b/qcodes/instrument_drivers/AlazarTech/ave_controller_test.py index 5ad362524813..a3eec4cc5441 100644 --- a/qcodes/instrument_drivers/AlazarTech/ave_controller_test.py +++ b/qcodes/instrument_drivers/AlazarTech/ave_controller_test.py @@ -86,7 +86,7 @@ class HD_Averaging_Controller(AcquisitionController): filter_dict = {'win': 0, 'ls': 1, 'ave': 2} samples_divisor = AlazarTech_ATS9360.samples_divisor - def __init__(self, name, alazar_name, demod_freqs=[20e6], filter='win', + def __init__(self, name, alazar_name, demod_length=1, filter='win', numtaps=101, chan_b=False, **kwargs): self.filter_settings = {'filter': self.filter_dict[filter], 'numtaps': numtaps} @@ -98,11 +98,10 @@ def __init__(self, name, alazar_name, demod_freqs=[20e6], filter='win', super().__init__(name, alazar_name, **kwargs) self.add_parameter(name='acquisition', - demod_length=self._demod_length, + demod_length=self.demod_length, parameter_class=AveragedAcqParam) - for i, res in enumerate(demod_freqs): + for i in range(demod_length): self.add_parameter(name='demod_freq_{}'.format(i), - initial_value=res, parameter_class=ManualParameter) self.add_parameter(name='int_time', initial_value=None, diff --git a/qcodes/instrument_drivers/AlazarTech/rec_controller_test.py b/qcodes/instrument_drivers/AlazarTech/rec_controller_test.py index 9fb3d1b2b54d..fb6535464b7e 100644 --- a/qcodes/instrument_drivers/AlazarTech/rec_controller_test.py +++ b/qcodes/instrument_drivers/AlazarTech/rec_controller_test.py @@ -94,12 +94,12 @@ class HD_Records_Controller(AcquisitionController): filter_dict = {'win': 0, 'ls': 1, 'ave': 2} samples_divisor = AlazarTech_ATS9360.samples_divisor - def __init__(self, name, alazar_name, demod_freqs=[20e6], filter='win', + def __init__(self, name, alazar_name, demod_length=1 filter='win', numtaps=101, chan_b=False, **kwargs): self.filter_settings = {'filter': self.filter_dict[filter], 'numtaps': numtaps} self.chan_b = chan_b - self._demod_length = len(demod_freqs) + self._demod_length = demod_length self.number_of_channels = 2 self.samples_per_record = None self.records_per_buffer = None @@ -109,9 +109,8 @@ def __init__(self, name, alazar_name, demod_freqs=[20e6], filter='win', self.add_parameter(name='acquisition', demod_length=self._demod_length, parameter_class=RecordsAcqParam) - for i, res in enumerate(demod_freqs): + for i in range(demod_length): self.add_parameter(name='demod_freq_{}'.format(i), - initial_value=res, parameter_class=ManualParameter) self.add_parameter(name='int_time', initial_value=None, diff --git a/qcodes/instrument_drivers/AlazarTech/samp_controller.py b/qcodes/instrument_drivers/AlazarTech/samp_controller.py index a6a0f79c705a..296a19779462 100644 --- a/qcodes/instrument_drivers/AlazarTech/samp_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/samp_controller.py @@ -97,12 +97,12 @@ class HD_Samples_Controller(AcquisitionController): filter_dict = {'win': 0, 'ls': 1} samples_divisor = AlazarTech_ATS9360.samples_divisor - def __init__(self, name, alazar_name, demod_freqs=[20e6], filter='win', + def __init__(self, name, alazar_name, demod_length=1, filter='win', numtaps=101, chan_b=False, **kwargs): self.filter_settings = {'filter': self.filter_dict[filter], 'numtaps': numtaps} self.chan_b = chan_b - self._demod_length = len(demod_freqs) + self._demod_length = demod_length self.number_of_channels = 2 self.samples_per_record = None self.sample_rate = None @@ -110,9 +110,8 @@ def __init__(self, name, alazar_name, demod_freqs=[20e6], filter='win', self.add_parameter(name='acquisition', parameter_class=SamplesAcqParam) - for i, res in enumerate(demod_freqs): + for i in range(demod_length): self.add_parameter(name='demod_freq_{}'.format(i), - initial_value=res, parameter_class=ManualParameter) self.add_parameter(name='int_time', initial_value=None, From cab3d5a3edcdf986b352a63bbddc437a3cca4a74 Mon Sep 17 00:00:00 2001 From: nataliejpg Date: Tue, 24 Jan 2017 12:08:23 +0100 Subject: [PATCH 093/180] typos and get around the uses of the demod freqs before set through get_max_demod_freq() --- .../AlazarTech/ave_controller_test.py | 29 ++++++++++--------- .../AlazarTech/rec_controller_test.py | 27 +++++++++-------- .../AlazarTech/samp_controller.py | 25 +++++++++------- 3 files changed, 45 insertions(+), 36 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/ave_controller_test.py b/qcodes/instrument_drivers/AlazarTech/ave_controller_test.py index a3eec4cc5441..cfeaa31c4cbb 100644 --- a/qcodes/instrument_drivers/AlazarTech/ave_controller_test.py +++ b/qcodes/instrument_drivers/AlazarTech/ave_controller_test.py @@ -91,14 +91,14 @@ def __init__(self, name, alazar_name, demod_length=1, filter='win', self.filter_settings = {'filter': self.filter_dict[filter], 'numtaps': numtaps} self.chan_b = chan_b - self._demod_length = len(demod_freqs) + self._demod_length = demod_length self.number_of_channels = 2 self.samples_per_record = None self.sample_rate = None super().__init__(name, alazar_name, **kwargs) self.add_parameter(name='acquisition', - demod_length=self.demod_length, + demod_length=demod_length, parameter_class=AveragedAcqParam) for i in range(demod_length): self.add_parameter(name='demod_freq_{}'.format(i), @@ -130,17 +130,18 @@ def _update_int_time(instr, value): raise ValueError('int_time must be 0 <= value <= 1') alazar = instr._get_alazar() instr.sample_rate = alazar.get_sample_rate() - oscilations_measured = value * instr.get_max_demod_freq() - oversampling = instr.sample_rate / (2 * instr.get_max_demod_freq()) - if oscilations_measured < 10: - logging.warning('{} oscilations measured, recommend at ' - 'least 10: decrease sampling rate, take ' - 'more samples or increase demodulation ' - 'freq'.format(oscilations_measured)) - elif oversampling < 1: - logging.warning('oversampling rate is {}, recommend > 1: ' - 'increase sampling rate or decrease ' - 'demodulation frequency'.format(oversampling)) + if instr.get_max_demod_freq() is not None: + oscilations_measured = value * instr.get_max_demod_freq() + oversampling = instr.sample_rate / (2 * instr.get_max_demod_freq()) + if oscilations_measured < 10: + logging.warning('{} oscilations measured, recommend at ' + 'least 10: decrease sampling rate, take ' + 'more samples or increase demodulation ' + 'freq'.format(oscilations_measured)) + elif oversampling < 1: + logging.warning('oversampling rate is {}, recommend > 1: ' + 'increase sampling rate or decrease ' + 'demodulation frequency'.format(oversampling)) if instr.int_delay() is None: instr.int_delay.to_default() @@ -262,6 +263,8 @@ def pre_start_capture(self): raise Exception('acq controller sample rate does not match ' 'instrument value, most likely need ' 'to set and check int_time and int_delay') + if self.get_max_demod_freq() is None: + raise Exception('no demodulation frequencies set') self.records_per_buffer = alazar.records_per_buffer.get() self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() self.board_info = alazar.get_idn() diff --git a/qcodes/instrument_drivers/AlazarTech/rec_controller_test.py b/qcodes/instrument_drivers/AlazarTech/rec_controller_test.py index fb6535464b7e..dd7e1c185305 100644 --- a/qcodes/instrument_drivers/AlazarTech/rec_controller_test.py +++ b/qcodes/instrument_drivers/AlazarTech/rec_controller_test.py @@ -94,7 +94,7 @@ class HD_Records_Controller(AcquisitionController): filter_dict = {'win': 0, 'ls': 1, 'ave': 2} samples_divisor = AlazarTech_ATS9360.samples_divisor - def __init__(self, name, alazar_name, demod_length=1 filter='win', + def __init__(self, name, alazar_name, demod_length=1, filter='win', numtaps=101, chan_b=False, **kwargs): self.filter_settings = {'filter': self.filter_dict[filter], 'numtaps': numtaps} @@ -139,17 +139,18 @@ def _update_int_time(instr, value): raise ValueError('int_time must be 0 <= value <= 1') alazar = instr._get_alazar() instr.sample_rate = alazar.get_sample_rate() - oscilations_measured = value * instr.get_max_demod_freq() - oversampling = instr.sample_rate / (2 * instr.get_max_demod_freq()) - if oscilations_measured < 10: - logging.warning('{} oscilations measured, recommend at ' - 'least 10: decrease sampling rate, take ' - 'more samples or increase demodulation ' - 'freq'.format(oscilations_measured)) - elif oversampling < 1: - logging.warning('oversampling rate is {}, recommend > 1: ' - 'increase sampling rate or decrease ' - 'demodulation frequency'.format(oversampling)) + if instr.get_max_demod_freq() is not None: + oscilations_measured = value * instr.get_max_demod_freq() + oversampling = instr.sample_rate / (2 * instr.get_max_demod_freq()) + if oscilations_measured < 10: + logging.warning('{} oscilations measured, recommend at ' + 'least 10: decrease sampling rate, take ' + 'more samples or increase demodulation ' + 'freq'.format(oscilations_measured)) + elif oversampling < 1: + logging.warning('oversampling rate is {}, recommend > 1: ' + 'increase sampling rate or decrease ' + 'demodulation frequency'.format(oversampling)) if instr.int_delay() is None: instr.int_delay.to_default() @@ -279,6 +280,8 @@ def pre_start_capture(self): 'instrument value, most likely need ' 'to call update_acquisition_kwargs with' 'records_per_buffer as a param') + if self.get_max_demod_freq() is None: + raise Exception('no demodulation frequencies set') self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() self.board_info = alazar.get_idn() self.buffer = np.zeros(self.samples_per_record * diff --git a/qcodes/instrument_drivers/AlazarTech/samp_controller.py b/qcodes/instrument_drivers/AlazarTech/samp_controller.py index 296a19779462..effe982dcb84 100644 --- a/qcodes/instrument_drivers/AlazarTech/samp_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/samp_controller.py @@ -140,17 +140,18 @@ def _update_int_time(instr, value): raise ValueError('int_time must be 0 <= value <= 1') alazar = instr._get_alazar() instr.sample_rate = alazar.get_sample_rate() - oscilations_measured = value * instr.get_max_demod_freq() - oversampling = instr.sample_rate / (2 * instr.get_max_demod_freq()) - if oscilations_measured < 10: - logging.warning('{} oscilations measured, recommend at ' - 'least 10: decrease sampling rate, take ' - 'more samples or increase demodulation ' - 'freq'.format(oscilations_measured)) - elif oversampling < 1: - logging.warning('oversampling rate is {}, recommend > 1: ' - 'increase sampling rate or decrease ' - 'demodulation frequency'.format(oversampling)) + if instr.get_max_demod_freq() is not None: + oscilations_measured = value * instr.get_max_demod_freq() + oversampling = instr.sample_rate / (2 * instr.get_max_demod_freq()) + if oscilations_measured < 10: + logging.warning('{} oscilations measured, recommend at ' + 'least 10: decrease sampling rate, take ' + 'more samples or increase demodulation ' + 'freq'.format(oscilations_measured)) + elif oversampling < 1: + logging.warning('oversampling rate is {}, recommend > 1: ' + 'increase sampling rate or decrease ' + 'demodulation frequency'.format(oversampling)) if instr.int_delay() is None: instr.int_delay.to_default() @@ -284,6 +285,8 @@ def pre_start_capture(self): raise Exception('acq controller sample rate does not match ' 'instrument value, most likely need ' 'to call update_acquisition_settings') + if self.get_max_demod_freq() is None: + raise Exception('no demodulation frequencies set') self.records_per_buffer = alazar.records_per_buffer.get() self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() self.board_info = alazar.get_idn() From cf8fcbd75b8fb46e3bb5e5f3fe8281306bf52cd0 Mon Sep 17 00:00:00 2001 From: nataliejpg Date: Tue, 24 Jan 2017 12:26:44 +0100 Subject: [PATCH 094/180] actually getting get_max_demod_freq to work if no demodulation frequencies specified --- .../instrument_drivers/AlazarTech/ave_controller_test.py | 8 +++++++- .../instrument_drivers/AlazarTech/rec_controller_test.py | 8 +++++++- qcodes/instrument_drivers/AlazarTech/samp_controller.py | 7 ++++++- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/ave_controller_test.py b/qcodes/instrument_drivers/AlazarTech/ave_controller_test.py index cfeaa31c4cbb..1ecce446922b 100644 --- a/qcodes/instrument_drivers/AlazarTech/ave_controller_test.py +++ b/qcodes/instrument_drivers/AlazarTech/ave_controller_test.py @@ -215,7 +215,13 @@ def get_max_demod_freq(self): nb: really hacky and we should have channels in qcodes but we don't (at time of writing) """ - return max([getattr(self, 'demod_freq_{}'.format(c))() for c in range(self._demod_length)]) + freqs = list(filter(None, [getattr(self, 'demod_freq_{}'.format(c))() + for c in range(self._demod_length)])) + if len(freqs) > 0: + return max(freqs) + else: + return None + def update_filter_settings(self, filter, numtaps): """ diff --git a/qcodes/instrument_drivers/AlazarTech/rec_controller_test.py b/qcodes/instrument_drivers/AlazarTech/rec_controller_test.py index dd7e1c185305..e19df17b195b 100644 --- a/qcodes/instrument_drivers/AlazarTech/rec_controller_test.py +++ b/qcodes/instrument_drivers/AlazarTech/rec_controller_test.py @@ -224,7 +224,13 @@ def get_max_demod_freq(self): nb: really hacky and we should have channels in qcodes but we don't (at time of writing) """ - return max([getattr(self, 'demod_freq_{}'.format(c))() for c in range(self._demod_length)]) + freqs = list(filter(None, [getattr(self, 'demod_freq_{}'.format(c))() + for c in range(self._demod_length)])) + if len(freqs) > 0: + return max(freqs) + else: + return None + def update_filter_settings(self, filter, numtaps): """ diff --git a/qcodes/instrument_drivers/AlazarTech/samp_controller.py b/qcodes/instrument_drivers/AlazarTech/samp_controller.py index effe982dcb84..484540a3ca36 100644 --- a/qcodes/instrument_drivers/AlazarTech/samp_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/samp_controller.py @@ -237,7 +237,12 @@ def get_max_demod_freq(self): nb: really hacky and we should have channels in qcodes but we don't (at time of writing) """ - return max([getattr(self, 'demod_freq_{}'.format(c))() for c in range(self._demod_length)]) + freqs = list(filter(None, [getattr(self, 'demod_freq_{}'.format(c))() + for c in range(self._demod_length)])) + if len(freqs) > 0: + return max(freqs) + else: + return None def update_filter_settings(self, filter, numtaps): """ From fa08a42b49bd497f62fed3f3d3b4ce24ba41bbda Mon Sep 17 00:00:00 2001 From: Natalie Pearson Date: Mon, 6 Feb 2017 15:38:14 +0100 Subject: [PATCH 095/180] pep8 and tidy up --- .../AlazarTech/ave_controller_test.py | 24 +- .../AlazarTech/basic_controller.py | 57 ++-- .../AlazarTech/rec_controller_test.py | 34 +- qcodes/instrument_drivers/AlazarTech/samp.py | 314 ------------------ .../AlazarTech/samp_controller.py | 85 +++-- 5 files changed, 120 insertions(+), 394 deletions(-) delete mode 100644 qcodes/instrument_drivers/AlazarTech/samp.py diff --git a/qcodes/instrument_drivers/AlazarTech/ave_controller_test.py b/qcodes/instrument_drivers/AlazarTech/ave_controller_test.py index 1ecce446922b..8dce5a6612e5 100644 --- a/qcodes/instrument_drivers/AlazarTech/ave_controller_test.py +++ b/qcodes/instrument_drivers/AlazarTech/ave_controller_test.py @@ -8,8 +8,14 @@ class AcqVariablesParam(Parameter): - def __init__(self, name, instrument, initial_value, - check_and_update_fn, default_fn): + """ + Parameter of an AcquisitionController which has a _check_and_update_instr + function used for validation and to update instrument attributes and a + _get_default function which it uses to set the parameter to an instrument + caluclated default. + """ + def __init__(self, name, instrument, check_and_update_fn, + default_fn, initial_value=None): super().__init__(name) self._instrument = instrument self._save_val(initial_value) @@ -27,6 +33,11 @@ def to_default(self): default = self._get_default() self.set(default) + def check(self): + val = self._latest()['value'] + self._check_and_update_instr(val) + return True + class AveragedAcqParam(Parameter): """ @@ -104,12 +115,10 @@ def __init__(self, name, alazar_name, demod_length=1, filter='win', self.add_parameter(name='demod_freq_{}'.format(i), parameter_class=ManualParameter) self.add_parameter(name='int_time', - initial_value=None, check_and_update_fn=self._update_int_time, default_fn=self._int_time_default, parameter_class=AcqVariablesParam) self.add_parameter(name='int_delay', - initial_value=None, check_and_update_fn=self._update_int_delay, default_fn=self._int_delay_default, parameter_class=AcqVariablesParam) @@ -215,13 +224,12 @@ def get_max_demod_freq(self): nb: really hacky and we should have channels in qcodes but we don't (at time of writing) """ - freqs = list(filter(None, [getattr(self, 'demod_freq_{}'.format(c))() - for c in range(self._demod_length)])) + freqs = list(filter(None, [getattr(self, 'demod_freq_{}'.format(c))() + for c in range(self._demod_length)])) if len(freqs) > 0: return max(freqs) else: - return None - + return None def update_filter_settings(self, filter, numtaps): """ diff --git a/qcodes/instrument_drivers/AlazarTech/basic_controller.py b/qcodes/instrument_drivers/AlazarTech/basic_controller.py index 7b172f070a7e..99421eef1f7e 100644 --- a/qcodes/instrument_drivers/AlazarTech/basic_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/basic_controller.py @@ -10,8 +10,10 @@ class SampleSweep(Parameter): Hardware controlled parameter class for Alazar acquisition. To be used with Acquisition Controller (tested with ATS9360 board) - Instrument returns an buffer of data (channels * samples * records) which - is processed by the post_acquire function of the Acquidiyion Controller + Alazar Instrument 'acquire' returns a buffer of data each time a buffer is + filled (channels * samples * records) which is processed by the + post_acquire function of the Acquisition Controller and finally the + processed result is returned when the SampleSweep parameter is called. """ def __init__(self, name, instrument): @@ -21,6 +23,15 @@ def __init__(self, name, instrument): self.names = ('A', 'B') def get(self): + """ + Gets the averaged samples for channels A and B by calling acquire + on the alazar (which in turn calls the processing functions of the + aqcuisition controller before returning the processed data) + + returns: + recordA: numpy array of channel A acquisition + recordB: numpy array of channel B acquisition + """ recordA, recordB = self._instrument._get_alazar().acquire( acquisition_controller=self._instrument, **self.acquisition_kwargs) @@ -38,8 +49,6 @@ class Basic_Acquisition_Controller(AcquisitionController): alazar_name: the name of the alazar instrument such that this controller can communicate with the Alazar **kwargs: kwargs are forwarded to the Instrument base class - - TODO(nataliejpg) make dtype general or get from alazar """ def __init__(self, name, alazar_name, **kwargs): @@ -59,7 +68,8 @@ def update_acquisition_kwargs(self, **kwargs): :return: """ self.samples_per_record = kwargs['samples_per_record'] - self.acquisition.shapes = ((self.samples_per_record,), (self.samples_per_record,)) + self.acquisition.shapes = ( + (self.samples_per_record,), (self.samples_per_record,)) self.acquisition.acquisition_kwargs.update(**kwargs) def pre_start_capture(self): @@ -84,22 +94,28 @@ def pre_acquire(self): See AcquisitionController :return: """ - # this could be used to start an Arbitrary Waveform Generator, etc... - # using this method ensures that the contents are executed AFTER the - # Alazar card starts listening for a trigger pulse pass def handle_buffer(self, data): """ - See AcquisitionController + Function which is called during the Alazar acquire each time a buffer + is completed. In this acquistion controller these buffers are just + added together (ie averaged) :return: """ self.buffer += data def post_acquire(self): """ - See AcquisitionController - :return: + Function which is called at the end of the Alazar acquire function to + signal completion and trigger data processing. This acquisition + controller has averaged over the buffers acquired so has one buffer of + data which is splits into records and channels, averages over records + and returns the samples for each channel. + + return: + recordA: numpy array of channel A acquisition + recordB: numpy array of channel B acquisition """ # for ATS9360 samples are arranged in the buffer as follows: @@ -124,6 +140,7 @@ def post_acquire(self): recB += self.buffer[i0:i1:self.number_of_channels] recordB = np.uint16(recB / records_per_acquisition) + # converts to volts if bits per sample is 12 (as ATS9360) bps = self.board_info['bits_per_sample'] if bps == 12: volt_rec_A = helpers.sample_to_volt_u12(recordA, bps) @@ -135,21 +152,3 @@ def post_acquire(self): volt_rec_B = recordB - np.mean(recordB) return volt_rec_A, volt_rec_B - -""" -def sample_to_volt_u12(raw_samples, bps): - # right_shift 16-bit sample by 4 to get 12 bit sample - shifted_samples = np.right_shift(raw_samples, 4) - - # Alazar calibration - code_zero = (1 << (bps - 1)) - 0.5 - code_range = (1 << (bps - 1)) - 0.5 - - # TODO(nataliejpg) make this not hard coded - input_range_volts = 1 - # Convert to volts - volt_samples = np.float64(input_range_volts * - (shifted_samples - code_zero) / code_range) - - return volt_samples -""" \ No newline at end of file diff --git a/qcodes/instrument_drivers/AlazarTech/rec_controller_test.py b/qcodes/instrument_drivers/AlazarTech/rec_controller_test.py index e19df17b195b..765a94b7acf0 100644 --- a/qcodes/instrument_drivers/AlazarTech/rec_controller_test.py +++ b/qcodes/instrument_drivers/AlazarTech/rec_controller_test.py @@ -8,8 +8,14 @@ class AcqVariablesParam(Parameter): - def __init__(self, name, instrument, initial_value, - check_and_update_fn, default_fn): + """ + Parameter of an AcquisitionController which has a _check_and_update_instr + function used for validation and to update instrument attributes and a + _get_default function which it uses to set the parameter to an instrument + caluclated default. + """ + def __init__(self, name, instrument, check_and_update_fn, + default_fn, initial_value=None): super().__init__(name) self._instrument = instrument self._save_val(initial_value) @@ -27,6 +33,11 @@ def to_default(self): default = self._get_default() self.set(default) + def check(self): + val = self._latest()['value'] + self._check_and_update_instr(val) + return True + class RecordsAcqParam(Parameter): """ @@ -113,12 +124,10 @@ def __init__(self, name, alazar_name, demod_length=1, filter='win', self.add_parameter(name='demod_freq_{}'.format(i), parameter_class=ManualParameter) self.add_parameter(name='int_time', - initial_value=None, check_and_update_fn=self._update_int_time, default_fn=self._int_time_default, parameter_class=AcqVariablesParam) self.add_parameter(name='int_delay', - initial_value=None, check_and_update_fn=self._update_int_delay, default_fn=self._int_delay_default, parameter_class=AcqVariablesParam) @@ -224,14 +233,13 @@ def get_max_demod_freq(self): nb: really hacky and we should have channels in qcodes but we don't (at time of writing) """ - freqs = list(filter(None, [getattr(self, 'demod_freq_{}'.format(c))() - for c in range(self._demod_length)])) + freqs = list(filter(None, [getattr(self, 'demod_freq_{}'.format(c))() + for c in range(self._demod_length)])) if len(freqs) > 0: return max(freqs) else: return None - def update_filter_settings(self, filter, numtaps): """ Updates the settings of the filter for filtering out @@ -294,13 +302,15 @@ def pre_start_capture(self): self.records_per_buffer * self.number_of_channels) - mat_shape = (self._demod_length, self.records_per_buffer, self.samples_per_record) + mat_shape = (self._demod_length, self.records_per_buffer, + self.samples_per_record) demod_list = np.array([getattr(self, 'demod_freq_{}'.format(n))() for n in range(self._demod_length)]) integer_list = np.arange(self.samples_per_record) integer_mat = np.outer(np.ones(self.records_per_buffer), integer_list) angle_mat = 2 * np.pi * \ - np.outer(demod_list, integer_mat).reshape(mat_shape) / self.sample_rate + np.outer(demod_list, integer_mat).reshape( + mat_shape) / self.sample_rate self.cos_mat = np.cos(angle_mat) self.sin_mat = np.sin(angle_mat) @@ -370,8 +380,10 @@ def _fit(self, rec): volt_rec = rec - np.mean(rec, axis=1) # volt_rec to matrix and multiply with demodulation signal matrices - mat_shape = (self._demod_length, self.records_per_buffer, self.samples_per_record) - volt_rec_mat = np.outer(np.ones(self._demod_length), volt_rec).reshape(mat_shape) + mat_shape = (self._demod_length, self.records_per_buffer, + self.samples_per_record) + volt_rec_mat = np.outer( + np.ones(self._demod_length), volt_rec).reshape(mat_shape) re_mat = np.multiply(volt_rec_mat, self.cos_mat) im_mat = np.multiply(volt_rec_mat, self.sin_mat) diff --git a/qcodes/instrument_drivers/AlazarTech/samp.py b/qcodes/instrument_drivers/AlazarTech/samp.py deleted file mode 100644 index 89f080ff4ddd..000000000000 --- a/qcodes/instrument_drivers/AlazarTech/samp.py +++ /dev/null @@ -1,314 +0,0 @@ -import logging -from .ATS import AcquisitionController -import numpy as np -from qcodes import Parameter -from qcodes.instrument_drivers.AlazarTech.acq_helpers import filter_win, filter_ls, sample_to_volt_u12, roundup -from qcodes.instrument.parameter import ManualParameter -from qcodes.utils.validators import Validator, Numbers, Ints, Enum, Anything -# from qcodes.utils import validators - - -class SamplesParam(Parameter): - """ - Hardware controlled parameter class for Alazar acquisition. To be used with - HD_Samples_Controller (tested with ATS9360 board) for return of an array of - sample data from the Alazar, averaged over records and buffers. - - TODO(nataliejpg) refactor setpoints/shapes horriblenesss - TODO(nataliejpg) setpoint units - """ - - def __init__(self, name, instrument): - super().__init__(name) - self._instrument = instrument - self.acquisition_kwargs = {} - self.names = ('magnitude', 'phase') - self.setpoint_names = (('acq_time (s)',), ('acq_time (s)',)) - - def update_sweep(self, start, stop, npts): - n = tuple(np.linspace(start, stop, num=npts)) - self.setpoints = ((n,), (n,)) - self.shapes = ((npts,), (npts,)) - - def get(self): - mag, phase = self._instrument._get_alazar().acquire( - acquisition_controller=self._instrument, - **self.acquisition_kwargs) - return mag, phase - - -class HD_Samples_Controller(AcquisitionController): - """ - This is the Acquisition Controller class which works with the ATS9360, - averaging over buffers and records and demodulating with a software - reference signal, returning the samples. - - TODO (nataliejpg) docstrings - - Args: - name: name for this acquisition_conroller as an instrument - alazar_name: the name of the alazar instrument such that this controller - can communicate with the Alazar - **kwargs: kwargs are forwarded to the Instrument base class - - Returns: - - - TODO(nataliejpg) test filter options - TODO(nataliejpg) finish implementation of channel b option - TODO(nataliejpg) set samples per record off int time and int delay - TODO(compare _get_alazar vs _alazar) - """ - filter_dict = {'win': 0, 'ls': 1} - - def __init__(self, name, alazar_name, filter='win', numtaps=101, chan_b=False, **kwargs): - self.filter_settings = {'filter': self.filter_dict[filter], - 'numtaps': numtaps} - self.chan_b = chan_b - self.number_of_channels = 2 - - super().__init__(name, alazar_name, **kwargs) - - self.add_parameter(name='acquisition', - parameter_class=SamplesParam) - self.add_parameter(name='demodulation_frequency', - parameter_class=ManualParameter) - self.add_parameter(name='int_time', - units='s', - vals=Anything(), - parameter_class=ManualParameter) - self.add_parameter(name='int_delay', - units='s', - vals=Anything(), - parameter_class=ManualParameter) - - def check_time_values(self): - if not (self.int_time() or self.int_delay()): - raise ValueError('int_time or int_delay are not set, set these ' - 'parameters or updats kwargs') - oscilations_measured = self.int_time() * self.demodulation_frequency() - total_time = self.samples_per_record / self.sample_rate - time_used = self.int_time() + self.int_delay() - samples_used = int(np.ceil(time_used * self.sample_rate)) - oversampling = self.sample_rate / (2 * self.demodulation_frequency()) - samples_delay_min = self.filter_settings['numtaps'] - 1 - int_delay_min = samples_delay_min / self.sample_rate - - if time_used > total_time: - raise ValueError('int_delay and int_time sum to {} which is more ' - 'than the total time available: {} . ' - 'Increase samples_per_record, decrease ' - 'sampling rate'.format(time_used, total_time)) - elif samples_used < self.samples_per_record - 32: - logging.info('{} samples used of {}, consider lowering the ' - 'number of samples per record to ' - '{}'.format(samples_used, self.samples_per_record, - np.ceil(samples_used / 32))) - - if self.int_time() == 0: - raise ValueError('int_time is set to 0') - elif oscilations_measured < 10: - logging.warning('{} oscilations measured, recommend at ' - 'least 10: decrease sampling rate, take ' - 'more samples or increase demodulation ' - 'freq'.format(oscilations_measured)) - if oversampling < 1: - logging.warning('oversampling rate is {}, recommend > 1: ' - 'increase sampling rate or decrease ' - 'demodulation frequency'.format(oversampling)) - if self.int_delay() < int_delay_min: - logging.warning( - 'delay is less than recommended for filter choice: ' - '(expect delay >= {}'.format(int_delay_min)) - - def update_filter_settings(self, filter, numtaps): - """ - Updates the settings of the filter for filtering out - double frwuency component for demodulation. - - Args: - filter (str): filter type ('win' or 'ls') - numtaps (int): numtaps for filter - """ - self.filter_settings.update({'filter': self.filter_dict[filter], - 'numtaps': numtaps}) - - def update_acquisition_kwargs(self, **kwargs): - """ - Updates the kwargs to be used when - alazar_driver.acquire is called via a get call of the - acquisition SamplesParam. - - It is also used to set the limits on the selection of - samples returned (bounded by delay and integration time) - and update this information in the Samples Parameter. - """ - alazar = self._get_alazar() - self.sample_rate = alazar.get_sample_rate() - if 'samples_per_record' in kwargs: - self.samples_per_record = roundup( - kwargs['samples_per_record'], alazar.samples_divisor) - time_available = self.samples_per_record / self.sample_rate - if self.int_delay() is None: - samp_delay = self.filter_settings['numtaps'] - 1 - self.int_delay(samp_delay / self.sample_rate) - time_available -= self.int_delay() - if self.int_time() is None: - self.int_time(time_available) - elif self.int_time() is not None: - if self.int_delay() is None: - samp_delay = self.filter_settings['numtaps'] - 1 - self.int_delay(samp_delay / self.sample_rate) - time_used = self.int_time() + self.int_delay() - samples_used = int(time_used * self.sample_rate) - self.samples_per_record = roundup( - samples_used, alazar.samples_divisor) - kwargs['samples_per_record'] = self.samples_per_record - else: - raise ValueError( - 'Either an integration time or samples_per_record ' - 'must be specified') - - self.check_time_values() - - start = self.int_delay() - stop = self.int_delay() + self.int_time() - npts = int(self.int_time() * self.sample_rate) - - self.acquisition.acquisition_kwargs.update(**kwargs) - self.acquisition.update_sweep(start, stop, npts) - - def pre_start_capture(self): - """ - Called before capture start to update Acquisition Controller with - alazar acquisition params and set up software wave for demodulation. - :return: - """ - alazar = self._get_alazar() - if self.samples_per_record != alazar.samples_per_record.get(): - raise Exception('Instrument samples_per_record settings does ' - 'not match acq controller value, most likely ' - 'need to call update_acquisition_settings') - if self.sample_rate != alazar.get_sample_rate(): - raise Exception('acq controller sample rate does not match ' - 'instrument value, most likely need to call ' - 'update_acquisition_settings') - self.check_time_values() - - self.records_per_buffer = alazar.records_per_buffer.get() - self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() - - self.board_info = alazar.get_idn() - self.buffer = np.zeros(self.samples_per_record * - self.records_per_buffer * - self.number_of_channels) - - integer_list = np.arange(self.samples_per_record, dtype=np.uint16) - angle_list = (2 * np.pi * self.demodulation_frequency() / - self.sample_rate * integer_list) - - self.cos_list = np.cos(angle_list) - self.sin_list = np.sin(angle_list) - - def pre_acquire(self): - """ - See AcquisitionController - :return: - """ - pass - - def handle_buffer(self, data): - """ - Adds data from alazar to buffer (effectively averaging) - :return: - """ - self.buffer += data - - def post_acquire(self): - """ - Processes the data according to ATS9360 settings, splitting into - records and averaging over them, then applying demodulation fit - nb: currently only channel A - :return: samples_magnitude_array, samples_phase_array - """ - records_per_acquisition = (self.buffers_per_acquisition * - self.records_per_buffer) - # for ATS9360 samples are arranged in the buffer as follows: - # S00A, S00B, S01A, S01B...S10A, S10B, S11A, S11B... - # where SXYZ is record X, sample Y, channel Z. - - # break buffer up into records and averages over them - recA = np.zeros(self.samples_per_record) - for i in range(self.records_per_buffer): - i0 = (i * self.samples_per_record * self.number_of_channels) - i1 = (i0 + self.samples_per_record * self.number_of_channels) - recA += self.buffer[i0:i1:self.number_of_channels] - recordA = np.uint16(recA / records_per_acquisition) - - # do demodulation - magA, phaseA = self.fit(recordA) - - # same for chan b - if self.chan_b: - raise NotImplementedError('chan b code not complete') - # recordB = np.zeros(self.samples_per_record, dtype=np.uint16) - # for i in range(self.records_per_buffer): - # i0 = (i * self.samples_per_record * - # self.number_of_channels + 1) - # i1 = (i0 + self.samples_per_record * self.number_of_channels) - # recordB += np.uint16(self.buffer[i0:i1:self.number_of_channels] / - # records_per_acquisition) - # magB, phaseB = self.fit(recordB) - - return magA, phaseA - - def fit(self, rec): - """ - Applies volts conversion, demodulation fit, low bandpass filter - and integration limits to samples array - :return: samples_magnitude_array, samples_phase_array - """ - - # convert rec to volts - bps = self.board_info['bits_per_sample'] - if bps == 12: - volt_rec = sample_to_volt_u12(rec, bps) - else: - logging.warning('sample to volt conversion does not exist for' - ' bps != 12, centered raw samples returned') - volt_rec = rec - np.mean(rec) - - # multiply with software wave - re_wave = np.multiply(volt_rec, self.cos_list) - im_wave = np.multiply(volt_rec, self.sin_list) - cutoff = self.demodulation_frequency() / 10 - - # filter out higher freq component - if self.filter_settings['filter'] == 0: - re_filtered = filter_win(re_wave, cutoff, - self.sample_rate, - self.filter_settings['numtaps']) - im_filtered = filter_win(im_wave, cutoff, - self.sample_rate, - self.filter_settings['numtaps']) - elif self.filter_settings['filter'] == 1: - re_filtered = filter_ls(re_wave, cutoff, - self.sample_rate, - self.filter_settings['numtaps']) - im_filtered = filter_ls(im_wave, cutoff, - self.sample_rate, - self.filter_settings['numtaps']) - - # apply integration limits - beginning = int(self.int_delay() * self.sample_rate) - end = beginning + int(self.int_time() * self.sample_rate) - - re_limited = re_filtered[beginning:end] - im_limited = im_filtered[beginning:end] - - # convert to magnitude and phase - complex_num = re_limited + im_limited * 1j - mag = abs(complex_num) - phase = np.angle(complex_num, deg=True) - - return mag, phase diff --git a/qcodes/instrument_drivers/AlazarTech/samp_controller.py b/qcodes/instrument_drivers/AlazarTech/samp_controller.py index 484540a3ca36..ce54f8a29c99 100644 --- a/qcodes/instrument_drivers/AlazarTech/samp_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/samp_controller.py @@ -8,8 +8,15 @@ class AcqVariablesParam(Parameter): - def __init__(self, name, instrument, initial_value, - check_and_update_fn, default_fn): + """ + Parameter of an AcquisitionController which has a _check_and_update_instr + function used for validation and to update instrument attributes and a + _get_default function which it uses to set the AcqVariablesParam to an + instrument caluclated default. + """ + + def __init__(self, name, instrument, check_and_update_fn, + default_fn, initial_value=None): super().__init__(name) self._instrument = instrument self._save_val(initial_value) @@ -17,6 +24,13 @@ def __init__(self, name, instrument, initial_value, setattr(self, '_get_default', default_fn) def set(self, value): + """ + Function which checks value using validation function and then sets + the Parameter value to this value. + + Args: + value: value to set the parameter to + """ self._check_and_update_instr(value) self._save_val(value) @@ -24,10 +38,22 @@ def get(self): return self._latest()['value'] def to_default(self): + """ + Function which executes the default_fn specified to calculate the + default value based on instrument values and then calls the set + function with this value + """ default = self._get_default() self.set(default) def check(self): + """ + Function which checks the current Parameter value using the specified + check_and_update_fn which can also serve to update instrument values. + + Return: + True (if no errors raised when check_and_update_fn executed) + """ val = self._latest()['value'] self._check_and_update_instr(val) return True @@ -60,8 +86,6 @@ def update_sweep(self, start, stop, npts): self.shapes = ((npts,), (npts,)) def get(self): - # self._instrument.int_time.check() - # self._instrument.int_delay.check() mag, phase = self._instrument._get_alazar().acquire( acquisition_controller=self._instrument, **self.acquisition_kwargs) @@ -90,9 +114,7 @@ class HD_Samples_Controller(AcquisitionController): TODO(nataliejpg) finish implementation of channel b option TODO(nataliejpg) what should be private? TODO(nataliejpg) where should filter_dict live? - TODO(nataliejpg) demod_freq should be changeable number: maybe channels - TODO(nataliejpg) try using fit from helpers - TODO(nataliejpg) check docstrings + TODO(nataliejpg) demod_freq number should be changeable number: channels? """ filter_dict = {'win': 0, 'ls': 1} samples_divisor = AlazarTech_ATS9360.samples_divisor @@ -114,12 +136,10 @@ def __init__(self, name, alazar_name, demod_length=1, filter='win', self.add_parameter(name='demod_freq_{}'.format(i), parameter_class=ManualParameter) self.add_parameter(name='int_time', - initial_value=None, check_and_update_fn=self._update_int_time, default_fn=self._int_time_default, parameter_class=AcqVariablesParam) self.add_parameter(name='int_delay', - initial_value=None, check_and_update_fn=self._update_int_delay, default_fn=self._int_delay_default, parameter_class=AcqVariablesParam) @@ -128,16 +148,24 @@ def _update_int_time(instr, value): """ Function to validate value for int_time before setting parameter value - Checks: limit between 0 and 0.1s - acq knows sample_rate (doesn't check with alazar for accuracy) - number of oscilation measured in this time - oversampling rate - Sets: samples_per_record of acq controller - acquisition_kwarg['samples_per_record'] of acquisition param - shape of acquisition param + + Args: + value to be validated and used for instrument attribute update + + Checks: + 0 <= value <= 0.1 seconds + number of oscilation measured in this time + oversampling rate + + Sets: + sample_rate attribute of instument to be that of alazar + samples_per_record of acq controller + acquisition_kwarg['samples_per_record'] of acquisition param + shape of acquisition param """ if (value is None) or not (0 <= value <= 0.1): raise ValueError('int_time must be 0 <= value <= 1') + alazar = instr._get_alazar() instr.sample_rate = alazar.get_sample_rate() if instr.get_max_demod_freq() is not None: @@ -237,12 +265,12 @@ def get_max_demod_freq(self): nb: really hacky and we should have channels in qcodes but we don't (at time of writing) """ - freqs = list(filter(None, [getattr(self, 'demod_freq_{}'.format(c))() - for c in range(self._demod_length)])) + freqs = list(filter(None, [getattr(self, 'demod_freq_{}'.format(c))() + for c in range(self._demod_length)])) if len(freqs) > 0: return max(freqs) else: - return None + return None def update_filter_settings(self, filter, numtaps): """ @@ -273,7 +301,8 @@ def update_acquisition_kwargs(self, **kwargs): raise ValueError('With HD_Samples_Controller ' 'samples_per_record cannot be set manually ' 'via update_acquisition_kwargs and should instead' - 'be set by setting int_time and int_delay') + 'be set by setting int_time int_delay and alazar ' + 'sample_rate') self.acquisition.acquisition_kwargs.update(**kwargs) def pre_start_capture(self): @@ -325,7 +354,7 @@ def post_acquire(self): Returns: magnitude (numpy array): shape = (demod_length, samples_used) phase (numpy array): shape = (demod_length, samples_used) - """ + """ records_per_acquisition = (self.buffers_per_acquisition * self.records_per_buffer) # for ATS9360 samples are arranged in the buffer as follows: @@ -346,14 +375,6 @@ def post_acquire(self): # same for chan b if self.chan_b: raise NotImplementedError('chan b code not complete') - # recordB = np.zeros(self.samples_per_record, dtype=np.uint16) - # for i in range(self.records_per_buffer): - # i0 = (i * self.samples_per_record * - # self.number_of_channels + 1) - # i1 = (i0 + self.samples_per_record * self.number_of_channels) - # recordB += np.uint16(self.buffer[i0:i1:self.number_of_channels] / - # records_per_acquisition) - # magB, phaseB = self.fit(recordB) return magA, phaseA @@ -385,7 +406,7 @@ def _fit(self, rec): volt_rec_mat = np.outer(np.ones(self._demod_length), volt_rec) re_mat = np.multiply(volt_rec_mat, self.cos_mat) im_mat = np.multiply(volt_rec_mat, self.sin_mat) - + # filter out higher freq component cutoff = self.get_max_demod_freq() / 20 if self.filter_settings['filter'] == 0: @@ -413,8 +434,8 @@ def _fit(self, rec): re_limited = re_filtered[:, beginning:end] im_limited = im_filtered[:, beginning:end] - #return re_limited, volt_rec_mat[:, beginning:end] - + # return re_limited, volt_rec_mat[:, beginning:end] + # convert to magnitude and phase complex_mat = re_limited + im_limited * 1j magnitude = abs(complex_mat) From b8689c84abb2228ef1d5c83e94e4f0f312d50023 Mon Sep 17 00:00:00 2001 From: Natalie Pearson Date: Mon, 6 Feb 2017 19:36:53 +0100 Subject: [PATCH 096/180] add docstrings and refactor demod_freq parameter to be homemade AcqVariable param so that setpoints will be updated when demod_freqs changed --- .../AlazarTech/ave_controller_test.py | 246 +++++++++++++---- .../AlazarTech/basic_controller.py | 9 +- .../AlazarTech/rec_controller_test.py | 258 ++++++++++++++---- .../AlazarTech/samp_controller.py | 206 +++++++++++--- 4 files changed, 575 insertions(+), 144 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/ave_controller_test.py b/qcodes/instrument_drivers/AlazarTech/ave_controller_test.py index 8dce5a6612e5..3018775875d3 100644 --- a/qcodes/instrument_drivers/AlazarTech/ave_controller_test.py +++ b/qcodes/instrument_drivers/AlazarTech/ave_controller_test.py @@ -4,38 +4,71 @@ import numpy as np from qcodes import Parameter import qcodes.instrument_drivers.AlazarTech.acq_helpers as helpers -from qcodes.instrument.parameter import ManualParameter class AcqVariablesParam(Parameter): """ Parameter of an AcquisitionController which has a _check_and_update_instr function used for validation and to update instrument attributes and a - _get_default function which it uses to set the parameter to an instrument - caluclated default. + _get_default function which it uses to set the AcqVariablesParam to an + instrument caluclated default. + + Args: + name: name for this parameter + instrument: acquisition controller instrument this parameter belongs to + check_and_update_fn: instrument function to be used for value + validation and updating instrument values + default_fn (optional): instrument function to be used to calculate + a default value to set parameter to + initial_value (optional): initial value for parameter """ + def __init__(self, name, instrument, check_and_update_fn, - default_fn, initial_value=None): + default_fn=None, initial_value=None): super().__init__(name) self._instrument = instrument self._save_val(initial_value) setattr(self, '_check_and_update_instr', check_and_update_fn) - setattr(self, '_get_default', default_fn) + if default_fn is not None: + setattr(self, '_get_default', default_fn) def set(self, value): - self._check_and_update_instr(value) + """ + Function which checks value using validation function and then sets + the Parameter value to this value. + + Args: + value: value to set the parameter to + """ + self._check_and_update_instr(value, param_name=self.name) self._save_val(value) def get(self): return self._latest()['value'] def to_default(self): - default = self._get_default() + """ + Function which executes the default_fn specified to calculate the + default value based on instrument values and then calls the set + function with this value + """ + try: + default = self._get_default() + except AttributeError as e: + raise AttributeError('no default function for {} Parameter ' + '{}'.format(self.name, e)) self.set(default) def check(self): + """ + Function which checks the current Parameter value using the specified + check_and_update_fn which can also serve to update instrument values. + + Return: + True (if no errors raised when check_and_update_fn executed) + """ val = self._latest()['value'] - self._check_and_update_instr(val) + self._check_and_update_instr(val, param_name=self.name) return True @@ -45,9 +78,15 @@ class AveragedAcqParam(Parameter): HD_Averaging_Controller (tested with ATS9360 board) for return of averaged magnitude and phase data from the Alazar. + Args: + name: name for this parameter + instrument: acquisition controller instrument this parameter belongs to + demod_length: numer of demodulation frequencies the acq controller has + NB this is currently set in acq controller init but that's really + not nice and should be changed when possible + TODO(nataliejpg) setpoints (including names and units) TODO(nataliejpg) setpoint units - TODO(nataliejpg) convert demod_index setpoint into actual frequency """ def __init__(self, name, instrument, demod_length): @@ -60,7 +99,34 @@ def __init__(self, name, instrument, demod_length): else: self.shapes = ((), ()) + def update_demod_setpoints(self, demod_freqs): + """ + Function to update the demodulation frequency setpoints to be called + when a demod_freq Parameter of the acq controller is updated + + Args: + demod_freqs: numpy array of demodulation frequencies to use as + setpoints if length > 1 + """ + demod_length = self._instrument._demod_length + self._demod_list = demod_freqs + if demod_length > 1: + self.setpoints = ((self._demod_list, ), (self._demod_list, )) + else: + pass + def get(self): + """ + Gets the magnitude and phase signal by calling acquire + on the alazar (which in turn calls the processing functions of the + aqcuisition controller before returning the processed data + demodulated at specified frequencies and averaged over samples, + records and buffers) + + Returns: + mag: numpy array of magnitude, shape (demod_length, ) + phase: numpy array of magnitude, shape (demod_length, ) + """ mag, phase = self._instrument._get_alazar().acquire( acquisition_controller=self._instrument, **self.acquisition_kwargs) @@ -70,19 +136,19 @@ def get(self): class HD_Averaging_Controller(AcquisitionController): """ This is the Acquisition Controller class which works with the ATS9360, - averaging over samples, buffers and records, demodulating with a software - reference signal. + averaging over samples (limited by int_time and int_delay values), + records and buffers and demodulating with software reference signal(s). Args: name: name for this acquisition_conroller as an instrument - alazar_name: the name of the alazar instrument such that this + alazar_name: name of the alazar instrument such that this controller can communicate with the Alazar - demod_freqs: the frequency of the software wave to be created - filter: the filter to be used to filter out double freq component - ('win' - window, 'ls' - least squared, 'ave' - averaging) - numtaps: number of freq components used in filter - chan_b: whether there is also a second channel of data to be processed - and returned + demod_length (default 1): number of demodulation frequencies + filter (default 'win'): filter to be used to filter out double freq + component ('win' - window, 'ls' - least squared, 'ave' - averaging) + numtaps (default 101): number of freq components used in filter + chan_b (default False): whether there is also a second channel of data + to be processed and returned **kwargs: kwargs are forwarded to the Instrument base class TODO(nataliejpg) test filter options @@ -91,7 +157,6 @@ class HD_Averaging_Controller(AcquisitionController): TODO(nataliejpg) where should filter_dict live? TODO(nataliejpg) demod_freq should be changeable number: maybe channels TODO(nataliejpg) try using fit from helpers - TODO(nataliejpg) check docstrings """ filter_dict = {'win': 0, 'ls': 1, 'ave': 2} @@ -113,7 +178,8 @@ def __init__(self, name, alazar_name, demod_length=1, filter='win', parameter_class=AveragedAcqParam) for i in range(demod_length): self.add_parameter(name='demod_freq_{}'.format(i), - parameter_class=ManualParameter) + check_and_update_fn=self._update_demod_freq, + parameter_class=AcqVariablesParam) self.add_parameter(name='int_time', check_and_update_fn=self._update_int_time, default_fn=self._int_time_default, @@ -123,30 +189,82 @@ def __init__(self, name, alazar_name, demod_length=1, filter='win', default_fn=self._int_delay_default, parameter_class=AcqVariablesParam) - def _update_int_time(instr, value): + def _update_demod_freq(instr, value, param_name=None): + """ + Function to validate and update acquisiton parameter when + a demod_freq_ Parameter is changed + + Args: + value to update demodulation frequency to + + Kwargs: + param_name: used to update demod_freq list used for updating + septionts of acquisition parameter + + Checks: + 1e6 <= value <= 500e6 + number of oscilation measured using current int_tiume param value + at this demod frequency value + oversampling rate for this demodulation frequency + + Sets: + sample_rate attr of acq controller to be that of alazar + setpoints of acquisiton parameter + """ + if (value is None) or not (1e6 <= value <= 500e6): + raise ValueError('demod_freqs must be 1e6 <= value <= 500e6') + alazar = instr._get_alazar() + instr.sample_rate = alazar.get_sample_rate() + min_oscilations_measured = instr.int_time() * value + oversampling = instr.sample_rate / (2 * value) + if min_oscilations_measured < 10: + logging.warning('{} oscilations measured for largest ' + 'demod freq, recommend at least 10: ' + 'decrease sampling rate, take ' + 'more samples or increase demodulation ' + 'freq'.format(min_oscilations_measured)) + elif oversampling < 1: + logging.warning('oversampling rate is {}, recommend > 1: ' + 'increase sampling rate or decrease ' + 'demodulation frequency'.format(oversampling)) + demod_freqs = instr.get_demod_freqs() + current_demod_index = ([int(s) for s in param_name.split() + if s.isdigit()][0]) + demod_freqs[current_demod_index] = value + instr.acquisition.update_demod_setpoints(demod_freqs) + + def _update_int_time(instr, value, **kwargs): """ Function to validate value for int_time before setting parameter value - Checks: limit between 0 and 0.1s - acq knows sample_rate (doesn't check with alazar for accuracy) - number of oscilation measured in this time - oversampling rate - Sets: samples_per_record of acq controller - acquisition_kwarg['samples_per_record'] of acquisition param - shape of acquisition param + + Args: + value to be validated and used for instrument attribute update + + Checks: + 0 <= value <= 0.1 seconds + number of oscilation measured in this time + oversampling rate + + Sets: + sample_rate attr of acq controller to be that of alazar + samples_per_record of acq controller + acquisition_kwarg['samples_per_record'] of acquisition param """ if (value is None) or not (0 <= value <= 0.1): raise ValueError('int_time must be 0 <= value <= 1') + alazar = instr._get_alazar() instr.sample_rate = alazar.get_sample_rate() if instr.get_max_demod_freq() is not None: - oscilations_measured = value * instr.get_max_demod_freq() + min_oscilations_measured = value * instr.get_max_demod_freq() oversampling = instr.sample_rate / (2 * instr.get_max_demod_freq()) - if oscilations_measured < 10: - logging.warning('{} oscilations measured, recommend at ' - 'least 10: decrease sampling rate, take ' + if min_oscilations_measured < 10: + logging.warning('{} oscilations measured for largest ' + 'demod freq, recommend at least 10: ' + 'decrease sampling rate, take ' 'more samples or increase demodulation ' - 'freq'.format(oscilations_measured)) + 'freq'.format(min_oscilations_measured)) elif oversampling < 1: logging.warning('oversampling rate is {}, recommend > 1: ' 'increase sampling rate or decrease ' @@ -162,16 +280,23 @@ def _update_int_time(instr, value): instr.acquisition.acquisition_kwargs.update( samples_per_record=instr.samples_per_record) - def _update_int_delay(instr, value): + def _update_int_delay(instr, value, **kwargs): """ Function to validate value for int_delay before setting parameter value - Checks: limit between 0 and 1s - acq knows sample_rate (doesn't check with alazar for accuracy) - number of samples discarded >= numtaps - Sets: samples_per_record of acq controller - acquisition_kwarg['samples_per_record'] of acquisition param - shape of acquisition param + + Args: + value to be validated and used for instrument attribute update + + Checks: + 0 <= value <= 0.1 seconds + number of samples discarded >= numtaps + + Sets: + sample_rate attr of acq controller to be that of alazar + samples_per_record of acq controller + acquisition_kwarg['samples_per_record'] of acquisition param + setpoints of acquisiton param """ if (value is None) or not (0 <= value <= 0.1): raise ValueError('int_delay must be 0 <= value <= 1') @@ -194,8 +319,11 @@ def _update_int_delay(instr, value): def _int_delay_default(instr): """ - Returns minimum int_delay recommended for (numtaps - 1) - samples to be discarded as recommended for filter + Function to generate default int_delay value + + Returns: + minimum int_delay recommended for (numtaps - 1) + samples to be discarded as recommended for filter """ alazar = instr._get_alazar() instr.sample_rate = alazar.get_sample_rate() @@ -204,8 +332,11 @@ def _int_delay_default(instr): def _int_time_default(instr): """ - Returns max total time for integration based on samples_per_record, - sample_rate and int_delay + Function to generate defult int_time value + + Returns: + max total time for integration based on samples_per_record, + sample_rate and int_delay """ if instr.samples_per_record is (0 or None): raise ValueError('Cannot set int_time to max if acq controller' @@ -218,14 +349,26 @@ def _int_time_default(instr): (instr.int_delay() or 0)) return total_time + def get_demod_freqs(self): + """ + Function to get all the demod_freq parameter values in a list, v hacky + + Returns: + freqs: numpy array of demodulation frequencies + """ + freqs = list(filter(None, [getattr(self, 'demod_freq_{}'.format(c))() + for c in range(self._demod_length)])) + return np.array(freqs) + def get_max_demod_freq(self): """ - Returns the largest demodulation frequency + Returns: + the largest demodulation frequency + nb: really hacky and we should have channels in qcodes but we don't (at time of writing) """ - freqs = list(filter(None, [getattr(self, 'demod_freq_{}'.format(c))() - for c in range(self._demod_length)])) + freqs = self.get_demod_freqs() if len(freqs) > 0: return max(freqs) else: @@ -277,8 +420,11 @@ def pre_start_capture(self): raise Exception('acq controller sample rate does not match ' 'instrument value, most likely need ' 'to set and check int_time and int_delay') - if self.get_max_demod_freq() is None: - raise Exception('no demodulation frequencies set') + + demod_list = self.get_demod_freqs() + if len(demod_list) == 0: + raise Exception('no demod_freqs set') + self.records_per_buffer = alazar.records_per_buffer.get() self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() self.board_info = alazar.get_idn() @@ -286,8 +432,6 @@ def pre_start_capture(self): self.records_per_buffer * self.number_of_channels) - demod_list = np.array([getattr(self, 'demod_freq_{}'.format(n))() - for n in range(self._demod_length)]) integer_list = np.arange(self.samples_per_record) angle_mat = 2 * np.pi * \ np.outer(demod_list, integer_list) / self.sample_rate diff --git a/qcodes/instrument_drivers/AlazarTech/basic_controller.py b/qcodes/instrument_drivers/AlazarTech/basic_controller.py index 99421eef1f7e..176749e57848 100644 --- a/qcodes/instrument_drivers/AlazarTech/basic_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/basic_controller.py @@ -14,6 +14,10 @@ class SampleSweep(Parameter): filled (channels * samples * records) which is processed by the post_acquire function of the Acquisition Controller and finally the processed result is returned when the SampleSweep parameter is called. + + :args: + name: name for this parameter + instrument: acquisition controller instrument this parameter belongs to """ def __init__(self, name, instrument): @@ -24,9 +28,10 @@ def __init__(self, name, instrument): def get(self): """ - Gets the averaged samples for channels A and B by calling acquire + Gets the samples for channels A and B by calling acquire on the alazar (which in turn calls the processing functions of the - aqcuisition controller before returning the processed data) + aqcuisition controller before returning the reshaped data averaged + over records and buffers) returns: recordA: numpy array of channel A acquisition diff --git a/qcodes/instrument_drivers/AlazarTech/rec_controller_test.py b/qcodes/instrument_drivers/AlazarTech/rec_controller_test.py index 765a94b7acf0..714354c462c8 100644 --- a/qcodes/instrument_drivers/AlazarTech/rec_controller_test.py +++ b/qcodes/instrument_drivers/AlazarTech/rec_controller_test.py @@ -4,70 +4,148 @@ import numpy as np from qcodes import Parameter import qcodes.instrument_drivers.AlazarTech.acq_helpers as helpers -from qcodes.instrument.parameter import ManualParameter class AcqVariablesParam(Parameter): """ Parameter of an AcquisitionController which has a _check_and_update_instr function used for validation and to update instrument attributes and a - _get_default function which it uses to set the parameter to an instrument - caluclated default. + _get_default function which it uses to set the AcqVariablesParam to an + instrument caluclated default. + + Args: + name: name for this parameter + instrument: acquisition controller instrument this parameter belongs to + check_and_update_fn: instrument function to be used for value + validation and updating instrument values + default_fn (optional): instrument function to be used to calculate + a default value to set parameter to + initial_value (optional): initial value for parameter """ + def __init__(self, name, instrument, check_and_update_fn, - default_fn, initial_value=None): + default_fn=None, initial_value=None): super().__init__(name) self._instrument = instrument self._save_val(initial_value) setattr(self, '_check_and_update_instr', check_and_update_fn) - setattr(self, '_get_default', default_fn) + if default_fn is not None: + setattr(self, '_get_default', default_fn) def set(self, value): - self._check_and_update_instr(value) + """ + Function which checks value using validation function and then sets + the Parameter value to this value. + + Args: + value: value to set the parameter to + """ + self._check_and_update_instr(value, param_name=self.name) self._save_val(value) def get(self): return self._latest()['value'] def to_default(self): - default = self._get_default() + """ + Function which executes the default_fn specified to calculate the + default value based on instrument values and then calls the set + function with this value + """ + try: + default = self._get_default() + except AttributeError as e: + raise AttributeError('no default function for {} Parameter ' + '{}'.format(self.name, e)) self.set(default) def check(self): + """ + Function which checks the current Parameter value using the specified + check_and_update_fn which can also serve to update instrument values. + + Return: + True (if no errors raised when check_and_update_fn executed) + """ val = self._latest()['value'] - self._check_and_update_instr(val) + self._check_and_update_instr(val, param_name=self.name) return True class RecordsAcqParam(Parameter): """ Software controlled parameter class for Alazar acquisition. To be used with - HD_Records_Controller (tested with ATS9360 board) for return of an array of - records data from the Alazar, averaged over and buffers. + HD_Records_Controller (tested with ATS9360 board) for return of + averaged magnitude and phase data from the Alazar. + + Args: + name: name for this parameter + instrument: acquisition controller instrument this parameter belongs to + demod_length: numer of demodulation frequencies the acq controller has + NB this is currently set in acq controller init but that's really + not nice and should be changed when possible TODO(nataliejpg) setpoints (including names and units) TODO(nataliejpg) setpoint units - TODO(nataliejpg) convert demod_index setpoint into actual frequency TODO(nataliejpg) convert records setpoint into actual frequency """ - def __init__(self, name, instrument, demod_length): super().__init__(name) self._instrument = instrument self.acquisition_kwargs = {} self.names = ('magnitude', 'phase') - self.shapes = ((demod_length, ), (demod_length, )) def update_sweep(self, npts, start=None, stop=None): + """ + Function which updates the shape of the parameter (and it's setpoints + when this is fixed) + + Args: + npts: number of recornds returned after processing + start (optional): start value of records returned (if relevant) + stop (optional): stop value of records returned (if relevant) + """ demod_length = self._instrument._demod_length - # rec_list = tuple(np.linspace(start, stop, num=npts)) + # self.rec_list = tuple(np.linspace(start, stop, num=npts)) # demod_index = tuple(range(demod_length)) if demod_length > 1: + # demod_index = tuple(range(demod_length)) + # demod_freqs = self._instrument.get_demod_freqs() + # self.setpoints = ((demod_freqs, self._rec_list), ( + # demod_freqs, self._rec_list)) self.shapes = ((demod_length, npts), (demod_length, npts)) else: self.shapes = ((npts,), (npts,)) + # self.setpoints = ((self._rec_list,), (self._rec_list,)) + + def update_demod_setpoints(self, demod_freqs): + """ + Function to update the demodulation frequency setpoints to be called + when a demod_freq Parameter of the acq controller is updated + + Args: + demod_freqs: numpy array of demodulation frequencies to use as + setpoints if length > 1 + """ + demod_length = self._instrument._demod_length + if demod_length > 1: + self.setpoints = ((demod_freqs, self._rec_list), + (demod_freqs, self._rec_list)) + else: + pass def get(self): + """ + Gets the magnitude and phase signal by calling acquire + on the alazar (which in turn calls the processing functions of the + aqcuisition controller before returning the processed data + demodulated at specified frequencies and averaged over samples + and buffers) + + Returns: + mag: numpy array of magnitude, shape (demod_length, records) + phase: numpy array of magnitude, shape (demod_length, records) + """ mag, phase = self._instrument._get_alazar().acquire( acquisition_controller=self._instrument, **self.acquisition_kwargs) @@ -77,19 +155,19 @@ def get(self): class HD_Records_Controller(AcquisitionController): """ This is the Acquisition Controller class which works with the ATS9360, - averaging over buffers and samples, demodulating with software - reference signals. + averaging over samples (limited by int_time and int_delay values) and + buffers and demodulating with software reference signal(s). Args: name: name for this acquisition_conroller as an instrument - alazar_name: the name of the alazar instrument such that this + alazar_name: name of the alazar instrument such that this controller can communicate with the Alazar - demod_freqs: the frequency of the software wave to be created - filter: the filter to be used to filter out double freq component - ('win' - window, 'ls' - least squared, 'ave' - averaging) - numtaps: number of freq components used in filter - chan_b: whether there is also a second channel of data to be processed - and returned + demod_length (default 1): number of demodulation frequencies + filter (default 'win'): filter to be used to filter out double freq + component ('win' - window, 'ls' - least squared, 'ave' - averaging) + numtaps (default 101): number of freq components used in filter + chan_b (default False): whether there is also a second channel of data + to be processed and returned **kwargs: kwargs are forwarded to the Instrument base class TODO(nataliejpg) test filter options @@ -99,7 +177,6 @@ class HD_Records_Controller(AcquisitionController): TODO(nataliejpg) demod_freq should be changeable number: maybe channels TODO(nataliejpg) try using fit from helpers TODO(nataliejpg) make records a parameter or similar (MultiParam?) - TODO(nataliejpg) check docstrings """ filter_dict = {'win': 0, 'ls': 1, 'ave': 2} @@ -122,7 +199,8 @@ def __init__(self, name, alazar_name, demod_length=1, filter='win', parameter_class=RecordsAcqParam) for i in range(demod_length): self.add_parameter(name='demod_freq_{}'.format(i), - parameter_class=ManualParameter) + check_and_update_fn=self._update_demod_freq, + parameter_class=AcqVariablesParam) self.add_parameter(name='int_time', check_and_update_fn=self._update_int_time, default_fn=self._int_time_default, @@ -132,17 +210,67 @@ def __init__(self, name, alazar_name, demod_length=1, filter='win', default_fn=self._int_delay_default, parameter_class=AcqVariablesParam) - def _update_int_time(instr, value): + def _update_demod_freq(instr, value, param_name=None): + """ + Function to validate and update acquisiton parameter when + a demod_freq_ Parameter is changed + + Args: + value to update demodulation frequency to + + Kwargs: + param_name: used to update demod_freq list used for updating + septionts of acquisition parameter + + Checks: + 1e6 <= value <= 500e6 + number of oscilation measured using current int_tiume param value + at this demod frequency value + oversampling rate for this demodulation frequency + + Sets: + sample_rate attr of acq controller to be that of alazar + setpoints of acquisiton parameter + """ + if (value is None) or not (1e6 <= value <= 500e6): + raise ValueError('demod_freqs must be 1e6 <= value <= 500e6') + alazar = instr._get_alazar() + instr.sample_rate = alazar.get_sample_rate() + min_oscilations_measured = instr.int_time() * value + oversampling = instr.sample_rate / (2 * value) + if min_oscilations_measured < 10: + logging.warning('{} oscilations measured for largest ' + 'demod freq, recommend at least 10: ' + 'decrease sampling rate, take ' + 'more samples or increase demodulation ' + 'freq'.format(min_oscilations_measured)) + elif oversampling < 1: + logging.warning('oversampling rate is {}, recommend > 1: ' + 'increase sampling rate or decrease ' + 'demodulation frequency'.format(oversampling)) + demod_freqs = instr.get_demod_freqs() + current_demod_index = ([int(s) for s in param_name.split() + if s.isdigit()][0]) + demod_freqs[current_demod_index] = value + instr.acquisition.update_demod_setpoints(demod_freqs) + + def _update_int_time(instr, value, **kwargs): """ Function to validate value for int_time before setting parameter value - Checks: limit between 0 and 0.1s - acq knows sample_rate (doesn't check with alazar for accuracy) - number of oscilation measured in this time - oversampling rate - Sets: samples_per_record of acq controller - acquisition_kwarg['samples_per_record'] of acquisition param - shape of acquisition param + + Args: + value to be validated and used for instrument attribute update + + Checks: + 0 <= value <= 0.1 seconds + number of oscilation measured in this time + oversampling rate + + Sets: + sample_rate attr of acq controller to be that of alazar + samples_per_record of acq controller + acquisition_kwarg['samples_per_record'] of acquisition param """ if (value is None) or not (0 <= value <= 0.1): raise ValueError('int_time must be 0 <= value <= 1') @@ -171,16 +299,23 @@ def _update_int_time(instr, value): instr.acquisition.acquisition_kwargs.update( samples_per_record=instr.samples_per_record) - def _update_int_delay(instr, value): + def _update_int_delay(instr, value, **kwargs): """ Function to validate value for int_delay before setting parameter value - Checks: limit between 0 and 1s - acq knows sample_rate (doesn't check with alazar for accuracy) - number of samples discarded >= numtaps - Sets: samples_per_record of acq controller - acquisition_kwarg['samples_per_record'] of acquisition param - shape of acquisition param + + Args: + value to be validated and used for instrument attribute update + + Checks: + 0 <= value <= 0.1 seconds + number of samples discarded >= numtaps + + Sets: + sample_rate attr of acq controller to be that of alazar + samples_per_record of acq controller + acquisition_kwarg['samples_per_record'] of acquisition param + setpoints of acquisiton param """ if (value is None) or not (0 <= value <= 0.1): raise ValueError('int_delay must be 0 <= value <= 1') @@ -203,8 +338,11 @@ def _update_int_delay(instr, value): def _int_delay_default(instr): """ - Returns minimum int_delay recommended for (numtaps - 1) - samples to be discarded as recommended for filter + Function to generate default int_delay value + + Returns: + minimum int_delay recommended for (numtaps - 1) + samples to be discarded as recommended for filter """ alazar = instr._get_alazar() instr.sample_rate = alazar.get_sample_rate() @@ -213,8 +351,11 @@ def _int_delay_default(instr): def _int_time_default(instr): """ - Returns max total time for integration based on samples_per_record, - sample_rate and int_delay + Function to generate defult int_time value + + Returns: + max total time for integration based on samples_per_record, + sample_rate and int_delay """ if instr.samples_per_record is (0 or None): raise ValueError('Cannot set int_time to max if acq controller' @@ -227,18 +368,30 @@ def _int_time_default(instr): (instr.int_delay() or 0)) return total_time + def get_demod_freqs(self): + """ + Function to get all the demod_freq parameter values in a list, v hacky + + Returns: + freqs: numpy array of demodulation frequencies + """ + freqs = list(filter(None, [getattr(self, 'demod_freq_{}'.format(c))() + for c in range(self._demod_length)])) + return np.array(freqs) + def get_max_demod_freq(self): """ - Returns the largest demodulation frequency + Returns: + the largest demodulation frequency + nb: really hacky and we should have channels in qcodes but we don't (at time of writing) """ - freqs = list(filter(None, [getattr(self, 'demod_freq_{}'.format(c))() - for c in range(self._demod_length)])) + freqs = self.get_demod_freqs() if len(freqs) > 0: return max(freqs) else: - return None + return None def update_filter_settings(self, filter, numtaps): """ @@ -256,7 +409,7 @@ def update_acquisition_kwargs(self, **kwargs): """ Updates the kwargs to be used when alazar_driver.acquisition() is called via a get call of the - acquisition SamplesParam. Should be used by the user for + acquisition SamplesParam. Should be used by the user for updating averaging settings since the 'samples_per_record' kwarg is updated via the int_time and int_delay parameters @@ -294,8 +447,11 @@ def pre_start_capture(self): 'instrument value, most likely need ' 'to call update_acquisition_kwargs with' 'records_per_buffer as a param') - if self.get_max_demod_freq() is None: - raise Exception('no demodulation frequencies set') + + demod_list = self.get_demod_freqs() + if len(demod_list) == 0: + raise Exception('no demod_freqs set') + self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() self.board_info = alazar.get_idn() self.buffer = np.zeros(self.samples_per_record * diff --git a/qcodes/instrument_drivers/AlazarTech/samp_controller.py b/qcodes/instrument_drivers/AlazarTech/samp_controller.py index ce54f8a29c99..02b67605d64d 100644 --- a/qcodes/instrument_drivers/AlazarTech/samp_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/samp_controller.py @@ -4,7 +4,6 @@ import numpy as np from qcodes import Parameter import qcodes.instrument_drivers.AlazarTech.acq_helpers as helpers -from qcodes.instrument.parameter import ManualParameter class AcqVariablesParam(Parameter): @@ -13,15 +12,25 @@ class AcqVariablesParam(Parameter): function used for validation and to update instrument attributes and a _get_default function which it uses to set the AcqVariablesParam to an instrument caluclated default. + + Args: + name: name for this parameter + instrument: acquisition controller instrument this parameter belongs to + check_and_update_fn: instrument function to be used for value + validation and updating instrument values + default_fn (optional): instrument function to be used to calculate + a default value to set parameter to + initial_value (optional): initial value for parameter """ def __init__(self, name, instrument, check_and_update_fn, - default_fn, initial_value=None): + default_fn=None, initial_value=None): super().__init__(name) self._instrument = instrument self._save_val(initial_value) setattr(self, '_check_and_update_instr', check_and_update_fn) - setattr(self, '_get_default', default_fn) + if default_fn is not None: + setattr(self, '_get_default', default_fn) def set(self, value): """ @@ -31,7 +40,7 @@ def set(self, value): Args: value: value to set the parameter to """ - self._check_and_update_instr(value) + self._check_and_update_instr(value, param_name=self.name) self._save_val(value) def get(self): @@ -43,7 +52,11 @@ def to_default(self): default value based on instrument values and then calls the set function with this value """ - default = self._get_default() + try: + default = self._get_default() + except AttributeError as e: + raise AttributeError('no default function for {} Parameter ' + '{}'.format(self.name, e)) self.set(default) def check(self): @@ -55,7 +68,7 @@ def check(self): True (if no errors raised when check_and_update_fn executed) """ val = self._latest()['value'] - self._check_and_update_instr(val) + self._check_and_update_instr(val, param_name=self.name) return True @@ -65,9 +78,12 @@ class SamplesAcqParam(Parameter): HD_Samples_Controller (tested with ATS9360 board) for return of an array of sample data from the Alazar, averaged over records and buffers. + Args: + name: name for this parameter + instrument: acquisition controller instrument this parameter belongs to + TODO(nataliejpg) setpoints (including names and units) TODO(nataliejpg) setpoint units - TODO(nataliejpg) convert demod_index setpoint into actual frequency """ def __init__(self, name, instrument): @@ -77,15 +93,56 @@ def __init__(self, name, instrument): self.names = ('magnitude', 'phase') def update_sweep(self, start, stop, npts): + """ + Function which updates the shape of the parameter (and it's setpoints + when this is fixed) + + Args: + start: start time of samples returned after processing + stop: stop time of samples returned after processing + npts: number of samples returned after processing + """ demod_length = self._instrument._demod_length - # freq = tuple(np.linspace(start, stop, num=npts)) - # demod_index = tuple(range(demod_length)) + # self._time_list = tuple(np.linspace(start, stop, num=npts)) if demod_length > 1: + # demod_index = tuple(range(demod_length)) + # self._demod_list = self._instrument.get_demod_freqs() + # self.setpoints = ((self._demod_list, self._time_list ), ( + # self._demod_list, self._time_list )) self.shapes = ((demod_length, npts), (demod_length, npts)) else: self.shapes = ((npts,), (npts,)) + # self.setpoints = ((self._time_list,), (self._time_list,)) + + def update_demod_setpoints(self, demod_freqs): + """ + Function to update the demodulation frequency setpoints to be called + when a demod_freq Parameter of the acq controller is updated + + Args: + demod_freqs: numpy array of demodulation frequencies to use as + setpoints if length > 1 + """ + demod_length = self._instrument._demod_length + self._demod_list = demod_freqs + if demod_length > 1: + self.setpoints = ((self._demod_list, self._time_list), + (self._demod_list, self._time_list)) + else: + pass def get(self): + """ + Gets the magnitude and phase signal by calling acquire + on the alazar (which in turn calls the processing functions of the + aqcuisition controller before returning the processed data + demodulated at specified frequencies and averaged over records + and buffers) + + Returns: + mag: numpy array of magnitude, shape (demod_length, samples) + phase: numpy array of magnitude, shape (demod_length, samples) + """ mag, phase = self._instrument._get_alazar().acquire( acquisition_controller=self._instrument, **self.acquisition_kwargs) @@ -95,19 +152,20 @@ def get(self): class HD_Samples_Controller(AcquisitionController): """ This is the Acquisition Controller class which works with the ATS9360, - averaging over buffers and records and demodulating with a software - reference signal, returning the samples. + averaging over records and buffers and demodulating with software + reference signal(s), returning samples limited by int_time and int_delay + values. Args: name: name for this acquisition_conroller as an instrument - alazar_name: the name of the alazar instrument such that this + alazar_name: name of the alazar instrument such that this controller can communicate with the Alazar - demod_freqs: the frequencies of the software wave to be created - filter: the filter to be used to filter out double freq component - ('win' - window, 'ls' - least squared) - numtaps: number of freq components used in the filter - chan_b: whether there is also a second channel of data to be processed - and returned + demod_length (default 1): number of demodulation frequencies + filter (default 'win'): filter to be used to filter out double + freq component ('win' - window, 'ls' - least squared) + numtaps (default 101): number of freq components used in the filter + chan_b (default False): whether there is also a second channel of data + to be processed and returned **kwargs: kwargs are forwarded to the Instrument base class TODO(nataliejpg) test filter options @@ -134,7 +192,8 @@ def __init__(self, name, alazar_name, demod_length=1, filter='win', parameter_class=SamplesAcqParam) for i in range(demod_length): self.add_parameter(name='demod_freq_{}'.format(i), - parameter_class=ManualParameter) + check_and_update_fn=self._update_demod_freq, + parameter_class=AcqVariablesParam) self.add_parameter(name='int_time', check_and_update_fn=self._update_int_time, default_fn=self._int_time_default, @@ -144,7 +203,51 @@ def __init__(self, name, alazar_name, demod_length=1, filter='win', default_fn=self._int_delay_default, parameter_class=AcqVariablesParam) - def _update_int_time(instr, value): + def _update_demod_freq(instr, value, param_name=None): + """ + Function to validate and update acquisiton parameter when + a demod_freq_ Parameter is changed + + Args: + value to update demodulation frequency to + + Kwargs: + param_name: used to update demod_freq list used for updating + septionts of acquisition parameter + + Checks: + 1e6 <= value <= 500e6 + number of oscilation measured using current int_tiume param value + at this demod frequency value + oversampling rate for this demodulation frequency + + Sets: + sample_rate attr of acq controller to be that of alazar + setpoints of acquisiton parameter + """ + if (value is None) or not (1e6 <= value <= 500e6): + raise ValueError('demod_freqs must be 1e6 <= value <= 500e6') + alazar = instr._get_alazar() + instr.sample_rate = alazar.get_sample_rate() + min_oscilations_measured = instr.int_time() * value + oversampling = instr.sample_rate / (2 * value) + if min_oscilations_measured < 10: + logging.warning('{} oscilations measured for largest ' + 'demod freq, recommend at least 10: ' + 'decrease sampling rate, take ' + 'more samples or increase demodulation ' + 'freq'.format(min_oscilations_measured)) + elif oversampling < 1: + logging.warning('oversampling rate is {}, recommend > 1: ' + 'increase sampling rate or decrease ' + 'demodulation frequency'.format(oversampling)) + demod_freqs = instr.get_demod_freqs() + current_demod_index = ([int(s) for s in param_name.split() + if s.isdigit()][0]) + demod_freqs[current_demod_index] = value + instr.acquisition.update_demod_setpoints(demod_freqs) + + def _update_int_time(instr, value, **kwargs): """ Function to validate value for int_time before setting parameter value @@ -158,9 +261,10 @@ def _update_int_time(instr, value): oversampling rate Sets: - sample_rate attribute of instument to be that of alazar + sample_rate attr of acq controller to be that of alazar samples_per_record of acq controller acquisition_kwarg['samples_per_record'] of acquisition param + setpoints of acquisiton param shape of acquisition param """ if (value is None) or not (0 <= value <= 0.1): @@ -169,13 +273,14 @@ def _update_int_time(instr, value): alazar = instr._get_alazar() instr.sample_rate = alazar.get_sample_rate() if instr.get_max_demod_freq() is not None: - oscilations_measured = value * instr.get_max_demod_freq() + min_oscilations_measured = value * instr.get_max_demod_freq() oversampling = instr.sample_rate / (2 * instr.get_max_demod_freq()) - if oscilations_measured < 10: - logging.warning('{} oscilations measured, recommend at ' - 'least 10: decrease sampling rate, take ' + if min_oscilations_measured < 10: + logging.warning('{} oscilations measured for largest ' + 'demod freq, recommend at least 10: ' + 'decrease sampling rate, take ' 'more samples or increase demodulation ' - 'freq'.format(oscilations_measured)) + 'freq'.format(min_oscilations_measured)) elif oversampling < 1: logging.warning('oversampling rate is {}, recommend > 1: ' 'increase sampling rate or decrease ' @@ -197,16 +302,24 @@ def _update_int_time(instr, value): instr.acquisition.acquisition_kwargs.update( samples_per_record=instr.samples_per_record) - def _update_int_delay(instr, value): + def _update_int_delay(instr, value, **kwargs): """ Function to validate value for int_delay before setting parameter value - Checks: limit between 0 and 1s - acq knows sample_rate (doesn't check with alazar for accuracy) - number of samples discarded >= numtaps - Sets: samples_per_record of acq controller - acquisition_kwarg['samples_per_record'] of acquisition param - shape of acquisition param + + Args: + value to be validated and used for instrument attribute update + + Checks: + 0 <= value <= 0.1 seconds + number of samples discarded >= numtaps + + Sets: + sample_rate attr of acq controller to be that of alazar + samples_per_record of acq controller + acquisition_kwarg['samples_per_record'] of acquisition param + setpoints of acquisiton param + shape of acquisition param """ if (value is None) or not (0 <= value <= 0.1): raise ValueError('int_delay must be 0 <= value <= 1') @@ -259,14 +372,26 @@ def _int_time_default(instr): (instr.int_delay() or 0)) return total_time + def get_demod_freqs(self): + """ + Function to get all the demod_freq parameter values in a list, v hacky + + Returns: + freqs: numpy array of demodulation frequencies + """ + freqs = list(filter(None, [getattr(self, 'demod_freq_{}'.format(c))() + for c in range(self._demod_length)])) + return np.array(freqs) + def get_max_demod_freq(self): """ - Returns the largest demodulation frequency + Returns: + the largest demodulation frequency + nb: really hacky and we should have channels in qcodes but we don't (at time of writing) """ - freqs = list(filter(None, [getattr(self, 'demod_freq_{}'.format(c))() - for c in range(self._demod_length)])) + freqs = self.get_demod_freqs() if len(freqs) > 0: return max(freqs) else: @@ -319,8 +444,11 @@ def pre_start_capture(self): raise Exception('acq controller sample rate does not match ' 'instrument value, most likely need ' 'to call update_acquisition_settings') - if self.get_max_demod_freq() is None: - raise Exception('no demodulation frequencies set') + + demod_list = self.get_demod_freqs() + if len(demod_list) == 0: + raise Exception('no demod_freqs set') + self.records_per_buffer = alazar.records_per_buffer.get() self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() self.board_info = alazar.get_idn() @@ -328,8 +456,6 @@ def pre_start_capture(self): self.records_per_buffer * self.number_of_channels) - demod_list = np.array([getattr(self, 'demod_freq_{}'.format(n))() - for n in range(self._demod_length)]) integer_list = np.arange(self.samples_per_record) angle_mat = 2 * np.pi * \ np.outer(demod_list, integer_list) / self.sample_rate From 3ecce9ad066ccbb995c4530dddfc08cf4dac4b88 Mon Sep 17 00:00:00 2001 From: Natalie Pearson Date: Tue, 7 Feb 2017 15:56:08 +0100 Subject: [PATCH 097/180] remove fit fn from acq helpers and TODOs for trying it in controllers, bigger inheritance needed but will do that later --- .../AlazarTech/acq_helpers.py | 75 ------------------- .../AlazarTech/ave_controller_test.py | 1 - .../AlazarTech/rec_controller_test.py | 1 - 3 files changed, 77 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/acq_helpers.py b/qcodes/instrument_drivers/AlazarTech/acq_helpers.py index 96bc621accbc..785145d3887a 100644 --- a/qcodes/instrument_drivers/AlazarTech/acq_helpers.py +++ b/qcodes/instrument_drivers/AlazarTech/acq_helpers.py @@ -1,6 +1,5 @@ import numpy as np from scipy import signal -import logging def filter_win(rec, cutoff, sample_rate, numtaps, axis=-1): @@ -73,77 +72,3 @@ def roundup(num, to_nearest): """ remainder = num % to_nearest return int(num if remainder == 0 else num + to_nearest - remainder) - - -def fit(acq_controller, record, averaging=False): - """ - Applies volts conversion, demodulation fit, low bandpass filter - and integration limits to samples array - - Args: - rec (numpy array): record from alazar to be multiplied with the - software signal, filtered and limited to - integration limits - shape = (samples_taken, ) - - Returns: - magnitude (numpy array): shape = (demod_length, samples_used) - phase (numpy array): shape = (demod_length, samples_used) - """ - # convert rec to volts - bps = acq_controller.board_info['bits_per_sample'] - if bps == 12: - volt_rec = sample_to_volt_u12(record, bps) - else: - logging.warning('sample to volt conversion does not exist for' - ' bps != 12, centered raw samples returned') - volt_rec = record - np.mean(record) - - # volt_rec to matrix and multiply with demodulation signal matrices - volt_rec_mat = np.outer(np.ones(acq_controller._demod_length), volt_rec) - re_mat = np.multiply(volt_rec_mat, acq_controller.cos_mat) - im_mat = np.multiply(volt_rec_mat, acq_controller.sin_mat) - - # filter out higher freq component - cutoff = acq_controller.get_max_demod_freq() / 10 - if acq_controller.filter_settings['filter'] == 0: - re_filtered = filter_win(re_mat, cutoff, - acq_controller.sample_rate, - acq_controller.filter_settings[ - 'numtaps'], - axis=1) - im_filtered = filter_win(im_mat, cutoff, - acq_controller.sample_rate, - acq_controller.filter_settings[ - 'numtaps'], - axis=1) - elif acq_controller.filter_settings['filter'] == 1: - re_filtered = filter_ls(re_mat, cutoff, - acq_controller.sample_rate, - acq_controller.filter_settings[ - 'numtaps'], - axis=1) - im_filtered = filter_ls(im_mat, cutoff, - acq_controller.sample_rate, - acq_controller.filter_settings[ - 'numtaps'], - axis=1) - - # apply integration limits - beginning = int(acq_controller.int_delay() * acq_controller.sample_rate) - end = beginning + int(acq_controller.int_time() * - acq_controller.sample_rate) - - re_limited = re_filtered[:, beginning:end] - im_limited = im_filtered[:, beginning:end] - - # convert to magnitude and phase - complex_mat = re_limited + im_limited * 1j - magnitude = abs(complex_mat) - phase = np.angle(complex_mat, deg=True) - - if averaging: - magnitude = np.mean(magnitude, axis=1) - phase = np.mean(phase, axis=1) - - return magnitude, phase diff --git a/qcodes/instrument_drivers/AlazarTech/ave_controller_test.py b/qcodes/instrument_drivers/AlazarTech/ave_controller_test.py index 3018775875d3..ee49c9afe102 100644 --- a/qcodes/instrument_drivers/AlazarTech/ave_controller_test.py +++ b/qcodes/instrument_drivers/AlazarTech/ave_controller_test.py @@ -156,7 +156,6 @@ class HD_Averaging_Controller(AcquisitionController): TODO(nataliejpg) what should be private? TODO(nataliejpg) where should filter_dict live? TODO(nataliejpg) demod_freq should be changeable number: maybe channels - TODO(nataliejpg) try using fit from helpers """ filter_dict = {'win': 0, 'ls': 1, 'ave': 2} diff --git a/qcodes/instrument_drivers/AlazarTech/rec_controller_test.py b/qcodes/instrument_drivers/AlazarTech/rec_controller_test.py index 714354c462c8..168658ca93e0 100644 --- a/qcodes/instrument_drivers/AlazarTech/rec_controller_test.py +++ b/qcodes/instrument_drivers/AlazarTech/rec_controller_test.py @@ -175,7 +175,6 @@ class HD_Records_Controller(AcquisitionController): TODO(nataliejpg) what should be private? TODO(nataliejpg) where should filter_dict live? TODO(nataliejpg) demod_freq should be changeable number: maybe channels - TODO(nataliejpg) try using fit from helpers TODO(nataliejpg) make records a parameter or similar (MultiParam?) """ From e8f9644d81e4cdb6a5db7b6e932eae57c46b7fce Mon Sep 17 00:00:00 2001 From: Natalie Pearson Date: Tue, 7 Feb 2017 16:07:31 +0100 Subject: [PATCH 098/180] delete old versions of controllers and rename new versions to replace them --- .../AlazarTech/ave_controller.py | 611 +++++++++++----- .../AlazarTech/ave_controller_test.py | 546 --------------- .../AlazarTech/rec_controller.py | 651 +++++++++++++----- .../AlazarTech/rec_controller_test.py | 581 ---------------- 4 files changed, 915 insertions(+), 1474 deletions(-) delete mode 100644 qcodes/instrument_drivers/AlazarTech/ave_controller_test.py delete mode 100644 qcodes/instrument_drivers/AlazarTech/rec_controller_test.py diff --git a/qcodes/instrument_drivers/AlazarTech/ave_controller.py b/qcodes/instrument_drivers/AlazarTech/ave_controller.py index d23767c7aeb2..ee49c9afe102 100644 --- a/qcodes/instrument_drivers/AlazarTech/ave_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/ave_controller.py @@ -1,130 +1,429 @@ import logging from .ATS import AcquisitionController +from .ATS9360 import AlazarTech_ATS9360 import numpy as np -import qcodes.utils.helpers as helpers +from qcodes import Parameter +import qcodes.instrument_drivers.AlazarTech.acq_helpers as helpers -class HD_Controller(AcquisitionController): +class AcqVariablesParam(Parameter): + """ + Parameter of an AcquisitionController which has a _check_and_update_instr + function used for validation and to update instrument attributes and a + _get_default function which it uses to set the AcqVariablesParam to an + instrument caluclated default. + + Args: + name: name for this parameter + instrument: acquisition controller instrument this parameter belongs to + check_and_update_fn: instrument function to be used for value + validation and updating instrument values + default_fn (optional): instrument function to be used to calculate + a default value to set parameter to + initial_value (optional): initial value for parameter + """ + + def __init__(self, name, instrument, check_and_update_fn, + default_fn=None, initial_value=None): + super().__init__(name) + self._instrument = instrument + self._save_val(initial_value) + setattr(self, '_check_and_update_instr', check_and_update_fn) + if default_fn is not None: + setattr(self, '_get_default', default_fn) + + def set(self, value): + """ + Function which checks value using validation function and then sets + the Parameter value to this value. + + Args: + value: value to set the parameter to + """ + self._check_and_update_instr(value, param_name=self.name) + self._save_val(value) + + def get(self): + return self._latest()['value'] + + def to_default(self): + """ + Function which executes the default_fn specified to calculate the + default value based on instrument values and then calls the set + function with this value + """ + try: + default = self._get_default() + except AttributeError as e: + raise AttributeError('no default function for {} Parameter ' + '{}'.format(self.name, e)) + self.set(default) + + def check(self): + """ + Function which checks the current Parameter value using the specified + check_and_update_fn which can also serve to update instrument values. + + Return: + True (if no errors raised when check_and_update_fn executed) + """ + val = self._latest()['value'] + self._check_and_update_instr(val, param_name=self.name) + return True + + +class AveragedAcqParam(Parameter): + """ + Software controlled parameter class for Alazar acquisition. To be used with + HD_Averaging_Controller (tested with ATS9360 board) for return of + averaged magnitude and phase data from the Alazar. + + Args: + name: name for this parameter + instrument: acquisition controller instrument this parameter belongs to + demod_length: numer of demodulation frequencies the acq controller has + NB this is currently set in acq controller init but that's really + not nice and should be changed when possible + + TODO(nataliejpg) setpoints (including names and units) + TODO(nataliejpg) setpoint units + """ + + def __init__(self, name, instrument, demod_length): + super().__init__(name) + self._instrument = instrument + self.acquisition_kwargs = {} + self.names = ('magnitude', 'phase') + if demod_length > 1: + self.shapes = ((demod_length, ), (demod_length, )) + else: + self.shapes = ((), ()) + + def update_demod_setpoints(self, demod_freqs): + """ + Function to update the demodulation frequency setpoints to be called + when a demod_freq Parameter of the acq controller is updated + + Args: + demod_freqs: numpy array of demodulation frequencies to use as + setpoints if length > 1 + """ + demod_length = self._instrument._demod_length + self._demod_list = demod_freqs + if demod_length > 1: + self.setpoints = ((self._demod_list, ), (self._demod_list, )) + else: + pass + + def get(self): + """ + Gets the magnitude and phase signal by calling acquire + on the alazar (which in turn calls the processing functions of the + aqcuisition controller before returning the processed data + demodulated at specified frequencies and averaged over samples, + records and buffers) + + Returns: + mag: numpy array of magnitude, shape (demod_length, ) + phase: numpy array of magnitude, shape (demod_length, ) + """ + mag, phase = self._instrument._get_alazar().acquire( + acquisition_controller=self._instrument, + **self.acquisition_kwargs) + return mag, phase + + +class HD_Averaging_Controller(AcquisitionController): """ This is the Acquisition Controller class which works with the ATS9360, - averaging over buffers and records, demodulating with a software - reference signal, averaging over the samples. - args: - name: name for this acquisition_conroller as an instrument - alazar_name: the name of the alazar instrument such that this controller - can communicate with the Alazar - demod_freq: the frequency of the software wave to be created - samp_rate: the rate of sampling - filt: the filter to be used to filter out double freq component - chan_b: whether there is also a second channel of data to be processed - and returned - **kwargs: kwargs are forwarded to the Instrument base class - - TODO(nataliejpg) fix sample rate problem + averaging over samples (limited by int_time and int_delay values), + records and buffers and demodulating with software reference signal(s). + + Args: + name: name for this acquisition_conroller as an instrument + alazar_name: name of the alazar instrument such that this + controller can communicate with the Alazar + demod_length (default 1): number of demodulation frequencies + filter (default 'win'): filter to be used to filter out double freq + component ('win' - window, 'ls' - least squared, 'ave' - averaging) + numtaps (default 101): number of freq components used in filter + chan_b (default False): whether there is also a second channel of data + to be processed and returned + **kwargs: kwargs are forwarded to the Instrument base class + TODO(nataliejpg) test filter options TODO(nataliejpg) finish implementation of channel b option - TODO(nataliejpg) make demodulation freq a param + TODO(nataliejpg) what should be private? + TODO(nataliejpg) where should filter_dict live? + TODO(nataliejpg) demod_freq should be changeable number: maybe channels """ - def __init__(self, name, alazar_name, demod_freq, samp_rate=5e8, - filt='win', numtaps=101, chan_b=False, **kwargs): - filter_dict = {'win': 0, 'ls': 1, 'dot': 2} - self.demodulation_frequency = demod_freq - self.sample_rate = samp_rate - self.filter = filter_dict[filt] - self.numtaps = numtaps - self.acquisitionkwargs = {} + filter_dict = {'win': 0, 'ls': 1, 'ave': 2} + samples_divisor = AlazarTech_ATS9360.samples_divisor + + def __init__(self, name, alazar_name, demod_length=1, filter='win', + numtaps=101, chan_b=False, **kwargs): + self.filter_settings = {'filter': self.filter_dict[filter], + 'numtaps': numtaps} self.chan_b = chan_b - self.samples_per_record = None - self.records_per_buffer = None - self.buffers_per_acquisition = None + self._demod_length = demod_length self.number_of_channels = 2 - self.samples_delay = None - self.samples_time = None - self.cos_list = None - self.sin_list = None - self.buffer = None - self.board_info = None - # make a call to the parent class and by extension, - # create the parameter structure of this class + self.samples_per_record = None + self.sample_rate = None super().__init__(name, alazar_name, **kwargs) self.add_parameter(name='acquisition', - names=('magnitude', 'phase'), - units=('', ''), - get_cmd=self.do_acquisition) + demod_length=demod_length, + parameter_class=AveragedAcqParam) + for i in range(demod_length): + self.add_parameter(name='demod_freq_{}'.format(i), + check_and_update_fn=self._update_demod_freq, + parameter_class=AcqVariablesParam) + self.add_parameter(name='int_time', + check_and_update_fn=self._update_int_time, + default_fn=self._int_time_default, + parameter_class=AcqVariablesParam) + self.add_parameter(name='int_delay', + check_and_update_fn=self._update_int_delay, + default_fn=self._int_delay_default, + parameter_class=AcqVariablesParam) + + def _update_demod_freq(instr, value, param_name=None): + """ + Function to validate and update acquisiton parameter when + a demod_freq_ Parameter is changed + + Args: + value to update demodulation frequency to + + Kwargs: + param_name: used to update demod_freq list used for updating + septionts of acquisition parameter - def update_acquisitionkwargs(self, **kwargs): + Checks: + 1e6 <= value <= 500e6 + number of oscilation measured using current int_tiume param value + at this demod frequency value + oversampling rate for this demodulation frequency + + Sets: + sample_rate attr of acq controller to be that of alazar + setpoints of acquisiton parameter """ - Updates the kwargs to be used when - alazar_driver.acquire is called. - - It is also used to set the limits on the selection of - samples used (bounded by delay and integration time) - - :param kwargs: - :return: - """ - samples_per_record = kwargs['samples_per_record'] - sample_rate = self.sample_rate - - if 'int_delay' in kwargs: - int_delay = kwargs.pop('int_delay') - samp_delay = int_delay * sample_rate - samples_delay_min = (self.numtaps - 1) - if samp_delay < samples_delay_min: - int_delay_min = samples_delay_min / sample_rate - logging.warning( - 'delay is less than recommended for filter choice: ' - '(expect delay >= {}'.format(int_delay_min)) - else: - samp_delay = self.numtaps - 1 - - if 'int_time' in kwargs: - int_time = kwargs.pop('int_time') - samp_time = int_time * sample_rate - samples_time_max = (samples_per_record - samp_delay) - oscilations_measured = int_time * self.demodulation_frequency - oversampling = sample_rate / (2 * self.demodulation_frequency) - if samp_time > samples_time_max: - int_time_max = samples_time_max / sample_rate - raise ValueError('int_time {} is longer than total_time - ' - 'delay: {}'.format(int_time, int_time_max)) - elif oscilations_measured < 10: - logging.warning('{} oscilations measured, recommend at ' - 'least 10: decrease sampling rate, take ' + if (value is None) or not (1e6 <= value <= 500e6): + raise ValueError('demod_freqs must be 1e6 <= value <= 500e6') + alazar = instr._get_alazar() + instr.sample_rate = alazar.get_sample_rate() + min_oscilations_measured = instr.int_time() * value + oversampling = instr.sample_rate / (2 * value) + if min_oscilations_measured < 10: + logging.warning('{} oscilations measured for largest ' + 'demod freq, recommend at least 10: ' + 'decrease sampling rate, take ' + 'more samples or increase demodulation ' + 'freq'.format(min_oscilations_measured)) + elif oversampling < 1: + logging.warning('oversampling rate is {}, recommend > 1: ' + 'increase sampling rate or decrease ' + 'demodulation frequency'.format(oversampling)) + demod_freqs = instr.get_demod_freqs() + current_demod_index = ([int(s) for s in param_name.split() + if s.isdigit()][0]) + demod_freqs[current_demod_index] = value + instr.acquisition.update_demod_setpoints(demod_freqs) + + def _update_int_time(instr, value, **kwargs): + """ + Function to validate value for int_time before setting parameter + value + + Args: + value to be validated and used for instrument attribute update + + Checks: + 0 <= value <= 0.1 seconds + number of oscilation measured in this time + oversampling rate + + Sets: + sample_rate attr of acq controller to be that of alazar + samples_per_record of acq controller + acquisition_kwarg['samples_per_record'] of acquisition param + """ + if (value is None) or not (0 <= value <= 0.1): + raise ValueError('int_time must be 0 <= value <= 1') + + alazar = instr._get_alazar() + instr.sample_rate = alazar.get_sample_rate() + if instr.get_max_demod_freq() is not None: + min_oscilations_measured = value * instr.get_max_demod_freq() + oversampling = instr.sample_rate / (2 * instr.get_max_demod_freq()) + if min_oscilations_measured < 10: + logging.warning('{} oscilations measured for largest ' + 'demod freq, recommend at least 10: ' + 'decrease sampling rate, take ' 'more samples or increase demodulation ' - 'freq'.format(oscilations_measured)) + 'freq'.format(min_oscilations_measured)) elif oversampling < 1: logging.warning('oversampling rate is {}, recommend > 1: ' 'increase sampling rate or decrease ' 'demodulation frequency'.format(oversampling)) + if instr.int_delay() is None: + instr.int_delay.to_default() + + # update acquision kwargs and acq controller value + total_time = value + instr.int_delay() + samples_needed = total_time * instr.sample_rate + instr.samples_per_record = helpers.roundup( + samples_needed, instr.samples_divisor) + instr.acquisition.acquisition_kwargs.update( + samples_per_record=instr.samples_per_record) + + def _update_int_delay(instr, value, **kwargs): + """ + Function to validate value for int_delay before setting parameter + value + + Args: + value to be validated and used for instrument attribute update + + Checks: + 0 <= value <= 0.1 seconds + number of samples discarded >= numtaps + + Sets: + sample_rate attr of acq controller to be that of alazar + samples_per_record of acq controller + acquisition_kwarg['samples_per_record'] of acquisition param + setpoints of acquisiton param + """ + if (value is None) or not (0 <= value <= 0.1): + raise ValueError('int_delay must be 0 <= value <= 1') + alazar = instr._get_alazar() + instr.sample_rate = alazar.get_sample_rate() + samples_delay_min = (instr.filter_settings['numtaps'] - 1) + int_delay_min = samples_delay_min / instr.sample_rate + if value < int_delay_min: + logging.warning( + 'delay is less than recommended for filter choice: ' + '(expect delay >= {})'.format(int_delay_min)) + + # update acquision kwargs and acq controller value + total_time = value + (instr.int_time() or 0) + samples_needed = total_time * instr.sample_rate + instr.samples_per_record = helpers.roundup( + samples_needed, instr.samples_divisor) + instr.acquisition.acquisition_kwargs.update( + samples_per_record=instr.samples_per_record) + + def _int_delay_default(instr): + """ + Function to generate default int_delay value + + Returns: + minimum int_delay recommended for (numtaps - 1) + samples to be discarded as recommended for filter + """ + alazar = instr._get_alazar() + instr.sample_rate = alazar.get_sample_rate() + samp_delay = instr.filter_settings['numtaps'] - 1 + return samp_delay / instr.sample_rate + + def _int_time_default(instr): + """ + Function to generate defult int_time value + + Returns: + max total time for integration based on samples_per_record, + sample_rate and int_delay + """ + if instr.samples_per_record is (0 or None): + raise ValueError('Cannot set int_time to max if acq controller' + ' has 0 or None samples_per_record, choose a ' + 'value for int_time and samples_per_record will ' + 'be set accordingly') + alazar = instr._get_alazar() + instr.sample_rate = alazar.get_sample_rate() + total_time = ((instr.samples_per_record / instr.sample_rate) - + (instr.int_delay() or 0)) + return total_time + + def get_demod_freqs(self): + """ + Function to get all the demod_freq parameter values in a list, v hacky + + Returns: + freqs: numpy array of demodulation frequencies + """ + freqs = list(filter(None, [getattr(self, 'demod_freq_{}'.format(c))() + for c in range(self._demod_length)])) + return np.array(freqs) + + def get_max_demod_freq(self): + """ + Returns: + the largest demodulation frequency + + nb: really hacky and we should have channels in qcodes but we don't + (at time of writing) + """ + freqs = self.get_demod_freqs() + if len(freqs) > 0: + return max(freqs) else: - samp_time = samples_per_record - samp_delay + return None - self.samples_time = int(samp_time) - self.samples_delay = int(samp_delay) + def update_filter_settings(self, filter, numtaps): + """ + Updates the settings of the filter for filtering out + double frwuency component for demodulation. - self.acquisitionkwargs.update(**kwargs) + Args: + filter (str): filter type ('win' or 'ls') + numtaps (int): numtaps for filter + """ + self.filter_settings.update({'filter': self.filter_dict[filter], + 'numtaps': numtaps}) - def do_acquisition(self): + def update_acquisition_kwargs(self, **kwargs): """ - this method performs an acquisition, which is the get_cmd for the - acquisiion parameter of this instrument - :return: + Updates the kwargs to be used when + alazar_driver.acquisition() is called via a get call of the + acquisition SamplesParam. Should be used by the user for + updating averaging settings since the 'samples_per_record' + kwarg is updated via the int_time and int_delay parameters + + Kwargs (ints): + records_per_buffer + buffers_per_acquisition + allocated_buffers """ - values = self._get_alazar().acquire(acquisition_controller=self, - **self.acquisitionkwargs) - return values + if 'samples_per_record' in kwargs: + raise ValueError('With HD_Samples_Controller ' + 'samples_per_record cannot be set manually ' + 'via update_acquisition_kwargs and should instead' + ' be set by setting int_time and int_delay') + self.acquisition.acquisition_kwargs.update(**kwargs) def pre_start_capture(self): """ Called before capture start to update Acquisition Controller with alazar acquisition params and set up software wave for demodulation. - :return: """ alazar = self._get_alazar() - self.samples_per_record = alazar.samples_per_record.get() + if self.samples_per_record != alazar.samples_per_record.get(): + raise Exception('acq controller samples per record does not match' + ' instrument value, most likely need ' + 'to set and check int_time and int_delay') + if self.sample_rate != alazar.get_sample_rate(): + raise Exception('acq controller sample rate does not match ' + 'instrument value, most likely need ' + 'to set and check int_time and int_delay') + + demod_list = self.get_demod_freqs() + if len(demod_list) == 0: + raise Exception('no demod_freqs set') + self.records_per_buffer = alazar.records_per_buffer.get() self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() self.board_info = alazar.get_idn() @@ -132,24 +431,18 @@ def pre_start_capture(self): self.records_per_buffer * self.number_of_channels) - integer_list = np.arange(self.samples_per_record, dtype=np.uint16) - angle_list = (2 * np.pi * self.demodulation_frequency / - self.sample_rate * integer_list) - - self.cos_list = np.cos(angle_list) - self.sin_list = np.sin(angle_list) + integer_list = np.arange(self.samples_per_record) + angle_mat = 2 * np.pi * \ + np.outer(demod_list, integer_list) / self.sample_rate + self.cos_mat = np.cos(angle_mat) + self.sin_mat = np.sin(angle_mat) def pre_acquire(self): - """ - See AcquisitionController - :return: - """ pass def handle_buffer(self, data): """ Adds data from alazar to buffer (effectively averaging) - :return: """ self.buffer += data @@ -158,7 +451,10 @@ def post_acquire(self): Processes the data according to ATS9360 settings, splitting into records and averaging over them, then applying demodulation fit nb: currently only channel A - :return: samples_magnitude_array, samples_phase_array + + Returns: + magnitude (numpy array): shape = (demod_length, samples_used) + phase (numpy array): shape = (demod_length, samples_used) """ records_per_acquisition = (self.buffers_per_acquisition * self.records_per_buffer) @@ -175,91 +471,76 @@ def post_acquire(self): recordA = np.uint16(recA / records_per_acquisition) # do demodulation - magA, phaseA = self.fit(recordA) + magA, phaseA = self._fit(recordA) # same for chan b if self.chan_b: raise NotImplementedError('chan b code not complete') - # recordB = np.zeros(self.samples_per_record, dtype=np.uint16) - # for i in range(self.records_per_buffer): - # i0 = (i * self.samples_per_record * - # self.number_of_channels + 1) - # i1 = (i0 + self.samples_per_record * self.number_of_channels) - # recordB += np.uint16(self.buffer[i0:i1:self.number_of_channels] / - # records_per_acquisition) - # magB, phaseB = self.fit(recordB) return magA, phaseA - def fit(self, rec): + def _fit(self, rec): """ Applies volts conversion, demodulation fit, low bandpass filter - and integration limits to samples array and averages - :return: magnitude, phase - """ + and integration limits to samples array + + Args: + rec (numpy array): record from alazar to be multiplied + with the software signal, filtered and limited + to integration limits shape = (samples_taken, ) + Returns: + magnitude (numpy array): shape = (demod_length, ) + phase (numpy array): shape = (demod_length, ) + """ # convert rec to volts bps = self.board_info['bits_per_sample'] if bps == 12: - volt_rec = sample_to_volt_u12(rec, bps) + volt_rec = helpers.sample_to_volt_u12(rec, bps) else: logging.warning('sample to volt conversion does not exist for' ' bps != 12, centered raw samples returned') volt_rec = rec - np.mean(rec) - # multiply with software wave - re_wave = np.multiply(volt_rec, self.cos_list) - im_wave = np.multiply(volt_rec, self.sin_list) - cutoff = self.demodulation_frequency / 10 + # volt_rec to matrix and multiply with demodulation signal matrices + volt_rec_mat = np.outer(np.ones(self._demod_length), volt_rec) + re_mat = np.multiply(volt_rec_mat, self.cos_mat) + im_mat = np.multiply(volt_rec_mat, self.sin_mat) # filter out higher freq component - if self.filter == 0: - re_filtered = helpers.filter_win(re_wave, cutoff, - self.sample_rate, self.numtaps) - im_filtered = helpers.filter_win(im_wave, cutoff, - self.sample_rate, self.numtaps) - elif self.filter == 1: - re_filtered = helpers.filter_ls(re_wave, cutoff, - self.sample_rate, self.numtaps) - im_filtered = helpers.filter_ls(im_wave, cutoff, - self.sample_rate, self.numtaps) - elif self.filter == 2: - re_filtered = re_wave - im_filtered = im_wave + cutoff = self.get_max_demod_freq() / 10 + if self.filter_settings['filter'] == 0: + re_filtered = helpers.filter_win(re_mat, cutoff, + self.sample_rate, + self.filter_settings['numtaps'], + axis=1) + im_filtered = helpers.filter_win(im_mat, cutoff, + self.sample_rate, + self.filter_settings['numtaps'], + axis=1) + elif self.filter_settings['filter'] == 1: + re_filtered = helpers.filter_ls(re_mat, cutoff, + self.sample_rate, + self.filter_settings['numtaps'], + axis=1) + im_filtered = helpers.filter_ls(im_mat, cutoff, + self.sample_rate, + self.filter_settings['numtaps'], + axis=1) + elif self.filter_settings['filter'] == 2: + re_filtered = re_mat + im_filtered = im_mat # apply integration limits - start = self.samples_delay - end = start + self.samples_time + beginning = int(self.int_delay() * self.sample_rate) + end = beginning + int(self.int_time() * self.sample_rate) - re_limited = re_filtered[start:end] - im_limited = im_filtered[start:end] + re_limited = re_filtered[:, beginning:end] + im_limited = im_filtered[:, beginning:end] # convert to magnitude and phase - complex_num = re_limited + im_limited * 1j - mag = np.mean(abs(complex_num)) - phase = np.mean(np.angle(complex_num, deg=True)) - - return mag, phase - - -def sample_to_volt_u12(raw_samples, bps): - """ - Applies volts conversion for 12 bit sample data stored - in 2 bytes - :return: samples_magnitude_array, samples_phase_array - """ - - # right_shift 16-bit sample by 4 to get 12 bit sample - shifted_samples = np.right_shift(raw_samples, 4) - - # Alazar calibration - code_zero = (1 << (bps - 1)) - 0.5 - code_range = (1 << (bps - 1)) - 0.5 - - # TODO(nataliejpg) make this not hard coded - input_range_volts = 1 - # Convert to volts - volt_samples = np.float64(input_range_volts * - (shifted_samples - code_zero) / code_range) + complex_mat = re_limited + im_limited * 1j + magnitude = np.mean(abs(complex_mat), axis=1) + phase = np.mean(np.angle(complex_mat, deg=True), axis=1) - return volt_samples + return magnitude, phase diff --git a/qcodes/instrument_drivers/AlazarTech/ave_controller_test.py b/qcodes/instrument_drivers/AlazarTech/ave_controller_test.py deleted file mode 100644 index ee49c9afe102..000000000000 --- a/qcodes/instrument_drivers/AlazarTech/ave_controller_test.py +++ /dev/null @@ -1,546 +0,0 @@ -import logging -from .ATS import AcquisitionController -from .ATS9360 import AlazarTech_ATS9360 -import numpy as np -from qcodes import Parameter -import qcodes.instrument_drivers.AlazarTech.acq_helpers as helpers - - -class AcqVariablesParam(Parameter): - """ - Parameter of an AcquisitionController which has a _check_and_update_instr - function used for validation and to update instrument attributes and a - _get_default function which it uses to set the AcqVariablesParam to an - instrument caluclated default. - - Args: - name: name for this parameter - instrument: acquisition controller instrument this parameter belongs to - check_and_update_fn: instrument function to be used for value - validation and updating instrument values - default_fn (optional): instrument function to be used to calculate - a default value to set parameter to - initial_value (optional): initial value for parameter - """ - - def __init__(self, name, instrument, check_and_update_fn, - default_fn=None, initial_value=None): - super().__init__(name) - self._instrument = instrument - self._save_val(initial_value) - setattr(self, '_check_and_update_instr', check_and_update_fn) - if default_fn is not None: - setattr(self, '_get_default', default_fn) - - def set(self, value): - """ - Function which checks value using validation function and then sets - the Parameter value to this value. - - Args: - value: value to set the parameter to - """ - self._check_and_update_instr(value, param_name=self.name) - self._save_val(value) - - def get(self): - return self._latest()['value'] - - def to_default(self): - """ - Function which executes the default_fn specified to calculate the - default value based on instrument values and then calls the set - function with this value - """ - try: - default = self._get_default() - except AttributeError as e: - raise AttributeError('no default function for {} Parameter ' - '{}'.format(self.name, e)) - self.set(default) - - def check(self): - """ - Function which checks the current Parameter value using the specified - check_and_update_fn which can also serve to update instrument values. - - Return: - True (if no errors raised when check_and_update_fn executed) - """ - val = self._latest()['value'] - self._check_and_update_instr(val, param_name=self.name) - return True - - -class AveragedAcqParam(Parameter): - """ - Software controlled parameter class for Alazar acquisition. To be used with - HD_Averaging_Controller (tested with ATS9360 board) for return of - averaged magnitude and phase data from the Alazar. - - Args: - name: name for this parameter - instrument: acquisition controller instrument this parameter belongs to - demod_length: numer of demodulation frequencies the acq controller has - NB this is currently set in acq controller init but that's really - not nice and should be changed when possible - - TODO(nataliejpg) setpoints (including names and units) - TODO(nataliejpg) setpoint units - """ - - def __init__(self, name, instrument, demod_length): - super().__init__(name) - self._instrument = instrument - self.acquisition_kwargs = {} - self.names = ('magnitude', 'phase') - if demod_length > 1: - self.shapes = ((demod_length, ), (demod_length, )) - else: - self.shapes = ((), ()) - - def update_demod_setpoints(self, demod_freqs): - """ - Function to update the demodulation frequency setpoints to be called - when a demod_freq Parameter of the acq controller is updated - - Args: - demod_freqs: numpy array of demodulation frequencies to use as - setpoints if length > 1 - """ - demod_length = self._instrument._demod_length - self._demod_list = demod_freqs - if demod_length > 1: - self.setpoints = ((self._demod_list, ), (self._demod_list, )) - else: - pass - - def get(self): - """ - Gets the magnitude and phase signal by calling acquire - on the alazar (which in turn calls the processing functions of the - aqcuisition controller before returning the processed data - demodulated at specified frequencies and averaged over samples, - records and buffers) - - Returns: - mag: numpy array of magnitude, shape (demod_length, ) - phase: numpy array of magnitude, shape (demod_length, ) - """ - mag, phase = self._instrument._get_alazar().acquire( - acquisition_controller=self._instrument, - **self.acquisition_kwargs) - return mag, phase - - -class HD_Averaging_Controller(AcquisitionController): - """ - This is the Acquisition Controller class which works with the ATS9360, - averaging over samples (limited by int_time and int_delay values), - records and buffers and demodulating with software reference signal(s). - - Args: - name: name for this acquisition_conroller as an instrument - alazar_name: name of the alazar instrument such that this - controller can communicate with the Alazar - demod_length (default 1): number of demodulation frequencies - filter (default 'win'): filter to be used to filter out double freq - component ('win' - window, 'ls' - least squared, 'ave' - averaging) - numtaps (default 101): number of freq components used in filter - chan_b (default False): whether there is also a second channel of data - to be processed and returned - **kwargs: kwargs are forwarded to the Instrument base class - - TODO(nataliejpg) test filter options - TODO(nataliejpg) finish implementation of channel b option - TODO(nataliejpg) what should be private? - TODO(nataliejpg) where should filter_dict live? - TODO(nataliejpg) demod_freq should be changeable number: maybe channels - """ - - filter_dict = {'win': 0, 'ls': 1, 'ave': 2} - samples_divisor = AlazarTech_ATS9360.samples_divisor - - def __init__(self, name, alazar_name, demod_length=1, filter='win', - numtaps=101, chan_b=False, **kwargs): - self.filter_settings = {'filter': self.filter_dict[filter], - 'numtaps': numtaps} - self.chan_b = chan_b - self._demod_length = demod_length - self.number_of_channels = 2 - self.samples_per_record = None - self.sample_rate = None - super().__init__(name, alazar_name, **kwargs) - - self.add_parameter(name='acquisition', - demod_length=demod_length, - parameter_class=AveragedAcqParam) - for i in range(demod_length): - self.add_parameter(name='demod_freq_{}'.format(i), - check_and_update_fn=self._update_demod_freq, - parameter_class=AcqVariablesParam) - self.add_parameter(name='int_time', - check_and_update_fn=self._update_int_time, - default_fn=self._int_time_default, - parameter_class=AcqVariablesParam) - self.add_parameter(name='int_delay', - check_and_update_fn=self._update_int_delay, - default_fn=self._int_delay_default, - parameter_class=AcqVariablesParam) - - def _update_demod_freq(instr, value, param_name=None): - """ - Function to validate and update acquisiton parameter when - a demod_freq_ Parameter is changed - - Args: - value to update demodulation frequency to - - Kwargs: - param_name: used to update demod_freq list used for updating - septionts of acquisition parameter - - Checks: - 1e6 <= value <= 500e6 - number of oscilation measured using current int_tiume param value - at this demod frequency value - oversampling rate for this demodulation frequency - - Sets: - sample_rate attr of acq controller to be that of alazar - setpoints of acquisiton parameter - """ - if (value is None) or not (1e6 <= value <= 500e6): - raise ValueError('demod_freqs must be 1e6 <= value <= 500e6') - alazar = instr._get_alazar() - instr.sample_rate = alazar.get_sample_rate() - min_oscilations_measured = instr.int_time() * value - oversampling = instr.sample_rate / (2 * value) - if min_oscilations_measured < 10: - logging.warning('{} oscilations measured for largest ' - 'demod freq, recommend at least 10: ' - 'decrease sampling rate, take ' - 'more samples or increase demodulation ' - 'freq'.format(min_oscilations_measured)) - elif oversampling < 1: - logging.warning('oversampling rate is {}, recommend > 1: ' - 'increase sampling rate or decrease ' - 'demodulation frequency'.format(oversampling)) - demod_freqs = instr.get_demod_freqs() - current_demod_index = ([int(s) for s in param_name.split() - if s.isdigit()][0]) - demod_freqs[current_demod_index] = value - instr.acquisition.update_demod_setpoints(demod_freqs) - - def _update_int_time(instr, value, **kwargs): - """ - Function to validate value for int_time before setting parameter - value - - Args: - value to be validated and used for instrument attribute update - - Checks: - 0 <= value <= 0.1 seconds - number of oscilation measured in this time - oversampling rate - - Sets: - sample_rate attr of acq controller to be that of alazar - samples_per_record of acq controller - acquisition_kwarg['samples_per_record'] of acquisition param - """ - if (value is None) or not (0 <= value <= 0.1): - raise ValueError('int_time must be 0 <= value <= 1') - - alazar = instr._get_alazar() - instr.sample_rate = alazar.get_sample_rate() - if instr.get_max_demod_freq() is not None: - min_oscilations_measured = value * instr.get_max_demod_freq() - oversampling = instr.sample_rate / (2 * instr.get_max_demod_freq()) - if min_oscilations_measured < 10: - logging.warning('{} oscilations measured for largest ' - 'demod freq, recommend at least 10: ' - 'decrease sampling rate, take ' - 'more samples or increase demodulation ' - 'freq'.format(min_oscilations_measured)) - elif oversampling < 1: - logging.warning('oversampling rate is {}, recommend > 1: ' - 'increase sampling rate or decrease ' - 'demodulation frequency'.format(oversampling)) - if instr.int_delay() is None: - instr.int_delay.to_default() - - # update acquision kwargs and acq controller value - total_time = value + instr.int_delay() - samples_needed = total_time * instr.sample_rate - instr.samples_per_record = helpers.roundup( - samples_needed, instr.samples_divisor) - instr.acquisition.acquisition_kwargs.update( - samples_per_record=instr.samples_per_record) - - def _update_int_delay(instr, value, **kwargs): - """ - Function to validate value for int_delay before setting parameter - value - - Args: - value to be validated and used for instrument attribute update - - Checks: - 0 <= value <= 0.1 seconds - number of samples discarded >= numtaps - - Sets: - sample_rate attr of acq controller to be that of alazar - samples_per_record of acq controller - acquisition_kwarg['samples_per_record'] of acquisition param - setpoints of acquisiton param - """ - if (value is None) or not (0 <= value <= 0.1): - raise ValueError('int_delay must be 0 <= value <= 1') - alazar = instr._get_alazar() - instr.sample_rate = alazar.get_sample_rate() - samples_delay_min = (instr.filter_settings['numtaps'] - 1) - int_delay_min = samples_delay_min / instr.sample_rate - if value < int_delay_min: - logging.warning( - 'delay is less than recommended for filter choice: ' - '(expect delay >= {})'.format(int_delay_min)) - - # update acquision kwargs and acq controller value - total_time = value + (instr.int_time() or 0) - samples_needed = total_time * instr.sample_rate - instr.samples_per_record = helpers.roundup( - samples_needed, instr.samples_divisor) - instr.acquisition.acquisition_kwargs.update( - samples_per_record=instr.samples_per_record) - - def _int_delay_default(instr): - """ - Function to generate default int_delay value - - Returns: - minimum int_delay recommended for (numtaps - 1) - samples to be discarded as recommended for filter - """ - alazar = instr._get_alazar() - instr.sample_rate = alazar.get_sample_rate() - samp_delay = instr.filter_settings['numtaps'] - 1 - return samp_delay / instr.sample_rate - - def _int_time_default(instr): - """ - Function to generate defult int_time value - - Returns: - max total time for integration based on samples_per_record, - sample_rate and int_delay - """ - if instr.samples_per_record is (0 or None): - raise ValueError('Cannot set int_time to max if acq controller' - ' has 0 or None samples_per_record, choose a ' - 'value for int_time and samples_per_record will ' - 'be set accordingly') - alazar = instr._get_alazar() - instr.sample_rate = alazar.get_sample_rate() - total_time = ((instr.samples_per_record / instr.sample_rate) - - (instr.int_delay() or 0)) - return total_time - - def get_demod_freqs(self): - """ - Function to get all the demod_freq parameter values in a list, v hacky - - Returns: - freqs: numpy array of demodulation frequencies - """ - freqs = list(filter(None, [getattr(self, 'demod_freq_{}'.format(c))() - for c in range(self._demod_length)])) - return np.array(freqs) - - def get_max_demod_freq(self): - """ - Returns: - the largest demodulation frequency - - nb: really hacky and we should have channels in qcodes but we don't - (at time of writing) - """ - freqs = self.get_demod_freqs() - if len(freqs) > 0: - return max(freqs) - else: - return None - - def update_filter_settings(self, filter, numtaps): - """ - Updates the settings of the filter for filtering out - double frwuency component for demodulation. - - Args: - filter (str): filter type ('win' or 'ls') - numtaps (int): numtaps for filter - """ - self.filter_settings.update({'filter': self.filter_dict[filter], - 'numtaps': numtaps}) - - def update_acquisition_kwargs(self, **kwargs): - """ - Updates the kwargs to be used when - alazar_driver.acquisition() is called via a get call of the - acquisition SamplesParam. Should be used by the user for - updating averaging settings since the 'samples_per_record' - kwarg is updated via the int_time and int_delay parameters - - Kwargs (ints): - records_per_buffer - buffers_per_acquisition - allocated_buffers - """ - if 'samples_per_record' in kwargs: - raise ValueError('With HD_Samples_Controller ' - 'samples_per_record cannot be set manually ' - 'via update_acquisition_kwargs and should instead' - ' be set by setting int_time and int_delay') - self.acquisition.acquisition_kwargs.update(**kwargs) - - def pre_start_capture(self): - """ - Called before capture start to update Acquisition Controller with - alazar acquisition params and set up software wave for demodulation. - """ - alazar = self._get_alazar() - if self.samples_per_record != alazar.samples_per_record.get(): - raise Exception('acq controller samples per record does not match' - ' instrument value, most likely need ' - 'to set and check int_time and int_delay') - if self.sample_rate != alazar.get_sample_rate(): - raise Exception('acq controller sample rate does not match ' - 'instrument value, most likely need ' - 'to set and check int_time and int_delay') - - demod_list = self.get_demod_freqs() - if len(demod_list) == 0: - raise Exception('no demod_freqs set') - - self.records_per_buffer = alazar.records_per_buffer.get() - self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() - self.board_info = alazar.get_idn() - self.buffer = np.zeros(self.samples_per_record * - self.records_per_buffer * - self.number_of_channels) - - integer_list = np.arange(self.samples_per_record) - angle_mat = 2 * np.pi * \ - np.outer(demod_list, integer_list) / self.sample_rate - self.cos_mat = np.cos(angle_mat) - self.sin_mat = np.sin(angle_mat) - - def pre_acquire(self): - pass - - def handle_buffer(self, data): - """ - Adds data from alazar to buffer (effectively averaging) - """ - self.buffer += data - - def post_acquire(self): - """ - Processes the data according to ATS9360 settings, splitting into - records and averaging over them, then applying demodulation fit - nb: currently only channel A - - Returns: - magnitude (numpy array): shape = (demod_length, samples_used) - phase (numpy array): shape = (demod_length, samples_used) - """ - records_per_acquisition = (self.buffers_per_acquisition * - self.records_per_buffer) - # for ATS9360 samples are arranged in the buffer as follows: - # S00A, S00B, S01A, S01B...S10A, S10B, S11A, S11B... - # where SXYZ is record X, sample Y, channel Z. - - # break buffer up into records and averages over them - recA = np.zeros(self.samples_per_record) - for i in range(self.records_per_buffer): - i0 = (i * self.samples_per_record * self.number_of_channels) - i1 = (i0 + self.samples_per_record * self.number_of_channels) - recA += self.buffer[i0:i1:self.number_of_channels] - recordA = np.uint16(recA / records_per_acquisition) - - # do demodulation - magA, phaseA = self._fit(recordA) - - # same for chan b - if self.chan_b: - raise NotImplementedError('chan b code not complete') - - return magA, phaseA - - def _fit(self, rec): - """ - Applies volts conversion, demodulation fit, low bandpass filter - and integration limits to samples array - - Args: - rec (numpy array): record from alazar to be multiplied - with the software signal, filtered and limited - to integration limits shape = (samples_taken, ) - - Returns: - magnitude (numpy array): shape = (demod_length, ) - phase (numpy array): shape = (demod_length, ) - """ - # convert rec to volts - bps = self.board_info['bits_per_sample'] - if bps == 12: - volt_rec = helpers.sample_to_volt_u12(rec, bps) - else: - logging.warning('sample to volt conversion does not exist for' - ' bps != 12, centered raw samples returned') - volt_rec = rec - np.mean(rec) - - # volt_rec to matrix and multiply with demodulation signal matrices - volt_rec_mat = np.outer(np.ones(self._demod_length), volt_rec) - re_mat = np.multiply(volt_rec_mat, self.cos_mat) - im_mat = np.multiply(volt_rec_mat, self.sin_mat) - - # filter out higher freq component - cutoff = self.get_max_demod_freq() / 10 - if self.filter_settings['filter'] == 0: - re_filtered = helpers.filter_win(re_mat, cutoff, - self.sample_rate, - self.filter_settings['numtaps'], - axis=1) - im_filtered = helpers.filter_win(im_mat, cutoff, - self.sample_rate, - self.filter_settings['numtaps'], - axis=1) - elif self.filter_settings['filter'] == 1: - re_filtered = helpers.filter_ls(re_mat, cutoff, - self.sample_rate, - self.filter_settings['numtaps'], - axis=1) - im_filtered = helpers.filter_ls(im_mat, cutoff, - self.sample_rate, - self.filter_settings['numtaps'], - axis=1) - elif self.filter_settings['filter'] == 2: - re_filtered = re_mat - im_filtered = im_mat - - # apply integration limits - beginning = int(self.int_delay() * self.sample_rate) - end = beginning + int(self.int_time() * self.sample_rate) - - re_limited = re_filtered[:, beginning:end] - im_limited = im_filtered[:, beginning:end] - - # convert to magnitude and phase - complex_mat = re_limited + im_limited * 1j - magnitude = np.mean(abs(complex_mat), axis=1) - phase = np.mean(np.angle(complex_mat, deg=True), axis=1) - - return magnitude, phase diff --git a/qcodes/instrument_drivers/AlazarTech/rec_controller.py b/qcodes/instrument_drivers/AlazarTech/rec_controller.py index 5513e384264b..168658ca93e0 100644 --- a/qcodes/instrument_drivers/AlazarTech/rec_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/rec_controller.py @@ -1,135 +1,284 @@ import logging from .ATS import AcquisitionController +from .ATS9360 import AlazarTech_ATS9360 import numpy as np from qcodes import Parameter -from qcodes.utils.helpers import filter_win, filter_ls +import qcodes.instrument_drivers.AlazarTech.acq_helpers as helpers -class RecordsParam(Parameter): +class AcqVariablesParam(Parameter): """ - Hardware controlled parameter class for Alazar acquisition. To be used with - HD_Records_Controller (tested with ATS9360 board) for return of an array of - record data from the Alazar, averaged over samples and buffers. - - TODO(nataliejpg) fix setpoints/shapes horriblenesss + Parameter of an AcquisitionController which has a _check_and_update_instr + function used for validation and to update instrument attributes and a + _get_default function which it uses to set the AcqVariablesParam to an + instrument caluclated default. + + Args: + name: name for this parameter + instrument: acquisition controller instrument this parameter belongs to + check_and_update_fn: instrument function to be used for value + validation and updating instrument values + default_fn (optional): instrument function to be used to calculate + a default value to set parameter to + initial_value (optional): initial value for parameter """ - def __init__(self, name, instrument): + def __init__(self, name, instrument, check_and_update_fn, + default_fn=None, initial_value=None): + super().__init__(name) + self._instrument = instrument + self._save_val(initial_value) + setattr(self, '_check_and_update_instr', check_and_update_fn) + if default_fn is not None: + setattr(self, '_get_default', default_fn) + + def set(self, value): + """ + Function which checks value using validation function and then sets + the Parameter value to this value. + + Args: + value: value to set the parameter to + """ + self._check_and_update_instr(value, param_name=self.name) + self._save_val(value) + + def get(self): + return self._latest()['value'] + + def to_default(self): + """ + Function which executes the default_fn specified to calculate the + default value based on instrument values and then calls the set + function with this value + """ + try: + default = self._get_default() + except AttributeError as e: + raise AttributeError('no default function for {} Parameter ' + '{}'.format(self.name, e)) + self.set(default) + + def check(self): + """ + Function which checks the current Parameter value using the specified + check_and_update_fn which can also serve to update instrument values. + + Return: + True (if no errors raised when check_and_update_fn executed) + """ + val = self._latest()['value'] + self._check_and_update_instr(val, param_name=self.name) + return True + + +class RecordsAcqParam(Parameter): + """ + Software controlled parameter class for Alazar acquisition. To be used with + HD_Records_Controller (tested with ATS9360 board) for return of + averaged magnitude and phase data from the Alazar. + + Args: + name: name for this parameter + instrument: acquisition controller instrument this parameter belongs to + demod_length: numer of demodulation frequencies the acq controller has + NB this is currently set in acq controller init but that's really + not nice and should be changed when possible + + TODO(nataliejpg) setpoints (including names and units) + TODO(nataliejpg) setpoint units + TODO(nataliejpg) convert records setpoint into actual frequency + """ + def __init__(self, name, instrument, demod_length): super().__init__(name) self._instrument = instrument - self.acquisitionkwargs = {} + self.acquisition_kwargs = {} self.names = ('magnitude', 'phase') - self.units = ('', '') - self.setpoint_names = (('record_num',), ('record_num',)) - self.setpoints = ((1,), (1,)) - self.shapes = ((1,), (1,)) - def update_acquisition_kwargs(self, **kwargs): - # needed to update config of the software parameter on sweep change - # freq setpoints tuple as needs to be hashable for look up - if 'records_per_buffer' in kwargs: - npts = kwargs['records_per_buffer'] - n = tuple(np.arange(npts)) - self.setpoints = ((n,), (n,)) + def update_sweep(self, npts, start=None, stop=None): + """ + Function which updates the shape of the parameter (and it's setpoints + when this is fixed) + + Args: + npts: number of recornds returned after processing + start (optional): start value of records returned (if relevant) + stop (optional): stop value of records returned (if relevant) + """ + demod_length = self._instrument._demod_length + # self.rec_list = tuple(np.linspace(start, stop, num=npts)) + # demod_index = tuple(range(demod_length)) + if demod_length > 1: + # demod_index = tuple(range(demod_length)) + # demod_freqs = self._instrument.get_demod_freqs() + # self.setpoints = ((demod_freqs, self._rec_list), ( + # demod_freqs, self._rec_list)) + self.shapes = ((demod_length, npts), (demod_length, npts)) + else: self.shapes = ((npts,), (npts,)) + # self.setpoints = ((self._rec_list,), (self._rec_list,)) + + def update_demod_setpoints(self, demod_freqs): + """ + Function to update the demodulation frequency setpoints to be called + when a demod_freq Parameter of the acq controller is updated + + Args: + demod_freqs: numpy array of demodulation frequencies to use as + setpoints if length > 1 + """ + demod_length = self._instrument._demod_length + if demod_length > 1: + self.setpoints = ((demod_freqs, self._rec_list), + (demod_freqs, self._rec_list)) else: - raise ValueError('records_per_buffer must be specified') - # updates dict to be used in acquisition get call - self.acquisitionkwargs.update(**kwargs) + pass def get(self): + """ + Gets the magnitude and phase signal by calling acquire + on the alazar (which in turn calls the processing functions of the + aqcuisition controller before returning the processed data + demodulated at specified frequencies and averaged over samples + and buffers) + + Returns: + mag: numpy array of magnitude, shape (demod_length, records) + phase: numpy array of magnitude, shape (demod_length, records) + """ mag, phase = self._instrument._get_alazar().acquire( acquisition_controller=self._instrument, - **self.acquisitionkwargs) + **self.acquisition_kwargs) return mag, phase class HD_Records_Controller(AcquisitionController): """ This is the Acquisition Controller class which works with the ATS9360, - averaging over buffers and records and demodulating with a software - reference signal, returning the samples. - args: - name: name for this acquisition_conroller as an instrument - alazar_name: the name of the alazar instrument such that this controller - can communicate with the Alazar - demod_freq: the frequency of the software wave to be created - samp_rate: the rate of sampling - filt: the filter to be used to filter out double freq component - numtaps: number of freq components used in the filter - chan_b: whether there is also a second channel of data to be processed - and returned - **kwargs: kwargs are forwarded to the Instrument base class - - TODO(nataliejpg) fix sample rate problem + averaging over samples (limited by int_time and int_delay values) and + buffers and demodulating with software reference signal(s). + + Args: + name: name for this acquisition_conroller as an instrument + alazar_name: name of the alazar instrument such that this + controller can communicate with the Alazar + demod_length (default 1): number of demodulation frequencies + filter (default 'win'): filter to be used to filter out double freq + component ('win' - window, 'ls' - least squared, 'ave' - averaging) + numtaps (default 101): number of freq components used in filter + chan_b (default False): whether there is also a second channel of data + to be processed and returned + **kwargs: kwargs are forwarded to the Instrument base class + TODO(nataliejpg) test filter options TODO(nataliejpg) finish implementation of channel b option - TODO(nataliejpg) make demodulation freq a param + TODO(nataliejpg) what should be private? + TODO(nataliejpg) where should filter_dict live? + TODO(nataliejpg) demod_freq should be changeable number: maybe channels + TODO(nataliejpg) make records a parameter or similar (MultiParam?) """ - def __init__(self, name, alazar_name, demod_freq, samp_rate=5e8, - filt='win', numtaps=101, chan_b=False, **kwargs): - filter_dict = {'win': 0, 'ls': 1, 'dot': 2} - self.demodulation_frequency = demod_freq - self.sample_rate = samp_rate - self.filter = filter_dict[filt] - self.numtaps = numtaps + filter_dict = {'win': 0, 'ls': 1, 'ave': 2} + samples_divisor = AlazarTech_ATS9360.samples_divisor + + def __init__(self, name, alazar_name, demod_length=1, filter='win', + numtaps=101, chan_b=False, **kwargs): + self.filter_settings = {'filter': self.filter_dict[filter], + 'numtaps': numtaps} self.chan_b = chan_b + self._demod_length = demod_length + self.number_of_channels = 2 self.samples_per_record = None self.records_per_buffer = None - self.buffers_per_acquisition = None - self.number_of_channels = 2 - self.samples_delay = None - self.samples_time = None - self.cos_mat = None - self.sin_mat = None - self.buffer = None - self.board_info = None - # make a call to the parent class and by extension, - # create the parameter structure of this class + self.sample_rate = None super().__init__(name, alazar_name, **kwargs) self.add_parameter(name='acquisition', - parameter_class=RecordsParam) + demod_length=self._demod_length, + parameter_class=RecordsAcqParam) + for i in range(demod_length): + self.add_parameter(name='demod_freq_{}'.format(i), + check_and_update_fn=self._update_demod_freq, + parameter_class=AcqVariablesParam) + self.add_parameter(name='int_time', + check_and_update_fn=self._update_int_time, + default_fn=self._int_time_default, + parameter_class=AcqVariablesParam) + self.add_parameter(name='int_delay', + check_and_update_fn=self._update_int_delay, + default_fn=self._int_delay_default, + parameter_class=AcqVariablesParam) + + def _update_demod_freq(instr, value, param_name=None): + """ + Function to validate and update acquisiton parameter when + a demod_freq_ Parameter is changed - def update_acquisitionkwargs(self, **kwargs): + Args: + value to update demodulation frequency to + + Kwargs: + param_name: used to update demod_freq list used for updating + septionts of acquisition parameter + + Checks: + 1e6 <= value <= 500e6 + number of oscilation measured using current int_tiume param value + at this demod frequency value + oversampling rate for this demodulation frequency + + Sets: + sample_rate attr of acq controller to be that of alazar + setpoints of acquisiton parameter """ - Updates the kwargs to be used when - alazar_driver.acquire is called via a get call of the - acquisition RecordsParam. - - It is also used to set the limits on the selection of - samples used (bounded by delay and integration time) - - :param kwargs: - :return: - """ - samples_per_record = kwargs['samples_per_record'] - sample_rate = self.sample_rate - - if 'int_delay' in kwargs: - int_delay = kwargs.pop('int_delay') - samp_delay = int_delay * sample_rate - samples_delay_min = (self.numtaps - 1) - if samp_delay < samples_delay_min: - int_delay_min = samples_delay_min / sample_rate - logging.warning( - 'delay is less than recommended for filter choice: ' - '(expect delay >= {}'.format(int_delay_min)) - else: - samp_delay = self.numtaps - 1 - - if 'int_time' in kwargs: - int_time = kwargs.pop('int_time') - samp_time = int_time * sample_rate - samples_time_max = (samples_per_record - samp_delay) - oscilations_measured = int_time * self.demodulation_frequency - oversampling = sample_rate / (2 * self.demodulation_frequency) - if samp_time > samples_time_max: - int_time_max = samples_time_max / sample_rate - raise ValueError('int_time {} is longer than total_time - ' - 'delay: {}'.format(int_time, int_time_max)) - elif oscilations_measured < 10: + if (value is None) or not (1e6 <= value <= 500e6): + raise ValueError('demod_freqs must be 1e6 <= value <= 500e6') + alazar = instr._get_alazar() + instr.sample_rate = alazar.get_sample_rate() + min_oscilations_measured = instr.int_time() * value + oversampling = instr.sample_rate / (2 * value) + if min_oscilations_measured < 10: + logging.warning('{} oscilations measured for largest ' + 'demod freq, recommend at least 10: ' + 'decrease sampling rate, take ' + 'more samples or increase demodulation ' + 'freq'.format(min_oscilations_measured)) + elif oversampling < 1: + logging.warning('oversampling rate is {}, recommend > 1: ' + 'increase sampling rate or decrease ' + 'demodulation frequency'.format(oversampling)) + demod_freqs = instr.get_demod_freqs() + current_demod_index = ([int(s) for s in param_name.split() + if s.isdigit()][0]) + demod_freqs[current_demod_index] = value + instr.acquisition.update_demod_setpoints(demod_freqs) + + def _update_int_time(instr, value, **kwargs): + """ + Function to validate value for int_time before setting parameter + value + + Args: + value to be validated and used for instrument attribute update + + Checks: + 0 <= value <= 0.1 seconds + number of oscilation measured in this time + oversampling rate + + Sets: + sample_rate attr of acq controller to be that of alazar + samples_per_record of acq controller + acquisition_kwarg['samples_per_record'] of acquisition param + """ + if (value is None) or not (0 <= value <= 0.1): + raise ValueError('int_time must be 0 <= value <= 1') + alazar = instr._get_alazar() + instr.sample_rate = alazar.get_sample_rate() + if instr.get_max_demod_freq() is not None: + oscilations_measured = value * instr.get_max_demod_freq() + oversampling = instr.sample_rate / (2 * instr.get_max_demod_freq()) + if oscilations_measured < 10: logging.warning('{} oscilations measured, recommend at ' 'least 10: decrease sampling rate, take ' 'more samples or increase demodulation ' @@ -138,80 +287,223 @@ def update_acquisitionkwargs(self, **kwargs): logging.warning('oversampling rate is {}, recommend > 1: ' 'increase sampling rate or decrease ' 'demodulation frequency'.format(oversampling)) + if instr.int_delay() is None: + instr.int_delay.to_default() + + # update acquision kwargs and acq controller value + total_time = value + instr.int_delay() + samples_needed = total_time * instr.sample_rate + instr.samples_per_record = helpers.roundup( + samples_needed, instr.samples_divisor) + instr.acquisition.acquisition_kwargs.update( + samples_per_record=instr.samples_per_record) + + def _update_int_delay(instr, value, **kwargs): + """ + Function to validate value for int_delay before setting parameter + value + + Args: + value to be validated and used for instrument attribute update + + Checks: + 0 <= value <= 0.1 seconds + number of samples discarded >= numtaps + + Sets: + sample_rate attr of acq controller to be that of alazar + samples_per_record of acq controller + acquisition_kwarg['samples_per_record'] of acquisition param + setpoints of acquisiton param + """ + if (value is None) or not (0 <= value <= 0.1): + raise ValueError('int_delay must be 0 <= value <= 1') + alazar = instr._get_alazar() + instr.sample_rate = alazar.get_sample_rate() + samples_delay_min = (instr.filter_settings['numtaps'] - 1) + int_delay_min = samples_delay_min / instr.sample_rate + if value < int_delay_min: + logging.warning( + 'delay is less than recommended for filter choice: ' + '(expect delay >= {})'.format(int_delay_min)) + + # update acquision kwargs and acq controller value + total_time = value + (instr.int_time() or 0) + samples_needed = total_time * instr.sample_rate + instr.samples_per_record = helpers.roundup( + samples_needed, instr.samples_divisor) + instr.acquisition.acquisition_kwargs.update( + samples_per_record=instr.samples_per_record) + + def _int_delay_default(instr): + """ + Function to generate default int_delay value + + Returns: + minimum int_delay recommended for (numtaps - 1) + samples to be discarded as recommended for filter + """ + alazar = instr._get_alazar() + instr.sample_rate = alazar.get_sample_rate() + samp_delay = instr.filter_settings['numtaps'] - 1 + return samp_delay / instr.sample_rate + + def _int_time_default(instr): + """ + Function to generate defult int_time value + + Returns: + max total time for integration based on samples_per_record, + sample_rate and int_delay + """ + if instr.samples_per_record is (0 or None): + raise ValueError('Cannot set int_time to max if acq controller' + ' has 0 or None samples_per_record, choose a ' + 'value for int_time and samples_per_record will ' + 'be set accordingly') + alazar = instr._get_alazar() + instr.sample_rate = alazar.get_sample_rate() + total_time = ((instr.samples_per_record / instr.sample_rate) - + (instr.int_delay() or 0)) + return total_time + + def get_demod_freqs(self): + """ + Function to get all the demod_freq parameter values in a list, v hacky + + Returns: + freqs: numpy array of demodulation frequencies + """ + freqs = list(filter(None, [getattr(self, 'demod_freq_{}'.format(c))() + for c in range(self._demod_length)])) + return np.array(freqs) + + def get_max_demod_freq(self): + """ + Returns: + the largest demodulation frequency + + nb: really hacky and we should have channels in qcodes but we don't + (at time of writing) + """ + freqs = self.get_demod_freqs() + if len(freqs) > 0: + return max(freqs) else: - samp_time = samples_per_record - samp_delay + return None - self.samples_time = int(samp_time) - self.samples_delay = int(samp_delay) + def update_filter_settings(self, filter, numtaps): + """ + Updates the settings of the filter for filtering out + double frwuency component for demodulation. - self.acquisition.update_acquisition_kwargs(**kwargs) + Args: + filter (str): filter type ('win' or 'ls') + numtaps (int): numtaps for filter + """ + self.filter_settings.update({'filter': self.filter_dict[filter], + 'numtaps': numtaps}) + + def update_acquisition_kwargs(self, **kwargs): + """ + Updates the kwargs to be used when + alazar_driver.acquisition() is called via a get call of the + acquisition SamplesParam. Should be used by the user for + updating averaging settings since the 'samples_per_record' + kwarg is updated via the int_time and int_delay parameters + + Kwargs (ints): + records_per_buffer + buffers_per_acquisition + allocated_buffers + """ + if 'samples_per_record' in kwargs: + raise ValueError('With HD_Samples_Controller ' + 'samples_per_record cannot be set manually ' + 'via update_acquisition_kwargs and should instead' + ' be set by setting int_time and int_delay') + if 'records_per_buffer' in kwargs: + self.acquisition.update_sweep(kwargs['records_per_buffer']) + self.records_per_buffer = kwargs['records_per_buffer'] + self.acquisition.acquisition_kwargs.update(**kwargs) def pre_start_capture(self): """ Called before capture start to update Acquisition Controller with alazar acquisition params and set up software wave for demodulation. - - sine and cosine matrices have shape (samples * records). - - :return: """ alazar = self._get_alazar() - self.samples_per_record = alazar.samples_per_record.get() - self.records_per_buffer = alazar.records_per_buffer.get() + if self.samples_per_record != alazar.samples_per_record.get(): + raise Exception('acq controller samples per record does not match' + ' instrument value, most likely need ' + 'to set and check int_time and int_delay') + if self.sample_rate != alazar.get_sample_rate(): + raise Exception('acq controller sample rate does not match ' + 'instrument value, most likely need ' + 'to set and check int_time and int_delay') + if self.records_per_buffer != alazar.records_per_buffer.get(): + raise Exception('acq controller records per buffer does not match ' + 'instrument value, most likely need ' + 'to call update_acquisition_kwargs with' + 'records_per_buffer as a param') + + demod_list = self.get_demod_freqs() + if len(demod_list) == 0: + raise Exception('no demod_freqs set') + self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() self.board_info = alazar.get_idn() self.buffer = np.zeros(self.samples_per_record * self.records_per_buffer * self.number_of_channels) - integer_list = np.arange(self.samples_per_record, dtype=np.uint16) - angle_list = (2 * np.pi * self.demodulation_frequency / - self.sample_rate * integer_list) - - cos_list = np.cos(angle_list).reshape(self.samples_per_record, 1) - sin_list = np.sin(angle_list).reshape(self.samples_per_record, 1) - - self.cos_mat = np.kron(np.ones((1, self.records_per_buffer)), cos_list) - self.sin_mat = np.kron(np.ones((1, self.records_per_buffer)), sin_list) + mat_shape = (self._demod_length, self.records_per_buffer, + self.samples_per_record) + demod_list = np.array([getattr(self, 'demod_freq_{}'.format(n))() + for n in range(self._demod_length)]) + integer_list = np.arange(self.samples_per_record) + integer_mat = np.outer(np.ones(self.records_per_buffer), integer_list) + angle_mat = 2 * np.pi * \ + np.outer(demod_list, integer_mat).reshape( + mat_shape) / self.sample_rate + self.cos_mat = np.cos(angle_mat) + self.sin_mat = np.sin(angle_mat) def pre_acquire(self): - """ - See AcquisitionController - :return: - """ pass def handle_buffer(self, data): """ Adds data from alazar to buffer (effectively averaging) - :return: """ self.buffer += data def post_acquire(self): """ Processes the data according to ATS9360 settings, splitting into - records and averaging over them, then applying demodulation fit + records and then applying demodulation fit nb: currently only channel A - :return: samples_magnitude_array, samples_phase_array - """ + Returns: + magnitude (numpy array): shape = (demod_length, records_per_buffer) + phase (numpy array): shape = (demod_length, records_per_buffer + """ # for ATS9360 samples are arranged in the buffer as follows: # S00A, S00B, S01A, S01B...S10A, S10B, S11A, S11B... # where SXYZ is record X, sample Y, channel Z. - # break buffer up into records and shapes to be (samples * records) - recordA = np.zeros((self.samples_per_record, self.records_per_buffer), - dtype=np.uint16) + # break buffer up into records and shapes to be (records, samples) + recordsA = np.empty((self.records_per_buffer, self.samples_per_record), + dtype=np.uint16) for i in range(self.records_per_buffer): i0 = (i * self.samples_per_record * self.number_of_channels) i1 = (i0 + self.samples_per_record * self.number_of_channels) - recordA[:, i] = np.uint16( + recordsA[i, :] = np.uint16( self.buffer[i0:i1:self.number_of_channels] / self.buffers_per_acquisition) # do demodulation - magA, phaseA = self.fit(recordA) + magA, phaseA = self._fit(recordsA) # same for chan b if self.chan_b: @@ -219,76 +511,71 @@ def post_acquire(self): return magA, phaseA - def fit(self, rec): + def _fit(self, rec): """ Applies volts conversion, demodulation fit, low bandpass filter - and integration limits to samples * records array - :return: records_magnitude_array, records_phase_array - """ + and integration limits to samples array + Args: + rec (numpy array): record from alazar to be multiplied + with the software signal, filtered and limited + to integration limits shape = (samples_taken, ) + + Returns: + magnitude (numpy array): shape = (demod_length, records_per_buffer) + phase (numpy array): shape = (demod_length, records_per_buffer) + """ # convert rec to volts bps = self.board_info['bits_per_sample'] if bps == 12: - volt_rec = sample_to_volt_u12(rec, bps) + volt_rec = helpers.sample_to_volt_u12(rec, bps) else: logging.warning('sample to volt conversion does not exist for' ' bps != 12, centered raw samples returned') - volt_rec = rec - np.mean(rec, 0) + volt_rec = rec - np.mean(rec, axis=1) - # multiply with software wave - re_wave = np.multiply(volt_rec, self.cos_mat) - im_wave = np.multiply(volt_rec, self.sin_mat) - cutoff = self.demodulation_frequency / 10 - ax = 0 + # volt_rec to matrix and multiply with demodulation signal matrices + mat_shape = (self._demod_length, self.records_per_buffer, + self.samples_per_record) + volt_rec_mat = np.outer( + np.ones(self._demod_length), volt_rec).reshape(mat_shape) + re_mat = np.multiply(volt_rec_mat, self.cos_mat) + im_mat = np.multiply(volt_rec_mat, self.sin_mat) # filter out higher freq component - if self.filter == 0: - re_filtered = filter_win(re_wave, cutoff, self.sample_rate, - self.numtaps, axis=ax) - im_filtered = filter_win(im_wave, cutoff, self.sample_rate, - self.numtaps, axis=ax) - elif self.filter == 1: - re_filtered = filter_ls(re_wave, cutoff, self.sample_rate, - self.numtaps, axis=ax) - im_filtered = filter_ls(im_wave, cutoff, self.sample_rate, - self.numtaps, axis=ax) - elif self.filter == 2: - re_filtered = re_wave - im_filtered = im_wave + cutoff = self.get_max_demod_freq() / 10 + if self.filter_settings['filter'] == 0: + re_filtered = helpers.filter_win(re_mat, cutoff, + self.sample_rate, + self.filter_settings['numtaps'], + axis=2) + im_filtered = helpers.filter_win(im_mat, cutoff, + self.sample_rate, + self.filter_settings['numtaps'], + axis=2) + elif self.filter_settings['filter'] == 1: + re_filtered = helpers.filter_ls(re_mat, cutoff, + self.sample_rate, + self.filter_settings['numtaps'], + axis=2) + im_filtered = helpers.filter_ls(im_mat, cutoff, + self.sample_rate, + self.filter_settings['numtaps'], + axis=2) + elif self.filter_settings['filter'] == 2: + re_filtered = re_mat + im_filtered = im_mat # apply integration limits - start = self.samples_delay - end = start + self.samples_time + beginning = int(self.int_delay() * self.sample_rate) + end = beginning + int(self.int_time() * self.sample_rate) - re_limited = re_filtered[start:end, :] - im_limited = im_filtered[start:end, :] + re_limited = re_filtered[:, :, beginning:end] + im_limited = im_filtered[:, :, beginning:end] # convert to magnitude and phase - complex_num = re_limited + im_limited * 1j - mag = np.mean(abs(complex_num), 0) - phase = np.mean(np.angle(complex_num, deg=True), 0) - - return mag, phase - - -def sample_to_volt_u12(raw_samples, bps): - """ - Applies volts conversion for 12 bit sample data stored - in 2 bytes - :return: samples_magnitude_array, samples_phase_array - """ - - # right_shift 16-bit sample by 4 to get 12 bit sample - shifted_samples = np.right_shift(raw_samples, 4) - - # Alazar calibration - code_zero = (1 << (bps - 1)) - 0.5 - code_range = (1 << (bps - 1)) - 0.5 - - # TODO(nataliejpg) make this not hard coded - input_range_volts = 1 - # Convert to volts - volt_samples = np.float64(input_range_volts * - (shifted_samples - code_zero) / code_range) + complex_mat = re_limited + im_limited * 1j + magnitude = np.mean(abs(complex_mat), axis=2) + phase = np.mean(np.angle(complex_mat, deg=True), axis=2) - return volt_samples + return magnitude, phase diff --git a/qcodes/instrument_drivers/AlazarTech/rec_controller_test.py b/qcodes/instrument_drivers/AlazarTech/rec_controller_test.py deleted file mode 100644 index 168658ca93e0..000000000000 --- a/qcodes/instrument_drivers/AlazarTech/rec_controller_test.py +++ /dev/null @@ -1,581 +0,0 @@ -import logging -from .ATS import AcquisitionController -from .ATS9360 import AlazarTech_ATS9360 -import numpy as np -from qcodes import Parameter -import qcodes.instrument_drivers.AlazarTech.acq_helpers as helpers - - -class AcqVariablesParam(Parameter): - """ - Parameter of an AcquisitionController which has a _check_and_update_instr - function used for validation and to update instrument attributes and a - _get_default function which it uses to set the AcqVariablesParam to an - instrument caluclated default. - - Args: - name: name for this parameter - instrument: acquisition controller instrument this parameter belongs to - check_and_update_fn: instrument function to be used for value - validation and updating instrument values - default_fn (optional): instrument function to be used to calculate - a default value to set parameter to - initial_value (optional): initial value for parameter - """ - - def __init__(self, name, instrument, check_and_update_fn, - default_fn=None, initial_value=None): - super().__init__(name) - self._instrument = instrument - self._save_val(initial_value) - setattr(self, '_check_and_update_instr', check_and_update_fn) - if default_fn is not None: - setattr(self, '_get_default', default_fn) - - def set(self, value): - """ - Function which checks value using validation function and then sets - the Parameter value to this value. - - Args: - value: value to set the parameter to - """ - self._check_and_update_instr(value, param_name=self.name) - self._save_val(value) - - def get(self): - return self._latest()['value'] - - def to_default(self): - """ - Function which executes the default_fn specified to calculate the - default value based on instrument values and then calls the set - function with this value - """ - try: - default = self._get_default() - except AttributeError as e: - raise AttributeError('no default function for {} Parameter ' - '{}'.format(self.name, e)) - self.set(default) - - def check(self): - """ - Function which checks the current Parameter value using the specified - check_and_update_fn which can also serve to update instrument values. - - Return: - True (if no errors raised when check_and_update_fn executed) - """ - val = self._latest()['value'] - self._check_and_update_instr(val, param_name=self.name) - return True - - -class RecordsAcqParam(Parameter): - """ - Software controlled parameter class for Alazar acquisition. To be used with - HD_Records_Controller (tested with ATS9360 board) for return of - averaged magnitude and phase data from the Alazar. - - Args: - name: name for this parameter - instrument: acquisition controller instrument this parameter belongs to - demod_length: numer of demodulation frequencies the acq controller has - NB this is currently set in acq controller init but that's really - not nice and should be changed when possible - - TODO(nataliejpg) setpoints (including names and units) - TODO(nataliejpg) setpoint units - TODO(nataliejpg) convert records setpoint into actual frequency - """ - def __init__(self, name, instrument, demod_length): - super().__init__(name) - self._instrument = instrument - self.acquisition_kwargs = {} - self.names = ('magnitude', 'phase') - - def update_sweep(self, npts, start=None, stop=None): - """ - Function which updates the shape of the parameter (and it's setpoints - when this is fixed) - - Args: - npts: number of recornds returned after processing - start (optional): start value of records returned (if relevant) - stop (optional): stop value of records returned (if relevant) - """ - demod_length = self._instrument._demod_length - # self.rec_list = tuple(np.linspace(start, stop, num=npts)) - # demod_index = tuple(range(demod_length)) - if demod_length > 1: - # demod_index = tuple(range(demod_length)) - # demod_freqs = self._instrument.get_demod_freqs() - # self.setpoints = ((demod_freqs, self._rec_list), ( - # demod_freqs, self._rec_list)) - self.shapes = ((demod_length, npts), (demod_length, npts)) - else: - self.shapes = ((npts,), (npts,)) - # self.setpoints = ((self._rec_list,), (self._rec_list,)) - - def update_demod_setpoints(self, demod_freqs): - """ - Function to update the demodulation frequency setpoints to be called - when a demod_freq Parameter of the acq controller is updated - - Args: - demod_freqs: numpy array of demodulation frequencies to use as - setpoints if length > 1 - """ - demod_length = self._instrument._demod_length - if demod_length > 1: - self.setpoints = ((demod_freqs, self._rec_list), - (demod_freqs, self._rec_list)) - else: - pass - - def get(self): - """ - Gets the magnitude and phase signal by calling acquire - on the alazar (which in turn calls the processing functions of the - aqcuisition controller before returning the processed data - demodulated at specified frequencies and averaged over samples - and buffers) - - Returns: - mag: numpy array of magnitude, shape (demod_length, records) - phase: numpy array of magnitude, shape (demod_length, records) - """ - mag, phase = self._instrument._get_alazar().acquire( - acquisition_controller=self._instrument, - **self.acquisition_kwargs) - return mag, phase - - -class HD_Records_Controller(AcquisitionController): - """ - This is the Acquisition Controller class which works with the ATS9360, - averaging over samples (limited by int_time and int_delay values) and - buffers and demodulating with software reference signal(s). - - Args: - name: name for this acquisition_conroller as an instrument - alazar_name: name of the alazar instrument such that this - controller can communicate with the Alazar - demod_length (default 1): number of demodulation frequencies - filter (default 'win'): filter to be used to filter out double freq - component ('win' - window, 'ls' - least squared, 'ave' - averaging) - numtaps (default 101): number of freq components used in filter - chan_b (default False): whether there is also a second channel of data - to be processed and returned - **kwargs: kwargs are forwarded to the Instrument base class - - TODO(nataliejpg) test filter options - TODO(nataliejpg) finish implementation of channel b option - TODO(nataliejpg) what should be private? - TODO(nataliejpg) where should filter_dict live? - TODO(nataliejpg) demod_freq should be changeable number: maybe channels - TODO(nataliejpg) make records a parameter or similar (MultiParam?) - """ - - filter_dict = {'win': 0, 'ls': 1, 'ave': 2} - samples_divisor = AlazarTech_ATS9360.samples_divisor - - def __init__(self, name, alazar_name, demod_length=1, filter='win', - numtaps=101, chan_b=False, **kwargs): - self.filter_settings = {'filter': self.filter_dict[filter], - 'numtaps': numtaps} - self.chan_b = chan_b - self._demod_length = demod_length - self.number_of_channels = 2 - self.samples_per_record = None - self.records_per_buffer = None - self.sample_rate = None - super().__init__(name, alazar_name, **kwargs) - - self.add_parameter(name='acquisition', - demod_length=self._demod_length, - parameter_class=RecordsAcqParam) - for i in range(demod_length): - self.add_parameter(name='demod_freq_{}'.format(i), - check_and_update_fn=self._update_demod_freq, - parameter_class=AcqVariablesParam) - self.add_parameter(name='int_time', - check_and_update_fn=self._update_int_time, - default_fn=self._int_time_default, - parameter_class=AcqVariablesParam) - self.add_parameter(name='int_delay', - check_and_update_fn=self._update_int_delay, - default_fn=self._int_delay_default, - parameter_class=AcqVariablesParam) - - def _update_demod_freq(instr, value, param_name=None): - """ - Function to validate and update acquisiton parameter when - a demod_freq_ Parameter is changed - - Args: - value to update demodulation frequency to - - Kwargs: - param_name: used to update demod_freq list used for updating - septionts of acquisition parameter - - Checks: - 1e6 <= value <= 500e6 - number of oscilation measured using current int_tiume param value - at this demod frequency value - oversampling rate for this demodulation frequency - - Sets: - sample_rate attr of acq controller to be that of alazar - setpoints of acquisiton parameter - """ - if (value is None) or not (1e6 <= value <= 500e6): - raise ValueError('demod_freqs must be 1e6 <= value <= 500e6') - alazar = instr._get_alazar() - instr.sample_rate = alazar.get_sample_rate() - min_oscilations_measured = instr.int_time() * value - oversampling = instr.sample_rate / (2 * value) - if min_oscilations_measured < 10: - logging.warning('{} oscilations measured for largest ' - 'demod freq, recommend at least 10: ' - 'decrease sampling rate, take ' - 'more samples or increase demodulation ' - 'freq'.format(min_oscilations_measured)) - elif oversampling < 1: - logging.warning('oversampling rate is {}, recommend > 1: ' - 'increase sampling rate or decrease ' - 'demodulation frequency'.format(oversampling)) - demod_freqs = instr.get_demod_freqs() - current_demod_index = ([int(s) for s in param_name.split() - if s.isdigit()][0]) - demod_freqs[current_demod_index] = value - instr.acquisition.update_demod_setpoints(demod_freqs) - - def _update_int_time(instr, value, **kwargs): - """ - Function to validate value for int_time before setting parameter - value - - Args: - value to be validated and used for instrument attribute update - - Checks: - 0 <= value <= 0.1 seconds - number of oscilation measured in this time - oversampling rate - - Sets: - sample_rate attr of acq controller to be that of alazar - samples_per_record of acq controller - acquisition_kwarg['samples_per_record'] of acquisition param - """ - if (value is None) or not (0 <= value <= 0.1): - raise ValueError('int_time must be 0 <= value <= 1') - alazar = instr._get_alazar() - instr.sample_rate = alazar.get_sample_rate() - if instr.get_max_demod_freq() is not None: - oscilations_measured = value * instr.get_max_demod_freq() - oversampling = instr.sample_rate / (2 * instr.get_max_demod_freq()) - if oscilations_measured < 10: - logging.warning('{} oscilations measured, recommend at ' - 'least 10: decrease sampling rate, take ' - 'more samples or increase demodulation ' - 'freq'.format(oscilations_measured)) - elif oversampling < 1: - logging.warning('oversampling rate is {}, recommend > 1: ' - 'increase sampling rate or decrease ' - 'demodulation frequency'.format(oversampling)) - if instr.int_delay() is None: - instr.int_delay.to_default() - - # update acquision kwargs and acq controller value - total_time = value + instr.int_delay() - samples_needed = total_time * instr.sample_rate - instr.samples_per_record = helpers.roundup( - samples_needed, instr.samples_divisor) - instr.acquisition.acquisition_kwargs.update( - samples_per_record=instr.samples_per_record) - - def _update_int_delay(instr, value, **kwargs): - """ - Function to validate value for int_delay before setting parameter - value - - Args: - value to be validated and used for instrument attribute update - - Checks: - 0 <= value <= 0.1 seconds - number of samples discarded >= numtaps - - Sets: - sample_rate attr of acq controller to be that of alazar - samples_per_record of acq controller - acquisition_kwarg['samples_per_record'] of acquisition param - setpoints of acquisiton param - """ - if (value is None) or not (0 <= value <= 0.1): - raise ValueError('int_delay must be 0 <= value <= 1') - alazar = instr._get_alazar() - instr.sample_rate = alazar.get_sample_rate() - samples_delay_min = (instr.filter_settings['numtaps'] - 1) - int_delay_min = samples_delay_min / instr.sample_rate - if value < int_delay_min: - logging.warning( - 'delay is less than recommended for filter choice: ' - '(expect delay >= {})'.format(int_delay_min)) - - # update acquision kwargs and acq controller value - total_time = value + (instr.int_time() or 0) - samples_needed = total_time * instr.sample_rate - instr.samples_per_record = helpers.roundup( - samples_needed, instr.samples_divisor) - instr.acquisition.acquisition_kwargs.update( - samples_per_record=instr.samples_per_record) - - def _int_delay_default(instr): - """ - Function to generate default int_delay value - - Returns: - minimum int_delay recommended for (numtaps - 1) - samples to be discarded as recommended for filter - """ - alazar = instr._get_alazar() - instr.sample_rate = alazar.get_sample_rate() - samp_delay = instr.filter_settings['numtaps'] - 1 - return samp_delay / instr.sample_rate - - def _int_time_default(instr): - """ - Function to generate defult int_time value - - Returns: - max total time for integration based on samples_per_record, - sample_rate and int_delay - """ - if instr.samples_per_record is (0 or None): - raise ValueError('Cannot set int_time to max if acq controller' - ' has 0 or None samples_per_record, choose a ' - 'value for int_time and samples_per_record will ' - 'be set accordingly') - alazar = instr._get_alazar() - instr.sample_rate = alazar.get_sample_rate() - total_time = ((instr.samples_per_record / instr.sample_rate) - - (instr.int_delay() or 0)) - return total_time - - def get_demod_freqs(self): - """ - Function to get all the demod_freq parameter values in a list, v hacky - - Returns: - freqs: numpy array of demodulation frequencies - """ - freqs = list(filter(None, [getattr(self, 'demod_freq_{}'.format(c))() - for c in range(self._demod_length)])) - return np.array(freqs) - - def get_max_demod_freq(self): - """ - Returns: - the largest demodulation frequency - - nb: really hacky and we should have channels in qcodes but we don't - (at time of writing) - """ - freqs = self.get_demod_freqs() - if len(freqs) > 0: - return max(freqs) - else: - return None - - def update_filter_settings(self, filter, numtaps): - """ - Updates the settings of the filter for filtering out - double frwuency component for demodulation. - - Args: - filter (str): filter type ('win' or 'ls') - numtaps (int): numtaps for filter - """ - self.filter_settings.update({'filter': self.filter_dict[filter], - 'numtaps': numtaps}) - - def update_acquisition_kwargs(self, **kwargs): - """ - Updates the kwargs to be used when - alazar_driver.acquisition() is called via a get call of the - acquisition SamplesParam. Should be used by the user for - updating averaging settings since the 'samples_per_record' - kwarg is updated via the int_time and int_delay parameters - - Kwargs (ints): - records_per_buffer - buffers_per_acquisition - allocated_buffers - """ - if 'samples_per_record' in kwargs: - raise ValueError('With HD_Samples_Controller ' - 'samples_per_record cannot be set manually ' - 'via update_acquisition_kwargs and should instead' - ' be set by setting int_time and int_delay') - if 'records_per_buffer' in kwargs: - self.acquisition.update_sweep(kwargs['records_per_buffer']) - self.records_per_buffer = kwargs['records_per_buffer'] - self.acquisition.acquisition_kwargs.update(**kwargs) - - def pre_start_capture(self): - """ - Called before capture start to update Acquisition Controller with - alazar acquisition params and set up software wave for demodulation. - """ - alazar = self._get_alazar() - if self.samples_per_record != alazar.samples_per_record.get(): - raise Exception('acq controller samples per record does not match' - ' instrument value, most likely need ' - 'to set and check int_time and int_delay') - if self.sample_rate != alazar.get_sample_rate(): - raise Exception('acq controller sample rate does not match ' - 'instrument value, most likely need ' - 'to set and check int_time and int_delay') - if self.records_per_buffer != alazar.records_per_buffer.get(): - raise Exception('acq controller records per buffer does not match ' - 'instrument value, most likely need ' - 'to call update_acquisition_kwargs with' - 'records_per_buffer as a param') - - demod_list = self.get_demod_freqs() - if len(demod_list) == 0: - raise Exception('no demod_freqs set') - - self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() - self.board_info = alazar.get_idn() - self.buffer = np.zeros(self.samples_per_record * - self.records_per_buffer * - self.number_of_channels) - - mat_shape = (self._demod_length, self.records_per_buffer, - self.samples_per_record) - demod_list = np.array([getattr(self, 'demod_freq_{}'.format(n))() - for n in range(self._demod_length)]) - integer_list = np.arange(self.samples_per_record) - integer_mat = np.outer(np.ones(self.records_per_buffer), integer_list) - angle_mat = 2 * np.pi * \ - np.outer(demod_list, integer_mat).reshape( - mat_shape) / self.sample_rate - self.cos_mat = np.cos(angle_mat) - self.sin_mat = np.sin(angle_mat) - - def pre_acquire(self): - pass - - def handle_buffer(self, data): - """ - Adds data from alazar to buffer (effectively averaging) - """ - self.buffer += data - - def post_acquire(self): - """ - Processes the data according to ATS9360 settings, splitting into - records and then applying demodulation fit - nb: currently only channel A - - Returns: - magnitude (numpy array): shape = (demod_length, records_per_buffer) - phase (numpy array): shape = (demod_length, records_per_buffer - """ - # for ATS9360 samples are arranged in the buffer as follows: - # S00A, S00B, S01A, S01B...S10A, S10B, S11A, S11B... - # where SXYZ is record X, sample Y, channel Z. - - # break buffer up into records and shapes to be (records, samples) - recordsA = np.empty((self.records_per_buffer, self.samples_per_record), - dtype=np.uint16) - for i in range(self.records_per_buffer): - i0 = (i * self.samples_per_record * self.number_of_channels) - i1 = (i0 + self.samples_per_record * self.number_of_channels) - recordsA[i, :] = np.uint16( - self.buffer[i0:i1:self.number_of_channels] / - self.buffers_per_acquisition) - - # do demodulation - magA, phaseA = self._fit(recordsA) - - # same for chan b - if self.chan_b: - raise NotImplementedError('chan b code not complete') - - return magA, phaseA - - def _fit(self, rec): - """ - Applies volts conversion, demodulation fit, low bandpass filter - and integration limits to samples array - - Args: - rec (numpy array): record from alazar to be multiplied - with the software signal, filtered and limited - to integration limits shape = (samples_taken, ) - - Returns: - magnitude (numpy array): shape = (demod_length, records_per_buffer) - phase (numpy array): shape = (demod_length, records_per_buffer) - """ - # convert rec to volts - bps = self.board_info['bits_per_sample'] - if bps == 12: - volt_rec = helpers.sample_to_volt_u12(rec, bps) - else: - logging.warning('sample to volt conversion does not exist for' - ' bps != 12, centered raw samples returned') - volt_rec = rec - np.mean(rec, axis=1) - - # volt_rec to matrix and multiply with demodulation signal matrices - mat_shape = (self._demod_length, self.records_per_buffer, - self.samples_per_record) - volt_rec_mat = np.outer( - np.ones(self._demod_length), volt_rec).reshape(mat_shape) - re_mat = np.multiply(volt_rec_mat, self.cos_mat) - im_mat = np.multiply(volt_rec_mat, self.sin_mat) - - # filter out higher freq component - cutoff = self.get_max_demod_freq() / 10 - if self.filter_settings['filter'] == 0: - re_filtered = helpers.filter_win(re_mat, cutoff, - self.sample_rate, - self.filter_settings['numtaps'], - axis=2) - im_filtered = helpers.filter_win(im_mat, cutoff, - self.sample_rate, - self.filter_settings['numtaps'], - axis=2) - elif self.filter_settings['filter'] == 1: - re_filtered = helpers.filter_ls(re_mat, cutoff, - self.sample_rate, - self.filter_settings['numtaps'], - axis=2) - im_filtered = helpers.filter_ls(im_mat, cutoff, - self.sample_rate, - self.filter_settings['numtaps'], - axis=2) - elif self.filter_settings['filter'] == 2: - re_filtered = re_mat - im_filtered = im_mat - - # apply integration limits - beginning = int(self.int_delay() * self.sample_rate) - end = beginning + int(self.int_time() * self.sample_rate) - - re_limited = re_filtered[:, :, beginning:end] - im_limited = im_filtered[:, :, beginning:end] - - # convert to magnitude and phase - complex_mat = re_limited + im_limited * 1j - magnitude = np.mean(abs(complex_mat), axis=2) - phase = np.mean(np.angle(complex_mat, deg=True), axis=2) - - return magnitude, phase From f1ddc48a217b1cd28ef6df374e8050cf0bbf910c Mon Sep 17 00:00:00 2001 From: Natalie Pearson Date: Tue, 7 Feb 2017 16:22:14 +0100 Subject: [PATCH 099/180] tweak and comment out demod setpoint logic for until setpoints are fixed --- .../AlazarTech/ave_controller.py | 10 ++++---- .../AlazarTech/rec_controller.py | 23 ++++++++----------- .../AlazarTech/samp_controller.py | 20 ++++++++-------- 3 files changed, 24 insertions(+), 29 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/ave_controller.py b/qcodes/instrument_drivers/AlazarTech/ave_controller.py index ee49c9afe102..87e25a89df8a 100644 --- a/qcodes/instrument_drivers/AlazarTech/ave_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/ave_controller.py @@ -109,9 +109,9 @@ def update_demod_setpoints(self, demod_freqs): setpoints if length > 1 """ demod_length = self._instrument._demod_length - self._demod_list = demod_freqs if demod_length > 1: - self.setpoints = ((self._demod_list, ), (self._demod_list, )) + pass + # self.setpoints = ((demod_freqs, ), (demod_freqs, )) else: pass @@ -420,8 +420,8 @@ def pre_start_capture(self): 'instrument value, most likely need ' 'to set and check int_time and int_delay') - demod_list = self.get_demod_freqs() - if len(demod_list) == 0: + demod_freqs = self.get_demod_freqs() + if len(demod_freqs) == 0: raise Exception('no demod_freqs set') self.records_per_buffer = alazar.records_per_buffer.get() @@ -433,7 +433,7 @@ def pre_start_capture(self): integer_list = np.arange(self.samples_per_record) angle_mat = 2 * np.pi * \ - np.outer(demod_list, integer_list) / self.sample_rate + np.outer(demod_freqs, integer_list) / self.sample_rate self.cos_mat = np.cos(angle_mat) self.sin_mat = np.sin(angle_mat) diff --git a/qcodes/instrument_drivers/AlazarTech/rec_controller.py b/qcodes/instrument_drivers/AlazarTech/rec_controller.py index 168658ca93e0..a04402623fc0 100644 --- a/qcodes/instrument_drivers/AlazarTech/rec_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/rec_controller.py @@ -86,9 +86,9 @@ class RecordsAcqParam(Parameter): not nice and should be changed when possible TODO(nataliejpg) setpoints (including names and units) - TODO(nataliejpg) setpoint units - TODO(nataliejpg) convert records setpoint into actual frequency + TODO(nataliejpg) convert records setpoint into variable/param """ + def __init__(self, name, instrument, demod_length): super().__init__(name) self._instrument = instrument @@ -107,12 +107,10 @@ def update_sweep(self, npts, start=None, stop=None): """ demod_length = self._instrument._demod_length # self.rec_list = tuple(np.linspace(start, stop, num=npts)) - # demod_index = tuple(range(demod_length)) if demod_length > 1: - # demod_index = tuple(range(demod_length)) # demod_freqs = self._instrument.get_demod_freqs() - # self.setpoints = ((demod_freqs, self._rec_list), ( - # demod_freqs, self._rec_list)) + # self.setpoints = ((demod_freqs, self._rec_list), + # (demod_freqs, self._rec_list)) self.shapes = ((demod_length, npts), (demod_length, npts)) else: self.shapes = ((npts,), (npts,)) @@ -129,8 +127,9 @@ def update_demod_setpoints(self, demod_freqs): """ demod_length = self._instrument._demod_length if demod_length > 1: - self.setpoints = ((demod_freqs, self._rec_list), - (demod_freqs, self._rec_list)) + pass + # self.setpoints = ((demod_freqs, self._rec_list), + # (demod_freqs, self._rec_list)) else: pass @@ -447,8 +446,8 @@ def pre_start_capture(self): 'to call update_acquisition_kwargs with' 'records_per_buffer as a param') - demod_list = self.get_demod_freqs() - if len(demod_list) == 0: + demod_freqs = self.get_demod_freqs() + if len(demod_freqs) == 0: raise Exception('no demod_freqs set') self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() @@ -459,12 +458,10 @@ def pre_start_capture(self): mat_shape = (self._demod_length, self.records_per_buffer, self.samples_per_record) - demod_list = np.array([getattr(self, 'demod_freq_{}'.format(n))() - for n in range(self._demod_length)]) integer_list = np.arange(self.samples_per_record) integer_mat = np.outer(np.ones(self.records_per_buffer), integer_list) angle_mat = 2 * np.pi * \ - np.outer(demod_list, integer_mat).reshape( + np.outer(demod_freqs, integer_mat).reshape( mat_shape) / self.sample_rate self.cos_mat = np.cos(angle_mat) self.sin_mat = np.sin(angle_mat) diff --git a/qcodes/instrument_drivers/AlazarTech/samp_controller.py b/qcodes/instrument_drivers/AlazarTech/samp_controller.py index 02b67605d64d..b4de18318781 100644 --- a/qcodes/instrument_drivers/AlazarTech/samp_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/samp_controller.py @@ -83,7 +83,6 @@ class SamplesAcqParam(Parameter): instrument: acquisition controller instrument this parameter belongs to TODO(nataliejpg) setpoints (including names and units) - TODO(nataliejpg) setpoint units """ def __init__(self, name, instrument): @@ -105,10 +104,9 @@ def update_sweep(self, start, stop, npts): demod_length = self._instrument._demod_length # self._time_list = tuple(np.linspace(start, stop, num=npts)) if demod_length > 1: - # demod_index = tuple(range(demod_length)) - # self._demod_list = self._instrument.get_demod_freqs() - # self.setpoints = ((self._demod_list, self._time_list ), ( - # self._demod_list, self._time_list )) + # demod_freqs = self._instrument.get_demod_freqs() + # self.setpoints = ((demod_freqs, self._time_list), + # (demod_freqs, self._time_list)) self.shapes = ((demod_length, npts), (demod_length, npts)) else: self.shapes = ((npts,), (npts,)) @@ -124,10 +122,10 @@ def update_demod_setpoints(self, demod_freqs): setpoints if length > 1 """ demod_length = self._instrument._demod_length - self._demod_list = demod_freqs if demod_length > 1: - self.setpoints = ((self._demod_list, self._time_list), - (self._demod_list, self._time_list)) + pass + # self.setpoints = ((demod_freqs, self._time_list), + # (demod_freqs, self._time_list)) else: pass @@ -445,8 +443,8 @@ def pre_start_capture(self): 'instrument value, most likely need ' 'to call update_acquisition_settings') - demod_list = self.get_demod_freqs() - if len(demod_list) == 0: + demod_freqs = self.get_demod_freqs() + if len(demod_freqs) == 0: raise Exception('no demod_freqs set') self.records_per_buffer = alazar.records_per_buffer.get() @@ -458,7 +456,7 @@ def pre_start_capture(self): integer_list = np.arange(self.samples_per_record) angle_mat = 2 * np.pi * \ - np.outer(demod_list, integer_list) / self.sample_rate + np.outer(demod_freqs, integer_list) / self.sample_rate self.cos_mat = np.cos(angle_mat) self.sin_mat = np.sin(angle_mat) From dab7ff0e4952c368e4e5e450cd783d86fcf56246 Mon Sep 17 00:00:00 2001 From: Natalie Pearson Date: Tue, 7 Feb 2017 16:39:07 +0100 Subject: [PATCH 100/180] move samples_divisor into init of acq controllers so no need to import ATS9360 class, should be more general --- qcodes/instrument_drivers/AlazarTech/ave_controller.py | 4 ++-- qcodes/instrument_drivers/AlazarTech/rec_controller.py | 4 ++-- qcodes/instrument_drivers/AlazarTech/samp_controller.py | 3 +-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/ave_controller.py b/qcodes/instrument_drivers/AlazarTech/ave_controller.py index 87e25a89df8a..a7e7d1b67fb4 100644 --- a/qcodes/instrument_drivers/AlazarTech/ave_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/ave_controller.py @@ -1,6 +1,5 @@ import logging from .ATS import AcquisitionController -from .ATS9360 import AlazarTech_ATS9360 import numpy as np from qcodes import Parameter import qcodes.instrument_drivers.AlazarTech.acq_helpers as helpers @@ -159,7 +158,6 @@ class HD_Averaging_Controller(AcquisitionController): """ filter_dict = {'win': 0, 'ls': 1, 'ave': 2} - samples_divisor = AlazarTech_ATS9360.samples_divisor def __init__(self, name, alazar_name, demod_length=1, filter='win', numtaps=101, chan_b=False, **kwargs): @@ -188,6 +186,8 @@ def __init__(self, name, alazar_name, demod_length=1, filter='win', default_fn=self._int_delay_default, parameter_class=AcqVariablesParam) + self.samples_divisor = self._get_alazar().samples_divisor + def _update_demod_freq(instr, value, param_name=None): """ Function to validate and update acquisiton parameter when diff --git a/qcodes/instrument_drivers/AlazarTech/rec_controller.py b/qcodes/instrument_drivers/AlazarTech/rec_controller.py index a04402623fc0..a10629a00ecf 100644 --- a/qcodes/instrument_drivers/AlazarTech/rec_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/rec_controller.py @@ -1,6 +1,5 @@ import logging from .ATS import AcquisitionController -from .ATS9360 import AlazarTech_ATS9360 import numpy as np from qcodes import Parameter import qcodes.instrument_drivers.AlazarTech.acq_helpers as helpers @@ -178,7 +177,6 @@ class HD_Records_Controller(AcquisitionController): """ filter_dict = {'win': 0, 'ls': 1, 'ave': 2} - samples_divisor = AlazarTech_ATS9360.samples_divisor def __init__(self, name, alazar_name, demod_length=1, filter='win', numtaps=101, chan_b=False, **kwargs): @@ -208,6 +206,8 @@ def __init__(self, name, alazar_name, demod_length=1, filter='win', default_fn=self._int_delay_default, parameter_class=AcqVariablesParam) + self.samples_divisor = self._get_alazar().samples_divisor + def _update_demod_freq(instr, value, param_name=None): """ Function to validate and update acquisiton parameter when diff --git a/qcodes/instrument_drivers/AlazarTech/samp_controller.py b/qcodes/instrument_drivers/AlazarTech/samp_controller.py index b4de18318781..7f1974eb8f9b 100644 --- a/qcodes/instrument_drivers/AlazarTech/samp_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/samp_controller.py @@ -1,6 +1,5 @@ import logging from .ATS import AcquisitionController -from .ATS9360 import AlazarTech_ATS9360 import numpy as np from qcodes import Parameter import qcodes.instrument_drivers.AlazarTech.acq_helpers as helpers @@ -173,7 +172,6 @@ class HD_Samples_Controller(AcquisitionController): TODO(nataliejpg) demod_freq number should be changeable number: channels? """ filter_dict = {'win': 0, 'ls': 1} - samples_divisor = AlazarTech_ATS9360.samples_divisor def __init__(self, name, alazar_name, demod_length=1, filter='win', numtaps=101, chan_b=False, **kwargs): @@ -200,6 +198,7 @@ def __init__(self, name, alazar_name, demod_length=1, filter='win', check_and_update_fn=self._update_int_delay, default_fn=self._int_delay_default, parameter_class=AcqVariablesParam) + self.samples_divisor = self._get_alazar().samples_divisor def _update_demod_freq(instr, value, param_name=None): """ From 1c44788be932274a105c88804679db4acc98f538 Mon Sep 17 00:00:00 2001 From: Natalie Pearson Date: Tue, 7 Feb 2017 19:21:32 +0100 Subject: [PATCH 101/180] updating docstrings, making rec_num and buf_num parameters where necessary and doing most of rec_samp controller and buf_rec controller --- .../instrument_drivers/AlazarTech/ATS9360.py | 7 +- .../AlazarTech/ave_controller.py | 8 +- .../AlazarTech/buf_rec_controller.py | 686 ++++++++++++++++ .../AlazarTech/rec_buf_controller.py | 220 ----- .../AlazarTech/rec_controller.py | 80 +- .../AlazarTech/rec_samp_controller.py | 751 ++++++++++++++---- .../AlazarTech/samp_controller.py | 20 +- 7 files changed, 1345 insertions(+), 427 deletions(-) create mode 100644 qcodes/instrument_drivers/AlazarTech/buf_rec_controller.py delete mode 100644 qcodes/instrument_drivers/AlazarTech/rec_buf_controller.py diff --git a/qcodes/instrument_drivers/AlazarTech/ATS9360.py b/qcodes/instrument_drivers/AlazarTech/ATS9360.py index 5ffe33f03699..3c33374d50c7 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS9360.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS9360.py @@ -8,8 +8,13 @@ class AlazarTech_ATS9360(AlazarTech_ATS): it inherits from the ATS base class TODO(nataliejpg): - - add clock source options and sample rate options + - add clock source options and sample rate options + (probelem being that byte_to_value_dict of + sample_rate relies on value of clock_source) """ + + # samples divisor is listed in the manual as being 32 but this gave + # incorrect data when tested for divisors less than 128 samples_divisor = 128 def __init__(self, name, **kwargs): diff --git a/qcodes/instrument_drivers/AlazarTech/ave_controller.py b/qcodes/instrument_drivers/AlazarTech/ave_controller.py index a7e7d1b67fb4..7cfa7036cf26 100644 --- a/qcodes/instrument_drivers/AlazarTech/ave_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/ave_controller.py @@ -235,7 +235,7 @@ def _update_demod_freq(instr, value, param_name=None): def _update_int_time(instr, value, **kwargs): """ Function to validate value for int_time before setting parameter - value + value and update instr attributes. Args: value to be validated and used for instrument attribute update @@ -282,7 +282,7 @@ def _update_int_time(instr, value, **kwargs): def _update_int_delay(instr, value, **kwargs): """ Function to validate value for int_delay before setting parameter - value + value and update instr attributes. Args: value to be validated and used for instrument attribute update @@ -389,7 +389,7 @@ def update_acquisition_kwargs(self, **kwargs): """ Updates the kwargs to be used when alazar_driver.acquisition() is called via a get call of the - acquisition SamplesParam. Should be used by the user for + acquisition AveragedAcqParam. Should be used by the user for updating averaging settings since the 'samples_per_record' kwarg is updated via the int_time and int_delay parameters @@ -399,7 +399,7 @@ def update_acquisition_kwargs(self, **kwargs): allocated_buffers """ if 'samples_per_record' in kwargs: - raise ValueError('With HD_Samples_Controller ' + raise ValueError('With HD_Averaging_Controller ' 'samples_per_record cannot be set manually ' 'via update_acquisition_kwargs and should instead' ' be set by setting int_time and int_delay') diff --git a/qcodes/instrument_drivers/AlazarTech/buf_rec_controller.py b/qcodes/instrument_drivers/AlazarTech/buf_rec_controller.py new file mode 100644 index 000000000000..b4e118970901 --- /dev/null +++ b/qcodes/instrument_drivers/AlazarTech/buf_rec_controller.py @@ -0,0 +1,686 @@ +import logging +from .ATS import AcquisitionController +import numpy as np +from qcodes import Parameter +import qcodes.instrument_drivers.AlazarTech.acq_helpers as helpers + + +class AcqVariablesParam(Parameter): + """ + Parameter of an AcquisitionController which has a _check_and_update_instr + function used for validation and to update instrument attributes and a + _get_default function which it uses to set the AcqVariablesParam to an + instrument caluclated default. + + Args: + name: name for this parameter + instrument: acquisition controller instrument this parameter belongs to + check_and_update_fn: instrument function to be used for value + validation and updating instrument values + default_fn (optional): instrument function to be used to calculate + a default value to set parameter to + initial_value (optional): initial value for parameter + """ + + def __init__(self, name, instrument, check_and_update_fn, + default_fn=None, initial_value=None): + super().__init__(name) + self._instrument = instrument + self._save_val(initial_value) + setattr(self, '_check_and_update_instr', check_and_update_fn) + if default_fn is not None: + setattr(self, '_get_default', default_fn) + + def set(self, value): + """ + Function which checks value using validation function and then sets + the Parameter value to this value. + + Args: + value: value to set the parameter to + """ + self._check_and_update_instr(value, param_name=self.name) + self._save_val(value) + + def get(self): + return self._latest()['value'] + + def to_default(self): + """ + Function which executes the default_fn specified to calculate the + default value based on instrument values and then calls the set + function with this value + """ + try: + default = self._get_default() + except AttributeError as e: + raise AttributeError('no default function for {} Parameter ' + '{}'.format(self.name, e)) + self.set(default) + + def check(self): + """ + Function which checks the current Parameter value using the specified + check_and_update_fn which can also serve to update instrument values. + + Return: + True (if no errors raised when check_and_update_fn executed) + """ + val = self._latest()['value'] + self._check_and_update_instr(val, param_name=self.name) + return True + + +class BuffersRecordsAcqParam(Parameter): + """ + Software controlled parameter class for Alazar acquisition. To be used with + HD_Records_Controller (tested with ATS9360 board) for return of + averaged magnitude and phase data from the Alazar. + + Args: + name: name for this parameter + instrument: acquisition controller instrument this parameter belongs to + + TODO(nataliejpg) setpoints (including names and units) + """ + + def __init__(self, name, instrument): + super().__init__(name) + self._instrument = instrument + self.acquisition_kwargs = {} + self.names = ('magnitude', 'phase') + + def update_buf_sweep(self, buf_npts, buf_start=None, buf_stop=None): + """ + Function which updates the shape of the parameter (and it's setpoints + when this is fixed) + + Args: + buf_npts: number of buffers returned + buf_start (optional): start value of buffers returned + buf_stop (optional): stop value of records returned + """ + demod_length = self._instrument._demod_length + # self._buf_list = tuple(np.linspace(buf_start, + # buf_stop, num=buf_npts)) + self._buf_npts = buf_npts + if demod_length > 1: + # demod_freqs = self._instrument.get_demod_freqs() + # self.setpoints = ((demod_freqs, self._buf_list, self._rec_list), + # (demod_freqs, self._buf_list, self._rec_list)) + self.shapes = ((demod_length, self._buf_npts, self._rec_npts), + (demod_length, self._buf_npts, self._rec_npts)) + else: + self.shapes = ((self._buf_npts, self._rec_npts), + (self._buf_npts, self._rec_npts)) + # self.setpoints = ((self._buf_list, self._rec_list), + # (self._buf_list, self._rec_list)) + + def update_rec_sweep(self, rec_npts, rec_start=None, rec_stop=None): + """ + Function which updates the shape of the parameter (and it's setpoints + when this is fixed) + + Args: + rec_npts: number of records returned after processing + rec_start (optional): start value of records returned + rec_stop (optional): stop value of records returned + """ + demod_length = self._instrument._demod_length + # self._rec_list = tuple(np.linspace(rec_start, + # rec_stop, num=rec_npts)) + self._rec_npts = rec_npts + if demod_length > 1: + # demod_freqs = self._instrument.get_demod_freqs() + # self.setpoints = ((demod_freqs, self._buf_list, self._rec_list), + # (demod_freqs, self._buf_list, self._rec_list)) + self.shapes = ((demod_length, self._buf_npts, self._rec_npts), + (demod_length, self._buf_npts, self._rec_npts)) + else: + self.shapes = ((self._buf_npts, self._rec_npts), + (self._buf_npts, self._rec_npts)) + # self.setpoints = ((self._buf_list, self._rec_list), + # (self._buf_list, self._rec_list)) + + def update_demod_setpoints(self, demod_freqs): + """ + Function to update the demodulation frequency setpoints to be called + when a demod_freq Parameter of the acq controller is updated + + Args: + demod_freqs: numpy array of demodulation frequencies to use as + setpoints if length > 1 + """ + demod_length = self._instrument._demod_length + if demod_length > 1: + pass + # self.setpoints = ((demod_freqs, self._buf_list, self._rec_list), + # (demod_freqs, self._buf_list, self._rec_list)) + else: + pass + + def get(self): + """ + Gets the magnitude and phase signal by calling acquire + on the alazar (which in turn calls the processing functions of the + aqcuisition controller before returning the processed data + demodulated at specified frequencies and averaged over samples + and buffers) + + Returns: + mag: numpy array of magnitude, shape (demod_length, records) + phase: numpy array of magnitude, shape (demod_length, records) + """ + mag, phase = self._instrument._get_alazar().acquire( + acquisition_controller=self._instrument, + **self.acquisition_kwargs) + return mag, phase + + +class HD_BuffersRecords_Controller(AcquisitionController): + """ + This is the Acquisition Controller class which works with the ATS9360, + averaging over samples (limited by int_time and int_delay values) and + buffers and demodulating with software reference signal(s). + + Args: + name: name for this acquisition_conroller as an instrument + alazar_name: name of the alazar instrument such that this + controller can communicate with the Alazar + demod_length (default 1): number of demodulation frequencies + filter (default 'win'): filter to be used to filter out double freq + component ('win' - window, 'ls' - least squared, 'ave' - averaging) + numtaps (default 101): number of freq components used in filter + chan_b (default False): whether there is also a second channel of data + to be processed and returned + **kwargs: kwargs are forwarded to the Instrument base class + + TODO(nataliejpg) test filter options + TODO(nataliejpg) finish implementation of channel b option + TODO(nataliejpg) what should be private? + TODO(nataliejpg) where should filter_dict live? + TODO(nataliejpg) demod_freq should be changeable number: maybe channels + TODO(nataliejpg) make record param 'start' and 'stop' meaningful + TODO(nataliejpg) make buffers param 'start' and 'stop' meaningful + """ + + filter_dict = {'win': 0, 'ls': 1, 'ave': 2} + + def __init__(self, name, alazar_name, demod_length=1, filter='win', + numtaps=101, chan_b=False, **kwargs): + self.filter_settings = {'filter': self.filter_dict[filter], + 'numtaps': numtaps} + self.chan_b = chan_b + self._demod_length = demod_length + self.number_of_channels = 2 + self.samples_per_record = None + self.sample_rate = None + super().__init__(name, alazar_name, **kwargs) + + self.add_parameter(name='acquisition', + parameter_class=BuffersRecordsAcqParam) + for i in range(demod_length): + self.add_parameter(name='demod_freq_{}'.format(i), + check_and_update_fn=self._update_demod_freq, + parameter_class=AcqVariablesParam) + self.add_parameter(name='int_time', + check_and_update_fn=self._update_int_time, + default_fn=self._int_time_default, + parameter_class=AcqVariablesParam) + self.add_parameter(name='int_delay', + check_and_update_fn=self._update_int_delay, + default_fn=self._int_delay_default, + parameter_class=AcqVariablesParam) + self.add_parameter(name='record_num', + check_and_update_fn=self._update_rec_num, + parameter_class=AcqVariablesParam) + self.add_parameter(name='buffer_num', + check_and_update_fn=self._update_buf_num, + parameter_class=AcqVariablesParam) + + self.samples_divisor = self._get_alazar().samples_divisor + + def _update_demod_freq(instr, value, param_name=None): + """ + Function to validate and update acquisiton parameter when + a demod_freq_ Parameter is changed + + Args: + value to update demodulation frequency to + + Kwargs: + param_name: used to update demod_freq list used for updating + septionts of acquisition parameter + + Checks: + 1e6 <= value <= 500e6 + number of oscilation measured using current int_tiume param value + at this demod frequency value + oversampling rate for this demodulation frequency + + Sets: + sample_rate attr of acq controller to be that of alazar + setpoints of acquisiton parameter + """ + if (value is None) or not (1e6 <= value <= 500e6): + raise ValueError('demod_freqs must be 1e6 <= value <= 500e6') + alazar = instr._get_alazar() + instr.sample_rate = alazar.get_sample_rate() + min_oscilations_measured = instr.int_time() * value + oversampling = instr.sample_rate / (2 * value) + if min_oscilations_measured < 10: + logging.warning('{} oscilations measured for largest ' + 'demod freq, recommend at least 10: ' + 'decrease sampling rate, take ' + 'more samples or increase demodulation ' + 'freq'.format(min_oscilations_measured)) + elif oversampling < 1: + logging.warning('oversampling rate is {}, recommend > 1: ' + 'increase sampling rate or decrease ' + 'demodulation frequency'.format(oversampling)) + demod_freqs = instr.get_demod_freqs() + current_demod_index = ([int(s) for s in param_name.split() + if s.isdigit()][0]) + demod_freqs[current_demod_index] = value + instr.acquisition.update_demod_setpoints(demod_freqs) + + def _update_record_num(instr, value, **kwargs): + """ + Function to update the record number, and instr attributes. Main + reason to record_num as a parameter is so we can more easily push the + record number setting up to other instruments which will control this. + + Args: + value to be validated and used for instrument attribute update + + Checks: + 1 <= value <= 1000 + + Sets: + acquisition_kwarg['records_per_buffer'] of acquisition param + setpoints of acquisiton param + shape of acquisition param + """ + if (value is None) or not (1 <= value <= 1000): + raise ValueError('int_time must be 1 <= value <= 1000') + + # update acquisition parameter shapes + instr.acquisition.update_sweep(value) + + # update acquision kwargs + instr.acquisition.acquisition_kwargs.update( + records_per_buffer=value) + + def _update_buffer_num(instr, value, **kwargs): + """ + Function to update the buffer number, and instr attributes. By now + I'm just making a parameter because it follows the patter of having a + parameter for everything we want to preserve and not average over. + At some point this should maybe be done more smartly with having + "number of averages" and the driver working out how to allocate + records and buffers accordingly depending on what is being averaged + over. If you have ideas let me know. nataliejpg + + Args: + value to be validated and used for instrument attribute update + + Checks: + 1 <= value <= 100000 + + Sets: + acquisition_kwarg['buffers_per_acquisition'] of acquisition param + setpoints of acquisiton param + shape of acquisition param + """ + if (value is None) or not (1 <= value <= 100000): + raise ValueError('int_time must be 1 <= value <= 1000') + + # update acquisition parameter shapes + instr.acquisition.update_buf_sweep(value) + + # update acquision kwargs + instr.acquisition.acquisition_kwargs.update( + buffers_per_acquisition=value) + + def _update_int_time(instr, value, **kwargs): + """ + Function to validate value for int_time before setting parameter + value and update instr attributes. + + Args: + value to be validated and used for instrument attribute update + + Checks: + 0 <= value <= 0.1 seconds + number of oscilation measured in this time + oversampling rate + + Sets: + sample_rate attr of acq controller to be that of alazar + samples_per_record of acq controller + acquisition_kwarg['samples_per_record'] of acquisition param + """ + if (value is None) or not (0 <= value <= 0.1): + raise ValueError('int_time must be 0 <= value <= 1') + alazar = instr._get_alazar() + instr.sample_rate = alazar.get_sample_rate() + if instr.get_max_demod_freq() is not None: + oscilations_measured = value * instr.get_max_demod_freq() + oversampling = instr.sample_rate / (2 * instr.get_max_demod_freq()) + if oscilations_measured < 10: + logging.warning('{} oscilations measured, recommend at ' + 'least 10: decrease sampling rate, take ' + 'more samples or increase demodulation ' + 'freq'.format(oscilations_measured)) + elif oversampling < 1: + logging.warning('oversampling rate is {}, recommend > 1: ' + 'increase sampling rate or decrease ' + 'demodulation frequency'.format(oversampling)) + if instr.int_delay() is None: + instr.int_delay.to_default() + + # update acquision kwargs and acq controller value + total_time = value + instr.int_delay() + samples_needed = total_time * instr.sample_rate + instr.samples_per_record = helpers.roundup( + samples_needed, instr.samples_divisor) + instr.acquisition.acquisition_kwargs.update( + samples_per_record=instr.samples_per_record) + + def _update_int_delay(instr, value, **kwargs): + """ + Function to validate value for int_delay before setting parameter + value and update instr attributes. + + Args: + value to be validated and used for instrument attribute update + + Checks: + 0 <= value <= 0.1 seconds + number of samples discarded >= numtaps + + Sets: + sample_rate attr of acq controller to be that of alazar + samples_per_record of acq controller + acquisition_kwarg['samples_per_record'] of acquisition param + """ + if (value is None) or not (0 <= value <= 0.1): + raise ValueError('int_delay must be 0 <= value <= 1') + alazar = instr._get_alazar() + instr.sample_rate = alazar.get_sample_rate() + samples_delay_min = (instr.filter_settings['numtaps'] - 1) + int_delay_min = samples_delay_min / instr.sample_rate + if value < int_delay_min: + logging.warning( + 'delay is less than recommended for filter choice: ' + '(expect delay >= {})'.format(int_delay_min)) + + # update acquision kwargs and acq controller value + total_time = value + (instr.int_time() or 0) + samples_needed = total_time * instr.sample_rate + instr.samples_per_record = helpers.roundup( + samples_needed, instr.samples_divisor) + instr.acquisition.acquisition_kwargs.update( + samples_per_record=instr.samples_per_record) + + def _int_delay_default(instr): + """ + Function to generate default int_delay value + + Returns: + minimum int_delay recommended for (numtaps - 1) + samples to be discarded as recommended for filter + """ + alazar = instr._get_alazar() + instr.sample_rate = alazar.get_sample_rate() + samp_delay = instr.filter_settings['numtaps'] - 1 + return samp_delay / instr.sample_rate + + def _int_time_default(instr): + """ + Function to generate defult int_time value + + Returns: + max total time for integration based on samples_per_record, + sample_rate and int_delay + """ + if instr.samples_per_record is (0 or None): + raise ValueError('Cannot set int_time to max if acq controller' + ' has 0 or None samples_per_record, choose a ' + 'value for int_time and samples_per_record will ' + 'be set accordingly') + alazar = instr._get_alazar() + instr.sample_rate = alazar.get_sample_rate() + total_time = ((instr.samples_per_record / instr.sample_rate) - + (instr.int_delay() or 0)) + return total_time + + def get_demod_freqs(self): + """ + Function to get all the demod_freq parameter values in a list, v hacky + + Returns: + freqs: numpy array of demodulation frequencies + """ + freqs = list(filter(None, [getattr(self, 'demod_freq_{}'.format(c))() + for c in range(self._demod_length)])) + return np.array(freqs) + + def get_max_demod_freq(self): + """ + Returns: + the largest demodulation frequency + + nb: really hacky and we should have channels in qcodes but we don't + (at time of writing) + """ + freqs = self.get_demod_freqs() + if len(freqs) > 0: + return max(freqs) + else: + return None + + def update_filter_settings(self, filter, numtaps): + """ + Updates the settings of the filter for filtering out + double frwuency component for demodulation. + + Args: + filter (str): filter type ('win' or 'ls') + numtaps (int): numtaps for filter + """ + self.filter_settings.update({'filter': self.filter_dict[filter], + 'numtaps': numtaps}) + + def update_acquisition_kwargs(self, **kwargs): + """ + Updates the kwargs to be used when + alazar_driver.acquisition() is called via a get call of the + acquisition BuffersRecordsAcqParam. Should be used by the user for + updating allocated_buffers kwarg since samples_per_record, + records_per_buffer and buffers_per_acquisition are updated via the + int_time, int_delay, record_num and buffer_num parameters + + Kwargs (ints): + allocated_buffers + """ + if 'samples_per_record' in kwargs: + raise ValueError('With HD_BuffersRecords_Controller ' + 'samples_per_record cannot be set manually ' + 'via update_acquisition_kwargs and should instead' + ' be set by setting int_time and int_delay') + if 'records_per_buffer' in kwargs: + raise ValueError('With HD_BuffersRecords_Controller ' + 'records_per_buffer cannot be set manually ' + 'via update_acquisition_kwargs and should instead' + ' be set by setting record_num') + if 'records_per_buffer' in kwargs: + raise ValueError('With HD_BuffersRecords_Controller ' + 'records_per_buffer cannot be set manually ' + 'via update_acquisition_kwargs and should instead' + ' be set by setting buffer_num') + self.acquisition.acquisition_kwargs.update(**kwargs) + + def pre_start_capture(self): + """ + Called before capture start to update Acquisition Controller with + alazar acquisition params and set up software wave for demodulation. + """ + alazar = self._get_alazar() + if self.samples_per_record != alazar.samples_per_record.get(): + raise Exception('acq controller samples per record does not match' + ' instrument value, most likely need ' + 'to set and check int_time and int_delay') + if self.sample_rate != alazar.get_sample_rate(): + raise Exception('acq controller sample rate does not match ' + 'instrument value, most likely need ' + 'to set and check int_time and int_delay') + if self.record_num() != alazar.records_per_buffer.get(): + raise Exception('acq controller record_num does not match ' + 'instrument value, most likely need ' + 'to call set and check record_num') + if self.buffer_num() != alazar.buffers_per_acquisition.get(): + raise Exception('acq controller buffer_num does not match ' + 'instrument value, most likely need ' + 'to call set and check buffer_num') + + demod_freqs = self.get_demod_freqs() + if len(demod_freqs) == 0: + raise Exception('no demod_freqs set') + + self.board_info = alazar.get_idn() + self.buffer_count = 0 + self.samples_per_buffer = (self.samples_per_record * + self.record_num() * + self.buffer_num() * + self.number_of_channels) + self.buffer = np.zeros(self.samples_per_record * + self.buffer_num() * + self.record_num() * + self.number_of_channels) + + mat_shape = (self._demod_length, self.buffer_num(), + self.record_num(), self.samples_per_record) + integer_list = np.arange(self.samples_per_record) + integer_mat = (np.outer(np.ones(self.buffer_num()), + np.outer(np.ones(self.record_num()), integer_list))) + angle_mat = 2 * np.pi * \ + np.outer(demod_freqs, integer_mat).reshape( + mat_shape) / self.sample_rate + self.cos_mat = np.cos(angle_mat) + self.sin_mat = np.sin(angle_mat) + + def pre_acquire(self): + pass + + def handle_buffer(self, data): + """ + Adds data from alazar to buffer (effectively averaging) + """ + i0 = self.buffer_count * self.samples_per_buffer + i1 = i0 + self.samples_per_buffer + self.buffer[i0:i1] = data + self.buf_count += 1 + + def post_acquire(self): + """ + Processes the data according to ATS9360 settings, splitting into + records and then applying demodulation fit + nb: currently only channel A + + Returns: + magnitude (numpy array): shape = (demod_length, records_per_buffer) + phase (numpy array): shape = (demod_length, records_per_buffer + """ + # for ATS9360 samples are arranged in the buffer as follows: + # S00A, S00B, S01A, S01B...S10A, S10B, S11A, S11B... + # where SXYZ is record X, sample Y, channel Z. + + # break buffer up into records and shapes to be (records, samples) + reshaped_buf = np.uint16(self.buffer.reshape(self.buffer_num(), + self.record_num(), + self.samples_per_buffer, + self.number_of_channels)) + + recA = reshaped_buf[:, :, :, 0] + + magA, phaseA = self._fit(recA) + + # same for chan b + if self.chan_b: + # recB = reshaped_buf[:, :, :, 1] + # magB, phaseB = self, _fit(recB) + raise NotImplementedError('chan b code not complete') + + self.buf_count = 0 + + return magA, phaseA + + def _fit(self, rec): + """ + Applies volts conversion, demodulation fit, low bandpass filter + and integration limits to samples array + + Args: + rec (numpy array): record from alazar to be multiplied + with the software signal, filtered and limited + to integration limits shape = (samples_taken, ) + + Returns: + magnitude (numpy array): shape = (demod_length, records_per_buffer) + phase (numpy array): shape = (demod_length, records_per_buffer) + """ + # convert rec to volts + bps = self.board_info['bits_per_sample'] + if bps == 12: + volt_rec = helpers.sample_to_volt_u12(rec, bps) + else: + logging.warning('sample to volt conversion does not exist for' + ' bps != 12, centered raw samples returned') + volt_rec = rec - np.mean(rec, axis=1) + + # volt_rec to matrix and multiply with demodulation signal matrices + mat_shape = (self._demod_length, self.buffer_num(), self.record_num(), + self.samples_per_record) + volt_rec_mat = np.outer( + np.ones(self._demod_length), volt_rec).reshape(mat_shape) + re_mat = np.multiply(volt_rec_mat, self.cos_mat) + im_mat = np.multiply(volt_rec_mat, self.sin_mat) + + # filter out higher freq component + cutoff = self.get_max_demod_freq() / 10 + if self.filter_settings['filter'] == 0: + re_filtered = helpers.filter_win(re_mat, cutoff, + self.sample_rate, + self.filter_settings['numtaps'], + axis=3) + im_filtered = helpers.filter_win(im_mat, cutoff, + self.sample_rate, + self.filter_settings['numtaps'], + axis=3) + elif self.filter_settings['filter'] == 1: + re_filtered = helpers.filter_ls(re_mat, cutoff, + self.sample_rate, + self.filter_settings['numtaps'], + axis=3) + im_filtered = helpers.filter_ls(im_mat, cutoff, + self.sample_rate, + self.filter_settings['numtaps'], + axis=3) + elif self.filter_settings['filter'] == 2: + re_filtered = re_mat + im_filtered = im_mat + + # apply integration limits + beginning = int(self.int_delay() * self.sample_rate) + end = beginning + int(self.int_time() * self.sample_rate) + + re_limited = re_filtered[:, :, beginning:end] + im_limited = im_filtered[:, :, beginning:end] + + # convert to magnitude and phase + complex_mat = re_limited + im_limited * 1j + magnitude = np.mean(abs(complex_mat), axis=3) + phase = np.mean(np.angle(complex_mat, deg=True), axis=3) + + return magnitude, phase diff --git a/qcodes/instrument_drivers/AlazarTech/rec_buf_controller.py b/qcodes/instrument_drivers/AlazarTech/rec_buf_controller.py deleted file mode 100644 index 65ddb9dea4d7..000000000000 --- a/qcodes/instrument_drivers/AlazarTech/rec_buf_controller.py +++ /dev/null @@ -1,220 +0,0 @@ -from .ATS import AcquisitionController -import numpy as np -from qcodes import Parameter -from scipy import signal - - -class RecBufParam(Parameter): - """ - Hardware controlled parameter class for Alazar acquisition. To be used with - HD_Samples_Controller (tested with ATS9360 board) for return of an array of - sample data from the Alazar, averaged over records and buffers. - """ - - def __init__(self, name, instrument): - super().__init__(name) - self._instrument = instrument - self.acquisitionkwargs = {} - self.names = ('magnitude', 'phase') - self.units = ('', '') - self.setpoint_names = (('rec_num', 'buf_num'), ('rec_num', 'buf_num')) - self.setpoints = ((1, 1), (1, 1)) - self.shapes = ((1, 1), (1, 1)) - - def update_acquisition_kwargs(self, **kwargs): - # needed to update config of the software parameter on sweep change - # freq setpoints tuple as needs to be hashable for look up - if 'records_per_buffer' and 'buffers_per_acquisition' in kwargs: - rpts = kwargs['records_per_buffer'] - bpts = kwargs['buffers_per_acquisition'] - r = tuple(np.arange(rpts)) - b = tuple(np.arange(bpts)) - self.setpoints = ((r, b), (r, b)) - self.shapes = ((rpts, bpts), (rpts, bpts)) - else: - raise ValueError( - 'records_per_buffer and buffers_per_acquisition must be specified') - # updates dict to be used in acquisition get call - self.acquisitionkwargs.update(**kwargs) - - def get(self): - mag, phase = self._instrument._get_alazar().acquire( - acquisition_controller=self._instrument, - **self.acquisitionkwargs) - return mag, phase - - -class HD_RecBuf_Controller(AcquisitionController): - """ - This is the Acquisition Controller class which works with the ATS9360, - averaging over buffers and records and demodulating with a software - reference signal, returning the samples. - args: - name: name for this acquisition_conroller as an instrument - alazar_name: the name of the alazar instrument such that this controller - can communicate with the Alazar - demod_freq: the frequency of the software wave to be created - samp_rate: the rate of sampling - filt: the filter to be used to filter out double freq component - chan_b: whether there is also a second channel of data to be processed - and returned - **kwargs: kwargs are forwarded to the Instrument base class - - TODO(nataliejpg) fix sample rate problem - TODO(nataliejpg) test filter options - TODO(nataliejpg) test mag phase logic - TODO(nataliejpg) finish implementation of channel b option - TODO(nataliejpg) make filter settings not hard coded - """ - - def __init__(self, name, alazar_name, demod_freq, samp_rate=500e6, - filt='win', chan_b=False, **kwargs): - filter_dict = {'win': 0, 'hamming': 1, 'ls': 2} - self.demodulation_frequency = demod_freq - self.sample_rate = samp_rate - self.filter = filter_dict[filt] - self.chan_b = chan_b - self.samples_per_record = 0 - self.records_per_buffer = 0 - self.buffers_per_acquisition = 0 - self.number_of_channels = 2 - self.cos_list = None - self.sin_list = None - self.buffer = None - self.buf_count = 0 - # make a call to the parent class and by extension, - # create the parameter structure of this class - super().__init__(name, alazar_name, **kwargs) - - self.add_parameter(name='acquisition', - parameter_class=RecBufParam) - - def update_acquisitionkwargs(self, **kwargs): - """ - This method must be used to update the kwargs used for the acquisition - with the alazar_driver.acquire - :param kwargs: - :return: - """ - self.acquisition.update_acquisition_kwargs(**kwargs) - - def pre_start_capture(self): - """ - See AcquisitionController - :return: - """ - alazar = self._get_alazar() - self.samples_per_record = alazar.samples_per_record.get() - self.records_per_buffer = alazar.records_per_buffer.get() - self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() - self.buf_count = 0 - self.samples_per_buffer = (self.samples_per_record * - self.records_per_buffer * - self.buffers_per_acquisition * - self.number_of_channels) - self.buffer = np.zeros(self.samples_per_buffer) - - integer_list = np.arange(self.samples_per_record) - angle_list = (2 * np.pi * self.demodulation_frequency / - self.sample_rate * integer_list) - - cos_list = np.cos(angle_list) - sin_list = np.sin(angle_list) - self.cos_mat = np.kron(np.ones((1, self.records_per_buffer)), cos_list) - self.sin_mat = np.kron(np.ones((1, self.records_per_buffer)), sin_list) - - def pre_acquire(self): - """ - See AcquisitionController - :return: - """ - # this could be used to start an Arbitrary Waveform Generator, etc... - # using this method ensures that the contents are executed AFTER the - # Alazar card starts listening for a trigger pulse - pass - - def handle_buffer(self, data): - """ - See AcquisitionController - :return: - """ - i0 = self.bufcount * self.samples_per_buffer - i1 = i0 + self.samples_per_buffer - self.buffer[i0:i1] = data - self.buf_count += 1 - - def post_acquire(self): - """ - See AcquisitionController - :return: - """ - # for ATS9360 samples are arranged in the buffer as follows: - # S00A, S00B, S01A, S01B...S10A, S10B, S11A, S11B... - # where SXYZ is record X, sample Y, channel Z. - - # reshapes data to be (samples * records * buffers) - - # TODO!! - - magA, phaseA = 0, 0 - - return magA, phaseA - - def fit(self, rec): - # center rec around 0 - rec = rec - np.mean(rec) - - # multiply with software wave - re_wave = np.multiply(rec, self.cos_mat) - im_wave = np.multiply(rec, self.sin_mat) - cutoff = self.demodulation_frequency - numtaps = 30 - axis = 0 - - # filter out double freq component to obtian constant term - if self.filter == 0: - RePart = self.filter_win(re_wave, numtaps, cutoff, axis=axis) - ImPart = self.filter_win(im_wave, numtaps, cutoff, axis=axis) - elif self.filter == 1: - RePart = self.filter_hamming(re_wave, numtaps, cutoff, axis=axis) - ImPart = self.filter_hamming(im_wave, numtaps, cutoff, axis=axis) - elif self.filter == 2: - RePart = self.filter_ls(re_wave, numtaps, cutoff, axis, axis=axis) - ImPart = self.filter_ls(im_wave, numtaps, cutoff, axis, axis=axis) - - # convert to magnitude and phase data and average over samples - # data returned is (records * buffers) - complex_mat = RePart + ImPart * 1j - mag = np.mean(2 * abs(complex_mat), axis=0) - phase = np.mean(np.angle(complex_mat, axis=0, deg=True)) - - return mag, phase - - def filter_hamming(self, rec, numtaps, cutoff, axis=-1): - sample_rate = self.sample_rate - nyq_rate = sample_rate / 2. - fir_coef = signal.firwin(numtaps, - cutoff / nyq_rate, - window="hamming") - filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec, axis=axis) - return filtered_rec - - def filter_win(self, rec, numtaps, cutoff, axis=-1): - sample_rate = self.sample_rate - nyq_rate = sample_rate / 2. - fir_coef = signal.firwin(numtaps, - cutoff / nyq_rate) - filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec, axis=axis) - return filtered_rec - - def filter_ls(self, rec, numtaps, cutoff, axis=-1): - sample_rate = self.sample_rate - nyq_rate = sample_rate / 2. - bands = [0, cutoff / nyq_rate, cutoff / nyq_rate, 1] - desired = [1, 1, 0, 0] - fir_coef = signal.firls(numtaps, - bands, - desired, - nyq=nyq_rate) - filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec, axis=axis) - return filtered_rec diff --git a/qcodes/instrument_drivers/AlazarTech/rec_controller.py b/qcodes/instrument_drivers/AlazarTech/rec_controller.py index a10629a00ecf..1027bf5eb3e0 100644 --- a/qcodes/instrument_drivers/AlazarTech/rec_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/rec_controller.py @@ -80,15 +80,11 @@ class RecordsAcqParam(Parameter): Args: name: name for this parameter instrument: acquisition controller instrument this parameter belongs to - demod_length: numer of demodulation frequencies the acq controller has - NB this is currently set in acq controller init but that's really - not nice and should be changed when possible TODO(nataliejpg) setpoints (including names and units) - TODO(nataliejpg) convert records setpoint into variable/param """ - def __init__(self, name, instrument, demod_length): + def __init__(self, name, instrument): super().__init__(name) self._instrument = instrument self.acquisition_kwargs = {} @@ -100,7 +96,7 @@ def update_sweep(self, npts, start=None, stop=None): when this is fixed) Args: - npts: number of recornds returned after processing + npts: number of records returned start (optional): start value of records returned (if relevant) stop (optional): stop value of records returned (if relevant) """ @@ -173,7 +169,7 @@ class HD_Records_Controller(AcquisitionController): TODO(nataliejpg) what should be private? TODO(nataliejpg) where should filter_dict live? TODO(nataliejpg) demod_freq should be changeable number: maybe channels - TODO(nataliejpg) make records a parameter or similar (MultiParam?) + TODO(nataliejpg) make record param 'start' and 'stop' meaningful """ filter_dict = {'win': 0, 'ls': 1, 'ave': 2} @@ -186,12 +182,10 @@ def __init__(self, name, alazar_name, demod_length=1, filter='win', self._demod_length = demod_length self.number_of_channels = 2 self.samples_per_record = None - self.records_per_buffer = None self.sample_rate = None super().__init__(name, alazar_name, **kwargs) self.add_parameter(name='acquisition', - demod_length=self._demod_length, parameter_class=RecordsAcqParam) for i in range(demod_length): self.add_parameter(name='demod_freq_{}'.format(i), @@ -205,6 +199,9 @@ def __init__(self, name, alazar_name, demod_length=1, filter='win', check_and_update_fn=self._update_int_delay, default_fn=self._int_delay_default, parameter_class=AcqVariablesParam) + self.add_parameter(name='record_num', + check_and_update_fn=self._update_rec_num, + parameter_class=AcqVariablesParam) self.samples_divisor = self._get_alazar().samples_divisor @@ -252,10 +249,37 @@ def _update_demod_freq(instr, value, param_name=None): demod_freqs[current_demod_index] = value instr.acquisition.update_demod_setpoints(demod_freqs) + def _update_record_num(instr, value, **kwargs): + """ + Function to update the record number, and instr attributes. Main + reason to record_num as a parameter is so we can more easily push the + record number setting up to other instruments which will control this. + + Args: + value to be validated and used for instrument attribute update + + Checks: + 1 <= value <= 1000 + + Sets: + acquisition_kwarg['records_per_buffer'] of acquisition param + setpoints of acquisiton param + shape of acquisition param + """ + if (value is None) or not (1 <= value <= 1000): + raise ValueError('int_time must be 1 <= value <= 1000') + + # update acquisition parameter shapes + instr.acquisition.update_sweep(value) + + # update acquision kwargs + instr.acquisition.acquisition_kwargs.update( + records_per_buffer=value) + def _update_int_time(instr, value, **kwargs): """ Function to validate value for int_time before setting parameter - value + value and update instr attributes. Args: value to be validated and used for instrument attribute update @@ -300,7 +324,7 @@ def _update_int_time(instr, value, **kwargs): def _update_int_delay(instr, value, **kwargs): """ Function to validate value for int_delay before setting parameter - value + value and update instr attributes. Args: value to be validated and used for instrument attribute update @@ -313,7 +337,6 @@ def _update_int_delay(instr, value, **kwargs): sample_rate attr of acq controller to be that of alazar samples_per_record of acq controller acquisition_kwarg['samples_per_record'] of acquisition param - setpoints of acquisiton param """ if (value is None) or not (0 <= value <= 0.1): raise ValueError('int_delay must be 0 <= value <= 1') @@ -407,23 +430,25 @@ def update_acquisition_kwargs(self, **kwargs): """ Updates the kwargs to be used when alazar_driver.acquisition() is called via a get call of the - acquisition SamplesParam. Should be used by the user for + acquisition RecordsAcqParam. Should be used by the user for updating averaging settings since the 'samples_per_record' - kwarg is updated via the int_time and int_delay parameters + and 'records_per_buffer' kwargs are updated via the int_time, + int_delay and record_num parameters Kwargs (ints): - records_per_buffer buffers_per_acquisition allocated_buffers """ if 'samples_per_record' in kwargs: - raise ValueError('With HD_Samples_Controller ' + raise ValueError('With HD_Records_Controller ' 'samples_per_record cannot be set manually ' 'via update_acquisition_kwargs and should instead' ' be set by setting int_time and int_delay') if 'records_per_buffer' in kwargs: - self.acquisition.update_sweep(kwargs['records_per_buffer']) - self.records_per_buffer = kwargs['records_per_buffer'] + raise ValueError('With HD_Records_Controller ' + 'records_per_buffer cannot be set manually ' + 'via update_acquisition_kwargs and should instead' + ' be set by setting record_num') self.acquisition.acquisition_kwargs.update(**kwargs) def pre_start_capture(self): @@ -440,11 +465,10 @@ def pre_start_capture(self): raise Exception('acq controller sample rate does not match ' 'instrument value, most likely need ' 'to set and check int_time and int_delay') - if self.records_per_buffer != alazar.records_per_buffer.get(): - raise Exception('acq controller records per buffer does not match ' + if self.record_num() != alazar.records_per_buffer.get(): + raise Exception('acq controller record_num does not match ' 'instrument value, most likely need ' - 'to call update_acquisition_kwargs with' - 'records_per_buffer as a param') + 'to call set and check record_num') demod_freqs = self.get_demod_freqs() if len(demod_freqs) == 0: @@ -453,13 +477,13 @@ def pre_start_capture(self): self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() self.board_info = alazar.get_idn() self.buffer = np.zeros(self.samples_per_record * - self.records_per_buffer * + self.record_num() * self.number_of_channels) - mat_shape = (self._demod_length, self.records_per_buffer, + mat_shape = (self._demod_length, self.record_num(), self.samples_per_record) integer_list = np.arange(self.samples_per_record) - integer_mat = np.outer(np.ones(self.records_per_buffer), integer_list) + integer_mat = np.outer(np.ones(self.record_num()), integer_list) angle_mat = 2 * np.pi * \ np.outer(demod_freqs, integer_mat).reshape( mat_shape) / self.sample_rate @@ -490,9 +514,9 @@ def post_acquire(self): # where SXYZ is record X, sample Y, channel Z. # break buffer up into records and shapes to be (records, samples) - recordsA = np.empty((self.records_per_buffer, self.samples_per_record), + recordsA = np.empty((self.record_num(), self.samples_per_record), dtype=np.uint16) - for i in range(self.records_per_buffer): + for i in range(self.record_num()): i0 = (i * self.samples_per_record * self.number_of_channels) i1 = (i0 + self.samples_per_record * self.number_of_channels) recordsA[i, :] = np.uint16( @@ -532,7 +556,7 @@ def _fit(self, rec): volt_rec = rec - np.mean(rec, axis=1) # volt_rec to matrix and multiply with demodulation signal matrices - mat_shape = (self._demod_length, self.records_per_buffer, + mat_shape = (self._demod_length, self.record_num(), self.samples_per_record) volt_rec_mat = np.outer( np.ones(self._demod_length), volt_rec).reshape(mat_shape) diff --git a/qcodes/instrument_drivers/AlazarTech/rec_samp_controller.py b/qcodes/instrument_drivers/AlazarTech/rec_samp_controller.py index 7e86e9ffc211..40b729965915 100644 --- a/qcodes/instrument_drivers/AlazarTech/rec_samp_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/rec_samp_controller.py @@ -1,233 +1,650 @@ +import logging from .ATS import AcquisitionController import numpy as np from qcodes import Parameter -from scipy import signal +import qcodes.instrument_drivers.AlazarTech.acq_helpers as helpers -class RecSampParam(Parameter): +class AcqVariablesParam(Parameter): """ - Hardware controlled parameter class for Alazar acquisition. To be used with - HD_Samples_Controller (tested with ATS9360 board) for return of an array of - sample data from the Alazar, averaged over records and buffers. + Parameter of an AcquisitionController which has a _check_and_update_instr + function used for validation and to update instrument attributes and a + _get_default function which it uses to set the AcqVariablesParam to an + instrument caluclated default. - TODO(nataliejpg) fix setpoints/shapes horriblenesss - TODO(nataliejpg) make it actually work... + Args: + name: name for this parameter + instrument: acquisition controller instrument this parameter belongs to + check_and_update_fn: instrument function to be used for value + validation and updating instrument values + default_fn (optional): instrument function to be used to calculate + a default value to set parameter to + initial_value (optional): initial value for parameter + """ + + def __init__(self, name, instrument, check_and_update_fn, + default_fn=None, initial_value=None): + super().__init__(name) + self._instrument = instrument + self._save_val(initial_value) + setattr(self, '_check_and_update_instr', check_and_update_fn) + if default_fn is not None: + setattr(self, '_get_default', default_fn) + + def set(self, value): + """ + Function which checks value using validation function and then sets + the Parameter value to this value. + + Args: + value: value to set the parameter to + """ + self._check_and_update_instr(value, param_name=self.name) + self._save_val(value) + + def get(self): + return self._latest()['value'] + + def to_default(self): + """ + Function which executes the default_fn specified to calculate the + default value based on instrument values and then calls the set + function with this value + """ + try: + default = self._get_default() + except AttributeError as e: + raise AttributeError('no default function for {} Parameter ' + '{}'.format(self.name, e)) + self.set(default) + + def check(self): + """ + Function which checks the current Parameter value using the specified + check_and_update_fn which can also serve to update instrument values. + + Return: + True (if no errors raised when check_and_update_fn executed) + """ + val = self._latest()['value'] + self._check_and_update_instr(val, param_name=self.name) + return True + + +class RecordsSamplesAcqParam(Parameter): + """ + TODO + + Args: + name: name for this parameter + instrument: acquisition controller instrument this parameter belongs to + demod_length: numer of demodulation frequencies the acq controller has + NB this is currently set in acq controller init but that's really + not nice and should be changed when possible + + TODO(nataliejpg) setpoints (including names and units) + TODO(nataliejpg) convert records setpoint into actual frequency """ def __init__(self, name, instrument): super().__init__(name) self._instrument = instrument - self.acquisitionkwargs = {} + self.acquisition_kwargs = {} self.names = ('magnitude', 'phase') - self.units = ('', '') - self.setpoint_names = (('rec_num', 'samp_num'), - ('rec_num', 'samp_num')) - self.setpoints = ((1, 1), (1, 1)) - self.shapes = ((1, 1), (1, 1)) - def update_acquisition_kwargs(self, **kwargs): - # needed to update config of the software parameter on sweep change - # freq setpoints tuple as needs to be hashable for look up - if 'samples_per_record' and 'records_per_buffer' in kwargs: - spts = kwargs['samples_per_record'] - rpts = kwargs['records_per_buffer'] - s = tuple(np.arange(spts)) - r = tuple(np.arange(rpts)) - self.setpoints = ((s, r), (s, r)) - self.shapes = ((spts, rpts), (spts, rpts)) + def update_time_sweep(self, time_npts, time_start, time_stop): + """ + Function which updates the shape of the parameter (and it's setpoints + when this is fixed) + + Args: + time_npts: number of samples returned after processing + time_start: start time of samples returned after processing + time_stop: stop time of samples returned after processing + """ + demod_length = self._instrument._demod_length + # self._time_list = tuple(np.linspace(time_start, + # time_stop, num=time_npts)) + self._time_npts = time_npts + if demod_length > 1: + # demod_freqs = self._instrument.get_demod_freqs() + # self.setpoints = ((demod_freqs, self._rec_list, self._time_list), + # (demod_freqs, self._rec_list, self._time_list)) + self.shapes = ((demod_length, self._rec_npts, self._time_npts), + (demod_length, self._rec_npts, self._time_npts)) else: - raise ValueError( - 'records_per_buffer and samples_per_record must be specified') - # updates dict to be used in acquisition get call - self.acquisitionkwargs.update(**kwargs) + self.shapes = ((self._rec_npts, self._time_npts), + (self._rec_npts, self._time_npts)) + # self.setpoints = ((self._rec_list, self._time_list), + # (self._rec_list, self._time_list)) + + def update_rec_sweep(self, rec_npts, rec_start=None, rec_stop=None): + """ + Function which updates the shape of the parameter (and it's setpoints + when this is fixed) + + Args: + rec_npts: number of records returned + rec_start (optional): start value of records returned + rec_stop (optional): stop value of records returned + """ + demod_length = self._instrument._demod_length + # self._rec_list = tuple(np.linspace(rec_start, + # rec_stop, num=rec_npts)) + self._rec_npts = rec_npts + if demod_length > 1: + # demod_freqs = self._instrument.get_demod_freqs() + # self.setpoints = ((demod_freqs, self._rec_list, self._time_list), + # (demod_freqs, self._rec_list, self._time_list)) + self.shapes = ((demod_length, self._rec_npts, self._time_npts), + (demod_length, self._rec_npts, self._time_npts)) + else: + self.shapes = ((self._rec_npts, self._time_npts), + (self._rec_npts, self._time_npts)) + # self.setpoints = ((self._rec_list, self._time_list), + # (self._rec_list, self._time_list)) + + def update_demod_setpoints(self, demod_freqs): + """ + Function to update the demodulation frequency setpoints to be called + when a demod_freq Parameter of the acq controller is updated + + Args: + demod_freqs: numpy array of demodulation frequencies to use as + setpoints if length > 1 + """ + demod_length = self._instrument._demod_length + if demod_length > 1: + pass + # self.setpoints = ((demod_freqs, self._rec_list, self._time_list), + # (demod_freqs, self._rec_list, self._time_list)) + else: + pass def get(self): + """ + Gets the magnitude and phase signal by calling acquire + on the alazar (which in turn calls the processing functions of the + aqcuisition controller before returning the processed data + demodulated at specified frequencies and averaged over buffers) + + Returns: + mag: numpy array of magnitude, shape (demod_length, records) + phase: numpy array of magnitude, shape (demod_length, records) + """ mag, phase = self._instrument._get_alazar().acquire( acquisition_controller=self._instrument, - **self.acquisitionkwargs) + **self.acquisition_kwargs) return mag, phase -class HD_RecSamp_Controller(AcquisitionController): +class HD_RecordsSamples_Controller(AcquisitionController): """ This is the Acquisition Controller class which works with the ATS9360, - averaging over buffers and records and demodulating with a software - reference signal, returning the samples. - args: - name: name for this acquisition_conroller as an instrument - alazar_name: the name of the alazar instrument such that this controller - can communicate with the Alazar - demod_freq: the frequency of the software wave to be created - samp_rate: the rate of sampling - filt: the filter to be used to filter out double freq component - chan_b: whether there is also a second channel of data to be processed - and returned - **kwargs: kwargs are forwarded to the Instrument base class - - TODO(nataliejpg) fix sample rate problem + averaging over buffers and demodulating with software reference signal(s). + + Args: + name: name for this acquisition_conroller as an instrument + alazar_name: name of the alazar instrument such that this + controller can communicate with the Alazar + demod_length (default 1): number of demodulation frequencies + filter (default 'win'): filter to be used to filter out double freq + component ('win' - window, 'ls' - least squared, 'ave' - averaging) + numtaps (default 101): number of freq components used in filter + chan_b (default False): whether there is also a second channel of data + to be processed and returned + **kwargs: kwargs are forwarded to the Instrument base class + TODO(nataliejpg) test filter options - TODO(nataliejpg) test mag phase logic TODO(nataliejpg) finish implementation of channel b option - TODO(nataliejpg) make filter settings not hard coded + TODO(nataliejpg) what should be private? + TODO(nataliejpg) where should filter_dict live? + TODO(nataliejpg) demod_freq should be changeable number: maybe channels + TODO(nataliejpg) make record param 'start' and 'stop' meaningful """ - def __init__(self, name, alazar_name, demod_freq, samp_rate=500e6, - filt='win', chan_b=False, **kwargs): - filter_dict = {'win': 0, 'hamming': 1, 'ls': 2} - self.demodulation_frequency = demod_freq - self.sample_rate = samp_rate - self.filter = filter_dict[filt] + filter_dict = {'win': 0, 'ls': 1, 'ave': 2} + + def __init__(self, name, alazar_name, demod_length=1, filter='win', + numtaps=101, chan_b=False, **kwargs): + self.filter_settings = {'filter': self.filter_dict[filter], + 'numtaps': numtaps} self.chan_b = chan_b - self.samples_per_record = 0 - self.records_per_buffer = 0 - self.buffers_per_acquisition = 0 + self._demod_length = demod_length self.number_of_channels = 2 - self.cos_list = None - self.sin_list = None - self.buffer = None - # make a call to the parent class and by extension, - # create the parameter structure of this class + self.samples_per_record = None + self.sample_rate = None super().__init__(name, alazar_name, **kwargs) self.add_parameter(name='acquisition', - parameter_class=RecSampParam) + parameter_class=RecordsSamplesAcqParam) + for i in range(demod_length): + self.add_parameter(name='demod_freq_{}'.format(i), + check_and_update_fn=self._update_demod_freq, + parameter_class=AcqVariablesParam) + self.add_parameter(name='int_time', + check_and_update_fn=self._update_int_time, + default_fn=self._int_time_default, + parameter_class=AcqVariablesParam) + self.add_parameter(name='int_delay', + check_and_update_fn=self._update_int_delay, + default_fn=self._int_delay_default, + parameter_class=AcqVariablesParam) + self.add_parameter(name='record_num', + check_and_update_fn=self._update_rec_num, + parameter_class=AcqVariablesParam) - def update_acquisitionkwargs(self, **kwargs): + self.samples_divisor = self._get_alazar().samples_divisor + + def _update_demod_freq(instr, value, param_name=None): """ - This method must be used to update the kwargs used for the acquisition - with the alazar_driver.acquire - :param kwargs: - :return: + Function to validate and update acquisiton parameter when + a demod_freq_ Parameter is changed + + Args: + value to update demodulation frequency to + + Kwargs: + param_name: used to update demod_freq list used for updating + septionts of acquisition parameter + + Checks: + 1e6 <= value <= 500e6 + number of oscilation measured using current int_tiume param value + at this demod frequency value + oversampling rate for this demodulation frequency + + Sets: + sample_rate attr of acq controller to be that of alazar + setpoints of acquisiton parameter + """ + if (value is None) or not (1e6 <= value <= 500e6): + raise ValueError('demod_freqs must be 1e6 <= value <= 500e6') + alazar = instr._get_alazar() + instr.sample_rate = alazar.get_sample_rate() + min_oscilations_measured = instr.int_time() * value + oversampling = instr.sample_rate / (2 * value) + if min_oscilations_measured < 10: + logging.warning('{} oscilations measured for largest ' + 'demod freq, recommend at least 10: ' + 'decrease sampling rate, take ' + 'more samples or increase demodulation ' + 'freq'.format(min_oscilations_measured)) + elif oversampling < 1: + logging.warning('oversampling rate is {}, recommend > 1: ' + 'increase sampling rate or decrease ' + 'demodulation frequency'.format(oversampling)) + demod_freqs = instr.get_demod_freqs() + current_demod_index = ([int(s) for s in param_name.split() + if s.isdigit()][0]) + demod_freqs[current_demod_index] = value + instr.acquisition.update_demod_setpoints(demod_freqs) + + def _update_record_num(instr, value, **kwargs): + """ + Function to update the record number, and instr attributes. Main + reason to record_num as a parameter is so we can more easily push the + record number setting up to other instruments which will control this. + + Args: + value to be validated and used for instrument attribute update + + Checks: + 1 <= value <= 1000 + + Sets: + acquisition_kwarg['records_per_buffer'] of acquisition param + setpoints of acquisiton param + shape of acquisition param """ - self.acquisition.update_acquisition_kwargs(**kwargs) + if (value is None) or not (1 <= value <= 1000): + raise ValueError('int_time must be 1 <= value <= 1000') + + # update acquisition parameter shapes + instr.acquisition.update_rec_sweep(value) + + # update acquision kwargs + instr.acquisition.acquisition_kwargs.update( + records_per_buffer=value) + + def _update_int_time(instr, value, **kwargs): + """ + Function to validate value for int_time before setting parameter + value and update instr attributes. + + Args: + value to be validated and used for instrument attribute update + + Checks: + 0 <= value <= 0.1 seconds + number of oscilation measured in this time + oversampling rate + + Sets: + sample_rate attr of acq controller to be that of alazar + samples_per_record of acq controller + acquisition_kwarg['samples_per_record'] of acquisition param + setpoints of acquisiton param + shape of acquisition param + """ + if (value is None) or not (0 <= value <= 0.1): + raise ValueError('int_time must be 0 <= value <= 1') + alazar = instr._get_alazar() + instr.sample_rate = alazar.get_sample_rate() + if instr.get_max_demod_freq() is not None: + oscilations_measured = value * instr.get_max_demod_freq() + oversampling = instr.sample_rate / (2 * instr.get_max_demod_freq()) + if oscilations_measured < 10: + logging.warning('{} oscilations measured, recommend at ' + 'least 10: decrease sampling rate, take ' + 'more samples or increase demodulation ' + 'freq'.format(oscilations_measured)) + elif oversampling < 1: + logging.warning('oversampling rate is {}, recommend > 1: ' + 'increase sampling rate or decrease ' + 'demodulation frequency'.format(oversampling)) + if instr.int_delay() is None: + instr.int_delay.to_default() + + # update acquisition parameter shapes + start = instr.int_delay() + stop = start + value + npts = int(value * instr.sample_rate) + instr.acquisition.update_time_sweep(start, stop, npts) + + # update acquision kwargs and acq controller value + total_time = value + instr.int_delay() + samples_needed = total_time * instr.sample_rate + instr.samples_per_record = helpers.roundup( + samples_needed, instr.samples_divisor) + instr.acquisition.acquisition_kwargs.update( + samples_per_record=instr.samples_per_record) + + def _update_int_delay(instr, value, **kwargs): + """ + Function to validate value for int_delay before setting parameter + value and update instr attributes. + + Args: + value to be validated and used for instrument attribute update + + Checks: + 0 <= value <= 0.1 seconds + number of samples discarded >= numtaps + + Sets: + sample_rate attr of acq controller to be that of alazar + samples_per_record of acq controller + acquisition_kwarg['samples_per_record'] of acquisition param + setpoints of acquisiton param + shape of acquisition param + """ + if (value is None) or not (0 <= value <= 0.1): + raise ValueError('int_delay must be 0 <= value <= 1') + alazar = instr._get_alazar() + instr.sample_rate = alazar.get_sample_rate() + samples_delay_min = (instr.filter_settings['numtaps'] - 1) + int_delay_min = samples_delay_min / instr.sample_rate + if value < int_delay_min: + logging.warning( + 'delay is less than recommended for filter choice: ' + '(expect delay >= {})'.format(int_delay_min)) + + # update acquisition parameter shapes + start = value + stop = start + (instr.int_time() or 0) + npts = int((instr.int_time() or 0) * instr.sample_rate) + instr.acquisition.update_time_sweep(start, stop, npts) + + # update acquision kwargs and acq controller value + total_time = value + (instr.int_time() or 0) + samples_needed = total_time * instr.sample_rate + instr.samples_per_record = helpers.roundup( + samples_needed, instr.samples_divisor) + instr.acquisition.acquisition_kwargs.update( + samples_per_record=instr.samples_per_record) + + def _int_delay_default(instr): + """ + Function to generate default int_delay value + + Returns: + minimum int_delay recommended for (numtaps - 1) + samples to be discarded as recommended for filter + """ + alazar = instr._get_alazar() + instr.sample_rate = alazar.get_sample_rate() + samp_delay = instr.filter_settings['numtaps'] - 1 + return samp_delay / instr.sample_rate + + def _int_time_default(instr): + """ + Function to generate defult int_time value + + Returns: + max total time for integration based on samples_per_record, + sample_rate and int_delay + """ + if instr.samples_per_record is (0 or None): + raise ValueError('Cannot set int_time to max if acq controller' + ' has 0 or None samples_per_record, choose a ' + 'value for int_time and samples_per_record will ' + 'be set accordingly') + alazar = instr._get_alazar() + instr.sample_rate = alazar.get_sample_rate() + total_time = ((instr.samples_per_record / instr.sample_rate) - + (instr.int_delay() or 0)) + return total_time + + def get_demod_freqs(self): + """ + Function to get all the demod_freq parameter values in a list, v hacky + + Returns: + freqs: numpy array of demodulation frequencies + """ + freqs = list(filter(None, [getattr(self, 'demod_freq_{}'.format(c))() + for c in range(self._demod_length)])) + return np.array(freqs) + + def get_max_demod_freq(self): + """ + Returns: + the largest demodulation frequency + + nb: really hacky and we should have channels in qcodes but we don't + (at time of writing) + """ + freqs = self.get_demod_freqs() + if len(freqs) > 0: + return max(freqs) + else: + return None + + def update_filter_settings(self, filter, numtaps): + """ + Updates the settings of the filter for filtering out + double frwuency component for demodulation. + + Args: + filter (str): filter type ('win' or 'ls') + numtaps (int): numtaps for filter + """ + self.filter_settings.update({'filter': self.filter_dict[filter], + 'numtaps': numtaps}) + + def update_acquisition_kwargs(self, **kwargs): + """ + Updates the kwargs to be used when + alazar_driver.acquisition() is called via a get call of the + acquisition RecordsSamplesAcqParam. Should be used by the user for + updating averaging settings since the 'samples_per_record' + and 'records_per_buffer' kwargs are updated via the int_time, + int_delay and record_num parameters + + Kwargs (ints): + buffers_per_acquisition + allocated_buffers + """ + if 'samples_per_record' in kwargs: + raise ValueError('With HD_RecordsSamples_Controller ' + 'samples_per_record cannot be set manually ' + 'via update_acquisition_kwargs and should instead' + ' be set by setting int_time and int_delay') + if 'records_per_buffer' in kwargs: + raise ValueError('With HD_RecordsSamples_Controller ' + 'records_per_buffer cannot be set manually ' + 'via update_acquisition_kwargs and should instead' + ' be set by setting record_num') + self.acquisition.acquisition_kwargs.update(**kwargs) def pre_start_capture(self): """ - See AcquisitionController - :return: + Called before capture start to update Acquisition Controller with + alazar acquisition params and set up software wave for demodulation. """ alazar = self._get_alazar() - self.samples_per_record = alazar.samples_per_record.get() - self.records_per_buffer = alazar.records_per_buffer.get() + if self.samples_per_record != alazar.samples_per_record.get(): + raise Exception('acq controller samples per record does not match' + ' instrument value, most likely need ' + 'to set and check int_time and int_delay') + if self.sample_rate != alazar.get_sample_rate(): + raise Exception('acq controller sample rate does not match ' + 'instrument value, most likely need ' + 'to set and check int_time and int_delay') + if self.record_num() != alazar.records_per_buffer.get(): + raise Exception('acq controller records per buffer does not match ' + 'instrument value, most likely need ' + 'to call update_acquisition_kwargs with' + 'records_per_buffer as a param') + + demod_freqs = self.get_demod_freqs() + if len(demod_freqs) == 0: + raise Exception('no demod_freqs set') + self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() + self.board_info = alazar.get_idn() self.buffer = np.zeros(self.samples_per_record * - self.records_per_buffer * + self.record_num() * self.number_of_channels) + mat_shape = (self._demod_length, self.record_num(), + self.samples_per_record) integer_list = np.arange(self.samples_per_record) - angle_list = (2 * np.pi * self.demodulation_frequency / - self.sample_rate * integer_list) - - cos_list = np.cos(angle_list).reshape(self.samples_per_record, 1) - sin_list = np.sin(angle_list).reshape(self.samples_per_record, 1) - self.cos_mat = np.kron(np.ones((1, self.records_per_buffer)), cos_list) - self.sin_mat = np.kron(np.ones((1, self.records_per_buffer)), sin_list) + integer_mat = np.outer(np.ones(self.record_num()), integer_list) + angle_mat = 2 * np.pi * \ + np.outer(demod_freqs, integer_mat).reshape( + mat_shape) / self.sample_rate + self.cos_mat = np.cos(angle_mat) + self.sin_mat = np.sin(angle_mat) def pre_acquire(self): - """ - See AcquisitionController - :return: - """ - # this could be used to start an Arbitrary Waveform Generator, etc... - # using this method ensures that the contents are executed AFTER the - # Alazar card starts listening for a trigger pulse pass def handle_buffer(self, data): """ - See AcquisitionController - :return: + Adds data from alazar to buffer (effectively averaging) """ - # average over buffers self.buffer += data def post_acquire(self): """ - See AcquisitionController - :return: - """ + Processes the data according to ATS9360 settings, splitting into + records and then applying demodulation fit + nb: currently only channel A + Returns: + magnitude (numpy array): shape = (demod_length, records_per_buffer) + phase (numpy array): shape = (demod_length, records_per_buffer + """ # for ATS9360 samples are arranged in the buffer as follows: # S00A, S00B, S01A, S01B...S10A, S10B, S11A, S11B... # where SXYZ is record X, sample Y, channel Z. - # reshapes date to be (samples * records) - recordA = np.zeros((self.samples_per_record, self.records_per_buffer)) - for i in range(self.records_per_buffer): - i0 = i * self.number_of_channels * self.samples_per_record - i1 = i0 + self.number_of_channels * self.samples_per_record - recordA[:, i] = (self.buffer[i0:i1:self.number_of_channels] / - self.buffers_per_acquisition) - - # return averaged chan A data (records) - magA, phaseA = self.fit(recordA) - - # same for B - # if self.chan_b: - # recordB = np.zeros( - # (self.samples_per_record, self.records_per_buffer)) - # for i in self.records_per_buffer: - # recordB[i, :] = self.buffer[1:full_rec_length:step] / averaging - # magB, phaseB = self.fit(recordB) - - # return data (samples * records) + # break buffer up into records and shapes to be (records, samples) + recordsA = np.empty((self.record_num(), self.samples_per_record), + dtype=np.uint16) + for i in range(self.record_num()): + i0 = (i * self.samples_per_record * self.number_of_channels) + i1 = (i0 + self.samples_per_record * self.number_of_channels) + recordsA[i, :] = np.uint16( + self.buffer[i0:i1:self.number_of_channels] / + self.buffers_per_acquisition) + + # do demodulation + magA, phaseA = self._fit(recordsA) + + # same for chan b + if self.chan_b: + raise NotImplementedError('chan b code not complete') + return magA, phaseA - def fit(self, rec): - # center rec around 0 - rec = rec - np.mean(rec) - - # multiply with software wave - re_wave = np.multiply(rec, self.cos_mat) - im_wave = np.multiply(rec, self.sin_mat) - cutoff = self.demodulation_frequency - numtaps = 30 - axis = 0 - - # filter out double freq component to obtian constant term - if self.filter == 0: - RePart = self.filter_win(re_wave, numtaps, cutoff, axis=axis) - ImPart = self.filter_win(im_wave, numtaps, cutoff, axis=axis) - elif self.filter == 1: - RePart = self.filter_hamming(re_wave, numtaps, cutoff, axis=axis) - ImPart = self.filter_hamming(im_wave, numtaps, cutoff, axis=axis) - elif self.filter == 2: - RePart = self.filter_ls(re_wave, numtaps, cutoff, axis, axis=axis) - ImPart = self.filter_ls(im_wave, numtaps, cutoff, axis, axis=axis) - - # convert to magnitude and phase data - # data returned is (samples * records) - complex_num = RePart + ImPart * 1j - mag = 2 * abs(complex_num) - phase = np.angle(complex_num, deg=True) + def _fit(self, rec): + """ + Applies volts conversion, demodulation fit, low bandpass filter + and integration limits to samples array - return mag, phase + Args: + rec (numpy array): record from alazar to be multiplied + with the software signal, filtered and limited + to integration limits shape = (samples_taken, ) + + Returns: + magnitude (numpy array): shape = (demod_length, records_per_buffer) + phase (numpy array): shape = (demod_length, records_per_buffer) + """ + # convert rec to volts + bps = self.board_info['bits_per_sample'] + if bps == 12: + volt_rec = helpers.sample_to_volt_u12(rec, bps) + else: + logging.warning('sample to volt conversion does not exist for' + ' bps != 12, centered raw samples returned') + volt_rec = rec - np.mean(rec, axis=1) + + # volt_rec to matrix and multiply with demodulation signal matrices + mat_shape = (self._demod_length, self.record_num, + self.samples_per_record) + volt_rec_mat = np.outer( + np.ones(self._demod_length), volt_rec).reshape(mat_shape) + re_mat = np.multiply(volt_rec_mat, self.cos_mat) + im_mat = np.multiply(volt_rec_mat, self.sin_mat) + + # filter out higher freq component + cutoff = self.get_max_demod_freq() / 10 + if self.filter_settings['filter'] == 0: + re_filtered = helpers.filter_win(re_mat, cutoff, + self.sample_rate, + self.filter_settings['numtaps'], + axis=2) + im_filtered = helpers.filter_win(im_mat, cutoff, + self.sample_rate, + self.filter_settings['numtaps'], + axis=2) + elif self.filter_settings['filter'] == 1: + re_filtered = helpers.filter_ls(re_mat, cutoff, + self.sample_rate, + self.filter_settings['numtaps'], + axis=2) + im_filtered = helpers.filter_ls(im_mat, cutoff, + self.sample_rate, + self.filter_settings['numtaps'], + axis=2) + elif self.filter_settings['filter'] == 2: + re_filtered = re_mat + im_filtered = im_mat + + # apply integration limits + beginning = int(self.int_delay() * self.sample_rate) + end = beginning + int(self.int_time() * self.sample_rate) + + re_limited = re_filtered[:, :, beginning:end] + im_limited = im_filtered[:, :, beginning:end] + + # convert to magnitude and phase + complex_mat = re_limited + im_limited * 1j + magnitude = abs(complex_mat) + phase = np.angle(complex_mat, deg=True) - def filter_hamming(self, rec, numtaps, cutoff, axis=-1): - sample_rate = self.sample_rate - nyq_rate = sample_rate / 2. - fir_coef = signal.firwin(numtaps, - cutoff / nyq_rate, - window="hamming") - filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec, axis=axis) - return filtered_rec - - def filter_win(self, rec, numtaps, cutoff, axis=-1): - sample_rate = self.sample_rate - nyq_rate = sample_rate / 2. - fir_coef = signal.firwin(numtaps, - cutoff / nyq_rate) - filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec, axis=axis) - return filtered_rec - - def filter_ls(self, rec, numtaps, cutoff, axis=-1): - sample_rate = self.sample_rate - nyq_rate = sample_rate / 2. - bands = [0, cutoff / nyq_rate, cutoff / nyq_rate, 1] - desired = [1, 1, 0, 0] - fir_coef = signal.firls(numtaps, - bands, - desired, - nyq=nyq_rate) - filtered_rec = 2 * signal.lfilter(fir_coef, 1.0, rec, axis=axis) - return filtered_rec + return magnitude, phase diff --git a/qcodes/instrument_drivers/AlazarTech/samp_controller.py b/qcodes/instrument_drivers/AlazarTech/samp_controller.py index 7f1974eb8f9b..a36382e74ab4 100644 --- a/qcodes/instrument_drivers/AlazarTech/samp_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/samp_controller.py @@ -247,7 +247,7 @@ def _update_demod_freq(instr, value, param_name=None): def _update_int_time(instr, value, **kwargs): """ Function to validate value for int_time before setting parameter - value + value and update instr attributes. Args: value to be validated and used for instrument attribute update @@ -302,7 +302,7 @@ def _update_int_time(instr, value, **kwargs): def _update_int_delay(instr, value, **kwargs): """ Function to validate value for int_delay before setting parameter - value + value and update instr attributes. Args: value to be validated and used for instrument attribute update @@ -345,8 +345,11 @@ def _update_int_delay(instr, value, **kwargs): def _int_delay_default(instr): """ - Returns minimum int_delay recommended for (numtaps - 1) - samples to be discarded as recommended for filter + Function to generate default int_delay value + + Returns: + minimum int_delay recommended for (numtaps - 1) + samples to be discarded as recommended for filter """ alazar = instr._get_alazar() instr.sample_rate = alazar.get_sample_rate() @@ -355,8 +358,11 @@ def _int_delay_default(instr): def _int_time_default(instr): """ - Returns max total time for integration based on samples_per_record, - sample_rate and int_delay + Function to generate defult int_time value + + Returns: + max total time for integration based on samples_per_record, + sample_rate and int_delay """ if instr.samples_per_record is (0 or None): raise ValueError('Cannot set int_time to max if acq controller' @@ -410,7 +416,7 @@ def update_acquisition_kwargs(self, **kwargs): """ Updates the kwargs to be used when alazar_driver.acquisition() is called via a get call of the - acquisition SamplesParam. Should be used by the user for updating + acquisition SamplesAcqParam. Should be used by the user for updating averaging settings since the 'samples_per_record' kwarg is updated via the int_time and int_delay parameters From d8cae492880ffaa3ad628b8298c7318dd4579cce Mon Sep 17 00:00:00 2001 From: Natalie Pearson Date: Wed, 8 Feb 2017 11:21:24 +0100 Subject: [PATCH 102/180] complete rec_samp and buf_rec controllers and change post processing reshape logic in others --- .../AlazarTech/ave_controller.py | 38 ++++++++++------- .../AlazarTech/buf_rec_controller.py | 18 ++++---- .../AlazarTech/rec_controller.py | 41 ++++++++++++------- .../AlazarTech/rec_samp_controller.py | 37 +++++++++++------ .../AlazarTech/samp_controller.py | 37 +++++++++++------ 5 files changed, 108 insertions(+), 63 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/ave_controller.py b/qcodes/instrument_drivers/AlazarTech/ave_controller.py index 7cfa7036cf26..48d593e1db74 100644 --- a/qcodes/instrument_drivers/AlazarTech/ave_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/ave_controller.py @@ -456,19 +456,29 @@ def post_acquire(self): magnitude (numpy array): shape = (demod_length, samples_used) phase (numpy array): shape = (demod_length, samples_used) """ - records_per_acquisition = (self.buffers_per_acquisition * - self.records_per_buffer) + # for ATS9360 samples are arranged in the buffer as follows: # S00A, S00B, S01A, S01B...S10A, S10B, S11A, S11B... # where SXYZ is record X, sample Y, channel Z. # break buffer up into records and averages over them - recA = np.zeros(self.samples_per_record) - for i in range(self.records_per_buffer): - i0 = (i * self.samples_per_record * self.number_of_channels) - i1 = (i0 + self.samples_per_record * self.number_of_channels) - recA += self.buffer[i0:i1:self.number_of_channels] - recordA = np.uint16(recA / records_per_acquisition) + reshaped_buf = self.buffer.reshape(self.records_per_buffer, + self.samples_per_record, + self.number_of_channels) + recordA = np.uint16(np.mean(reshaped_buf[:, :, 0], axis=0) / + self.buffers_per_acquisition) + + # TODO(nataliejpg): test above version works on alazar and + # compare performance + + # records_per_acquisition = (self.buffers_per_acquisition * + # self.records_per_buffer) + # recA = np.zeros(self.samples_per_record) + # for i in range(self.records_per_buffer): + # i0 = (i * self.samples_per_record * self.number_of_channels) + # i1 = (i0 + self.samples_per_record * self.number_of_channels) + # recA += self.buffer[i0:i1:self.number_of_channels] + # recordA = np.uint16(recA / records_per_acquisition) # do demodulation magA, phaseA = self._fit(recordA) @@ -513,20 +523,20 @@ def _fit(self, rec): re_filtered = helpers.filter_win(re_mat, cutoff, self.sample_rate, self.filter_settings['numtaps'], - axis=1) + axis=-1) im_filtered = helpers.filter_win(im_mat, cutoff, self.sample_rate, self.filter_settings['numtaps'], - axis=1) + axis=-1) elif self.filter_settings['filter'] == 1: re_filtered = helpers.filter_ls(re_mat, cutoff, self.sample_rate, self.filter_settings['numtaps'], - axis=1) + axis=-1) im_filtered = helpers.filter_ls(im_mat, cutoff, self.sample_rate, self.filter_settings['numtaps'], - axis=1) + axis=-1) elif self.filter_settings['filter'] == 2: re_filtered = re_mat im_filtered = im_mat @@ -540,7 +550,7 @@ def _fit(self, rec): # convert to magnitude and phase complex_mat = re_limited + im_limited * 1j - magnitude = np.mean(abs(complex_mat), axis=1) - phase = np.mean(np.angle(complex_mat, deg=True), axis=1) + magnitude = np.mean(abs(complex_mat), axis=-1) + phase = np.mean(np.angle(complex_mat, deg=True), axis=-1) return magnitude, phase diff --git a/qcodes/instrument_drivers/AlazarTech/buf_rec_controller.py b/qcodes/instrument_drivers/AlazarTech/buf_rec_controller.py index b4e118970901..6f8f75ee6f01 100644 --- a/qcodes/instrument_drivers/AlazarTech/buf_rec_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/buf_rec_controller.py @@ -563,7 +563,8 @@ def pre_start_capture(self): self.record_num(), self.samples_per_record) integer_list = np.arange(self.samples_per_record) integer_mat = (np.outer(np.ones(self.buffer_num()), - np.outer(np.ones(self.record_num()), integer_list))) + np.outer(np.ones(self.record_num()), + integer_list))) angle_mat = 2 * np.pi * \ np.outer(demod_freqs, integer_mat).reshape( mat_shape) / self.sample_rate @@ -637,7 +638,8 @@ def _fit(self, rec): else: logging.warning('sample to volt conversion does not exist for' ' bps != 12, centered raw samples returned') - volt_rec = rec - np.mean(rec, axis=1) + # TODO(nataliejpg): think about this recentering makes sense here + volt_rec = rec - np.mean(rec) # volt_rec to matrix and multiply with demodulation signal matrices mat_shape = (self._demod_length, self.buffer_num(), self.record_num(), @@ -653,20 +655,20 @@ def _fit(self, rec): re_filtered = helpers.filter_win(re_mat, cutoff, self.sample_rate, self.filter_settings['numtaps'], - axis=3) + axis=-1) im_filtered = helpers.filter_win(im_mat, cutoff, self.sample_rate, self.filter_settings['numtaps'], - axis=3) + axis=-1) elif self.filter_settings['filter'] == 1: re_filtered = helpers.filter_ls(re_mat, cutoff, self.sample_rate, self.filter_settings['numtaps'], - axis=3) + axis=-1) im_filtered = helpers.filter_ls(im_mat, cutoff, self.sample_rate, self.filter_settings['numtaps'], - axis=3) + axis=-1) elif self.filter_settings['filter'] == 2: re_filtered = re_mat im_filtered = im_mat @@ -680,7 +682,7 @@ def _fit(self, rec): # convert to magnitude and phase complex_mat = re_limited + im_limited * 1j - magnitude = np.mean(abs(complex_mat), axis=3) - phase = np.mean(np.angle(complex_mat, deg=True), axis=3) + magnitude = np.mean(abs(complex_mat), axis=-1) + phase = np.mean(np.angle(complex_mat, deg=True), axis=-1) return magnitude, phase diff --git a/qcodes/instrument_drivers/AlazarTech/rec_controller.py b/qcodes/instrument_drivers/AlazarTech/rec_controller.py index 1027bf5eb3e0..6053f71c0669 100644 --- a/qcodes/instrument_drivers/AlazarTech/rec_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/rec_controller.py @@ -514,20 +514,30 @@ def post_acquire(self): # where SXYZ is record X, sample Y, channel Z. # break buffer up into records and shapes to be (records, samples) - recordsA = np.empty((self.record_num(), self.samples_per_record), - dtype=np.uint16) - for i in range(self.record_num()): - i0 = (i * self.samples_per_record * self.number_of_channels) - i1 = (i0 + self.samples_per_record * self.number_of_channels) - recordsA[i, :] = np.uint16( - self.buffer[i0:i1:self.number_of_channels] / - self.buffers_per_acquisition) + reshaped_buf = self.buffer.reshape(self.records_per_buffer, + self.samples_per_record, + self.number_of_channels) + recordsA = np.uint16(reshaped_buf[:, :, 0] / + self.buffers_per_acquisition) + + # TODO(nataliejpg): test above version works on alazar and + # compare performance + # recordsA = np.empty((self.record_num(), self.samples_per_record), + # dtype=np.uint16) + # for i in range(self.record_num()): + # i0 = (i * self.samples_per_record * self.number_of_channels) + # i1 = (i0 + self.samples_per_record * self.number_of_channels) + # recordsA[i, :] = np.uint16( + # self.buffer[i0:i1:self.number_of_channels] / + # self.buffers_per_acquisition) # do demodulation magA, phaseA = self._fit(recordsA) # same for chan b if self.chan_b: + # recordsB = np.uint16(reshaped_buf[:, :, 1] / + # self.buffers_per_acquisition) raise NotImplementedError('chan b code not complete') return magA, phaseA @@ -553,7 +563,8 @@ def _fit(self, rec): else: logging.warning('sample to volt conversion does not exist for' ' bps != 12, centered raw samples returned') - volt_rec = rec - np.mean(rec, axis=1) + # TODO(nataliejpg): think about this recentering makes sense here + volt_rec = rec - np.mean(rec) # volt_rec to matrix and multiply with demodulation signal matrices mat_shape = (self._demod_length, self.record_num(), @@ -569,20 +580,20 @@ def _fit(self, rec): re_filtered = helpers.filter_win(re_mat, cutoff, self.sample_rate, self.filter_settings['numtaps'], - axis=2) + axis=-1) im_filtered = helpers.filter_win(im_mat, cutoff, self.sample_rate, self.filter_settings['numtaps'], - axis=2) + axis=-1) elif self.filter_settings['filter'] == 1: re_filtered = helpers.filter_ls(re_mat, cutoff, self.sample_rate, self.filter_settings['numtaps'], - axis=2) + axis=-1) im_filtered = helpers.filter_ls(im_mat, cutoff, self.sample_rate, self.filter_settings['numtaps'], - axis=2) + axis=-1) elif self.filter_settings['filter'] == 2: re_filtered = re_mat im_filtered = im_mat @@ -596,7 +607,7 @@ def _fit(self, rec): # convert to magnitude and phase complex_mat = re_limited + im_limited * 1j - magnitude = np.mean(abs(complex_mat), axis=2) - phase = np.mean(np.angle(complex_mat, deg=True), axis=2) + magnitude = np.mean(abs(complex_mat), axis=-1) + phase = np.mean(np.angle(complex_mat, deg=True), axis=-1) return magnitude, phase diff --git a/qcodes/instrument_drivers/AlazarTech/rec_samp_controller.py b/qcodes/instrument_drivers/AlazarTech/rec_samp_controller.py index 40b729965915..4987fd32b59e 100644 --- a/qcodes/instrument_drivers/AlazarTech/rec_samp_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/rec_samp_controller.py @@ -562,16 +562,26 @@ def post_acquire(self): # where SXYZ is record X, sample Y, channel Z. # break buffer up into records and shapes to be (records, samples) - recordsA = np.empty((self.record_num(), self.samples_per_record), - dtype=np.uint16) - for i in range(self.record_num()): - i0 = (i * self.samples_per_record * self.number_of_channels) - i1 = (i0 + self.samples_per_record * self.number_of_channels) - recordsA[i, :] = np.uint16( - self.buffer[i0:i1:self.number_of_channels] / - self.buffers_per_acquisition) + reshaped_buf = self.buffer.reshape(self.records_per_buffer, + self.samples_per_record, + self.number_of_channels) + recordsA = np.uint16(reshaped_buf[:, :, 0] / + self.buffers_per_acquisition) + + # TODO(nataliejpg): test above version works on alazar and + # compare performance + # recordsA = np.empty((self.record_num(), self.samples_per_record), + # dtype=np.uint16) + # for i in range(self.record_num()): + # i0 = (i * self.samples_per_record * self.number_of_channels) + # i1 = (i0 + self.samples_per_record * self.number_of_channels) + # recordsA[i, :] = np.uint16( + # self.buffer[i0:i1:self.number_of_channels] / + # self.buffers_per_acquisitin) # do demodulation + # recordsB = np.uint16(reshaped_buf[:, :, 1] / + # self.buffers_per_acquisition) magA, phaseA = self._fit(recordsA) # same for chan b @@ -601,7 +611,8 @@ def _fit(self, rec): else: logging.warning('sample to volt conversion does not exist for' ' bps != 12, centered raw samples returned') - volt_rec = rec - np.mean(rec, axis=1) + # TODO(nataliejpg): think about this recentering makes sense here + volt_rec = rec - np.mean(rec) # volt_rec to matrix and multiply with demodulation signal matrices mat_shape = (self._demod_length, self.record_num, @@ -617,20 +628,20 @@ def _fit(self, rec): re_filtered = helpers.filter_win(re_mat, cutoff, self.sample_rate, self.filter_settings['numtaps'], - axis=2) + axis=-1) im_filtered = helpers.filter_win(im_mat, cutoff, self.sample_rate, self.filter_settings['numtaps'], - axis=2) + axis=-1) elif self.filter_settings['filter'] == 1: re_filtered = helpers.filter_ls(re_mat, cutoff, self.sample_rate, self.filter_settings['numtaps'], - axis=2) + axis=-1) im_filtered = helpers.filter_ls(im_mat, cutoff, self.sample_rate, self.filter_settings['numtaps'], - axis=2) + axis=-1) elif self.filter_settings['filter'] == 2: re_filtered = re_mat im_filtered = im_mat diff --git a/qcodes/instrument_drivers/AlazarTech/samp_controller.py b/qcodes/instrument_drivers/AlazarTech/samp_controller.py index a36382e74ab4..995250d9fc89 100644 --- a/qcodes/instrument_drivers/AlazarTech/samp_controller.py +++ b/qcodes/instrument_drivers/AlazarTech/samp_controller.py @@ -484,25 +484,37 @@ def post_acquire(self): magnitude (numpy array): shape = (demod_length, samples_used) phase (numpy array): shape = (demod_length, samples_used) """ - records_per_acquisition = (self.buffers_per_acquisition * - self.records_per_buffer) + # for ATS9360 samples are arranged in the buffer as follows: # S00A, S00B, S01A, S01B...S10A, S10B, S11A, S11B... # where SXYZ is record X, sample Y, channel Z. # break buffer up into records and averages over them - recA = np.zeros(self.samples_per_record) - for i in range(self.records_per_buffer): - i0 = (i * self.samples_per_record * self.number_of_channels) - i1 = (i0 + self.samples_per_record * self.number_of_channels) - recA += self.buffer[i0:i1:self.number_of_channels] - recordA = np.uint16(recA / records_per_acquisition) + reshaped_buf = self.buffer.reshape(self.records_per_buffer, + self.samples_per_record, + self.number_of_channels) + recordA = np.uint16(np.mean(reshaped_buf[:, :, 0], axis=0) / + self.buffers_per_acquisition) + + # TODO(nataliejpg): test above version works on alazar and + # compare performance + + # records_per_acquisition = (self.buffers_per_acquisition * + # self.records_per_buffer) + # recA = np.zeros(self.samples_per_record) + # for i in range(self.records_per_buffer): + # i0 = (i * self.samples_per_record * self.number_of_channels) + # i1 = (i0 + self.samples_per_record * self.number_of_channels) + # recA += self.buffer[i0:i1:self.number_of_channels] + # recordA = np.uint16(recA / records_per_acquisition) # do demodulation magA, phaseA = self._fit(recordA) # same for chan b if self.chan_b: + # recordB = np.uint16(np.mean(reshaped_buf[:, :, 1], axis=0) / + # self.buffers_per_acquisition) raise NotImplementedError('chan b code not complete') return magA, phaseA @@ -542,20 +554,20 @@ def _fit(self, rec): re_filtered = helpers.filter_win(re_mat, cutoff, self.sample_rate, self.filter_settings['numtaps'], - axis=1) + axis=-1) im_filtered = helpers.filter_win(im_mat, cutoff, self.sample_rate, self.filter_settings['numtaps'], - axis=1) + axis=-1) elif self.filter_settings['filter'] == 1: re_filtered = helpers.filter_ls(re_mat, cutoff, self.sample_rate, self.filter_settings['numtaps'], - axis=1) + axis=-1) im_filtered = helpers.filter_ls(im_mat, cutoff, self.sample_rate, self.filter_settings['numtaps'], - axis=1) + axis=-1) # apply integration limits beginning = int(self.int_delay() * self.sample_rate) @@ -563,7 +575,6 @@ def _fit(self, rec): re_limited = re_filtered[:, beginning:end] im_limited = im_filtered[:, beginning:end] - # return re_limited, volt_rec_mat[:, beginning:end] # convert to magnitude and phase complex_mat = re_limited + im_limited * 1j From 1f4ea7e881c740477f7b7a81cd00ca6a5d02a9c9 Mon Sep 17 00:00:00 2001 From: Natalie Pearson Date: Mon, 13 Feb 2017 11:36:12 +0100 Subject: [PATCH 103/180] updating notebook to reflect driver changes, nb untested on an alazar --- .../Qcodes example with Alazar ATS9360.ipynb | 217 ++++++++++++------ 1 file changed, 152 insertions(+), 65 deletions(-) diff --git a/docs/examples/Qcodes example with Alazar ATS9360.ipynb b/docs/examples/Qcodes example with Alazar ATS9360.ipynb index 905fd7081d53..cf493af6acda 100644 --- a/docs/examples/Qcodes example with Alazar ATS9360.ipynb +++ b/docs/examples/Qcodes example with Alazar ATS9360.ipynb @@ -2,7 +2,10 @@ "cells": [ { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "deletable": true, + "editable": true + }, "source": [ "### Qcodes example notebook for Alazar card ATS9360 and acq controllers" ] @@ -11,7 +14,9 @@ "cell_type": "code", "execution_count": 1, "metadata": { - "collapsed": false + "collapsed": false, + "deletable": true, + "editable": true }, "outputs": [ { @@ -39,7 +44,10 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "deletable": true, + "editable": true + }, "source": [ "NB: See ATS9360 example notebook for general commands " ] @@ -48,7 +56,9 @@ "cell_type": "code", "execution_count": 2, "metadata": { - "collapsed": false + "collapsed": false, + "deletable": true, + "editable": true }, "outputs": [ { @@ -86,7 +96,9 @@ "cell_type": "code", "execution_count": 3, "metadata": { - "collapsed": false + "collapsed": false, + "deletable": true, + "editable": true }, "outputs": [], "source": [ @@ -118,7 +130,10 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "deletable": true, + "editable": true + }, "source": [ "### Basic Acquisition\n", "\n", @@ -129,7 +144,9 @@ "cell_type": "code", "execution_count": 4, "metadata": { - "collapsed": false + "collapsed": false, + "deletable": true, + "editable": true }, "outputs": [], "source": [ @@ -143,7 +160,9 @@ "cell_type": "code", "execution_count": 5, "metadata": { - "collapsed": false + "collapsed": false, + "deletable": true, + "editable": true }, "outputs": [], "source": [ @@ -160,7 +179,9 @@ "cell_type": "code", "execution_count": 6, "metadata": { - "collapsed": false + "collapsed": false, + "deletable": true, + "editable": true }, "outputs": [ { @@ -183,7 +204,9 @@ "cell_type": "code", "execution_count": 11, "metadata": { - "collapsed": false + "collapsed": false, + "deletable": true, + "editable": true }, "outputs": [ { @@ -211,7 +234,9 @@ "cell_type": "code", "execution_count": 17, "metadata": { - "collapsed": false + "collapsed": false, + "deletable": true, + "editable": true }, "outputs": [ { @@ -234,7 +259,9 @@ "cell_type": "code", "execution_count": null, "metadata": { - "collapsed": true + "collapsed": true, + "deletable": true, + "editable": true }, "outputs": [], "source": [] @@ -243,7 +270,9 @@ "cell_type": "code", "execution_count": 10, "metadata": { - "collapsed": true + "collapsed": true, + "deletable": true, + "editable": true }, "outputs": [ { @@ -274,7 +303,9 @@ "cell_type": "code", "execution_count": null, "metadata": { - "collapsed": false + "collapsed": false, + "deletable": true, + "editable": true }, "outputs": [], "source": [ @@ -289,39 +320,32 @@ "cell_type": "code", "execution_count": null, "metadata": { - "collapsed": true + "collapsed": true, + "deletable": true, + "editable": true }, "outputs": [], "source": [] }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "deletable": true, + "editable": true + }, "source": [ "### Samples Acquisition\n", "\n", "This is the same as above except that it does some demodulation at the freqiencies specified" ] }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "# make a list of the frequencies to demodulate at (nb these values can be changed later, if unset the default is [20e6])\n", - "# NB the number of demodulation frequencies cannot currently be changed once an acq controller is created, this sucks:\n", - "# lets have channels :)\n", - "demod_list = [5e6,1e6]" - ] - }, { "cell_type": "code", "execution_count": 19, "metadata": { - "collapsed": false + "collapsed": false, + "deletable": true, + "editable": true }, "outputs": [], "source": [ @@ -329,14 +353,16 @@ "# alazar instrument to talk to and does the demodulation and signal processing\n", "samp_acq_controller = samp_acq_contr.HD_Samples_Controller(name='samp_acq_controller', \n", " alazar_name='Alazar',\n", - " demod_freqs=demod_list)" + " demod_length=2)" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { - "collapsed": false + "collapsed": false, + "deletable": true, + "editable": true }, "outputs": [ { @@ -348,6 +374,10 @@ } ], "source": [ + "# set the two demodulation frequencies\n", + "samp_acq_controller.demod_freq_0(1e6)\n", + "samp_acq_controller.demod_freq_1(2e6)\n", + "\n", "# set integration time and delay (nb this replaces need to set samples_per record)\n", "# if int_delay is unset it will default to a value corresponding to the about needed for the filter to work well\n", "samp_acq_controller.int_time(10e-6)\n", @@ -358,7 +388,9 @@ "cell_type": "code", "execution_count": 40, "metadata": { - "collapsed": true + "collapsed": true, + "deletable": true, + "editable": true }, "outputs": [], "source": [ @@ -372,7 +404,9 @@ "cell_type": "code", "execution_count": 22, "metadata": { - "collapsed": false + "collapsed": false, + "deletable": true, + "editable": true }, "outputs": [], "source": [ @@ -388,7 +422,9 @@ "cell_type": "code", "execution_count": 43, "metadata": { - "collapsed": false + "collapsed": false, + "deletable": true, + "editable": true }, "outputs": [], "source": [ @@ -401,7 +437,9 @@ "cell_type": "code", "execution_count": 31, "metadata": { - "collapsed": false + "collapsed": false, + "deletable": true, + "editable": true }, "outputs": [ { @@ -423,7 +461,9 @@ "cell_type": "code", "execution_count": 53, "metadata": { - "collapsed": false + "collapsed": false, + "deletable": true, + "editable": true }, "outputs": [], "source": [ @@ -435,7 +475,9 @@ "cell_type": "code", "execution_count": 54, "metadata": { - "collapsed": false + "collapsed": false, + "deletable": true, + "editable": true }, "outputs": [], "source": [ @@ -447,6 +489,8 @@ "execution_count": 48, "metadata": { "collapsed": false, + "deletable": true, + "editable": true, "scrolled": false }, "outputs": [ @@ -489,7 +533,9 @@ "cell_type": "code", "execution_count": 35, "metadata": { - "collapsed": false + "collapsed": false, + "deletable": true, + "editable": true }, "outputs": [ { @@ -512,7 +558,9 @@ "cell_type": "code", "execution_count": 45, "metadata": { - "collapsed": false + "collapsed": false, + "deletable": true, + "editable": true }, "outputs": [ { @@ -535,7 +583,9 @@ "cell_type": "code", "execution_count": 30, "metadata": { - "collapsed": false + "collapsed": false, + "deletable": true, + "editable": true }, "outputs": [ { @@ -565,7 +615,9 @@ "cell_type": "code", "execution_count": 33, "metadata": { - "collapsed": false + "collapsed": false, + "deletable": true, + "editable": true }, "outputs": [ { @@ -594,7 +646,10 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "deletable": true, + "editable": true + }, "source": [ "### Averaged Acquisition\n", "\n", @@ -605,21 +660,24 @@ "cell_type": "code", "execution_count": 4, "metadata": { - "collapsed": false + "collapsed": false, + "deletable": true, + "editable": true }, "outputs": [], "source": [ - "demod_list = [80e6, 85e6, 90e6, 95e6, 100e6, 105e6, 110e6, 115e6]\n", "ave_controller = ave_controller.HD_Averaging_Controller(name='ave_controller', \n", " alazar_name='Alazar', \n", - " demod_freqs = demod_list)" + " demod_length = 8)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { - "collapsed": false + "collapsed": false, + "deletable": true, + "editable": true }, "outputs": [ { @@ -631,6 +689,17 @@ } ], "source": [ + "# set the demodulation frequencies\n", + "samp_acq_controller.demod_freq_0(1e6)\n", + "samp_acq_controller.demod_freq_1(2e6)\n", + "samp_acq_controller.demod_freq_2(3e6)\n", + "samp_acq_controller.demod_freq_3(4e6)\n", + "samp_acq_controller.demod_freq_4(5e6)\n", + "samp_acq_controller.demod_freq_5(6e6)\n", + "samp_acq_controller.demod_freq_6(7e6)\n", + "samp_acq_controller.demod_freq_7(8e6)\n", + "\n", + "\n", "# This command is specific to this acquisition controller. The kwargs provided here are being forwarded to ats_inst.acquire\n", "# This way, it becomes easy to change acquisition specific settings from the ipython notebook\n", "ave_controller.update_acquisition_kwargs(#mode='NPT',\n", @@ -649,7 +718,9 @@ "cell_type": "code", "execution_count": 6, "metadata": { - "collapsed": false + "collapsed": false, + "deletable": true, + "editable": true }, "outputs": [ { @@ -674,7 +745,9 @@ "cell_type": "code", "execution_count": 7, "metadata": { - "collapsed": false + "collapsed": false, + "deletable": true, + "editable": true }, "outputs": [ { @@ -712,7 +785,10 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "deletable": true, + "editable": true + }, "source": [ "### Records Acquisition\n", "\n", @@ -723,7 +799,9 @@ "cell_type": "code", "execution_count": null, "metadata": { - "collapsed": true + "collapsed": true, + "deletable": true, + "editable": true }, "outputs": [], "source": [ @@ -736,32 +814,43 @@ "cell_type": "code", "execution_count": 8, "metadata": { - "collapsed": false + "collapsed": false, + "deletable": true, + "editable": true }, "outputs": [], "source": [ - "demod_list = [95e6, 98e6, 100e6, 105e6]\n", "rec_controller = record_controller.HD_Records_Controller(name='rec_controller', \n", " alazar_name='Alazar', \n", - " demod_freqs = demod_list)" + " demod_length = 4)\n", + "rec_controller.demod_freq_0(1e6)\n", + "rec_controller.demod_freq_1(4e6)\n", + "rec_controller.demod_freq_2(8e6)\n", + "rec_controller.demod_freq_3(12e6)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { - "collapsed": false + "collapsed": false, + "deletable": true, + "editable": true }, "outputs": [], "source": [ - "# This command is specific to this acquisition controller. The kwargs provided here are being forwarded to ats_inst.acquire\n", - "# This way, it becomes easy to change acquisition specific settings from the ipython notebook\n", + "# This command is specific to this acquisition controller. The kwargs provided here are being forwarded to \n", + "# ats_inst.acquire. This way, it becomes easy to change acquisition specific settings from the ipython notebook\n", "rec_controller.update_acquisition_kwargs(#mode='NPT',\n", - " records_per_buffer=20,\n", - " buffers_per_acquisition=1,\n", + " buffers_per_acquisition=100,\n", " allocated_buffers=1,\n", ")\n", "\n", + "# records_num a parameter of the records acq controller which is mainly a move towards having the \n", + "# setpoints in the record direction be settable by the user and also to make it easier to write wrapper functions\n", + "# which change it when there is an AWG upload, (replaces need to set records_per_buffer)\n", + "rec_controller.record_num(20)\n", + "\n", "# set integration time and delay (nb this replaces need to set samples_per record)\n", "# if int_delay is unset it will default to a value corresponding to the about needed for the filter to work well\n", "rec_controller.int_time(2e-6)\n", @@ -772,7 +861,9 @@ "cell_type": "code", "execution_count": 19, "metadata": { - "collapsed": false + "collapsed": false, + "deletable": true, + "editable": true }, "outputs": [ { @@ -825,10 +916,6 @@ "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.2" - }, - "widgets": { - "state": {}, - "version": "1.1.2" } }, "nbformat": 4, From c00d8cddad954d96d8891abd8213ba416a936943 Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Mon, 13 Feb 2017 16:19:53 +0100 Subject: [PATCH 104/180] Revert "Change lower limit of freq allowed to 1 MHz" This is a non related change. Will go in on a different pr This reverts commit e8190ec03f5e98b824fe09d4d4d4e1ecbfca33b1. --- qcodes/instrument_drivers/rohde_schwarz/SGS100A.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qcodes/instrument_drivers/rohde_schwarz/SGS100A.py b/qcodes/instrument_drivers/rohde_schwarz/SGS100A.py index 094d5d64738b..83eb19ee0543 100644 --- a/qcodes/instrument_drivers/rohde_schwarz/SGS100A.py +++ b/qcodes/instrument_drivers/rohde_schwarz/SGS100A.py @@ -36,7 +36,7 @@ def __init__(self, name, address, **kwargs): get_cmd='SOUR:FREQ' + '?', set_cmd='SOUR:FREQ' + ' {:.2f}', get_parser=float, - vals=vals.Numbers(1e6, 20e9)) + vals=vals.Numbers(1e9, 20e9)) self.add_parameter(name='phase', label='Phase', units='deg', From 72cbaf4761ca6e0ee68a9c95c436bd9c649f7b99 Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Mon, 13 Feb 2017 16:21:03 +0100 Subject: [PATCH 105/180] Fix: remove conflict leftover --- qcodes/instrument_drivers/rohde_schwarz/SMR40.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/qcodes/instrument_drivers/rohde_schwarz/SMR40.py b/qcodes/instrument_drivers/rohde_schwarz/SMR40.py index d3cc0df98c51..3b31aa89e34d 100644 --- a/qcodes/instrument_drivers/rohde_schwarz/SMR40.py +++ b/qcodes/instrument_drivers/rohde_schwarz/SMR40.py @@ -13,22 +13,15 @@ class RohdeSchwarz_SMR40(VisaInstrument): """This is the qcodes driver for the Rohde & Schwarz SMR40 signal generator -<<<<<<< HEAD - Status: beta-version. TODO: -======= Status: beta-version. .. todo:: ->>>>>>> master - Add all parameters that are in the manual - Add test suite - See if there can be a common driver for RS mw sources from which different models inherit -<<<<<<< HEAD -======= ->>>>>>> master This driver does not contain all commands available for the SMR40 but only the ones most commonly used. From 91c1f4397756df679e49607218bde7e7c0af4d4e Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Mon, 13 Feb 2017 17:52:11 +0100 Subject: [PATCH 106/180] Fix: sync AWG example notebook with master --- ...odes example with Tektronix AWG5014C.ipynb | 1071 ++--------------- 1 file changed, 126 insertions(+), 945 deletions(-) diff --git a/docs/examples/Qcodes example with Tektronix AWG5014C.ipynb b/docs/examples/Qcodes example with Tektronix AWG5014C.ipynb index fbd09310add5..0328d7ade7d5 100644 --- a/docs/examples/Qcodes example with Tektronix AWG5014C.ipynb +++ b/docs/examples/Qcodes example with Tektronix AWG5014C.ipynb @@ -1,8 +1,30 @@ { "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# QCoDeS Example with Tektronix AWG5014\n", + "\n", + "## Table of contents\n", + "\n", + "* [Imports and initialisation](#init)\n", + "* [Sending waveforms](#sending)\n", + " * [Via an .awg-file](#viaawg)\n", + " * [Sending directly to list](#tolist)\n", + "* [Running in \"lazy\" mode](#lazy)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Imports and initialisation " + ] + }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": { "collapsed": false }, @@ -18,80 +40,26 @@ "import matplotlib.pyplot as plt\n", "\n", "logger = logging.getLogger()\n", - "logger.setLevel(logging.INFO)" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "import numpy as np\n" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "6.0" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "np.ceil(26/5)" + "logger.setLevel(logging.WARNING)" ] }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "ename": "VisaIOError", - "evalue": "VI_ERROR_RSRC_NFOUND (-1073807343): Insufficient location information or the requested device or resource is not present in the system.", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mVisaIOError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mqcodes\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0minstrument_drivers\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mtektronix\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mAWGFileParser\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mparse_awg_file\u001b[0m \u001b[1;31m# <--- A helper function\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0mawg1\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mawg\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mTektronix_AWG5014\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'AWG1'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'TCPIP0::192.168.137.182::inst0::INSTR'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtimeout\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m40\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;32ma:\\qcodes\\qcodes\\instrument\\metaclass.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(cls, server_name, *args, **kwargs)\u001b[0m\n\u001b[1;32m 32\u001b[0m \"\"\"\n\u001b[1;32m 33\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mserver_name\u001b[0m \u001b[1;32mis\u001b[0m \u001b[1;32mNone\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m---> 34\u001b[0;31m \u001b[0minstrument\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0msuper\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m__call__\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m*\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 35\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 36\u001b[0m warnings.warn('Multiprocessing is in beta, use at own risk',\n", - "\u001b[0;32ma:\\qcodes\\qcodes\\instrument_drivers\\tektronix\\AWG5014.py\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, name, address, timeout, **kwargs)\u001b[0m\n\u001b[1;32m 137\u001b[0m \u001b[1;32mNone\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 138\u001b[0m \"\"\"\n\u001b[0;32m--> 139\u001b[0;31m \u001b[0msuper\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m__init__\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mname\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0maddress\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtimeout\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mtimeout\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 140\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 141\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[0;32ma:\\qcodes\\qcodes\\instrument\\visa.py\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, name, address, timeout, terminator, **kwargs)\u001b[0m\n\u001b[1;32m 54\u001b[0m vals.Enum(None)))\n\u001b[1;32m 55\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m---> 56\u001b[0;31m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mset_address\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0maddress\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 57\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mset_terminator\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mterminator\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 58\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mtimeout\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mset\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mtimeout\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[0;32ma:\\qcodes\\qcodes\\instrument\\visa.py\u001b[0m in \u001b[0;36mset_address\u001b[0;34m(self, address)\u001b[0m\n\u001b[1;32m 101\u001b[0m \u001b[0mresource_manager\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mvisa\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mResourceManager\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 102\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m--> 103\u001b[0;31m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mvisa_handle\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mresource_manager\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mopen_resource\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0maddress\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 104\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 105\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mvisa_handle\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mclear\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[0;32mc:\\users\\triton2acq\\anaconda3\\envs\\qcodes-master\\lib\\site-packages\\pyvisa\\highlevel.py\u001b[0m in \u001b[0;36mopen_resource\u001b[0;34m(self, resource_name, access_mode, open_timeout, resource_pyclass, **kwargs)\u001b[0m\n\u001b[1;32m 1642\u001b[0m \u001b[1;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'%r is not a valid attribute for type %s'\u001b[0m \u001b[1;33m%\u001b[0m \u001b[1;33m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mres\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m__class__\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m__name__\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 1643\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1644\u001b[0;31m \u001b[0mres\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mopen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0maccess_mode\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mopen_timeout\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1645\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 1646\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mkey\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mvalue\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mitems\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[0;32mc:\\users\\triton2acq\\anaconda3\\envs\\qcodes-master\\lib\\site-packages\\pyvisa\\resources\\resource.py\u001b[0m in \u001b[0;36mopen\u001b[0;34m(self, access_mode, open_timeout)\u001b[0m\n\u001b[1;32m 201\u001b[0m \u001b[0mlogger\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdebug\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'%s - opening ...'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_resource_name\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mextra\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_logging_extra\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 202\u001b[0m \u001b[1;32mwith\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_resource_manager\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mignore_warning\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mconstants\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mVI_SUCCESS_DEV_NPRESENT\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m--> 203\u001b[0;31m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msession\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mstatus\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_resource_manager\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mopen_bare_resource\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_resource_name\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0maccess_mode\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mopen_timeout\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 204\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 205\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mstatus\u001b[0m \u001b[1;33m==\u001b[0m \u001b[0mconstants\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mVI_SUCCESS_DEV_NPRESENT\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[0;32mc:\\users\\triton2acq\\anaconda3\\envs\\qcodes-master\\lib\\site-packages\\pyvisa\\highlevel.py\u001b[0m in \u001b[0;36mopen_bare_resource\u001b[0;34m(self, resource_name, access_mode, open_timeout)\u001b[0m\n\u001b[1;32m 1599\u001b[0m \u001b[1;33m:\u001b[0m\u001b[1;32mreturn\u001b[0m\u001b[1;33m:\u001b[0m \u001b[0mUnique\u001b[0m \u001b[0mlogical\u001b[0m \u001b[0midentifier\u001b[0m \u001b[0mreference\u001b[0m \u001b[0mto\u001b[0m \u001b[0ma\u001b[0m \u001b[0msession\u001b[0m\u001b[1;33m.\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 1600\u001b[0m \"\"\"\n\u001b[0;32m-> 1601\u001b[0;31m \u001b[1;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mvisalib\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mopen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msession\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mresource_name\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0maccess_mode\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mopen_timeout\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1602\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 1603\u001b[0m def open_resource(self, resource_name,\n", - "\u001b[0;32mc:\\users\\triton2acq\\anaconda3\\envs\\qcodes-master\\lib\\site-packages\\pyvisa\\ctwrapper\\functions.py\u001b[0m in \u001b[0;36mopen\u001b[0;34m(library, session, resource_name, access_mode, open_timeout)\u001b[0m\n\u001b[1;32m 1209\u001b[0m \u001b[1;31m# [ViSession, ViRsrc, ViAccessMode, ViUInt32, ViPSession]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 1210\u001b[0m \u001b[1;31m# ViRsrc converts from (str, unicode, bytes) to bytes\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1211\u001b[0;31m \u001b[0mret\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mlibrary\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mviOpen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0msession\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mresource_name\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0maccess_mode\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mopen_timeout\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mbyref\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mout_session\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1212\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[0mout_session\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mvalue\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mret\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 1213\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[0;32mc:\\users\\triton2acq\\anaconda3\\envs\\qcodes-master\\lib\\site-packages\\pyvisa\\ctwrapper\\highlevel.py\u001b[0m in \u001b[0;36m_return_handler\u001b[0;34m(self, ret_value, func, arguments)\u001b[0m\n\u001b[1;32m 186\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 187\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mret_value\u001b[0m \u001b[1;33m<\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m--> 188\u001b[0;31m \u001b[1;32mraise\u001b[0m \u001b[0merrors\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mVisaIOError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mret_value\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 189\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 190\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mret_value\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0missue_warning_on\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[0;31mVisaIOError\u001b[0m: VI_ERROR_RSRC_NFOUND (-1073807343): Insufficient location information or the requested device or resource is not present in the system." - ] - } - ], + "outputs": [], "source": [ "import qcodes.instrument_drivers.tektronix.AWG5014 as awg # <--- The instrument driver\n", "from qcodes.instrument_drivers.tektronix.AWGFileParser import parse_awg_file # <--- A helper function\n", "\n", - "awg1 = awg.Tektronix_AWG5014('AWG1', 'TCPIP0::192.168.137.182::inst0::INSTR', timeout=40)" + "awg1 = awg.Tektronix_AWG5014('AWG1', 'TCPIP0::172.20.3.57::inst0::INSTR', timeout=40)" ] }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": { "collapsed": false }, @@ -112,22 +80,11 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0\n", - "\n", - "0.0\n", - "0.1\n" - ] - } - ], + "outputs": [], "source": [ "print(awg1.ch3_state.get())\n", "print(awg1.ch2_offset.get())\n", @@ -144,92 +101,11 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "DC_output : DC Output (ON/OFF)\n", - "IDN : IDN\n", - "ch1_DC_out : DC output level channel 1\n", - "ch1_add_input : Add input channel {}\n", - "ch1_amp : Amplitude channel 1 (Vpp)\n", - "ch1_direct_output : Direct output channel 1\n", - "ch1_filter : Low pass filter channel 1\n", - "ch1_m1_del : Channel 1 Marker 1 delay (ns)\n", - "ch1_m1_high : Channel 1 Marker 1 high level (V)\n", - "ch1_m1_low : Channel 1 Marker 1 low level (V)\n", - "ch1_m2_del : Channel 1 Marker 2 delay (ns)\n", - "ch1_m2_high : Channel 1 Marker 2 high level (V)\n", - "ch1_m2_low : Channel 1 Marker 2 low level (V)\n", - "ch1_offset : Offset channel 1 (V)\n", - "ch1_state : Status channel 1\n", - "ch1_waveform : Waveform channel 1\n", - "ch2_DC_out : DC output level channel 2\n", - "ch2_add_input : Add input channel {}\n", - "ch2_amp : Amplitude channel 2 (Vpp)\n", - "ch2_direct_output : Direct output channel 2\n", - "ch2_filter : Low pass filter channel 2\n", - "ch2_m1_del : Channel 2 Marker 1 delay (ns)\n", - "ch2_m1_high : Channel 2 Marker 1 high level (V)\n", - "ch2_m1_low : Channel 2 Marker 1 low level (V)\n", - "ch2_m2_del : Channel 2 Marker 2 delay (ns)\n", - "ch2_m2_high : Channel 2 Marker 2 high level (V)\n", - "ch2_m2_low : Channel 2 Marker 2 low level (V)\n", - "ch2_offset : Offset channel 2 (V)\n", - "ch2_state : Status channel 2\n", - "ch2_waveform : Waveform channel 2\n", - "ch3_DC_out : DC output level channel 3\n", - "ch3_add_input : Add input channel {}\n", - "ch3_amp : Amplitude channel 3 (Vpp)\n", - "ch3_direct_output : Direct output channel 3\n", - "ch3_filter : Low pass filter channel 3\n", - "ch3_m1_del : Channel 3 Marker 1 delay (ns)\n", - "ch3_m1_high : Channel 3 Marker 1 high level (V)\n", - "ch3_m1_low : Channel 3 Marker 1 low level (V)\n", - "ch3_m2_del : Channel 3 Marker 2 delay (ns)\n", - "ch3_m2_high : Channel 3 Marker 2 high level (V)\n", - "ch3_m2_low : Channel 3 Marker 2 low level (V)\n", - "ch3_offset : Offset channel 3 (V)\n", - "ch3_state : Status channel 3\n", - "ch3_waveform : Waveform channel 3\n", - "ch4_DC_out : DC output level channel 4\n", - "ch4_add_input : Add input channel {}\n", - "ch4_amp : Amplitude channel 4 (Vpp)\n", - "ch4_direct_output : Direct output channel 4\n", - "ch4_filter : Low pass filter channel 4\n", - "ch4_m1_del : Channel 4 Marker 1 delay (ns)\n", - "ch4_m1_high : Channel 4 Marker 1 high level (V)\n", - "ch4_m1_low : Channel 4 Marker 1 low level (V)\n", - "ch4_m2_del : Channel 4 Marker 2 delay (ns)\n", - "ch4_m2_high : Channel 4 Marker 2 high level (V)\n", - "ch4_m2_low : Channel 4 Marker 2 low level (V)\n", - "ch4_offset : Offset channel 4 (V)\n", - "ch4_state : Status channel 4\n", - "ch4_waveform : Waveform channel 4\n", - "clock_freq : Clock frequency (Hz)\n", - "event_impedance : Event impedance (Ohm)\n", - "event_jump_timing : event_jump_timing\n", - "event_level : Event level (V)\n", - "event_polarity : event_polarity\n", - "ref_clock_source : Reference clock source\n", - "run_mode : run_mode\n", - "sequence_length : Sequence length\n", - "setup_filename : setup_filename\n", - "state : state\n", - "timeout : timeout\n", - "trigger_impedance : Trigger impedance (Ohm)\n", - "trigger_level : Trigger level (V)\n", - "trigger_mode : trigger_mode\n", - "trigger_slope : trigger_slope\n", - "trigger_source : trigger_source\n" - ] - } - ], + "outputs": [], "source": [ "pars = np.sort(list(awg1.parameters.keys()))\n", "for param in pars:\n", @@ -242,7 +118,7 @@ "collapsed": false }, "source": [ - "## SENDING WAVEFORMS\n", + "## SENDING WAVEFORMS \n", "\n", "There are two supported ways of sending waveforms to the AWG; by making an .awg file, sending and loading that, or by sending waveforms to the User Defined list one by one and putting them in the sequencer. The first method is generally faster." ] @@ -264,7 +140,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": { "collapsed": false, "scrolled": true @@ -298,786 +174,12 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": { "collapsed": false, "scrolled": true }, - "outputs": [ - { - "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "window.mpl = {};\n", - "\n", - "mpl.get_websocket_type = function() {\n", - " if (typeof(WebSocket) !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof(MozWebSocket) !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert('Your browser does not have WebSocket support.' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.');\n", - " };\n", - "}\n", - "\n", - "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = (this.ws.binaryType != undefined);\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById(\"mpl-warnings\");\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent = (\n", - " \"This browser does not support binary websocket messages. \" +\n", - " \"Performance may be slow.\");\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = $('
');\n", - " this._root_extra_style(this.root)\n", - " this.root.attr('style', 'display: inline-block');\n", - "\n", - " $(parent_element).append(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", - " fig.send_message(\"send_image_mode\", {});\n", - " fig.send_message(\"refresh\", {});\n", - " }\n", - "\n", - " this.imageObj.onload = function() {\n", - " if (fig.image_mode == 'full') {\n", - " // Full images could contain transparency (where diff images\n", - " // almost always do), so we need to clear the canvas so that\n", - " // there is no ghosting.\n", - " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", - " }\n", - " fig.context.drawImage(fig.imageObj, 0, 0);\n", - " };\n", - "\n", - " this.imageObj.onunload = function() {\n", - " this.ws.close();\n", - " }\n", - "\n", - " this.ws.onmessage = this._make_on_message_function(this);\n", - "\n", - " this.ondownload = ondownload;\n", - "}\n", - "\n", - "mpl.figure.prototype._init_header = function() {\n", - " var titlebar = $(\n", - " '
');\n", - " var titletext = $(\n", - " '
');\n", - " titlebar.append(titletext)\n", - " this.root.append(titlebar);\n", - " this.header = titletext[0];\n", - "}\n", - "\n", - "\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._init_canvas = function() {\n", - " var fig = this;\n", - "\n", - " var canvas_div = $('
');\n", - "\n", - " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", - "\n", - " function canvas_keyboard_event(event) {\n", - " return fig.key_event(event, event['data']);\n", - " }\n", - "\n", - " canvas_div.keydown('key_press', canvas_keyboard_event);\n", - " canvas_div.keyup('key_release', canvas_keyboard_event);\n", - " this.canvas_div = canvas_div\n", - " this._canvas_extra_style(canvas_div)\n", - " this.root.append(canvas_div);\n", - "\n", - " var canvas = $('');\n", - " canvas.addClass('mpl-canvas');\n", - " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", - "\n", - " this.canvas = canvas[0];\n", - " this.context = canvas[0].getContext(\"2d\");\n", - "\n", - " var rubberband = $('');\n", - " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", - "\n", - " var pass_mouse_events = true;\n", - "\n", - " canvas_div.resizable({\n", - " start: function(event, ui) {\n", - " pass_mouse_events = false;\n", - " },\n", - " resize: function(event, ui) {\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " stop: function(event, ui) {\n", - " pass_mouse_events = true;\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " });\n", - "\n", - " function mouse_event_fn(event) {\n", - " if (pass_mouse_events)\n", - " return fig.mouse_event(event, event['data']);\n", - " }\n", - "\n", - " rubberband.mousedown('button_press', mouse_event_fn);\n", - " rubberband.mouseup('button_release', mouse_event_fn);\n", - " // Throttle sequential mouse events to 1 every 20ms.\n", - " rubberband.mousemove('motion_notify', mouse_event_fn);\n", - "\n", - " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", - " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", - "\n", - " canvas_div.on(\"wheel\", function (event) {\n", - " event = event.originalEvent;\n", - " event['data'] = 'scroll'\n", - " if (event.deltaY < 0) {\n", - " event.step = 1;\n", - " } else {\n", - " event.step = -1;\n", - " }\n", - " mouse_event_fn(event);\n", - " });\n", - "\n", - " canvas_div.append(canvas);\n", - " canvas_div.append(rubberband);\n", - "\n", - " this.rubberband = rubberband;\n", - " this.rubberband_canvas = rubberband[0];\n", - " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", - " this.rubberband_context.strokeStyle = \"#000000\";\n", - "\n", - " this._resize_canvas = function(width, height) {\n", - " // Keep the size of the canvas, canvas container, and rubber band\n", - " // canvas in synch.\n", - " canvas_div.css('width', width)\n", - " canvas_div.css('height', height)\n", - "\n", - " canvas.attr('width', width);\n", - " canvas.attr('height', height);\n", - "\n", - " rubberband.attr('width', width);\n", - " rubberband.attr('height', height);\n", - " }\n", - "\n", - " // Set the figure to an initial 600x600px, this will subsequently be updated\n", - " // upon first draw.\n", - " this._resize_canvas(600, 600);\n", - "\n", - " // Disable right mouse context menu.\n", - " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", - " return false;\n", - " });\n", - "\n", - " function set_focus () {\n", - " canvas.focus();\n", - " canvas_div.focus();\n", - " }\n", - "\n", - " window.setTimeout(set_focus, 100);\n", - "}\n", - "\n", - "mpl.figure.prototype._init_toolbar = function() {\n", - " var fig = this;\n", - "\n", - " var nav_element = $('
')\n", - " nav_element.attr('style', 'width: 100%');\n", - " this.root.append(nav_element);\n", - "\n", - " // Define a callback function for later on.\n", - " function toolbar_event(event) {\n", - " return fig.toolbar_button_onclick(event['data']);\n", - " }\n", - " function toolbar_mouse_event(event) {\n", - " return fig.toolbar_button_onmouseover(event['data']);\n", - " }\n", - "\n", - " for(var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " // put a spacer in here.\n", - " continue;\n", - " }\n", - " var button = $('');\n", + " button.click(method_name, toolbar_event);\n", + " button.mouseover(tooltip, toolbar_mouse_event);\n", + " nav_element.append(button);\n", + " }\n", + "\n", + " // Add the status bar.\n", + " var status_bar = $('');\n", + " nav_element.append(status_bar);\n", + " this.message = status_bar[0];\n", + "\n", + " // Add the close button to the window.\n", + " var buttongrp = $('
');\n", + " var button = $('');\n", + " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", + " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", + " buttongrp.append(button);\n", + " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", + " titlebar.prepend(buttongrp);\n", + "}\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(el){\n", + " var fig = this\n", + " el.on(\"remove\", function(){\n", + "\tfig.close_ws(fig, {});\n", + " });\n", + "}\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(el){\n", + " // this is important to make the div 'focusable\n", + " el.attr('tabindex', 0)\n", + " // reach out to IPython and tell the keyboard manager to turn it's self\n", + " // off when our div gets focus\n", + "\n", + " // location in version 3\n", + " if (IPython.notebook.keyboard_manager) {\n", + " IPython.notebook.keyboard_manager.register_events(el);\n", + " }\n", + " else {\n", + " // location in version 2\n", + " IPython.keyboard_manager.register_events(el);\n", + " }\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._key_event_extra = function(event, name) {\n", + " var manager = IPython.notebook.keyboard_manager;\n", + " if (!manager)\n", + " manager = IPython.keyboard_manager;\n", + "\n", + " // Check for shift+enter\n", + " if (event.shiftKey && event.which == 13) {\n", + " this.canvas_div.blur();\n", + " // select the cell after this one\n", + " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", + " IPython.notebook.select(index + 1);\n", + " }\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_save = function(fig, msg) {\n", + " fig.ondownload(fig, null);\n", + "}\n", + "\n", + "\n", + "mpl.find_output_cell = function(html_output) {\n", + " // Return the cell and output element which can be found *uniquely* in the notebook.\n", + " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", + " // IPython event is triggered only after the cells have been serialised, which for\n", + " // our purposes (turning an active figure into a static one), is too late.\n", + " var cells = IPython.notebook.get_cells();\n", + " var ncells = cells.length;\n", + " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", + " data = data.data;\n", + " }\n", + " if (data['text/html'] == html_output) {\n", + " return [cell, data, j];\n", + " }\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + "// Register the function which deals with the matplotlib target/channel.\n", + "// The kernel may be null if the page has been refreshed.\n", + "if (IPython.notebook.kernel != null) {\n", + " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", + "}\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "plot = qc.MatPlot()\n", + "plot.add(data2.MyMockAlazar_rawname)\n", + "plot.add(data2.MyMockAlazar_demod_freq_0_name)\n", + "plot.add(data2.MyMockAlazar_demod_freq_1_name)\n", + "#plot.add(data.MyMockAlazar_demod_freq_2_name)\n", + "plot.fig.axes[0].legend()" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "from toymodel import AModel, MockGates, MockSource, MockMeter, AverageGetter, AverageAndRaw\n", + "\n", + "# now create this \"experiment\", note that all these are instruments \n", + "model = AModel()\n", + "gates = MockGates('gates', model=model)\n", + "source = MockSource('source', model=model)\n", + "meter = MockMeter('meter', model=model)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DataSet:\n", + " mode = DataMode.LOCAL\n", + " location = 'data/2017-02-21/#028_{name}_14-12-35'\n", + " | | | \n", + " Setpoint | gates_chan0_set | chan0 | (2,)\n", + " Setpoint | timename_set | timename | (2, 629)\n", + " Measured | MyMockAlazar_rawname | rawname | (2, 629)\n", + " Measured | MyMockAlazar_demod_freq_0_name | demod_freq_0_name | (2, 629)\n", + " Measured | MyMockAlazar_demod_freq_1_name | demod_freq_1_name | (2, 629)\n", + " Measured | MyMockAlazar_demod_freq_2_name | demod_freq_2_name | (2, 629)\n", + "started at 2017-02-21 14:12:36\n" + ] + } + ], + "source": [ + "data3 = qc.Loop(gates.chan0.sweep(0,1,num=2)).each(a.acquisition).run()" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'__class__': 'qcodes.data.data_array.DataArray',\n", + " 'action_indices': (0, 0),\n", + " 'array_id': 'MyMockAlazar_rawname',\n", + " 'instrument': '__main__.MockAlazar',\n", + " 'instrument_name': 'MyMockAlazar',\n", + " 'is_setpoint': False,\n", + " 'label': 'rawlabel',\n", + " 'labels': ('rawlabel',\n", + " 'demod_freq_0_label',\n", + " 'demod_freq_1_label',\n", + " 'demod_freq_2_label'),\n", + " 'name': 'rawname',\n", + " 'names': ('rawname',\n", + " 'demod_freq_0_name',\n", + " 'demod_freq_1_name',\n", + " 'demod_freq_2_name'),\n", + " 'setpoint_labels': (('timelabel',),\n", + " ('timelabel',),\n", + " ('timelabel',),\n", + " ('timelabel',)),\n", + " 'setpoint_names': (('timename',),\n", + " ('timename',),\n", + " ('timename',),\n", + " ('timename',)),\n", + " 'shape': (2, 629),\n", + " 'unit': 'v',\n", + " 'units': ('v', 'v', 'v', 'v')}" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data3.metadata['arrays']['MyMockAlazar_rawname']" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'__class__': 'qcodes.data.data_array.DataArray',\n", + " 'action_indices': (0,),\n", + " 'array_id': 'timename_set',\n", + " 'is_setpoint': True,\n", + " 'label': 'timelabel',\n", + " 'name': 'timename',\n", + " 'shape': (2, 629),\n", + " 'unit': 's'}" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data3.metadata['arrays']['timename_set']" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'__class__': 'qcodes.data.data_array.DataArray',\n", + " 'action_indices': (),\n", + " 'array_id': 'gates_chan0_set',\n", + " 'instrument': 'toymodel.MockGates',\n", + " 'instrument_name': 'gates',\n", + " 'is_setpoint': True,\n", + " 'label': 'Gate Channel 0 (mV)',\n", + " 'name': 'chan0',\n", + " 'shape': (2,),\n", + " 'unit': '',\n", + " 'vals': ''}" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data3.metadata['arrays']['gates_chan0_set']" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'__class__': 'qcodes.data.data_array.DataArray',\n", + " 'action_indices': (0,),\n", + " 'array_id': 'timename_set',\n", + " 'is_setpoint': True,\n", + " 'label': 'timelabel',\n", + " 'name': 'timename',\n", + " 'shape': (2, 629),\n", + " 'unit': 's'}" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data3.metadata['arrays']['timename_set']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From d5bac792b85045116b142dc460fecf076e2a7430 Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Thu, 23 Feb 2017 10:49:16 +0100 Subject: [PATCH 139/180] Fix: Alazar add new controller that aims to be more general Also Handles multiple demod freq as a multiparameter that can be dynamically expanded --- .../acq_controllers/ATS9360Controller.py | 450 ++++++++++++++++++ .../AlazarTech/acqusition_parameters.py | 88 +++- 2 files changed, 537 insertions(+), 1 deletion(-) create mode 100644 qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py diff --git a/qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py b/qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py new file mode 100644 index 000000000000..b7d9e154f0b5 --- /dev/null +++ b/qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py @@ -0,0 +1,450 @@ +import logging +from ..ATS import AcquisitionController +import numpy as np +import qcodes.instrument_drivers.AlazarTech.acq_helpers as helpers +from ..acqusition_parameters import AcqVariablesParam, ExpandingAlazarArrayMultiParameter + + +class ATS9360Controller(AcquisitionController): + """ + This is the Acquisition Controller class which works with the ATS9360, + averaging over records and buffers and demodulating with software reference + signal(s). It may optionally integrate over the samples following the post processing + + + Args: + name: name for this acquisition_controller as an instrument + alazar_name: name of the alazar instrument such that this + controller can communicate with the Alazar + filter (default 'win'): filter to be used to filter out double freq + component ('win' - window, 'ls' - least squared, 'ave' - averaging) + numtaps (default 101): number of freq components used in filter + chan_b (default False): whether there is also a second channel of data + to be processed and returned. Not currently fully implemented. + **kwargs: kwargs are forwarded to the Instrument base class + + TODO(nataliejpg) test filter options + TODO(nataliejpg) finish implementation of channel b option + TODO(nataliejpg) what should be private? + TODO(nataliejpg) where should filter_dict live? + TODO(nataliejpg) demod_freq should be changeable number: maybe channels + """ + + filter_dict = {'win': 0, 'ls': 1, 'ave': 2} + + def __init__(self, name, alazar_name, filter: str = 'win', + numtaps: int =101, chan_b: bool = False, + integrate_samples: bool = False, + **kwargs): + self.filter_settings = {'filter': self.filter_dict[filter], + 'numtaps': numtaps} + self.chan_b = chan_b + self.number_of_channels = 2 + self.samples_per_record = None + self.sample_rate = None + super().__init__(name, alazar_name, **kwargs) + + self.add_parameter(name='acquisition', + integrate_samples=integrate_samples, + parameter_class=ExpandingAlazarArrayMultiParameter) + + self._integrate_samples = integrate_samples + if integrate_samples: + self.add_parameter(name='int_time', + check_and_update_fn=self._update_int_time, + default_fn=self._int_time_default, + parameter_class=AcqVariablesParam) + self.add_parameter(name='int_delay', + check_and_update_fn=self._update_int_delay, + default_fn=self._int_delay_default, + parameter_class=AcqVariablesParam) + + self.samples_divisor = self._get_alazar().samples_divisor + self._demod_freqs = [] + + def add_demodulator(self, demod_freq): + if demod_freq not in self.demod_freqs: + self._verify_demod_freq(demod_freq) + self._demod_freqs.append(demod_freq) + self.acquisition.set_setpoints_and_labels() + + def remove_demodulator(self, demod_freq): + if demod_freq in self.demod_freqs: + self._demod_freqs.pop(self.demod_freqs.index(demod_freq)) + self.acquisition.set_setpoints_and_labels() + + def _verify_demod_freq(self, value): + """ + Function to validate a demodulation frequency + + Checks: + - 1e6 <= value <= 500e6 + - number of oscillation measured using current 'int_time' param value + at this demodulation frequency value + - oversampling rate for this demodulation frequency + + Args: + value: proposed demodulation frequency + Returns: + bool: Returns True if suitable number of oscillations are measured and + oversampling is > 1, False otherwise. + Raises: + ValueError: If value is not a valid demodulation frequency. + """ + if (value is None) or not (1e6 <= value <= 500e6): + raise ValueError('demod_freqs must be 1e6 <= value <= 500e6') + isValid = True + alazar = self._get_alazar() + self.sample_rate = alazar.get_sample_rate() + min_oscillations_measured = self.int_time() * value + oversampling = self.sample_rate / (2 * value) + if min_oscillations_measured < 10: + isValid = False + logging.warning('{} oscillation measured for largest ' + 'demod freq, recommend at least 10: ' + 'decrease sampling rate, take ' + 'more samples or increase demodulation ' + 'freq'.format(min_oscillations_measured)) + elif oversampling < 1: + isValid = False + logging.warning('oversampling rate is {}, recommend > 1: ' + 'increase sampling rate or decrease ' + 'demodulation frequency'.format(oversampling)) + + return isValid + + def _update_int_time(self, value, **kwargs): + """ + Function to validate value for int_time before setting parameter + value and update instr attributes. + + Args: + value to be validated and used for instrument attribute update + + Checks: + 0 <= value <= 0.1 seconds + number of oscillation measured in this time + oversampling rate + + Sets: + sample_rate attr of acq controller to be that of alazar + samples_per_record of acq controller + acquisition_kwarg['samples_per_record'] of acquisition param + """ + if (value is None) or not (0 <= value <= 0.1): + raise ValueError('int_time must be 0 <= value <= 1') + + alazar = self._get_alazar() + self.sample_rate = alazar.get_sample_rate() + if self.get_max_demod_freq() is not None: + self._verify_demod_freq(self.get_max_demod_freq()) + if self.int_delay() is None: + self.int_delay.to_default() + + # update acquisition kwargs and acq controller value + total_time = value + self.int_delay() + samples_needed = total_time * self.sample_rate + self.samples_per_record = helpers.roundup( + samples_needed, self.samples_divisor) + self.acquisition.acquisition_kwargs.update( + samples_per_record=self.samples_per_record) + + def _update_int_delay(self, value, **kwargs): + """ + Function to validate value for int_delay before setting parameter + value and update instr attributes. + + Args: + value to be validated and used for instrument attribute update + + Checks: + 0 <= value <= 0.1 seconds + number of samples discarded >= numtaps + + Sets: + sample_rate attr of acq controller to be that of alazar + samples_per_record of acq controller + acquisition_kwarg['samples_per_record'] of acquisition param + setpoints of acquisition param + """ + int_delay_min = 0 + int_delay_max = 0.1 + if (value is None) or not (int_delay_min <= value <= int_delay_max): + raise ValueError('int_delay must be {} <= value <= {}. Got {}'.format(int_delay_min, + int_delay_max, + value)) + alazar = self._get_alazar() + self.sample_rate = alazar.get_sample_rate() + samples_delay_min = (self.filter_settings['numtaps'] - 1) + int_delay_min = samples_delay_min / self.sample_rate + if value < int_delay_min: + logging.warning( + 'delay is less than recommended for filter choice: ' + '(expect delay >= {})'.format(int_delay_min)) + + # update acquisition kwargs and acq controller value + total_time = value + (self.int_time() or 0) + samples_needed = total_time * self.sample_rate + self.samples_per_record = helpers.roundup( + samples_needed, self.samples_divisor) + self.acquisition.acquisition_kwargs.update( + samples_per_record=self.samples_per_record) + + def _int_delay_default(self): + """ + Function to generate default int_delay value + + Returns: + minimum int_delay recommended for (numtaps - 1) + samples to be discarded as recommended for filter + """ + alazar = self._get_alazar() + self.sample_rate = alazar.get_sample_rate() + samp_delay = self.filter_settings['numtaps'] - 1 + return samp_delay / self.sample_rate + + def _int_time_default(self): + """ + Function to generate default int_time value + + Returns: + max total time for integration based on samples_per_record, + sample_rate and int_delay + """ + if self.samples_per_record is (0 or None): + raise ValueError('Cannot set int_time to max if acq controller' + ' has 0 or None samples_per_record, choose a ' + 'value for int_time and samples_per_record will ' + 'be set accordingly') + alazar = self._get_alazar() + self.sample_rate = alazar.get_sample_rate() + total_time = ((self.samples_per_record / self.sample_rate) - + (self.int_delay() or 0)) + return total_time + + def get_demod_freqs(self): + """ + Function to get all the demod_freq parameter values in a numpy array + + Returns: + numpy array of demodulation frequencies + """ + return np.array(self._demod_freqs) + + def get_max_demod_freq(self): + """ + Returns: + the largest demodulation frequency + + """ + freqs = self.get_demod_freqs() + if len(freqs) > 0: + return max(freqs) + else: + return None + + def update_filter_settings(self, filter, numtaps): + """ + Updates the settings of the filter for filtering out + double frequency component for demodulation. + + Args: + filter (str): filter type ('win' or 'ls') + numtaps (int): numtaps for filter + """ + self.filter_settings.update({'filter': self.filter_dict[filter], + 'numtaps': numtaps}) + + def update_acquisition_kwargs(self, **kwargs): + """ + Updates the kwargs to be used when + alazar_driver.acquisition() is called via a get call of the + acquisition parameter. Should be used by the user for + updating averaging settings. If integrating over samples + 'samples_per_record' cannot be set directly it should instead + be set via the int_time and int_delay parameters. + + Kwargs (ints): + - records_per_buffer + - buffers_per_acquisition + - allocated_buffers + """ + if 'samples_per_record' in kwargs and self._integrate_samples: + raise ValueError('With integrating over samples ' + 'samples_per_record should not be set manually ' + 'via update_acquisition_kwargs and should instead' + ' be set by setting int_time and int_delay') + self.acquisition.acquisition_kwargs.update(**kwargs) + + def pre_start_capture(self): + """ + Called before capture start to update Acquisition Controller with + Alazar acquisition params and set up software wave for demodulation. + """ + alazar = self._get_alazar() + if self.samples_per_record != alazar.samples_per_record.get(): + raise Exception('acq controller samples per record does not match' + ' instrument value, most likely need ' + 'to set and check int_time and int_delay') + if self.sample_rate != alazar.get_sample_rate(): + raise Exception('acq controller sample rate does not match ' + 'instrument value, most likely need ' + 'to set and check int_time and int_delay') + + demod_freqs = self.get_demod_freqs() + # if len(demod_freqs) == 0: + # raise Exception('no demod_freqs set') + + self.records_per_buffer = alazar.records_per_buffer.get() + self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() + self.board_info = alazar.get_idn() + self.buffer = np.zeros(self.samples_per_record * + self.records_per_buffer * + self.number_of_channels) + + if demod_freqs: + integer_list = np.arange(self.samples_per_record) + angle_mat = 2 * np.pi * \ + np.outer(demod_freqs, integer_list) / self.sample_rate + self.cos_mat = np.cos(angle_mat) + self.sin_mat = np.sin(angle_mat) + + def pre_acquire(self): + pass + + def handle_buffer(self, data): + """ + Adds data from Alazar to buffer (effectively averaging) + """ + self.buffer += data + + def post_acquire(self): + """ + Processes the data according to ATS9360 settings, splitting into + records and averaging over them, then applying demodulation fit + nb: currently only channel A. Depending on the value of integrate_samples + it may either sum over all samples or return arrays of individual samples + for all the data given below. + + Returns: + - Raw data + - For each demodulation frequency: + * magnitude + * phase + """ + + # for ATS9360 samples are arranged in the buffer as follows: + # S00A, S00B, S01A, S01B...S10A, S10B, S11A, S11B... + # where SXYZ is record X, sample Y, channel Z. + + # break buffer up into records and averages over them + reshaped_buf = self.buffer.reshape(self.records_per_buffer, + self.samples_per_record, + self.number_of_channels) + recordA = np.uint16(np.mean(reshaped_buf[:, :, 0], axis=0) / + self.buffers_per_acquisition) + + # TODO(nataliejpg): test above version works on alazar and + # compare performance + recordA = self._to_volts(recordA) + # records_per_acquisition = (self.buffers_per_acquisition * + # self.records_per_buffer) + # recA = np.zeros(self.samples_per_record) + # for i in range(self.records_per_buffer): + # i0 = (i * self.samples_per_record * self.number_of_channels) + # i1 = (i0 + self.samples_per_record * self.number_of_channels) + # recA += self.buffer[i0:i1:self.number_of_channels] + # recordA = np.uint16(recA / records_per_acquisition) + unpacked = [] + if self._integrate_samples: + unpacked.append(np.mean(recordA, axis=-1)) + else: + unpacked.append(recordA) + # do demodulation + if self.get_demod_freqs(): + magA, phaseA = self._fit(recordA) + if self._integrate_samples: + magA = np.mean(magA, axis=-1) + phaseA = np.mean(phaseA, axis=-1) + for i in range(magA.shape[0]): + unpacked.append(magA[i]) + unpacked.append(phaseA[i]) + # same for chan b + if self.chan_b: + raise NotImplementedError('chan b code not complete') + + + return tuple(unpacked) + + def _to_volts(self, record): + # convert rec to volts + bps = self.board_info['bits_per_sample'] + if bps == 12: + volt_rec = helpers.sample_to_volt_u12(record, bps) + else: + logging.warning('sample to volt conversion does not exist for' + ' bps != 12, centered raw samples returned') + volt_rec = record - np.mean(record) + return volt_rec + + def _fit(self, volt_rec): + """ + Applies low bandpass filter and demodulation fit, + and integration limits to samples array + + Args: + record (numpy array): record from alazar to be multiplied + with the software signal, filtered and limited + to integration limits shape = (samples_taken, ) + + Returns: + magnitude (numpy array): shape = (demod_length, samples_after_limiting) + phase (numpy array): shape = (demod_length, samples_after_limiting) + """ + + # volt_rec to matrix and multiply with demodulation signal matrices + volt_rec_mat = np.outer(np.ones(self._demod_length), volt_rec) + re_mat = np.multiply(volt_rec_mat, self.cos_mat) + im_mat = np.multiply(volt_rec_mat, self.sin_mat) + + # filter out higher freq component + cutoff = self.get_max_demod_freq() / 10 + if self.filter_settings['filter'] == 0: + re_filtered = helpers.filter_win(re_mat, cutoff, + self.sample_rate, + self.filter_settings['numtaps'], + axis=-1) + im_filtered = helpers.filter_win(im_mat, cutoff, + self.sample_rate, + self.filter_settings['numtaps'], + axis=-1) + elif self.filter_settings['filter'] == 1: + re_filtered = helpers.filter_ls(re_mat, cutoff, + self.sample_rate, + self.filter_settings['numtaps'], + axis=-1) + im_filtered = helpers.filter_ls(im_mat, cutoff, + self.sample_rate, + self.filter_settings['numtaps'], + axis=-1) + elif self.filter_settings['filter'] == 2: + re_filtered = re_mat + im_filtered = im_mat + + if self.__integrate_samples: + # apply integration limits + beginning = int(self.int_delay() * self.sample_rate) + end = beginning + int(self.int_time() * self.sample_rate) + + re_limited = re_filtered[:, beginning:end] + im_limited = im_filtered[:, beginning:end] + else: + re_limited = re_filtered + im_limited = im_filtered + + # convert to magnitude and phase + complex_mat = re_limited + im_limited * 1j + magnitude = abs(complex_mat) + phase = np.angle(complex_mat, deg=True) + + return magnitude, phase diff --git a/qcodes/instrument_drivers/AlazarTech/acqusition_parameters.py b/qcodes/instrument_drivers/AlazarTech/acqusition_parameters.py index 994fe256e3bb..bed3339079ab 100644 --- a/qcodes/instrument_drivers/AlazarTech/acqusition_parameters.py +++ b/qcodes/instrument_drivers/AlazarTech/acqusition_parameters.py @@ -1,5 +1,5 @@ from qcodes import Parameter, MultiParameter - +import numpy as np class AcqVariablesParam(Parameter): """ @@ -201,3 +201,89 @@ def update_rec_sweep(self, rec_npts, rec_start=None, rec_stop=None): (self._buf_npts, self._rec_npts)) # self.setpoints = ((self._buf_list, self._rec_list), # (self._buf_list, self._rec_list)) + + +class ExpandingAlazarArrayMultiParameter(MultiParameter): + def __init__(self, + name, + instrument, + names = ('raw_output',), + labels = ("raw output",), + units = ('V',), + shapes = ((),), + setpoints = ((),), + setpoint_names = (('time',),), + setpoint_labels = (('time',),), + setpoint_units = (('s',),), + integrate_samples=False): + self.acquisition_kwargs = {} + self._integrate_samples = integrate_samples + super().__init__(name, + names=names, + units=units, + labels=labels, + shapes=shapes, + instrument=instrument, + setpoints=setpoints, + setpoint_names=setpoint_names, + setpoint_labels=setpoint_labels, + setpoint_units=setpoint_units) + + def set_setpoints_and_labels(self): + if not self._integrate_samples: + if self._instrument.sample_rate and self._instrument.samples_per_record: + start = 0 + step = 1/self._instrument.sample_rate + stop = self._instrument.samples_per_record/self._instrument.sample_rate + else: + start = 0 + step = 1 + stop = 1 + arraysetpoints = (tuple(np.arange(start, stop, step)),) + base_shape = (len(arraysetpoints[0]),) + else: + arraysetpoints = () + base_shape = () + setpoints = [arraysetpoints] + names = [self.names[0]] + labels = [self.labels[0]] + setpoint_name = self.setpoint_names[0] + setpoint_names = [setpoint_name] + setpoint_label = self.setpoint_labels[0] + setpoint_labels = [setpoint_label] + setpoint_unit = self.setpoint_units[0] + setpoint_units = [setpoint_unit] + units = [self.units[0]] + shapes = [base_shape] + for i, demod_freq in enumerate(self._instrument.demod_freqs): + names.append("demod_freq_{}_mag".format(i)) + labels.append("demod freq {} mag".format(i)) + names.append("demod_freq_{}_phase".format(i)) + labels.append("demod freq {} phase".format(i)) + units.append('v') + units.append('v') + shapes.append(base_shape) + shapes.append(base_shape) + setpoints.append(arraysetpoints) + setpoint_names.append(setpoint_name) + setpoint_labels.append(setpoint_label) + setpoint_units.append(setpoint_unit) + setpoints.append(arraysetpoints) + setpoint_names.append(setpoint_name) + setpoint_labels.append(setpoint_label) + setpoint_units.append(setpoint_unit) + self.metadata['demod_freqs'] = self._instrument.demod_freqs + self.names = tuple(names) + self.labels = tuple(labels) + self.units = tuple(units) + self.shapes = tuple(shapes) + self.setpoints = tuple(setpoints) + self.setpoint_names = tuple(setpoint_names) + self.setpoint_labels = tuple(setpoint_labels) + self.setpoint_units = tuple(setpoint_units) + + def get(self): + output = self._instrument._get_alazar().acquire( + acquisition_controller=self._instrument, + **self.acquisition_kwargs) + return output \ No newline at end of file From 810dc252cf68de9ca9e180be0d5afc2bd195c6e0 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Thu, 23 Feb 2017 17:04:37 +0100 Subject: [PATCH 140/180] Fix: correct calls to cdll with numpy arrays could also rewrite these as pure ctypes datatypes as we are not doing any array operations --- qcodes/instrument_drivers/AlazarTech/ATS.py | 32 +++++++++++---------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/ATS.py b/qcodes/instrument_drivers/AlazarTech/ATS.py index 96572812704e..f4b0a08382b4 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS.py @@ -282,46 +282,46 @@ def get_idn(self): revision = np.array([0], dtype=np.uint8) self._call_dll('AlazarGetCPLDVersion', self._handle, - major.ctypes.data, - minor.ctypes.data) + major.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8)), + minor.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8))) cpld_ver = str(major[0]) + "." + str(minor[0]) self._call_dll('AlazarGetDriverVersion', - major.ctypes.data, - minor.ctypes.data, - revision.ctypes.data) + major.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8)), + major.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8)), + revision.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8))) driver_ver = str(major[0])+"."+str(minor[0])+"."+str(revision[0]) self._call_dll('AlazarGetSDKVersion', - major.ctypes.data, - minor.ctypes.data, - revision.ctypes.data) + major.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8)), + minor.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8)), + revision.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8))) sdk_ver = str(major[0])+"."+str(minor[0])+"."+str(revision[0]) value = np.array([0], dtype=np.uint32) self._call_dll('AlazarQueryCapability', - self._handle, 0x10000024, 0, value.ctypes.data) + self._handle, 0x10000024, 0, value.ctypes.data_as(ctypes.POINTER(ctypes.c_uint32))) serial = str(value[0]) self._call_dll('AlazarQueryCapability', - self._handle, 0x10000026, 0, value.ctypes.data) + self._handle, 0x10000026, 0, value.ctypes.data_as(ctypes.POINTER(ctypes.c_uint32))) latest_cal_date = (str(value[0])[0:2] + "-" + str(value[0])[2:4] + "-" + str(value[0])[4:6]) self._call_dll('AlazarQueryCapability', - self._handle, 0x1000002A, 0, value.ctypes.data) + self._handle, 0x1000002A, 0, value.ctypes.data_as(ctypes.POINTER(ctypes.c_uint32))) memory_size = str(value[0]) self._call_dll('AlazarQueryCapability', - self._handle, 0x1000002C, 0, value.ctypes.data) + self._handle, 0x1000002C, 0, value.ctypes.data_as(ctypes.POINTER(ctypes.c_uint32))) asopc_type = str(value[0]) # see the ATS-SDK programmer's guide # about the encoding of the link speed self._call_dll('AlazarQueryCapability', - self._handle, 0x10000030, 0, value.ctypes.data) + self._handle, 0x10000030, 0, value.ctypes.data_as(ctypes.POINTER(ctypes.c_uint32))) pcie_link_speed = str(value[0] * 2.5 / 10) + "GB/s" self._call_dll('AlazarQueryCapability', - self._handle, 0x10000031, 0, value.ctypes.data) + self._handle, 0x10000031, 0, value.ctypes.data_as(ctypes.POINTER(ctypes.c_uint32))) pcie_link_width = str(value[0]) return {'firmware': None, @@ -453,7 +453,9 @@ def _get_channel_info(self, handle): bps = np.array([0], dtype=np.uint8) # bps bits per sample max_s = np.array([0], dtype=np.uint32) # max_s memory size in samples self._call_dll('AlazarGetChannelInfo', - handle, max_s.ctypes.data, bps.ctypes.data) + handle, + max_s.ctypes.data_as(ctypes.POINTER(ctypes.c_uint32)), + bps.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8))) return max_s[0], bps[0] def acquire(self, mode=None, samples_per_record=None, From 731d98b7e00a2a8283a9d23d47f66f02fe6b73c8 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 Feb 2017 11:04:20 +0100 Subject: [PATCH 141/180] Fix: use ctypes api directly --- qcodes/instrument_drivers/AlazarTech/ATS.py | 72 +++++++++++---------- 1 file changed, 37 insertions(+), 35 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/ATS.py b/qcodes/instrument_drivers/AlazarTech/ATS.py index f4b0a08382b4..9212753fd5fb 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS.py @@ -201,7 +201,7 @@ def get_board_info(cls, dll, system_id, board_id): Get the information from a connected Alazar board Args: - dll (string): path of the Alazar driver dll + dll (CDLL): CTypes CDLL system_id: id of the Alazar system board_id: id of the board within the alazar system @@ -277,52 +277,53 @@ def get_idn(self): max_s, bps = self._get_channel_info(self._handle) - major = np.array([0], dtype=np.uint8) - minor = np.array([0], dtype=np.uint8) - revision = np.array([0], dtype=np.uint8) + major = ctypes.c_uint8(0) + minor = ctypes.c_uint8(0) + revision = ctypes.c_uint8(0) self._call_dll('AlazarGetCPLDVersion', self._handle, - major.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8)), - minor.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8))) - cpld_ver = str(major[0]) + "." + str(minor[0]) + ctypes.byref(major), + ctypes.byref(minor)) + cpld_ver = str(major.value) + "." + str(minor.value) self._call_dll('AlazarGetDriverVersion', - major.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8)), - major.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8)), - revision.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8))) - driver_ver = str(major[0])+"."+str(minor[0])+"."+str(revision[0]) + ctypes.byref(major), + ctypes.byref(minor), + ctypes.byref(revision)) + driver_ver = str(major.value)+"."+str(minor.value)+"."+str(revision.value) self._call_dll('AlazarGetSDKVersion', - major.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8)), - minor.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8)), - revision.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8))) - sdk_ver = str(major[0])+"."+str(minor[0])+"."+str(revision[0]) + ctypes.byref(major), + ctypes.byref(minor), + ctypes.byref(revision)) + sdk_ver = str(major.value)+"."+str(minor.value)+"."+str(revision.value) - value = np.array([0], dtype=np.uint32) + value = ctypes.c_uint32(0) self._call_dll('AlazarQueryCapability', - self._handle, 0x10000024, 0, value.ctypes.data_as(ctypes.POINTER(ctypes.c_uint32))) - serial = str(value[0]) + self._handle, 0x10000024, 0, ctypes.byref(value)) + serial = str(value.value) self._call_dll('AlazarQueryCapability', - self._handle, 0x10000026, 0, value.ctypes.data_as(ctypes.POINTER(ctypes.c_uint32))) - latest_cal_date = (str(value[0])[0:2] + "-" + - str(value[0])[2:4] + "-" + - str(value[0])[4:6]) + self._handle, 0x10000026, 0, ctypes.byref(value)) + Capabilitystring = str(value.value) + latest_cal_date = (Capabilitystring[0:2] + "-" + + Capabilitystring[2:4] + "-" + + Capabilitystring[4:6]) self._call_dll('AlazarQueryCapability', - self._handle, 0x1000002A, 0, value.ctypes.data_as(ctypes.POINTER(ctypes.c_uint32))) - memory_size = str(value[0]) + self._handle, 0x1000002A, 0, ctypes.byref(value)) + memory_size = str(value.value) self._call_dll('AlazarQueryCapability', - self._handle, 0x1000002C, 0, value.ctypes.data_as(ctypes.POINTER(ctypes.c_uint32))) - asopc_type = str(value[0]) + self._handle, 0x1000002C, 0, ctypes.byref(value)) + asopc_type = str(value.value) # see the ATS-SDK programmer's guide # about the encoding of the link speed self._call_dll('AlazarQueryCapability', - self._handle, 0x10000030, 0, value.ctypes.data_as(ctypes.POINTER(ctypes.c_uint32))) - pcie_link_speed = str(value[0] * 2.5 / 10) + "GB/s" + self._handle, 0x10000030, 0, ctypes.byref(value)) + pcie_link_speed = str(value.value * 2.5 / 10) + "GB/s" self._call_dll('AlazarQueryCapability', - self._handle, 0x10000031, 0, value.ctypes.data_as(ctypes.POINTER(ctypes.c_uint32))) - pcie_link_width = str(value[0]) + self._handle, 0x10000031, 0, ctypes.byref(value)) + pcie_link_width = str(value.value) return {'firmware': None, 'model': board_kind, @@ -450,13 +451,13 @@ def config(self, clock_source=None, sample_rate=None, clock_edge=None, self.aux_io_param) def _get_channel_info(self, handle): - bps = np.array([0], dtype=np.uint8) # bps bits per sample - max_s = np.array([0], dtype=np.uint32) # max_s memory size in samples + bps = ctypes.c_uint8(0) # bps bits per sample + max_s = ctypes.c_uint32(0) # max_s memory size in samples self._call_dll('AlazarGetChannelInfo', handle, - max_s.ctypes.data_as(ctypes.POINTER(ctypes.c_uint32)), - bps.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8))) - return max_s[0], bps[0] + ctypes.byref(max_s), + ctypes.byref(bps)) + return max_s.value, bps.value def acquire(self, mode=None, samples_per_record=None, records_per_buffer=None, buffers_per_acquisition=None, @@ -591,6 +592,7 @@ def acquire(self, mode=None, samples_per_record=None, # bytes per sample max_s, bps = self._get_channel_info(self._handle) + # TODO(JHN) Why +7 bytes_per_sample = (bps + 7) // 8 # bytes per record From 1fa1c340073e3d26d9259ce9b599364f29f6d683 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Tue, 28 Feb 2017 14:50:01 +0100 Subject: [PATCH 142/180] fix: some comments --- qcodes/instrument_drivers/AlazarTech/ATS.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/ATS.py b/qcodes/instrument_drivers/AlazarTech/ATS.py index 9212753fd5fb..a8b746fe2d62 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS.py @@ -592,9 +592,8 @@ def acquire(self, mode=None, samples_per_record=None, # bytes per sample max_s, bps = self._get_channel_info(self._handle) - # TODO(JHN) Why +7 + # TODO(JHN) Why +7 I guess its to do ceil division? bytes_per_sample = (bps + 7) // 8 - # bytes per record bytes_per_record = bytes_per_sample * samples_per_record @@ -610,6 +609,7 @@ def acquire(self, mode=None, samples_per_record=None, # create buffers for acquisition # TODO(nataliejpg) should this be > 1 (as intuitive) or > 8 as in alazar sample code? + # the alazar code probably uses bits per sample? sample_type = ctypes.c_uint8 if bytes_per_sample > 1: sample_type = ctypes.c_uint16 From f26977f1bc08b425269dc01dd76bd10512c75542 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Tue, 28 Feb 2017 14:50:58 +0100 Subject: [PATCH 143/180] Fix: Simplify memory allocation in ATS driver --- qcodes/instrument_drivers/AlazarTech/ATS.py | 25 ++++----------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/ATS.py b/qcodes/instrument_drivers/AlazarTech/ATS.py index a8b746fe2d62..f0c30df7b452 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS.py @@ -980,22 +980,13 @@ def __init__(self, c_sample_type, size_bytes): self._allocated = True self.addr = None - if os.name == 'nt': - MEM_COMMIT = 0x1000 - PAGE_READWRITE = 0x4 - ctypes.windll.kernel32.VirtualAlloc.argtypes = [ctypes.c_void_p, ctypes.c_long, ctypes.c_long, ctypes.c_long] - ctypes.windll.kernel32.VirtualAlloc.restype = ctypes.c_void_p - self.addr = ctypes.windll.kernel32.VirtualAlloc( - 0, ctypes.c_long(size_bytes), MEM_COMMIT, PAGE_READWRITE) - else: - self._allocated = False - raise Exception("Unsupported OS") - ctypes_array = (c_sample_type * - (size_bytes // bytes_per_sample)).from_address(self.addr) + ctypes_array_type = c_sample_type * (size_bytes // bytes_per_sample) # PyCharm deducts the wrong type + # This is not an int but a PyCArrayType which is callable. Not sure how to annotate this correctly + ctypes_array = ctypes_array_type() self.buffer = np.frombuffer(ctypes_array, dtype=npSampleType) self.ctypes_buffer = ctypes_array - pointer, read_only_flag = self.buffer.__array_interface__['data'] + self.addr = ctypes.addressof(self.ctypes_buffer) def free_mem(self): """ @@ -1003,14 +994,6 @@ def free_mem(self): """ self._allocated = False - if os.name == 'nt': - MEM_RELEASE = 0x8000 - ctypes.windll.kernel32.VirtualFree.argtypes = [ctypes.c_void_p, ctypes.c_long, ctypes.c_long] - ctypes.windll.kernel32.VirtualFree.restype = ctypes.c_int - ctypes.windll.kernel32.VirtualFree(ctypes.c_void_p(self.addr), 0, MEM_RELEASE); - else: - self._allocated = True - raise Exception("Unsupported OS") def __del__(self): """ From 8ca333d5a9ba47577355943042c3f643444f1583 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Tue, 28 Feb 2017 14:53:11 +0100 Subject: [PATCH 144/180] Fix: comments and typos --- qcodes/instrument_drivers/AlazarTech/ATS9360.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/ATS9360.py b/qcodes/instrument_drivers/AlazarTech/ATS9360.py index e507030fbb95..8963ef71e1f5 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS9360.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS9360.py @@ -16,6 +16,7 @@ class AlazarTech_ATS9360(AlazarTech_ATS): # samples divisor is listed in the manual as being 32 but this gave # incorrect data when tested for divisors less than 128 + # JHN As far as I can see this is listed as 128 in table 8 of the SDK manual samples_divisor = 128 def __init__(self, name, **kwargs): @@ -170,7 +171,7 @@ def __init__(self, name, **kwargs): # ----- Parameters for the acquire function ----- self.add_parameter(name='mode', parameter_class=AlazarParameter, - label='Acquisiton mode', + label='Acquisition mode', unit=None, value='NPT', byte_to_value_dict={0x200: 'NPT', 0x400: 'TS'}) @@ -201,7 +202,7 @@ def __init__(self, name, **kwargs): byte_to_value_dict={1: 'A', 2: 'B', 3: 'AB'}) self.add_parameter(name='transfer_offset', parameter_class=AlazarParameter, - label='Transer Offset', + label='Transfer Offset', unit='Samples', value=0, vals=validators.Ints(min_value=0)) From 25ba6eaeaf448260c3fc91aa277d2e90665bc3a7 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Tue, 28 Feb 2017 14:54:23 +0100 Subject: [PATCH 145/180] Add support for both internal and external clock --- qcodes/instrument_drivers/AlazarTech/ATS.py | 12 ++- .../instrument_drivers/AlazarTech/ATS9360.py | 74 ++++++++++++++++++- 2 files changed, 80 insertions(+), 6 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/ATS.py b/qcodes/instrument_drivers/AlazarTech/ATS.py index f0c30df7b452..2a287dd603f8 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS.py @@ -341,6 +341,7 @@ def get_idn(self): 'pcie_link_width': pcie_link_width} def config(self, clock_source=None, sample_rate=None, clock_edge=None, + external_sample_rate=None, decimation=None, coupling=None, channel_range=None, impedance=None, bwlimit=None, trigger_operation=None, trigger_engine1=None, trigger_source1=None, @@ -385,6 +386,7 @@ def config(self, clock_source=None, sample_rate=None, clock_edge=None, self._set_if_present('clock_source', clock_source) self._set_if_present('sample_rate', sample_rate) + self._set_if_present('external_sample_rate', external_sample_rate) self._set_if_present('clock_edge', clock_edge) self._set_if_present('decimation', decimation) @@ -414,8 +416,14 @@ def config(self, clock_source=None, sample_rate=None, clock_edge=None, self._set_if_present('aux_io_param', aux_io_param) # endregion + + if clock_source == 'EXTERNAL_CLOCK_10MHz_REF': + sample_rate = self.external_sample_rate + elif clock_source == 'INTERNAL_CLOCK': + sample_rate = self.sample_rate + self._call_dll('AlazarSetCaptureClock', - self._handle, self.clock_source, self.sample_rate, + self._handle, self.clock_source, sample_rate, self.clock_edge, self.decimation) for i in range(1, self.channels + 1): @@ -865,7 +873,7 @@ def __init__(self, name=None, label=None, unit=None, instrument=None, # TODO(damazter) (S) test this validator vals = validators.Enum(*byte_to_value_dict.values()) - super().__init__(name=name, label=label, units=unit, vals=vals) + super().__init__(name=name, label=label, unit=unit, vals=vals) self.instrument = instrument self._byte = None self._uptodate_flag = False diff --git a/qcodes/instrument_drivers/AlazarTech/ATS9360.py b/qcodes/instrument_drivers/AlazarTech/ATS9360.py index 8963ef71e1f5..163de13696bc 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS9360.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS9360.py @@ -30,13 +30,54 @@ def __init__(self, name, **kwargs): parameter_class=AlazarParameter, label='Clock Source', unit=None, - value='EXTERNAL_CLOCK_10MHz_REF', - byte_to_value_dict={7: 'EXTERNAL_CLOCK_10MHz_REF'}) - self.add_parameter(name='sample_rate', + value='INTERNAL_CLOCK', + byte_to_value_dict={1: 'INTERNAL_CLOCK', + 2: 'FAST_EXTERNAL_CLOCK', + 7: 'EXTERNAL_CLOCK_10MHz_REF'}) + self.add_parameter(name='external_sample_rate', parameter_class=AlazarParameter, - label='Sample Rate', + label='External Sample Rate', unit='S/s', value=500000000) + self.add_parameter(name='sample_rate', + parameter_class=AlazarParameter, + label='Internal Sample Rate', + unit='S/s', + value=500000000, + byte_to_value_dict={0x00000001: 1000, + 0x00000002: 2000, + 0x00000004: 5000, + 0x00000008: 10000, + 0x0000000A: 20000, + 0x0000000C: 50000, + 0x0000000E: 100000, + 0x00000010: 200000, + 0x00000012: 500000, + 0x00000014: 1000000, + 0x00000018: 2000000, + 0x0000001A: 5000000, + 0x0000001C: 10000000, + 0x0000001E: 20000000, + 0x00000021: 25000000, + 0x00000022: 50000000, + 0x00000024: 100000000, + 0x00000025: 125000000, + 0x00000026: 160000000, + 0x00000027: 180000000, + 0x00000028: 200000000, + 0x0000002B: 250000000, + 0x00000030: 500000000, + 0x00000032: 800000000, + 0x00000035: 1000000000, + 0x00000037: 1200000000, + 0x0000003A: 1500000000, + 0x0000003D: 1800000000, + 0x0000003F: 2000000000, + 0x0000006A: 2400000000, + 0x00000075: 3000000000, + 0x0000007B: 3600000000, + 0x00000080: 4000000000, + }) self.add_parameter(name='clock_edge', parameter_class=AlazarParameter, label='Clock Edge', @@ -266,3 +307,28 @@ def __init__(self, name, **kwargs): if model != 'ATS9360': raise Exception("The Alazar board kind is not 'ATS9360'," " found '" + str(model) + "' instead.") + + + def get_sample_rate(self): + """ + Obtain the effective sampling rate of the acquisition + based on clock type, clock speed and decimation + + Returns: + the number of samples (per channel) per second + """ + if self.clock_source.get() == 'EXTERNAL_CLOCK_10MHz_REF': + rate = self.external_sample_rate.get() + elif self.clock_source.get() == 'INTERNAL_CLOCK': + rate = self.sample_rate.get() + else: + raise Exception("Don't know how to get sample rate with {}".format(alazar.clock_source.get())) + + if rate == '1GHz_REFERENCE_CLOCK': + rate = 1e9 + + decimation = self.decimation.get() + if decimation > 0: + return rate / decimation + else: + return rate From 9619f572941e90fa312265b7053bfbf1b0ba02c6 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Tue, 28 Feb 2017 14:56:47 +0100 Subject: [PATCH 146/180] Fix: Acqusition parameters correct setpoints --- .../AlazarTech/acqusition_parameters.py | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/acqusition_parameters.py b/qcodes/instrument_drivers/AlazarTech/acqusition_parameters.py index bed3339079ab..933efe6a933a 100644 --- a/qcodes/instrument_drivers/AlazarTech/acqusition_parameters.py +++ b/qcodes/instrument_drivers/AlazarTech/acqusition_parameters.py @@ -210,8 +210,8 @@ def __init__(self, names = ('raw_output',), labels = ("raw output",), units = ('V',), - shapes = ((),), - setpoints = ((),), + shapes = ((1,),), + setpoints = (((1,),),), setpoint_names = (('time',),), setpoint_labels = (('time',),), setpoint_units = (('s',),), @@ -231,15 +231,17 @@ def __init__(self, def set_setpoints_and_labels(self): if not self._integrate_samples: - if self._instrument.sample_rate and self._instrument.samples_per_record: + + if self._instrument._get_alazar().sample_rate.get() and self.acquisition_kwargs.get('samples_per_record'): start = 0 - step = 1/self._instrument.sample_rate - stop = self._instrument.samples_per_record/self._instrument.sample_rate + samples = self.acquisition_kwargs['samples_per_record'] + stop = samples/self._instrument._get_alazar().sample_rate.get() else: start = 0 - step = 1 + samples = 1 stop = 1 - arraysetpoints = (tuple(np.arange(start, stop, step)),) + print("start {} stop {} num steps {}".format(start, stop, samples)) + arraysetpoints = (tuple(np.linspace(start, stop, samples)),) base_shape = (len(arraysetpoints[0]),) else: arraysetpoints = () @@ -255,7 +257,7 @@ def set_setpoints_and_labels(self): setpoint_units = [setpoint_unit] units = [self.units[0]] shapes = [base_shape] - for i, demod_freq in enumerate(self._instrument.demod_freqs): + for i, demod_freq in enumerate(self._instrument._demod_freqs): names.append("demod_freq_{}_mag".format(i)) labels.append("demod freq {} mag".format(i)) names.append("demod_freq_{}_phase".format(i)) @@ -272,7 +274,7 @@ def set_setpoints_and_labels(self): setpoint_names.append(setpoint_name) setpoint_labels.append(setpoint_label) setpoint_units.append(setpoint_unit) - self.metadata['demod_freqs'] = self._instrument.demod_freqs + self.metadata['demod_freqs'] = self._instrument._demod_freqs self.names = tuple(names) self.labels = tuple(labels) self.units = tuple(units) From 0fdc9d60d9f2e56e426271dd528a69ef3f89ecd8 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Tue, 28 Feb 2017 14:57:46 +0100 Subject: [PATCH 147/180] Fix: ATS9360 controller wip improvements --- .../acq_controllers/ATS9360Controller.py | 100 ++++++++++-------- 1 file changed, 56 insertions(+), 44 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py b/qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py index b7d9e154f0b5..0e8ac426311e 100644 --- a/qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py +++ b/qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py @@ -40,8 +40,6 @@ def __init__(self, name, alazar_name, filter: str = 'win', 'numtaps': numtaps} self.chan_b = chan_b self.number_of_channels = 2 - self.samples_per_record = None - self.sample_rate = None super().__init__(name, alazar_name, **kwargs) self.add_parameter(name='acquisition', @@ -63,7 +61,7 @@ def __init__(self, name, alazar_name, filter: str = 'win', self._demod_freqs = [] def add_demodulator(self, demod_freq): - if demod_freq not in self.demod_freqs: + if demod_freq not in self._demod_freqs: self._verify_demod_freq(demod_freq) self._demod_freqs.append(demod_freq) self.acquisition.set_setpoints_and_labels() @@ -95,9 +93,13 @@ def _verify_demod_freq(self, value): raise ValueError('demod_freqs must be 1e6 <= value <= 500e6') isValid = True alazar = self._get_alazar() - self.sample_rate = alazar.get_sample_rate() - min_oscillations_measured = self.int_time() * value - oversampling = self.sample_rate / (2 * value) + sample_rate = alazar.get_sample_rate() + if 'int_time' in self.parameters: + int_time = self.int_time.get() + else: + int_time = self.acquisition.acquisition_kwargs["samples_per_record"]/sample_rate + min_oscillations_measured = int_time * value + oversampling = sample_rate / (2 * value) if min_oscillations_measured < 10: isValid = False logging.warning('{} oscillation measured for largest ' @@ -135,7 +137,7 @@ def _update_int_time(self, value, **kwargs): raise ValueError('int_time must be 0 <= value <= 1') alazar = self._get_alazar() - self.sample_rate = alazar.get_sample_rate() + sample_rate = alazar.get_sample_rate() if self.get_max_demod_freq() is not None: self._verify_demod_freq(self.get_max_demod_freq()) if self.int_delay() is None: @@ -143,11 +145,11 @@ def _update_int_time(self, value, **kwargs): # update acquisition kwargs and acq controller value total_time = value + self.int_delay() - samples_needed = total_time * self.sample_rate - self.samples_per_record = helpers.roundup( + samples_needed = total_time * sample_rate + samples_per_record = helpers.roundup( samples_needed, self.samples_divisor) self.acquisition.acquisition_kwargs.update( - samples_per_record=self.samples_per_record) + samples_per_record=samples_per_record) def _update_int_delay(self, value, **kwargs): """ @@ -174,9 +176,9 @@ def _update_int_delay(self, value, **kwargs): int_delay_max, value)) alazar = self._get_alazar() - self.sample_rate = alazar.get_sample_rate() + sample_rate = alazar.get_sample_rate() samples_delay_min = (self.filter_settings['numtaps'] - 1) - int_delay_min = samples_delay_min / self.sample_rate + int_delay_min = samples_delay_min / sample_rate if value < int_delay_min: logging.warning( 'delay is less than recommended for filter choice: ' @@ -184,11 +186,11 @@ def _update_int_delay(self, value, **kwargs): # update acquisition kwargs and acq controller value total_time = value + (self.int_time() or 0) - samples_needed = total_time * self.sample_rate - self.samples_per_record = helpers.roundup( + samples_needed = total_time * sample_rate + samples_per_record = helpers.roundup( samples_needed, self.samples_divisor) self.acquisition.acquisition_kwargs.update( - samples_per_record=self.samples_per_record) + samples_per_record=samples_per_record) def _int_delay_default(self): """ @@ -199,9 +201,9 @@ def _int_delay_default(self): samples to be discarded as recommended for filter """ alazar = self._get_alazar() - self.sample_rate = alazar.get_sample_rate() + sample_rate = alazar.get_sample_rate() samp_delay = self.filter_settings['numtaps'] - 1 - return samp_delay / self.sample_rate + return samp_delay / sample_rate def _int_time_default(self): """ @@ -211,14 +213,15 @@ def _int_time_default(self): max total time for integration based on samples_per_record, sample_rate and int_delay """ - if self.samples_per_record is (0 or None): + samples_per_record = self.acquisition.acquisition_kwargs.get('samples_per_record') + if samples_per_record in (0 or None): raise ValueError('Cannot set int_time to max if acq controller' ' has 0 or None samples_per_record, choose a ' 'value for int_time and samples_per_record will ' 'be set accordingly') alazar = self._get_alazar() - self.sample_rate = alazar.get_sample_rate() - total_time = ((self.samples_per_record / self.sample_rate) - + sample_rate = alazar.get_sample_rate() + total_time = ((samples_per_record / sample_rate) - (self.int_delay() or 0)) return total_time @@ -275,6 +278,7 @@ def update_acquisition_kwargs(self, **kwargs): 'via update_acquisition_kwargs and should instead' ' be set by setting int_time and int_delay') self.acquisition.acquisition_kwargs.update(**kwargs) + self.acquisition.set_setpoints_and_labels() def pre_start_capture(self): """ @@ -282,15 +286,18 @@ def pre_start_capture(self): Alazar acquisition params and set up software wave for demodulation. """ alazar = self._get_alazar() - if self.samples_per_record != alazar.samples_per_record.get(): - raise Exception('acq controller samples per record does not match' - ' instrument value, most likely need ' - 'to set and check int_time and int_delay') - if self.sample_rate != alazar.get_sample_rate(): - raise Exception('acq controller sample rate does not match ' - 'instrument value, most likely need ' - 'to set and check int_time and int_delay') - + acq_s_p_r = self.acquisition.acquisition_kwargs['samples_per_record'] + inst_s_p_r = alazar.samples_per_record.get() + sample_rate = alazar.get_sample_rate() + if acq_s_p_r != inst_s_p_r: + raise Exception('acq controller samples per record {} does not match' + ' instrument value {}, most likely need ' + 'to set and check int_time and int_delay'.format(acq_s_p_r, inst_s_p_r)) + # if acq_s_r != inst_s_r: + # raise Exception('acq controller sample rate {} does not match ' + # 'instrument value {}, most likely need ' + # 'to set and check int_time and int_delay'.format(acq_s_r, inst_s_r)) + samples_per_record = inst_s_p_r demod_freqs = self.get_demod_freqs() # if len(demod_freqs) == 0: # raise Exception('no demod_freqs set') @@ -298,14 +305,14 @@ def pre_start_capture(self): self.records_per_buffer = alazar.records_per_buffer.get() self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() self.board_info = alazar.get_idn() - self.buffer = np.zeros(self.samples_per_record * + self.buffer = np.zeros(samples_per_record * self.records_per_buffer * self.number_of_channels) - if demod_freqs: - integer_list = np.arange(self.samples_per_record) + if len(demod_freqs): + integer_list = np.arange(samples_per_record) angle_mat = 2 * np.pi * \ - np.outer(demod_freqs, integer_list) / self.sample_rate + np.outer(demod_freqs, integer_list) / sample_rate self.cos_mat = np.cos(angle_mat) self.sin_mat = np.sin(angle_mat) @@ -338,8 +345,10 @@ def post_acquire(self): # where SXYZ is record X, sample Y, channel Z. # break buffer up into records and averages over them + alazar = self._get_alazar() + samples_per_record = alazar.samples_per_record.get() reshaped_buf = self.buffer.reshape(self.records_per_buffer, - self.samples_per_record, + samples_per_record, self.number_of_channels) recordA = np.uint16(np.mean(reshaped_buf[:, :, 0], axis=0) / self.buffers_per_acquisition) @@ -361,7 +370,7 @@ def post_acquire(self): else: unpacked.append(recordA) # do demodulation - if self.get_demod_freqs(): + if len(self.get_demod_freqs()): magA, phaseA = self._fit(recordA) if self._integrate_samples: magA = np.mean(magA, axis=-1) @@ -395,7 +404,7 @@ def _fit(self, volt_rec): Args: record (numpy array): record from alazar to be multiplied with the software signal, filtered and limited - to integration limits shape = (samples_taken, ) + to ifantegration limits shape = (samples_taken, ) Returns: magnitude (numpy array): shape = (demod_length, samples_after_limiting) @@ -403,7 +412,10 @@ def _fit(self, volt_rec): """ # volt_rec to matrix and multiply with demodulation signal matrices - volt_rec_mat = np.outer(np.ones(self._demod_length), volt_rec) + alazar = self._get_alazar() + sample_rate = alazar.get_sample_rate() + demod_length = len(self._demod_freqs) + volt_rec_mat = np.outer(np.ones(demod_length), volt_rec) re_mat = np.multiply(volt_rec_mat, self.cos_mat) im_mat = np.multiply(volt_rec_mat, self.sin_mat) @@ -411,30 +423,30 @@ def _fit(self, volt_rec): cutoff = self.get_max_demod_freq() / 10 if self.filter_settings['filter'] == 0: re_filtered = helpers.filter_win(re_mat, cutoff, - self.sample_rate, + sample_rate, self.filter_settings['numtaps'], axis=-1) im_filtered = helpers.filter_win(im_mat, cutoff, - self.sample_rate, + sample_rate, self.filter_settings['numtaps'], axis=-1) elif self.filter_settings['filter'] == 1: re_filtered = helpers.filter_ls(re_mat, cutoff, - self.sample_rate, + sample_rate, self.filter_settings['numtaps'], axis=-1) im_filtered = helpers.filter_ls(im_mat, cutoff, - self.sample_rate, + sample_rate, self.filter_settings['numtaps'], axis=-1) elif self.filter_settings['filter'] == 2: re_filtered = re_mat im_filtered = im_mat - if self.__integrate_samples: + if self._integrate_samples: # apply integration limits - beginning = int(self.int_delay() * self.sample_rate) - end = beginning + int(self.int_time() * self.sample_rate) + beginning = int(self.int_delay() * sample_rate) + end = beginning + int(self.int_time() * sample_rate) re_limited = re_filtered[:, beginning:end] im_limited = im_filtered[:, beginning:end] From cdaad8cb23cf5dcd404f992f680eb3b106d2d4c5 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Tue, 28 Feb 2017 16:36:32 +0100 Subject: [PATCH 148/180] Fix: add init file --- qcodes/instrument_drivers/AlazarTech/acq_controllers/__init__.py | 1 + 1 file changed, 1 insertion(+) create mode 100644 qcodes/instrument_drivers/AlazarTech/acq_controllers/__init__.py diff --git a/qcodes/instrument_drivers/AlazarTech/acq_controllers/__init__.py b/qcodes/instrument_drivers/AlazarTech/acq_controllers/__init__.py new file mode 100644 index 000000000000..c822410d32ce --- /dev/null +++ b/qcodes/instrument_drivers/AlazarTech/acq_controllers/__init__.py @@ -0,0 +1 @@ +from .ATS9360Controller import ATS9360Controller From 6ef072e07934089bdde2adb5de53641fec65b501 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Thu, 2 Mar 2017 11:14:05 +0100 Subject: [PATCH 149/180] Fix: correctly init instrument in AlazarParameter Storing the instrument as a non private member of the Parameter prevents picling of the instrument and adding it to a station --- qcodes/instrument_drivers/AlazarTech/ATS.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/ATS.py b/qcodes/instrument_drivers/AlazarTech/ATS.py index 2a287dd603f8..8c3d2763337c 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS.py @@ -873,8 +873,7 @@ def __init__(self, name=None, label=None, unit=None, instrument=None, # TODO(damazter) (S) test this validator vals = validators.Enum(*byte_to_value_dict.values()) - super().__init__(name=name, label=label, unit=unit, vals=vals) - self.instrument = instrument + super().__init__(name=name, label=label, unit=unit, vals=vals, instrument=instrument) self._byte = None self._uptodate_flag = False From 9759ea5563ff0d17c04f634054cdcefaf8814b92 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Thu, 2 Mar 2017 15:23:04 +0100 Subject: [PATCH 150/180] Fix: Alazar mark internal/external sample rate as up to date when not in use --- qcodes/instrument_drivers/AlazarTech/ATS.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/qcodes/instrument_drivers/AlazarTech/ATS.py b/qcodes/instrument_drivers/AlazarTech/ATS.py index 8c3d2763337c..805f9ca9bf56 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS.py @@ -416,11 +416,19 @@ def config(self, clock_source=None, sample_rate=None, clock_edge=None, self._set_if_present('aux_io_param', aux_io_param) # endregion - + # handle that external clock and internal clock uses + # two different ways of setting the sample rate. + # We use the matching one and make the order one + # as up to date since it's not being pushed to + # the instrument at any time and is never used if clock_source == 'EXTERNAL_CLOCK_10MHz_REF': sample_rate = self.external_sample_rate + if 'sample_rate' in self.parameters: + self.parameters['sample_rate']._set_updated() elif clock_source == 'INTERNAL_CLOCK': sample_rate = self.sample_rate + if 'external_sample_rate' in self.parameters: + self.parameters['external_sample_rate']._set_updated() self._call_dll('AlazarSetCaptureClock', self._handle, self.clock_source, sample_rate, From 46ed0e921b8270853dd935bb366bfccf4ecf65b1 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Thu, 2 Mar 2017 15:26:00 +0100 Subject: [PATCH 151/180] Fix more work on acq controller fixing issues and making more stuff parameters --- .../acq_controllers/ATS9360Controller.py | 191 +++++++----------- .../AlazarTech/acqusition_parameters.py | 143 ++++++++++++- 2 files changed, 201 insertions(+), 133 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py b/qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py index 0e8ac426311e..8955493c3dfc 100644 --- a/qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py +++ b/qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py @@ -2,7 +2,10 @@ from ..ATS import AcquisitionController import numpy as np import qcodes.instrument_drivers.AlazarTech.acq_helpers as helpers -from ..acqusition_parameters import AcqVariablesParam, ExpandingAlazarArrayMultiParameter +from ..acqusition_parameters import AcqVariablesParam, \ + ExpandingAlazarArrayMultiParameter, \ + NonSettableDerivedParameter, \ + DemodFreqParameter class ATS9360Controller(AcquisitionController): @@ -47,73 +50,38 @@ def __init__(self, name, alazar_name, filter: str = 'win', parameter_class=ExpandingAlazarArrayMultiParameter) self._integrate_samples = integrate_samples - if integrate_samples: - self.add_parameter(name='int_time', - check_and_update_fn=self._update_int_time, - default_fn=self._int_time_default, - parameter_class=AcqVariablesParam) - self.add_parameter(name='int_delay', - check_and_update_fn=self._update_int_delay, - default_fn=self._int_delay_default, - parameter_class=AcqVariablesParam) - self.samples_divisor = self._get_alazar().samples_divisor - self._demod_freqs = [] + self.add_parameter(name='int_time', + check_and_update_fn=self._update_int_time, + default_fn=self._int_time_default, + parameter_class=AcqVariablesParam) + self.add_parameter(name='int_delay', + check_and_update_fn=self._update_int_delay, + default_fn=self._int_delay_default, + parameter_class=AcqVariablesParam) + self.add_parameter(name='num_avg', + check_and_update_fn=self._update_num_avg, + default_fn= lambda : 1, + parameter_class=AcqVariablesParam) + self.add_parameter(name='allocated_buffers', + alternative='not controllable in this controller', + parameter_class=NonSettableDerivedParameter) + self.add_parameter(name='buffers_per_acquisition', + alternative='not controllable in this controller', + parameter_class=NonSettableDerivedParameter) + self.add_parameter(name='records_per_buffer', + alternative='num_avg', + parameter_class=NonSettableDerivedParameter) + self.add_parameter(name='samples_per_record', + alternative='int_time and int_delay', + parameter_class=NonSettableDerivedParameter) + + self.add_parameter(name='demod_freqs', + shape=(), + parameter_class=DemodFreqParameter) - def add_demodulator(self, demod_freq): - if demod_freq not in self._demod_freqs: - self._verify_demod_freq(demod_freq) - self._demod_freqs.append(demod_freq) - self.acquisition.set_setpoints_and_labels() + self.samples_divisor = self._get_alazar().samples_divisor - def remove_demodulator(self, demod_freq): - if demod_freq in self.demod_freqs: - self._demod_freqs.pop(self.demod_freqs.index(demod_freq)) - self.acquisition.set_setpoints_and_labels() - - def _verify_demod_freq(self, value): - """ - Function to validate a demodulation frequency - - Checks: - - 1e6 <= value <= 500e6 - - number of oscillation measured using current 'int_time' param value - at this demodulation frequency value - - oversampling rate for this demodulation frequency - - Args: - value: proposed demodulation frequency - Returns: - bool: Returns True if suitable number of oscillations are measured and - oversampling is > 1, False otherwise. - Raises: - ValueError: If value is not a valid demodulation frequency. - """ - if (value is None) or not (1e6 <= value <= 500e6): - raise ValueError('demod_freqs must be 1e6 <= value <= 500e6') - isValid = True - alazar = self._get_alazar() - sample_rate = alazar.get_sample_rate() - if 'int_time' in self.parameters: - int_time = self.int_time.get() - else: - int_time = self.acquisition.acquisition_kwargs["samples_per_record"]/sample_rate - min_oscillations_measured = int_time * value - oversampling = sample_rate / (2 * value) - if min_oscillations_measured < 10: - isValid = False - logging.warning('{} oscillation measured for largest ' - 'demod freq, recommend at least 10: ' - 'decrease sampling rate, take ' - 'more samples or increase demodulation ' - 'freq'.format(min_oscillations_measured)) - elif oversampling < 1: - isValid = False - logging.warning('oversampling rate is {}, recommend > 1: ' - 'increase sampling rate or decrease ' - 'demodulation frequency'.format(oversampling)) - - return isValid def _update_int_time(self, value, **kwargs): """ @@ -138,18 +106,21 @@ def _update_int_time(self, value, **kwargs): alazar = self._get_alazar() sample_rate = alazar.get_sample_rate() - if self.get_max_demod_freq() is not None: - self._verify_demod_freq(self.get_max_demod_freq()) + max_demod_freq = self.demod_freqs.get_max_demod_freq() + if max_demod_freq is not None: + self._verify_demod_freq(max_demod_freq) if self.int_delay() is None: self.int_delay.to_default() + int_delay = self.int_delay.get() + self._update_samples_per_record(sample_rate, value, int_delay) + def _update_samples_per_record(self, sample_rate, int_time, int_delay): # update acquisition kwargs and acq controller value - total_time = value + self.int_delay() + total_time = (int_time or 0) + (int_delay or 0) samples_needed = total_time * sample_rate samples_per_record = helpers.roundup( samples_needed, self.samples_divisor) - self.acquisition.acquisition_kwargs.update( - samples_per_record=samples_per_record) + self.samples_per_record._save_val(samples_per_record) def _update_int_delay(self, value, **kwargs): """ @@ -164,7 +135,7 @@ def _update_int_delay(self, value, **kwargs): number of samples discarded >= numtaps Sets: - sample_rate attr of acq controller to be that of alazar + sample_rate attr of acq controller to be that of Alazar samples_per_record of acq controller acquisition_kwarg['samples_per_record'] of acquisition param setpoints of acquisition param @@ -184,13 +155,17 @@ def _update_int_delay(self, value, **kwargs): 'delay is less than recommended for filter choice: ' '(expect delay >= {})'.format(int_delay_min)) - # update acquisition kwargs and acq controller value - total_time = value + (self.int_time() or 0) - samples_needed = total_time * sample_rate - samples_per_record = helpers.roundup( - samples_needed, self.samples_divisor) - self.acquisition.acquisition_kwargs.update( - samples_per_record=samples_per_record) + int_time = self.int_time.get() + self._update_samples_per_record(sample_rate, int_time, value) + + def _update_num_avg(self, value: int, **kwargs): + if not isinstance(value, int) or value < 1: + raise ValueError('number of averages must be a positive integer') + + self.records_per_buffer._save_val(value) + self.buffers_per_acquisition._save_val(1) + self.allocated_buffers._save_val(1) + def _int_delay_default(self): """ @@ -213,7 +188,7 @@ def _int_time_default(self): max total time for integration based on samples_per_record, sample_rate and int_delay """ - samples_per_record = self.acquisition.acquisition_kwargs.get('samples_per_record') + samples_per_record = self.samples_per_record.get() if samples_per_record in (0 or None): raise ValueError('Cannot set int_time to max if acq controller' ' has 0 or None samples_per_record, choose a ' @@ -225,27 +200,6 @@ def _int_time_default(self): (self.int_delay() or 0)) return total_time - def get_demod_freqs(self): - """ - Function to get all the demod_freq parameter values in a numpy array - - Returns: - numpy array of demodulation frequencies - """ - return np.array(self._demod_freqs) - - def get_max_demod_freq(self): - """ - Returns: - the largest demodulation frequency - - """ - freqs = self.get_demod_freqs() - if len(freqs) > 0: - return max(freqs) - else: - return None - def update_filter_settings(self, filter, numtaps): """ Updates the settings of the filter for filtering out @@ -272,9 +226,8 @@ def update_acquisition_kwargs(self, **kwargs): - buffers_per_acquisition - allocated_buffers """ - if 'samples_per_record' in kwargs and self._integrate_samples: - raise ValueError('With integrating over samples ' - 'samples_per_record should not be set manually ' + if 'samples_per_record' in kwargs: + raise ValueError('Samples_per_record should not be set manually ' 'via update_acquisition_kwargs and should instead' ' be set by setting int_time and int_delay') self.acquisition.acquisition_kwargs.update(**kwargs) @@ -286,7 +239,7 @@ def pre_start_capture(self): Alazar acquisition params and set up software wave for demodulation. """ alazar = self._get_alazar() - acq_s_p_r = self.acquisition.acquisition_kwargs['samples_per_record'] + acq_s_p_r = self.samples_per_record.get() inst_s_p_r = alazar.samples_per_record.get() sample_rate = alazar.get_sample_rate() if acq_s_p_r != inst_s_p_r: @@ -298,15 +251,14 @@ def pre_start_capture(self): # 'instrument value {}, most likely need ' # 'to set and check int_time and int_delay'.format(acq_s_r, inst_s_r)) samples_per_record = inst_s_p_r - demod_freqs = self.get_demod_freqs() + demod_freqs = self.demod_freqs.get() # if len(demod_freqs) == 0: # raise Exception('no demod_freqs set') - self.records_per_buffer = alazar.records_per_buffer.get() - self.buffers_per_acquisition = alazar.buffers_per_acquisition.get() + records_per_buffer = alazar.records_per_buffer.get() self.board_info = alazar.get_idn() self.buffer = np.zeros(samples_per_record * - self.records_per_buffer * + records_per_buffer * self.number_of_channels) if len(demod_freqs): @@ -347,30 +299,22 @@ def post_acquire(self): # break buffer up into records and averages over them alazar = self._get_alazar() samples_per_record = alazar.samples_per_record.get() - reshaped_buf = self.buffer.reshape(self.records_per_buffer, + records_per_buffer = alazar.records_per_buffer.get() + buffers_per_acquisition = alazar.buffers_per_acquisition.get() + reshaped_buf = self.buffer.reshape(records_per_buffer, samples_per_record, self.number_of_channels) recordA = np.uint16(np.mean(reshaped_buf[:, :, 0], axis=0) / - self.buffers_per_acquisition) + buffers_per_acquisition) - # TODO(nataliejpg): test above version works on alazar and - # compare performance recordA = self._to_volts(recordA) - # records_per_acquisition = (self.buffers_per_acquisition * - # self.records_per_buffer) - # recA = np.zeros(self.samples_per_record) - # for i in range(self.records_per_buffer): - # i0 = (i * self.samples_per_record * self.number_of_channels) - # i1 = (i0 + self.samples_per_record * self.number_of_channels) - # recA += self.buffer[i0:i1:self.number_of_channels] - # recordA = np.uint16(recA / records_per_acquisition) unpacked = [] if self._integrate_samples: unpacked.append(np.mean(recordA, axis=-1)) else: unpacked.append(recordA) # do demodulation - if len(self.get_demod_freqs()): + if self.demod_freqs.get_num_demods(): magA, phaseA = self._fit(recordA) if self._integrate_samples: magA = np.mean(magA, axis=-1) @@ -414,13 +358,13 @@ def _fit(self, volt_rec): # volt_rec to matrix and multiply with demodulation signal matrices alazar = self._get_alazar() sample_rate = alazar.get_sample_rate() - demod_length = len(self._demod_freqs) + demod_length = self.demod_freqs.get_num_demods() volt_rec_mat = np.outer(np.ones(demod_length), volt_rec) re_mat = np.multiply(volt_rec_mat, self.cos_mat) im_mat = np.multiply(volt_rec_mat, self.sin_mat) # filter out higher freq component - cutoff = self.get_max_demod_freq() / 10 + cutoff = self.demod_freqs.get_max_demod_freq() / 10 if self.filter_settings['filter'] == 0: re_filtered = helpers.filter_win(re_mat, cutoff, sample_rate, @@ -460,3 +404,4 @@ def _fit(self, volt_rec): phase = np.angle(complex_mat, deg=True) return magnitude, phase + diff --git a/qcodes/instrument_drivers/AlazarTech/acqusition_parameters.py b/qcodes/instrument_drivers/AlazarTech/acqusition_parameters.py index 933efe6a933a..434ebee3a88c 100644 --- a/qcodes/instrument_drivers/AlazarTech/acqusition_parameters.py +++ b/qcodes/instrument_drivers/AlazarTech/acqusition_parameters.py @@ -1,5 +1,6 @@ -from qcodes import Parameter, MultiParameter +from qcodes import Parameter, MultiParameter, ArrayParameter import numpy as np +import logging class AcqVariablesParam(Parameter): """ @@ -209,7 +210,7 @@ def __init__(self, instrument, names = ('raw_output',), labels = ("raw output",), - units = ('V',), + units = ('v',), shapes = ((1,),), setpoints = (((1,),),), setpoint_names = (('time',),), @@ -231,11 +232,13 @@ def __init__(self, def set_setpoints_and_labels(self): if not self._integrate_samples: - - if self._instrument._get_alazar().sample_rate.get() and self.acquisition_kwargs.get('samples_per_record'): + int_time = self._instrument.int_time.get() + int_delay = self._instrument.int_delay.get() + total_time = int_time + int_delay + samples = self._instrument.samples_per_record.get() + if total_time and samples: start = 0 - samples = self.acquisition_kwargs['samples_per_record'] - stop = samples/self._instrument._get_alazar().sample_rate.get() + stop = total_time else: start = 0 samples = 1 @@ -257,7 +260,8 @@ def set_setpoints_and_labels(self): setpoint_units = [setpoint_unit] units = [self.units[0]] shapes = [base_shape] - for i, demod_freq in enumerate(self._instrument._demod_freqs): + demod_freqs = self._instrument.demod_freqs.get() + for i, demod_freq in enumerate(demod_freqs): names.append("demod_freq_{}_mag".format(i)) labels.append("demod freq {} mag".format(i)) names.append("demod_freq_{}_phase".format(i)) @@ -274,7 +278,6 @@ def set_setpoints_and_labels(self): setpoint_names.append(setpoint_name) setpoint_labels.append(setpoint_label) setpoint_units.append(setpoint_unit) - self.metadata['demod_freqs'] = self._instrument._demod_freqs self.names = tuple(names) self.labels = tuple(labels) self.units = tuple(units) @@ -285,7 +288,127 @@ def set_setpoints_and_labels(self): self.setpoint_units = tuple(setpoint_units) def get(self): + inst = self._instrument + params_to_kwargs = ['samples_per_record', 'records_per_buffer', + 'buffers_per_acquisition', 'allocated_buffers'] + acq_kwargs = self.acquisition_kwargs.copy() + additional_acq_kwargs = {key: val.get() for key, val in inst.parameters.items() if + key in params_to_kwargs} + acq_kwargs.update(additional_acq_kwargs) + output = self._instrument._get_alazar().acquire( acquisition_controller=self._instrument, - **self.acquisition_kwargs) - return output \ No newline at end of file + **acq_kwargs) + return output + + +class NonSettableDerivedParameter(Parameter): + """ + Parameter of an AcquisitionController which cannot be updated directly + as it's value is derived from other parameters. This is intended to be + used in high level APIs where Alazar parameters such as 'samples_per_record' + are not set directly but are parameters of the actual instrument anyway. + + This assumes that the parameter is stored via a call to '_save_val' by + any set of parameter that this parameter depends on. + + Args: + name: name for this parameter + instrument: acquisition controller instrument this parameter belongs to + alternative (str): name of parameter(s) that controls the value of this + parameter and can be set directly. + """ + + def __init__(self, name, instrument, alternative: str): + self._alternative = alternative + super().__init__(name, instrument=instrument) + + def set(self, value): + """ + It's not possible to directly set this parameter as it's derived from other + parameters. + """ + raise NotImplementedError("Cannot directly set {}. To control this parameter" + "set {}".format(self.name, self._alternative)) + + def get(self): + return self.get_latest() + + +class DemodFreqParameter(ArrayParameter): + + # + def __init__(self, name, shape, **kwargs): + self._demod_freqs = [] + super().__init__(name, shape, **kwargs) + + + def add_demodulator(self, demod_freq): + ndemod_freqs = len(self._demod_freqs) + if demod_freq not in self._demod_freqs: + self._verify_demod_freq(demod_freq) + self._demod_freqs.append(demod_freq) + self._save_val(self._demod_freqs) + self.shape = (ndemod_freqs+1,) + self._instrument.acquisition.set_setpoints_and_labels() + + def remove_demodulator(self, demod_freq): + ndemod_freqs = len(self._demod_freqs) + if demod_freq in self._demod_freqs: + self._demod_freqs.pop(self._demod_freqs.index(demod_freq)) + self.shape = (ndemod_freqs - 1,) + self._save_val(self._demod_freqs) + self._instrument.acquisition.set_setpoints_and_labels() + + def get(self): + return self._demod_freqs + + def get_num_demods(self): + return len(self._demod_freqs) + + def get_max_demod_freq(self): + if len(self._demod_freqs): + return max(self._demod_freqs) + else: + return None + + def _verify_demod_freq(self, value): + """ + Function to validate a demodulation frequency + + Checks: + - 1e6 <= value <= 500e6 + - number of oscillation measured using current 'int_time' param value + at this demodulation frequency value + - oversampling rate for this demodulation frequency + + Args: + value: proposed demodulation frequency + Returns: + bool: Returns True if suitable number of oscillations are measured and + oversampling is > 1, False otherwise. + Raises: + ValueError: If value is not a valid demodulation frequency. + """ + if (value is None) or not (1e6 <= value <= 500e6): + raise ValueError('demod_freqs must be 1e6 <= value <= 500e6') + isValid = True + alazar = self._instrument._get_alazar() + sample_rate = alazar.get_sample_rate() + int_time = self._instrument.int_time.get() + min_oscillations_measured = int_time * value + oversampling = sample_rate / (2 * value) + if min_oscillations_measured < 10: + isValid = False + logging.warning('{} oscillation measured for largest ' + 'demod freq, recommend at least 10: ' + 'decrease sampling rate, take ' + 'more samples or increase demodulation ' + 'freq'.format(min_oscillations_measured)) + elif oversampling < 1: + isValid = False + logging.warning('oversampling rate is {}, recommend > 1: ' + 'increase sampling rate or decrease ' + 'demodulation frequency'.format(oversampling)) + + return isValid \ No newline at end of file From be421dcbeb95b44dc787dded3c217008fa7106a3 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Thu, 2 Mar 2017 15:27:16 +0100 Subject: [PATCH 152/180] fix typo --- qcodes/instrument_drivers/AlazarTech/ATS9360.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qcodes/instrument_drivers/AlazarTech/ATS9360.py b/qcodes/instrument_drivers/AlazarTech/ATS9360.py index 163de13696bc..b220857bae6e 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS9360.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS9360.py @@ -322,7 +322,7 @@ def get_sample_rate(self): elif self.clock_source.get() == 'INTERNAL_CLOCK': rate = self.sample_rate.get() else: - raise Exception("Don't know how to get sample rate with {}".format(alazar.clock_source.get())) + raise Exception("Don't know how to get sample rate with {}".format(self.clock_source.get())) if rate == '1GHz_REFERENCE_CLOCK': rate = 1e9 From de840b6285f34c10eeaa97981b57d62b896a2165 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Thu, 2 Mar 2017 15:57:01 +0100 Subject: [PATCH 153/180] fix: correct changing of inttime/intdelay --- .../AlazarTech/acq_controllers/ATS9360Controller.py | 3 ++- qcodes/instrument_drivers/AlazarTech/acqusition_parameters.py | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py b/qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py index 8955493c3dfc..24c4b44201bd 100644 --- a/qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py +++ b/qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py @@ -108,7 +108,7 @@ def _update_int_time(self, value, **kwargs): sample_rate = alazar.get_sample_rate() max_demod_freq = self.demod_freqs.get_max_demod_freq() if max_demod_freq is not None: - self._verify_demod_freq(max_demod_freq) + self.demod_freqs._verify_demod_freq(max_demod_freq) if self.int_delay() is None: self.int_delay.to_default() int_delay = self.int_delay.get() @@ -121,6 +121,7 @@ def _update_samples_per_record(self, sample_rate, int_time, int_delay): samples_per_record = helpers.roundup( samples_needed, self.samples_divisor) self.samples_per_record._save_val(samples_per_record) + self.acquisition.set_setpoints_and_labels() def _update_int_delay(self, value, **kwargs): """ diff --git a/qcodes/instrument_drivers/AlazarTech/acqusition_parameters.py b/qcodes/instrument_drivers/AlazarTech/acqusition_parameters.py index 434ebee3a88c..6ac1f4afaae8 100644 --- a/qcodes/instrument_drivers/AlazarTech/acqusition_parameters.py +++ b/qcodes/instrument_drivers/AlazarTech/acqusition_parameters.py @@ -232,8 +232,8 @@ def __init__(self, def set_setpoints_and_labels(self): if not self._integrate_samples: - int_time = self._instrument.int_time.get() - int_delay = self._instrument.int_delay.get() + int_time = self._instrument.int_time.get() or 0 + int_delay = self._instrument.int_delay.get() or 0 total_time = int_time + int_delay samples = self._instrument.samples_per_record.get() if total_time and samples: From ff6fbbd3b8fde17e466fb2698db1b99aebcf84c1 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 3 Mar 2017 17:07:37 +0100 Subject: [PATCH 154/180] Wip getting this working with multidim arrays --- ...e with Alazar ATS9360 new controller.ipynb | 949 ++++++++++++++++++ .../acq_controllers/ATS9360Controller.py | 60 +- ...arameters.py => acquisition_parameters.py} | 7 +- 3 files changed, 1001 insertions(+), 15 deletions(-) create mode 100644 docs/examples/Qcodes example with Alazar ATS9360 new controller.ipynb rename qcodes/instrument_drivers/AlazarTech/{acqusition_parameters.py => acquisition_parameters.py} (98%) diff --git a/docs/examples/Qcodes example with Alazar ATS9360 new controller.ipynb b/docs/examples/Qcodes example with Alazar ATS9360 new controller.ipynb new file mode 100644 index 000000000000..5f2672a82652 --- /dev/null +++ b/docs/examples/Qcodes example with Alazar ATS9360 new controller.ipynb @@ -0,0 +1,949 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "### Qcodes example notebook for Alazar card ATS9360 and acq controllers" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "No loop running\n" + ] + } + ], + "source": [ + "import qcodes as qc\n", + "import qcodes.instrument.parameter as parameter\n", + "import qcodes.instrument_drivers.AlazarTech.ATS9360 as ATSdriver\n", + "from qcodes.instrument_drivers.AlazarTech.acq_controllers import ATS9360Controller\n", + "from qcodes.station import Station\n", + "#import qcodes.instrument_drivers.AlazarTech.samp_controller as samp_acq_contr\n", + "#import qcodes.instrument_drivers.AlazarTech.ave_controller_test as ave_acq_controller\n", + "#import qcodes.instrument_drivers.AlazarTech.rec_controller_test as record_acq_controller\n", + "\n", + "import logging\n", + "# logging.basicConfig(filename='example.log',level=logging.INFO)\n", + "\n", + "qc.halt_bg()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "NB: See ATS9360 example notebook for general commands " + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'CPLD_version': '25.16',\n", + " 'SDK_version': '5.10.22',\n", + " 'asopc_type': '1645511520',\n", + " 'bits_per_sample': 12,\n", + " 'driver_version': '5.10.22',\n", + " 'firmware': None,\n", + " 'latest_cal_date': '25-01-17',\n", + " 'max_samples': 4294967294,\n", + " 'memory_size': '4294967294',\n", + " 'model': 'ATS9360',\n", + " 'pcie_link_speed': '0.5GB/s',\n", + " 'pcie_link_width': '8',\n", + " 'serial': '970396',\n", + " 'vendor': 'AlazarTech'}" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Create the ATS9360 instrument\n", + "alazar = ATSdriver.AlazarTech_ATS9360(name='Alazar')\n", + "# Print all information about this Alazar card\n", + "alazar.get_idn()" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "752" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "alazar._handle" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false, + "scrolled": false + }, + "outputs": [], + "source": [ + "# Configure all settings in the Alazar card\n", + "alazar.config(clock_source='INTERNAL_CLOCK',\n", + " sample_rate=500000000,\n", + " clock_edge='CLOCK_EDGE_RISING',\n", + " decimation=1,\n", + " coupling=['DC','DC'],\n", + " channel_range=[.4,.4],\n", + " impedance=[50,50],\n", + " trigger_operation='TRIG_ENGINE_OP_J',\n", + " trigger_engine1='TRIG_ENGINE_J',\n", + " trigger_source1='CHANNEL_A',\n", + " trigger_slope1='TRIG_SLOPE_POSITIVE',\n", + " trigger_level1=128,\n", + " trigger_engine2='TRIG_ENGINE_K',\n", + " trigger_source2='DISABLE',\n", + " trigger_slope2='TRIG_SLOPE_POSITIVE',\n", + " trigger_level2=128,\n", + " external_trigger_coupling='DC',\n", + " external_trigger_range='ETR_2V5',\n", + " trigger_delay=0,\n", + " timeout_ticks=1,\n", + " aux_io_mode='AUX_IN_AUXILIARY', # AUX_IN_TRIGGER_ENABLE for seq mode on\n", + " aux_io_param='NONE' # TRIG_SLOPE_POSITIVE for seq mode on\n", + " )" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "### Basic Acquisition\n", + "\n", + "Pulls the raw data the alazar acquires averaged over number of records buffers." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true, + "scrolled": true + }, + "outputs": [], + "source": [ + "# Create the acquisition controller which will take care of the data handling and tell it which \n", + "# alazar instrument to talk to.\n", + "myctrl = ATS9360Controller(name='my_controller', alazar_name='Alazar')" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "station = qc.Station(alazar, myctrl)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "start 0 stop 1 num steps 1\n", + "start 0 stop 2e-07 num steps 1152\n" + ] + } + ], + "source": [ + "myctrl.int_delay(2e-7)\n", + "myctrl.int_time(2e-6)\n", + "myctrl.num_avg(100)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "100" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "myctrl.parameters['records_per_buffer'].get()" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "start 0 stop 2.2e-06 num steps 1152\n", + "1152\n", + "start 0 stop 2.2e-06 num steps 1152\n", + "1152\n" + ] + } + ], + "source": [ + "myctrl.int_delay(2e-7)\n", + "print(myctrl.samples_per_record.get_latest())\n", + "myctrl.int_time(2e-6)\n", + "print(myctrl.samples_per_record.get_latest())" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n", + "1\n", + "100\n" + ] + } + ], + "source": [ + "myctrl.num_avg(100)\n", + "print(myctrl.buffers_per_acquisition.get())\n", + "print(myctrl.allocated_buffers.get())\n", + "print(myctrl.records_per_buffer.get())" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[ 0.001221 0.0002442 0.001221 ..., 0.0002442 0.001221 0.0002442]\n", + "(1152,)\n" + ] + } + ], + "source": [ + "# Pull data from the card by calling get of the controllers acquisition parameter\n", + "data1 = myctrl.acquisition.get()\n", + "print(data1[0])\n", + "print(data1[0].shape)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING:root:4.0 oscillation measured for largest demod freq, recommend at least 10: decrease sampling rate, take more samples or increase demodulation freq\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "start 0 stop 2.2e-06 num steps 1152\n", + "[2000000.0]\n", + "start 0 stop 2.2e-06 num steps 1152\n", + "[2000000.0, 6000000.0]\n", + "start 0 stop 2.2e-06 num steps 1152\n", + "[2000000.0]\n" + ] + } + ], + "source": [ + "myctrl.demod_freqs.add_demodulator(2e6)\n", + "print(myctrl.demod_freqs.get())\n", + "myctrl.demod_freqs.add_demodulator(6e6)\n", + "print(myctrl.demod_freqs.get())\n", + "myctrl.demod_freqs.remove_demodulator(6e6)\n", + "print(myctrl.demod_freqs.get())" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING:root:8.0 oscillation measured for largest demod freq, recommend at least 10: decrease sampling rate, take more samples or increase demodulation freq\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "start 0 stop 2.2e-06 num steps 1152\n", + "start 0 stop 2.2e-06 num steps 1152\n" + ] + }, + { + "data": { + "text/plain": [ + "[4000000.0]" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "myctrl.demod_freqs.add_demodulator(2e6)\n", + "myctrl.demod_freqs.get_latest()\n", + "myctrl.demod_freqs.add_demodulator(4e6)\n", + "myctrl.demod_freqs.get_latest()\n", + "myctrl.demod_freqs.remove_demodulator(2e6)\n", + "myctrl.demod_freqs.get_latest()" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# myctrl.acquisition.set_setpoints_and_labels()" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true, + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DataSet:\n", + " mode = DataMode.LOCAL\n", + " location = 'data/2017-03-03/#007_{name}_16-45-29'\n", + " | | | \n", + " Setpoint | time_set | time | (1152,)\n", + " Measured | my_controller_raw_output | raw_output | (1152,)\n", + " Measured | my_controller_demod_freq_0_mag | demod_freq_0_mag | (1152,)\n", + " Measured | my_controller_demod_freq_0_phase | demod_freq_0_phase | (1152,)\n", + "acquired at 2017-03-03 16:45:30\n" + ] + } + ], + "source": [ + "# Do this in as qcodes measurement (ie the same but makes a data set)\n", + "data2 = qc.Measure(myctrl.acquisition).run(station=station)\n", + "plot = qc.MatPlot(data2.my_controller_raw_output)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(1, 1, 1, 1152)" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "myctrl.mat_shape" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/png": "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\nrkJggg==\n", + "text/plain": [ + "" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "plot.fig" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING:root:8.0 oscillation measured for largest demod freq, recommend at least 10: decrease sampling rate, take more samples or increase demodulation freq\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "start 0 stop 2.2e-06 num steps 1152\n", + "start 0 stop 2.2e-06 num steps 3200\n" + ] + } + ], + "source": [ + "myctrl.int_delay(2e-7)\n", + "myctrl.int_time(6e-6)\n", + "myctrl.num_avg(1)" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DataSet:\n", + " mode = DataMode.LOCAL\n", + " location = 'data/2017-03-03/#008_{name}_16-45-33'\n", + " | | | \n", + " Setpoint | time_set | time | (3200,)\n", + " Measured | my_controller_raw_output | raw_output | (3200,)\n", + " Measured | my_controller_demod_freq_0_mag | demod_freq_0_mag | (3200,)\n", + " Measured | my_controller_demod_freq_0_phase | demod_freq_0_phase | (3200,)\n", + "acquired at 2017-03-03 16:45:34\n" + ] + }, + { + "data": { + "image/png": "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\nnx8n1iblGhHpglXHvnKRTUkixhj907/Q/rBGOh9gTUP/0/67EUuxTcGatp6HtVHMYK2fg7UBbR6W\nArodqMHaULYRa3R7FdZa+teBbtgGREa8r2IZFpsz/l7MeL4j1rr8FqyNcmflyL2I5t3eqb9BGc/H\nYi2jiIc8EKwNhevsv9+l/GGNQt+x82c9Vqf6rSLhDbLzbivWuv/XM579D9ZreluwpuUfB3axn30T\neN4hvAew9g0IloHWxsFNu4z8XwlcnvN8BDDDlul9YETGs/ZYr6Mut/2/D5xQQh16ALjZIQ/S9cW+\nNwX4gf37CKwZhc1YG2Ovx5rKT7k1wO4Z128A52Vc3wj8NeP6BLts1tvpeBLYIUemqcAFJaRrikMd\nOyrj+elYxtRG2+0wj+Fm5Q3Qy5Y9VcemAccV8N8Ly1Bdb8c9C7gw4/kZGXm7GstA3y9s3aJ/wf2l\nlJOiVA0i8l3gO8aY70YtS5wRkbuA2caYu6KWpRRE5GYsQ+QUY8z2qOVxQkS6YZ1h8QNjTN6GWkVJ\nErr0oFQj64FboxYiAXwIPB21EGXwV6AD8KWI5L5pEDki8jOsEfZr2NPzipJkdEZBUZRYICIDsUbh\nTgw1xridnZAI7L0Af3F4tNgYU86ZHYoSCmooKIqiKIriii49KIqiKIriihoKiqIoiqK4ooaCoiiK\noiiuqKGgKIqiKIoraigoiqIoiuKKGgqKoiiKoriihoKiKIqiKK6ooaAoiqIoiitqKCiKoiiK4ooa\nCoqiKIqiuKKGgqIoiqIorqihoCiKoiiKK2ooKIqiKIriihoKiqIoiqK4ooaCoiiKoiiuqKGgKIqi\nKIoraigoiqIoiuKKGgqKoiiKoriihoKiKIqiKK6ooaAoiqIoiitqKCiKoiiK4krrqAWIAz179jSD\nBg2KWgxFURRFCY0ZM2asMcb0KuZODQVg0KBBTJ8+PWoxFEVRFCU0RGSxF3e69KAoiqIoiitqKCiK\noiiK4ooaCoqiKIqiuKKGgqIoiqIorqihoCiKoiiKK2ooKIqiKIriihoKiqIoiqK4ooaCoiiKoiiu\nqKGgKIqiKIoraigoiaG+oYm3PluTdW/dlnpmLd0QkUTJZ86KjazcWBe1GEqVUre9kXcWro1aDKVC\n1FBQEsPN4z/lrPveYfayZsPgW3e9ycl/fiNCqZLNCX+aykG/mRy1GEqV8stnZvO9e6fx+ZotUYui\n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\n", + "text/plain": [ + "" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data3 = qc.Measure(myctrl.acquisition).run()\n", + "plot = qc.MatPlot(data3.my_controller_raw_output)\n", + "plot.fig" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DataSet:\n", + " mode = DataMode.LOCAL\n", + " location = 'data/2017-03-03/#009_{name}_16-45-34'\n", + " | | | \n", + " Setpoint | time_set | time | (3200,)\n", + " Measured | my_controller_raw_output | raw_output | (3200,)\n", + " Measured | my_controller_demod_freq_0_mag | demod_freq_0_mag | (3200,)\n", + " Measured | my_controller_demod_freq_0_phase | demod_freq_0_phase | (3200,)\n", + "acquired at 2017-03-03 16:45:35\n" + ] + }, + { + "data": { + "image/png": "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\nYII=\n", + "text/plain": [ + "" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "myctrl.num_avg(100)\n", + "data3 = qc.Measure(myctrl.acquisition).run()\n", + "plot = qc.MatPlot(data3.my_controller_raw_output)\n", + "plot.fig" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Do this in as qcodes measurement (ie the same but makes a data set) _demod_freqs\n", + "#data3 = qc.Measure(basic_acq_controller.acquisition).run()\n", + "plot = qc.MatPlot(data3.my_controller_demod_freq_0_mag)\n", + "plot.fig" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/png": "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\nYII=\n", + "text/plain": [ + "" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "plot = qc.MatPlot(data3.my_controller_demod_freq_0_phase)\n", + "plot.fig" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING:root:oversampling rate is 0.625, recommend > 1: increase sampling rate or decrease demodulation frequency\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "start 0 stop 6.2e-06 num steps 3200\n" + ] + } + ], + "source": [ + "myctrl.demod_freqs.add_demodulator(400e6)" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "collapsed": false, + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DataSet:\n", + " mode = DataMode.LOCAL\n", + " location = 'data/2017-03-03/#010_{name}_16-45-37'\n", + " | | | \n", + " Setpoint | time_set | time | (3200,)\n", + " Measured | my_controller_raw_output | raw_output | (3200,)\n", + " Measured | my_controller_demod_freq_0_mag | demod_freq_0_mag | (3200,)\n", + " Measured | my_controller_demod_freq_0_phase | demod_freq_0_phase | (3200,)\n", + " Measured | my_controller_demod_freq_1_mag | demod_freq_1_mag | (3200,)\n", + " Measured | my_controller_demod_freq_1_phase | demod_freq_1_phase | (3200,)\n", + "acquired at 2017-03-03 16:45:38\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data3 = qc.Measure(myctrl.acquisition).run()\n", + "plot = qc.MatPlot(data3.my_controller_raw_output)\n", + "plot.fig" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/png": "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\nEtO6Lo9hAAAAAElFTkSuQmCC\n", + "text/plain": [ + "" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "plot = qc.MatPlot(data3.my_controller_demod_freq_0_mag)\n", + "plot.fig" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/png": "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\nCBtSvRMQCSE7pH8PS/cPReRHsBORE+CXFL6XI/V6j/+Nku5/EZEphzzagBA5S24R/y6PyyFa3T4n\n2mcbolXmPzrojRJttxvAYgAfle79B6KtjTsRmQbuBPA6ce/TAP6ioXcLIn8KQiTMDdfkGSm1/wYA\nFyj3J2ra6x+k+xeIcj2IHHRHFuhDtwD4maYNkv4i8fBVcf0hRJqKHYicfn+MyJwQ52UAx0i/JwM4\nW/r9EwA3Sb9PFu9mm+h/dwM4QOFpEoB/K/Bcrjb7JwBLRZtNBPBWT7qZtgFwuOA97mNTAXzMUv5w\nRELtNlH3PABfU/LsI+6fNJjjSfg3OP/iwSkgYK8EEX0BwOeZ+Qut5qWdQUTXAJjPzNe0mpciIKKf\nIXKaPJWZB1rNjw5EdDCiGCFfZeacs3BAwFBCMH8E7O3YBuDXrWZiCOB5APe3mok6cBOAfQGsJSJ1\nx0XLQUQXItKKPIW8iSAgYMghaCoCAgKGHIjotYhW9zocx8ym2BRDAsJ34XrNrRXMXE9MlICAQUEQ\nKgICAgICAgJKQTB/BAQEBAQEBJSCIFQEBAQEBAQElIIgVAQEBAQEBASUgiBUBAQEBAQEBJSCIFQE\nBAQEBAQElIIgVAQEBAQEBASUgiBUBAQEBAQEBJSCIFQEBAQEBAQElIIgVAQEBAQEBASUgiBUBAQE\nBAQEBJSCIFQEBAQEBAQElIIgVAQEBAQEBASUgiBUBAQEBAQEBJSCIFQEBAQEBAQElIIgVAQEBAQE\nBASUgiBUBAQEBAQEBJSCIFQEBAQEBAQElIIgVAQEBAQEBASUgiBUBAQEBAQEBJSCIFQEBAQEBAQE\nlIIgVAQEBAQEBASUgmGtZmCo4ZWvfCWPGjWq1WwEBAQEBAQMCmbOnLmJmQ/3yRuEioIYNWoUZsyY\n0Wo2AgICAgICBgVEtMI3bzB/BAQEBAQEBJSCIFQEBAQEBAQElIIgVAQEBAQEBASUgiBUBAQEBAQE\nBJSCIFQEBAQEBAQElIIgVAQEBAQEBASUgiBUBAQEBAQEBJSCIFQEBAQEBAQElIIgVAQEBAQEBASU\ngqYKFUR0MhEtJqKlRDRac5+I6Epxfy4RvdtVlogOJaLHiWiJ+HuISP8YEc0konni70ekMu8R6UtF\nfSTSRxLRXSL9OSIa1cz2CAgI2HPAzHj6xS4wc6tZCQhoGzRNqCCiTgBXAzgFwHEAvkhExynZTgFw\n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\nRU5ErkJggg==\n", + "text/plain": [ + "" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "plot = qc.MatPlot(data3.my_controller_demod_freq_1_mag)\n", + "plot.fig" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Create the acquisition controller which will take care of the data handling and tell it which \n", + "# alazar instrument to talk to.\n", + "myintctrl = ATS9360Controller(name='my_controller_int', alazar_name='Alazar', integrate_samples=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "myintctrl.int_delay(2e-7)\n", + "myintctrl.int_time(2e-6)\n", + "myintctrl.num_avg(100)" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DataSet:\n", + " mode = DataMode.LOCAL\n", + " location = 'data/2017-03-03/#011_{name}_16-45-41'\n", + " | | | \n", + " Setpoint | single_set | single | (1,)\n", + " Measured | my_controller_int_raw_output | raw_output | (1,)\n", + "acquired at 2017-03-03 16:45:42\n" + ] + } + ], + "source": [ + "data4 = qc.Measure(myintctrl.acquisition).run()" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING:root:2.0 oscillation measured for largest demod freq, recommend at least 10: decrease sampling rate, take more samples or increase demodulation freq\n" + ] + } + ], + "source": [ + "myintctrl.demod_freqs.add_demodulator(1e6)" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DataSet:\n", + " mode = DataMode.LOCAL\n", + " location = 'data/2017-03-03/#012_{name}_16-45-42'\n", + " | | | \n", + " Setpoint | single_set | single | (1,)\n", + " Measured | my_controller_int_raw_output | raw_output | (1,)\n", + " Measured | my_controller_int_demod_freq_0_mag | demod_freq_0_mag | (1,)\n", + " Measured | my_controller_int_demod_freq_0_phase | demod_freq_0_phase | (1,)\n", + "acquired at 2017-03-03 16:45:43\n" + ] + } + ], + "source": [ + "data5 = qc.Measure(myintctrl.acquisition).run()" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "myrecctrl = ATS9360Controller(name='my_controller_rec', alazar_name='Alazar', \n", + " integrate_samples=True, average_records=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "ename": "ValueError", + "evalue": "Wrong number of inputs supplied", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mValueError\u001b[0m Traceback (most recent call last)", + "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[0mmyrecctrl\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mint_time\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m2e-6\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 3\u001b[0m \u001b[0mmyrecctrl\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnum_avg\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m100\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 4\u001b[1;33m \u001b[0mdata6\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mqc\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mMeasure\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mmyrecctrl\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0macquisition\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mrun\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[1;32mc:\\users\\jhn\\qcodes\\qcodes\\measure.py\u001b[0m in \u001b[0;36mrun\u001b[1;34m(self, use_threads, quiet, data_manager, station, **kwargs)\u001b[0m\n\u001b[0;32m 76\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 77\u001b[0m data_set = self._dummyLoop.get_data_set(data_manager=data_manager,\n\u001b[1;32m---> 78\u001b[1;33m **kwargs)\n\u001b[0m\u001b[0;32m 79\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 80\u001b[0m \u001b[1;31m# set the DataSet to local for now so we don't save it, since\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[1;32mc:\\users\\jhn\\qcodes\\qcodes\\loops.py\u001b[0m in \u001b[0;36mget_data_set\u001b[1;34m(self, data_manager, *args, **kwargs)\u001b[0m\n\u001b[0;32m 732\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 733\u001b[0m data_set = new_data(arrays=self.containers(), mode=data_mode,\n\u001b[1;32m--> 734\u001b[1;33m data_manager=data_manager, *args, **kwargs)\n\u001b[0m\u001b[0;32m 735\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 736\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdata_set\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mdata_set\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[1;32mc:\\users\\jhn\\qcodes\\qcodes\\loops.py\u001b[0m in \u001b[0;36mcontainers\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 521\u001b[0m \u001b[1;31m# note that this supports lists (separate output arrays)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 522\u001b[0m \u001b[1;31m# and arrays (nested in one/each output array) of return values\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 523\u001b[1;33m \u001b[0maction_arrays\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_parameter_arrays\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0maction\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 524\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 525\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[1;32mc:\\users\\jhn\\qcodes\\qcodes\\loops.py\u001b[0m in \u001b[0;36m_parameter_arrays\u001b[1;34m(self, action)\u001b[0m\n\u001b[0;32m 596\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 597\u001b[0m \u001b[0msp_blank\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m(\u001b[0m\u001b[1;32mNone\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m*\u001b[0m \u001b[0mlen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mshape\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 598\u001b[1;33m \u001b[0msp_vi\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_fill_blank\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0msp_vi\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0msp_blank\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 599\u001b[0m \u001b[0msp_ni\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_fill_blank\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0msp_ni\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0msp_blank\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 600\u001b[0m \u001b[0msp_li\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_fill_blank\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0msp_li\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0msp_blank\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[1;32mc:\\users\\jhn\\qcodes\\qcodes\\loops.py\u001b[0m in \u001b[0;36m_fill_blank\u001b[1;34m(self, inputs, blanks)\u001b[0m\n\u001b[0;32m 623\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[0minputs\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 624\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 625\u001b[1;33m \u001b[1;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'Wrong number of inputs supplied'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 626\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 627\u001b[0m def _make_setpoint_array(self, shape, i, prev_setpoints, vals, name,\n", + "\u001b[1;31mValueError\u001b[0m: Wrong number of inputs supplied" + ] + } + ], + "source": [ + "myrecctrl.int_delay(2e-7)\n", + "myrecctrl.int_time(2e-6)\n", + "myrecctrl.num_avg(100)\n", + "data6 = qc.Measure(myrecctrl.acquisition).run()" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "((),)" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "myrecctrl.acquisition.setpoints" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "anaconda-cloud": {}, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.3" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py b/qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py index 24c4b44201bd..2619ffeca4ff 100644 --- a/qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py +++ b/qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py @@ -2,7 +2,7 @@ from ..ATS import AcquisitionController import numpy as np import qcodes.instrument_drivers.AlazarTech.acq_helpers as helpers -from ..acqusition_parameters import AcqVariablesParam, \ +from ..acquisition_parameters import AcqVariablesParam, \ ExpandingAlazarArrayMultiParameter, \ NonSettableDerivedParameter, \ DemodFreqParameter @@ -38,15 +38,20 @@ class ATS9360Controller(AcquisitionController): def __init__(self, name, alazar_name, filter: str = 'win', numtaps: int =101, chan_b: bool = False, integrate_samples: bool = False, + average_records: bool = True, **kwargs): self.filter_settings = {'filter': self.filter_dict[filter], 'numtaps': numtaps} self.chan_b = chan_b self.number_of_channels = 2 + if not integrate_samples and not average_records: + raise RuntimeError("You need to either average records or integrate over samples") + super().__init__(name, alazar_name, **kwargs) self.add_parameter(name='acquisition', integrate_samples=integrate_samples, + average_records=average_records, parameter_class=ExpandingAlazarArrayMultiParameter) self._integrate_samples = integrate_samples @@ -261,11 +266,27 @@ def pre_start_capture(self): self.buffer = np.zeros(samples_per_record * records_per_buffer * self.number_of_channels) + avg_buffers = True + if avg_buffers: + len_buffers = 1 + else: + pass # not implemented yet - if len(demod_freqs): + if self.acquisition._average_records: + len_records = 1 + else: + len_records = records_per_buffer + + num_demods = self.demod_freqs.get_num_demods() + if num_demods: + mat_shape = (num_demods, len_buffers, + len_records, self.samples_per_record.get()) + self.mat_shape = mat_shape integer_list = np.arange(samples_per_record) + integer_mat = (np.outer(np.ones(len_buffers), + np.outer(len_records, integer_list))) angle_mat = 2 * np.pi * \ - np.outer(demod_freqs, integer_list) / sample_rate + np.outer(demod_freqs, integer_mat).reshape(mat_shape) / sample_rate self.cos_mat = np.cos(angle_mat) self.sin_mat = np.sin(angle_mat) @@ -302,24 +323,35 @@ def post_acquire(self): samples_per_record = alazar.samples_per_record.get() records_per_buffer = alazar.records_per_buffer.get() buffers_per_acquisition = alazar.buffers_per_acquisition.get() - reshaped_buf = self.buffer.reshape(records_per_buffer, + number_of_buffers = 1 # Hardcoded for now assuming all buffers go to the same array + reshaped_buf = self.buffer.reshape(number_of_buffers, + records_per_buffer, samples_per_record, self.number_of_channels) - recordA = np.uint16(np.mean(reshaped_buf[:, :, 0], axis=0) / - buffers_per_acquisition) - recordA = self._to_volts(recordA) - unpacked = [] - if self._integrate_samples: - unpacked.append(np.mean(recordA, axis=-1)) + channelAData = reshaped_buf[:, :, :, 0] + if self.acquisition._average_records: + recordA = np.uint16(np.mean(channelAData, axis=1, keepdims=True) / + buffers_per_acquisition) else: - unpacked.append(recordA) + recordA = np.uint16(channelAData)/buffers_per_acquisition + + recordA = self._to_volts(recordA) + # do demodulation if self.demod_freqs.get_num_demods(): magA, phaseA = self._fit(recordA) if self._integrate_samples: magA = np.mean(magA, axis=-1) phaseA = np.mean(phaseA, axis=-1) + + unpacked = [] + if self._integrate_samples: + unpacked.append(np.mean(recordA, axis=-1)) + else: + unpacked.append(np.squeeze(recordA)) + + if self.demod_freqs.get_num_demods(): for i in range(magA.shape[0]): unpacked.append(magA[i]) unpacked.append(phaseA[i]) @@ -360,7 +392,7 @@ def _fit(self, volt_rec): alazar = self._get_alazar() sample_rate = alazar.get_sample_rate() demod_length = self.demod_freqs.get_num_demods() - volt_rec_mat = np.outer(np.ones(demod_length), volt_rec) + volt_rec_mat = np.outer(np.ones(demod_length), volt_rec).reshape(self.mat_shape) re_mat = np.multiply(volt_rec_mat, self.cos_mat) im_mat = np.multiply(volt_rec_mat, self.sin_mat) @@ -393,8 +425,8 @@ def _fit(self, volt_rec): beginning = int(self.int_delay() * sample_rate) end = beginning + int(self.int_time() * sample_rate) - re_limited = re_filtered[:, beginning:end] - im_limited = im_filtered[:, beginning:end] + re_limited = re_filtered[..., beginning:end] + im_limited = im_filtered[..., beginning:end] else: re_limited = re_filtered im_limited = im_filtered diff --git a/qcodes/instrument_drivers/AlazarTech/acqusition_parameters.py b/qcodes/instrument_drivers/AlazarTech/acquisition_parameters.py similarity index 98% rename from qcodes/instrument_drivers/AlazarTech/acqusition_parameters.py rename to qcodes/instrument_drivers/AlazarTech/acquisition_parameters.py index 6ac1f4afaae8..36aec466b65b 100644 --- a/qcodes/instrument_drivers/AlazarTech/acqusition_parameters.py +++ b/qcodes/instrument_drivers/AlazarTech/acquisition_parameters.py @@ -216,9 +216,11 @@ def __init__(self, setpoint_names = (('time',),), setpoint_labels = (('time',),), setpoint_units = (('s',),), - integrate_samples=False): + integrate_samples=False, + average_records=True): self.acquisition_kwargs = {} self._integrate_samples = integrate_samples + self._average_records = average_records super().__init__(name, names=names, units=units, @@ -246,6 +248,9 @@ def set_setpoints_and_labels(self): print("start {} stop {} num steps {}".format(start, stop, samples)) arraysetpoints = (tuple(np.linspace(start, stop, samples)),) base_shape = (len(arraysetpoints[0]),) + elif not self._average_records: + arraysetpoints = tuple(range(self._instrument.records_per_buffer.get() or 0)) + base_shape = (self._instrument.records_per_buffer.get(),) else: arraysetpoints = () base_shape = () From 88b822b8d5377ab3c5aed554d0e26aee0923798b Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Mon, 6 Mar 2017 14:17:55 +0100 Subject: [PATCH 155/180] fix: more informative error message --- qcodes/loops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qcodes/loops.py b/qcodes/loops.py index 57532f83206f..61744b4f035c 100644 --- a/qcodes/loops.py +++ b/qcodes/loops.py @@ -622,7 +622,7 @@ def _fill_blank(self, inputs, blanks): elif len(inputs) == len(blanks): return inputs else: - raise ValueError('Wrong number of inputs supplied') + raise ValueError('Wrong number of inputs supplied got {} expected {}'.format(len(inputs), len(blanks))) def _make_setpoint_array(self, shape, i, prev_setpoints, vals, name, label, unit): From 55397d8042d6680c3adb8f5f2278e76788ec5c7a Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Mon, 6 Mar 2017 14:25:55 +0100 Subject: [PATCH 156/180] fix: correct tuple shape --- qcodes/instrument_drivers/AlazarTech/acquisition_parameters.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qcodes/instrument_drivers/AlazarTech/acquisition_parameters.py b/qcodes/instrument_drivers/AlazarTech/acquisition_parameters.py index 36aec466b65b..7884156dff70 100644 --- a/qcodes/instrument_drivers/AlazarTech/acquisition_parameters.py +++ b/qcodes/instrument_drivers/AlazarTech/acquisition_parameters.py @@ -249,7 +249,7 @@ def set_setpoints_and_labels(self): arraysetpoints = (tuple(np.linspace(start, stop, samples)),) base_shape = (len(arraysetpoints[0]),) elif not self._average_records: - arraysetpoints = tuple(range(self._instrument.records_per_buffer.get() or 0)) + arraysetpoints = (tuple(range(self._instrument.records_per_buffer.get() or 0)),) base_shape = (self._instrument.records_per_buffer.get(),) else: arraysetpoints = () From 2b9c1f806b7187a7c6b597244ac1b3539582ef8c Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Mon, 6 Mar 2017 14:27:15 +0100 Subject: [PATCH 157/180] fix: records per sample should be configurable in sequence mode --- .../acq_controllers/ATS9360Controller.py | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py b/qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py index 2619ffeca4ff..448b53f7c27a 100644 --- a/qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py +++ b/qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py @@ -74,9 +74,15 @@ def __init__(self, name, alazar_name, filter: str = 'win', self.add_parameter(name='buffers_per_acquisition', alternative='not controllable in this controller', parameter_class=NonSettableDerivedParameter) - self.add_parameter(name='records_per_buffer', - alternative='num_avg', - parameter_class=NonSettableDerivedParameter) + if average_records: + self.add_parameter(name='records_per_buffer', + alternative='num_avg', + parameter_class=NonSettableDerivedParameter) + else: + self.add_parameter(name='records_per_buffer', + parameter_class=AcqVariablesParam, + default_fn= lambda : 1, + check_and_update_fn= lambda x, **kwargs: True) self.add_parameter(name='samples_per_record', alternative='int_time and int_delay', parameter_class=NonSettableDerivedParameter) @@ -168,10 +174,14 @@ def _update_num_avg(self, value: int, **kwargs): if not isinstance(value, int) or value < 1: raise ValueError('number of averages must be a positive integer') - self.records_per_buffer._save_val(value) - self.buffers_per_acquisition._save_val(1) - self.allocated_buffers._save_val(1) + if self.acquisition._average_records: + self.records_per_buffer._save_val(value) + self.buffers_per_acquisition._save_val(1) + self.allocated_buffers._save_val(1) + else: + self.buffers_per_acquisition._save_val(value) + self.allocated_buffers._save_val(value) def _int_delay_default(self): """ From 7ea1e1a073778ed2ada8c11af44cb891e825b0e5 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Mon, 6 Mar 2017 14:27:28 +0100 Subject: [PATCH 158/180] Fix: bug fix --- .../AlazarTech/acq_controllers/ATS9360Controller.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py b/qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py index 448b53f7c27a..2bb2d68b9ef7 100644 --- a/qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py +++ b/qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py @@ -344,7 +344,7 @@ def post_acquire(self): recordA = np.uint16(np.mean(channelAData, axis=1, keepdims=True) / buffers_per_acquisition) else: - recordA = np.uint16(channelAData)/buffers_per_acquisition + recordA = np.uint16(channelAData/buffers_per_acquisition) recordA = self._to_volts(recordA) From 01cf358e5ce1dbcb79292c351a5a32ef172ca674 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Mon, 6 Mar 2017 15:38:19 +0100 Subject: [PATCH 159/180] Fix update setpoints when updating records --- .../AlazarTech/acq_controllers/ATS9360Controller.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py b/qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py index 2bb2d68b9ef7..8fe97d519b8a 100644 --- a/qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py +++ b/qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py @@ -82,7 +82,7 @@ def __init__(self, name, alazar_name, filter: str = 'win', self.add_parameter(name='records_per_buffer', parameter_class=AcqVariablesParam, default_fn= lambda : 1, - check_and_update_fn= lambda x, **kwargs: True) + check_and_update_fn=self._update_records_per_buffer) self.add_parameter(name='samples_per_record', alternative='int_time and int_delay', parameter_class=NonSettableDerivedParameter) @@ -134,6 +134,11 @@ def _update_samples_per_record(self, sample_rate, int_time, int_delay): self.samples_per_record._save_val(samples_per_record) self.acquisition.set_setpoints_and_labels() + def _update_records_per_buffer(self, value, **kwargs): + # Hack store the value early so its useful for set_setpoints... + self.records_per_buffer._save_val(value) + self.acquisition.set_setpoints_and_labels() + def _update_int_delay(self, value, **kwargs): """ Function to validate value for int_delay before setting parameter From c3cc1aa37e5905558cf04f3e4e8ee53870034b0f Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Tue, 7 Mar 2017 12:39:42 +0100 Subject: [PATCH 160/180] Fix: correct array shape --- .../AlazarTech/acq_controllers/ATS9360Controller.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py b/qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py index 8fe97d519b8a..00fafa84dbfe 100644 --- a/qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py +++ b/qcodes/instrument_drivers/AlazarTech/acq_controllers/ATS9360Controller.py @@ -299,7 +299,7 @@ def pre_start_capture(self): self.mat_shape = mat_shape integer_list = np.arange(samples_per_record) integer_mat = (np.outer(np.ones(len_buffers), - np.outer(len_records, integer_list))) + np.outer(np.ones(len_records), integer_list))) angle_mat = 2 * np.pi * \ np.outer(demod_freqs, integer_mat).reshape(mat_shape) / sample_rate self.cos_mat = np.cos(angle_mat) From a2be56bf038f48baf009fffbc3aa4510c012e5ef Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Tue, 7 Mar 2017 12:40:23 +0100 Subject: [PATCH 161/180] Fix: correct setpoints handling --- .../AlazarTech/acquisition_parameters.py | 80 ++++++++++++++----- 1 file changed, 62 insertions(+), 18 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/acquisition_parameters.py b/qcodes/instrument_drivers/AlazarTech/acquisition_parameters.py index 7884156dff70..96ec344d9271 100644 --- a/qcodes/instrument_drivers/AlazarTech/acquisition_parameters.py +++ b/qcodes/instrument_drivers/AlazarTech/acquisition_parameters.py @@ -213,14 +213,43 @@ def __init__(self, units = ('v',), shapes = ((1,),), setpoints = (((1,),),), - setpoint_names = (('time',),), - setpoint_labels = (('time',),), - setpoint_units = (('s',),), + setpoint_names = None, + setpoint_labels = None, + setpoint_units = None, integrate_samples=False, average_records=True): self.acquisition_kwargs = {} self._integrate_samples = integrate_samples self._average_records = average_records + + if setpoint_names: + self.setpoint_names_base = setpoint_names[0] + elif integrate_samples and average_records: + self.setpoint_names_base = () + elif integrate_samples: + self.setpoint_names_base = ('record_num',) + elif average_records: + self.setpoint_names_base = ('time',) + if setpoint_labels: + self.setpoint_labels_base = setpoint_names[0] + elif integrate_samples and average_records: + self.setpoint_labels_base = () + elif integrate_samples: + self.setpoint_labels_base = ('record num',) + elif average_records: + self.setpoint_labels_base = ('time',) + if setpoint_units: + self.setpoint_units_base = setpoint_units[0] + elif integrate_samples and average_records: + self.setpoint_units_base = () + elif integrate_samples: + self.setpoint_units_base = ('',) + elif average_records: + self.setpoint_units_base = ('s',) + + self.setpoints_start = 0 + self.setpoints_stop = 0 + super().__init__(name, names=names, units=units, @@ -232,6 +261,22 @@ def __init__(self, setpoint_labels=setpoint_labels, setpoint_units=setpoint_units) + + + def set_base_setpoints(self, base_name=None, base_label=None, base_unit=None, + setpoints_start=None, setpoints_stop=None): + if base_name: + self.setpoint_names_base = (base_name,) + if base_label: + self.setpoint_labels_base = (base_label,) + if base_unit: + self.setpoint_units_base = (base_unit,) + if setpoints_start: + self.setpoints_start = setpoints_start + if setpoints_stop: + self.setpoints_stop = setpoints_stop + self.set_setpoints_and_labels() + def set_setpoints_and_labels(self): if not self._integrate_samples: int_time = self._instrument.int_time.get() or 0 @@ -243,13 +288,15 @@ def set_setpoints_and_labels(self): stop = total_time else: start = 0 - samples = 1 stop = 1 - print("start {} stop {} num steps {}".format(start, stop, samples)) + samples = samples or 1 arraysetpoints = (tuple(np.linspace(start, stop, samples)),) base_shape = (len(arraysetpoints[0]),) elif not self._average_records: - arraysetpoints = (tuple(range(self._instrument.records_per_buffer.get() or 0)),) + num_records = self._instrument.records_per_buffer.get() or 0 + start = self.setpoints_start + stop = self.setpoints_stop or num_records-1 + arraysetpoints = (tuple(np.linspace(start, stop, num_records)),) base_shape = (self._instrument.records_per_buffer.get(),) else: arraysetpoints = () @@ -257,12 +304,9 @@ def set_setpoints_and_labels(self): setpoints = [arraysetpoints] names = [self.names[0]] labels = [self.labels[0]] - setpoint_name = self.setpoint_names[0] - setpoint_names = [setpoint_name] - setpoint_label = self.setpoint_labels[0] - setpoint_labels = [setpoint_label] - setpoint_unit = self.setpoint_units[0] - setpoint_units = [setpoint_unit] + setpoint_names = [self.setpoint_names_base] + setpoint_labels = [self.setpoint_labels_base] + setpoint_units = [self.setpoint_units_base] units = [self.units[0]] shapes = [base_shape] demod_freqs = self._instrument.demod_freqs.get() @@ -276,13 +320,13 @@ def set_setpoints_and_labels(self): shapes.append(base_shape) shapes.append(base_shape) setpoints.append(arraysetpoints) - setpoint_names.append(setpoint_name) - setpoint_labels.append(setpoint_label) - setpoint_units.append(setpoint_unit) + setpoint_names.append(self.setpoint_names_base) + setpoint_labels.append(self.setpoint_labels_base) + setpoint_units.append(self.setpoint_units_base) setpoints.append(arraysetpoints) - setpoint_names.append(setpoint_name) - setpoint_labels.append(setpoint_label) - setpoint_units.append(setpoint_unit) + setpoint_names.append(self.setpoint_names_base) + setpoint_labels.append(self.setpoint_labels_base) + setpoint_units.append(self.setpoint_units_base) self.names = tuple(names) self.labels = tuple(labels) self.units = tuple(units) From 38214dc74647fbfaa32eea50055f2482ac59cf2c Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Tue, 7 Mar 2017 12:40:51 +0100 Subject: [PATCH 162/180] Update example notebook --- ...e with Alazar ATS9360 new controller.ipynb | 587 +++++++----------- 1 file changed, 227 insertions(+), 360 deletions(-) diff --git a/docs/examples/Qcodes example with Alazar ATS9360 new controller.ipynb b/docs/examples/Qcodes example with Alazar ATS9360 new controller.ipynb index 5f2672a82652..b77761ed3ec0 100644 --- a/docs/examples/Qcodes example with Alazar ATS9360 new controller.ipynb +++ b/docs/examples/Qcodes example with Alazar ATS9360 new controller.ipynb @@ -103,7 +103,7 @@ { "data": { "text/plain": [ - "752" + "812" ] }, "execution_count": 3, @@ -157,9 +157,9 @@ "editable": true }, "source": [ - "### Basic Acquisition\n", + "## Example 1\n", "\n", - "Pulls the raw data the alazar acquires averaged over number of records buffers." + "Pulls the raw data the alazar acquires averaged over records and buffers." ] }, { @@ -174,8 +174,17 @@ "outputs": [], "source": [ "# Create the acquisition controller which will take care of the data handling and tell it which \n", - "# alazar instrument to talk to.\n", - "myctrl = ATS9360Controller(name='my_controller', alazar_name='Alazar')" + "# alazar instrument to talk to. Explicitly pass the default options to the Alazar.\n", + "# Dont integrate over samples but avarage over records\n", + "myctrl = ATS9360Controller(name='my_controller', alazar_name='Alazar',\n", + " integrate_samples=False, average_records=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Put the Alazar and the controller in a station so we ensure that all parameters are captured" ] }, { @@ -189,22 +198,20 @@ "station = qc.Station(alazar, myctrl)" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This controller is designed to be highlevel and it is not possible to directly set number of records, buffers and samples. The number of samples is indirecly controlled by the integration time and integration delay and the number of averages controls the number of buffers and records acquired" + ] + }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "start 0 stop 1 num steps 1\n", - "start 0 stop 2e-07 num steps 1152\n" - ] - } - ], + "outputs": [], "source": [ "myctrl.int_delay(2e-7)\n", "myctrl.int_time(2e-6)\n", @@ -219,18 +226,24 @@ }, "outputs": [ { - "data": { - "text/plain": [ - "100" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" + "name": "stdout", + "output_type": "stream", + "text": [ + "100 records per buffer set by num_avg\n", + "1152 samples per record set by int_time and int_delay\n" + ] } ], "source": [ - "myctrl.parameters['records_per_buffer'].get()" + "print(\"{} records per buffer set by num_avg\".format(myctrl.records_per_buffer()))\n", + "print(\"{} samples per record set by int_time and int_delay\".format(myctrl.samples_per_record()))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Per default the output will contain an array called raw_output of unprocessed data" ] }, { @@ -244,18 +257,19 @@ "name": "stdout", "output_type": "stream", "text": [ - "start 0 stop 2.2e-06 num steps 1152\n", - "1152\n", - "start 0 stop 2.2e-06 num steps 1152\n", - "1152\n" + "DataSet:\n", + " mode = DataMode.LOCAL\n", + " location = 'data/2017-03-07/#030_{name}_12-36-03'\n", + " | | | \n", + " Setpoint | time_set | time | (1152,)\n", + " Measured | my_controller_raw_output | raw_output | (1152,)\n", + "acquired at 2017-03-07 12:36:03\n" ] } ], "source": [ - "myctrl.int_delay(2e-7)\n", - "print(myctrl.samples_per_record.get_latest())\n", - "myctrl.int_time(2e-6)\n", - "print(myctrl.samples_per_record.get_latest())" + "# Measure this \n", + "data1 = qc.Measure(myctrl.acquisition).run(station=station)\n" ] }, { @@ -266,50 +280,46 @@ }, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "1\n", - "1\n", - "100\n" - ] + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ - "myctrl.num_avg(100)\n", - "print(myctrl.buffers_per_acquisition.get())\n", - "print(myctrl.allocated_buffers.get())\n", - "print(myctrl.records_per_buffer.get())" + "plot = qc.MatPlot(data1.my_controller_raw_output)\n", + "plot.fig" ] }, { - "cell_type": "code", - "execution_count": 11, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[ 0.001221 0.0002442 0.001221 ..., 0.0002442 0.001221 0.0002442]\n", - "(1152,)\n" - ] - } - ], + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As we are not integrating over samples the setpoints (label, unit and ticks on number) are automatically set from the integration time and integration delay. **Note at the moment this does not cut of the int_delay from the plot. It probably should**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Demodulation" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, "source": [ - "# Pull data from the card by calling get of the controllers acquisition parameter\n", - "data1 = myctrl.acquisition.get()\n", - "print(data1[0])\n", - "print(data1[0].shape)" + "We can add demodulators and remove them again, This will automatically take care of adapting the multiparameter to return multiple arrays to the dataset" ] }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 11, "metadata": { "collapsed": false }, @@ -325,11 +335,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "start 0 stop 2.2e-06 num steps 1152\n", "[2000000.0]\n", - "start 0 stop 2.2e-06 num steps 1152\n", "[2000000.0, 6000000.0]\n", - "start 0 stop 2.2e-06 num steps 1152\n", "[2000000.0]\n" ] } @@ -345,60 +352,7 @@ }, { "cell_type": "code", - "execution_count": 13, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "WARNING:root:8.0 oscillation measured for largest demod freq, recommend at least 10: decrease sampling rate, take more samples or increase demodulation freq\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "start 0 stop 2.2e-06 num steps 1152\n", - "start 0 stop 2.2e-06 num steps 1152\n" - ] - }, - { - "data": { - "text/plain": [ - "[4000000.0]" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "myctrl.demod_freqs.add_demodulator(2e6)\n", - "myctrl.demod_freqs.get_latest()\n", - "myctrl.demod_freqs.add_demodulator(4e6)\n", - "myctrl.demod_freqs.get_latest()\n", - "myctrl.demod_freqs.remove_demodulator(2e6)\n", - "myctrl.demod_freqs.get_latest()" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "# myctrl.acquisition.set_setpoints_and_labels()" - ] - }, - { - "cell_type": "code", - "execution_count": 15, + "execution_count": 12, "metadata": { "collapsed": false, "deletable": true, @@ -412,70 +366,79 @@ "text": [ "DataSet:\n", " mode = DataMode.LOCAL\n", - " location = 'data/2017-03-03/#007_{name}_16-45-29'\n", + " location = 'data/2017-03-07/#031_{name}_12-36-08'\n", " | | | \n", " Setpoint | time_set | time | (1152,)\n", " Measured | my_controller_raw_output | raw_output | (1152,)\n", " Measured | my_controller_demod_freq_0_mag | demod_freq_0_mag | (1152,)\n", " Measured | my_controller_demod_freq_0_phase | demod_freq_0_phase | (1152,)\n", - "acquired at 2017-03-03 16:45:30\n" + "acquired at 2017-03-07 12:36:09\n" ] } ], "source": [ "# Do this in as qcodes measurement (ie the same but makes a data set)\n", - "data2 = qc.Measure(myctrl.acquisition).run(station=station)\n", - "plot = qc.MatPlot(data2.my_controller_raw_output)" + "data2 = qc.Measure(myctrl.acquisition).run(station=station)\n" ] }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 13, "metadata": { "collapsed": false }, "outputs": [ { "data": { + "image/png": "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\n", "text/plain": [ - "(1, 1, 1, 1152)" + "" ] }, - "execution_count": 16, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "myctrl.mat_shape" + "plot = qc.MatPlot(data2.my_controller_demod_freq_0_mag)\n", + "plot.fig" ] }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 14, "metadata": { "collapsed": false }, "outputs": [ { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAggAAAFhCAYAAAAV71JsAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzt3Xm8HFWd9/HPN/dm324CYUsIYQlq2AQjoOO+AEExuD6g\nDrjMMIwyy6M+Do/Oy3F8XBh0nBFFEEcU1BlknGGMA8ooCggYJEEIBIiEEEhCgCxkX2/ye/6ouknf\n7r73Vt/bS3X39/169au7q+pUnVq6+lfnnDqliMDMzMys0LBGZ8DMzMzyxwGCmZmZlXCAYGZmZiUc\nIJiZmVkJBwhmZmZWwgGCmZmZlXCAYGZmZiUcIFhDSPqepM83Oh/WPCQdJ+n3kjZJekWj81NM0icl\nvSDpVkljGp0fs6FygGC5Jul2SX8yiHS3SjpD0oWSFqZ/KislXS6ps2C6yZJukrRV0lOS3lswboSk\nH0taLikkva5oGT+TtKXgtUvSQ/3kSZL+QdK69PUPklQw/teS1qR5fVDS3AHWcUaaZpukxyS9qWDc\n6yU9JGlDuqybJE0tSj9C0lpJ44qG35huu5GSni0aN1LStWken5X0saLxL02397b0/aUF464u2l47\nJW3ubx2LfAhYBnRFxG8rSFcXEXE5MA14MXBG1nSSrpG0RNJeSR8oM/4oSf8taXO6vy7PON/b0uO2\n8Hi/XdKOgn2wpJ/0IyV9J/1dbJb0gKQ5RdP8iaSl6bx+LumwrOtt+ecAwVqOpLHAbOAOYAzw18CB\nwGnAG4FPFEx+JbALOBh4H3CVpOMKxt8FvB/o9UcJEBFzImJczwu4B/j3frJ2EXAucBJwInAO8GcF\n4/8amBYRE9JpfyDp0H7m92/A74EDgE8DP5Y0JR33CHA2MAk4DHgcuKoo/WuAByJiS9HwlwEL0jw+\nXDTus8BM4Ajg9cAnJZ0FScAB/AT4Qbrc64CfpMOJiIuLtte/0f/2KjYZeDQi9laQpq4iYivwJMk+\nyepB4CPA/cUj0m33C+BXwCEkAcgPBpqhpPcBw/sYfUnBfnhRP7PpBFYArwUmAn8L3ChpRrqM1wFf\nBOaS7JsnSfaptYqI8Muvmr+Ak0lOgJuBHwE3AJ8n+SP5b2AN8EL6eVqa5gvAHmAHsAX4Rjr8ayQn\nrk3AQuDVRct6GzCvj3x8DPhp+nksSXBwbMH464HLyqRbCbyun/WbkeZ1Rj/T3ANcVPD9Q8D8PqY9\nNV3vU/sYfyywExhfMOxO4OIy044EvgQ8UjT8q8DHioZNApaln/8cuLxo/DPAGQXfPwfckH4+A1gF\nqGD808BZZfI0Nj0WXlvBMfR94HNltnsAF6bLWgt8umg7/hbYAKwGvgGMKBgfJH/Oj6f5+X/A0em+\n2gTcWDT9W4EH0vndA5xYJp+/Av5sEL+Ru4APFA27CPhNhfOZCPwBOD1dv86CcbcDf1Jp3grSLwLe\nmX7+CvDNgnGHpcs7erDz9ytfL5cgWM2lV0H/RXKCn0xy1fjOdPQw4LskV6TTge0kJ3Ei4tPAb9h/\nxXNJmuY+4KXpvP4V+HdJowoWeTZwcx/ZeQ2wOP18LNAdEX8oGP8gcFxJqoFdQHIiX97PNMel8+9z\nWWlR8g7gXpKT+YJ+5rUsIgqL6HvNT9J0SRtItukngOKi6X3bSdIb02lXANPSz18DPppWU7xW0iTg\n0H7W4ThgUaT/Fn2tY+qdJEHhnX2sXy+SJpOUCj3dxySvAl5EUkL0GUkvSYfvAf43SQnSK9LxHylK\neyZJqcnpwCeBa0hKjQ4HjgfOT/NwMnAtSanPAcC3gHmSRhbNbwXwup6SkyE6HVieVmetTasIThgg\nzRdJSotKSr1SX0rndXdxtVl/JB1M8ptZ3Nck6fvxWedp+eYAwerhdJLizn+OiN0R8WOSP3kiYl1E\n/EdEbEv/7L5AUqTZp4j4QZquOyL+keQKubCo9GzgluJ0kj5E8ifzlXTQOJKrxEKbgPEVr2ESIHxv\ngGnGARuLljWusB1CRLw1Xf7ZwP9E38XpxfPqmd++vEfE0xHRRfLn+LfAYz3jJB1NcmW5JJ32tnTa\n/wLeDUwFlgMHRkRXRNyRLpMy69CzzAHzVOBC4PqiYKIsSX8BrEvnfV0fk/19RGyPiAdJgpKT0vVa\nGBHz02NlOcmfevHxdXlEbIqIxSRVKv8TEcsiYiPwM5LSL0iu5r8VEfdGxJ6IuI6kFOf0ovl9jqT6\nZauk2QOt3wCmAecBV5Bcod9MQbVNsXR5fwR8vY/5/Q1wFMn+vQb4aXos9EvScOCHwHUR0XMc/Rx4\nt6QTJY0GPkNSguAGmi3CAYLVw2HAqqI/g6cAJI2R9K20IdQmkivKLkkdfc1M0ickPSppY3qlO5Hk\nT5D06mpjRKwoSnMuSTH7nIhYmw7eAkwomv1EkqLmzCS9iqR++McFwz5V0BDs6j6WNxHYUvwnmQZR\nPwPOkPS2dH6LC+b36kryHhHr2d8eoKfB2tkkf349+V2Zbsvz02mfJynVWS3pqwX5p8w6bC4YP2Ce\nJE0HXkdSnTOgiPg6ScnFIST13eUUXi1vIw1mJB2blso8mx5fXyQ9Vgo8V/B5e5nvPYHREcDH0xKV\nDen2Opzk+C70VyQB8ISI6KsEKKvtwF0R8bOI2EUS3B4AvETS+wqOiZ9JGgZ8E/iriOguN7M0uNkc\nETvTAOdukmOhuNHt+3rSpPP9Pkl13CUF8/olSZuU/yAJJpeT7OuVQ1xnywkHCFYPq4GphVfKJNUJ\nAB8nufo/LZLGea9Jh/dM2+vPM/1z/CTwHmBSetW7sWD6ktKDtBHdt4FzIqLwLoM/AJ2SZhYMO4m+\ni1D7ciHwn1HQ2C8ivhj7G4JdnA5enM4/67I6SerDiYjjCub3mzTdUZIKr877m18ncBD7/8B7baeI\nmAacBfwy3abXAB9NSw8+lk7zAsm+7GsdFgMnFu3nE8vk6Y+BuyNiWT/r3ktEPEvSlmBW1jSpq0hK\nTmamx9en2H+sVGoF8IV0m/S8xkREccO8lwA/j4jtg1xOoUUU/QZ6RMQPC46JOST7djbwIyV3n9yX\nTroy/d2UnQ3p9ojejW5/CMmdN8B3SBrxvjMidhfl4cqImBkRB5MECp2UNmy1JuUAwerht0A38JeS\nhkt6B0njMUiKn7cDG9J65r8rSvscSZEoBdN3k9Rfd0r6DL2vWnu1P5D0BpKi0XdGxO8KZxxJi/P/\nBD4naWxaEvA2kqulnvQjC9o3jJA0qvAPMC1afQ8DVy9AcsX8MUlTldxy+PGedJJeLGmOpNHpNno/\nSbB0R7kZpe0mHgD+Ls3TO4ATSE7SSHqHpBdJGpbe2fBV4PcRsV7JPfqnAr8umu3L2N+S/hTKt3+4\nHvhbSZPSev4/LVj320nq/P8y3W5/SfIH9KuieWSpjilnJ1Bpvf54kmqOLZJeTNLwcrC+DVws6TQl\nxkp6S1GQBkl12s6sM1Vyu+kokj/q4en+7Dk3/wA4XdKb0lK1vyZpiPlomVltJCnNeGn6Ojsd/jLg\nXkldks5M59+ZlhK8hqSqoC9XkQQ85xQHPOl8jk+3xXSSoPJraSBpraBWrR/98qvwRXJl83v238Xw\nI5K7GA4j+WPZQnJF/2cUtLwmaVj2B5I7HK4AOkgaim0iuZr9JEnR5puALtLAoWC5vyYJKLYUvH5W\nMH4ySb37VpIGcO8tyvfyND+FrxkF488nqS5Rhm0gkoaC69PX5T3pSE7C96bbZwPJ1d/bB5jfjHTb\nbQeWAG8qGPcXJLedbSUpfr8BOCId91bgv8vM71qS9gciCcyGl5lmZMH2f47SuyBOJrmzZDtJsHFy\n0fhXpHka39+69bG+1wJfLLMN+mypT/IH+Fi6339D0j7groJpAzim4HuvOwlIjtF/Kfh+Vrpveu6K\n+PfidUmX86EK1uv2MsfY6wrGvwNYmm7z24HjMs6317YBpqR57znG5gNv7if9EWn6nruIel7vS8d3\nkZRw9BxjXwI66nVO8av2r56Tk1nTk/Qe4F0R8Z5G5yXPJH0TeDgivtnovFRC0hdJApC3RVFRd15I\n6iLpg+JPIqKkoaxZM3EVg7WSDcA/NToTTeAB4KZGZ2IQ/gUYDTwjqfjOgYaT9AmS0oo7gNsanB2z\nIXMJgpk1VFp//Ugfo2dFRF99HzSFtK7/W2VGPRURg+lzw6wuHCCYmZlZCVcxmJmZWQkHCGZmZlbC\nAYKZmZmVcIBgZmZmJRwgmJmZWQkHCGZmZlbCAYKZmZmVcIBgZmZmJRwgmJmZWQkHCGZmZlbCAYKZ\nmZmVcIBgZmZmJRwgmJmZWQkHCGZmZlbCAYKZmZmVcIBgZmZmJRwgmJmZWQkHCGZmZlbCAYKZmZmV\ncIBgZmZmJRwgmJmZWYnORmegkQ488MCYMWNGo7NhZmZWNwsXLlwbEVMGmq6tA4QZM2awYMGCRmfD\nzMysbiQ9lWU6VzGYmZlZCQcIZmZmVsIBgpmZmZVwgGBmZmYlHCCYmZlZCQcIZmZmVsIBgpmZmZVw\ngGBmZmYlHCCYmZlZibbuSbHatu3qZvEzm+gYJo45aBwTRg3fN+53T67nhKkTGTV8GHctXcvBE0bx\n8KqNnHPSYQi498n1dI0ZzqjhHWze0c2LDxnPAys2cPpRB+ybx5ad3Sx5dhPde4I/PL+FU2dM5kWH\njAdgx+49PLhiAyOHd3DkAWOZOGY4dy9dy2lHTqazI4kDH161kYVPvcD4UZ3s2L2XYYLOjmGMGdHB\nkQeO5YCxIzhowijueWItT67dystnTObAcSO5fcnzbN+9hyMPGMsrjzmQ5zftYN3WXazbsotDJo5i\nZOcwDp88hkUrNzB2ZCcPrtjAtl17OHrKOF4+YxL3PrmePzrmwH3r8ZvH17Bi/XZOPXIyxxw0jiXP\nbuaR1Rs5cVoXC596ga7RwzmsazSHTBzFhm27uW/5eqZ2jWb8qE4WrdzI+FGdnHR4Fxu27Wb3nr1s\n3tHNm2cdXLI/fv/0C0wYPZwHV2zgVcccyNZde+iQGN4pNu/o5tiDk233q8eeY1RnB69M8/jIM5tY\n8twmTpjaxcKn1nPQ+FG8/sUHsX7rLla9sJ3NO3cz+4jJDNP+/fb4c1t420mHsWvPXh5YsYHRwzsY\nNyrZFkledwHiRYeMZ+yIDu5aupZDJ45CEms372Tk8I50v+xhw7bdHDxhFBIsWrmBCDjp8C627uxm\n5kHjeWjVRjo7xOoNO3jLiYeyecdufvHIc5x0eBfPbdrB+JHDWbY2yc/23Xv4+cPPsjeS43P2EZNZ\nv3UXrzj6AO5dto6d3Xs5YNwIfv/0Bk6ZPonNO5NlD5P25fPVM6cwZfzIfdu1cD+fdHgXL2zdxUsP\n7+q1n5c+v4VFK5PxEXDMQeP2HcP/s/hZAM447hCWr93KoRNHccC4ZP4r1m9j1569HD0lmX7zjt08\n/vwWTpk+idUbt7N5RzdTxo1kxQvbOHFaV7+/x2c2bGf+snWcdHgX23bu4YRpE3l63Tb2RDB2RAfr\ntu7iJYdOYNmaLfzuyfXsDRg1fBivf9FBTBo7Yt98Fj71Al1jkuNo845uxo3sZNeevQCM7BzGG158\nEF1jRvA/i59l4ujkN79x++6CY3gXi1Zu5OwTDmVExzDufmItrzrmQLbs7OYPz23hhKkT+e9FzwDQ\nMUzMOnQCY0d2cljX6H3H8M7de1m/Nfm99WzXvXuDA8aNZNUL21mzZQdrN+9i2DCxfVc3s2dM5rCu\n0Sxbs4WtO/ewe+9eXnfsFOY9+Ax79gYnHd7Fgys2APDmWQczPj1XPZFui8O6RvPaY/f3xHvP0rUc\nNGEUwzvEyM4O7nliLR3DxDknHsawYWLF+m3s7N7D6o07mDJ+JMM7hrFh225OnDaRnz6YrNtrj53C\nAeNG8tsn1nHKEV10DhvGTx98hmMPHs/T67eyZeceTp6e5OuEqROZmf4+73li7b5j8sgDx/LIM5sY\nOXwYm7bvZvee4ISpExk9ooN1W3Zyxx/W8IqjD+DQiaP35X3xMxt7/T5veWg1J07r2ndM3rN0LS8/\ncjLDOyq7Xp6/bB2bd3TzppccxF1L13LIhFGMGdnJ1K5k2c9vTvbJtMmjWfr8Fnbs3sP2XXs4aPyo\nfb/P+cvWc8oRXYzs7OD5TTu4a+naXvtmzvGHMnpER0X5qiYHCFX0sR89yM/Tk9+pR07mxj97BZCc\nqN7zrd9yzkmH8YqjDuBTNz20L80jz2xi7MhOvnbb473m9b9mH86PFqzgto+/dt/J8pJ/vZ/bl6zp\nNd3yy94CwKdueoj/vH8VAMdPncCnz57F+/7lXv7yjTP52JuPBeCtX7+r3/yP6BjGXZe+nvd++959\nw444YAxPrdu27/u9n3ojr7n81+zs3luSj7d94+6Sef7x6Ufw/flP8a9/ehqvPPpAnl63jT/+zu96\npTvzn+8sm58Dx41g7ZZd/ea5x39+5JWcMn3Svu8Rwdu/eU+vdes5qRcu+5FnNvGh7y3Yt24HTxjF\n2Vf8pmT+t/zlq/nT6xewasN2AD78qiMZP6qTf/7l/v22dstOnlizhX/73Yo+8/nqmQdy/qnT+cgP\n78+0XsXOfelh/NcDz+xfr87ZfOeuZcxftr5k2h2793Dn42u5edHqknEXvuIIrvtt/72tDu8Qu/cE\nE0Z1suizZ+4bXm4/v//06fxg/tP86KLTOe2oA3jTV+/oNb7nOP3zHyzkN4+vBeB1L3qG25es4eAJ\nI7n3U28C4NWX/7rX9H96/QLmL1vPY//vLF7xpV8BcNSBY1m2duu+afryyst+VZKH13z5173Wbfll\nb+EN/9g7r0dPGcttH38dkAQ077zqHvrzkkMn8Lm5x3HR9xeWjJsyfiRrNu8EkouEYw4ax+dvfpRv\n/fHLuO6e5dzzxDree9p0/vXep0vSPvHFs3sdw+UcPnk0K9ZvLzvu5Old/P7pDfu+f+CVM/jePctL\npvujYw7gh39yOgBvLNgWPeee+5av573/cm9JOoAN23Zz4Stn7Ntvxd532nR+mK7bYRNH8d0Pnsr5\n357P+0+fzrRJY7jsZ4/1uW7LL3sLD6/a2Ot8tPyyt5T8Ps856TC+fv7JvO0bd+/7fRYeG2+5Ijnv\nFf8+l1/2FhY+lazbxa89mkvnvLjPvBRbv3UX510zHyjdrj3LfsNX7mDLzm5OO3Iy9z5Z+vt8YMUG\nvnv3ci58xRH8/dzjeXWZ8+qvHnueb7z3lMz5qjYHCFX0yOpN+z4/tHLjvs9bdnYD8NjqTUybNLpX\nmifWbGFcQUlDj8ee2wzApu279w17eNXGkun2Tb96c8F0m3h+8w4Anly7NXP+d+3Zy/Zde3oNKwwO\nALbt2lNyEPdn8TNJnntOkpt27O5v8l6yBgcA6weYtjg46PHCtv3pthWte6EN23ftO/lAcoXcNab3\nfntq3TYee3ZzcdJeFj+ziWc2lD+hZ/Ho6t7zf3bTjl7HWqGVL2zn0Wc2lR23uI/hhXbvCQA27ege\ncNpH0vkNtM8eKjiGe/Lw3KadfU+frlv33tg3bFkFx3RfetatnCfW7J//7gzH+qOrN7F2c/l1WFMw\nfMlzm/ddpT5XsN8eW11+X+yNvvPYo6/gANh3Fdqjr/NHX8dPz7mnr3VLlr+tz3GQbJsez2zcse/3\n9ofnttDdzz7oUfj77EvP9ls1wO+q3O9zzeZk/svWbBlwOYV27N5/rli0ckPZaXrO+4v62L492/3x\n55NllzuvPtrHsVEvboNQZxl+831OmDmtWarZD5lmz3+eNOO2bIZzXhNkcdAcIFhLaoYTSzWo0Rkw\n64fkI7SZOUAwMzOzEg4QcqrnAnioEXi7xu/1KEBo123bCN7WjeNCgPblAMHMzMxKOECos8h4bVuu\nDr2Sq+J2qYO3/kWTHwhNnv1cacZjoRly3ISbNTMHCNaSmvFkaFbIh7A1mgOEnMpa0mBmZlYLDhBy\nbqjtg9zAqHbycAtXDrJQF+2ynvk0+I3v3dbcHCDklIsXh8abz5qdSxGt0RwgmJmZWQkHCPVW7u6E\njMUFlTS8G+zVR6uUXAxmPYbasLFRV3z9LbWvcc22m/N+XOYxe8V5ymMeB5LlNzm0u7sat1WaYX84\nQMipap0QXQdYO3nYtspFLmqnnYvZqx0UDXZ+Q2n/0Q5tR1r5CK1pgCDpLElLJC2VdGmZ8ZJ0RTp+\nkaRTBkor6d2SFkvaK2l20fxOlPTbdPxDkkbVcv2qpVxjt/09KdY7L/VdXp4MvdfKxmy8wSy1jXdz\nTeRxexbnqVV/25WsVuk2aNxGaYbdUbMAQVIHcCUwB5gFnC9pVtFkc4CZ6esi4KoMaR8G3gHcWbS8\nTuAHwMURcRzwOiD7s4VzxvfxD007X3m2Iu/N5uTTWHOrZQnCqcDSiFgWEbuAG4C5RdPMBa6PxHyg\nS9Kh/aWNiEcjYkmZ5Z0BLIqIB9Pp1kXEnjLTmZmZ2QBqGSBMBVYUfF+ZDssyTZa0xY4FQtKtku6X\n9MlB5brGhhJQu6tlq1SzHwfNnv88acZt2RRZbsYNm1FnozNQRZ3Aq4CXA9uA2yQtjIjbCieSdBFJ\ndQbTp0+veyatPlr1N9voqpNGVX21Y5VbK6xyC6xCW6tlCcIq4PCC79PSYVmmyZK22ErgzohYGxHb\ngFuAU4oniohrImJ2RMyeMmVKphVphFY4OZiZWfOqZYBwHzBT0pGSRgDnAfOKppkHXJDezXA6sDEi\nVmdMW+xW4ARJY9IGi68FHqnmCjXCUFvG56E74JaVg03r3Wu15kOsfdWsiiEiuiVdQvLH3QFcGxGL\nJV2cjr+a5Cr/bGApSbXAB/tLCyDp7cDXgSnAzZIeiIgzI+IFSV8lCS4CuCUibq7V+tVao4uSLZ8a\nXbLUqOW38q+h786smn+t27FqqJXUtA1CRNxCEgQUDru64HMAH82aNh1+E3BTH2l+QHKro5mZmQ2B\ne1Kss3IRdfaulitZTvZpq5Eub9qlq2UxUFfL5cc2227O+3GZx+y1QlfLWTLtrpZrxwFCTjVbV8vt\nWJTYiJ4TG72V6738Rq9vI1X9JzXIGQ6lHVM77L9WXkcHCDngrpbzwV0t22ANZXvWKrYu7VW4Nfe6\nu1quHQcIOVXtK/JaX+HnrQChFRp4ldPokpqGLX8IT0Gt8mLrtoxWOILzdl6wyjhAMDMzsxIOEOos\na0RdbrJKrphKGig5km9LTb/fmz3/edKEB0MzlAQ24WbNzAGCVUXefiOt+qNt9Go1avnl/ijqsY/r\nUqXSxzIaXZ1UDc2/Bu3NAUJeVfmX5R+qmZlVwgFCDtT0SqHCprItcNECDC4gqnQ/FLeIbkg/CBrk\nulY9J7WV9+Myj9mrVj8IeW9t734QascBQpuo/V0MzXC4t4A27Wq5nEbeYVAPOdrUg5enA8Yq5gAh\nB/rrB6HeWvRW6UzcD4IN1pD6QahaLnorzlOr7nP3g1A7DhDqbCh3J1RWlNZ76qxpWyXgH0yJRnN2\ntaz+u1ruY2Sz7ea85zeP+WuFrpaz/CRdxVA7DhByqlpF9j1XtbX+42+Gg73aGnEF0OjtXO8gqL/l\nVfobGVzQWHGSqqn2sgc7v6EUrDX6eK2HZrgVc7AcIOSAu1rOB1cx2GA1Q1fLrfrbdhVD7ThAyKmq\nXz3UOMrNW9VEzrJTNY1uDNqoKouyT0GteB6DWG4djqQ+l9ECB3HezgtWGQcIZmZmVsIBQp1l72q5\n3NNpKljOIJdrlic+bqunGbdlM+S5GfI4WA4QrCry1lCnVX+0JauVk4rMRjSCrXSZg8pi43pazt1v\najBaYR3Kac21KuUAIada9Q/OzMyagwOEHKhlw7NKWy63TGAymAZpTdjVcrLc+qRppLwfl3nMXmk/\nCIPLZd7vfnA/CLXjAKFN1LwIuHUbYudKo/8o87SfK/3DG1Q/CBWnqJ5G7+tqaIV1KKfRdxPViwOE\nHCjbD0J6/NX73vq8Xy3UkvtBsMFqin4QWnSv570fhL4C2WbYGw4Q6qz8c+2r39Vy8cRZr7ZaJTAe\nTHFqc3a13P9x0dc6NdtuzntjtzzmrlpVDI2UJceuYqgdBwgtridKbdQff6sEHOU04oqs0Sf5vjv1\nqU2+BvOcicHMq1rLqKZqL3rQXS0P4Thv1d9/4XoNtI7NvA0cIORA+SqGSMfVOy/1XV6euIqhvpr5\nxFmsKZ7mmIedXgN5r2LoSzPsjpoGCJLOkrRE0lJJl5YZL0lXpOMXSTploLSS3i1psaS9kmaXmed0\nSVskfaJ2a1Z7Vb96yDrdIBecp8Zr0Fp/PoUavV7V3c9D6PlrMEvLa1fLfVUDNXpnV0Hzr8HQNfM2\nqFmAIKkDuBKYA8wCzpc0q2iyOcDM9HURcFWGtA8D7wDu7GPRXwV+Vr01MTMzaz+dNZz3qcDSiFgG\nIOkGYC7wSME0c4HrIwmV50vqknQoMKOvtBHxaDqsZIGSzgWeBLbWaqWGqtxFQX9XCr3rurLHosVX\nPjVpCJljg6tvbr5GislyKx/XbPs57/nNY/5aobv1LL/J3DdSzFnpaiVqWcUwFVhR8H1lOizLNFnS\n9iJpHPA3wN8PMr+5ktcfc9+t4uvbeK1dFW/OobabqHj5fQ1vwG6uvJHiYO5sqThJ1bTCL6cVqknK\nqWS1Gt2weChaqZHiZ4F/iogt/U0k6SJJCyQtWLNmTX1yNoCyjRSrfFA17yHaPNxIsTJZTrLN8geT\nh+1ZLI95qoVGN1Ic7BHaDPunllUMq4DDC75PS4dlmWZ4hrTFTgPeJelyoAvYK2lHRHyjcKKIuAa4\nBmD27Nm5OPv0W8UwxL/2yrtazsUmGbJ69JrnrpbrJ++HZR6zV7Uqhpz/k+W9iiFvDbgrUcsA4T5g\npqQjSf7czwPeWzTNPOCStI3BacDGiFgtaU2GtL1ExKt7Pkv6LLClODhoZ9U6wVZaxNwMPwLLruIq\nphqqvKvlwSyjcfIeFLWzZq42qETNAoSI6JZ0CXAr0AFcGxGLJV2cjr8auAU4G1gKbAM+2F9aAElv\nB74OTAFulvRARJxZq/Woh/66Wrbm0UxVDHnQSod4XrtaLpy1+0FoVFfL5TXD7qhlCQIRcQtJEFA4\n7OqCzwEK8ud/AAAgAElEQVR8NGvadPhNwE0DLPezg8huw2S+i6GieRYPyJiugmXkWSN6zctnV8t9\nDW+uPZ33K7Y85q4l7mKo0jT7pm3EXQx9aIbd0UqNFFtKtQ6enqvaap1gK61KaMaTUlaNuCJr9B97\nvffzYIKfqi6/gds7Lw2V81g60miV3H7e6N/sUDhAyAFXMbQGVzFUpplPnMWG1tVybbZD6dMcW1Pe\nqxj60gz7wwFCHQzuPFjlq4esVQwDTldZt7ANa9mfg21eC9XK4WDn03eVRW3zULaDsUqXN5g81qWU\noq8RtV92rTW6aqhWQWhFx25NclAfDhDMzMxqpJkLyhwg1Fm5iDZ7V8sVLGeA79lTNqdG9JrXkEaK\nGqCevs8Sn9rkp1bynt085m/w54D8yNSZ1pDm50aK/XGAUAfN1sVrf9xIsbEavj1z1N9FpcXHjS7u\nrlRz5ba8Rh+vNWs82+gVqxMHCDlQvqvl6mqXA7qR3EixMtm6Wq59PqphaI0Ua6NZj4tKuZFi7ThA\nyIF8dbU8pMXlR116zeu9cd3Vcu3kPcDNY+5K+0EYXC7r/UCwSrmKoXYcINRBHs5ttW79Xs3W7da3\nRheT992mof75apW7GPK47Gpp9CrUavmNXq96cYCQA+X7QWiXQ7B1uIqhMq10jA+tM6E69YOQ85KA\nwXIVQ+04QKiDodwjXrWHLGXtB2Gw88lR47XBLrcZ/q+qlsdBzqia22jI/SBUmJfBVcXU/qDo+yfV\nBAfkAKod/FTcMLVW/SA0/67JxAFCnWU9rsp3DFPBzYpFk7bCycYq1y4nMhtYc5bY5D/PTblZM3KA\nkAP9N1IcmnZtpDi4UpvKEhVv2zz2g9CXFtnNuZHH7VmtPOW9KNyNFGvHAUId5OLqvVpVFX01UsvY\neC3vAUjer7Ianbtc9XdRaRXDIDLpRopDU/3btRu7/HrMOU8cIOSAGym2BjdSrFALHeJD2gc12g5N\ne1xUyI0Ua8cBQp2Vb2zVTxVDwbjKulouunIfZLpm1TZdLaMBulruY3iT7ea85zeP2ctjnirlrpYb\nywFCHdT6SXf1NNT+DvIegOT+j6jB+cvTUzsrXWaztdXI+aGYTZVXoh59XzRyvnnjACEHyt6fXO0f\nVpsc0I3kKobKtNIh6a6WG6fRVQyDDY6bYf84QMiBWt7FUOlh2CqBRD16zSvess3V1XJz7ei85zeP\nuSvO02B/23nvX8lVDLXjAKFNVOsEO9SnOeY9AMl59mh0DvPUpqHiFu2DChob+AfS4B9Lz9KHko3q\n38VQabVSjTpKqslc88cBQg7U42mOVnuuYqhMo/8Aq6k5ulquyWIartFVDIPVDLvDAUIdDOXKpe5d\nLQ8wXaUP6xns3RRDNdhi97z/adX7eMiartYNAMv3LFrDBQ4+SdWWMfS7aoaYPoY+n6p3tVzx8qu6\n+JrPN28cINRZ1iKvclMN5YTaJsezFWmXE5kNrBmPhWbIcjNu16wcIFTJ3r3Bjt17BpW2/yh7aEdf\nxV0tN8VPcmD16DWvqbtabrLdXKvsVusKN4+bs12ex+JGirWjWhapSjoL+BrQAfxLRFxWNF7p+LOB\nbcAHIuL+/tJKejfwWeAlwKkRsSAd/mbgMmAEsAv4PxHxq/7yN3v27FiwYEFV1vWpdVt57Zdvr8q8\nzMzMAEZ0DOMPX5hT1XlKWhgRswearmYlCJI6gCuBOcAs4HxJs4ommwPMTF8XAVdlSPsw8A7gzqJ5\nrQXOiYgTgAuB71d7nczMzOpp1569DVt2Zw3nfSqwNCKWAUi6AZgLPFIwzVzg+kiKMeZL6pJ0KDCj\nr7QR8Wg6rNfCIuL3BV8XA6MljYyInbVYuWKNasFuZmZWC7VsgzAVWFHwfWU6LMs0WdL2553A/fUK\nDszMzFpNLUsQGkLSccA/AGf0Mf4ikuoMpk+fXsXlVm1WZmZmDVfLEoRVwOEF36elw7JMkyVtCUnT\ngJuACyLiiXLTRMQ1ETE7ImZPmTJlwJUwMzNrR7UMEO4DZko6UtII4DxgXtE084ALlDgd2BgRqzOm\n7UVSF3AzcGlE3F3tlTEzM2snNQsQIqIbuAS4FXgUuDEiFku6WNLF6WS3AMuApcC3gY/0lxZA0tsl\nrQReAdws6dZ0XpcAxwCfkfRA+jqoVutnZmbWyjK1QZA0CTgM2A4sj4hM911ExC0kQUDhsKsLPgfw\n0axp0+E3kVQjFA//PPD5LPmqBbdBMDOzVtJngCBpIsmf9/kknQ+tAUYBB0uaD3wzIn5dl1yamZlZ\nXfVXgvBj4Hrg1RGxoXCEpJcBfyzpqIj4Ti0z2CzKPZHRzMysWfUZIETEm/sZtxBYWJMcNSmHB2Zm\n1koGbKQo6aeS3itpbD0yZGZmZo2X5S6GrwCvAh6R9GNJ75I0qsb5ajquYTAzs1Yy4F0MEXEHcEf6\nAKU3AH8KXAtMqHHezMzMrEGy3uY4GjgH+F/AKcB1tcxUM/LDmszMrJUMGCBIupHkyYw/B74B3JG1\nHwQzMzNrTllKEL4DnB8Re2qdmWbmNghmZtZK+mykKOlVABFxa7ngQNIEScfXMnNmZmbWGP2VILxT\n0uUkVQsL2d+T4jHA64EjgI/XPIdNwgUIZmbWSvrrKOl/S5oMvBN4N3AoybMYHgW+FRF31SeLTcIR\ngpmZtZB+2yBExHqSpyx+uz7ZMTMzszyo2eOe241vczQzs1biAMHMzMxKZHkWw8gsw9qdb3M0M7NW\nkqUE4bcZh5mZmVmL6LORoqRDgKnAaEkns7+d/gRgTB3y1lRcgGBmZq2kv7sYzgQ+AEwDvlowfDPw\nqRrmyczMzBqsv34QrgOuk/TOiPiPOuapKcmNEMzMrIVkeRbD8ZKOKx4YEZ+rQX7MzMwsB7IECFsK\nPo8C3krSm6IVcPmBmZm1kgEDhIj4x8Lvkr4C3FqzHDUp1zCYmVkrGUxHSWNIGi6amZlZixqwBEHS\nQ0CkXzuAKYDbHxRxV8tmZtZKspQgvBU4J32dARwWEd/IMnNJZ0laImmppEvLjJekK9LxiySdMlBa\nSe+WtFjSXkmzi+b3f9Ppl0g6M0sezczMrNSAAUJEPAUcAMwF3gGckGXGkjqAK4E5wCzgfEmziiab\nA8xMXxcBV2VI+3CajzuLljcLOA84DjgL+GY6n/pwAYKZmbWQLM9i+AxwHUmQcCDwPUl/m2HepwJL\nI2JZROwCbiAJMgrNBa6PxHygS9Kh/aWNiEcjYkmZ5c0FboiInRHxJLA0nY+ZmZlVKMttju8DToqI\nHQCSLgMeAD4/QLqpwIqC7yuB0zJMMzVj2nLLm19mXnXhuxjMzKyVZGmD8AxJ/wc9RgKrapOd2pN0\nkaQFkhasWbOm0dkxMzPLpSwBwkZgsaTvSfouSRuADWnjwiv6SbcKOLzg+zRKA4u+psmSdjDLIyKu\niYjZETF7ypQpA8wyOxcgmJlZK8lSxXBT+upxe8Z53wfMlHQkyR/1ecB7i6aZB1wi6QaSKoSNEbFa\n0poMaYvNA/5V0leBw0gaPv4uY16HzM9iMDOzVpIlQOiKiK8VDpD0V8XDikVEt6RLSHpd7ACujYjF\nki5Ox18N3AKcTdKgcBvwwf7Spst+O/B1kv4Ybpb0QEScmc77RuARoBv4aETsybYZzMzMrJAiov8J\npPsj4pSiYb+PiJNrmrM6mD17dixYsKAq89q6s5vj/s49UJuZWXUtv+wtVZ2fpIURMXug6fosQZB0\nPkmx/pGS5hWMGg+sH3oWzczMLK/6q2K4B1hN0vdB4QObNgOLapmpZuQmCGZm1kr6DBDSHhSfAl5R\nv+yYmZlZHmR5WNNm9j+saQQwHNgaERNqmbFm44c1mZlZKxkwQIiI8T2fldzLNxc4vZaZMjMzs8bK\n0lHSPukzE/4L8JMSi7gNgpmZtZIsVQzvKPg6DJgN7KhZjszMzKzhsnSUdE7B525gOaVPZTQzM7MW\nkqUNwgfrkZFm5yoGMzNrJQO2QZA0TdJNkp5PX/8haVo9MmdmZmaNkaWR4ndJHoR0WPr6aTrMCvg2\nRzMzayVZAoQpEfHdiOhOX98jeVCSmZmZtagsAcI6Se+X1JG+3g+sq3XGmo3bIJiZWSvJEiB8CHgP\n8CzJsxneRfpYZjMzM2tNWe5ieAp4Wx3y0tRcgGBmZq2kop4UzczMrD04QKgSuRGCmZm1EAcIVeLw\nwMzMWkmWZzE8AcwHfgP8JiIW1zxXZmZm1lBZShBmAd8CDgC+LOkJSTfVNlvNxzUMZmbWSrIECHuA\n3en7XuD59GVmZmYtKsvTHDcBDwFfBb4dEe4kqQw3UjQzs1aSpQThfOBO4CPADZL+XtIba5stMzMz\na6QsHSX9BPiJpBcDc4C/Bj4JjK5x3szMzKxBsjzu+T8kLQW+BowBLgAm1TpjZmZm1jhZqhi+BLwo\nIs6MiC9ExB0RsSPLzCWdJWmJpKWSLi0zXpKuSMcvknTKQGklTZb0C0mPp++T0uHDJV0n6SFJj0r6\nv1nyaGZmZqUGDBAiYgHwEknvkXRBz2ugdJI6gCtJqiVmAedLmlU02RxgZvq6CLgqQ9pLgdsiYiZw\nW/od4N3AyIg4AXgZ8GeSZgyUTzMzMyuVpYrh74Cvp6/XA5eT7eFNpwJLI2JZROwCbgDmFk0zF7g+\nEvOBLkmHDpB2LnBd+vk64Nz0cwBjJXWStI/YRXIHhpmZmVUoSxXDu4A3As9GxAeBk4CJGdJNBVYU\nfF+ZDssyTX9pD46I1ennZ4GD088/BraSPJL6aeArEbE+Qz7NzMysSJYAYXtE7AW6JU0g6STp8Npm\nK5uICJKSA0hKHfYAhwFHAh+XdFRxGkkXSVogacGaNWvql1kzM7MmkiVAWCCpC/g2sBC4H/hthnSr\n6B1ITEuHZZmmv7TPpdUQpO89vTq+F/h5ROyOiOeBu4HZxZmKiGsiYnZEzJ4yZUqG1TAzM2s//QYI\nSroH/FJEbIiIq4E3AxemVQ0DuQ+YKelISSOA84B5RdPMAy5I72Y4HdiYVh/0l3YecGH6+ULgJ+nn\np4E3pPkeC5wOPJYhn2ZmZlak346SIiIk3QKckH5fnnXGEdEt6RLgVqADuDYiFku6OB1/NXALcDaw\nFNgGfLC/tOmsLwNulPRh4CngPenwK4HvSlpM8vTl70bEoqz5NTMzs/2yPIvhfkkvj4j7Kp15RNxC\nEgQUDru64HMAH82aNh2+jqTRZPHwLSS3OpqZmdkQZQkQTgPeJ+kpkrsERPLffmJNc2ZmZmYNkyVA\nOLPmuTAzM7NcyfKwpqfqkREzMzPLjyy3OZqZmVmDJM316s8BgpmZmZVwgGBmZpZjDSpAcIBgZmZm\npRwg5Myc4w8BYMr4kQ3OiZmZ5UGDChAcIJhZ85AanQOz9uEAIWd6ToA+D5qZGfguBiviKyUzM2sk\nBwhm1jQcN1s7chsEMzMzK+HbHK0X+VrJzMwayAGCmTUNuXGOtaFoUCWDA4Sc6Sk58HnQzMwayQFC\nTjk+MDMzcBsEM7MBOXA2qx8HCDnTU9fkulYzs3xql9OzA4ScaVRRklkzaJcTs+VbuxyGDhDMzMxy\nzG0QrBdfKZmZ5VO9q4B9m6MBrmIw6487ELM8aJej0AGCmZlZjrmKwXpxFYOZWT61y/m5pgGCpLMk\nLZG0VNKlZcZL0hXp+EWSThkoraTJkn4h6fH0fVLBuBMl/VbSYkkPSRpVy/WrJRelmpXhn4XlQL3P\nzy33NEdJHcCVwBxgFnC+pFlFk80BZqavi4CrMqS9FLgtImYCt6XfkdQJ/AC4OCKOA14H7K7V+plZ\n/Tk+sFxokwOxliUIpwJLI2JZROwCbgDmFk0zF7g+EvOBLkmHDpB2LnBd+vk64Nz08xnAooh4ECAi\n1kXEnlqtXK3s7yipwRkxM7Oy6n16jgY1QqhlgDAVWFHwfWU6LMs0/aU9OCJWp5+fBQ5OPx8LhKRb\nJd0v6ZPlMiXpIkkLJC1Ys2ZNpetkZmbWFpq6kWIkYVVPaNUJvAp4X/r+dklvLJPmmoiYHRGzp0yZ\nUr/MZtQTKLoAwcwsn+pdwttybRCAVcDhBd+npcOyTNNf2ufSagjS9+fT4SuBOyNibURsA24BTqHJ\nuBsEs7656s3yoF0akdcyQLgPmCnpSEkjgPOAeUXTzAMuSO9mOB3YmFYf9Jd2HnBh+vlC4Cfp51uB\nEySNSRssvhZ4pFYrV2t+WJOZmUHj+kHorNWMI6Jb0iUkf9wdwLURsVjSxen4q0mu8s8GlgLbgA/2\nlzad9WXAjZI+DDwFvCdN84Kkr5IEFwHcEhE312r9as3hgZlZPtX9+q3VAgSAiLiFJAgoHHZ1wecA\nPpo1bTp8HVDStiAd9wOSWx2blrtaNutbuxTtWr61y1HY1I0UzczMWp0f1mS9tUuIalYBN82xPBjW\nJgeiA4Scao/Dz8zMBuKHNZmZmTWDNrmCc4CQOz1dLbfJEWhm1mTa5CYGBwhmZmZWygFCzrirZbO+\n+TZgy4N6l/C24sOabBB8/jMzyzc/i8Eayk0QzMyskRwg5JR7jDMzy6e6N1L0bY4GjatrMjOzbNrl\nLjMHCGZmZjnmrpatlzYJUM0q0qgTpVmhYW1yfnaAYGZmlmdug2BmZtYM2qMIwQFCzvQEiu3SCMbM\nrNm4HwQzMzNrWw4QcsZdLZv1zXcBWx64HwRrCJ//zMzyrf5VDL7N0Qq4CYKZmTWSA4SccoBgZpZP\n9e4K31UMZmZmTaBdLuAcIOSUH9ZkZpZPdW+kWOfl9XCAkDN+WJNZ3/zrsDxol35qahogSDpL0hJJ\nSyVdWma8JF2Rjl8k6ZSB0kqaLOkXkh5P3ycVzXO6pC2SPlHLdau1Njn+zMxsAI26cKxZgCCpA7gS\nmAPMAs6XNKtosjnAzPR1EXBVhrSXArdFxEzgtvR7oa8CP6v6CpmZmbWRWpYgnAosjYhlEbELuAGY\nWzTNXOD6SMwHuiQdOkDaucB16efrgHN7ZibpXOBJYHGtVqrW3FGSmVm+1b0fhBa8i2EqsKLg+8p0\nWJZp+kt7cESsTj8/CxwMIGkc8DfA31cj82ZmZu2sqRspRlIx0xNbfRb4p4jY0l8aSRdJWiBpwZo1\na2qdxcFzIwSzUm6laDnQLqfnzhrOexVweMH3aemwLNMM7yftc5IOjYjVaXXE8+nw04B3Sboc6AL2\nStoREd8oXGBEXANcAzB79uzcnW4a1aWmmZll446Shu4+YKakIyWNAM4D5hVNMw+4IL2b4XRgY1p9\n0F/aecCF6ecLgZ8ARMSrI2JGRMwA/hn4YnFw0EzaJEA1M2s6LkEYoojolnQJcCvQAVwbEYslXZyO\nvxq4BTgbWApsAz7YX9p01pcBN0r6MPAU8J5arUMjtcsBaGbWbOrfUVJjihBqWcVARNxCEgQUDru6\n4HMAH82aNh2+DnjjAMv97CCya2ZmZqmmbqTYylyAYGaWT/XuSbEV2yDYILinZbO+uRGv5UG7XMA5\nQMipdunr28zM+ueHNZmZmTWDNrl+c4CQM3tdx2Bmlmt1v4uh1R7WZGZmZkPnKgbrpU1KsMwq4gI2\ny4NhbdJGzAGCmZlZjvk2RzMzsybQJgUIDhDyxkWoZmb5Vu+HNTWqFYIDBDMzMyvhAMHMzCzH3AbB\ngMbdzmLWDPz7MKsfBwhmZmY55n4QzMzMrISrGAzY36Wmi1LNzPLJtzmamZlZwzXqMecOEHKqTQJU\ns4o06qE1Zu3IAYKZmVmOuQ2CmZmZ5YYDhJxxCaqZmRVyCYIBcO7JUwE46/hDGpyT+ps8dgQHjhvZ\n6GxYjvX8Pswa6czj2uP8rHZu9DN79uxYsGBB1ea3bVc3m7Z3szeCYVLJO0DHMDFq+DA27+hmmLSv\ndaoQw4bBQeNHsX7rLiaNGc6m7d1s3dW9bx5jR3ayZ2+ws3sPYv98J44ezsbtuwH2DRsmGDuyk2HS\nvnE90xXmp7NDjOgcxpYd3SV5LZf/oazbmBGdbNq+u895dY0ZDsCGbbszLbtw/pXkdcLoTjbv6CaC\nkuknjh7O1p3d7C0zrtyyJ4yqbPq+8lq8b8rt0/72W1/zHzuikyDYtmtPr/kOtJ+DGHC79swry36Y\nMHo423Z1s3cv/U5fvN7jRnWyu3svu/bsRYgDx41gR/fefo+j/o7JgaYf6jE2lOk7honRIzrKrlvW\n/ZblmB8mGDeqc992znIMF597BspPX+eqrOeSns8SjB/VOeB5Nct+KPc7G8z0Y0d2Mn5kJ89v3rnv\nGKvGfps4ejhbd3UzangHu7v3sntPsGnHbrbt2sOLDh7P6BEdVIukhRExe8DpHCBUL0AwMzPLu6wB\ngqsYzMzMrERNAwRJZ0laImmppEvLjJekK9LxiySdMlBaSZMl/ULS4+n7pHT4myUtlPRQ+v6GWq6b\nmZlZK6tZgCCpA7gSmAPMAs6XNKtosjnAzPR1EXBVhrSXArdFxEzgtvQ7wFrgnIg4AbgQ+H6NVs3M\nzKzl1bIE4VRgaUQsi4hdwA3A3KJp5gLXR2I+0CXp0AHSzgWuSz9fB5wLEBG/j4hn0uGLgdGS3CTe\nzMxsEGoZIEwFVhR8X5kOyzJNf2kPjojV6edngYPLLPudwP0RsXNwWTczM2tvnY3OwFBEREjqdRuG\npOOAfwDOKJdG0kUk1RlMnz695nk0MzNrRrUsQVgFHF7wfVo6LMs0/aV9Lq2GIH1/vmciSdOAm4AL\nIuKJcpmKiGsiYnZEzJ4yZUrFK2VmZtYOahkg3AfMlHSkpBHAecC8omnmARekdzOcDmxMqw/6SzuP\npBEi6ftPACR1ATcDl0bE3TVcLzMzs5ZXsyqGiOiWdAlwK9ABXBsRiyVdnI6/GrgFOBtYCmwDPthf\n2nTWlwE3Svow8BTwnnT4JcAxwGckfSYddkZE7CthMDMzs2zck6J7UjQzszbirpYzkLSGpBSimg4k\n6ZPB6sPbu768vevL27v+2mGbHxERAzbCa+sAoRYkLcgSmVl1eHvXl7d3fXl715+3+X5+FoOZmZmV\ncIBgZmZmJRwgVN81jc5Am/H2ri9v7/ry9q4/b/OU2yCYmZlZCZcgmJmZWYm2CRAknSVpiaSlki4t\nM16SrkjHL5J0ykBpJU2W9AtJj6fvkwrG/d90+iWSziwY/jJJD6XjrpCkdPhIST9Kh98raUZBmgvT\nZTwuqacXyVxr8u29R9ID6au498/caoJt/hpJ90vqlvSuorz5GKeu27vpjvEm2N4fk/RIuuzbJB1R\nkKbpjm8AIqLlXyS9MT4BHAWMAB4EZhVNczbwM0DA6cC9A6UFLifp2hngUuAf0s+z0ulGAkem6TvS\ncb9L5690eXPS4R8Brk4/nwf8KP08GViWvk9KP09q9DZt1e2dft/S6G3Yott8BnAicD3wroJ8+Riv\n4/ZuxmO8Sbb364Ex6ec/p4nP4T2vdilBOBVYGhHLImIXcAMwt2iaucD1kZgPdCl5GFR/aecC16Wf\nrwPOLRh+Q0TsjIgnSbqSPjWd34SImB/JkXN9UZqeef0YeGMamZ4J/CIi1kfEC8AvgLOqslVqp5m3\nd7PK/TaPiOURsQjYW5QvH+P13d7NqBm2968jYluafj7JQwahOY9voH2qGKYCKwq+r0yHZZmmv7QH\nR/JwKYBngYMzzGtlH/PalyYiuoGNwAEZ8543zby9AUalRbPzJZ1Lc2iGbT6UvOdNM29vaL5jvNm2\n94dJShey5j2XavawpnYTESHJt4TUSY239xERsUrSUcCvJD0UfTw+vJ34GK8vH+P1Va3tLen9wGzg\ntUPPVWO1SwnCKuDwgu/T0mFZpukv7XNpkRPpe8+TI/ub17Qyw3ulkdQJTATWZcx73jTz9iYiVqXv\ny4DbgZP7X91caIZtPpS8500zb+9mPMabYntLehPwaeBtEbGzgrznUzUaMuT9RVJSsoyksUlPI5Xj\niqZ5C70buPxuoLTAl+ndwOXy9PNx9G7gsoy+G7icnQ7/KL0bzd0Y+xu4PEnSuGVS+nlyo7dpC2/v\nScDI9POBwOMUNYbK46sZtnlBPr5HaSNFH+P1295Nd4w3w/YmCbKeAGYW5avpju99eW90Bup4gJ0N\n/CHdgZ9Oh10MXJx+FnBlOv4hYHZ/adPhBwC3pT+wXxbudJIo8glgCWkr13T4bODhdNw32N9Z1Sjg\n30kaw/wOOKogzYfS4UuBDzZ6W7by9gZemebnwfT9w43eli20zV9OUv+6laS0ZrGP8fpv72Y9xptg\ne/8SeA54IH3Na+bjOyLck6KZmZmVapc2CGZmZlYBBwhmZmZWwgGCmZmZlXCAYGZmZiUcIJiZmVkJ\nBwhmlomkLkkfKfh+mKQf12hZ50r6TD/jT5D0vVos28wSvs3RzDJR8kjs/46I4+uwrHtIeqNb2880\nvwQ+FBFP1zo/Zu3IJQhmltVlwNGSHpD0ZUkzJD0MIOkDkv5L0i8kLZd0iaSPSfp9+kCgyel0R0v6\nuaSFkn4j6cXFC5F0LLCzJziQ9G5JD0t6UNKdBZP+lKQXTDOrAQcIZpbVpcATEfHSiPg/ZcYfD7yD\npAe/LwDbIuJk4LfABek01wB/EREvAz4BfLPMfP4IuL/g+2eAMyPiJOBtBcMXAK8ewvqYWT/8NEcz\nq5ZfR8RmYLOkjSRX+JB0e3uipHEk3fz+u6SeNCPLzOdQYE3B97uB70m6EfjPguHPA4dVMf9mVsAB\ngplVy86Cz3sLvu8lOdcMAzZExEsHmM92kqdrAhARF0s6jeRhPAslvSwi1pE8T2N7tTJvZr25isHM\nstoMjB9s4ojYBDwp6d0ASpxUZtJHgWN6vkg6OiLujYjPkJQs9Dw691iSh+aYWQ04QDCzTNKr9rvT\nBoNfHuRs3gd8WNKDwGJgbplp7gRO1v56iC9LeihtEHkPyVMIAV4P3DzIfJjZAHybo5nljqSvAT+N\niF/2MX4kcAfwqojormvmzNqESxDMLI++CIzpZ/x04FIHB2a14xIEMzMzK+ESBDMzMyvhAMHMzMxK\nOEbt0AIAAAAgSURBVEAwMzOzEg4QzMzMrIQDBDMzMyvhAMHMzMxK/H9RIHz4hahpqAAAAABJRU5E\nrkJggg==\n", + "image/png": "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\n", "text/plain": [ - "" + "" ] }, - "execution_count": 17, + "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ + "plot = qc.MatPlot(data2.my_controller_demod_freq_0_phase)\n", "plot.fig" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It's possible to change int_time, int_delay and num_avg in an already created acq_controller" + ] + }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 15, "metadata": { "collapsed": false }, @@ -484,15 +447,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "WARNING:root:8.0 oscillation measured for largest demod freq, recommend at least 10: decrease sampling rate, take more samples or increase demodulation freq\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "start 0 stop 2.2e-06 num steps 1152\n", - "start 0 stop 2.2e-06 num steps 3200\n" + "WARNING:root:4.0 oscillation measured for largest demod freq, recommend at least 10: decrease sampling rate, take more samples or increase demodulation freq\n" ] } ], @@ -504,7 +459,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 16, "metadata": { "collapsed": false }, @@ -515,23 +470,23 @@ "text": [ "DataSet:\n", " mode = DataMode.LOCAL\n", - " location = 'data/2017-03-03/#008_{name}_16-45-33'\n", + " location = 'data/2017-03-07/#032_{name}_12-36-13'\n", " | | | \n", " Setpoint | time_set | time | (3200,)\n", " Measured | my_controller_raw_output | raw_output | (3200,)\n", " Measured | my_controller_demod_freq_0_mag | demod_freq_0_mag | (3200,)\n", " Measured | my_controller_demod_freq_0_phase | demod_freq_0_phase | (3200,)\n", - "acquired at 2017-03-03 16:45:34\n" + "acquired at 2017-03-07 12:36:14\n" ] }, { "data": { - "image/png": "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\nnx8n1iblGhHpglXHvnKRTUkixhj907/Q/rBGOh9gTUP/0/67EUuxTcGatp6HtVHMYK2fg7UBbR6W\nArodqMHaULYRa3R7FdZa+teBbtgGREa8r2IZFpsz/l7MeL4j1rr8FqyNcmflyL2I5t3eqb9BGc/H\nYi2jiIc8EKwNhevsv9+l/GGNQt+x82c9Vqf6rSLhDbLzbivWuv/XM579D9ZreluwpuUfB3axn30T\neN4hvAew9g0IloHWxsFNu4z8XwlcnvN8BDDDlul9YETGs/ZYr6Mut/2/D5xQQh16ALjZIQ/S9cW+\nNwX4gf37CKwZhc1YG2Ovx5rKT7k1wO4Z128A52Vc3wj8NeP6BLts1tvpeBLYIUemqcAFJaRrikMd\nOyrj+elYxtRG2+0wj+Fm5Q3Qy5Y9VcemAccV8N8Ly1Bdb8c9C7gw4/kZGXm7GstA3y9s3aJ/wf2l\nlJOiVA0i8l3gO8aY70YtS5wRkbuA2caYu6KWpRRE5GYsQ+QUY8z2qOVxQkS6YZ1h8QNjTN6GWkVJ\nErr0oFQj64FboxYiAXwIPB21EGXwV6AD8KWI5L5pEDki8jOsEfZr2NPzipJkdEZBUZRYICIDsUbh\nTgw1xridnZAI7L0Af3F4tNgYU86ZHYoSCmooKIqiKIriii49KIqiKIriihoKiqIoiqK4ooaCoiiK\noiiuqKGgKIqiKIoraigoiqIoiuKKGgqKoiiKoriihoKiKIqiKK6ooaAoiqIoiitqKCiKoiiK4ooa\nCoqiKIqiuKKGgqIoiqIorqihoCiKoiiKK2ooKIqiKIriihoKiqIoiqK4ooaCoiiKoiiuqKGgKIqi\nKIoraigoiqIoiuKKGgqKoiiKoriihoKiKIqiKK6ooaAoiqIoiitqKCiKoiiK4krrqAWIAz179jSD\nBg2KWgxFURRFCY0ZM2asMcb0KuZODQVg0KBBTJ8+PWoxFEVRFCU0RGSxF3e69KAoiqIoiitqKCiK\noiiK4ooaCoqiKIqiuKKGgqIoiqIorqihoCiKoiiKK2ooKIqiKIriihoKiqIoiqK4ooaCoiiKoiiu\nqKGgKIqiKIoraigoiaG+oYm3PluTdW/dlnpmLd0QkUTJZ86KjazcWBe1GEqVUre9kXcWro1aDKVC\n1FBQEsPN4z/lrPveYfayZsPgW3e9ycl/fiNCqZLNCX+aykG/mRy1GEqV8stnZvO9e6fx+ZotUYui\n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\n", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAgoAAAFhCAYAAAARGoJRAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzsnXe8HGW5+L/PaTklPTkJkBASIJTQMVKkC4SEIiqIgF4Q\nrxcb14YiV5Bq4adiASmConLVy1WxoBcBpQcSIAES0oAQ0ns7vZ/398fM7pndM7M7uzszO7vn+X4+\n53N2Zt7yvP15n/edd8QYg6IoiqIoihsVxRZAURRFUZT4ooqCoiiKoiieqKKgKIqiKIonqigoiqIo\niuKJKgqKoiiKoniiioKiKIqiKJ6ooqAoiqIoiieqKChFRUR+JSLfKrYcSukgIoeIyGsi0iwixxdb\nnnRE5BoR2SUij4tIfbHlUZRCUUVBKQlE5BkR+VQe/h4XkVkicrmILLQHl/Ui8j0RqXK4GysifxaR\nNhFZIyKXOp7ViMgfRWS1iBgROTUtjn+ISKvjr1tE3sggk4jI/xORHfbf/xMRcTx/WkS22bIuEpHz\ns6Rxqu2nXURWiMgZjmffSJOtQ0T6RWR8Wvq2i8jwtHB/b+fdMBHZnPZsmIg8YMu4WUS+4ng2XkRe\nsNPWJCLzROQEx/OMZeGDTwKrgNHGmHk5+IsEY8z3gMnAQcAsv/5E5D4RedMun0+kPcspz0TkYjus\nZhHZKiK/FpGRLm6W23X+HRE5KUN4V4nIAhHpEpFfpT2bYT/bZf/9S0Rm+E23En9UUVDKFhFpAGYC\nzwL1wJeA8cCxwOnAVx3O7wK6gYnAx4B7ROQQx/O5wMeBlAETwBgzxxgzPPEHvAj8IYNoVwIfBI4A\nDgfOAz7teP4lYLIxZqTt9jcismeG8P4HeA0YB1wH/FFEGm3ZvpMm2/8DnjHGbHf4Pxl43RjTmhbu\ne4AFtoxL0p7dBEwH9gFOA64Rkdn2s1bgU1h5OdqO82+OgS1bWWRjLLDcGNOfg59IMca0Ae9ilYlf\nFgGfA151eZZrnr0InGLXoX2BKiBpuRORM7HK5QpgBFYdWJUhvI22/wc8nn3Ulm088AjwUIawlBJD\nFQUlUkTkKBF5VURaROR/gVr7/hgR+bs9k95l/55sP/s2cBLwU3tW/FP7/k9EZJ09a1roMiM6HXjB\nGNNljLnHGPO8MabbGLMB+C1wgh1OA3AB8E1jTKsxZi7wV+DfAGw/P7bv92VJ31Rb1gczOLscuN0Y\ns96W5QfAJxIPjTGLjDFdiUugGtjbI74DgKOBG40xHcaYh4HFdnrS3QpwGfDrtEdnA4+muR0DiDFm\nJ5aylT54XQ7caozZZYxZDtyXSIMxptMYs9wY0wsIVp6NwRrgyVQWPqkCUpQE26pi7Jn3WttCcp3j\n+TG2ZWO3iGwSkZ+KSI3juRGRz4nI23bdvFVE9hORF+369fs09+eKyOt2eC+KyOEucvbbsvrCGHOX\nMeZJoNPlWU55ZoxZa4xxKrV9wP6O65uBW4wx840x/caYDXa4XuH9yRjzF2CHy7Pdxph3jDF9DJT3\n/unulNJFFQUlMuyO9i/Af2MNGn9gYECrAH6JNUOdAnQAPwUwxlwHPA9cZc+Mr7L9vAIcaYf1O+AP\nIlLriPJs4P88xDkZWGr/PgDoNca85Xi+CDhkkK/sXAY8b4xZncHNIXb4nnHZilIn8BLwDNbM3ius\nVcaYlkzh2ZwETAAeTrufzCcROV1EdgPrgMn2758An7cHxVNsJWJPH2lYjDXoPQL83Biz1SMNzrLI\niIiMxVJc1no4ORE4EEtJvEFEDrbv9wFfxprxHm8//1ya37OwrCjHAddgKT8fx1LSDgUusWU4Cmtm\n/Wksi8HPgEdEZFhaeOuAU50KRoBkzTMROVFEmoAWrHb2Y/t+JVYeNorISnsp46ciUleIQHZd6QTu\nBL5TSFhKvFBFQYmS47Bmxz82xvQYY/6INdhjjNlhjHnYGNNuD3rfBk7JFJgx5je2v15jzO3AMKxB\nIsGgmTKAiHwSq6P8gX1rONCc5qwZyySbK5cBv8riZjjQlBbXcHvGD4Ax5lw7/rOBJzKY2dPDSoTn\nJvvlwB+dSwwish9QZYx50473SWPMaCyF7iPAJGA1MN4YM9oY86wdJy5pSInTGHM4MBK4FGvpZhAu\nZeGJiPwn1oy2icFWkQQ325aVRVjKyxG2LAvt2XOvrcT9jMH163vGmGZjzFKspZYnjDGrjDFNwD+A\no2x3VwI/M8a8ZIzpM8b8GujCqt9ObsFalmkTkZnZ0ucXv3lmjJlrjBmFtV/i+1jlCNaSUDVwIZby\neCRW2q4vRC673owCrsJaClPKBFUUlCjZC9hgUj9ZugZAROpF5GdibSRsBp4DRtuzH1dE5Kv2Zqwm\nezYzCmvGiIgcBjQZY9al+fkg8F1gjmOdvhVrQHMyCmsm5hsRORHYA/ij455zM+G9HvGNAlrT8gVb\nmfoHMEtEPmCHt9QR3kl+ZRdr9/1HcF92+IfD3Xo7Ly+x3W7FsvJsEpEfOuTHJQ2D8stehvgf4FoR\nOSJNJrey8MQYcyeWJWMPwGuDp9Pc3o6t1IjIAbaVZrNdv76DXVccbHH87nC5TihI+wBX2xaW3XZ+\n7Y1Vv518EUsRHmmM8bII5YRbnonIxxx14h/pfuwlhccY2DfQYf+/0xizyQ7nh1h1IX1z7sdykc/e\nm3Ev8KCITMgnjUr8UEVBiZJNwCTnzBlrmQHgaixrwLH2BqyT7fsJtymDqD1IXgNcBIyxZzNNDvdu\n6+6zgfuB84wxzrcS3gKqRGS6494R+DSHO7gc+JNzxp62mfAz9u2ldvh+46oC9rPDO8QR3vO2v31F\nxDmbdwvvQ8BOrGUMJyn5ZIyZDMwG/mXn6X3A521rwldsN7uwyjKXNFRjbaoDMpZFRux193lArrvq\n7wFWANPt+vUNBupKrqwDvm3nSeKv3laInBwMPGaM6XAJI2e88swY81tHnZjj4d1Zh3YB60ltU8nf\nJnVz7m/zELUCa/PlpDz8KjFEFQUlSuYBvcAXRKRaRD4MHGM/G4E109ltr0PfmOZ3C46BxnbfC2zD\nGuRvIHWGm7I/QUTej7UB7AJjzMvOgO1Z0J+AW0SkwbYMfABrL0XC/zDH/ocaEal1Kjz2+u5FZF92\nAGuj41dEZJKITMJSkn5lh3OQiMwRkTo7jz6OpTQ96xaQva/ideBGW6YPA4cxeB/C5cCDTquFbWU4\nBng6ze17GNi8eDTu+yMeBK4XaxPqwcB/ONJwnL0+XmOn4+tY5u6X7OeeZeGTLiDXdf8RWMsjrSJy\nEPDZPOJNcD/wGRE5ViwaROScNGUNLOWoy8W/K3Z+1WIpMNV2eVbYz3LKM9vKMMX+vQ/WUt6TDie/\nBP5TRCbYe06+DPw9Q3hVtmyVQKUtW5X97EyxNilXivUK5g+BXcByv2lXYo4xRv/0L7I/rLXV17DM\n1P9r/30Ly2z7DJZZ+y2sjWIGa/0crA1ob2F1QHdgdVgPYHX+m7CsC6uBM7BeyduW8Gv7fxpLsWh1\n/P3D8Xws1rp8G9ZGuUvT5F5ty+P8m+p4fgnWMor4yAMBvoc1w99p/xb72cFYA2oLsBvLdP2hLOFN\ntfOuA3gTOCPt+SQ77fun3T8X+LtLeA9gLVMIloJW7eJmmCP/twBfcTw7BWt/QIudvmeBk/2WhY/8\newD4jkseJOuLfe8Z4FP275OxLAqtWBtjbwHmOtwaZ/5g7an4hOP6W1gbMhPXs+2y2W3Xvz8AI9Jk\neh74ZA7pesaljp2aT55hKQbr7fq8HssyNM7xvBq425Z/M1abqs0Q3k0ust1kP/uII2+3YSnohxez\nn9G/YP8SnZOilA0ichFwoTHmomLLEmdE5G5giTHm7mLLkgsi8h2szXcfMMb0FFseN0RkNLAMS1EZ\ntKFWUUoJXXpQypHdwI+KLUQJ8Drw52ILkQc/B+qAjSKS/qZB0RGRr2LNsJ8l1dyvKCWJWhQURYkF\n9pr6Mo/HM4wxXmcnlAT2GwQ/c3m0xhiTz5kdihIJqigoiqIoiuKJLj0oiqIoiuKJKgqKoiiKonii\nioKiKIqiKJ6ooqAoiqIoiieqKCiKoiiK4okqCoqiKIqieKKKgqIoiqIonqiioCiKoiiKJ6ooKIqi\nKIriiSoKiqIoiqJ4ooqCoiiKoiieqKKgKIqiKIonqigoiqIoiuKJKgqKoiiKoniiioKiKIqiKJ6o\noqAoiqIoiieqKCiKoiiK4okqCoqiKIqieKKKgqIoiqIonqiioCiKoiiKJ6ooKIqiKIriSVWxBYgD\n48ePN1OnTi22GIqiKIoSGQsXLtxujGnM5k4VBWDq1KksWLCg2GIoiqIoSmSIyBo/7nTpQVEURVEU\nT1RRUBRFURTFE1UUFEVRFEXxRBUFRVEURVE8UUVBURRFURRPVFFQFEVRFMUTVRQURVEURfFEFQVF\nURRFUTxRRUFRFEVRFE9UUVAURVEiY+XWFjbs7ii2GL5p7+7lldU7I43ztbW7aOroiTTOTKiioCiK\nokTGGT98jhNue6rYYvjmq39YxEfunceW5s5I4uvrN3zo7he54pcvRxKfH1RRUBRFURQPlm1sBqC9\nuy+S+PqNAWDx+qZI4vNDURUFEZktIm+KyEoRudbluYjIHfbzxSJydA5+rxYRIyLjw06HoiiKopQr\nRVMURKQSuAuYA8wALhGRGWnO5gDT7b8rgXv8+BWRvYFZwNqQk6EoiqIoZU0xLQrHACuNMauMMd3A\nQ8D5aW7OBx40FvOB0SKypw+/PwKuAUzoqVAURVGUgDAxHLWKqShMAtY5rtfb9/y48fQrIucDG4wx\ni4IWWFEURVGiQKTYEgxQVWwBgkRE6oFvYC07ZHN7JdZyBlOmTAlZMkVRFEXxT5wsC8W0KGwA9nZc\n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\nQmCC\n", "text/plain": [ - "" + "" ] }, - "execution_count": 19, + "execution_count": 16, "metadata": {}, "output_type": "execute_result" } @@ -544,129 +499,73 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 17, "metadata": { "collapsed": false }, "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "DataSet:\n", - " mode = DataMode.LOCAL\n", - " location = 'data/2017-03-03/#009_{name}_16-45-34'\n", - " | | | \n", - " Setpoint | time_set | time | (3200,)\n", - " Measured | my_controller_raw_output | raw_output | (3200,)\n", - " Measured | my_controller_demod_freq_0_mag | demod_freq_0_mag | (3200,)\n", - " Measured | my_controller_demod_freq_0_phase | demod_freq_0_phase | (3200,)\n", - "acquired at 2017-03-03 16:45:35\n" - ] - }, { "data": { - "image/png": "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\nYII=\n", + "image/png": "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\n5TeRJ2x5AAAAAElFTkSuQmCC\n", "text/plain": [ - "" + "" ] }, - "execution_count": 20, + "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "myctrl.num_avg(100)\n", - "data3 = qc.Measure(myctrl.acquisition).run()\n", - "plot = qc.MatPlot(data3.my_controller_raw_output)\n", + "plot = qc.MatPlot(data3.my_controller_demod_freq_0_phase)\n", "plot.fig" ] }, { - "cell_type": "code", - "execution_count": 21, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "" - ] - }, - "execution_count": 21, - "metadata": {}, - "output_type": "execute_result" - } - ], + "cell_type": "markdown", + "metadata": {}, "source": [ - "# Do this in as qcodes measurement (ie the same but makes a data set) _demod_freqs\n", - "#data3 = qc.Measure(basic_acq_controller.acquisition).run()\n", - "plot = qc.MatPlot(data3.my_controller_demod_freq_0_mag)\n", - "plot.fig" + "Assuming that you have establised the correct int time and delay we can integrate over samples. To change averaging and integrating setting you currently have to create a new controller" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 2" ] }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 18, "metadata": { "collapsed": false }, - "outputs": [ - { - "data": { - "image/png": "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\nYII=\n", - "text/plain": [ - "" - ] - }, - "execution_count": 22, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "plot = qc.MatPlot(data3.my_controller_demod_freq_0_phase)\n", - "plot.fig" + "# Create the acquisition controller which will take care of the data handling and tell it which \n", + "# alazar instrument to talk to.\n", + "myintctrl = ATS9360Controller(name='my_controller_int', alazar_name='Alazar', integrate_samples=True)" ] }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 19, "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "WARNING:root:oversampling rate is 0.625, recommend > 1: increase sampling rate or decrease demodulation frequency\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "start 0 stop 6.2e-06 num steps 3200\n" - ] - } - ], + "outputs": [], "source": [ - "myctrl.demod_freqs.add_demodulator(400e6)" + "myintctrl.int_delay(2e-7)\n", + "myintctrl.int_time(2e-6)\n", + "myintctrl.num_avg(100)" ] }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 20, "metadata": { - "collapsed": false, - "scrolled": false + "collapsed": false }, "outputs": [ { @@ -675,112 +574,100 @@ "text": [ "DataSet:\n", " mode = DataMode.LOCAL\n", - " location = 'data/2017-03-03/#010_{name}_16-45-37'\n", - " | | | \n", - " Setpoint | time_set | time | (3200,)\n", - " Measured | my_controller_raw_output | raw_output | (3200,)\n", - " Measured | my_controller_demod_freq_0_mag | demod_freq_0_mag | (3200,)\n", - " Measured | my_controller_demod_freq_0_phase | demod_freq_0_phase | (3200,)\n", - " Measured | my_controller_demod_freq_1_mag | demod_freq_1_mag | (3200,)\n", - " Measured | my_controller_demod_freq_1_phase | demod_freq_1_phase | (3200,)\n", - "acquired at 2017-03-03 16:45:38\n" + " location = 'data/2017-03-07/#033_{name}_12-36-23'\n", + " | | | \n", + " Setpoint | single_set | single | (1,)\n", + " Measured | my_controller_int_raw_output | raw_output | (1,)\n", + "acquired at 2017-03-07 12:36:23\n" ] - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "" - ] - }, - "execution_count": 24, - "metadata": {}, - "output_type": "execute_result" } ], "source": [ - "data3 = qc.Measure(myctrl.acquisition).run()\n", - "plot = qc.MatPlot(data3.my_controller_raw_output)\n", - "plot.fig" + "data4 = qc.Measure(myintctrl.acquisition).run()" ] }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 21, "metadata": { "collapsed": false }, "outputs": [ { - "data": { - "image/png": "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\nEtO6Lo9hAAAAAElFTkSuQmCC\n", - "text/plain": [ - "" - ] - }, - "execution_count": 25, - "metadata": {}, - "output_type": "execute_result" + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING:root:2.0 oscillation measured for largest demod freq, recommend at least 10: decrease sampling rate, take more samples or increase demodulation freq\n" + ] } ], "source": [ - "plot = qc.MatPlot(data3.my_controller_demod_freq_0_mag)\n", - "plot.fig" + "myintctrl.demod_freqs.add_demodulator(1e6)" ] }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 22, "metadata": { "collapsed": false }, "outputs": [ { - "data": { - "image/png": "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\nCBtSvRMQCSE7pH8PS/cPReRHsBORE+CXFL6XI/V6j/+Nku5/EZEphzzagBA5S24R/y6PyyFa3T4n\n2mcbolXmPzrojRJttxvAYgAfle79B6KtjTsRmQbuBPA6ce/TAP6ioXcLIn8KQiTMDdfkGSm1/wYA\nFyj3J2ra6x+k+xeIcj2IHHRHFuhDtwD4maYNkv4i8fBVcf0hRJqKHYicfn+MyJwQ52UAx0i/JwM4\nW/r9EwA3Sb9PFu9mm+h/dwM4QOFpEoB/K/Bcrjb7JwBLRZtNBPBWT7qZtgFwuOA97mNTAXzMUv5w\nRELtNlH3PABfU/LsI+6fNJjjSfg3OP/iwSkgYK8EEX0BwOeZ+Qut5qWdQUTXAJjPzNe0mpciIKKf\nIXKaPJWZB1rNjw5EdDCiGCFfZeacs3BAwFBCMH8E7O3YBuDXrWZiCOB5APe3mok6cBOAfQGsJSJ1\nx0XLQUQXItKKPIW8iSAgYMghaCoCAgKGHIjotYhW9zocx8ym2BRDAsJ34XrNrRXMXE9MlICAQUEQ\nKgICAgICAgJKQTB/BAQEBAQEBJSCIFQEBAQEBAQElIIgVAQEBAQEBASUgiBUBAQEBAQEBJSCIFQE\nBAQEBAQElIIgVAQEBAQEBASUgiBUBAQEBAQEBJSCIFQEBAQEBAQElIIgVAQEBAQEBASUgiBUBAQE\nBAQEBJSCIFQEBAQEBAQElIIgVAQEBAQEBASUgiBUBAQEBAQEBJSCIFQEBAQEBAQElIIgVAQEBAQE\nBASUgiBUBAQEBAQEBJSCIFQEBAQEBAQElIIgVAQEBAQEBASUgiBUBAQEBAQEBJSCIFQEBAQEBAQE\nlIIgVAQEBAQEBASUgmGtZmCo4ZWvfCWPGjWq1WwEBAQEBAQMCmbOnLmJmQ/3yRuEioIYNWoUZsyY\n0Wo2AgICAgICBgVEtMI3bzB/BAQEBAQEBJSCIFQEBAQEBAQElIIgVAQEBAQEBASUgiBUBAQEBAQE\nBJSCIFQEBAQEBAQElIIgVAQEBAQEBASUgiBUBAQEBAQEBJSCIFQEBAQEBAQElIIgVAQEBAQEBASU\ngqYKFUR0MhEtJqKlRDRac5+I6Epxfy4RvdtVlogOJaLHiWiJ+HuISP8YEc0konni70ekMu8R6UtF\nfSTSRxLRXSL9OSIa1cz2CAgI2HPAzHj6xS4wc6tZCQhoGzRNqCCiTgBXAzgFwHEAvkhExynZTgFw\n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\nRU5ErkJggg==\n", - "text/plain": [ - "" - ] - }, - "execution_count": 26, - "metadata": {}, - "output_type": "execute_result" + "name": "stdout", + "output_type": "stream", + "text": [ + "DataSet:\n", + " mode = DataMode.LOCAL\n", + " location = 'data/2017-03-07/#034_{name}_12-36-25'\n", + " | | | \n", + " Setpoint | single_set | single | (1,)\n", + " Measured | my_controller_int_raw_output | raw_output | (1,)\n", + " Measured | my_controller_int_demod_freq_0_mag | demod_freq_0_mag | (1,)\n", + " Measured | my_controller_int_demod_freq_0_phase | demod_freq_0_phase | (1,)\n", + "acquired at 2017-03-07 12:36:26\n" + ] } ], "source": [ - "plot = qc.MatPlot(data3.my_controller_demod_freq_1_mag)\n", - "plot.fig" + "data5 = qc.Measure(myintctrl.acquisition).run()" ] }, { - "cell_type": "code", - "execution_count": 27, - "metadata": { - "collapsed": true - }, - "outputs": [], + "cell_type": "markdown", + "metadata": {}, "source": [ - "# Create the acquisition controller which will take care of the data handling and tell it which \n", - "# alazar instrument to talk to.\n", - "myintctrl = ATS9360Controller(name='my_controller_int', alazar_name='Alazar', integrate_samples=True)" + "We can also chose to not average over records. You currently have to either integrate over samples or average over records (the returned data must be 1D)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 3" ] }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 23, "metadata": { - "collapsed": true + "collapsed": false }, "outputs": [], "source": [ - "myintctrl.int_delay(2e-7)\n", - "myintctrl.int_time(2e-6)\n", - "myintctrl.num_avg(100)" + "myrecctrl = ATS9360Controller(name='my_controller_rec', alazar_name='Alazar', \n", + " integrate_samples=True, average_records=False)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When not averaging over records averaging is implemented by averaging over buffers and records_per_buffer can be set independently " ] }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 24, "metadata": { "collapsed": false }, @@ -791,40 +678,57 @@ "text": [ "DataSet:\n", " mode = DataMode.LOCAL\n", - " location = 'data/2017-03-03/#011_{name}_16-45-41'\n", + " location = 'data/2017-03-07/#035_{name}_12-36-33'\n", " | | | \n", - " Setpoint | single_set | single | (1,)\n", - " Measured | my_controller_int_raw_output | raw_output | (1,)\n", - "acquired at 2017-03-03 16:45:42\n" + " Setpoint | record_num_set | record_num | (123,)\n", + " Measured | my_controller_rec_raw_output | raw_output | (123,)\n", + "acquired at 2017-03-07 12:36:34\n" ] } ], "source": [ - "data4 = qc.Measure(myintctrl.acquisition).run()" + "myrecctrl.int_delay(2e-7)\n", + "myrecctrl.int_time(2e-6)\n", + "myrecctrl.num_avg(100)\n", + "myrecctrl.records_per_buffer(123)\n", + "data6 = qc.Measure(myrecctrl.acquisition).run()" ] }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 25, "metadata": { "collapsed": false }, "outputs": [ { - "name": "stderr", - "output_type": "stream", - "text": [ - "WARNING:root:2.0 oscillation measured for largest demod freq, recommend at least 10: decrease sampling rate, take more samples or increase demodulation freq\n" - ] + "data": { + "image/png": "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\nQmCC\n", + "text/plain": [ + "" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ - "myintctrl.demod_freqs.add_demodulator(1e6)" + "plot = qc.MatPlot(data6.my_controller_rec_raw_output)\n", + "plot.fig" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As the setpoints along a records axis is expected to be dependent on an external instrument\n", + "which the driver has no way of knowing there is support for setting the base name, unit and start and stop of setpoints (the number of setpoints is automatically set from the number of records)" ] }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 26, "metadata": { "collapsed": false }, @@ -835,53 +739,11 @@ "text": [ "DataSet:\n", " mode = DataMode.LOCAL\n", - " location = 'data/2017-03-03/#012_{name}_16-45-42'\n", - " | | | \n", - " Setpoint | single_set | single | (1,)\n", - " Measured | my_controller_int_raw_output | raw_output | (1,)\n", - " Measured | my_controller_int_demod_freq_0_mag | demod_freq_0_mag | (1,)\n", - " Measured | my_controller_int_demod_freq_0_phase | demod_freq_0_phase | (1,)\n", - "acquired at 2017-03-03 16:45:43\n" - ] - } - ], - "source": [ - "data5 = qc.Measure(myintctrl.acquisition).run()" - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "myrecctrl = ATS9360Controller(name='my_controller_rec', alazar_name='Alazar', \n", - " integrate_samples=True, average_records=False)" - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "ename": "ValueError", - "evalue": "Wrong number of inputs supplied", - "output_type": "error", - "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mValueError\u001b[0m Traceback (most recent call last)", - "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[0mmyrecctrl\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mint_time\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m2e-6\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 3\u001b[0m \u001b[0mmyrecctrl\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnum_avg\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m100\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 4\u001b[1;33m \u001b[0mdata6\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mqc\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mMeasure\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mmyrecctrl\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0macquisition\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mrun\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[1;32mc:\\users\\jhn\\qcodes\\qcodes\\measure.py\u001b[0m in \u001b[0;36mrun\u001b[1;34m(self, use_threads, quiet, data_manager, station, **kwargs)\u001b[0m\n\u001b[0;32m 76\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 77\u001b[0m data_set = self._dummyLoop.get_data_set(data_manager=data_manager,\n\u001b[1;32m---> 78\u001b[1;33m **kwargs)\n\u001b[0m\u001b[0;32m 79\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 80\u001b[0m \u001b[1;31m# set the DataSet to local for now so we don't save it, since\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[1;32mc:\\users\\jhn\\qcodes\\qcodes\\loops.py\u001b[0m in \u001b[0;36mget_data_set\u001b[1;34m(self, data_manager, *args, **kwargs)\u001b[0m\n\u001b[0;32m 732\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 733\u001b[0m data_set = new_data(arrays=self.containers(), mode=data_mode,\n\u001b[1;32m--> 734\u001b[1;33m data_manager=data_manager, *args, **kwargs)\n\u001b[0m\u001b[0;32m 735\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 736\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdata_set\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mdata_set\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[1;32mc:\\users\\jhn\\qcodes\\qcodes\\loops.py\u001b[0m in \u001b[0;36mcontainers\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 521\u001b[0m \u001b[1;31m# note that this supports lists (separate output arrays)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 522\u001b[0m \u001b[1;31m# and arrays (nested in one/each output array) of return values\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 523\u001b[1;33m \u001b[0maction_arrays\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_parameter_arrays\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0maction\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 524\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 525\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[1;32mc:\\users\\jhn\\qcodes\\qcodes\\loops.py\u001b[0m in \u001b[0;36m_parameter_arrays\u001b[1;34m(self, action)\u001b[0m\n\u001b[0;32m 596\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 597\u001b[0m \u001b[0msp_blank\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m(\u001b[0m\u001b[1;32mNone\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m*\u001b[0m \u001b[0mlen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mshape\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 598\u001b[1;33m \u001b[0msp_vi\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_fill_blank\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0msp_vi\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0msp_blank\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 599\u001b[0m \u001b[0msp_ni\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_fill_blank\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0msp_ni\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0msp_blank\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 600\u001b[0m \u001b[0msp_li\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_fill_blank\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0msp_li\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0msp_blank\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[1;32mc:\\users\\jhn\\qcodes\\qcodes\\loops.py\u001b[0m in \u001b[0;36m_fill_blank\u001b[1;34m(self, inputs, blanks)\u001b[0m\n\u001b[0;32m 623\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[0minputs\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 624\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 625\u001b[1;33m \u001b[1;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'Wrong number of inputs supplied'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 626\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 627\u001b[0m def _make_setpoint_array(self, shape, i, prev_setpoints, vals, name,\n", - "\u001b[1;31mValueError\u001b[0m: Wrong number of inputs supplied" + " location = 'data/2017-03-07/#036_{name}_12-36-45'\n", + " | | | \n", + " Setpoint | foo_set | foo | (123,)\n", + " Measured | my_controller_rec_raw_output | raw_output | (123,)\n", + "acquired at 2017-03-07 12:36:46\n" ] } ], @@ -889,29 +751,34 @@ "myrecctrl.int_delay(2e-7)\n", "myrecctrl.int_time(2e-6)\n", "myrecctrl.num_avg(100)\n", - "data6 = qc.Measure(myrecctrl.acquisition).run()" + "myrecctrl.records_per_buffer(123)\n", + "myrecctrl.acquisition.set_base_setpoints(base_name='foo', base_label='bar', base_unit='ket',\n", + " setpoints_start=200, setpoints_stop = 1e6)\n", + "data7 = qc.Measure(myrecctrl.acquisition).run()" ] }, { "cell_type": "code", - "execution_count": 36, + "execution_count": 27, "metadata": { "collapsed": false }, "outputs": [ { "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAg4AAAFhCAYAAAAY8SIrAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzsvXm8I2d15/092qW79+LudrftdkODbbABu2M6YQs7zmYS\nlsGQ4CSTAQZIJgFeXhhmJgnbJLyESRgWYxLABhJCTAIGDMZxMKsNbtvYxm4vTdu973fX1a7n/aOe\np1RVqtKVdHWl27ef7+dzP1cqVZVKpVI95znnd84RpRQWi8VisVgs7RAb9AFYLBaLxWI5fbCGg8Vi\nsVgslraxhoPFYrFYLJa2sYaDxWKxWCyWtrGGg8VisVgslraxhoPFYrFYLJa2sYaDxWKxWCyWtrGG\ng2VFISKfE5H3D/o4LKcPIvIUEblHRGZF5JcHfTxBROSdIjIlIjeLSG7Qx2OxLBVrOFhOS0TkNhH5\noy62u1lEXiIiV4vIXXqwOSgiHxKRhGe9NSLybyKSF5F9IvJaz2spEblBRB4XESUivxp4j2+JyLzn\nrywi97c4JhGRvxaRU/rvr0VEPK9/V0RO6GO9V0SuXOQzbtXbLIjIQyLyIs9r/z1wbAURqYvIusDn\nOykiw4H9flmfu7SIHA28lhaRz+hjPCoib/O8tk5EfqQ/24yI3C4izwpsv01EviEic/q9P9TqMwb4\nQ2AvMK6Uur2D7fqCUupDwBbgAuAl7W4nIteKyMP6+/n9wGstr9+Qfb1G72tWRI6LyHUiMhqyzm59\nzf9CRJ7TxjFuF5GiiHzBs2yr/l14r7P/2e7ntqx8rOFgOWMQkSFgB/A9IAf8KbAOeCbwQuAdntU/\nDpSBDcDrgE+KyFM8r/8Q+F3AN4ACKKWuUEoNmz/gx8C/tDi0NwAvB54GXAL8JvBGz+t/CmxRSo3q\ndb8gIpta7O+fgHuAtcB7gBtEZL0+tg8Gju2vgduUUic92z8X+JlSaj6w38uAXfoYfx547S+A7cB5\nwPOBd4rIy/Rr88Af4ZzLcf2eXzcDnYikgFuA/wA24gyyX6B91gC7lVL1DrbpK0qpPPAYznfSLvcC\nbwbuDnltses3yI+B5+lraBuQAFzPnoi8GOd7+QNgBOca2NvGMX4cuDPitXHPtfa+NvZlOU2whoNl\noIjIM0Tkbj3T/Gcgo5dP6BnoCe3m/YaIbNGvfQB4DvAxPZv5mF7+dyJyQM+q7gqZMb0Q+JFSqqSU\n+qRS6gdKqbJS6hDwReBZej9DwCuA/6mUmldK/RD4GvB7AHqbv9XLa4t8vq36WK9vsdrVwN8opQ7q\nY/kw8PvmRaXUvUqpknkKJIFzIt7vScClwJ8rpQpKqa8A9+nPE1xXgNcD1wVe+jXgpsC6E4AopSZx\njK/gYHY18D6l1JRSajdwrfkMSqmiUmq3UqoKCM45m8AZ8NHrHVZKfUQpldfr3xf2+SJIAD6jwTPr\nvVpE9msvxns8r1+uPR/TInJERD6mDRjzuhKRN4vIo/rafJ+IPEFEfqyvry8H1v8NEfmZ3t+PReSS\nkOOs62NtC6XUx5VStwLFkNcir9+Ife1XSnmN3BrwRM/zvwTeq5S6QylVV0od0vuNREReA0wDt7b7\nmSyrA2s4WAaGvvF+Ffg8ziDyLzQGuBjwWZwZ7LlAAfgYgFLqPcAPgLfq2cxb9TZ3Ak/X+/pH4F9E\nJON5y18DvhlxOM8FHtCPnwRUlVKPeF6/F3hK01aL83rgB0qpx1us8xS9/8j30oZTEfgJcBvOzD9q\nX3uVUnOt9qd5DnAW8JXAcvc8icgLRWQaOABs0Y//DniLHiSfp42KTW18hvtwBsEbgb9XSh3XL+0E\nHhcnxHNSnDDUxRGfz4eIrMExZPZHrPJs4Mk4RuP/EpEL9fIa8Gc4M/Zf1q+/ObDtS3G8LDuBd+IY\nQ7+LY7Q9FbhKH8MzgM/geInWAp8CbhSRdGB/B4Bf9RocPcR7/YYiIs8WkRlgDud39rd6eRznHK4X\nkT069PExEcm22Nco8F7gbVHrAPv0vj4rnlCY5fTHGg6WQbITZ/b8t0qpilLqBrTbUyl1Sin1FaXU\ngh4EPwA8r9XOlFJf0NtVlVJ/A6RxBg1D00waQET+EOfG+WG9aBiYDaw2i+PC7ZTXA59bZJ1hYCbw\nXsPaIwCAUuo39Pv/GvCdFm754L7M/sKO/WrgBm9IQkSeACSUUg/r971VKTWOY+C9CtgMPA6sU0qN\nK6W+p9+TkM/ge0+l1CXAKPBanFCPYQvwGuCjwNk4RsvXFhtgReSPgVP6fYNeE8Nfas/LvTjGzNP0\nsdylZ9dVbdR9iubr60NKqVml1AM4oZnvKKX2KqVmgG8Bz9DrvQH4lFLqJ0qpmlLqOqCEc317eS9O\nGCcvIjtafbZOCLl+Q1FK/VApNYZzvv8/nO8RnBBSEngljjH5dJzP9j9a7O59wD8opQ6GvHYS+CUc\no/8ynOvgi21+HMtpgDUcLIPkbOCQ8rdo3QcgIjkR+ZQ4wsRZ4PvAuJ4dhSIi79Dirhk9Mx7DmVGi\nZ7AzSqkDgW1eDvxv4ApPnH8eZ4DzMoYzU2sbEXk2Tsz+Bs8yrzjxmoj3GwPmA+cFbVx9C3iJiPyW\n3t8Dnv09p91jF0fd/yrCwxTf8qx3UJ/Lq/S6x3EGhCMi8hHP8RPyGZrOlw5D/BPwLhF5ml5cAH6o\nlPqWUqqMMwCuBS4Mbh/Y1//F8XRsBKIEo173/ALayBGRJ2kvzlF9fX0Qfa14OOZ5XAh5bgym84C3\naw/MtD5f5+Bc317+G45hPKqUivIYdUTY9Ssir/NcE98KbqNDEN8GvuT5LAD/Vyl1RO/nIzjXQlDs\n+zoReTrwIuD/hB2TDu/t0kbZMeCtONdsN4a3ZQViDQfLIDkCbPbOrHHCEgBvx/EWPFMLup6rl5t1\nfYOqHjTfCbwamNCz5BnP+mFx+5cBnwZ+UynlzXp4BEiIyHbPsqexiCs4hKuBf/XO6APixDfpxQ/o\n/bf7XgngCXp/T/Hs7wd6u22Bm3TY/n4bmMQJe3jxnSel1BbgZcC/63N6LfAW7W14m15nCue77OQz\nJHFEeuBoMFSLdSPRcfvbgYs63PSTwEPAdn19/Xca10qnHAA+oM+J+ctpA8nLhcC3lVKFkH10TNT1\nq5T6oueauCJic+81NAUcxP8duI+VX+z7ReBXga3AfnGya94BvEJEwkSc3n3Z8WaVYL9IyyC5HagC\nfyIiSRH5HeBy/doIzkxoWsex/zyw7TEaA49ZvwqcwBn0/xf+GbBP3yAiL8Bxn75CKfVT746Vo4D/\nV+C9IjKkPQe/haPFMNunPfqJlIhkvAaQjg+/msXDFOAIJ98mIptFZDOO0fQ5vZ8LROQKEcnqc/S7\nOEbU98J2pHUZPwP+XB/T7wAX06xjuBq43uvV0F6Iy4HvBta9jIYY8lLC9RXXA/9DHFHrhcB/8XyG\nnTq+ntKf4//FcY//RG/7BWCniLxIe5T+FMfdvTvqhAUoAZ3qBkZwwinzInIB8F873N7Lp4E3icgz\nxWFIRH49ZIad1MfaFvp8ZXAMmqT+PmP6tcjrN2JfrxORc/Xj83BCf15R42eBPxaRs8TRrPwZ8I2I\n3V2LY3Q8Xf9dg/Pbeqne/zNF5MkiEhORtTghqNt0iMeyGlBK2T/7N7A/nNjsPThu7X/Wf+/HcfPe\nhuMGfwRHeKZw4u/gCNoeAaZwbkxxHIHaLM7s9504MdwX4aQAnjDb6u2/i2NozHv+vuV5fQ1OXD+P\nI7x7beC4H9fH4/3b6nn9Kpywi7RxDgT4EI4HYFI/Fv3ahTgD7ByOgv1O4LcX2d9Wfe4KwMPAiwKv\nb9af/YmB5b8BfCNkf5/BCWsIjsGWDFkn7Tn/x4C3eV57Ho6+YE5/vu8Bzw1s/zvAHr39bcBTOriG\nPgN8MOQcuNeLXnYb8Ef68XNxPA7zOELb9+KES8y6ynt+cDQZv+95/n4cgad5/jL93Uzr6+9fgJHA\nMf0A+MMOPtdtIdfYr7Zz/Ybs6wM4XoW8/n8tsNbzehL4hD7+ozi/qUybx/kXwBcC1/5j+r2O4BiV\nG/t1T7F/y/9nbk4Wy6pFRF4NvFIp9epBH8tKRkQ+AfxcKfWJQR9LJ4jIB3HEfL+llKoM+njCEJFx\n4EEcw6VJoGuxnE7YUIXlTGCaCCGXxcfPgH8b9EF0wd8DWeCwiAQzGQaOiLwDx7vxPWzNA8sqwHoc\nLBbLikTH5B+MePkipVRU7YbTAhF5HU4aaJB9SqluaoZYLH3BGg4Wi8VisVjaxoYqLBaLxWKxtI01\nHCwWi8VisbSNNRwsFovFYrG0jTUcLBaLxWKxtI01HCwWi8VisbSNNRwsFovFYrG0jTUcLBaLxWKx\ntI01HCwWi8VisbSNNRwsFovFYrG0jTUcLBaLxWKxtI01HCwWi8VisbSNNRwsFovFYrG0jTUcLBaL\nxWKxtI01HCwWi8VisbSNNRwsFovFYrG0jTUcLBaLxWKxtI01HCwWi8VisbSNNRwsFovFYrG0jTUc\nLBaLxWKxtI01HCwWi8VisbSNNRwsFovFYrG0TWLQB7BSWbdundq6deugD8NisVgslr5w1113nVRK\nrV9sPWs4RLB161Z27do16MOwWCwWi6UviMi+dtZb1lCFiLxMRB4WkT0i8q6Q10VEPqpfv09ELl1s\nWxFZIyK3iMij+v+EXp4UketE5H4R2S0i7/Zs820RuVdEHhCRa0Qkvpyf22KxWCyW1cqyGQ56cP44\ncAVwEXCViFwUWO0KYLv+ewPwyTa2fRdwq1JqO3Crfg7wKiCtlLoYuAx4o4hs1a+9Win1NOCpwHq9\nrsVisVgslg5ZTo/D5cAepdRepVQZ+BJwZWCdK4HrlcMdwLiIbFpk2yuB6/Tj64CX68cKGBKRBJAF\nysAsgFJqVq+TAFJ6XYvFYrFYLB2ynIbDZuCA5/lBvayddVptu0EpdUQ/Pgps0I9vAPLAEWA/8GGl\n1KTZgYjcDBwH5vS6FovFYrFYOuS0TsdUSika3oPLgRpwNnA+8HYR2eZZ96XAJiANvCBsfyLyBhHZ\nJSK7Tpw4sazHbrFYLBbL6chyGg6HgHM8z7foZe2s02rbYzqcgf5/XC9/LfBtpVRFKXUc+BGww/tm\nSqki8DWaQybm9WuVUjuUUjvWr180I8VisVgsljOO5TQc7gS2i8j5IpICXgPcGFjnRuD1OrtiJzCj\nwxCttr0RuFo/vhrHEAAnPPECABEZAnYCD4nIsMfQSAC/DjzU+49rsVgsFsvqZ9nqOCilqiLyVuBm\nIA58Rin1gIi8Sb9+DXAT8GvAHmAB+INW2+pd/xXwZRH5z8A+4NV6+ceBz4rIA4AAn1VK3SciG4Ab\nRSSNYyh9F7hmuT63xWKxWCyrGXFkApYgO3bsULYAlMVisVjOFETkLqXUjsXWO63FkRaLxWLpHcVK\njdt/cWrQh2FZ4VjDwWKxWCwA3HT/Ea769B0cny0O+lAsKxhrOFgsFosFgJlCxfffYgnDGg4Wi8Vi\nAaBYqQOQL9cGfCSWlYw1HCwWi8UCOBoHgIVydcBHYlnJWMPBYrFYLIDHcChZj4MlGms4WCwWiwXw\nGA4VazhYorGGg8VisViAhsZhoWRDFZZorOFgsVgsFgCKVaNxsB4HSzTWcLBYLBYLAAVtMBRsqMLS\nAms4WCwWiwWAYlWnY9pQhaUF1nCwWFYwn7/9ca6//fEBH4XlTKGRjjk4j0O5Wucd/3Iv+07lB3YM\nK5GpfJn/9qV7mC0OvjiXNRwslhXK0Zki7/vGbr5y18FBH4rlDGEl1HHYdyrPDXcd5Id7Tg7sGFYi\nd++f4ms/O8yDh2cHfSjWcLBYViqfuG0P5Vqdci28g22trrDdbS29ZCV4HKZ1ueuCFWj6mNfho0qt\nPuAjsYaDxbIiOTJT4Es/PQBAudp8Ay1Walz6vlu4+YGj/T40yyrGTccc4KA9s1AZ+DGsRPK6KJc1\nHCwWSyifvO0X1JXi8q1rKIfcKGYLFWYKFR45Nj+Ao7OsVgorIFRhPA7WcPBjBKvl6uC9jIlBH4DF\nYvFjvA2v2rGFeh32TTaLxEpa/T69MHihlGX1sCJCFQtlAAq2X4aPvD4fYROJfmM9DhbLCsN4G97y\n/CeSSsQoV5tvFObmMV0o9/vwLKuY0koIVViPQyjG41AJuR/0G2s4WCwriGKlxpd+eoBXXraFLRO5\naMNBL5stWI+DpTfU6so1SAdZctp40Wy/DD/zVuNgsVjCODFXolyrc+m5EwCkEjEqIVkVZRuqsPSY\nomegHuSgPWOzKkLJ26wKi8UShjEEJoZSAKTiMcq1elPaZSNUYQ0HS28whsNQKr4i0jEHKdBcibji\nyIj07H5iDQeLZQUxqYVhE7kk4HgcoFkQZT0Oll5jyk1PDKUoV+tUBzSzndG/Aatx8GPEkdbjYLFY\nfBhF+Xiu4XEAmnQO5vlMoWyLQFl6ggkNrNXerkGFK2w6ZjimjkOY5qnfLKvhICIvE5GHRWSPiLwr\n5HURkY/q1+8TkUsX21ZE1ojILSLyqP4/oZcnReQ6EblfRHaLyLv18pyIfFNEHhKRB0Tkr5bzM1ss\nS2Ey7xgOa0yoIhFuOJh0zEpN2U6Glp5gQhXm2lsoDchwWDizNQ4f+OaD/PuDx5qWnxEaBxGJAx8H\nrgAuAq4SkYsCq10BbNd/bwA+2ca27wJuVUptB27VzwFeBaSVUhcDlwFvFJGt+rUPK6UuAJ4BPEtE\nrujtp7VYesPUQgURGMv6QxVBgaQ3dGHDFZZeUKoawyENDEZjUK8rt4nTmahxUEpx3Y/38Z0HmyvC\nzpfOjDoOlwN7lFJ7lVJl4EvAlYF1rgSuVw53AOMismmRba8ErtOPrwNerh8rYEhEEkAWKAOzSqkF\npdR3AfS+7ga2LMPntViWzPRCmbFsknhMgMVDFc421nDoBts62o8pN71myDFaBxEqmCtWUQqScTkj\nQxWzhSrlWp3ZQvO12ajjMPjQ5HIaDpuBA57nB/WydtZpte0GpdQR/fgosEE/vgHIA0eA/Thehknv\nm4nIOPCbOJ6KJkTkDSKyS0R2nThxYtEPaLH0msl8mQmtbwCvONJ/E/UZDrYIVMfsOT7HJX/5HR46\nOvhOgysFExpoeBz6P3Cba3njWIZStU6tPvhBsp+cmC8BMFfyTwbqdUW+bOs49ATlqMLMlXU5UAPO\nBs4H3i4i28y62hPxT8BHlVJ7I/Z3rVJqh1Jqx/r165f34C2WEKYXKm5GBUBSexxKTR6Hxk19xnoc\nOubxkwvU6opDU4VBH8qKoVj1iyPzAwgVGO/ZprEswBmn3zmpDYegx8F7Hla74XAIOMfzfIte1s46\nrbY9psMZ6P/H9fLXAt9WSlWUUseBHwE7PPu4FnhUKfW3XX8ii2WZCXoc0hHiSG+cc8bWcugYc86M\ne97SOBemhsggxIkmo2LTWAY483QOruFQ9P+mvWG11a5xuBPYLiLni0gKeA1wY2CdG4HX6+yKncCM\nDkO02vZG4Gr9+Grga/rxfuAFACIyBOwEHtLP3w+MAX/a+49psfSO6YWym4oJ0VkV/lDF6jQcanXl\nCsJ6jbkxF8+wGW0rCoGsikFoQGYKAY/DGaZzODmnQxVF/7n3/g5WdTqmUqoKvBW4GdgNfFkp9YCI\nvElE3qRXuwnYC+wBPg28udW2epu/Al4sIo8CL9LPwcnCGBaRB3AMj88qpe4TkS3Ae3CyM+4WkZ+J\nyB8t1+e2WJbC5ELZFadBi6wKffNIxmXViiM/9+PHecGHb1uWOhVuWWNrOLiUKv5QxSDOjSn+dPa4\n8TicWd/PyXnn888WKr7rPl9aWaGKZW2rrZS6Ccc48C67xvNYAW9pd1u9/BTwwpDl8zgpmcHlBwHp\n9Ngtln5TrNQoVup+j0M8XBxZqtVJJWKMZpLMrFJx5MGpBY7PlZhaqLiz4F5hYsjW49DAreMwrOs4\nDCJUEdA4nHmGg+NxqNad+iy5lDNEez0OYb1r+s1pLY60WFYTUwv+4k/QEEeGhSrS8RjjueSq9TiY\nmPuRmd4LGBsahzNrYGpFsVInHhOGUwlEBtMhc7pQIZeKM5pxBswzLlQx35gEeMMVJmyUiMmK8DhY\nw8FiWSGYqpHerAoTqmjOqnA8DuPZ1Ws4GNf50Zliz/fd0DgM/ia8UihUamQSMWIxIZscTKOr6YUK\n49kkQ2nHcDhTxZHghCsMJsNlPJdc3RoHi8XSGcYAGG8nq8IYDrnkqs2qMOmBR5bDcLAahyaKlRrZ\nVByAXCrh1g3oJzOFCmO5lHscZ9r3c3K+5GpMvJkVRuMwkUtZj4PFYmkQ7FMBLbpjao3DWDa1eg0H\n7Q1YDo+DDVU0U6zUSSeM4RCnMIDZ/kyhzHg2SU4bDmeSxkEpxcn5EuevGwJgNiRUMZFLrfp0TIvF\n0gGNzpieUIXWOFTCPA7xGGPZpLtdL7nz8UnuPzjT8/12ghnUl8PjYOLHNlTRoFipkUk611suFR+I\nx2F6ocJ4LkkuaUIVZ47hkC874uht67Xh4JkQGHHkWC656ktOWyynNdML5b66Bad0qCK85HR0qCJf\nrvU87vn+b+7mI7c83NN9dooxHI7OWnFkP/CHKuIDKwA1lk02QhVnkMbB1HA4f90w0CyOzKXipBMx\nG6qwWFYq9briBX/zPT73o8f79p6T+TIj6YSbSQEtsipqDcMBel89slSpDTy+3Miq6K3HoVqruzM4\nazg0KFZrZBJejUN/B22llNY4JEklYiRiZ1ajKyOMbIQqvOJIJzUzFY/ZUIXFslKZL1eZzJd56Ohc\n395zeqHMuKf4EzgFniBCHKlDFdB7w6FcqzdlcvQbI448OlPsaREo70xu0MbRSqJQrpFJDs7jUKzU\nKVfrjGcdj1s2NZjMjkFhDIctE1mScfH1q8iXqgyn4yTj1uNgsaxYTOOo5aghEMXkQoU1OX+hIxEh\nlYhRihBHmgyMXheBqtTqA0/7KmmPw0K5xlwPawp4Z3LW49CgWKn7NA79HrRNZ0zjRRtUuGRQnNA1\nHNaPpBnNJJnzZVVUGUonSCbEFoCyWFYq067h0HthXvR7+vtUGNLxWJMgqlytk9Z1HJxte+txqFTV\n4D0OlZpbCKiXmRVmJhcTKCyTOHIyX6ZUPb0GvWLV43FIJ/peQ8FNR84awyHBwhlk2BmNw5qhFKPZ\npC+rYl4bDql4fOAGPVjDwWIJxcx+Dk8XlqVXQhiT+XJoaeVUItZUctqII8eWyXCo1gfvcShWam68\nt5cGnAnrrB9Ju0Wmes0Vf/d9PvW9vcuy7+WiVKk3DIcBFIAy17C5prPJ+ECqVw6KU/kSE7kkyXiM\nkUyiqQDUsPY4WI2DxbJCMTexUrXu1lfox3t6UzENyXgsXBwZb4gje90hs1xdAYZDtc5WbTgc7WHI\nyIQqzhrJLEuoYqFc5dhsiUePz/d838tJwZuOmU6wUK5Rr/fPLW4MujFPqOKM0jjMlVk3nAYICVXU\ntMfB0Tj0azIThTUcLJYQvGLDfoQrylVH6T8REqpIJUIMB+1xGMkkEWl0FewVlZoaqKu9UqtTqyvO\nXZMD2v8OqrU6n/nhYy0NAvPdbhhNdyyO/Pq9h3n0WGvB7Ckdqz42278wVy8oVmpkPeJIaAhU+8GM\nq3HwiCPPpFDFfKlhOGQTTQWghlKOOFIpp+X8ILGGg8USgtdwODy9/AJJU8RpIjJUEW44xGOiO2T2\nWOMwYHGkGfhHMgnWDafb1jjcc2Ca937jQX7w6MnIdYwL+KzRTMcFoN79r/fznq/+vOU6Rh1/OhkO\nSildAMoxGIa04eBt57zcNGscBlO9clCcnC+xbsQxHEbSSX+owogjTUG4AQskreFgsYTgrcbYD49D\no/hTc6giFRaqqNZJxZ2b+3gu2dNQhVKKal0NNJZqBvRsMs6msUzb34HJhplqEV6aKVSIx4S1QykK\nlVrbbt96XZEvV/npY5M8dHQ2cj3jceh1GulyUq7VqStcwyGb6n93yulChWRcXG9HLpU4s0IV82W3\nT8VoNuGmDTvXXU0bDjo9e8A6B2s4WCwhTC9U2DCaJhkXDvchJdPtUxEVqgjMMEo6HRPoeYdMM5up\n1FRTjLtQrvHqa25n95HogRMcw+sVn/wxjyzi1o/CeBzSyTgbxzJtz96NfmGyRehmtuhUJzSDZLvZ\nI8VqDWMHfP72fZHrGY9DqVr35eKvZIyhZpqqmcG7n0Wgphec70XEGRyzZ1A6ZrFSY75UZb3xOGSS\nFCo1KrW6G64ZTscjm971G2s4WCwhTBcqTORSbBrLcmR6+T0OjT4VURqHxg1UKeWGKgBGs36Pw7HZ\nIp/54WNdC9u8BWaCM5tD0wV++vgkt//iVMt9fP/Rk9y1b4qfH+qu34XRV2Q69DgY9+5UC8NhplBl\nNJNw4/ntCiSN2z6bjPNv9xzy1YPwcsrj7Th6moQrTHaJt+Q09LdXxKwuN20YRGbHoDihUzHXDWuP\ng05DnitW3QZX/lCFNRwslhXHjL6JOYPW8nscTKgiNB0zEKowHgEz+xjPpXziyM/9+HHe+40H2bVv\nqqtj8d6UgrNxM6Av5gG4Y69jWHTbRMpsl0nE2DiWYaZQaauugBGUTeejPTCzhQqjHo9D8BgL5Zrr\nNfBi3v8//dI5LJRr/OtdB0P37932dDEcGue7ESYA+lrLYbrgr2OSS8UpVPqb2TEozDXTEEc6BtRs\noeKWRx9KWcPBYlnRzOjUyLPHsxzug8dhKqQzpiEojjSPTefM8axfHGkG7X+751BXx1L2GQ7+GZ8x\nJBYbEM0xdJuZYbwAmWScjaMZ5z3b8DoYj0N7oYqY770MH/2PR3nVNbc3bWc8Dju3reFp54zz+Tv2\nhWoYTs2X3e/mdBFIFjznGwbjcZheqLjCSGjoLPqZ2TEoTmpdjDEcRjLacChWWNDXnVM50hoOFsuK\nZbpQZjybYtNYhqOzxWVPf5rKl8km4+6N20vQ42AeuxqHnGM41OuKfKnKfQdniMeEb953uKuB26vY\nDsZSTRnoVgPi8dkie0/kgR54HLTGAdo0HHT4oFWr8ZlChdFM0g1VBFMyj0wXQjNpzOw7l0rw+p3n\n8YsTeX6BDYe1AAAgAElEQVQcErI5lS/xpI1Oh8Njfaw8uhSKbqjCr3HoqzhyoeLWcPAew5kQrjhl\nPA4jpo5DI1ThehzScVJu7xqbVWGxrDhMMaZN41lqdeXGIJeLyYXwqpHgGAhhg7kxHMaySeoK5kpV\ndu2bolZX/MGvbGW2WOW2h090fCyVanSoouiGKqLPxx2PTXq2X6rHIcamsSzQXnaLESO2Kto1W6gG\nQhX+Y5wv1ShV61QDs7p82cz84vz6JZuYyCW5/vbHm/Z/ar7MprEsE7nkaRSq0OdbhyqG0s7A1U9x\n5ExQ4zAA42VQmFBFI6uiEaowGodhq3GwWFYuxYozcIxmk5ytZ7vLnVkRVTUSmgtAuYZDvKFxACe8\ncsfeUyRiwp+8aDvrhlN8tYtwRbXe/F4G43FolWp4x95Tuj24dO9xqIaEKtoYhBseh3CNg1JKaxwS\nruEQ9DiYG3WwhoEpf5xLOdtecfGmUI/Dyfky64ZTbBhtPxtk0BQ8WSzQEEn2a9Cu6FbnpjMmeHUW\nZ4LhUGYk3bgmR7THYbZYcY23oXTCnSys6nRMEXmZiDwsIntE5F0hr4uIfFS/fp+IXLrYtiKyRkRu\nEZFH9f8JvTwpIteJyP0isltE3u3Z5gMickBETq8asJaBYPQC47lkY7a7zDqHqD4V4JSc9s78Td+K\npMfjAE545Y69p3jaOeOMZpL8xiVnc+tDxzsuDuV1gzYZDnpAL1Rqvsp2Xu7Ye4rLz19DJhFfgseh\nIdbLpuKM55JtiVRdw0GHboKUqnXKtbpP41CqBD0LzueaD8y2zQA2pAe089bkmCtWfdkV9bpiMl9i\n7VBap5Eur6eqVzRCQzpUkexvAahZz2/O0AhVnB4prUvhhKf4EzQ8Dr5QhVccuVrTMUUkDnwcuAK4\nCLhKRC4KrHYFsF3/vQH4ZBvbvgu4VSm1HbhVPwd4FZBWSl0MXAa8UUS26te+Dlze449oWaU0Ktil\nOHvcme0ud2ZFVGdMcLInvOmYpSaPg3OTOTxd5L6DM+zctgaA337GZsrVOt/++ZGOjqV1VkXj+fGQ\n2fQxrW/YuW0t6WRsCRqHRqgCYONohqMziw/CJlRRqyu3gI4XY0SNZpKNWXWExyHYYMnVOKSd7TZP\nOEalVw8xXahQV7B2OMWGkcxpE6owBp7RfSTiMVKJGAuV/gza0yGGw3J5Pd7zb/fzDz98rKf7XCon\n50puKibAcCqBiD9UMZSOu4bDavY4XA7sUUrtVUqVgS8BVwbWuRK4XjncAYyLyKZFtr0SuE4/vg54\nuX6sgCERSQBZoAzMAiil7lBKdXb3tJyxTHsyHMaySXKp+LJnVkwtVEKrRkJIVkXVX6zHKNFv3X2M\nWl2xc9taAC7ZMsa2dUMdZ1dUQt7L4DUcwgZFk02xc9ta0kvyOPhd5xvHMhydXdx4mylUXDdvWC0H\nM7MdzSbdeH5Q42Bm2fMBwyEf8DicPd5sOJzypNVtGMtwcr408Hh0OxQDWRWgm0z1yeMQ7Ixp3h96\nH6r41s+P8tPHWtch6TfePhUAsZgwnHb6VZjrcSiVcCcLq7nk9GbggOf5Qb2snXVabbvBYwQcBTbo\nxzcAeeAIsB/4sFJqEoulQ8zsx1SxW+5aDtVanRldcCqMxbIqjBL9lt3HSMaFy86bAEBEuPLpm/nJ\nY5Md9dvwp34G0jE9g2xYlsMdeycZSSe46OxR0slY21UZg5jtjMdh01hm0ayKel0xV6xw3lqnMVZY\nSqYJK4y1qOPQSuMg0jimLdpwODTVOLcmrW7tcIqNoxmUIrQmxErDzOq9hsNQH0s+mwZXoYZDDxtd\nFSs1JvPlgQ+8QRxdTNq3bDSTdDQOpSq5VJxYTEgmnKyKQRujp7U4UjnqLHMFXA7UgLOB84G3i8i2\nTvYnIm8QkV0isuvEic7V6JbVwUxg9uPUclg+w8G4z1t5HOqejnhuHYegxmGhwtO2jLuiMoBfv2QT\nSsH3H2n/evbeVIPxf68hECb8+4nWN8Rj4mgcurzpFys1RBrhmI2jWU7Ol1t6MPLlKnUF5611WnGH\npWQ2QhWJ0HRMpVRD4xDiccgl425J5HXDaVLxGAe9Hoe8x+Mw6gwE7TboGiTFaqM3iCGbivdNX9DQ\nFTWM50a/jN4dg7lmB12y2Uu56kwcgobDSCbBbKFKvlx1s1zOhKyKQ8A5nudb9LJ21mm17TEdzkD/\nP66Xvxb4tlKqopQ6DvwI2NHJASulrlVK7VBK7Vi/fn0nm1pWETOBeOumsQyHl/HmP9WiMyY0DARz\nswtmVaQTcXd2ZsIUhk06K6QTgWS1RclpYziMZZNNwr9js0X2nszzy09wjmEpHodipUYm0Rikzec4\n3kJsaMSa5+lW3FMh1SONBmIsmyQdUgCqUKlhNJX5EI1DLt0wymIxYdN4xhfGMg2u1g45WRVwehSB\nckNDicaQMJTqX8lnk+48Hig5Db0NVRgjbtAaAS+usTni//2PZpPMFSvMl2put1Lzm+/2d9UrltNw\nuBPYLiLni0gKeA1wY2CdG4HX6+yKncCMDkO02vZG4Gr9+Grga/rxfuAFACIyBOwEHlqej2ZZzUwX\nysR1jBFg01iWk/OlZZulNDpjRmdVQIjh4LnJG69D0HDIpeKINA+CrfCJI5s8DjXSiZhbGMuLV98A\nTkZEu30gghQrdTckALhFoFrVcjD6ha3a4xCmcZjxaBzSiRgifsPBG54Izrbznhu44eyxLIemFtzn\nJ+dLxMSZOZtjPh0yKwqVGqlEjFhM3GWtPA7HZ4tc+/1f9KT7p1KKr/3sME/aMBwqjuyp4bACPQ4n\n54yxGRaqqLottaHxm1+1HgelVBV4K3AzsBv4slLqARF5k4i8Sa92E7AX2AN8Gnhzq231Nn8FvFhE\nHgVepJ+Dk4UxLCIP4Bgen1VK3QcgIh8SkYNATkQOishfLNfntpz+mNK3ZrZ79rgTq16umaNpAR2p\ncdA3i5LWGwRDFeAYDsm4cOl5475tRYShVIL5DkRu3k6cpaDHoVInnYhxVkiNgp8dmCabjHPhplGg\nBx4Hj9vcdA1sVYjLGA5nj2dJxKS1ODLjfL9B48ZrYAXP2UK55gsDgZNZ4fU4nJx30mrjMWFNLkUy\nLqdFZkWpUieT8A8HrTQO3/r5UT5400Mc70FhtHsOTPPA4Vl+75e3ur85cLwfMeltVoUxPAc98HqJ\nClWOZhJuVkVTqGLAhk9i8VW6Ryl1E45x4F12jeexAt7S7rZ6+SnghSHL53FSMsP29U7gnZ0cu+XM\nZbrgL31rajkcni5wjnaD94pjs0U+cdsviMfEnaEGSQc8DsF0TIBz1+RYN5xuGtjASePqyOMQIsQ0\nlKo1XZQpzcNH/a21Hz46x5M3jhDXs9aleBwKAcPBGFXThVY9KBphiPFcksmQUMVMoUI2GXeNrqxu\npGTw6hrCQhVD6YDHYTzLsbmi26301HzJnTnGYsJZI5nToux0sVJzZ/iGVm2tzTkLeqS64fO372M4\nneC3n+HXzosIuVSip9Urj65Aw8Gcy+D5N6GKfDnJWSPOvSEZN+LIwYo7l9VwsFhOR2YCzXZM2l27\nrZ3bZdfjk/zXL95NvlTlY1c9w51VB4nSOHjj0R/5T0+PdBsPpRNNxYxaUWnV5KpSJ52MsXE0w4m5\nEtVanUQ8hlKK3UdmeelTNrrrLs3jUPd9PuPCjqoICd5UywQTuVSoONI0uDJkEv5aE36PQ7M40ntd\ngJNZYbxR56zJcSpfZq0nH3/DaJpjcyvfcAgaauB4HKIGbWMQBrNuOuXkfIlv3neEqy4/xw0Nemll\nvHSDyY5aSaEKt09I4PyPZhLMlarMFaucv87vcRi0RuO0zqqwWJaDYM18UwSql2Wnb7r/CFd9+g6G\nUnG++pZnccXFmyLXbcQ1dVZFiMZhOJ1wO+oFGUolOvM41FtVjqyTTsQ5azRDXTXSD0/MlZhaqHDB\nxhF33XQi1vWM1Hg2DJlknEwy1lLkaVItRzNJJnKp0H4VTp+KxgCVSQZCFeUWHodSuMcB4KBOyTwV\nyMffMLp4GulKwIhRvWRbiCONsdVtgS/DP995gHKtzu/98nmhr+d6LNBseBxWTjpmsDOpYSSTRClH\nEDyc9osjB+0xsYaD5Yxj36l8y4F0uuCv4phLJRjLJnuakvmPP9nP2eNZvvbWZ/OkDSMt120SR4Zo\nHFoxlO6skM9ioYp0ItbUP2L30TkALtD6BtCD8hIKQHnFkeBU8pxapHkVOGlsE0PJUO+E6YzpO8YQ\ncWRMmkV5C+Ua2WSzxgEaRaBOzQc9DqdH2elipU4m4CofSjuDdpgnq+Fx6H4Aq9UV//iT/fzKE9by\nxLPCfwPZZI8Nh9mVl1VRjAxV6HTUSkNbE4sJiZhYw8Fi6Te/9bEf8ekf7I18fXrB73EAJx2wl/0q\nZosVtq4danqfMBqNbfTNOkTj0IrhdKLJ7d4Kc1MSCS85nU7EPBkDzjl56Iijd+iVx8HJqvDfSMdz\nSbc4VxizxQpDqTiJeIyJXCpcHBkMVSTDQxXrhtMhoYpmj4NJEz00XaBYqTFXqvo8DhvHMsyXqh2d\n/0HgeBz811MulaBWV6GDrAlhLcXl/x8PHefQdIHXR3gbnGOIU+hR2etKre6KOVdSqMKEYoKhCq8H\nccgTxkkGCsINAms4WM4oTLGVKO9BtVZnrlht6lR59ni2p7Uc5opVt5HNYgRzt8vVOjFx+gm0w1C6\nM4GZMRyGU4nQ7phOqMIZHI3h8PDROTaOZnyeGuNx6CZlL8x1Pp5LusW5wnC6Xib1uo7hEHzvGc86\nEC2O3DCaCQlVNGdVZJJx1g2nOTRVcEMja4f8GgdY+bUcglks0BjIwrxVxthaSj2Bf77zABtHM7zo\nwg2R6+R6WL3yxFwJpRxDetAzdi9RoQqvZ2zYY7Am4zLwUIs1HCxnFGYwmIoYgIwyPyiCWzOUYiZk\nBtstc8VGT4XFaBJH1upthylAGw4dzHhNOmYuHQ8PVSRjrBtKk4iJGzPefXSOCzb53c3pRAyluosn\nF6sRoYoW38FssRGGWDOUpFJTbn8Jd51CUBwZHqpYP+L3OFRqTlfNYB0HgM3jGQ7PFBrFnwIaB8DN\nrDg+W+R/f2t31z08lotg3QzA9a6ElXx2QxVLMByOzRa56OzRlgZwL8WRRtx8zprcijMcUomYm41k\n8GpxvB6HYO+aQWANh1XM4emC23TH4mAGg6iZqxHfjTXlVCcj20h3w2yx2rbhkA4RR7YbpgCnAmCn\noYpkXMgkm5tUmWwHJ9UwzbFZp4nTnuNzXLBx1Leu2wuii0Gyq1CFR/hoPB9eTUS9rpgrVRn1nPdM\nwOOQL1dJJ2KMZvxeGjPrzYUo/zdPZDk0VeCkrgDo1TgYLYjJrHjPV3/Op763lwcOzzbtZ5AUq7Um\nV7kp+RzsEgoNw2EpBlCxUvNlzoTRS3GkMXLPW5OjUlOhbdcHQbHcfO7BH6oYDoQqBl3HwRoOq5g3\nf/Fu3v/N3YM+jBWFuQlFzVzdzpjZYPlXRydQ7YGlX6zUKFfrPldkK4Ieh1K1TirRfKOJYiidoFip\nt33s1VqdZDzmNNdqKjldI63fe8NYxm2jXakpLgzxOEB3uf5hrvPxXIqZhUpk6MPncTCGg+d7nitV\nUQpfqMLpp+HXOAynE9pL01xFMszjcPZYlkPTBU7q+Pm6oWaPw9GZEjc/cJRbHjzmHEsPjdBeUCiH\npWNGV240oYqleByMXqYVvQxVmFTMc3UTtEp9ZXgdwrw9gM/A9YbIkvHYwD0m1nBYxZyYK3GqhQr9\nTGR+kVDFdAuPg3f7pWAGjdE2PQ6N3O2Ge3ixG64XM1tpt8tgpaYcwyFE3FiqNm5yG0acstMPHTXC\nSL/HwbTE7qYIlKkX4WU8l6Rcq0cOJLPFhn5hYsj57/2evS21DdlUrKly5FA6wXAgvGOMiCiPQ6la\n59Hj84Df4zCUTjCSTvCLE/P8+dcecPUP8yvMcAjVOGjDIUwfU+yBONJrhEaRS8V71uTq6EyRbDLO\nOv39BENop+ZLPOdD/8HPD8305P3apVBZ3OPgFeWmEjGrcbAsH/OlateV+1YrZuY4HSKcg0YII6hx\nMIONSflbCnO63kBU3YUgvdA4QPv9Kso6VJEOiaWaOg7gZAwcmymy+8gcybiwbf2Qb13X49Dh4GKU\n/E3iSNMFNCJcMVtohCHCQhUznnLThkwiKI6sMaQ9DqVqw0vT0uOgazncd9ApuT0UMC42jGX4yt0H\nOTZX5H0vfyrQuAZWCsVqs6E25HanXB5xZCnkPYPkUnEWKt0JbIMcnS2ycSzjhvmCRs/BqQIHJgvc\ndP+RJb9XJ4QV3wLnd2+M9GCoYjU3ubIMEKUUeWs4NGEGz2pdhXoP3FBFoG+EGZBme3DDNx6HtsWR\nTU2uap1pHDo0HCrVesPj0JRV0YhLbxjNMFeqcvf+KZ6wftj1jBiMgdFpHNysHxaqgPB22fW6Ys7j\ncQgLVZjvzp+O6YgjzcDkhCrinnNW8/0P5toDbNaGw88Pzfq8DYaNo06vk9/beR7P3r4OWFmhinpd\nUa7Wm2a9uRahilIPxJGlyuKes2wqjlK96QZ5dKbIxtEMyYhGUeY9TLO2fhFW7ttgjFyfODJu6zhY\nlolStU61rqzhEMAbtw4rEDTtzkr9g3rD47B0w2G2S4+DNx2zE4+DSeVqt9FVxWgcEvHwOg4mVKFT\nDe/eN+U2tvKScdtWd3aTM+s3ZVXo8FGYsDVfrlJXjRvtaDaJiN/j4C1Jbcim4tRVoyBQvlwll0q4\nngVTqrvhcQgJVWjDYb5U9WVUGJ541jCbxjK846VPZjiVQMTRW6wUihGGmgnLhHXIXGoBKKVUe6GK\nHrbWPjJTZNNYpqmgmsE8v+/gTEdZSEulECGOhMZ9p0kcaQ0Hy3JgfmhLLQm72vDGa6PaLo+kE00p\nYmZA6qXHwTuAtSKYVVGpqY4MByOsatvjUFeNUIXn5lqtOcaoG6rQwr9qXfkKPzWOuzuPQ1TtfmM4\nhOlTZgPnNB4TxrPJgMah0QSrcYx+42beI46ExjkzaZ3BAlDmuMzsfN1Qs8fhPb9+Ibe87XmMZpLE\nYsJwKrGiQhWuoRYsAKXPfz6sjoMR6nY5ManWFXVFW+JICDdeOqFeVxzToQrznkGjx2iIqnXFXfum\nlvR+nRClcYCGVzLn8UhYw8GybJgbnvU4+PGGJ0JLEi9UmoSR0BiQBqFxaCo53WE65vASQhVlz6Bv\nbrRuqMLTzfPJIYaD8Rh0mlVRjCiI06pDpvEmeI2CYPXImVBxpF/AuVCqMZSON50zk5IY1n1URFyd\nQ1ioIhmP+WaMw5lEz8SRByYXeO/XH1zSQBJV8tg8L7So4xBsu94uxpO1mMbBPYYlehxO5ktU68rn\ncQieM6+R3M9wRaFSayr3bXBDFd6sikTMrbUyKKzhsEoxA2TYj/5MxlsFL8zjMF2oNFWNBE+oYgAa\nh3hMiMfEnRGVuhVHtjlrM6GKdECEZWamXo2DISxU0b3HITxUYYyCMINvNkT4OJ5LNmkcYuJUxDQY\nAaYZCE1WRVDjYDx4YaEKaIQrwkIVQUYyiZ5oHJRS/D833MtnfvQYjx6b73o/UZUL04kYMWketJVq\nhEC71TgYT0U7WRWw9FCFqeGwcSzbMByq/sHXXOtrhlJ9NRxKlWYhsGEkkyCXihPzFIdK2ToOluXC\nzJS67RWwWlnM4zC9UG6q4QC4semeaBwKFSQwgC1GylOfvlONw1DHGgcdqkj6QxXGADBplsM6bXEi\nl+SskJbgXWscAu/T2J/TITO8XbYJVTQMhzVDKabyje9r/+QCa4bSvptww+NQdwTFZROqMOfMr3GI\nErG5HoeQUEWQTnuHRPGVuw9xx95JYGlZGsWIQVxEQptMVWpOmAG6Fy26Hoc2xJGwdMPBVI3cNJZp\n6v0SPKZnP3FdX3UOhUqNbCr8PGxbN8S5a3K+ZamE2MqRluXB3JjKtTq1FVIhbSWwUK66edxRHoew\nUEUsJoykEz2pHjlbdAanWKDEbCtSiZg/q6KLOg6dpWM6BaC8A0MpxBOwaSzDhZtGEWn+LGbg71bj\nEDYLm8ilOvA4NEIVlVqd7z50nOc+aZ1vO/NZCpUahUqNusKt4wB+jUNKh2/C2KK7ZK5ry+OQXLLG\nYTJf5gPffNB9v6V4MKI8POBUjwx6Lb2VQLv2OLQZqjChoaU2ujK9QjaMZkjGnWu1HPA4mM/y3Cet\np1pX7OqTzqGVOPJPXridr77lWb5lVuNwhvDX336Iv/nOw319T6+FbnUODfKlGqPZJCOZROQAFNWx\ncjSb7InHYa5YbbtqpMFbn75cq5PuQOOQTcYR6UDjoEMh6WQ84HEws8TGTe6vX3kJf/6bTwndT1B4\n2C5hBophLBtedtqEkLyC0zVDDcPhp49NMlus8pKLNvq284YqjLE9lIo3BKXlhsYhFyKMNJw97oRt\n2jEchnsQqvjAN3czV6zy/pc7536u1P11WYoQo0J4ASbv/aR7j0N/QxVHZook48LaoZSrD4rSOPzK\nE9aSiEnPwxXX3/44P31s0rdMKdVSHJmIx5pCSCuh5HT7vlJL19yzf4p+Vzf1ukKLlVpTUZozFeOK\nrtZUk8dBKcX0QqWp+JPB6VfRC8Oh/QZXBidU0ehVEayZ0AoRYSjVvnu8aipHBkpON272jfe+9NyJ\nyP1klupxCLmZjueS4aEKLVr1ihDHc0mKlTqFco3vPHCUTDLG85603n+MHgGg0b/4PQ5a+1CuuVkG\nYTzrCet40YUbuHjz2KKfbzSTWFI65o9/cZKv3H2Qtzz/CVx6nnP+wwyRozNFStUa560danrNS5TG\nAQgNVXjDn+Uue1WUKm2GKnqUjnl0psiG0QyxmDQVVDOYa308l+Rp54z33HD4yC2P8MILNnD5+Wvc\nZcbwihJHhpGMW3HkGUE2Ge+7SNE7uywO2DpdSeRLVXKpOBO5ZFNaX75co1pXoeJIcGazvciqmO3G\ncPB6HDrUOICjcwhrjxyGaXKVSsSo1ZVbPTHM49CKbntVRNUVgBahimKF4UAarcnCmFwo850Hj/Gc\n7eubNArG41DyehzSCTJJRxiY92gcwspNG84azfD3V+8IDXMFWWqo4prv7WXzeJY/fsF213MVZji8\n9xsP8Kf//LNF99cIVYQYDqnme5fX47DkUEW7Hocl6g2OzBTYpLOAFsuqSMVj7Ny2pqc6B6UU88Vq\n0/6M8DTK4xCGLQB1hpALiRMuN/mAx2ElcHBqgR3vv4W9J7pXgC+V+VKN4XRCN0zyz1yjGlwZeudx\n6CJUEW+kRnZnOCTcYkaLUa7VScRjTfnu7ixxkbi0IRl3WgV32h2zVcw9qkPmbKHSVLTLGA4/fPQE\nR2aKvOSiDU3beVMOzW9mOJ1wvDQeEWO+VAstN90Nw7rpWPDm/39ueYQ/um5Xy20rtTp3PjbJiy/a\nQCYZJ52IkYxLqOFwfLYU2QXWS1TdDDChiuYOqYYlhyra1Di022cliqMzRTaOOTqUVEQdh1K1Rkyc\n8MDObWup9VDnYAryBTObCi3OfRROrwprOKx6Msne9ZRvF6+Cvt/vHcVjJ/OcnC/z8NG5gR3Dgq4M\nOB7icTAz2ahZ42g26dYCWApzHbTUNvjEkR2mYwJNTZtaUanVfULARlfO5lDFYqRDGmUtRitx5Fg2\nvEOmt8GVYUJ/j1+68wAxgRde2Gw4eDM/zE3dhPW856xQroXWcOgG890Hazn87MA0P3mstXv8voMz\nFCo1dm5z3N0iEunBmC1W2po0NEIVIeLIkFBFT8SRbYYqMskYEpIS2glKKbdqJDSXcDeUPX1YLjtv\ngkRMuP0XvQlXGMOuyeMQUUOjFcl4rOvz3iuW1XAQkZeJyMMiskdE3hXyuojIR/Xr94nIpYttKyJr\nROQWEXlU/5/Qy5Micp2I3C8iu0Xk3Z5tLtPL9+j3a1/O3gOyqdhAPQ6dxpiXCxMvjmpS1J9jcPL0\ng8WBILyIkJfRTK/EkZW2iz8ZTKiiXldO5cgONA7g1B9ovwCUckMV0JhVNuo4tH+TyyTjS/A4hIUq\nwjtkOg2u/Od0jU6NvGf/NL+0dY373IuZ6TniSGefpkT3UDrhGhP5cjW0amQ3GP1E0EswvVBmrlht\nWSXRxN0vP3+tuyyqLsRModKWR8BNx4wIVQSND/N8JJ3oOi2w3VBFVEpoJ0wvOOfBVDpthCqasyrM\nNZ9LJXjiWcPsOd4b76jXc+UlKhW2Fcl4zKm8OcBsuWUzHEQkDnwcuAK4CLhKRC4KrHYFsF3/vQH4\nZBvbvgu4VSm1HbhVPwd4FZBWSl0MXAa8UUS26tc+CfwXz3u9rJefdTGyA/A4eF1iK6XstLkhhqVB\n9gvjch7PJZkrVt34PcBJ3dcgbIABR+OQL9d823SKUorZbjwO8RiVqnJv1N1oHNqt41Ct6wJQ+mY2\nKI9D2PsY/UnQ+HQ8DonAuo3v8SVP8WdTGIxx4ogj/dUhh1KNc7bQU4+D1iUEMiEm9e/i2Gwpcts7\n9p7igo0jvmvUMRzCwjftNblzBXohHodcKsTjoL/P0Wyy6zoxnVxLYcfQCUfc4k/a4+B60vz7DHry\n1o+kOTEf/V10gvEuBQXKUVU7W2GOsdJvxb2H5fQ4XA7sUUrtVUqVgS8BVwbWuRK4XjncAYyLyKZF\ntr0SuE4/vg54uX6sgCERSQBZoAzM6v2NKqXuUI5/83rPNn3BiCN70Rq2Xbyzy5USqjD1/tuJuy4H\ntbqT+mQ8DuAfgA5MLgCNnPwgrYRo7VKo1KjVVZNbfTGSiRilWr2p7HO7DKUTbdf7N1kbQY9Du7n3\nXhyPQ+fiyFQiFlrnYiwb3iFztlhp8jh4Ra5h+gbwp4x6xZHm/0Kp4WLulcfBaDGaPA66WJWpchik\nXK2z6/Epdm5b61s+kk427atcrVOo1No694WyE9sP82I5s/3wwW40m1y6x6GNaykbkhLaCYemC0Cj\numtNZzwAACAASURBVKep4xD0OJQCpdzXj6Q5MRv+XXSKMRKbNA5l5zx0onGIOv5+spyGw2bggOf5\nQb2snXVabbtBKWUaph8FzB3hBiAPHAH2Ax9WSk3q7Q4uchzLikm16WcP9Xypxoi+AXbqKl4uzE04\nTBXfl/cvN8Rv7szVMwAdmFxg3XA6cmbZi7LTnZabNpjKka7yuwvDIRiq2HN8jg/etLvJoDVNtMxN\n1MwOSy20B1E4HocO22pX6k0NlwwTufCy07OFapMxlozHGMkkuGjTKOcEqu8ZRIRMMkaxUnPdyEYE\n6RVH9tLjMByicShX626K5rGIwer+Q9M+fYMhLFRhrtFaXS0qpCtWamSS8dAiXtlUosljaQyHsWyi\n6yZX7ZacBsglE0vyOBw2hsOEMRyixJH+Nt9njWQ4MV/qyYRvfjGNQ0eGgymZvTo9DsuO9iCYb/Vy\noAacDZwPvF1EtnWyPxF5g4jsEpFdJ06c6Nlxmvzvfs7850tV1ukywEsJVfxoz8meVZ40HodBhSrM\nwJBLxxseB88AtH9ygXPWhHsboDFTXEpKZqcNrgxp3XDKmzLWCWFljm+6/yjXfn9vk0i0UquTiIk7\nGywvweOQTsQ6NpjNQBbGeMj3Vq8r5orNWRUAv/8rW/njFzyx5ftlkk4cP1+ukknG3JTOYa1xMKWo\ncz3KqggLVXgbd0UZDqa8tFffYPYXDFV4tTiLhSuK1ejznUvFKdfqvvCc8WKMZnrgcWjDAF4zlOJU\nvvt7xqHpAulEzC0H3kocmfIZDmkqNdWTiY757VVqyve+DXFk+78pN1QxwMyK5TQcDgHneJ5v0cva\nWafVtsd0+AH9/7he/lrg20qpilLqOPAjYIfebssixwGAUupapdQOpdSO9evXh63SFW699T4KJPOl\nqhsH7TYd89Fjc7zu73/CDx7tjRFl3I2DEkfmQzwO3kHzwNRCU114L73wOMxooyNskGuFEUd27XHQ\nM0fvAHBizonfeq+Pel1RrSu3yRU0hyo6MVrSyWZx3WK0NhyMxqExkOTLVeqK0PDP21/yZK64eFPL\n9zMaJNNS2zCUjpMv1XQfi/DOmN1g3sPrcfD21DgaaTg06xsg3OPgzf5ZzHArVuqRM163AJO3WqTr\ncUgue68KcEKHB6cWunofcAyHzeNZ16MSiwmJWHMthHLA47BeT7yOzy1d5+A12n2p8uXomiVRJAO/\ny0HQ1h1ARCZE5Ckisk1E2r1r3AlsF5HzRSQFvAa4MbDOjcDrdXbFTmBGhyFabXsjcLV+fDXwNf14\nP/ACfbxDwE7gIb2/WRHZqbMpXu/Zpi9kBuBxWCjXXAu7W8PBDJC96OQHg9c45D3iN+Nx8PYyODxd\nbG046JniUjIruvU4uKGKJYgjofEdQLjhYARXTsnp5nTMREx8RZYWozuPQz1UqAfhHTLdBlcdnlOD\n0WEslKo+48BU22ykafbK46A9V17DYaG1xyFK3wCOETpfrvpU9t59L/b7L1RqkV4ktwlYSAn70SUZ\nDjXibV5LWyZyHJstLZod9sbP7+Ivv/5A0/JDUwW3CZkhrN9DmMcB4Pjc0nUO3nuo14joqo5DRAGr\nfhJpQovIGPAW4CogBZwAMsAGEbkD+IRS6rtR2yulqiLyVuBmIA58Rin1gIi8Sb9+DXAT8GvAHmAB\n+INW2+pd/xXwZRH5z8A+4NV6+ceBz4rIA4AAn1VK3adfezPwORzR5Lf0X9/wpnz1i/lS1W3x2+37\nGsV0r3KGjcZhUKGKhvgt3qRxODJdpFZXnDMRbTiY+g690Dh043Hwujk7Tsf0NG0yg69RjHtDWVUt\nuErGhVQ8kFVRqXcsyswk466B0i6tXOeZZJxsMu7TprgNrrLdeQRMqEIpfKXZh9IJytW6u/9eeRzC\nija5xcdyydCsiih9AziaCaUcz4sxSGd8oYrWv99SpRapWwnrFVGs1ImJowUpV52uol59xA13HUQp\nxat2nNO0v8Z7tn8tGbHy4eki56+LLp+9+8gcByYLTcsPTxd4/pPP8i3z1kUxlGt+g/Usnb7Z6fUb\nhtfL4M94666OAwxWHNnql3ADTgbCc5RS094XROQy4PdEZJtS6h+idqCUugnHOPAuu8bzWOEYJ21t\nq5efAl4YsnweJyUzbF+7gKdGHedy461O1w+UUuRLVSZySWLSvcYh6KJeKma2O12oNN1s+sGCm6fv\n9CJIxMQNVRzQrtAoER30SuNgxJEdZlVoj0Op21CFHhC9CvmTxnDwzOTMLCYqqyIs178V6ZAb9GIU\nytEDGZh+FY2BcSakM2YnGHFktabcGg7QOGdm4OhV5UhTtGneo3GY1KGKCzaOhA5+UfoG8Ggmig3D\noRONw96TebZFDMhhhkNBh5LMteCIaRu/5S/+ZB+n5sutDYdq54bDwamFlobDfKnKibmS795SqtY4\nPlcK9TgE+z2Uq3WfQd+PUIVbfKujOg4mq2IFehyUUi9u8dpdwF3LckSrkGyfQxWmvKlTc7/7Phlm\nwOi2kU0QM2iVq3UnrtqjG3G7GEs/l3JKCo/nUu5Mb79OxTx3bbThMJRKEJOleRzCuji2g5khdatx\nMAOit5ZDWKii7DEcGiWna+563XgcOtY4BG7gQcZzKZ9OpuFx6NJwSDjHWKrWffoBc87MwNGqV0Wn\nBHUJxgt3wcZR7to3Rb2ufOmoUfoGsy/wu8Pb1ThM5svsPZHnlZdtCX3dW+fCYDQo3qwb7/VYKNfY\nP7nAVL7MRERNlFK11nbRoy3amD841WxQeZkvVinX6hybLbk1G0xq6+ZAinVYv4fgMQ2nE+RScY63\nqKvRLl49i7cIVKESnXocRTKiZHY/WfQuICJfF5HXat2ApQuyPWoN2y7emvvZLm7cBhNT7NUF6v3B\neMVt/SLv8TiAk9pnRGn7JxdIxsWtLhdGLObMFJeqcYjHpKOYJjTEkd0UYQLH6IHGtZEvVd3r0VvE\np+INVTSVnO48VNGNxqHUQhwJMJ71d8hcqsbBNHKa11VFDebx8R57HEBnufjEkWWyyTjnrc1RCXRu\nrdUVux6f4pnnN4cpwOtx8Oo+PIZDi9//PfudXgyXRXQ5NeGZQiBUkQnRwDRed9a996DPUe3D8V61\ndy1tGEmTiElLgWSpWnPvU3tPNqo9HtLGhml7bggNVYT0gDmrR0Wg5kpV4to4CIojO70XpE+TdMwP\nA88GHhSRG0TklSISfXe1NNFvjYObdpiK6xlfdxeY2xuhVxqHcuPH41WR9wtXHKlnkk7DpIbHYfN4\n1j2+KEazCZ/wrFNMn4pOwzRmwDaDvdEftIsZBI3L1Bu39Ykjq61CFe3PEg1deRwWMxwCoYqlaxxi\nTq+KUpXhVJjh4Mxae+kha/Y4VJjIJV3D1ZtZse9UnkKlxlMjWnaHeRx8oYoWHsO79k2RiAlPO2c8\n9PVGqMLbbdfvcQhOLIx34r6DM5Hv69TqaO98JuIxNo1nWnocvEbY4ycbBsZBXcNhy7jfk9iOOBKc\ncMXxHhSBmi9WWa81Z0FxZKeGw2nhcVBKfU8p9WZgG/ApHDHi8dZbWbz0W+PgTTtMJ2NdF4Dqucah\nVHNvjAPxOBh1vB4cxj0tmg9OLrTUNxiW2q+imwZX0BBDmhtktxoHYzyd9MyivNdHtR4SqvBcB1HZ\nDlF0nVXR4vM1hSr07Hq4y1CCMW4WSjXXqITGddLQOPQuVDGc9ndanV4oM55LsUG72L2ZFY8cc2bQ\nT9owErovV3vj9TgUvAK86PO/a98UT9k81lKMCv57V6lSI52MNwzLwP6Nd+LeA608DtGZHGFsGc+1\nNhw8g/FjHo/D4ekCIo1y04ZQwyGkedxZI5meiCPnS1X3u/VrHDoP2Ua1Be8n7aZjZoFXAG8CfolG\nyWdLG/Rb45B3swcSTvy2y/fttcehUKm5ZV8HkZKZLzkFfoxXYSKXdF3C+ydb13AwLLW1ttP+uXOX\nuhFEmeqCS03H9HscGt9vuWpCFSEeh0q9Y49DOhGnWlcd9fdolVUBxuNQdiv67Tk+z7rhdEdpol5M\n99p8ubmOAzTOVa5H6ZigUyg9A8jkQpk1QynXsPZmVuw57nSTfeJZw6H7GgkphT5brCxax6VSq3Pv\ngenIMAU0PA5NoYqkp5dJhMfh3oMzkVUXOw17LVbLwfvZHzuZdx8fmipw1ki66feSCjFogyWnQZed\n7pXhoMWW3pToQrn1tR6GuReY3+ogaEfj8GVgN06NhI8BT1BK/fFyH9hqIsxqX068Nfezqc67Exp6\n73GourHGYLXCfjBfqvkGBqdDZoW5YoWphUp7HodsYslZFV15HPRNOt+l4TAc8Dh447a+UIVbJ0I8\n4jdPqKJDj4PxUHRyDTmhihYeh2ySSk2xoIs2/fvuY1zx1PAmVu2QTcaZLlSoB9Ixh5uyKnrocQiE\nKqYXKoznkqwfSSPi71fxyLF5No9nfcfmJUocaeoQRJ37Bw/PUqrW2bF1ccNhIVDHIZMI9zhUanUq\nNcW64TQn50tug6kgpWpnRuhitRzMPW80k2Cvx3A4PNNcwwF007iwktPJZsNhrlRd8qRvrlhl7XCK\nREyaOhdnO/xNrYQ6Du0c8T/gGAtvUkp9Vym1MlotnkakE05P+X5rHIbTCTd+2w2ux6EHF2i15qQS\nbtI/4kGEKhbKfvHbeC5FuVrnkWPOjK4vHocuWmpDw1AwN8hO6zhkk3Fi4jEcIjwO3nRMEfGJyLoV\nR5pt20EppWe00YOKt0HZzT8/SrFS5+XP6L79TCYZc8uqtxJHdhqLbsWI9jiYGflk3vE4JOMx1g6l\nA6GKOZ60IdzbYI4rHhO/OLJQcesQRN13du3Twsjzog2H0KyKak17HPxZN973eqauNxEVrnD0Mp15\nHMCp5RCGCeFdvGWMA5MLrofr0FTB9XJ6SSbEVwdBKadGSjoeDFX0pgjUfMn53Qd7xnTjcVjRJadF\n5NkASqmblVJNV56IjIrIwGojnE6ICLkl9pTvhEaoIk4m0X1LbzerogceB1Oydu1QikwyNrBQhbeI\nj2mYdO8BR8TVluGQHZDGQd8s5rrUOIiIWwkRHI3DuuFmV7YxEhMxZ//peKzR5KrDWSI0Bp52jeZG\ni+fo9xnzFO/66s8Oce6aHJeeGy7ua+sYfSl4/nQ8cAb1XCreUcrcYoxkkm631lpdMVusuH04No41\nDIdqrc7eE3m2R+gbwNSFSER6HKImDnfvm2LzeJYNLTKJ0okYMQkLVcSbQlnQMDAuO3eCZFy4N0Ig\nWaq0n1UB/loOYZjr+uLN41RqikPTBep1xeGZYlMqJjQqsRqMEdGkcehBEahKzUk/N/Vj5gPpmB2L\nI1eAx6HVHewVIvIh4Ns4NRtM5cgnAs8HzgPevuxHuEowKV/9wCsCzCwhVBFsbrQUFtxMjwTj2dRA\nqkfmSzXfwGCqR95/yLm5tSuOzJdrVGv1tmLqQaV2WPvndnDFkfoG2enMH5wYvdfjsH4kw2yxGigA\nZW6gziCZTjZusN3UcUh3GKowbu9W7zOu6zU8cmyOH+05yVuf/8QlFRPzitO84Yh0wtHD1OqqZ1Uj\nDd5+FcW40wtjjb4eN4xkOKxd/PsnFyjX6myP0DcYRjyaCaUUs8Wqx3Bo/v0rpdi1b5JnhhSU8iIi\n5FKJ5lBFhOFQ1G2ix7JJLtw02sLj0GGoYpFaDkb7c8kWJ/Nk78k8WV3ZMtTjEAhVRJVyN5kQ7RaB\nqtcVCnzZWd70+CHPbxB0Ma0uxZHBAlb9JPLXqZT6M+A3cNpUvwp4H/A2YDvwKaXUc5VSd/blKFcB\nmWT3IsVOCYojg6rndullAShvvf9gOl2/cDoc+kMVAPcdnGY0k3BLMbfCpPy107/juw8d55K/vNmd\nPdbrivlSteNy09AYSOe1O7rTUAWY1toNceT6kTSZRMx3fVQ9oQrzPr5QRacah0RnHgdjxLQMVWjR\n3/W376Ou4MolhCkAXzVMb6jCGTRNi+3eFivz9quY1J0fzefaMJZxr5nFMioMw+lGh8x82fFijOeS\noSJAcBo/HZsttdQ3GIJF5BriyOY6DgsV53eRTcW5ZMsY9x+a8fXQMHQaqlisloMbqtApq4+fzLth\njfBQhd/jEFXK/axRbTi0mZJ57Q/28uKPfM+3zNwrhjMJ5zfoTW3too5DVHfPftLym1NKTSqlPq2U\n+n2l1EuVUi9XSr1bKfXDfh3gaiG7hAqOnTJfqpHSqnhTTrcbeplV4fM45JID6ZCZD3Q/NLHyvSfz\nLStGenEbXbWhc/jGfUcoVupukR2nRXPn5aahMZDnS06jqW7c5sOem9bJ+TLrh9NNdRYqQcPBM/CU\nKp3XcejU42COZbECUAD37J/mki1jPOH/b+/Nw+W4qzvv7+nq9d7bd9FdtFuWsbzIgGVL2DIYsxgM\nZiByMjyAB4whZDxss2R5M2Yy2WbeGcj6EN4QjMmQGMZhSQJBJE4MOJglMWAZjPEuWbJ0rfUuurpL\n397P+0f9frV1dXdV9XJvX53P8/TT3dVV1dW/ruXUOd9zznjju/FmZOoYDoDtGWinvgFwChpLjj4V\nKlQxmMbsUhGFcgUHTzfOqHCuT9cXmXeU4E7F/Y//R5S+4eoGGRWavqRhdbYF7P3Az3DQIY1MwsCV\nW4axWCi7CjJZ6wipl2lWy2GxYBZW2zKSQTYVx5HpJUfxp1rDIWXEXNotq7Ca539e15eEEaPARaD+\n9bkZHJ5ecok4tScom4q7woVA1DoOK19yupNttQUHXQ1VFMrWHVIrBks7K0fa4RMDw5mkq/Jft1gq\nVFx3jlrjwBxM3wA4Wms3yaxgZnxXtSN/4sQ8AGefihY0DoVyaH2Dpj9pCrOYGVMLBYxlkzWGQ7Fi\np2MCZjpla+LIkB4H5f1odDLVGgcA2LerNW8DAFcGx4DHs6ANiXoZDVHRxuNiwfY4rFOGw3rrLreA\nZ880zqjQDDo0Drrc9FAmgXTC8M1E+PHRs+hLGrhsQ2NPBmAaDq5QhVUAyhwrP41DOmFYRaW0hsiJ\nqXEId8FsVMthSWVMERG2j/fjyPQSTqjiT34ah5pQRR2PQyxGGBtIBi47/fRJ81jX/ylgGw6mx8Gw\nbqIAZThEreOwWj0OQvvIJKKLFMOy5Cida3f+Cx8PK7TR46B/e18qvnKhioJ/qAIIpm8A/Ivt+PHU\nyQVLUPW40lDYfSpayaooRTcclDBrftms6W96HNxZN3blSLK+t1gxOyBGaXIVNh3T9jjU/42puGGK\nFQl4y5UbQ22PH408Dvp9X5v7qjhTKPWxoDU36wftIlAHm2RU2OuzQxXO3h31sqoeOXYWV10wHEin\n47zpqVQZpQqboQqfktPObo8vGh9Af9KoKT1t7kvh9TKNajks5G1v4vaxfhyeWsLxuWVkU3FfTVEi\nTv6hCp9tmsimA2kcZpeK1nwziz6GQyqujkFbi9Isg8iPeIxAtMo9DkSUCjJNaEw3PQ6LDpd8OhFD\nlaO1YG2nONLpcRhSoYooxkxUmLmmwE8yHrP6DzRqp+3E9jg0Nhy0t+EVF4+2x+PgqByZiFjoaEAJ\ns6YWzXjteFaFKup0xwR0qMLuAxDV49CoX4KTIKEKve3X7xjHRLb16vfphqEKpXHooDhSC4V1wSZd\n5fD43DIOTy011TcA7hLWzt4d6Xitx6FYruKpkwu4amvzMAXgvulx/j92rN1Z0MjcT/qSZoroizcP\n1WRWlKuMKofflxrVcjDTHW3D4cS5ZRyeXvL1NgBmyXbnObFR19mJgEWgnj41b712VmZddBz3znCh\n/s6woQoi8u3u2U2C/HMPBZwmNKCbHodcsWLdIbVSfKqdHgftnsskDYyo+gndMqQA0wVe5drqf9rr\nEDpU0cTj8N1np3DZhixee9l6nFko4MxC3rojbLWOQxRhJGB6e5YKZUwtmBcqUxzp0ThUvaEKdzvv\n8N0xzfnzQT0OVjpm4+/59G278QdvfWmobamH87v6PCdx7aFqZ9VIwN4H5vMlzOaKSBox65jV1SN/\ndGTWzKgIaDjouhDeUIXX47BYKKNSZUv41wxnqMIyHBxNrvxCFfpiuGvrMJ46Me86h9j7UshQhTIC\njvuEK5wNyraP9YMZOPD8rK++AVAeB5+sCr/9ezybCuRxePrkgvXa3+PgruOgrwdhy7gD/gWsukmj\nOg4biGg3gAwRXUVEV6vHqwEEO8sKFt0VR7pDFUDwOz4n7RRHOlNEtbitm+EKZ/8OJ9o9HNhw0KGK\nBhqHXLGMA8+fxQ2XjOOKTYMATJ1DOzwOpQpHSsUEVEfGQtkSeo0PpMxeJj6hiqRHHGmlSYbt5Ofj\ncZhaKOC7z075zq8vTM0uKpdtGGxYfyAM+hhJJ2I1rnu9v3TK47CQL2NuyawaqVNKhzJmNsT3D00D\nQNNUTMCuC5ErVlxNv/zEkfrCFfRON5OMW+uwDTvDV92vRZR6TC8Y7UOxUnXF/PW+EDZDx67l4GM4\neEIVgHkD5ZdRAdjZQtrrqffveh6HmaVC07LpT5+at7ZhZqnW4zCQjqM/aXo6CuVKjZEVhoRBqzar\n4g0wO2NuAfDHAP5IPX4FwH/r/KatLdLJ6O2tw7LkClVocVr4ncxZ+KdVcpbGwbAu1l01HAq24eJk\npC8JIn/ltR/9yThi1Njj8IPDMyhWqrhhxzh2KsPhyRPzLrV7WJwntFbEkYVyFafOmSdeK1Thl1Wh\nlNv6BGtf0KPVcXB6HD730PN4z1/8yNcDFzRU0U70d/k1ydJi2nZ7HIwYoT9pmOJI1adCQ2S2dz86\nY8bzm2VUAG7NhPY4ZNOJmv8XsI/FoILPTCJW63FIGIgbZnEoX49D0j2mzkyCqN6rRrUcFgplDKgx\nuFAZDkD941obPWXlYWvmcWB2Cx79ePrUAq7cOoRUPIZph8dB15joSxjWmOcKlZqxCoNfk65u0qiO\nwz3M/BoA72Hm1zgeP8fMX+niNq4JVk4cqU/cLYQq2pFVUSgjHjP7H+jwQDczK3T9Am8+/vrBNC5Y\n1xf4YhyLEbJNOmR+55kpZBIG9lw4gsF0AttG+/D48XNW7LmVrArv6zDo3350JoeEQQ7VvX/JacD0\nMLQSqvDzOJyez6PK/lUA9Z1fFPdtVPQdn9+FtL9DHgdA96soqc6YbmNShyu2jDTPqACcja5KZlnz\nVBxGjHzFkdr7FlTwaRaAMpfxildTccN1ftAaB2tMk+4eKUD0UMWGwXTdWg6L+TKyapwG0wmMqcJN\n9TQOujW13t/trIrabRpXOppG4YpKlfHs6QVcvmHQ6tPh3LaBVByxGLna29uhimiGw0q21Q5yNLyY\niK7wTmTm/9GB7Vmz9CUN5FR2QytV7oLgFEe20pnTEke2wVOidRdEZHsculjLwS5A5d7l/+vNl4Zu\nWjWYsXPm/fjuwWnsvWiddUK4YtMgHj8+j22j/UgasUgnCpfhEFkcaf7252eWMD6QAhEh7XFla8FV\nPGZ7HArlqp3nHrrkdG0cXMd/j83mauL3QQpAtZu05yLnZEBrHNqcVQGYF/vFQhlnc6WazAmtPwgS\npjDXpTwOBdPjoLU4KZ90zFwhpMchaesk8iU7VAHA1csEMD0Oybjdgdbbzh1w1EwIaYQaMcKm4Yx/\nqMJTo2X7WB+mFwvYPOwfznKGWfqSTbIq1H/RSCB5dGYJ+VIVl27I4kfPz3o0DiVr26xmc8WynYES\nYV9PxWORBO/tIsg/twhgST0qAG4GcGEHt2lNkk4YYG5fp8l6MJtxTn13GbZXgJN2exz0SWQ4oz0O\n3Q9VeEsHT2TTgVzBTgYbeBwmZ3M4Mr2EGy4Zt6ZdsWkIx2ZzZnpYBG8D4DYWonoc+rThMJ3DmCpH\n7BeqSBhkGbephDYcqtb7KNvtND6nlct3crb2znElQhWZhqEKbTi03+OgMyHOLhVdqcGA7XEIklEB\n2NqbhXwZ88tl23CIt+5xyCRMr0K5UrX+R6fh4DRM8p6CRr6hilK0fQnwT8nU2o6BtNNwMMMVm4f9\ntUva46DPbbpRl2+oYqB5o6unT5nCyMs3DmK0P+nWODjCKE5DquVQxQpqHJoeDcz8R873RPSHAO7v\n2BatUTKOC3gnT4qFchVlR239sKp277qA9jW50icq7XHoZr8KZ8fQVmnUIfM7SvT3KpfhYOocfnh4\nJlINB8CuqwBENxx0auGJc8tW4R+vK7tcqbrSPU2NQ8UOIYT0OBARUp6yxzPKjXtstvbO0bqjjfgb\no6AvFn46Bm2At7vkNGDui/PLJcwtl6ziTxqdkhkkowLwhCqWSxjK2BqnGo9D0V/vUw+rtXapUuMR\n8v63y54SynrcnGWWo4YqANNwePAZt7DWWSdB84qLx/Do5BzGs/6ZI0lDV19sLo7U62hUBOrpk/OI\nkalHGR1IWYYE4K4xoY/BxULFOq9GEkfGaXVqHBrQB1MwKYRAW5WdzqxY8hxE+uCMFqowl6kymiqK\nm5HzZHqkEzFLxNUNbI9D6xeAwUy8bnjj+wensXk4Y93xAKbHATBjpFE9DkRkZzpEDFXoCwWzfTLU\ndRy0urxUYZfhoC8Mdkne8N/t9Wo4QxVe8iWzpHaQwkTtIhYz24c30jh0wuMwmE7gxLm81VfCiS5I\ntnPjYKB1ObM0nI3UzHRbj8dBl38PaAzpc1e+WHGEKuysG3evCnclRNvjYP//UUMVgOlBOLPgruVg\nlXR2HFv7dm3GN375Va5mU060gVD0eFX9DId0wsBQJtGw7PRTpxZw0fgA0gkDowNJzCwWrWNqsWB3\nxNX7Uc7hcehFjUOQAlA/I6LH1OMJAM8A+HjnN21t0YrWIAxLnvilPoj9iqY0o1CuQssxWt1Jlzx3\nIt0uO10vHTMK9TwOVsfBi9a5dCzj2ZRVRjiq4QDYJ7VWKkdqtHhMh9Bsl221xnAoqrbA+n1YnHel\nuaJ9wvQPVYSvpNcOMgnD0jM46VTlSMDcF3XcfMTjcXjd5evxtx+4zsrKaYaz98W8Q+OQTsRqawCk\nJQAAIABJREFUjn2rimtAY0gft7lixVHHQYUqjFqPg19BrSW/UEUEj4PWG7g0BDrdMRXcm+dtTd1I\n4wCoWg4NPA7PnFrApcqLN9afQrFStbIpFl0eBzt0k2+hjkPC0xa82wTZ4jcDeIt63ARgEzP/aZCV\nE9EbiegZIjpERHf6fE5E9An1+WNEdHWzZYloHRF9k4gOqucRNf2dRPSo41Elol3qs7drw4eIfi/I\ntrebVgoxhcF227WmcWBmFCtVa0eP2mFTkyuWXReubpeddnYMbZXBjL/G4dhsDtOLRezeVluRT3sd\nsiFObl5aNRycRpP2OGhDQLdDLpWrlhtXfxezPX5RTvZOj4M+4Q+m45g8m6upHmr2Qeh+Jfxfu+kS\nvO1ltY7Uay5ch198xfZAzaDC4jQinemYgCkE3L1tXeB19SfjILLTMYcsw8GsG1BxdKjURnRQF7kV\nqnB5HFSoImHUlJzOOAtqJQ0Q1cmqiPA/a4PXlbVQMI/FgRBGecJTg8KqHFnH0zWRTdXVOCwWyjg2\nm8Pl2nDImv+l3tedwk1fjUMUsfRqTcfUMPNRAKMA9gH4BQAvCbJiIjIAfBKmmHIngFuJaKdntpth\ntuneAeAOAJ8KsOydAB5g5h0AHlDvwcz3MvMuZt4F4DYAR5j5USIaBfAHAG5k5isAbCCiG4P8hnai\nD75OexxynuwBHSsO+72lCpudHNV6WvU45AoV111b1w2HYgUJgyJfdJ0MphNYKlZqwje64+AenxO+\n1jnottxR0Ce1qAWg+n0MB8uwVHelpUrVFSawmmspD0urHgd9wt91wQhyxQpmPLnx+QgdONvBbddd\n6Huh7k/F8Vtv2RlJwNYMZwVRb6giLLEYYSAVx9lcEUvFihWqsAxDx41DTnn/6rnxvWSUZ2K5VKlN\nxzRqsyqcngwiwoCnI2QroYqxAfOi7DYcwuuXkl5xZJN044lsqm6o4hmlZ7hsg3mMj/Zrr4g5/2Le\nKY7Umo/W6jgkV3tWBRH9FoB7YBoPYwD+koj+e4B1XwPgEDMfZuYigC/CND6c7APwOTb5AYBhItrY\nZNl9anugnm/x+e5b1TIAcBGAg8ysFTXfAvBvA2x/W+mWxmHRc2dtxSdDurX0AaVPbq26xZaKZZcY\naziTxNxyN8WR5bZ4GwD74r/gScl85OhZZFNx3xQ6bThEKTetsTwOUTUOjph2jeGg9stSlV1CTH0R\n1+mnrWoc9F3YVapzolfnUChVV8TjsBIMNPA4RGEwncCJOfOu2CmOBNyGg7N7bhCcYdYacaQnFOIN\nVQBwlVkGWhNHWh6HhdpQRZgwoFWJ1eFxSBqxuqny6wfTOH2u4Hse1D0qLttoehxGLePG1DksFu0a\nE6m4gYRB7joOEcYhYax+ceQ7AbyMmX+bmX8bwF6Yd/TN2Axg0vH+BTUtyDyNll3PzCfV61MA1vt8\n99sBfEG9PgTgUiK6kIjiMA2NrX4bTER3ENEBIjowNeVfEjcqXdc46KyKkG2NNTrtSh+MraaR5goV\nlxhrpL/boYpK24r46Ls5b1bII0fP4qptI4j53MlZoYoWNA7OjpVRyCTMjpKAU+Og70jtUEXCx+Og\nQzNRTvb+HgfTcPDqHDqddbSacO4L3nTMqOvTqYpOjQPgvnEwa6oE3w/tUEW5RuuS9Ij0/NpE96cM\n67wEOEpOR/I4qJoKfqGKEDcGtsZBVY4sVxseV7u3jaBYqeLA0dmaz54+uYBsKm6Vt3aGU3LFCpjd\nRmJ/Ko5coay8azHf80WQ7V/V4kgAJwA4q2ikABzvzOaEg80AqctfQ0TXAsgx8+NqnrMAPgDgSwC+\nB+B5mPUo/NZ3NzPvYeY94+PjfrNEplsaBzuWb35fTFVrDFtyWp/obcMh+nYzM3Il94V7KJPEXK57\nHTLD3mU14orNpvdA9xIAzBLUz5xewO46sfAtIxn82k2X4M0v3RT5e5NakBbRcCAi6z+wPA4ew7JU\ncZ9AU1aooux6HwaXx0GFJnZtqWM4lM8jw0Fd6IwYWXUYWlpfOm41gHJqHAB3HQ2zvXwIj4PDW1pQ\nFzt9Z56Mx1z6JzMds7bfh2/J6QiepUzSQH/ScIUqFhy9IIJihyoq1nOj4+q6F40iHiN899npms+0\nMFKPiRa6ziwWXQ2uNP1Js7193sfICrz9PSCOPAfgCSL6SyL6CwCPA5hTosZPNFjuONx39ltQa3DU\nm6fRsqdVOAPq+Yxnne+A7W0AADDz15n5Wma+DmZWyLMNtrsjWCGDrokj7YPIzNUP973FcvtCFYVy\nFZUquzwOw30JFCvd65C5VGxfqOKyDYO4bEMWX/2JvTs/emwOzPAVRgLmRfvDr90RutiUEztUEf3C\n2p+KI5MwrHbiNaEKTzqmpXEotE/jMJCKY6Q/ifFsqiZUkT+PQhX62BpxNLhqdX1LyqPpLAAFuHvV\nmAXiwnscllVWhdOw01k3mmVPASigfqgiashtLJty9YKwwrMhvCjae1csOzwODbYnm07g6m0jNc3Z\nFvIl/PSFObxUGcKAecwMZRKYWSr4GjX9qr2931gF3/5VLo4E8FWYTa2+DeBBAL8B4GsAHlGPejwM\nYAcRbSeiJMwL+n7PPPsBvFtlV+wFcE6FIRotux/A7er17WpbAABEFAPwNtj6Bj19Qj2PAPgggD8P\n8LvbijOlqZP4ZQ/4Nbpphj649Q7fiuFgNdVxaRy62+hqqVBua7+BW67ajJ8cm8Pz00sAzDBFjGwX\nfCdIOTpWRqU/ZWA8m7IuVF5XdlFVjtTok+n8ctl1pxlquxO24TCzWLQEbhes6/MxHCqRYr69iD62\n2hGmANyhjyFHyWnA3atmqRjS4+BKx3Qbdn4lpzOe46y/xuPQWq2OsYEUphfcvSD6k8HFnoCj5LRD\nHNnMA/KqS8bx5Ml5V+npf3r8FArlKt585UbXvLqWg1VjIuUOVSwVy1huIfXYLAC1isWRAIZVwyvr\n4ZxWbyFmLgP4MMwqk08B+DIzP0FE7yei96vZ7gNwGKYO4TMwL+p1l1XLfAzA64noIIDXqfeaGwBM\nMvNhz+b8CRE9CeBfAHyMmbvucejrVgGooulyc941RjEcip5QRSvxNKuNryurwjxZdqp65JcePob/\n9tWfObah0rZQBQD83JWbQAR87dETAEzD4bINg22pE1GPVtMxAdMTpS/cgJ/HwVPHQX2+kC9FzuYw\nixDpUEUBoyoGvHUkg0lP9Ug/cd1aRR9b3qqRra4PgKsAFODJqvBkODXDGarwhpKSDm9Spcoolqs1\nd9E1oYpSNfK+BJiZFe6sivDeRH0MecWRjdDVYL930PY6/N2jx7FttM8S+1rb2G82ulr08Tjo8Whl\nX08axoqWnA7y793uM+09QVbOzPcx8yXM/CJm/l9q2l3MfJd6zcz8IfX5S5j5QKNl1fQZZr6RmXcw\n8+uYedbx2YPMvNdnO25l5p3q8UXv593AzpfvvMfBe/FKJ2KhDRataRhsQ6jC1+Og0s/OdcDjwMz4\n9HcO469+eAxHlEfAm9XRKpuGM7h2+zr83aPHUa5U8ZNjZ+uGKdpFOwyHD77mYnz4tRdb721xpPkf\nlb2hCu1xyJctIyIsXo/DaL/tcTh5btnat6YWCjgys9RSOKeXyFoeh9ZSMe312esZtLIqapuM5Urh\njoWkYTatWi5WzItd3BmqsOs4WE2bku79U7vmNYVyNfK+BJgeB2car7OldlD8CkA1O652qj4UOlxx\n6lwe//rcDG7ZtbnGEzc6kMTMUtFXuNmfjCOnNQ4Rw3KJOK1OcSQR3UpEXwewnYj2Ox7fBlArLRUa\nQkRma+0uiCO9dxOZRG3Z2WZ4PQ6tZFVYTXU8GgegMx0yn5taxGFlMHztUVOH0M50TM3PX7UZR6aX\n8DePvIClYqXjhoMOIaQiungB4A1XbMBrL7MTkey21yqrwhuqcNRxiHqXmHJ4HKYXi7bHYV0fqgyc\nmDO9Dg88dRrM5jaeD+hiYO1IxQTsYzVhkHXX7yeO9GY4NUOfu3LFCvLl+qEKfYPgr3Fwl5xuzeOQ\nwtlc0aqj4mypHZSEN1RRaW44xGKEV+4Yw/cOTqNaZXz9pyfAbIYt/bZxZtGhcfCEKha1xqEFceRq\n1Tj8K4A/AvC0etaPXwXwhs5v2tojk+y84eBtLwuY7ubIGodUGzQOhVqPw0gHQxX3P3EaAHDp+iz+\n7ifHwcxYKoY7WQbhjS/eiGQ8ht+//xkA9YWR7aLVrAo/vAWg/EpOA7bGIQra41CtMmaXClaoRPdj\n0DqHbzx5GltGMrh8Y7DGTr1OOhHDYDqOTSqNr1X0xXMwbYst/cSRUbxv5rlLpRA6QxUqLbBa5bqd\nTQeScRQrVVeVxpYMh2wKzMDskqMyY0iPg7dXRZBQBQC86tJxzCwV8cSJeXz1J8dx5dZhV18azehA\nEmdzJasfj9twMEyNQ7E1cWQ7eghFpe5IMfNR5fq/jpm/43j8WGkQhJBkEgaWi539o/2yB8xGRlHT\nMVsPVfi18R3qoDjyG0+expVbh/G+67fj+ZkcHjl6FsVy1bcXQSsMZRK48bIJzC4VMZFNYctIey4A\n9Ui2QRzpxRuqKFXcJ1B9gi9WqpErOqaVO3s2V0SV4QpVAKbhsFgo4/uHpnHTzg1tyTDoBYgI+z98\nPd53/fa2rE8fq0OODqxeDUulysiXqqGbdvUlDSwXzXRMV1ZFwt4/6lVC9ParMDUOLYQq1P4z5azM\nGFbj4FPHIUj45JU7TJ3Dn3//MJ48OY+f3+WfXq29atoo7veKIwvlllKPvXUouk2QypELRDSvHnki\nqhDRfDc2bq2hrfZOYooA3QdRJhELra3QGgerV0ULlq0ueuXN9EgnYvjmk6fx0X98Ch/9x6fwpYeP\noVpt7UA4dS6Pn07O4aad6/HGl2xAMh7DvT88VvP97UK7KXdvG+n4Ba/VypF+2BcWXQDKPx0TiJZ3\n71zupKpqqE+q6wfTSBoxTJ7N4bvPTqFYruKmK/zqua1dLhzrb9t+qUMV2QaGg12SPtwFywpVlKqu\nlufO7AS7eZbH45C2GzsBKlTRQsrtWFYXWHL2gginE7HTMcN5HMYGUrhi0yC+9ugJGDHCm6/0Nxy0\ncXNkegmpeMx1HA2k4ihVGPPLpRY8Dmr7V8jj0HSPZWbLb0jmmXEfzOqRQkhMj0PnNQ6bhtOuabp1\nchhqsira4HHo95xQrtk+ih8ensFTJ+fB6jv++ekz+KO37YqcnfDNp8wwxRuuWI/BdAKvu3wC//Az\ns9BoO7MqNK++dBwv3TKEN71kY/OZWyTVBnGkl4QSvjk9DnGfktPO7w+LFtMdnzPvvnRJXiNG2DKS\nweRsDqfP5THSl8CeDod71jL+Hge3ONLSIYSMreswq/cuOZWwNTL12kTrY1mfB1oOVVhlp02Pw0K+\nFLoia9yIIUZOcWRw3cWrLhnHEyfm8codY9a2eNHG8dGZXM226fPg7FIxssZBb+tK6RxCjbaq1Ph3\nRPTbUM2lhOB0TxzpCVXEo2scdFZFK5Ujtcahz2MMfO4Xr7FeMzM++y/P43/f9xRu+eS/4O7bduOi\n8fDq+m88cQoXjfXjRWrZW3Ztxn0/OwWgMx6HVNzA/g9f3/b1+tFqyel6pON2ZVFvOqa7imT0rAoA\nOK48Ds6T7ZZ1fTg8tYTjc8t44xUbIuf2C7aR76xCmYq7PUpLEYolAXaowiwA5dgnDJ9QhY840vnd\nBZ+UzTA4G10xs6+uKwjOIkpBxJGaGy+fwJ89+Bx+4erabqoabRwfn1vGVk8IU49HlWuNrKB4s0K6\nTZBQxS84Hm8loo8B8O8vKjQknTSw3GJ76mb4HUSZZHhPRyc8Do1OFkSE912/HZ9/3zWYXSpi35/+\nC06eW647vx/nlkt46LkZvP6K9VbY4NWXTlh3YO1Mx1wJ2pGO6UcmaTi6Y7JvyWkAiFrRUV+8dDnk\nUUcWwQXrMnj61AIW8mXcdJ5kU3QKfaw6PQ5GjJAwyPp/c3XCCc1whSo8dRwAM2tjuY43Y0B5+nQX\ny1azKgZScaTiMUwvFpAvVVHlcOWmrW037DThYggvyO5t63Dff3ol3vLS+l7GMdUhs1Llmm3zhmyj\nYBkO5VWqcQDwFsfjDQAWUNvlUghAFK1BGHT2gNcln0rEIosj0wkD8Ri1XMchnYgFquz28heN4a53\n7cZCoYzHXjgX6nsefOYMylXGTTvtC1AyHsO/UQd4JzwO3USXmm6nxgFwp0vWS8fU80UhbXkccoiR\nnVED2ALJTMLAK3eMRVq/YKJDFYMZd7zf6XH0qywbhEwybrXV9pacBtwah2Yeh3ypeZXGRhCRWT1y\nsWiVQo/icTBbUwev4+Bk56bBhpqmwUwccXW+826bc+wjaxw8vTa6TRCNw3u7sSHnA50OVeieEDVZ\nFUrVXq1y4E5sOjSRVMKeljwOIcs9bxs1LyZnHKVdg/CNJ05jbCBVU8XtXdduw4+OzOKi8dq0qV6i\nUx6HdMJsVFStMspVtzgyHiMQAczRNQ7a4Dgxl8e6/pRrH9w6Yv7XN1wydt5UjOwU2VQcey9aV6MT\nSSUMW+NQiuZx6EsYyBXLKJQ94khHWmPdUEXSRxzZYllxs19FIVJLbY0zVBFUHBkUIsLoQBKn5ws1\nws0Bx41d1AJQSU+vjW4TJFSxhYi+SkRn1ONviah+cEeoSyYZ72ivCm3R11aOVAKmEBf/YrmKeIxg\nxKimkU1YciFrKIz2J0EEV034ZizkS/j2M2fw+p3ra4yjnZsG8a1feVVdIVOv0ImsCsAuSV6qmv+x\n03AgIstgiHqXaHscll3lrgFgx3pTi9INcelaJxYjfPGO63Dj5e7MFGeTO6umSmiPg2GlTqf8QhXl\nqqNyZB1xpCsds7V9eHwgiWlX98kIhkPc9qSG9TgEQZ9vasSRTo9DRHHkqtc4APgLmI2lNqnH19U0\nISSZCIWYwrDkU2jJ/F7zbw7j7XAqn72tc8NvVziPQ9yIYbQ/iamF4FKar/7kOHLFCt7+sq3NZ+5R\nWr2A10Nn3ZRVTrgzVAHYhkpkcWTcVpGPegyHiyey+OYv34Cfq5PWJrROynH8+tVUCUImabjCl/a6\nzdfFsh2q8HqO/MSRrRoOZqjC0QsiSqjCiKFUYcvT1m7DQWdW1IQqkq1rHKxeG6s4q2KcmZ2Gwl8S\n0X/p1AatZTJJs2cEM3ck51+LCScG3XfW3lzuIDgt8GSLHoflUrimOgAwnk3jzHwwjwMz43MPHcVL\ntwxh19bOdadcad5wxQbkSxVsGEw3nzkE5h1p1ToJJTweDbNiZfTKkU5R5Wh/rddnx/rzo1LkSuFs\ncpcraMMhZFaF4wLnLTkN2KGKhEE++08MSSPmFke2GJYaHUhidqmI+bzSOEQMVRQrVevc1mr4xIuu\n5eDdtoF2aBw8JbO7TZAzwQwRvYuIDPV4F4CZTm/YWiSTMFCpcseqfU0q1bqOG2uiGA7OOGTSaIPG\nIeQdwXg2ZVWGa8ZDh2dw6Mwibtu7Lcrm9Qzj2RR+6ZUXtd3o1OK5Yh3DwfJ0tOhxAFDjcRA6j7OO\ny1LUrIqkMy5fK44slCtKBO2/Xt3oipnb5nGoVNnqrpoNWQAKsPtsaE9K+z0OynDwnPucYds1WzkS\nwC8CeBuAUwBOAngrABFMRkDvJJ0SSB6bNVXr3tr3Ub7X7XEwQukjvOSK4T0OE9lUYI/D5x86iuG+\nBN4i7u5IWBoHdRLyaihaDZE4LxK9rjPpRbT4FTArR2rdUhichoNvOqbSONS7g9aNnUoVbkloq9H7\n0ZEZs5ld1HTMUqXqEoK3k9E6GodU3LDCga00uQJaS5NvhSBZFUcB/FwXtmXNY/W1L1ZcudbtYnI2\nh41DmZoDwO5HEHwnc94VtCqOXCrWFqVqxoRSTTfLBDl1Lo9vPHkav3T9dlHlRySlQxXqJJSIezQO\njv0gCs7/ZbRNnSCF4KTjhtVsaalgGvFhvVZ9yTqhCsMdqqh3gzCgDAd9kW45q0JdlJ9XXXCjVIXV\nWRX64ttK11k/9L7up7/oT8Uxl2uh5LQ6RlezOFJoE/qg6qTHQefFO/FrrdsMr8YhzLJecoUoGocU\nylVu2j3zr350DFVmvPPatR2m6CTphIFCuWKdhOIxf49DVMPMaXCMiseh62jDEDA9DlEKoWUSDkGf\nswy5o6T1coNQxYBq7KQ9l60KfMez5kX5+eklJI1YJENEhyqKHQpVjNURRwK2QHLNVo4U2oe2LjvV\nr2JyNoet62o7NHpbJweh3R6HsBqHiawpAGxUy6FYruILPzqGV18yjgtGaw0mIRimxqFqhSr8xG1A\nezwO3nRMofO4CkBFbC/vdKk7hY0pw5FVUarUdb33ew2HNoUqTs7nI4UpAC2OZIc4sr2Xwys2D+Il\nm4ewc9NgzWfamOjVUIUYDl2kkxqH5WIFZxYKvh4H22AJV8fBWTcg6g5qt/ENqXFQmSGNDIcfHpnB\n1EIB/068DS2RTpjZPvruJekJVei7uejiSNE4rCTOAlDLxUokj0PdUEXc7XGo53q3QhWl9oQqhjIJ\nJAwCc7RUTMDcz52hinZ7HCayaXz9P16PLSO152QdWokaqrDTMVepOJKIniOie4no/UR0RTc2aq2S\niZDdEJQXzpqdB7f6hiq0xiFiVkULlSO1kRT2ZDWuLjCNikDp+OaVW4YibZtgklbZPro4Wbs9DrEY\nWXdIklXRfZwFoMwmeBE8Dq50zFpxpOVxaJhVUWmbx4GIrNTeyIaD0dmsikZoD2yr6ZirOVSxE8Cn\nAYwC+ANlSHy1s5u1NnGKI9vNsVnTcGikcWglVBE1q8LKGw/pHrU9DvWLQB2bzSEVj2E8K3exraAN\nywWVE19jOOgCUC3EpVPxGDIJI7RIVmidVNxwZFWE1xsB9bMqjBiZvWwqFSyXKkgHDVW0oYjZWNa/\nTkJQvOLIdldkbYS+kYpqQOmsjNVsOFQAlNRzFcAZ9RBCoq3LXAc8DpOzjTwO4Q2WmgJQEQ0HnTce\nvo1vHAOpeMOUzMnZZWxd19eRYlrnE3r/0OV7a+o4JFqr42CuwxBvwwqRTpgapUqVzQynCHforlBF\nvNYjVShVkS9WXIWinAyk4lgqli3PRzuKLWmPQzaixyHRYXFkI/pVh8+gvYO86GO0lTT5Vggy4vMA\nfgbgjwF8hpml+FNEtNXeiQ6Zx2aX0Zc0fNPd0onwO5npcXCEKiJatkuFaCVugeZFoOplkQjh0Cr5\nhbw2HOqVnG7N4yAZFSuD3aumglyhgv4Ix2Jfon6ZZC2ebiaOrDLsfhdtuEhbWQsRPQ5JVTnSDp90\nL51783AaG4aiV4BN9kCo4lYA3wXwQQBfJKLfJaIbg6yciN5IRM8Q0SEiutPncyKiT6jPHyOiq5st\nS0TriOibRHRQPY+o6e8kokcdjyoR7VKf3UpEP1Pf8U9EtCL9ezMdFEfqi6jf3XfSiIEorMbBKY40\nInscclaluvAH93g2hak6HgdmNrNIRmqzSIRwpJqFKtrQIyOTNDAuHocVQXsICqVqpJoqAJBO2v+9\n13DQHsnGGgfzO2eXzPTqdlykrVBFZHGkClVUuu9x+OBrLsZXPvDyyMvHVIho1RoOzPw1Zv5/APwH\nAPcBeA+Av2+2HBEZAD4J4GaYOolbiWinZ7abAexQjzsAfCrAsncCeICZdwB4QL0HM9/LzLuYeReA\n2wAcYeZHiSgO4E8AvIaZXwrgMQAfbrb9nSDjqeNQrTI+9eBzDeP4QZmczfmqdwFTSBS2wZYpjmxH\nqCKaxgEwi0DV8zjM5UpYKJR9QzNCOPSFwPY4eOs4mJ+nWzjZ/+abd+I/3bgj8vJCdJwap1yxEqlY\nUtKIwYgREobZMddJKm5guVRBvlRtUMdBNzozj+d2aBzGW/Q4JAyzO6ad6dE9wyGdMFr2wCVUk66V\nIEhWxd8S0SGYF98+AO8GMNJ4KQDANQAOMfNhZi4C+CKAfZ559gH4HJv8AMAwEW1ssuw+APeo1/cA\nuMXnu29VywAAqUc/mbfjgwBOBNj+tqNPvFpr8LPj5/B7//Q0/uGxky2tl5kxebax2z6dMEKXnPbW\ncahWw++kuTodO4Mwnk3hzLy/UTV5tr4YVAiHPtnPK8PBKxJrh8fhVZeM46Vb1m4DstWM/t/OLZdQ\nqXIkjwMRoS9h+BqPyXgM86oyZd1QhfrOGcvj0L5QRVSNQ9IwUGXbE9tNj0M72DScjpyV0SpBRvyj\nAH7CzGH965sBTDrevwDg2gDzbG6y7Hpm1lfaUwDczedN3g5laDBziYg+AFOnsQTgIIAPhfwtbSGm\nasTrC/iBo2cBNK5VEISZpSJyxQou8Cn+pEnHY4FLTnsb0VgpV5Uq0rFwO2rUNr6AmQe9VKz4Nsmy\nskik8FPLaFe2FaqoW3JaSnr3Ivpir8MEUTQOgGkU+N07JI2YVdK6Uclp5za0JVTRoDJjEPR+rrt2\ndjOroh088KuvXrHvDhKqOADgciJ6GxG9Wz+6sG1NYWYG4NqViehaADlmfly9TwD4AICrAGyCGar4\niN/6iOgOIjpARAempqY6ss2ZpGF5HH6sDYeAzZzqEeQimg4RqrCaHXny96MIJPVvDVs5EjBDFYB/\nLQf9m72dQIXwNMuq0Hc16Ta4l4Xuo//fs0v64h7tQptJGr77QCoRw5wyHOqGKtJuw6Ed+5JOw86m\no/X90YaCFnC3I3xyvtB0DyKi3wbwaphag/tg6g6+D+BzTRY9DmCr4/0WNS3IPIkGy54moo3MfFKF\nNbypoe8A8AXH+10AwMzPqd/zZShdhBdmvhvA3QCwZ8+ejgSP+lTIgJlx4OgsAARuH12PyQAX0TCG\ng7cRjbPIS1ha8TjoE8OZhQIuHOt3fTY5m8NofzKSQSK4qdE4eHpV/MLVm7FhKCU1GHoUfUHU+oIo\neiPANCDLPi6HpOEIVTQRR84sts/jcMn6Afy/t7wYN13h53Rujj6vaYO51zwOK0mQkXoZn8m4AAAg\nAElEQVQrgBsBnGLm9wK4EkCQUn0PA9hBRNuJKAnzgr7fM89+AO9W2RV7AZxTYYhGy+4HcLt6fTuA\nr+mVEVEMZgtwrW8ATINjJxGNq/evB/BUgO3vCOmkaTicOJfHaeVpqBfHD4o2HOqJIwFdPS7Yhd+b\n19xKXfRcoRKpjS/QuAiUruEgtE5NAShPqGL9YBo/f9WWrm+X0B60YThjhSqiGYB9dTwOyXjMSrNs\nVHLa3IaCtUyrEBHetXdbZI+D9qwt5MuIERAXwyEwQfagZWauElGZiAZh3uFvbbYQM5eJ6MMA7gdg\nAPgsMz9BRO9Xn98F04PxJgCHAOQAvLfRsmrVHwPwZSJ6H4CjMA0FzQ0AJpn5sGM7ThDR7wL4LhGV\n1DLvCfC7O0ImYSBfrODA86a34cotQ3jh7HJL6zw2m8NENtWwYUo4j4O7LGwqQh0IzfMzSxjpS0Qq\n0qQbXdULVezaKmK7dtAsq0LobfRxrMMEUbx/ALBpOON7DkjFbU9EozoOgBku8cvMWAkSjlBFrwkj\nV5oghsMBIhoG8BkAjwBYBPBQkJUz830wjQPntLscrxl1hIp+y6rpMzA9IH7LPAhgr8/0uwDcVbPA\nCpBRoYofHz2LvqSBGy4Zx59++xBKlWrkE/ax2VzTu+9MwsC8uqNsRq3HwXBND8r0YgH3P3Eqcsvr\n4UwC8RjViEfLlSqOzy3jLVdujLRewY23AFR8FZzUhfZR43GIGN77/be+FOwTwHV6E+tpHHRFyWKl\nGlnM2G6coQoR/oaj4T+o0hc/ysxzAO4ion8CMMjMj3Vl69YgmaSBhXwZjxw7i6suGMaGoTSYzdhf\n1Epik7PLuGb7uobzpBNG4JLT3kpqUTUOX3p4EqUK47brohkOsRiplEy34XDyXB6VKksqZpvQHqXF\nQlkVCxPDYS1hiyNb8zjU07g4DYd6647FCP1JA0vFSlfrJTQiaeisCvE4hKXhaCmPwH2O98+L0dAa\nmYSBmaUCnjq5gN0XjFhFTKIWgSqWqzh5rnm8PxVB41Cbjhk8I7dcqeLeHxzF9ReP4UXjA4GX8+JX\nBOpYg74cQnhScbOyKFBbblrofdKeUEW7BcXOi26jugL6e1eL4eAKVUh4LhRBRuvHRPSyjm/JeUIm\naWBydhmVKuPqbSOYGKwfxw/CibllVLl5IaR0wrCyJZqh5/OKI8NoHB54+gxOnMtH9jZo/IpABcki\nEYJDZItXRSC29kgl3HUcGmmhouAyHBqsW4coUitUtMiLO1Qh+30YgozWtQAeUu20H9M9Hzq9YWsV\nbZETAVddMGLVKohaBMquZ9C4Z0MmRKjC63GIIo78/ENHsWkojRsvmwi8jB/j2XSNUXVsNod4jLCx\nhSYxghvtzhZh5NpDexzO5lSoos0X7iAaB2D1ehwW8xKqCEsQn9UbOr4V5xH6wLpkIouhTMIyJKIW\ngQpaQTGdiCEf8MJfaDEd87mpRXz/0DR+7aZLWr6DncimMJsrusSjx2Zz2DySkbvjNmIKJEtW3FdY\nO8SNmGqIxEjFY20/boKHKszPVp3hUBSPQ1iaGg7MfLQbG3K+oF15V28z230k4zGM9CUwtRhN46AL\nqow3aZgylEmgUmUs5EtN8569BaBSIcWRn3/oKBIG4e0vuyDQ/I0Yz6ZqxKOT0k677ej8/IScQNck\n6YSBRZ/S7e1AZ13pJlj1sEIVqySDQZ/XmHuvT8VKI6PVZbRFvmeb3SdsIpuO7HFYLlWQDHAXsWHI\nDGWcPNfcQKnxOIQ0HO5/4hRed/l6q/JjK/iVnZ48u9yw2JUQHglVrG20YRg1o6IROpTZlzAaZuRY\noYpVUtrZua+L4RAOGa0uo63u3Q7DYTybiqxxyJcqVgyzEZvU3frxuebFprwFoPRBFUTjUK0yziwU\ncNF4f9N5g6DFozrrZCFfwuxSUTwObUYbDlLDYW2i7/KjVo1shA5lppsYJQOrTuNg7+uSVRGO1VGJ\n4zzilqs2YzybcvVemMimcGR6KdL68qVKIJX0pmHlcZhr7nGoEUfGdQGo5uLKOdW6d7S/dW8D4O5X\nAZg1KwBpp91u9B2p3HmtTSyvQMQ+FY3Q+0yzFs+rLVTh3Ndlvw+HjFaXWdefxFuu3OSaNp5NYWqh\nAPYry9aE5VIlUE/2iWwKMQJOngvjcfAUgHJ0x5zPl3Dw9ELNstOq5sJYG8IUgK3dOKk8JZYYVAyH\ntiKhirWNrg7akVBFQMNhtWVVOL0Mq8WY6RXE47AKGM+mUKxUcW65hOG+ZKhll4uVhilQmrgRw/rB\nNE6E8Dg0yqq4+zuHcc+/Po/HfucmV1xzWnkGxgbC/Y56JOMxbB7O4BP/fAg/PjaHoYwp7Ny6rnH6\nqRAOfWGRAlBrE1vj0IFQRTxYqEI0DmsHGa1VQCtFoJYDhioAYONQ2tfj8P7PP4KPf+tZ6723AJS+\nmDgNhxNzy1golHE25+5/oas8NsvyCMNXP/hy/OrrL8GR6SX8w89OYjAdtwwIoT1YWRXicViT2BqH\nTngclDejaahCZ2mtjrt7CVVERzwOqwC77HQBO9ZnQy2bDxiqAICNwxk8eWLeNa1aZTz47BmrJz1g\nGgjxmN3BjoiQjMdc4shZVUzmzEIe6/pt74JODx1ro+EwMZjGf7xxBz74movxvYNTiMekn0K70V4r\nEYmtTSyPQwfSMa1QRVCPwyq5SLs8DrLfh0JGaxUwMVibchiUoBoHwMysODG37NJSnJrPI1+qunpl\nFMrVmoM75TUcVPna05400unFAuIx6ohHwIgRXn3pBK7fMdb2dZ/vWFkVEqpYk+j/txMeh6DiyNVn\nONj7+mrZpl5BRmsVYJedDl8EarlYaRpb1GwcyqBQrrrCCzqbw5kOWixXa+rJp+IxlzhSexa8fSSm\nFwsYHUgiJml9PUVKQhVrGm04dELjoC+6zbRWq61XBRFZngYxHMIho7UKGEjFkU7EIhWBypeqlrCt\nGZuGTS3FCUcth8PKcJjLlSxtQ6FcqXHdJY2YS+Nw1gpVeD0OxbaGKYTuoPchcdmuTXSoor+T6ZjJ\nxvuOriGxmi7S2usgGodwyGitAogIE9l0TfvoIJh1HIL9jbqWg9NweN5RP2JaeRFMj4PHcIjbhkO+\nVEFONcw67eNxEMOh95B0zLWNFiRmOphVEbyOw+rZx7zVcYVgyGitEiayqUgehzAah40+Zaedhad0\n2KFQrtZ6HOIxyyMxo/QN5jIej8OCGaoQegu7V4WEmNYi+kagk1kVzYySjcNp7Nu1CXsvGm37NkRF\nG8riaQuHjNYqwSw7HU7jwMyhDIfR/iSSRgwnHCmZR6aXrGJKWpxZ8PE4pOKG5XE46zAcTju2mZkx\nvVhsayqm0B3E47C2sQtArZzHIWHE8CfvuCp05lgnsQyHVZIi2ivIWWKVMKGqR4ahUK6CuXnhFU0s\nRtgwlLbKTpcqVUzO5nDN9nUAbL1CsY7HQYsjtcfhgnV9Lo/DfL6MYqUqoYoeROo4rG2srIoOaBx0\n/YaBdO9l99tl9WW/D4OM1iphPJvCfL6MfKl5PwiNnjeoxwFwF4F64ewyylXGyy4cAZFtOBTKlZoi\nLU5x5OySOd/lG7M4s5C30jvtctMSqug1pHLk2qaTlSNH+pP47Hv24JZdm5rPvMqwPQ5yKQyDjNYq\nYSIbvnrkcgTDYdNwxio7fWR6EQBw8cQARvuT1ncXy9WaA8kpjpxdMtM5L9swiFKFrfTOThR/ErqD\nhCrWNlblyA54HADgtZetRzbde9VctaZHDIdwdHS0iOiNRPQMER0iojt9Pici+oT6/DEiurrZskS0\njoi+SUQH1fOImv5OInrU8agS0S4iynqmTxPRxzv5u6MwPujuAhmEZZXZEKRXhWbjUBqn5/OoVBlH\nps2GUdvHBjCeTWNqwRZHel13zsqRs0sFGDHCxRMDapvN5SyPgxgOPYfUcVjbXDjah0zCwHp1gyKY\nJMXjEImOjRYRGQA+CeBmADsB3EpEOz2z3Qxgh3rcAeBTAZa9E8ADzLwDwAPqPZj5Xmbexcy7ANwG\n4AgzP8rMC3q6+uwogK906ndHRQsKp0IIJLXHIZThMJxBucqYWijgyPQihjIJjPQllDizvsch5fI4\nFDHSl8TGIfMkpKtHiuHQu0jJ6bXNyy8ew2O/cxNG+iWM6CQhBaAi0cnRugbAIWY+zMxFAF8EsM8z\nzz4An2OTHwAYJqKNTZbdB+Ae9foeALf4fPetahkXRHQJgAkA32vtp7WfiQgeh3zJvJAHbXIFAJt1\nEahzyzgyvYQLx/pVHYmUO6vCq3FweRyKWNefsMIrOo1zeqGAGMHVu0LoDUTjsPYRb1ItSRFHRqKT\no7UZwKTj/QtqWpB5Gi27nplPqtenAKz3+e63A/iCz/R3APgSO5s1rBJG+1OIUTiNQzRxpKrlMJfH\nkaklXDTWD8DO6qhW2azj4OdxqDgNh2SNsTO1aE43pNx0z6HFc3G5uAjnEVaowpB0zDD09FlCGQAu\nI4CIrgWQY+bHfRZ5B/wNCr3sHUR0gIgOTE1NtXdjm2DECKMD4YpAaY1DKHGkMhyOTC/ixLk8tivD\nYTybQrnKOJsrqqyK+iWnZ5eKGO1PIZ0wMJiOW9UjpWpk7zKWTWEgFce20b6V3hRB6BqSVRGNTibe\nHgew1fF+i5oWZJ5Eg2VPE9FGZj6pwhpnPOv0NQ6I6EoAcWZ+pN4GM/PdAO4GgD179nTdK7FhMI3n\nphYDz29lVQQsOQ0Ag5k4+pIGHjo8AwC40PI4qLDDQqFuyWldOXJ2qYiRflNBvX4wbRk7usGV0HsM\nphN47LdvgnQrF84nElJyOhKdHK2HAewgou1ElIR5Qd/vmWc/gHer7Iq9AM6pMESjZfcDuF29vh3A\n1/TKiCgG4G3w0TfA1D3U9TasBt780o04cPQsHjl6NtD8UcSRRISNQ2kceN78DitU4Qg7FMpVpAxv\nqMKsHFmpMuaWS1jXb86/fjBtVY8Uj0NvE4sRSCwH4TxCumNGo2OjxcxlAB8GcD+ApwB8mZmfIKL3\nE9H71Wz3ATgM4BCAzwD4YKNl1TIfA/B6IjoI4HXqveYGAJPMfNhnk96GVW443HbdNqzrT+JPHjgY\naP58BMMBMGs5aKGj9jjorA7dAMvb+jYZj6HKwMxiAcxm+WrA3WNjekE6YwqC0DskpY5DJDpaI5SZ\n74NpHDin3eV4zQA+FHRZNX0GwI11lnkQwN46n10UdLtXir5kHP/hhovw0X98Go8cPYvd20Yazh9F\n4wDASqMcV3FtwPY4vHDWrO3gV3IasBtk6cyJicE0zizksVQoY7lUEcNBEISeQTQO0ZDRWmVor8PH\nv/Vs03l1OmZYj4POrNDCSMA0WgZScbxwVnscasWRQK3hsH4whVKFceiMqc0YE42DIAg9QlK6Y0ZC\nRmuVob0O3zs4jUeOzjacd7lUQTIeC53+uHnYNBwuchgOgOmBmJxt7HE4pfpcWB4HJap84sQ8AFOd\nLwiC0AtY4kgxHEIho7UKsb0OjbUO+RAttZ1sVEWgLvQxHOp5HLR46JTSM4w6PA4A8MSJc+Y6JFQh\nCEKP8IYrNuCDr34RYlJ7JhRiOKxC+pJxvO/67fjewWlLrOjHcjGa4XDp+iwGUnG87EK3hmLCUXba\nWxDF63EY7tOGg2mEPHlSeRzEcBAEoUfYtXUYv/7Gy1Z6M3oOMRxWKa+5dAIA8ANVb8GP5VIlVLlp\nzcRgGo//7huwe9s61/RxR5jBm56Ucogjs+m4ZUjoZZ4+uQBAyk0LgiCsdcRwWKVctiGLoUyiqeHQ\nzvzjCUfnPL+22gBwaj5vhSkAU5g5lElguVTBUCYh6mRBEIQ1jpzlVymxGOHa7evwg8P1BZL5iB6H\nekw08Djo0MXJc/maDnt6OcmoEARBWPuI4bCK2XvRKI7N5nC8js4hqsahHs5QRU2TKyWWLJarLo8D\nYOscRN8gCIKw9hHDYRWz96JRAMAP64Qr8uX2Gg66CBSA2rbajnQlr45BLyepmIIgCGsfMRxWMc10\nDsvFCtJtDVXYGge/Jlea2lCFqkQpHgdBEIQ1jxgOqxitc3ionsehVG2rx2E4k0Bc5TPXKwAFwCdU\nIRoHQRCE8wUxHFY5171oFJOzy1YPCSfLEQtA1SMWI0vnUK/kNACrM6ZGNA6CIAjnD2I4rHJsnUNt\ndsVysYJ0or1/oc6QSHkKQDkNCa/HYcuIWcJ6kyplLQiCIKxdxHBY5Vy6PovhvlqdAzO33eMAoK7H\nwWlIeDUOL9k8hC/8+724/uKxtm6LIAiCsProaFttoXWseg5H3IZDoaw6Y7ZRHAkA40roGEbjQES4\n7kWjbd0OQRAEYXUiHoceYO9FtTqH5WIFANrucdi9bQQv3jxY0/TFaThIWWlBEITzF/E49ADXbDd7\nSjxy9Cy2jPQBMGs4AO03HN66ewveuntLzXQjRtajr81eDkEQBKF3EMOhB9gybBoLU6pzJeDwOHTx\nIp6KxzCUSYBIWtAKgiCcr0ioogfIpuMwYoSzuaI1bblkGg7pNnscGpGMxyRMIQiCcJ4jhkMPEIsR\nhjMJnM2VrGn5lTAcDDEcBEEQznfEcOgRRvqTmHN6HIpmVkW7NQ6NGO5LYNOQ1GoQBEE4nxGNQ48w\n0pfA7FJtqKKbhsPdt+1BNi27jCAIwvmMXAV6hOG+JCZnHemY2nBIds9pdOFYf9e+SxAEQViddPSq\nQ0RvJKJniOgQEd3p8zkR0SfU548R0dXNliWidUT0TSI6qJ5H1PR3EtGjjkeViHapz5JEdDcRPUtE\nTxPRv+3k7+4E6/qSLo9Dvth9jYMgCIIgdMxwICIDwCcB3AxgJ4BbiWinZ7abAexQjzsAfCrAsncC\neICZdwB4QL0HM9/LzLuYeReA2wAcYeZH1TK/AeAMM1+i1vedDvzkjjLcn8BcrgRmBtC5Og6CIAiC\n0IhOehyuAXCImQ8zcxHAFwHs88yzD8Dn2OQHAIaJaGOTZfcBuEe9vgfALT7ffataRvOLAD4KAMxc\nZebp1n9ed1nXl0SxUkVOeRpWoo6DIAiCIHTScNgMYNLx/gU1Lcg8jZZdz8wn1etTANb7fPfbAXwB\nAIhoWE37n0T0YyL6ayLyWwZEdAcRHSCiA1NTUw1/XLcZ6TPTIHW4wqrjEBfDQRAEQegePZ2Oyabf\nnp3TiOhaADlmflxNigPYAuBfmflqAA8B+MM667ubmfcw857x8fEObnl4dEfKOVXLYblUQTIeq+kp\nIQiCIAidpJOGw3EAWx3vt6hpQeZptOxpFc6Aej7jWec7oLwNihkAOQBfUe//GsDV6DFG+hIAgFlV\nyyFfbH9LbUEQBEFoRicNh4cB7CCi7USUhHlB3++ZZz+Ad6vsir0AzqkwRKNl9wO4Xb2+HcDX9MqI\nKAbgbXDoG5RX4usAXq0m3Qjgybb9yi5hexzsUIUYDoIgCEK36VgdB2YuE9GHAdwPwADwWWZ+goje\nrz6/C8B9AN4E4BBMr8B7Gy2rVv0xAF8movcBOArTUNDcAGCSmQ97Nue/Avg8EX0cwJT+nl6iVuNQ\nFWGkIAiC0HU6WgCKme+DaRw4p93leM0APhR0WTV9BqbXwG+ZBwHs9Zl+FKZR0bOYXSlh9atYLlak\nhoMgCILQdXpaHHk+YcQIQ5mEFaoolCvIJOTvEwRBELqLXHl6iBFH9UjxOAiCIAgrgRgOPcRIX8KV\njiniSEEQBKHbiOHQQ7g8DqUK0iKOFARBELqMGA49xEh/0tI4SB0HQRAEYSUQw6GHGOlL2FkVEqoQ\nBEEQVgAxHHqI4b4klksV5EsV03CQUIUgCILQZcRw6CHW9dtFoPKlqmRVCIIgCF1HDIceQverOHku\nDwASqhAEQRC6jhgOPYQuO33y3DIAIC0FoARBEIQuI1eeHkI3ujo5Jx4HQRAEYWUQw6GH0B6H43Om\nx0HEkYIgCEK3EcOhhxi2NA46VCGGgyAIgtBdxHDoIRJGDNl0HCckVCEIgiCsEGI49BgjfUnL4yCh\nCkEQBKHbiOHQY4z0JTC9aJadFo+DIAiC0G3EcOgxdGYFIOmYgiAIQveRK0+PoTMrABFHCoIgCN1H\nDIcew2k4SKhCEARB6DZiOPQYuuw0IOJIQRAEofuI4dBjuDQOcTEcBEEQhO4ihkOPoUMVqXgMsRit\n8NYIgiAI5xsdNRyI6I1E9AwRHSKiO30+JyL6hPr8MSK6utmyRLSOiL5JRAfV84ia/k4ietTxqBLR\nLvXZg2pd+rOJTv7uTjLSb4YqJEwhCIIgrAQdMxyIyADwSQA3A9gJ4FYi2umZ7WYAO9TjDgCfCrDs\nnQAeYOYdAB5Q78HM9zLzLmbeBeA2AEeY+VHHd71Tf87MZ9r/i7uD9jhImEIQBEFYCTrpcbgGwCFm\nPszMRQBfBLDPM88+AJ9jkx8AGCaijU2W3QfgHvX6HgC3+Hz3rWqZNYc2HMTjIAiCIKwEnTQcNgOY\ndLx/QU0LMk+jZdcz80n1+hSA9T7f/XYAX/BMu0eFKX6TiHpWHKAbXUkNB0EQBGEl6GlxJDMzAHZO\nI6JrAeSY+XHH5Hcy8xUAXqket/mtj4juIKIDRHRgamqqU5vdEumEgb6kgYxUjRQEQRBWgE5efY4D\n2Op4v0VNCzJPo2VPq3AG1LNXr/AOeLwNzHxcPS8A+CuYoZAamPluZt7DzHvGx8cb/riVZKQvKaEK\nQRAEYUXopOHwMIAdRLSdiJIwL+j7PfPsB/BulV2xF8A5FYZotOx+ALer17cD+JpeGRHFALwNDn0D\nEcWJaEy9TgB4MwCnN6Ln2D7Wj41DmZXeDEEQBOE8JN6pFTNzmYg+DOB+AAaAzzLzE0T0fvX5XQDu\nA/AmAIcA5AC8t9GyatUfA/BlInofgKMwDQXNDQAmmfmwY1oKwP3KaDAAfAvAZzrxm7vFp2/bDUNq\nOAiCIAgrAJkyAcHLnj17+MCBAyu9GYIgCILQFYjoEWbe02w+UdgJgiAIghAYMRwEQRAEQQiMGA6C\nIAiCIARGDAdBEARBEAIjhoMgCIIgCIERw0EQBEEQhMCI4SAIgiAIQmDEcBAEQRAEITBiOAiCIAiC\nEBgxHARBEARBCIyUnK4DEU3B7IXRLsYATLdxfecjMoatI2PYOjKG7UHGsXXaPYbbmLlpa2gxHLoE\nER0IUgNcqI+MYevIGLaOjGF7kHFsnZUaQwlVCIIgCIIQGDEcBEEQBEEIjBgO3ePuld6ANYCMYevI\nGLaOjGF7kHFsnRUZQ9E4CIIgCIIQGPE4CIIgCIIQGDEcOgwRvZGIniGiQ0R050pvz0pARFuJ6NtE\n9CQRPUFE/1lNX0dE3ySig+p5xLHMR9SYPUNEb3BM301EP1OffYKISE1PEdGX1PQfEtGFjmVuV99x\nkIhu794vbz9EZBDRT4jo79V7GcMQENEwEf0NET1NRE8R0XUyhuEgol9Wx/HjRPQFIkrLGDaHiD5L\nRGeI6HHHtBUdNyLaruY9pJZNBvoxzCyPDj0AGACeA3ARgCSAnwLYudLbtQLjsBHA1ep1FsCzAHYC\n+H0Ad6rpdwL4PfV6pxqrFIDtagwN9dmPAOwFQAD+EcDNavoHAdylXr8DwJfU63UADqvnEfV6ZKXH\npIWx/BUAfwXg79V7GcNw43cPgF9Sr5MAhmUMQ43fZgBHAGTU+y8DeI+MYaCxuwHA1QAed0xb0XFT\n/9871Ou7AHwg0G9Z6cFcyw8A1wG43/H+IwA+stLbtdIPAF8D8HoAzwDYqKZtBPCM3zgBuF+N5UYA\nTzum3wrg08551Os4zKIo5JxHffZpALeu9BhEHLctAB4A8FrYhoOMYfDxG4J50SPPdBnD4GO4GcCk\nugjFAfw9gJtkDAOP34VwGw4rNm7qs2kAcTXddb1q9JBQRWfRB5nmBTXtvEW5z64C8EMA65n5pPro\nFID16nW9cdusXnunu5Zh5jKAcwBGG6yrF/k4gF8HUHVMkzEMznYAUwD+QoV7/pyI+iFjGBhmPg7g\nDwEcA3ASwDlm/gZkDKOykuM2CmBOzetdV0PEcBC6BhENAPhbAP+Fmeedn7Fp8kqKTx2I6M0AzjDz\nI/XmkTFsShymq/hTzHwVgCWY7mELGcPGqBj8PphG2CYA/UT0Luc8MobR6KVxE8OhsxwHsNXxfoua\ndt5BRAmYRsO9zPwVNfk0EW1Un28EcEZNrzdux9Vr73TXMkQUh+mWnmmwrl7jFQB+joieB/BFAK8l\nov8LGcMwvADgBWb+oXr/NzANCRnD4LwOwBFmnmLmEoCvAHg5ZAyjspLjNgNgWM3rXVdDxHDoLA8D\n2KGUq0mYgpX9K7xNXUepfv8PgKeY+Y8dH+0HoBW+t8PUPujp71Aq4e0AdgD4kXLpzRPRXrXOd3uW\n0et6K4B/Vhb8/QBuIqIRdbd0k5rWUzDzR5h5CzNfCHM/+mdmfhdkDAPDzKcATBLRpWrSjQCehIxh\nGI4B2EtEfeq33wjgKcgYRmXFxk199m01r/f7G7PSYpG1/gDwJphZBM8B+I2V3p4VGoPrYbrgHgPw\nqHq8CWaM7QEABwF8C8A6xzK/ocbsGSjVsJq+B8Dj6rM/hV3ELA3grwEcgqk6vsixzC+q6YcAvHel\nx6MN4/lq2OJIGcNwY7cLwAG1L/4dTJW5jGG4MfxdAE+r3/95mMp/GcPm4/YFmLqQEkzv1/tWetxg\nZvz9SE3/awCpIL9FKkcKgiAIghAYCVUIgiAIghAYMRwEQRAEQQiMGA6CIAiCIARGDAdBEARBEAIj\nhoMgCIIgCIERw0EQhEgQ0YXOTn9tWuctRPRb6vVfEtFbmy3jWPY9RLTJ8f6LRLSjndsnCIIYDoIg\nrBCOinVOfh3An0Vc5XtglkHWfEqtTxCENiKGgyAIrRAnonuJ6Cki+hsi6gMAIvotInqYiB4nortV\nlTsQ0YNE9HEiOgDgPztXRESXACgw87T3S4jofyoPhEFEu4noO0T0CBHdT0QblS2MzUEAAAIHSURB\nVGdiD4B7iehRIsoA+B6A19UxUARBiIgYDoIgtMKlAP6MmS8HMA/gg2r6nzLzy5j5xQAyAN7sWCbJ\nzHuY+Y8863oFgB97v4CI/gDAOID3wjxn/X8A3srMuwF8FsD/Yua/gVkR8p3MvIuZl5m5CrMi3pXt\n+rGCIIjhIAhCa0wy87+o1/8XZnlxAHgNEf2QiH4G4LUArnAs86U669oIs+21k98EMMTM72ezzO2l\nAF4M4JtE9CiA/w530x8vZ+AOXwiC0CLiwhMEoRW8NeuZiNIwdQp7mHmSiH4HZh19zVKddS3D7Ojn\n5GEAu4loHTPPAiAATzDzdQG3L63WKwhCmxCPgyAIrXABEemL+L8D8H3YRsI0EQ3A7r7XjKcAXOyZ\n9k8APgbgH4goC7Phz7j+TiJKEJH2ZiwAyHqWvwRmQyBBENqEGA6CILTCMwA+RERPwew0+SlmngPw\nGZgX7Ptheg2C8F0AV2khpYaZ/1qtbz8AA6Yh8ntE9FOYnVZfrmb9SwB3aXEkEa0HsMxmO21BENqE\ndMcUBGHVQER/AuDrzPytNqzrlwHMM/P/aX3LBEHQiMdBEITVxP8G0Nemdc0BuKdN6xIEQSEeB0EQ\nBEEQAiMeB0EQBEEQAiOGgyAIgiAIgRHDQRAEQRCEwIjhIAiCIAhCYMRwEARBEAQhMGI4CIIgCIIQ\nmP8fAxszqDdoHlkAAAAASUVORK5CYII=\n", "text/plain": [ - "((),)" + "" ] }, - "execution_count": 36, + "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "myrecctrl.acquisition.setpoints" + "plot = qc.MatPlot(data7.my_controller_rec_raw_output)\n", + "plot.fig" ] }, { From be1568291835cf47f9000ae5b7ac3613f298a062 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Wed, 8 Mar 2017 14:41:48 +0100 Subject: [PATCH 163/180] Revert "Fix: Simplify memory allocation in ATS driver" This reverts commit f26977f1bc08b425269dc01dd76bd10512c75542. --- qcodes/instrument_drivers/AlazarTech/ATS.py | 25 +++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/qcodes/instrument_drivers/AlazarTech/ATS.py b/qcodes/instrument_drivers/AlazarTech/ATS.py index e041b9ce1758..a4542ffde3a1 100644 --- a/qcodes/instrument_drivers/AlazarTech/ATS.py +++ b/qcodes/instrument_drivers/AlazarTech/ATS.py @@ -997,13 +997,22 @@ def __init__(self, c_sample_type, size_bytes): self._allocated = True self.addr = None + if os.name == 'nt': + MEM_COMMIT = 0x1000 + PAGE_READWRITE = 0x4 + ctypes.windll.kernel32.VirtualAlloc.argtypes = [ctypes.c_void_p, ctypes.c_long, ctypes.c_long, ctypes.c_long] + ctypes.windll.kernel32.VirtualAlloc.restype = ctypes.c_void_p + self.addr = ctypes.windll.kernel32.VirtualAlloc( + 0, ctypes.c_long(size_bytes), MEM_COMMIT, PAGE_READWRITE) + else: + self._allocated = False + raise Exception("Unsupported OS") - ctypes_array_type = c_sample_type * (size_bytes // bytes_per_sample) # PyCharm deducts the wrong type - # This is not an int but a PyCArrayType which is callable. Not sure how to annotate this correctly - ctypes_array = ctypes_array_type() + ctypes_array = (c_sample_type * + (size_bytes // bytes_per_sample)).from_address(self.addr) self.buffer = np.frombuffer(ctypes_array, dtype=npSampleType) self.ctypes_buffer = ctypes_array - self.addr = ctypes.addressof(self.ctypes_buffer) + pointer, read_only_flag = self.buffer.__array_interface__['data'] def free_mem(self): """ @@ -1011,6 +1020,14 @@ def free_mem(self): """ self._allocated = False + if os.name == 'nt': + MEM_RELEASE = 0x8000 + ctypes.windll.kernel32.VirtualFree.argtypes = [ctypes.c_void_p, ctypes.c_long, ctypes.c_long] + ctypes.windll.kernel32.VirtualFree.restype = ctypes.c_int + ctypes.windll.kernel32.VirtualFree(ctypes.c_void_p(self.addr), 0, MEM_RELEASE); + else: + self._allocated = True + raise Exception("Unsupported OS") def __del__(self): """ From 98c7b661a28b9463507108dfb82848750b6a37c0 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Wed, 8 Mar 2017 17:32:16 +0100 Subject: [PATCH 164/180] Docs: update example notebook --- ...e with Alazar ATS9360 new controller.ipynb | 4436 ++++++++++++++++- 1 file changed, 4285 insertions(+), 151 deletions(-) diff --git a/docs/examples/Qcodes example with Alazar ATS9360 new controller.ipynb b/docs/examples/Qcodes example with Alazar ATS9360 new controller.ipynb index b77761ed3ec0..b760d68435d0 100644 --- a/docs/examples/Qcodes example with Alazar ATS9360 new controller.ipynb +++ b/docs/examples/Qcodes example with Alazar ATS9360 new controller.ipynb @@ -13,6 +13,17 @@ { "cell_type": "code", "execution_count": 1, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "%matplotlib notebook" + ] + }, + { + "cell_type": "code", + "execution_count": 2, "metadata": { "collapsed": false, "deletable": true, @@ -33,9 +44,6 @@ "import qcodes.instrument_drivers.AlazarTech.ATS9360 as ATSdriver\n", "from qcodes.instrument_drivers.AlazarTech.acq_controllers import ATS9360Controller\n", "from qcodes.station import Station\n", - "#import qcodes.instrument_drivers.AlazarTech.samp_controller as samp_acq_contr\n", - "#import qcodes.instrument_drivers.AlazarTech.ave_controller_test as ave_acq_controller\n", - "#import qcodes.instrument_drivers.AlazarTech.rec_controller_test as record_acq_controller\n", "\n", "import logging\n", "# logging.basicConfig(filename='example.log',level=logging.INFO)\n", @@ -55,13 +63,29 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 3, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING:root:`units` is deprecated for the `Parameter` class, use `unit` instead. \n", + "WARNING:root:`units` is deprecated for the `Parameter` class, use `unit` instead. \n", + "WARNING:root:`units` is deprecated for the `Parameter` class, use `unit` instead. \n", + "WARNING:root:`units` is deprecated for the `Parameter` class, use `unit` instead. \n", + "WARNING:root:`units` is deprecated for the `Parameter` class, use `unit` instead. \n", + "WARNING:root:`units` is deprecated for the `Parameter` class, use `unit` instead. \n", + "WARNING:root:`units` is deprecated for the `Parameter` class, use `unit` instead. \n", + "WARNING:root:`units` is deprecated for the `Parameter` class, use `unit` instead. \n", + "WARNING:root:`units` is deprecated for the `Parameter` class, use `unit` instead. \n", + "WARNING:root:`units` is deprecated for the `Parameter` class, use `unit` instead. \n" + ] + }, { "data": { "text/plain": [ @@ -81,7 +105,7 @@ " 'vendor': 'AlazarTech'}" ] }, - "execution_count": 2, + "execution_count": 3, "metadata": {}, "output_type": "execute_result" } @@ -95,7 +119,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 4, "metadata": { "collapsed": false }, @@ -103,10 +127,10 @@ { "data": { "text/plain": [ - "812" + "944" ] }, - "execution_count": 3, + "execution_count": 4, "metadata": {}, "output_type": "execute_result" } @@ -117,7 +141,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 23, "metadata": { "collapsed": false, "scrolled": false @@ -134,9 +158,9 @@ " impedance=[50,50],\n", " trigger_operation='TRIG_ENGINE_OP_J',\n", " trigger_engine1='TRIG_ENGINE_J',\n", - " trigger_source1='CHANNEL_A',\n", + " trigger_source1='EXTERNAL',\n", " trigger_slope1='TRIG_SLOPE_POSITIVE',\n", - " trigger_level1=128,\n", + " trigger_level1=160,\n", " trigger_engine2='TRIG_ENGINE_K',\n", " trigger_source2='DISABLE',\n", " trigger_slope2='TRIG_SLOPE_POSITIVE',\n", @@ -144,7 +168,7 @@ " external_trigger_coupling='DC',\n", " external_trigger_range='ETR_2V5',\n", " trigger_delay=0,\n", - " timeout_ticks=1,\n", + " timeout_ticks=0,\n", " aux_io_mode='AUX_IN_AUXILIARY', # AUX_IN_TRIGGER_ENABLE for seq mode on\n", " aux_io_param='NONE' # TRIG_SLOPE_POSITIVE for seq mode on\n", " )" @@ -164,7 +188,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 6, "metadata": { "collapsed": false, "deletable": true, @@ -189,11 +213,19 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 7, "metadata": { "collapsed": false }, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING:root:Error getting or interpreting *IDN?: ''\n" + ] + } + ], "source": [ "station = qc.Station(alazar, myctrl)" ] @@ -207,20 +239,20 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [], "source": [ "myctrl.int_delay(2e-7)\n", - "myctrl.int_time(2e-6)\n", - "myctrl.num_avg(100)" + "myctrl.int_time(3.1e-6)\n", + "myctrl.num_avg(1000)" ] }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 9, "metadata": { "collapsed": false }, @@ -229,8 +261,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "100 records per buffer set by num_avg\n", - "1152 samples per record set by int_time and int_delay\n" + "1000 records per buffer set by num_avg\n", + "1664 samples per record set by int_time and int_delay\n" ] } ], @@ -248,7 +280,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 10, "metadata": { "collapsed": false }, @@ -259,41 +291,818 @@ "text": [ "DataSet:\n", " mode = DataMode.LOCAL\n", - " location = 'data/2017-03-07/#030_{name}_12-36-03'\n", + " location = 'data/2017-03-08/#059_{name}_15-55-30'\n", " | | | \n", - " Setpoint | time_set | time | (1152,)\n", - " Measured | my_controller_raw_output | raw_output | (1152,)\n", - "acquired at 2017-03-07 12:36:03\n" + " Setpoint | time_set | time | (1664,)\n", + " Measured | my_controller_raw_output | raw_output | (1664,)\n", + "acquired at 2017-03-08 15:55:31\n" ] } ], "source": [ "# Measure this \n", - "data1 = qc.Measure(myctrl.acquisition).run(station=station)\n" + "data1 = qc.Measure(myctrl.acquisition).run()\n" ] }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 11, "metadata": { "collapsed": false }, "outputs": [ { "data": { - "image/png": "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\n", + "application/javascript": [ + "/* Put everything inside the global mpl namespace */\n", + "window.mpl = {};\n", + "\n", + "\n", + "mpl.get_websocket_type = function() {\n", + " if (typeof(WebSocket) !== 'undefined') {\n", + " return WebSocket;\n", + " } else if (typeof(MozWebSocket) !== 'undefined') {\n", + " return MozWebSocket;\n", + " } else {\n", + " alert('Your browser does not have WebSocket support.' +\n", + " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", + " 'Firefox 4 and 5 are also supported but you ' +\n", + " 'have to enable WebSockets in about:config.');\n", + " };\n", + "}\n", + "\n", + "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", + " this.id = figure_id;\n", + "\n", + " this.ws = websocket;\n", + "\n", + " this.supports_binary = (this.ws.binaryType != undefined);\n", + "\n", + " if (!this.supports_binary) {\n", + " var warnings = document.getElementById(\"mpl-warnings\");\n", + " if (warnings) {\n", + " warnings.style.display = 'block';\n", + " warnings.textContent = (\n", + " \"This browser does not support binary websocket messages. \" +\n", + " \"Performance may be slow.\");\n", + " }\n", + " }\n", + "\n", + " this.imageObj = new Image();\n", + "\n", + " this.context = undefined;\n", + " this.message = undefined;\n", + " this.canvas = undefined;\n", + " this.rubberband_canvas = undefined;\n", + " this.rubberband_context = undefined;\n", + " this.format_dropdown = undefined;\n", + "\n", + " this.image_mode = 'full';\n", + "\n", + " this.root = $('
');\n", + " this._root_extra_style(this.root)\n", + " this.root.attr('style', 'display: inline-block');\n", + "\n", + " $(parent_element).append(this.root);\n", + "\n", + " this._init_header(this);\n", + " this._init_canvas(this);\n", + " this._init_toolbar(this);\n", + "\n", + " var fig = this;\n", + "\n", + " this.waiting = false;\n", + "\n", + " this.ws.onopen = function () {\n", + " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", + " fig.send_message(\"send_image_mode\", {});\n", + " if (mpl.ratio != 1) {\n", + " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", + " }\n", + " fig.send_message(\"refresh\", {});\n", + " }\n", + "\n", + " this.imageObj.onload = function() {\n", + " if (fig.image_mode == 'full') {\n", + " // Full images could contain transparency (where diff images\n", + " // almost always do), so we need to clear the canvas so that\n", + " // there is no ghosting.\n", + " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", + " }\n", + " fig.context.drawImage(fig.imageObj, 0, 0);\n", + " };\n", + "\n", + " this.imageObj.onunload = function() {\n", + " this.ws.close();\n", + " }\n", + "\n", + " this.ws.onmessage = this._make_on_message_function(this);\n", + "\n", + " this.ondownload = ondownload;\n", + "}\n", + "\n", + "mpl.figure.prototype._init_header = function() {\n", + " var titlebar = $(\n", + " '
');\n", + " var titletext = $(\n", + " '
');\n", + " titlebar.append(titletext)\n", + " this.root.append(titlebar);\n", + " this.header = titletext[0];\n", + "}\n", + "\n", + "\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._init_canvas = function() {\n", + " var fig = this;\n", + "\n", + " var canvas_div = $('
');\n", + "\n", + " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", + "\n", + " function canvas_keyboard_event(event) {\n", + " return fig.key_event(event, event['data']);\n", + " }\n", + "\n", + " canvas_div.keydown('key_press', canvas_keyboard_event);\n", + " canvas_div.keyup('key_release', canvas_keyboard_event);\n", + " this.canvas_div = canvas_div\n", + " this._canvas_extra_style(canvas_div)\n", + " this.root.append(canvas_div);\n", + "\n", + " var canvas = $('');\n", + " canvas.addClass('mpl-canvas');\n", + " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", + "\n", + " this.canvas = canvas[0];\n", + " this.context = canvas[0].getContext(\"2d\");\n", + "\n", + " var backingStore = this.context.backingStorePixelRatio ||\n", + "\tthis.context.webkitBackingStorePixelRatio ||\n", + "\tthis.context.mozBackingStorePixelRatio ||\n", + "\tthis.context.msBackingStorePixelRatio ||\n", + "\tthis.context.oBackingStorePixelRatio ||\n", + "\tthis.context.backingStorePixelRatio || 1;\n", + "\n", + " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", + "\n", + " var rubberband = $('');\n", + " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", + "\n", + " var pass_mouse_events = true;\n", + "\n", + " canvas_div.resizable({\n", + " start: function(event, ui) {\n", + " pass_mouse_events = false;\n", + " },\n", + " resize: function(event, ui) {\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " stop: function(event, ui) {\n", + " pass_mouse_events = true;\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " });\n", + "\n", + " function mouse_event_fn(event) {\n", + " if (pass_mouse_events)\n", + " return fig.mouse_event(event, event['data']);\n", + " }\n", + "\n", + " rubberband.mousedown('button_press', mouse_event_fn);\n", + " rubberband.mouseup('button_release', mouse_event_fn);\n", + " // Throttle sequential mouse events to 1 every 20ms.\n", + " rubberband.mousemove('motion_notify', mouse_event_fn);\n", + "\n", + " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", + " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", + "\n", + " canvas_div.on(\"wheel\", function (event) {\n", + " event = event.originalEvent;\n", + " event['data'] = 'scroll'\n", + " if (event.deltaY < 0) {\n", + " event.step = 1;\n", + " } else {\n", + " event.step = -1;\n", + " }\n", + " mouse_event_fn(event);\n", + " });\n", + "\n", + " canvas_div.append(canvas);\n", + " canvas_div.append(rubberband);\n", + "\n", + " this.rubberband = rubberband;\n", + " this.rubberband_canvas = rubberband[0];\n", + " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", + " this.rubberband_context.strokeStyle = \"#000000\";\n", + "\n", + " this._resize_canvas = function(width, height) {\n", + " // Keep the size of the canvas, canvas container, and rubber band\n", + " // canvas in synch.\n", + " canvas_div.css('width', width)\n", + " canvas_div.css('height', height)\n", + "\n", + " canvas.attr('width', width * mpl.ratio);\n", + " canvas.attr('height', height * mpl.ratio);\n", + " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", + "\n", + " rubberband.attr('width', width);\n", + " rubberband.attr('height', height);\n", + " }\n", + "\n", + " // Set the figure to an initial 600x600px, this will subsequently be updated\n", + " // upon first draw.\n", + " this._resize_canvas(600, 600);\n", + "\n", + " // Disable right mouse context menu.\n", + " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", + " return false;\n", + " });\n", + "\n", + " function set_focus () {\n", + " canvas.focus();\n", + " canvas_div.focus();\n", + " }\n", + "\n", + " window.setTimeout(set_focus, 100);\n", + "}\n", + "\n", + "mpl.figure.prototype._init_toolbar = function() {\n", + " var fig = this;\n", + "\n", + " var nav_element = $('
')\n", + " nav_element.attr('style', 'width: 100%');\n", + " this.root.append(nav_element);\n", + "\n", + " // Define a callback function for later on.\n", + " function toolbar_event(event) {\n", + " return fig.toolbar_button_onclick(event['data']);\n", + " }\n", + " function toolbar_mouse_event(event) {\n", + " return fig.toolbar_button_onmouseover(event['data']);\n", + " }\n", + "\n", + " for(var toolbar_ind in mpl.toolbar_items) {\n", + " var name = mpl.toolbar_items[toolbar_ind][0];\n", + " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", + " var image = mpl.toolbar_items[toolbar_ind][2];\n", + " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", + "\n", + " if (!name) {\n", + " // put a spacer in here.\n", + " continue;\n", + " }\n", + " var button = $('');\n", + " button.click(method_name, toolbar_event);\n", + " button.mouseover(tooltip, toolbar_mouse_event);\n", + " nav_element.append(button);\n", + " }\n", + "\n", + " // Add the status bar.\n", + " var status_bar = $('');\n", + " nav_element.append(status_bar);\n", + " this.message = status_bar[0];\n", + "\n", + " // Add the close button to the window.\n", + " var buttongrp = $('
');\n", + " var button = $('');\n", + " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", + " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", + " buttongrp.append(button);\n", + " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", + " titlebar.prepend(buttongrp);\n", + "}\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(el){\n", + " var fig = this\n", + " el.on(\"remove\", function(){\n", + "\tfig.close_ws(fig, {});\n", + " });\n", + "}\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(el){\n", + " // this is important to make the div 'focusable\n", + " el.attr('tabindex', 0)\n", + " // reach out to IPython and tell the keyboard manager to turn it's self\n", + " // off when our div gets focus\n", + "\n", + " // location in version 3\n", + " if (IPython.notebook.keyboard_manager) {\n", + " IPython.notebook.keyboard_manager.register_events(el);\n", + " }\n", + " else {\n", + " // location in version 2\n", + " IPython.keyboard_manager.register_events(el);\n", + " }\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._key_event_extra = function(event, name) {\n", + " var manager = IPython.notebook.keyboard_manager;\n", + " if (!manager)\n", + " manager = IPython.keyboard_manager;\n", + "\n", + " // Check for shift+enter\n", + " if (event.shiftKey && event.which == 13) {\n", + " this.canvas_div.blur();\n", + " // select the cell after this one\n", + " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", + " IPython.notebook.select(index + 1);\n", + " }\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_save = function(fig, msg) {\n", + " fig.ondownload(fig, null);\n", + "}\n", + "\n", + "\n", + "mpl.find_output_cell = function(html_output) {\n", + " // Return the cell and output element which can be found *uniquely* in the notebook.\n", + " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", + " // IPython event is triggered only after the cells have been serialised, which for\n", + " // our purposes (turning an active figure into a static one), is too late.\n", + " var cells = IPython.notebook.get_cells();\n", + " var ncells = cells.length;\n", + " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", + " data = data.data;\n", + " }\n", + " if (data['text/html'] == html_output) {\n", + " return [cell, data, j];\n", + " }\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + "// Register the function which deals with the matplotlib target/channel.\n", + "// The kernel may be null if the page has been refreshed.\n", + "if (IPython.notebook.kernel != null) {\n", + " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", + "}\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], "text/plain": [ - "" + "" ] }, - "execution_count": 13, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 47, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "plot = qc.MatPlot(data2.my_controller_demod_freq_0_mag)\n", - "plot.fig" + "plot = qc.MatPlot()\n", + "plot.add(data2.my_controller_demod_freq_0_mag)\n", + "plot.fig.axes[0].legend()" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { - "collapsed": false + "collapsed": false, + "scrolled": false }, "outputs": [ { "data": { - "image/png": "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\n", + "application/javascript": [ + "/* Put everything inside the global mpl namespace */\n", + "window.mpl = {};\n", + "\n", + "\n", + "mpl.get_websocket_type = function() {\n", + " if (typeof(WebSocket) !== 'undefined') {\n", + " return WebSocket;\n", + " } else if (typeof(MozWebSocket) !== 'undefined') {\n", + " return MozWebSocket;\n", + " } else {\n", + " alert('Your browser does not have WebSocket support.' +\n", + " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", + " 'Firefox 4 and 5 are also supported but you ' +\n", + " 'have to enable WebSockets in about:config.');\n", + " };\n", + "}\n", + "\n", + "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", + " this.id = figure_id;\n", + "\n", + " this.ws = websocket;\n", + "\n", + " this.supports_binary = (this.ws.binaryType != undefined);\n", + "\n", + " if (!this.supports_binary) {\n", + " var warnings = document.getElementById(\"mpl-warnings\");\n", + " if (warnings) {\n", + " warnings.style.display = 'block';\n", + " warnings.textContent = (\n", + " \"This browser does not support binary websocket messages. \" +\n", + " \"Performance may be slow.\");\n", + " }\n", + " }\n", + "\n", + " this.imageObj = new Image();\n", + "\n", + " this.context = undefined;\n", + " this.message = undefined;\n", + " this.canvas = undefined;\n", + " this.rubberband_canvas = undefined;\n", + " this.rubberband_context = undefined;\n", + " this.format_dropdown = undefined;\n", + "\n", + " this.image_mode = 'full';\n", + "\n", + " this.root = $('
');\n", + " this._root_extra_style(this.root)\n", + " this.root.attr('style', 'display: inline-block');\n", + "\n", + " $(parent_element).append(this.root);\n", + "\n", + " this._init_header(this);\n", + " this._init_canvas(this);\n", + " this._init_toolbar(this);\n", + "\n", + " var fig = this;\n", + "\n", + " this.waiting = false;\n", + "\n", + " this.ws.onopen = function () {\n", + " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", + " fig.send_message(\"send_image_mode\", {});\n", + " if (mpl.ratio != 1) {\n", + " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", + " }\n", + " fig.send_message(\"refresh\", {});\n", + " }\n", + "\n", + " this.imageObj.onload = function() {\n", + " if (fig.image_mode == 'full') {\n", + " // Full images could contain transparency (where diff images\n", + " // almost always do), so we need to clear the canvas so that\n", + " // there is no ghosting.\n", + " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", + " }\n", + " fig.context.drawImage(fig.imageObj, 0, 0);\n", + " };\n", + "\n", + " this.imageObj.onunload = function() {\n", + " this.ws.close();\n", + " }\n", + "\n", + " this.ws.onmessage = this._make_on_message_function(this);\n", + "\n", + " this.ondownload = ondownload;\n", + "}\n", + "\n", + "mpl.figure.prototype._init_header = function() {\n", + " var titlebar = $(\n", + " '
');\n", + " var titletext = $(\n", + " '
');\n", + " titlebar.append(titletext)\n", + " this.root.append(titlebar);\n", + " this.header = titletext[0];\n", + "}\n", + "\n", + "\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._init_canvas = function() {\n", + " var fig = this;\n", + "\n", + " var canvas_div = $('
');\n", + "\n", + " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", + "\n", + " function canvas_keyboard_event(event) {\n", + " return fig.key_event(event, event['data']);\n", + " }\n", + "\n", + " canvas_div.keydown('key_press', canvas_keyboard_event);\n", + " canvas_div.keyup('key_release', canvas_keyboard_event);\n", + " this.canvas_div = canvas_div\n", + " this._canvas_extra_style(canvas_div)\n", + " this.root.append(canvas_div);\n", + "\n", + " var canvas = $('');\n", + " canvas.addClass('mpl-canvas');\n", + " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", + "\n", + " this.canvas = canvas[0];\n", + " this.context = canvas[0].getContext(\"2d\");\n", + "\n", + " var backingStore = this.context.backingStorePixelRatio ||\n", + "\tthis.context.webkitBackingStorePixelRatio ||\n", + "\tthis.context.mozBackingStorePixelRatio ||\n", + "\tthis.context.msBackingStorePixelRatio ||\n", + "\tthis.context.oBackingStorePixelRatio ||\n", + "\tthis.context.backingStorePixelRatio || 1;\n", + "\n", + " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", + "\n", + " var rubberband = $('');\n", + " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", + "\n", + " var pass_mouse_events = true;\n", + "\n", + " canvas_div.resizable({\n", + " start: function(event, ui) {\n", + " pass_mouse_events = false;\n", + " },\n", + " resize: function(event, ui) {\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " stop: function(event, ui) {\n", + " pass_mouse_events = true;\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " });\n", + "\n", + " function mouse_event_fn(event) {\n", + " if (pass_mouse_events)\n", + " return fig.mouse_event(event, event['data']);\n", + " }\n", + "\n", + " rubberband.mousedown('button_press', mouse_event_fn);\n", + " rubberband.mouseup('button_release', mouse_event_fn);\n", + " // Throttle sequential mouse events to 1 every 20ms.\n", + " rubberband.mousemove('motion_notify', mouse_event_fn);\n", + "\n", + " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", + " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", + "\n", + " canvas_div.on(\"wheel\", function (event) {\n", + " event = event.originalEvent;\n", + " event['data'] = 'scroll'\n", + " if (event.deltaY < 0) {\n", + " event.step = 1;\n", + " } else {\n", + " event.step = -1;\n", + " }\n", + " mouse_event_fn(event);\n", + " });\n", + "\n", + " canvas_div.append(canvas);\n", + " canvas_div.append(rubberband);\n", + "\n", + " this.rubberband = rubberband;\n", + " this.rubberband_canvas = rubberband[0];\n", + " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", + " this.rubberband_context.strokeStyle = \"#000000\";\n", + "\n", + " this._resize_canvas = function(width, height) {\n", + " // Keep the size of the canvas, canvas container, and rubber band\n", + " // canvas in synch.\n", + " canvas_div.css('width', width)\n", + " canvas_div.css('height', height)\n", + "\n", + " canvas.attr('width', width * mpl.ratio);\n", + " canvas.attr('height', height * mpl.ratio);\n", + " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", + "\n", + " rubberband.attr('width', width);\n", + " rubberband.attr('height', height);\n", + " }\n", + "\n", + " // Set the figure to an initial 600x600px, this will subsequently be updated\n", + " // upon first draw.\n", + " this._resize_canvas(600, 600);\n", + "\n", + " // Disable right mouse context menu.\n", + " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", + " return false;\n", + " });\n", + "\n", + " function set_focus () {\n", + " canvas.focus();\n", + " canvas_div.focus();\n", + " }\n", + "\n", + " window.setTimeout(set_focus, 100);\n", + "}\n", + "\n", + "mpl.figure.prototype._init_toolbar = function() {\n", + " var fig = this;\n", + "\n", + " var nav_element = $('
')\n", + " nav_element.attr('style', 'width: 100%');\n", + " this.root.append(nav_element);\n", + "\n", + " // Define a callback function for later on.\n", + " function toolbar_event(event) {\n", + " return fig.toolbar_button_onclick(event['data']);\n", + " }\n", + " function toolbar_mouse_event(event) {\n", + " return fig.toolbar_button_onmouseover(event['data']);\n", + " }\n", + "\n", + " for(var toolbar_ind in mpl.toolbar_items) {\n", + " var name = mpl.toolbar_items[toolbar_ind][0];\n", + " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", + " var image = mpl.toolbar_items[toolbar_ind][2];\n", + " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", + "\n", + " if (!name) {\n", + " // put a spacer in here.\n", + " continue;\n", + " }\n", + " var button = $('');\n", + " button.click(method_name, toolbar_event);\n", + " button.mouseover(tooltip, toolbar_mouse_event);\n", + " nav_element.append(button);\n", + " }\n", + "\n", + " // Add the status bar.\n", + " var status_bar = $('');\n", + " nav_element.append(status_bar);\n", + " this.message = status_bar[0];\n", + "\n", + " // Add the close button to the window.\n", + " var buttongrp = $('
');\n", + " var button = $('');\n", + " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", + " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", + " buttongrp.append(button);\n", + " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", + " titlebar.prepend(buttongrp);\n", + "}\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(el){\n", + " var fig = this\n", + " el.on(\"remove\", function(){\n", + "\tfig.close_ws(fig, {});\n", + " });\n", + "}\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(el){\n", + " // this is important to make the div 'focusable\n", + " el.attr('tabindex', 0)\n", + " // reach out to IPython and tell the keyboard manager to turn it's self\n", + " // off when our div gets focus\n", + "\n", + " // location in version 3\n", + " if (IPython.notebook.keyboard_manager) {\n", + " IPython.notebook.keyboard_manager.register_events(el);\n", + " }\n", + " else {\n", + " // location in version 2\n", + " IPython.keyboard_manager.register_events(el);\n", + " }\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._key_event_extra = function(event, name) {\n", + " var manager = IPython.notebook.keyboard_manager;\n", + " if (!manager)\n", + " manager = IPython.keyboard_manager;\n", + "\n", + " // Check for shift+enter\n", + " if (event.shiftKey && event.which == 13) {\n", + " this.canvas_div.blur();\n", + " // select the cell after this one\n", + " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", + " IPython.notebook.select(index + 1);\n", + " }\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_save = function(fig, msg) {\n", + " fig.ondownload(fig, null);\n", + "}\n", + "\n", + "\n", + "mpl.find_output_cell = function(html_output) {\n", + " // Return the cell and output element which can be found *uniquely* in the notebook.\n", + " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", + " // IPython event is triggered only after the cells have been serialised, which for\n", + " // our purposes (turning an active figure into a static one), is too late.\n", + " var cells = IPython.notebook.get_cells();\n", + " var ncells = cells.length;\n", + " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", + " data = data.data;\n", + " }\n", + " if (data['text/html'] == html_output) {\n", + " return [cell, data, j];\n", + " }\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + "// Register the function which deals with the matplotlib target/channel.\n", + "// The kernel may be null if the page has been refreshed.\n", + "if (IPython.notebook.kernel != null) {\n", + " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", + "}\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plot = qc.MatPlot(data6.my_controller_rec_demod_freq_5_mag)" ] }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 50, "metadata": { "collapsed": false }, "outputs": [ { "data": { - "image/png": "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\nmP8fAxszqDdoHlkAAAAASUVORK5CYII=\n", + "application/javascript": [ + "/* Put everything inside the global mpl namespace */\n", + "window.mpl = {};\n", + "\n", + "\n", + "mpl.get_websocket_type = function() {\n", + " if (typeof(WebSocket) !== 'undefined') {\n", + " return WebSocket;\n", + " } else if (typeof(MozWebSocket) !== 'undefined') {\n", + " return MozWebSocket;\n", + " } else {\n", + " alert('Your browser does not have WebSocket support.' +\n", + " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", + " 'Firefox 4 and 5 are also supported but you ' +\n", + " 'have to enable WebSockets in about:config.');\n", + " };\n", + "}\n", + "\n", + "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", + " this.id = figure_id;\n", + "\n", + " this.ws = websocket;\n", + "\n", + " this.supports_binary = (this.ws.binaryType != undefined);\n", + "\n", + " if (!this.supports_binary) {\n", + " var warnings = document.getElementById(\"mpl-warnings\");\n", + " if (warnings) {\n", + " warnings.style.display = 'block';\n", + " warnings.textContent = (\n", + " \"This browser does not support binary websocket messages. \" +\n", + " \"Performance may be slow.\");\n", + " }\n", + " }\n", + "\n", + " this.imageObj = new Image();\n", + "\n", + " this.context = undefined;\n", + " this.message = undefined;\n", + " this.canvas = undefined;\n", + " this.rubberband_canvas = undefined;\n", + " this.rubberband_context = undefined;\n", + " this.format_dropdown = undefined;\n", + "\n", + " this.image_mode = 'full';\n", + "\n", + " this.root = $('
');\n", + " this._root_extra_style(this.root)\n", + " this.root.attr('style', 'display: inline-block');\n", + "\n", + " $(parent_element).append(this.root);\n", + "\n", + " this._init_header(this);\n", + " this._init_canvas(this);\n", + " this._init_toolbar(this);\n", + "\n", + " var fig = this;\n", + "\n", + " this.waiting = false;\n", + "\n", + " this.ws.onopen = function () {\n", + " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", + " fig.send_message(\"send_image_mode\", {});\n", + " if (mpl.ratio != 1) {\n", + " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", + " }\n", + " fig.send_message(\"refresh\", {});\n", + " }\n", + "\n", + " this.imageObj.onload = function() {\n", + " if (fig.image_mode == 'full') {\n", + " // Full images could contain transparency (where diff images\n", + " // almost always do), so we need to clear the canvas so that\n", + " // there is no ghosting.\n", + " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", + " }\n", + " fig.context.drawImage(fig.imageObj, 0, 0);\n", + " };\n", + "\n", + " this.imageObj.onunload = function() {\n", + " this.ws.close();\n", + " }\n", + "\n", + " this.ws.onmessage = this._make_on_message_function(this);\n", + "\n", + " this.ondownload = ondownload;\n", + "}\n", + "\n", + "mpl.figure.prototype._init_header = function() {\n", + " var titlebar = $(\n", + " '
');\n", + " var titletext = $(\n", + " '
');\n", + " titlebar.append(titletext)\n", + " this.root.append(titlebar);\n", + " this.header = titletext[0];\n", + "}\n", + "\n", + "\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._init_canvas = function() {\n", + " var fig = this;\n", + "\n", + " var canvas_div = $('
');\n", + "\n", + " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", + "\n", + " function canvas_keyboard_event(event) {\n", + " return fig.key_event(event, event['data']);\n", + " }\n", + "\n", + " canvas_div.keydown('key_press', canvas_keyboard_event);\n", + " canvas_div.keyup('key_release', canvas_keyboard_event);\n", + " this.canvas_div = canvas_div\n", + " this._canvas_extra_style(canvas_div)\n", + " this.root.append(canvas_div);\n", + "\n", + " var canvas = $('');\n", + " canvas.addClass('mpl-canvas');\n", + " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", + "\n", + " this.canvas = canvas[0];\n", + " this.context = canvas[0].getContext(\"2d\");\n", + "\n", + " var backingStore = this.context.backingStorePixelRatio ||\n", + "\tthis.context.webkitBackingStorePixelRatio ||\n", + "\tthis.context.mozBackingStorePixelRatio ||\n", + "\tthis.context.msBackingStorePixelRatio ||\n", + "\tthis.context.oBackingStorePixelRatio ||\n", + "\tthis.context.backingStorePixelRatio || 1;\n", + "\n", + " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", + "\n", + " var rubberband = $('');\n", + " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", + "\n", + " var pass_mouse_events = true;\n", + "\n", + " canvas_div.resizable({\n", + " start: function(event, ui) {\n", + " pass_mouse_events = false;\n", + " },\n", + " resize: function(event, ui) {\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " stop: function(event, ui) {\n", + " pass_mouse_events = true;\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " });\n", + "\n", + " function mouse_event_fn(event) {\n", + " if (pass_mouse_events)\n", + " return fig.mouse_event(event, event['data']);\n", + " }\n", + "\n", + " rubberband.mousedown('button_press', mouse_event_fn);\n", + " rubberband.mouseup('button_release', mouse_event_fn);\n", + " // Throttle sequential mouse events to 1 every 20ms.\n", + " rubberband.mousemove('motion_notify', mouse_event_fn);\n", + "\n", + " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", + " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", + "\n", + " canvas_div.on(\"wheel\", function (event) {\n", + " event = event.originalEvent;\n", + " event['data'] = 'scroll'\n", + " if (event.deltaY < 0) {\n", + " event.step = 1;\n", + " } else {\n", + " event.step = -1;\n", + " }\n", + " mouse_event_fn(event);\n", + " });\n", + "\n", + " canvas_div.append(canvas);\n", + " canvas_div.append(rubberband);\n", + "\n", + " this.rubberband = rubberband;\n", + " this.rubberband_canvas = rubberband[0];\n", + " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", + " this.rubberband_context.strokeStyle = \"#000000\";\n", + "\n", + " this._resize_canvas = function(width, height) {\n", + " // Keep the size of the canvas, canvas container, and rubber band\n", + " // canvas in synch.\n", + " canvas_div.css('width', width)\n", + " canvas_div.css('height', height)\n", + "\n", + " canvas.attr('width', width * mpl.ratio);\n", + " canvas.attr('height', height * mpl.ratio);\n", + " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", + "\n", + " rubberband.attr('width', width);\n", + " rubberband.attr('height', height);\n", + " }\n", + "\n", + " // Set the figure to an initial 600x600px, this will subsequently be updated\n", + " // upon first draw.\n", + " this._resize_canvas(600, 600);\n", + "\n", + " // Disable right mouse context menu.\n", + " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", + " return false;\n", + " });\n", + "\n", + " function set_focus () {\n", + " canvas.focus();\n", + " canvas_div.focus();\n", + " }\n", + "\n", + " window.setTimeout(set_focus, 100);\n", + "}\n", + "\n", + "mpl.figure.prototype._init_toolbar = function() {\n", + " var fig = this;\n", + "\n", + " var nav_element = $('
')\n", + " nav_element.attr('style', 'width: 100%');\n", + " this.root.append(nav_element);\n", + "\n", + " // Define a callback function for later on.\n", + " function toolbar_event(event) {\n", + " return fig.toolbar_button_onclick(event['data']);\n", + " }\n", + " function toolbar_mouse_event(event) {\n", + " return fig.toolbar_button_onmouseover(event['data']);\n", + " }\n", + "\n", + " for(var toolbar_ind in mpl.toolbar_items) {\n", + " var name = mpl.toolbar_items[toolbar_ind][0];\n", + " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", + " var image = mpl.toolbar_items[toolbar_ind][2];\n", + " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", + "\n", + " if (!name) {\n", + " // put a spacer in here.\n", + " continue;\n", + " }\n", + " var button = $('