def test_fit_background(self, verbose=0): np.random.seed(2019) im = np.random.rand(200, 100) bg = fitBackground(im, verbose=verbose) bgo = fitBackground(im, verbose=verbose, removeoutliers=True) c = cleanSensingImage(im) self.assertEqual(bg.size, 20000) self.assertAlmostEqual(bg.min(), 4.180688953684698e-06, 6) self.assertAlmostEqual(bg.max(), 0.6620333371459401, 6) self.assertAlmostEqual(bg.sum(), 9725.006056739836, 2) self.assertEqual(bgo.size, 20000) self.assertAlmostEqual(bgo.min(), 3.6926296812183113e-06, 6) self.assertAlmostEqual(bgo.max(), 0.6424973079407454, 6) self.assertAlmostEqual(bgo.sum(), 9669.358784435484, 3) self.assertEqual(c.size, 20000) self.assertAlmostEqual(c.min(), -0.9865077626697246, 6) self.assertAlmostEqual(c.max(), 0.9970046055805283, 6) self.assertAlmostEqual(c.sum(), -0.786837730323506, 3)
def analyse_awg_to_plunger(result: dict, method: str = 'hough', fig: Optional[int] = None) -> dict: """ Determine the awg_to_plunger conversion factor from a 2D scan, two possible methods: 'hough' it fits the slope of the addition line and calculates the correction to the awg_to_plunger conversion factor from there. if this doesn't work for some reason, method 'click' can be used to find the addition lines by hand/eye. Args: result: result dictionary of the function measure_awg_to_plunger, shape: result = {'type': 'awg_to_plunger', 'awg_to_plunger': None, 'dataset': ds.location}. method: either 'hough' or 'click'. fig : determines of the analysis staps and the result is plotted. Returns: result: including to following entries: angle (float): angle in radians. angle_degrees (float): angle in degrees. correction of awg_to_plunger (float): correction factor. dataset (str): location where the dataset is stored. type(str): type of calibration, 'awg_to_plunger'. """ # getting the dataset from the result from the measure_awg_to_plunger function if result.get('type') != 'awg_to_plunger': raise AssertionError('not of type awg_to_plunger!') ds = get_dataset(result) # choosing a method; # the method 'hough' fits the addition line if method == 'hough': import cv2 im, tr = qtt.data.dataset2image(ds) imextent = tr.scan_image_extent() istep = tr.scan_resolution() _, r = qtt.algorithms.images.straightenImage( im, imextent, mvx=istep, mvy=None) H = r[4] imc = cleanSensingImage(im, sigma=0.93, dy=0) imx, _ = straightenImage(imc, imextent, mvx=istep, verbose=0) imx = imx.astype(np.float64) * \ (100. / np.percentile(imx, 99)) # scale image gray = qtt.pgeometry.scaleImage(imx) edges = cv2.Canny(gray, 50, 150, apertureSize=3) lines = cv2.HoughLines(edges, 1, np.pi / 180, int(gray.shape[0] * .5)) if lines is None: angle_pixel = None angle = None xscan = None angle_deg = None correction = None else: angles = lines[:, 0, 1] angle_pixel = angles[0] # take most voted line fac = 2 xpix = np.array([[0, 0], [-fac * np.sin(angle_pixel), fac * np.cos(angle_pixel)]]).T tmp = qtt.pgeometry.projectiveTransformation(np.linalg.inv(H), xpix) xscan = tr.pixel2scan(tmp) def vec2angle(v): return np.arctan2(v[0], v[1]) angle = vec2angle(xscan[:, 1] - xscan[:, 0]) correction = -1 / np.tan(angle) angle_deg = np.rad2deg(angle) # plotting the analysis steps of the data if fig is not None: plt.figure(fig + 1) plt.clf() plt.imshow(gray) plt.axis('image') if angle_pixel is not None: for offset_in_pixels in [-40, -20, 0, 20, 40]: label = None if offset_in_pixels == 0: label = 'detected angle' qtt.pgeometry.plot2Dline( [np.cos(angle_pixel), np.sin(angle_pixel), offset_in_pixels], 'm', label=label) if angle is not None: plt.title(f'Detected line direction: angle {angle_deg:.2f} [deg]') plt.figure(fig + 2) plt.clf() plt.imshow(edges) plt.axis('image') plt.title('Detected edge points') # the method click relies on the user clicking two points to indicate the addition line elif method == 'click': if fig is not None: plt.figure(fig) plt.clf() MatPlot(ds.default_parameter_array(), num=fig) plt.draw() plt.pause(1e-3) print("Please click two different points on the addition line") offset, slope = click_line(fig=fig) angle_pixel = None angle = -np.pi / 2 - np.tanh(slope) correction = -1 / np.tan(angle) angle_deg = angle / (2 * np.pi) * 360 else: raise Exception('method %s not implemented' % (method,)) # filling the result dictionary result = copy.copy(result) result['_angle_pixel'] = angle_pixel result['angle'] = angle result['angle_degrees'] = angle_deg result['correction of awg_to_plunger'] = correction if method == 'click': result['slope'] = slope result['offset'] = offset # optional, plotting figures showing the analysis if fig is not None: plot_awg_to_plunger(result=result, fig=fig) return result
def fit_anticrossing(dataset, width_guess=None, angles_guess=None, psi=None, w=2.5, diff_dir='dx', plot=False, verbose=1, param={}): """ Fits an anti-crossing model to a 2D scan. The model fitted is without tunnel coupling. Args: dataset (qcodes dataset): the 2D scan measurement dataset width_guess (None or float): Initial estimate for width of anti-crossing in the same unit as the dataset axis. angles_guess (None or float): Initial estimate for angles of anti-crossing in radians psi (None or float): angle for cross section of anti-crossing w (float): Width of lines in anti-crossing model diff_dir (str): differentiation direction plot (int): If non-zero, then plot into specified matplotlib window verbose (int): verbosity level param (dict): additional parameters Returns: anticross_fit: (dict) the parameters describing the fitted anti-cross optionally the cost for fitting and the figure number The main fields in the result structure are: * centre (2x1 array): position of the fitted anti-crossing * fit_params (array): fitting parameters of the model. See :func:`fitModel` * fitpoints (dict): a dictionary with fitted points. centre is the centre point; left_point and right_point are the corners of the anti-crossing. the four lines outwards are define by inner_points and outer_points """ abs_val = True set_arrays = dataset.default_parameter_array().set_arrays labels = [x.name for x in set_arrays] im, tr = qtt.data.dataset2image(dataset) imextent = tr.scan_image_extent() # get parameters of the algorithm istep = param.get('istep', 0.25) # resolution to convert the data into istepmodel = param.get('istepmodel', 0.5) # resolution in which to perform model fitting ksizemv = param.get('ksizemv', 31) # kernel size in mV diffvals = {'dx': 0, 'dy': 1, 'dxy': 2, 'xmy': 'xmy', 'g': 'g'} imc = cleanSensingImage(im, sigma=0.93, dy=diffvals[diff_dir]) imx, (fw, fh, mvx, mvy, Hstraight) = qtt.algorithms.images.straightenImage(imc, imextent, mvx=istep, verbose=verbose) imx = imx.astype(np.float64) * \ (100. / np.percentile(imx, 99)) # scale image # initialization of anti-crossing model param0 = [(imx.shape[0] / 2 + .5) * istep, (imx.shape[0] / 2 + .5) * istep, 3.5, 1.17809725, 3.5, 4.3196899, 0.39269908] if width_guess is not None: param0[2] = width_guess if angles_guess is not None: param0[3:] = angles_guess if psi is not None: param0e = np.hstack((param0, [psi])) else: psi = np.pi / 4 param0e = copy.copy(param0) # fit anti-crossing (twice) res = fitModel(param0e, imx, verbose=verbose, cfig=10, istep=istep, istepmodel=istepmodel, ksizemv=ksizemv, use_abs=abs_val, model_line_width=w) fitparam = res.x res = fitModel(fitparam, imx, verbose=verbose, cfig=10, istep=istep, istepmodel=istepmodel, ksizemv=ksizemv, use_abs=abs_val, model_line_width=w) fitparam = res.x cost, patch, cdata, _ = evaluateCross(fitparam, imx, verbose=0, fig=None, istep=istep, istepmodel=istepmodel) ccpixel_straight = cdata[0] ccpixel = qtt.pgeometry.projectiveTransformation( np.linalg.inv(Hstraight), (istepmodel / istep) * ccpixel_straight) if verbose: print('fit_anticrossing: patch size %s' % (patch.shape, )) def convert_coordinates(xpix): ccpixel = qtt.pgeometry.projectiveTransformation( np.linalg.inv(Hstraight), (istepmodel / istep) * xpix) return tr.pixel2scan(ccpixel) (cc, lp, hp, ip, op, _, _, _) = cdata centre = convert_coordinates(np.array(cc)) lp = convert_coordinates(np.array(lp)) hp = convert_coordinates(np.array(hp)) ip = convert_coordinates(np.array(ip).T) op = convert_coordinates(np.array(op).T) anticross_fit = {'labels': labels} anticross_fit['centre'] = tr.pixel2scan(ccpixel) anticross_fit['fitpoints'] = { 'centre': centre, 'left_point': lp, 'right_point': hp, 'inner_points': ip, 'outer_points': op } if len(param) == 7: param = np.append(fitparam, psi) anticross_fit['fit_params'] = fitparam anticross_fit['params'] = param if plot: if isinstance(plot, int): fig = plot else: fig = None fig_anticross = plt.figure(fig) cost, patch, cdata, _ = evaluateCross(fitparam, imx, verbose=verbose, fig=fig_anticross.number, istep=istep, istepmodel=istepmodel, w=w) anticross_fit['cost'] = cost anticross_fit['patch'] = patch anticross_fit['cdata'] = cdata anticross_fit['fig_num'] = fig_anticross.number anticross_fit['imx'] = imx return anticross_fit