Source code for qtt.instrument_drivers.simulation_instruments

# -*- coding: utf-8 -*-
"""
Contains simulated instruments

"""
# %%
import numpy as np
import logging
import time

import qcodes


# %%


[docs]class SimulationDigitizer(qcodes.Instrument): def __init__(self, name, model=None, **kwargs): """ Class to provide virtual digitizer for simulation model """ super().__init__(name, **kwargs) self.current_sweep = None self.model = model self.add_parameter('sample_rate', set_cmd=None, initial_value=1e6) self.debug = {} self.verbose = 0
[docs] def measuresegment(self, waveform, channels=[0]): """ Measure a segment of data Args: waveform (object): waveform currently on AWG channels (list): channels to measure """ if self.verbose: print('{}: measuresegment: channels {}'.format(self.name, channels)) print(waveform) self._waveform = waveform waveform_type = waveform.get('type', None) if waveform_type != 'raw': sd1, sd2 = self.myhoneycomb() time.sleep(0.05) return [sd1, sd2][0:len(channels)] # Empty waveform, return random array with periodic signal. sample_rate = waveform.get('sample_rate', 1e6) period = waveform.get('period', 1e-3) number_samples = int(period * sample_rate) data = np.array([self.model.keithley1_amplitude() for ii in range(number_samples)]) noise_frequencies = [16e3, 100e3] # Hz for noise_frequency in noise_frequencies: noise = 0.01 * np.sin(noise_frequency * np.arange(data.size) / sample_rate) data += noise return ([data] * 2)[0:len(channels)]
[docs] def myhoneycomb(self, multiprocess=False, verbose=0): """ Args: multiprocess (bool): honeycomb simulation multiprocess verbose (int): verbosity of the method (0 == none) """ test_dot = self.model.ds waveform = self._waveform model = self.model sweepgates = waveform['sweepgates'] if isinstance(sweepgates, dict): sweepgates = [sweepgates] ndim = len(sweepgates) nn = waveform['resolution'] if isinstance(nn, float): nn = [nn] * ndim nnr = nn[::-1] # funny reverse ordering if verbose >= 2: print('myhoneycomb: start resolution %s' % (nn,)) if ndim != len(nn): raise Exception( 'number of sweep gates %d does not match resolution' % ndim) ng = len(model.gate_transform.sourcenames) test2Dparams = np.zeros((test_dot.ngates, *nnr)) gate2Dparams = np.zeros((ng, *nnr)) logging.info('honeycomb: %s' % (nn,)) rr = waveform['sweepranges'] wtype = waveform.get('type') v = model.gate_transform.sourcenames Vmatrix = np.eye(len(v)) if wtype == 'sweep_2D_virt' or wtype == 'sweep_2D': if wtype == 'sweep_2D_virt': sweepgatesx = sweepgates else: sweepgatesx = [{sweepgates[0]: 1}, {sweepgates[1]: 1}] iih = [v.index(s) for s in sweepgatesx[0]] iiv = [v.index(s) for s in sweepgatesx[1]] vh = list(sweepgatesx[0].values()) vv = list(sweepgatesx[1].values()) Vmatrix[0, :] = 0 Vmatrix[1, :] = 0 for idx, j in enumerate(iih): Vmatrix[0, j] = vh[idx] for idx, j in enumerate(iiv): Vmatrix[1, j] = vv[idx] inverseV = Vmatrix.T Vmatrix = None else: if isinstance(sweepgates[0], str): gatenames = [sweepgates[0]] else: gatenames = sweepgates[0].keys() ii = [v.index(s) for s in gatenames] idx = np.array((range(len(v)))) for i, j in enumerate(ii): idx[i], idx[j] = idx[j], idx[i] Vmatrix = Vmatrix[:, idx].copy() inverseV = np.linalg.inv(Vmatrix) sweeps = [] for ii in range(ndim): sweeps.append(np.linspace(-rr[ii] / 2, rr[ii] / 2, nn[ii])) meshgrid = np.meshgrid(*sweeps) mm = tuple([xv.flatten() for xv in meshgrid]) w = np.vstack((*mm, np.zeros((ng - ndim, mm[0].size)))) ww = inverseV.dot(w) for ii, p in enumerate(model.gate_transform.sourcenames): val = model.get_gate(p) if verbose >= 2: print('p %s: centre %s' % (p, val)) gate2Dparams[ii] = val for ii, p in enumerate(model.gate_transform.sourcenames): gate2Dparams[ii] += ww[ii].reshape(nnr) qq = model.gate_transform.transformGateScan( gate2Dparams.reshape((gate2Dparams.shape[0], -1))) # for debugging self.debug['gate2Dparams'] = gate2Dparams self.debug['qq'] = qq self.debug['inverseV'] = inverseV for ii in range(test_dot.ndots): test2Dparams[ii] = qq['det%d' % (ii + 1)].reshape(nnr) if ndim == 1: test2Dparams = test2Dparams.reshape( (test2Dparams.shape[0], test2Dparams.shape[1], 1)) # run the honeycomb simulation test_dot.simulate_honeycomb( test2Dparams, multiprocess=multiprocess, verbose=0) sd1 = (test_dot.hcgs * (model.sensingdot1_distance.reshape((1, 1, -1)))).sum(axis=-1) sd2 = (test_dot.hcgs * (model.sensingdot2_distance.reshape((1, 1, -1)))).sum(axis=-1) sd1 *= (1 / np.sum(model.sensingdot1_distance)) sd2 *= (1 / np.sum(model.sensingdot2_distance)) if verbose >= 2: print('sd1.shape %s' % (sd1.shape,)) print('sd2.shape %s' % (sd2.shape,)) if model.sdnoise > 0: sd1 += model.sdnoise * \ (np.random.rand(*test_dot.honeycomb.shape) - .5) sd2 += model.sdnoise * \ (np.random.rand(*test_dot.honeycomb.shape) - .5) if ndim == 1: sd1 = sd1.reshape((-1,)) sd2 = sd2.reshape((-1,)) # plt.figure(1000); plt.clf(); plt.plot(sd1, '.b'); plt.plot(sd2,'.r') self.debug['sd'] = sd1, sd2 return sd1, sd2
[docs]class SimulationAWG(qcodes.Instrument): def __init__(self, name, **kwargs): """ Class to provide an AWG object when using the simulation """ super().__init__(name, **kwargs) self.add_parameter('sampling_frequency', set_cmd=None, initial_value=1e6)
[docs] def awg_gate(self, name): return False
[docs] def sweep_gate(self, gate, sweeprange, period, width=.95, wave_name=None, delete=True): self.current_sweep = {'waveform': 'simulation_awg', 'gate': gate, 'sweeprange': sweeprange, 'type': 'sweep_gate', 'period': period, 'width': width, 'wave_name': wave_name} waveform = self.current_sweep waveform['resolution'] = [int(period * self.sampling_frequency())] waveform['sweepgates'] = [waveform['gate']] waveform['sweepranges'] = [waveform['sweeprange']] sweep_info = None self._waveform = waveform return waveform, sweep_info
[docs] def sweep_gate_virt(self, fast_sweep_gates, sweeprange, period, delete=None): self.current_sweep = {'waveform': 'simulation_awg', 'sweepgates': [fast_sweep_gates], 'sweeprange': sweeprange, 'type': 'sweep_1D_virt', 'period': period, } waveform = self.current_sweep waveform['resolution'] = [int(period * self.sampling_frequency())] waveform['sweepranges'] = [waveform['sweeprange']] self._waveform = waveform return waveform, None
[docs] def sweep_2D_virt(self, samp_freq, gates_horz, gates_vert, sweepranges, resolution): self.current_sweep = {'waveform': 'simulation_awg', 'sweepgates': [gates_horz, gates_vert], 'sweepranges': sweepranges, 'type': 'sweep_2D_virt', 'samp_freq': samp_freq, 'resolution': resolution} waveform = self.current_sweep self._waveform = waveform return waveform, None
[docs] def sweep_2D(self, samp_freq, sweepgates, sweepranges, resolution): self.current_sweep = {'waveform': 'simulation_awg', 'sweepgates': sweepgates, 'sweepranges': sweepranges, 'type': 'sweep_2D', 'samp_freq': samp_freq, 'resolution': resolution} waveform = self.current_sweep self._waveform = waveform return waveform, None
[docs] def stop(self): pass