Ejemplo n.º 1
0
    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)
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
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