def plot_fit_function(self, num_points=100): ''' try: x_coords = np.linspace(self.x_vec[0], self.x_vec[-1], num_points) except Exception as message: print 'no x axis information specified', message return ''' if not qkit.module_available("matplotlib"): raise ImportError("matplotlib not found.") if self.landscape: for trace in self.landscape: try: # plt.clear() plt.plot(self.x_vec, trace) plt.fill_between(self.x_vec, trace + float(self.span) / 2, trace - float(self.span) / 2, alpha=0.5) except Exception: print('invalid trace...skip') plt.axhspan(self.y_vec[0], self.y_vec[-1], facecolor='0.5', alpha=0.5) plt.show() else: print('No trace generated.')
def _plot_sequence(self, seq, ro_ind, x_unit, bounds, col="C0", plot_readout=True): """ The actual plotting of the sequences happens here. Input: seq: sequence (as array) to be plotted ro_ind: index of the readout in seq x_unit: x_unit for the time axis bounds: boundaries for the plot (xmin, xmax, ymin, ymax) """ if not qkit.module_available("matplotlib"): raise ImportError("matplotlib not found.") if plot_readout: fig = plt.figure(figsize=(18, 6)) xmin, xmax, ymin, ymax = bounds samplerate = self._sample.clock time = -(np.arange(0, len(seq) + 1, 1) - ro_ind) / (samplerate * self._x_unit[x_unit]) # make sure last point of the waveform goes to zero seq = np.append(seq, 0) # plot sequence plt.plot(time, seq, col) plt.fill(time, seq, color=col, alpha=0.2) # plot readout if plot_readout: plt.fill([ 0, 0, -self._sample.readout_tone_length / self._x_unit[x_unit], -self._sample.readout_tone_length / self._x_unit[x_unit] ], [0, ymax, ymax, 0], color="C7", alpha=0.3) # add label for readout plt.text(-0.5 * self._sample.readout_tone_length / self._x_unit[x_unit], ymax / 2., "readout", horizontalalignment="center", verticalalignment="center", rotation=90, size=14) # adjust bounds plt.xlim(xmin + 0.005 * abs(xmax - xmin), xmax - 0.006 * abs(xmax - xmin)) plt.ylim(ymin, ymax + 0.025 * (ymax - ymin)) plt.xlabel("time " + x_unit) return
def findmin(self, function, start, stop, stepsize, plot=False, averages=1): a = np.arange(start, stop + stepsize / 2, stepsize) if (len(a) < 2): # print "*************TRYING TO MINIMIZE %s BETWEEN %f and %f => NOT POSSIBLE!*********"%(function,start,stop) return start b = np.zeros(len(a)) for u, v in enumerate(a): for i in range(averages): b[u] += function(v) b = b / averages if plot and qkit.module_available("matplotlib"): plt.plot(a, b, "k*-") plt.show() return a[b.argmin()]
def _plot_sequences(self, seq_ind, seqs, ro_inds, x_unit, bounds): """ The actual plotting of the sequences happens here. Args: seqs: list of sequences to be plotted (i.e. one list of sequence for each channel) ro_inds: indices of the readout x_unit: x_unit for the time axis bounds: boundaries of the plot (xmin, xmax, ymin, ymax) show_quadrature: set to "I" or "Q" if you want to display either quadrature instead of the amplitude """ if not qkit.module_available("matplotlib"): raise ImportError("matplotlib not found.") fig = plt.figure(figsize=(18, 6)) xmin, xmax, ymin, ymax = bounds samplerate = self._sample.clock # plot sequence for i, chan in enumerate(self.channels[1:]): if len(ro_inds[i]) > seq_ind: chan._plot_sequence(seqs[i][seq_ind], ro_inds[i][seq_ind], x_unit, bounds, col=self._chancols[i + 1], plot_readout=False) # plot readout plt.fill([ 0, 0, -self._sample.readout_tone_length / self._x_unit[x_unit], -self._sample.readout_tone_length / self._x_unit[x_unit] ], [0, ymax, ymax, 0], color="C7", alpha=0.3) # add label for readout plt.text(-0.5 * self._sample.readout_tone_length / self._x_unit[x_unit], ymax / 2., "readout", horizontalalignment="center", verticalalignment="center", rotation=90, size=14) # adjust plot limits plt.xlim(xmin + 0.005 * abs(xmax - xmin), xmax - 0.006 * abs(xmax - xmin)) plt.ylim(ymin, ymax + 0.025 * (ymax - ymin)) plt.xlabel("time " + x_unit) return
def __init__(self, h5_filepath, comment='', save_pdf=False): """Inits h5plot with a h5_filepath (string, absolute path), optional comment string, and optional save_pdf boolean. """ if not plot_enable or not qkit.module_available("matplotlib"): logging.warning( "matplotlib not installed. I can not save your measurement files as png. I will disable this function." ) qkit.cfg['save_png'] = False if not qkit.cfg.get('save_png', True): return self.comment = comment self.save_pdf = save_pdf self.path = h5_filepath filepath = os.path.abspath( self.path) #put filepath to platform standards self.filedir = os.path.dirname( filepath ) #return directory component of the given pathname, here filepath self.image_dir = os.path.join(self.filedir, 'images') try: os.mkdir(self.image_dir) except OSError: logging.warning('Error creating image directory.') pass # open the h5 file and get the hdf_lib object self.hf = store.Data(self.path) # check for datasets for i, pentry in enumerate(self.hf['/entry'].keys()): key = '/entry/' + pentry for j, centry in enumerate(self.hf[key].keys()): try: self.key = '/entry/' + pentry + "/" + centry self.ds = self.hf[self.key] if self.ds.attrs.get('save_plot', True): self.plt() # this is the plot function except Exception as e: print("Exception in qkit/gui/plot/plot.py while plotting") print(self.key) print(e) #close hf file self.hf.close() print('Plots saved in ' + self.image_dir)
def gen_fit_function(self, curve_f, curve_p, units='', p0=[-1, 0.1, 7]): ''' curve_f: 'parab', 'hyp', specifies the fit function to be employed curve_p: set of points that are the basis for the fit in the format [[x1,x2,x3,...],[y1,y2,y3,...]], frequencies in Hz units: set this to 'Hz' in order to avoid large values that cause the fit routine to diverge p0 (optional): start parameters for the fit, must be an 1D array of length 3 ([a,b,c,d]), where for the parabula p0[3] will be ignored The parabolic function takes the form y = a*(x-b)**2 + c , where (a,b,c) = p0 The hyperbolic function takes the form y = sqrt[ a*(x-b)**2 + c ], where (a,b,c) = p0 adds a trace to landscape ''' if not qkit.module_available("scipy"): raise ImportError('scipy not available.') if not self.landscape: self.landscape = [] x_fit = curve_p[0] if units == 'Hz': y_fit = np.array(curve_p[1]) * 1e-9 else: y_fit = np.array(curve_p[1]) try: multiplier = 1 if units == 'Hz': multiplier = 1e9 fit_fct = None if curve_f == 'parab': fit_fct = self.f_parab elif curve_f == 'hyp': fit_fct = self.f_hyp elif curve_f == 'lin': fit_fct = self.f_lin p0 = p0[:2] else: print('function type not known...aborting') raise ValueError popt, pcov = curve_fit(fit_fct, x_fit, y_fit, p0=p0) self.landscape.append(multiplier * fit_fct(self.x_vec, *popt)) except Exception as message: print('fit not successful:', message) popt = p0
def object_hook(self, obj): if 'content' in obj and 'dtype' in obj and len(obj) == 2: if obj['dtype'] == 'ndarray': return np.array(obj['content']) if obj['dtype'] == 'ufloat': if qkit.module_available('uncertainties'): return uncertainties.ufloat( nominal_value=obj['content']['nominal_value'], std_dev=obj['content']['std_dev']) else: logging.warning( 'Uncertainties package not installed. Only nominal value returned.' ) return float(obj['content']['nominal_value']) if obj['dtype'] == 'qkitInstrument': # or obj['dtype'] == 'instance' return qkit.instruments.get(obj['content']) else: return obj
def default(self, obj): if type(obj) == np.ndarray: return {'dtype': type(obj).__name__, 'content': obj.tolist()} # if type(obj) == types.InstanceType: # no valid synatx in python 3 and probably not needed (MMW) # return {'dtype' : type(obj).__name__, 'content': str(obj.get_name())} if uncertainties_enable or qkit.module_available('uncertainties'): if type(obj) in (uncertainties.core.Variable, uncertainties.core.AffineScalarFunc): return { 'dtype': 'ufloat', 'content': { 'nominal_value': obj.nominal_value, 'std_dev': obj.std_dev } } try: return obj._json() except AttributeError: return { 'dtype': type(obj).__name__, 'content': json.JSONEncoder.default(self, obj) }
# MP/AS @ KIT 05/2017 # JSON en-/decoder for non-JSON standard data-types import json import types import numpy as np import logging import qkit try: if qkit.module_available('uncertainties'): import uncertainties uncertainties_enable = True except AttributeError: try: import uncertainties uncertainties_enable = True except ImportError: uncertainties_enable = False class QkitJSONEncoder(json.JSONEncoder): def default(self, obj): if type(obj) == np.ndarray: return {'dtype': type(obj).__name__, 'content': obj.tolist()} # if type(obj) == types.InstanceType: # no valid synatx in python 3 and probably not needed (MMW) # return {'dtype' : type(obj).__name__, 'content': str(obj.get_name())} if uncertainties_enable or qkit.module_available('uncertainties'): if type(obj) in (uncertainties.core.Variable, uncertainties.core.AffineScalarFunc): return { 'dtype': 'ufloat',
@author: [email protected] / 2019 inspired by and based on resonator tools of Sebastian Probst https://github.com/sebastianprobst/resonator_tools """ import numpy as np import logging import scipy.optimize as spopt from scipy import stats from scipy.interpolate import splrep, splev from scipy.ndimage.filters import gaussian_filter1d plot_enable = False try: import qkit if qkit.module_available("matplotlib"): import matplotlib.pyplot as plt plot_enable = True except (ImportError, AttributeError): try: import matplotlib.pyplot as plt plot_enable = True except ImportError: plot_enable = False class circuit: """ Base class for common routines and definitions shared between both ports. inputs: - f_data: Frequencies for which scattering data z_data_raw is taken
def recalibrate(self, dcx, dcy, x, y, phaseoffset, relamp, relamp2): self.cache_valid = False if self._swb is not None: # switching to fsup self._swb.set_position('2') else: logging.warning( __name__ + ' : Switch was not switched. Define switchbox instrument via iq.connect_switchbox(swb). If you do not have a switchbox, make sure your cables are connected and go on.') self._sample.awg.set_clock(self._sample.clock) if not self._FSUP_connected: raise ValueError(( 'FSUP is possibly not connected. \nIncrease trust_region and maxage to interpolate values or connect FSUP and execute connect_FSUP(fsup)')) qkit.flow.start() (hx_amp, hx_phase, hy_amp, hy_phase) = (0, 0, 0, 0) if self._iq_frequency == 0: logging.warning( __name__ + ': Your IQ Frequency is 0. It is better to calibrate with a finite IQ frequency because you will get inconsistent data in the calibration file otherwise. If you calibrate with iq!=0, the right values for iq=0 are extracted.') mw_freq = self._f_rounded - self._iq_frequency # self._sample.awg.stop() self._sample.awg.set({'ch1_output': 0, 'ch2_output': 0, 'runmode': 'CONT'}) self._sample.qubit_mw_src.set({'frequency': mw_freq, 'power': self._mw_power, 'status': 1}) print("Recalibrating %s for Frequency: %.2fGHz (MW-Freq: %.2fGHz), MW Power: %.2fdBm" % ( self.mixer_name, self._sideband_frequency / 1e9, mw_freq / 1e9, self._mw_power)) sys.stdout.flush() frequencies = [mw_freq - 3 * self._iq_frequency, mw_freq - 2 * self._iq_frequency, mw_freq - self._iq_frequency, mw_freq, mw_freq + self._iq_frequency, mw_freq + 2 * self._iq_frequency, mw_freq + 3 * self._iq_frequency] self.focus(mw_freq, 1) self.load_zeros() print("Optimizing DC offsets to reduce leakage when there is no pulse") (xold, yold) = (np.inf, np.inf) while (np.all(np.around((dcx, dcy), 3) != np.around((xold, yold), 3))): (xold, yold) = (dcx, dcy) dcx = self.minimize(self.xoptimize, dcx - .002, dcx + .002, .002, 1e-3, final_averages=3, confirmonly=True)[ 0] dcy = self.minimize(self.yoptimize, dcy - .002, dcy + .002, .002, 1e-3, final_averages=3, confirmonly=True)[ 0] if not self._iq_frequency == 0: self.load_wfm(sin_phase=phaseoffset, update_channels=(True, True), relamp=relamp, relamp2=relamp2, init=True) optimized = [(self.focus(frequencies[i], 1), self._fsup.get_marker_level(1))[1] for i in range(len(frequencies))] optimized_old = [np.inf, np.inf, np.inf, np.inf] print("iterating") while (optimized_old[2] - optimized[2] > 1 or optimized_old[3] - optimized[3] > 1): print ".", sys.stdout.flush() optimized_old = copy(optimized) self.focus(mw_freq, 1) (xold, yold) = (np.inf, np.inf) while (np.all(np.around((x, y), 3) != np.around((xold, yold), 3))): (xold, yold) = (x, y) x = \ self.minimize(self.xoptimize, x - .002, x + .002, .001, 1e-3, final_averages=1, confirmonly=True)[0] y = \ self.minimize(self.yoptimize, y - .002, y + .002, .001, 1e-3, final_averages=1, confirmonly=True)[0] self.focus(mw_freq - self._iq_frequency, 4) phaseoffset = \ self.minimize(self.phaseoptimize, phaseoffset - .15, phaseoffset + .15, 5e-3, 5e-3, final_averages=1, confirmonly=True)[0] relamp = self.minimize(self.relampoptimize, relamp - .01, relamp + .01, .05, 1e-3, final_averages=2, bounds=(.5, 2), confirmonly=True)[0] relamp2 = self.minimize(self.relampoptimize2, relamp2 - .01, relamp2 + .01, .05, 1e-3, final_averages=2, bounds=(.5, 2), confirmonly=True)[0] optimized = [(self.focus(frequencies[i], 1), np.mean([(self._fsup.sweep(), self._fsup.get_marker_level(1))[1] for j in range(5)]))[1] for i in range(len(frequencies))] else: x, y, phaseoffset, relamp, relamp2 = 0, 0, 0, 1, 1 optimized = [(self.focus(frequencies[i], 1), np.mean([(self._fsup.sweep(), self._fsup.get_marker_level(1))[1] for j in range(5)]))[1] for i in range(len(frequencies))] print("Parameters: DC x: %.1fmV, DC y: %.1fmV AC x: %.1fmV, AC y: %.1fmV phase: %.1fdegree Amplitude: %.3fVpp/%.3fVpp" % ( dcx * 1e3, dcy * 1e3, x * 1e3, y * 1e3, phaseoffset * 180 / np.pi, relamp, relamp2)) print( "Your Sideband has a power of %.3fdBm, Leakage is %.2fdB lower, other sideband is %.2fdB lower.\nThe largest of the higher harmonics is %.2fdB lower." % ( optimized[4], optimized[4] - optimized[3], optimized[4] - optimized[2], np.max((optimized[4] - optimized[0], optimized[4] - optimized[1], optimized[4] - optimized[4], optimized[5] - optimized[6])))) data = np.array([np.append( (self._f_rounded, mw_freq, self._mw_power, time.time(), dcx, dcy, x, y, phaseoffset, relamp, relamp2), optimized)]) currentdata = copy(data) # Make a nice image on the FSUP so that you can see the results of calibration there. self._fsup.set({'freqspan': self._iq_frequency * 10, 'centerfreq': self._sideband_frequency - self._iq_frequency, 'resolutionBW': 5e5, 'videoBW': 5e2}) self._fsup.set_marker(1, self._sideband_frequency - self._iq_frequency) self._fsup.set_marker(2, self._sideband_frequency) self._fsup.set_marker(3, self._sideband_frequency + self._iq_frequency) self._fsup.set_marker(4, self._sideband_frequency + 2 * self._iq_frequency) sweeptime = self._fsup.get_sweeptime() self._fsup.sweep() qkit.flow.sleep(sweeptime) if qkit.module_available("matplotlib"): plt.plot(self._fsup.get_frequencies() / 1e9, self._fsup.get_trace()) plt.xlabel('Frequency (GHz)') plt.ylabel('Power (dBm)') plt.grid() if self._swb is not None: # switching back self._swb.set_position('1') # reset awg [self._sample.awg.set({'ch%i_amplitude' % i: 2, 'ch%i_offset' % i: 0}) for i in (1, 2)] try: storedvalues = np.loadtxt(os.path.join(qkit.cfg.getget('datadir'), "IQMixer\\%s.cal" % self.mixer_name)) if np.size(storedvalues) < 30: # Only one dataset storedvalues = [storedvalues] # If there was a calibration with the same parameters, remove it todelete = [] for index, t in enumerate(storedvalues): if t[0] == self._f_rounded and t[1] == mw_freq and t[2] == self._mw_power: todelete = np.append(todelete, index) print("\nLast time (%s), there have been the following values:" % (time.ctime(t[3]))) print("Parameters: DC x: %.1fmV, DC y: %.1fmV phase: %.1fdegree Amplitude: %.3fVpp/%.3fVpp" % ( t[6] * 1e3, t[7] * 1e3, t[8] * 180 / np.pi, t[9], t[10])) print( "Your Sideband had a power of %.3fdBm, Leakage was %.2fdB lower, other sideband was %.2fdB lower.\nThe largest of the higher harmonics was %.2fdB lower." % ( t[15], t[15] - t[14], t[15] - t[13], np.max((t[15] - t[11], t[15] - t[12], t[15] - t[16], t[15] - t[17])))) storedvalues = np.delete(storedvalues, todelete, axis=0) data = np.append(storedvalues, data) except IOError: pass data = data.reshape((data.size / 18, 18)) np.savetxt(os.path.join(qkit.cfg.getget('datadir'), "IQMixer\\%s.cal" % self.mixer_name), data, ( "%.2f", "%.2f", "%.2f", "%i", "%.3f", "%.3f", "%.3f", "%.3f", "%.6f", "%.3f", "%.3f", "%.4f", "%.4f", "%.4f", "%.4f", "%.4f", "%.4f", "%.4f")) return currentdata[0]