def correctChargeSensor(xscan, yscan, xs, ys, fig=None): """ Calculate correction for a non-linear charge sensor Args: xscan, yscan: data of scan to be corrected xs, ys: scan of charge sensor response Returns: results (dict): dictionary with intermediate results """ peaks = qtt.algorithms.coulomb.coulombPeaks(xs, ys, fig=fig, istep=1) try: # range for fit: select from the first detected peak xsr = xs[peaks[0]['pbottoml']:peaks[0]['p']] ysr = ys[peaks[0]['pbottoml']:peaks[0]['p']] except Exception as ex: # no good peaks, just take the entire range xsr = xs ysr = ys # smooth fit to SD curve dl = DataLinearizer(xsr, ysr) if fig is not None: dl.show(fig) minv, maxv = np.min(yscan), np.max(yscan) pgeometry.plot2Dline([0, -1, minv], '--c', label='range of scan') pgeometry.plot2Dline([0, -1, maxv], '--c', label=None) # plt.plot(xsr, linfit(xsr), ':k', label='linear fit') return dl, {'peaks': peaks}
def plot_pinchoff(result, ds=None, fig=10, verbose=1): """ Plot result of a pinchoff scan """ if ds is None: ds = qtt.data.get_dataset(result) if not result.get('type', 'none') in ['gatesweep', 'pinchoff']: raise Exception('calibration result of incorrect type') if fig is not None: plt.figure(fig) plt.clf() MatPlot(ds.default_parameter_array(), num=fig) lowvalue = result['lowvalue'] highvalue = result['highvalue'] pinchoff_point = result['pinchoff_point'] midpoint = result['midpoint'] midvalue = result['midvalue'] plot2Dline([0, -1, lowvalue], '--c', alpha=.5, label='low value') plot2Dline([0, -1, highvalue], '--c', alpha=.5, label='high value') plot2Dline([-1, 0, midpoint], ':m', linewidth=2, alpha=0.5, label='midpoint') if verbose >= 2: plt.plot(midpoint, midvalue, '.m', label='midpoint') plot2Dline([-1, 0, pinchoff_point], '--g', linewidth=1, alpha=0.5, label='pinchoff_point')
def plot_onedot(results, ds=None, verbose=2, fig=100, linecolor='c', ims=None, extentImageMatlab=None, lv=None): """ Plot results of a barrier-barrier scan of a single dot Args: results (dict): results of the onedotGetBalance function ds (None or DataSet): dataset to use for plotting fig (int or None): figure window to plot to """ if ds is None: ds = qtt.data.get_dataset(results) if fig is not None: _plot_dataset(ds, fig) if verbose >= 2: pgeometry.plotPoints(results['balancefit'], '--', color=linecolor, linewidth=2, label='balancefit') if verbose >= 2: pgeometry.plotPoints(results['balancepoint0'], '.r', markersize=13, label='balancepoint0') pgeometry.plotPoints(results['balancepoint'], '.m', markersize=17, label='balancepoint') if ims is not None: qtt.utilities.tools.showImage(ims, extentImageMatlab, fig=fig + 1) # XX plt.axis('image') plt.title('Smoothed image') pgeometry.plotPoints(results['balancepoint'], '.m', markersize=16, label='balancepoint') qtt.utilities.tools.showImage(ims > lv, None, fig=fig + 2) pgeometry.plotPoints(results['balancefitpixel'], '--c', markersize=16, label='balancefit') pgeometry.plotLabels(results['balancefitpixel']) plt.axis('image') plt.title('thresholded area') if verbose >= 2: qq = ims.flatten() plt.figure(fig + 3) plt.clf() plt.hist(qq, 20) plot2Dline([-1, 0, np.percentile(ims, 1)], '--m', label='percentile 1') plot2Dline([-1, 0, np.percentile(ims, 2)], '--m', label='percentile 2') plot2Dline([-1, 0, np.percentile(ims, 99)], '--m', label='percentile 99') plot2Dline([-1, 0, lv], '--r', linewidth=2, label='lv') plt.legend(numpoints=1) plt.title('Histogram of image intensities') plt.xlabel('Image (smoothed) values')
def analysePeaks(x, y, peaks, verbose=1, doplot=0, typicalhalfwidth=None, parameters=None, istep=None): """ Analyse Coulomb peaks Args: x,y: arrays with data data in mV peaks: list of detected peaks to be analysed typicalhalfwidth : float typical width of peak (half side) in mV (mV ??) """ if parameters is None: parameters = {} if istep is not None: warnings.warn('ignoring legacy argument istep') if typicalhalfwidth is not None: raise Exception( 'please set typicalhalfwidth in the parameters argument') typicalhalfwidth = parameters.get('typicalhalfwidth', 13) if not issorted(x): pass if x[0] > x[-1]: print('analysePeaks: warning: x values are not sorted!!!!') leftp = max(3, x.size / 200) # ignore all data to the left of this point for ii, peak in enumerate(peaks): p = peak['p'] if verbose: print('analysePeaks: peak %d: max %.1f' % (ii, peak['y'])) if p < leftp: # discard all measurements to the left of the scan peak['valid'] = 0 peak['xhalf'] = np.NaN peak['xhalfl'] = np.NaN peak['phalf'] = np.NaN continue # determine starting points for search of peak zi = np.interp( [x[p] - 3. * typicalhalfwidth, x[p], x[p] + 3. * typicalhalfwidth], x, range(x.size)) zi = np.round(zi).astype(int) zi[0] = max(zi[0], leftp) # discard points on the left of scan zi[1] = max(zi[1], leftp) if doplot >= 2: plt.plot(x[zi[0]], y[zi[0]], '.g', markersize=11, label='mu-3*thw') plt.plot(x[zi[-1]], y[zi[-1]], '.', color=[0, .27, 0], markersize=11, label='mu+3*thw') ind = range(zi[0], zi[1]) if len(ind) == 0: if verbose >= 2: print('analysePeaks: error? x[p] %f' % x[p]) peak['valid'] = 0 peak['xhalf'] = np.NaN peak['phalf'] = np.NaN continue if verbose >= 2: print(' peak %d: range to search for half width %d to %d' % (ii, zi[0], zi[1])) xl, yl = x[ind], y[ind] if 0: hminval0 = peak['halfvaluelow'] fv = peak['y'] - 1.8 * (peak['y'] - peak['halfvaluelow']) else: hminval0 = .5 * (peak['y'] + np.min(y[ind])) fv = peak['y'] - 1.8 * (peak['y'] - hminval0) xh = np.interp(hminval0, yl, xl) ph = np.interp(hminval0, yl, range(xl.size)) ph0 = ind[int(ph)] xf = np.interp(fv, yl, xl) peak['phalf0'] = ph0 peak['phalfl'] = None #peak['indlocal'] = list(ind) phalfvalue = np.interp(ph, range(xl.size), yl) yhalfl = np.interp(ph, range(xl.size), yl) peak['xhalfl'] = xh peak['xfoot'] = xf peak['yhalfl'] = yhalfl if doplot >= 2: plt.plot(peak['xhalfl'], yhalfl, '.', color=[1, 1, 0], markersize=11) pgeometry.plot2Dline([-1, 0, x[p] - 3 * typicalhalfwidth], ':c', label='3*thw') pgeometry.plot2Dline([-1, 0, peak['xfoot']], ':y', label='xfoot') pratio = np.abs(phalfvalue - peak['y']) / (-peak['halfvaluelow'] + peak['y']) if verbose >= 2: print(' paratio %.2f' % pratio) if verbose >= 2: print( np.abs(phalfvalue - peak['y']) / (-peak['halfvaluelow'] + peak['y'])) if pratio > .1: peak['valid'] = peak['valid'] else: peak['valid'] = 0 if verbose: print(' peak %d: valid %d' % (ii, peak['valid'])) return peaks
def peakFindBottom(x, y, peaks, fig=None, verbose=1): """ Find the left bottom of a detected peak Args: x (array): independent variable data y (array): signal data peaks (list): list of detected peaks fig (None or int): if integer, then plot results verbose (int): verbosity level """ kk = np.ones(3) / 3. ys = scipy.ndimage.filters.correlate1d(y, kk, mode='nearest') peaks = copy.deepcopy(peaks) dy = np.diff(ys, n=1) dy = np.hstack((dy, [0])) for ii, peak in enumerate(peaks): if verbose: print('peakFindBottom: peak %d' % ii) if not peak['valid']: continue ind = range(peak['phalf0']) left_of_peak = 0 * y.copy() left_of_peak[ind] = 1 r = range(y.size) left_of_peak_and_decreasing = left_of_peak * ( dy < 0) # set w to zero where the scan is increasing left_of_peak_and_decreasing[ 0] = 1 # make sure to stop at the left end of the scan... ww = left_of_peak_and_decreasing.nonzero()[0] if verbose >= 2: print(' peakFindBottom: size of decreasing area %d' % ww.size) if ww.size == 0: if peak['valid']: peak['valid'] = 0 peak['validreason'] = 'peakFindBottom' if verbose >= 2: print('peakFindBottom: invalid peak') print(ind) print(dy) continue bidx = ww[-1] peak['pbottomlow'] = bidx w = left_of_peak * (dy > 0) # we need to be rising # we need to be above 10% of absolute low value w = w * ((ys) < ys[bidx] + .1 * (ys[peak['p']] - ys[bidx])) w = w * (r >= peak['pbottomlow']) ww = w.nonzero()[0] if ww.size == 0: if peak['valid']: peak['valid'] = 0 peak['validreason'] = 'peakFindBottom' if verbose >= 2: print('peakFindBottom: invalid peak (%s)' % ('rising part ww.size == 0', )) print(w) print(ys) continue bidx = ww[-1] peak['pbottom'] = bidx peak['pbottoml'] = bidx peak['xbottom'] = x[bidx] peak['xbottoml'] = x[bidx] peak['vbottom'] = y[bidx] # legacy peak['ybottoml'] = y[bidx] if verbose >= 3: plt.figure(53) plt.clf() plt.plot(x[ind], 0 * np.array(ind) + 1, '.b', label='ind') plt.plot(x[range(y.size)], w, 'or', label='w') plt.plot(x[range(y.size)], dy < 0, 'dg', markersize=12, label='dy<0') pgeometry.enlargelims() pgeometry.plot2Dline([-1, 0, peak['x']], '--c', label='x') pgeometry.plot2Dline([-1, 0, x[peak['phalf0']]], '--y', label='phalf0') pgeometry.plot2Dline([-1, 0, x[peak['pbottomlow']]], ':k', label='pbottomlow') pgeometry.plot2Dline([-1, 0, peak['xbottoml']], '--y', label='xbottoml') plt.legend(loc=0) return peaks
def analyseGateSweep(dd, fig=None, minthr=None, maxthr=None, verbose=1, drawsmoothed=True, drawmidpoints=True): """ Analyse sweep of a gate for pinch value, low value and high value Args: dd (1D qcodes DataSet): structure containing the scan data minthr, maxthr : float parameters for the algorithm (default: None) Returns: result (dict): dictionary with analysis results """ goodgate = True data = dd XX = None # should be made generic setpoint_name = [x for x in list(data.arrays.keys()) if not x.endswith('amplitude') and getattr(data, x).is_setpoint][0] value_parameter_name = data.default_parameter_name() # e.g. 'amplitude' x = data.arrays[setpoint_name] value = np.array(data.arrays[value_parameter_name]) # detect direction of scan scandirection = np.sign(x[-1] - x[0]) if scandirection < 0: scandirection = 1 x = x[::-1] value = value[::-1] # crude estimate of noise noise = np.nanpercentile(np.abs(np.diff(value)), 50) lowvalue = np.nanpercentile(value, 1) highvalue = np.nanpercentile(value, 90) # sometimes a channel is almost completely closed, then the percentile # approach does not function well ww = value[value >= (lowvalue + highvalue) / 2] highvalue = np.nanpercentile(ww, 90) if verbose >= 2: print('analyseGateSweep: lowvalue %.1f highvalue %.1f' % (lowvalue, highvalue)) d = highvalue - lowvalue vv1 = value > (lowvalue + .2 * d) vv2 = value < (lowvalue + .8 * d) midpoint1 = vv1 * vv2 ww = midpoint1.nonzero()[0] midpoint1 = np.mean(x[ww]) # smooth signal kk = np.ones(3) / 3. ww = value for ii in range(4): ww = scipy.ndimage.filters.correlate1d(ww, kk, mode='nearest') # ww=scipy.signal.convolve(ww, kk, mode='same') # ww=scipy.signal.convolve2d(ww, kk, mode='same', boundary='symm') midvalue = .7 * lowvalue + .3 * highvalue if scandirection >= 0: mp = (ww >= (.7 * lowvalue + .3 * highvalue)).nonzero()[0][0] else: mp = (ww >= (.7 * lowvalue + .3 * highvalue)).nonzero()[0][-1] mp = max(mp, 2) # fix for case with zero data signal midpoint2 = x[mp] if verbose >= 2: print('analyseGateSweep: midpoint2 %.1f midpoint1 %.1f' % (midpoint2, midpoint1)) if minthr is not None and np.abs(lowvalue) > minthr: if verbose: print('analyseGateSweep: gate not good: gate is not closed') print(' minthr %s' % minthr) midpoint1 = np.percentile(x, .5) midpoint2 = np.percentile(x, .5) goodgate = False # check for gates that are fully open or closed if scandirection > 0: xleft = x[0:mp] leftval = ww[0:mp] rightval = ww[mp] else: xleft = x[mp:] leftval = ww[mp:] rightval = ww[0:mp] st = ww.std() if verbose>=2: print('analyseGateSweep: leftval %.2f, rightval %.2f' % (leftval.mean(), rightval.mean())) if goodgate and (rightval.mean() - leftval.mean() < .3 * st): if verbose: print( 'analyseGateSweep: gate not good: gate is not closed (or fully closed)') midpoint1 = np.percentile(x, .5) midpoint2 = np.percentile(x, .5) goodgate = False # fit a polynomial to the left side if goodgate and leftval.size > 5: # TODO: make this a robust fit fit = np.polyfit(xleft, leftval, 1) pp = np.polyval(fit, xleft) # pmid = np.polyval(fit, midpoint2) p0 = np.polyval(fit, xleft[-1]) pmid = np.polyval(fit, xleft[0]) if verbose>=2: print('analyseGateSweep: p0 %.1f, pmid %.1f, leftval[0] %.1f' % (p0, pmid, leftval[0])) if pmid + (pmid - p0) * .25 > leftval[0]: midpoint1 = np.percentile(x, .5) midpoint2 = np.percentile(x, .5) goodgate = False if verbose: print( 'analyseGateSweep: gate not good: gate is not closed (or fully closed) (line fit check)') # another check on closed gates if scandirection > 0: leftidx = range(0, mp) fitleft = np.polyfit( [x[leftidx[0]], x[leftidx[-1]]], [lowvalue, value[leftidx[-1]]], 1) else: leftidx = range(mp, value.shape[0]) fitleft = np.polyfit( [x[leftidx[-1]], x[leftidx[0]]], [lowvalue, value[leftidx[0]]], 1) leftval = value[leftidx] leftpred = np.polyval(fitleft, x[leftidx]) if np.abs(scandirection * (xleft[1] - xleft[0])) > 150 and xleft.size > 15: xleft0 = x[mp + 6:] leftval0 = ww[mp + 6:] fitL = np.polyfit(xleft0, leftval0, 1) pp = np.polyval(fitL, xleft0) nd = fitL[0] / (highvalue - lowvalue) if goodgate and (nd * 750 > 1): midpoint1 = np.percentile(x, .5) midpoint2 = np.percentile(x, .5) goodgate = False if verbose: print('analyseGateSweep: gate not good: gate is not closed (or fully closed) (slope check)') pass if np.mean(leftval - leftpred) > noise: midpoint1 = np.percentile(x, .5) midpoint2 = np.percentile(x, .5) goodgate = False if verbose: print( 'analyseGateSweep: gate not good: gate is not closed (or fully closed) (left region check)') pass if fig is not None: cfigure(fig) plt.clf() plt.plot(x, value, '.-b', linewidth=2) plt.xlabel('Sweep %s [mV]' % setpoint_name, fontsize=14) plt.ylabel('keithley [pA]', fontsize=14) if drawsmoothed: plt.plot(x, ww, '-g', linewidth=1) plot2Dline([0, -1, lowvalue], '--m', label='low value') plot2Dline([0, -1, highvalue], '--m', label='high value') if drawmidpoints: if verbose >= 2: plot2Dline([-1, 0, midpoint1], '--g', linewidth=1) plot2Dline([-1, 0, midpoint2], '--m', linewidth=2) if verbose >= 2: plt.plot(x[leftidx], leftpred, '--r', markersize=15, linewidth=1, label='leftpred') plt.plot(x[leftidx], leftval, '--m', markersize=15, linewidth=1, label='leftval') adata = dict({'description': 'pinchoff analysis', 'pinchvalue': 'use pinchoff_point instead', '_pinchvalueX': midpoint1 - 50, 'goodgate': goodgate}) adata['lowvalue'] = lowvalue adata['highvalue'] = highvalue adata['xlabel'] = 'Sweep %s [mV]' % setpoint_name adata['pinchoff_point'] = midpoint2 - 50 pinchoff_index = np.interp(-70.5, x, np.arange(x.size) ) adata['pinchoff_value'] = value[int(pinchoff_index)] adata['midpoint'] = float(midpoint2) adata['midvalue'] = midvalue adata['dataset']=dd.location adata['type']='gatesweep' if verbose>=1: print('analyseGateSweep: pinch-off point %.3f, value %.3f' % (adata['midpoint'], adata['midvalue']) ) if verbose >= 2: print('analyseGateSweep: gate status %d: pinchvalue %.1f' % (goodgate, adata['pinchoff_point'])) adata['Xsmooth'] = ww adata['XX'] = XX adata['X'] = value adata['x'] = x adata['ww'] = ww adata['_mp'] = mp return adata
noise.sort() pp = np.zeros((len(noise), 6)) for ii, n in enumerate(noise): pgeometry.tprint('quick fit %d/%d' % (ii, len(noise))) yyx = yy + n * (np.random.rand(yy.size) - .5) parfit, _, _ = fit_pol_all(xx, yyx, kT=0.001, par_guess=None) pp[ii] = parfit plt.figure(200) plt.clf() plt.plot(noise, pp[:, 0], '.b', label='tunnel coupling') plt.xlabel('Noise') plt.ylabel('Estimated tunnel frequency') pgeometry.plot2Dline([0, -1, par[0]], '--c', label='true value') # %% Show effect of proper initialization yyx = yy + n * (np.random.rand(yy.size) - .5) parfit1, _, _ = fit_pol_all(xx, yyx, kT=0.001, par_guess=par) parfit2, _, _ = fit_pol_all(xx, yyx, kT=0.001, par_guess=None, verbose=2) parfit2i, _, _ = fit_pol_all(xx, yyx, kT=0.001, par_guess=parfit2) yy1 = polmod_all_2slopes(xx, parfit1, kT=0.001) yy2 = polmod_all_2slopes(xx, parfit2, kT=0.001) yy2i = polmod_all_2slopes(xx, parfit2i, kT=0.001) c0 = polweight_all_2slopes(xx, yy, par, kT=0.001) c1 = polweight_all_2slopes(xx, yy1, par, kT=0.001) c2 = polweight_all_2slopes(xx, yy2, par, kT=0.001) c2i = polweight_all_2slopes(xx, yy2i, par, kT=0.001)
def peakFindBottom(x, y, peaks, fig=None, verbose=1): """ Find the left bottom of a detected peak """ kk = np.ones(3) / 3. ys = scipy.ndimage.filters.correlate1d(y, kk, mode='nearest') peaks = copy.deepcopy(peaks) dy = np.diff(ys, n=1) dy = np.hstack((dy, [0])) for ii, peak in enumerate(peaks): if verbose: print('peakFindBottom: peak %d' % ii) if not peak['valid']: continue ind = range(peak['phalf0']) w0 = 0 * y.copy() w0[ind] = 1 r = range(y.size) w = w0 * (dy < 0) # set w to zero where the scan is increasing w[0] = 1 # make sure to stop at the left end of the scan... ww = w.nonzero()[0] if verbose >= 2: print(' peakFindBottom: ww.size %d' % ww.size) if ww.size == 0: if peak['valid']: peak['valid'] = 0 peak['validreason'] = 'peakFindBottom' if verbose >= 2: print('peakFindBottom: invalid peak') print(ind) print(dy) continue bidx = ww[-1] peak['pbottomlow'] = bidx w = w0 * (dy > 0) # we need to be rising # we need to be above 10% of absolute low value w = w * ((ys) < ys[bidx] + .1 * (ys[peak['p']] - ys[bidx])) w = w * (r >= peak['pbottomlow']) ww = w.nonzero()[0] if ww.size == 0: if peak['valid']: peak['valid'] = 0 peak['validreason'] = 'peakFindBottom' if verbose >= 2: print('peakFindBottom: invalid peak (%s)' % ('rising part ww.size == 0', )) print(w) print(ys) # print(w) continue bidx = ww[-1] peak['pbottom'] = bidx peak['pbottoml'] = bidx peak['xbottom'] = x[bidx] peak['xbottoml'] = x[bidx] peak['vbottom'] = y[bidx] # legacy peak['ybottoml'] = y[bidx] if verbose >= 3: # for debugging plt.figure(53) plt.clf() plt.plot(x[ind], 0 * np.array(ind) + 1, '.b', label='ind') plt.plot(x[range(y.size)], w, 'or', label='w') plt.plot(x[range(y.size)], dy < 0, 'dg', markersize=12, label='dy<0') pmatlab.enlargelims() pmatlab.plot2Dline([-1, 0, peak['x']], '--c', label='x') pmatlab.plot2Dline([-1, 0, x[peak['phalf0']]], '--y', label='phalf0') pmatlab.plot2Dline([-1, 0, x[peak['pbottomlow']]], ':k', label='pbottomlow') pmatlab.plot2Dline([-1, 0, peak['xbottoml']], '--y', label='xbottoml') plt.legend(loc=0) return peaks