def calibrate_stage_lowmag_from_image_fn(center_fn, other_fn):
    """
    Calibrate pixel->stageposition coordinates from a set of images

    center_fn: `str`
        Reference image at the center of the grid (with the clover in the middle)
    other_fn: `tuple` of `str`
        Set of images to cross correlate to the first reference image

    return:
        instance of Calibration class with conversion methods
    """
    img_cent, h_cent = load_img(center_fn)
    
    img_cent, scale = autoscale(img_cent, maxdim=512)

    x_cent, y_cent, _, _, _ = h_cent["StagePosition"]
    xy_cent = np.array([x_cent, y_cent])
    print("Center:", center_fn)
    print("Stageposition: x={:.0f} | y={:.0f}".format(*xy_cent))
    print()

    binsize = h_cent["ImageBinSize"]

    shifts = []
    stagepos = []
    
    # gridsize = 5
    # stepsize = 50000
    # n = (gridsize - 1) / 2 # number of points = n*(n+1)
    # x_grid, y_grid = np.meshgrid(np.arange(-n, n+1) * stepsize, np.arange(-n, n+1) * stepsize)
    # stagepos_p = np.array(zip(x_grid.flatten(), y_grid.flatten()))

    for fn in other_fn:
        img, h = load_img(fn)

        img = imgscale(img, scale)
        
        xobs, yobs, _, _, _ = h["StagePosition"]
        print("Image:", fn)
        print(f"Stageposition: x={xobs:.0f} | y={yobs:.0f}")
        print()
        
        shift = cross_correlate(img_cent, img, upsample_factor=10, verbose=False)
        
        stagepos.append((xobs, yobs))
        shifts.append(shift)

    # correct for binsize, store as binsize=1
    shifts = np.array(shifts) * binsize / scale
    stagepos = np.array(stagepos) - xy_cent

    c = CalibStage.from_data(shifts, stagepos, reference_position=xy_cent, header=h_cent)
    c.plot()

    return c
Ejemplo n.º 2
0
        def one_cycle(tilt: float=5, sign=1) -> list:
            angle1 = -tilt*sign
            self.stageposition.a = angle1
            img1 = self.getRawImage()
            
            angle2 = +tilt*sign
            self.stageposition.a = angle2
            img2 = self.getRawImage()
            
            if sign < 1:
                img2, img1 = img1, img2

            shift = cross_correlate(img1, img2, upsample_factor=10, verbose=verbose)

            return shift
Ejemplo n.º 3
0
def calibrate_directbeam_from_file(center_fn, other_fn, key="DiffShift"):
    print()
    print("Center:", center_fn)

    img_cent, h_cent = load_img(center_fn)
    readout_cent = np.array(h_cent[key])

    img_cent, scale = autoscale(img_cent, maxdim=512)

    binsize = h_cent["ImageBinSize"]

    print("{}: x={} | y={}".format(key, *readout_cent))

    shifts = []
    readouts = []

    for i, fn in enumerate(other_fn):
        print(fn)
        img, h = load_img(fn)
        img = imgscale(img, scale)

        readout = np.array((h[key]))
        print()
        print("Image:", fn)
        print("{}: dx={} | dy={}".format(key, *readout))

        shift = cross_correlate(img_cent,
                                img,
                                upsample_factor=10,
                                verbose=False)

        readouts.append(readout)
        shifts.append(shift)

    # correct for binsize, store in binsize=1
    shifts = np.array(shifts) * binsize / scale
    readouts = np.array(readouts) - np.array((readout_cent))

    c = CalibDirectBeam.from_data(shifts,
                                  readouts,
                                  key,
                                  header=h_cent,
                                  **refine_params[key])
    c.plot(key)

    return c
Ejemplo n.º 4
0
    def align_to(self, ref_img: "np.array", 
                       apply: bool= True,
                       verbose: bool=True) -> list:
        """Align current view by comparing it against the given image using
        cross correlation. The stage is translated so that the object of interest
        (in the reference image) is at the center of the view.
        
        Parameters
        ----------
        ref_img: np.array
            Reference image that the microscope will be aligned to
        apply: bool
            Toggle to translate the stage to center the image
        verbose: bool
            Be more verbose
        
        Returns
        -------
        stage_shift : np.array[2]
            The stage shift vector determined from cross correlation
            
        """
        from instamatic.processing.cross_correlate import cross_correlate

        current_x, current_y = self.stageposition.xy
        print(f"Current stage position: {current_x:.0f} {current_y:.0f}")
        stagematrix = self.get_stagematrix()
        mati = np.linalg.inv(stagematrix)

        img = self.getRawImage()

        pixel_shift = cross_correlate(ref_img, img, upsample_factor=10, verbose=verbose)

        stage_shift = np.dot(pixel_shift, mati)

        print(f"Shifting stage by dx={stage_shift[0]:.2f} dy={stage_shift[1]:.2f}")

        new_x = current_x - stage_shift[0] 
        new_y = current_y + stage_shift[1] 
        print(f"New stage position: {new_x:.0f} {new_y:.0f}")
        if apply:
            self.stageposition.set_xy_with_backlash_correction(x=new_x, y=new_y)

        return stage_shift
Ejemplo n.º 5
0
def center_z_height(ctrl, verbose=False):
    """Automated routine to find the z-height

    Koster, A. J., et al. "Automated microscopy for electron tomography." 
    Ultramicroscopy 46.1-4 (1992): 207-227.
    http://www.msg.ucsf.edu/agard/Publications/52-Koster.pdf
    """
    print("\033[k", "Finding eucentric height...", end="\r")
    if ctrl.mode != 'mag1':
        ctrl.mode = 'mag1'

    ctrl.brightness.value = 65535
    ctrl.magnification.value = 2500

    z0 = ctrl.stageposition.z
    ctrl.stageposition.set(a=-5)
    a0 = ctrl.stageposition.a
    z = []
    d = []
    ctrl.stageposition.z = z0 - 2000
    ctrl.stageposition.z = z0 - 1000
    ctrl.stageposition.z = z0

    for i in range(0, 10):
        z1 = ctrl.stageposition.z
        ctrl.stageposition.set(a=a0)
        img0, h = ctrl.getImage(exposure=0.01, comment="z height finding")
        z.append(z0 + i * 1000)
        ctrl.stageposition.set(a=a0 + 10)
        img1, h = ctrl.getImage(exposure=0.01, comment="z height finding")
        shift = cross_correlate(img0, img1, upsample_factor=10, verbose=False)
        d1 = np.linalg.norm(shift)
        if shift[0] < 0:
            d1 = -d1
        d.append(d1)
        if verbose:
            print(f"Step {i}: z = {z1}, d = {np.linalg.norm(shift)}")
        ctrl.stageposition.set(z=z1 + 1000)
        time.sleep(1)

    d_f = reject_outlier(d)
    z_f = []
    for e in d_f:
        z_f.append(z[d.index(e)])
    p = np.polyfit(z, d, 1)
    z_center = -p[1] / p[0]
    satisfied = input(
        f"Found eucentric height: {z_center}. Press ENTER to set the height, x to cancel setting."
    )
    if satisfied == "x":
        ctrl.stageposition.set(a=a0, z=z0)
        if verbose:
            print("Did not find proper eucentric height...")
    else:
        if z_center > ctrl.stageposition.z:
            ctrl.stageposition.set(a=a0, z=z_center - 2000)
            ctrl.stageposition.set(a=a0, z=z_center)
        else:
            ctrl.stageposition.set(a=a0, z=z_center + 2000)
            ctrl.stageposition.set(a=a0, z=z_center)

        print(
            "\033[k",
            "Eucentric height set. Find the crystal again and start data collection!",
            end="\r")
Ejemplo n.º 6
0
def calibrate_mag1_live(ctrl,
                        gridsize=5,
                        stepsize=5000,
                        minimize_backlash=True,
                        save_images=False,
                        **kwargs):
    """
    Calibrate pixel->stageposition coordinates live on the microscope

    ctrl: instance of `TEMController`
        contains tem + cam interface
    gridsize: `int`
        Number of grid points to take, gridsize=5 results in 25 points
    stepsize: `float`
        Size of steps for stage position along x and y
    minimize_backlash: bool,
        Attempt to minimize backlash by overshooting a bit
        Follows the routine from Oostergetel (1998): https://doi.org/10.1016/S0304-3991(98)00022-9
    exposure: `float`
        Exposure time in seconds
    binsize: `int`

    return:
        instance of Calibration class with conversion methods
    """

    work_drc = get_new_work_subdirectory(stem="calib_mag1")

    settle_delay = 1.0  # seconds

    # make sure the angle == 0.0
    for _ in range(3):
        ctrl.stageposition.a = 0.0
        time.sleep(settle_delay)

    exposure = kwargs.get("exposure", config.camera.default_exposure)
    binsize = kwargs.get("binsize", config.camera.default_binsize)

    if minimize_backlash:
        ctrl.stageposition.eliminate_backlash_xy(step=stepsize,
                                                 settle_delay=settle_delay)

    outfile = work_drc / "calib_start" if save_images else None

    # Accurate reading fo the center positions is needed so that we can come back to it,
    #  because this will be our anchor point
    img_cent, h_cent = ctrl.getImage(exposure=exposure,
                                     binsize=binsize,
                                     out=outfile,
                                     comment="Center image (start)")
    stage_cent = ctrl.stageposition.get()

    cam_dimensions = h_cent["ImageCameraDimensions"]
    bin_x, bin_y = cam_dimensions / np.array(img_cent.shape)
    assert bin_x == bin_y, "Binsizes do not match {bin_x} != {bin_y}"
    binsize = int(bin_x)

    x_cent = stage_cent.x
    y_cent = stage_cent.y

    xy_cent = np.array([x_cent, y_cent])

    img_cent, scale = autoscale(img_cent)

    stagepos = []
    shifts = []

    n = int((gridsize - 1) / 2)  # number of points = n*(n+1)
    x_grid, y_grid = np.meshgrid(
        np.arange(-n, n + 1) * stepsize,
        np.arange(-n, n + 1) * stepsize)
    tot = gridsize * gridsize

    i = 0

    x_range = np.arange(-n, n + 1) * stepsize
    y_range = np.arange(-n, n + 1) * stepsize

    if minimize_backlash:
        xtarget = x_cent + x_range[0]
        ytarget = y_cent + y_range[0]
        ctrl.stageposition.set(x=xtarget - stepsize, y=ytarget - stepsize)
        time.sleep(settle_delay)

        print("(minimize_backlash) Overshoot a bit in XY: ",
              ctrl.stageposition.xy)

    for dx in x_range:
        for dy in y_range:
            ctrl.stageposition.set(x=x_cent + dx, y=y_cent + dy)
            time.sleep(settle_delay)
            stage = ctrl.stageposition.get()

            print()
            print(f"Position {I+1}/{tot}")
            print(stage)

            outfile = work_drc / f"calib_{i:04d}" if save_images else None

            comment = f"Calib image {i}: dx={dx} - dy={dy}"
            img, h = ctrl.getImage(exposure=exposure,
                                   binsize=binsize,
                                   out=outfile,
                                   comment=comment)

            img = imgscale(img, scale)

            shift = cross_correlate(img_cent,
                                    img,
                                    upsample_factor=10,
                                    verbose=False)

            xobs = stage.x
            yobs = stage.y

            stagepos.append((xobs, yobs))
            shifts.append(shift)

            i += 1

        if minimize_backlash:
            ytarget = y_cent + y_range[0]
            ctrl.stageposition.set(y=ytarget - stepsize)
            time.sleep(settle_delay)
            print("(minimize_backlash) Overshoot a bit in Y: ",
                  ctrl.stageposition.xy)

    print(" >> Reset to center")
    ctrl.stageposition.set(x=x_cent, y=y_cent)
    time.sleep(settle_delay)
    # ctrl.stageposition.reset_xy()

    # correct for binsize, store as binsize=1
    shifts = np.array(shifts) * binsize / scale
    stagepos = np.array(stagepos) - np.array((x_cent, y_cent))

    m = gridsize**2 // 2
    if gridsize % 2 and stagepos[m].max() > 50:
        print(
            f" >> Warning: Large difference between image {m}, and center image. These should be close for a good calibration."
        )
        print("    Difference:", stagepos[m])
        print()

    if save_images:
        outfile = work_drc / "calib_end"
        ctrl.getImage(exposure=exposure,
                      binsize=binsize,
                      out=outfile,
                      comment="Center image (end)")

    c = CalibStage.from_data(shifts,
                             stagepos,
                             reference_position=xy_cent,
                             camera_dimensions=cam_dimensions)
    c.plot()
    c.to_file(work_drc / "calib.pickle")

    return c
Ejemplo n.º 7
0
def calibrate_mag1_from_image_fn(center_fn, other_fn):
    """
    Calibrate pixel->stageposition coordinates from a set of images

    center_fn: `str`
        Reference image at the center of the grid (with the clover in the middle)
    other_fn: `tuple` of `str`
        Set of images to cross correlate to the first reference image

    return:
        instance of Calibration class with conversion methods
    """
    img_cent, h_cent = read_image(center_fn)

    # binsize = h_cent["ImageBinSize"]
    cam_dimensions = h_cent["ImageCameraDimensions"]
    bin_x, bin_y = cam_dimensions / np.array(img_cent.shape)
    assert bin_x == bin_y, "Binsizes do not match {bin_x} != {bin_y}"
    binsize = int(bin_x)

    img_cent, scale = autoscale(img_cent, maxdim=512)

    x_cent, y_cent, _, _, _ = h_cent["StagePosition"]
    # x_cent=40943.0
    # y_cent=-6258.4

    xy_cent = np.array([x_cent, y_cent])
    print("Center:", center_fn)
    print("Stageposition: x={:.0f} | y={:.0f}".format(*xy_cent))
    print()

    shifts = []
    stagepos = []

    # stage = ((30943.5, -16255.5),
    # (30874.701171875, -11258.2998046875),
    # (31009.701171875, -6256.89990234375),
    # (30876.0, -1256.9000244140625),
    # (31011.0, 3744.400146484375),
    # (35943.5, -16256.900390625),
    # (35874.6015625, -11256.900390625),
    # (36011.0, -6256.89990234375),
    # (35874.6015625, -1256.9000244140625),
    # (36012.30078125, 3743.0),
    # (40943.40234375, -16252.7001953125),
    # (40943.40234375, -11256.900390625),
    # (40943.40234375, -6258.30029296875),
    # (40943.40234375, -1256.9000244140625),
    # (40943.40234375, 3744.400146484375),
    # (45943.40234375, -16255.5),
    # (45943.40234375, -11258.2998046875),
    # (45943.40234375, -6255.5),
    # (45943.40234375, -1259.7000732421875),
    # (45943.40234375, 3745.800048828125),
    # (50943.40234375, -16255.5),
    # (50943.40234375, -11258.2998046875),
    # (50943.40234375, -6256.89990234375),
    # (50943.40234375, -1256.9000244140625),
    # (50943.40234375, 3743.0))

    for i, fn in enumerate(other_fn):
        img, h = read_image(fn)

        img = imgscale(img, scale)

        x_xobs, yobs, _, _, _ = h_cent["StagePosition"]
        # xobs, yobs = stage[i]
        print("Image:", fn)
        print(f"Stageposition: x={xobs:.0f} | y={yobs:.0f}")

        shift = cross_correlate(img_cent,
                                img,
                                upsample_factor=10,
                                verbose=False)
        print("Shift:", shift)
        print()

        stagepos.append((xobs, yobs))
        shifts.append(shift)

    # correct for binsize, store as binsize=1
    shifts = np.array(shifts) * binsize / scale
    stagepos = np.array(stagepos) - xy_cent

    c = CalibStage.from_data(shifts,
                             stagepos,
                             reference_position=xy_cent,
                             camera_dimensions=cam_dimensions)
    c.plot()
    c.to_file()

    return c
Ejemplo n.º 8
0
def calibrate_beamshift_from_image_fn(center_fn, other_fn):
    """
    Calibrate pixel->beamshift coordinates from a set of images

    center_fn: `str`
        Reference image with the beam at the center of the image
    other_fn: `tuple` of `str`
        Set of images to cross correlate to the first reference image

    return:
        instance of Calibration class with conversion methods
    """
    print()
    print("Center:", center_fn)

    img_cent, h_cent = load_img(center_fn)
    beamshift_cent = np.array(h_cent["BeamShift"])

    img_cent, scale = autoscale(img_cent, maxdim=512)

    binsize = h_cent["ImageBinSize"]

    holes = find_holes(img_cent,
                       plot=False,
                       verbose=False,
                       max_eccentricity=0.8)
    pixel_cent = np.array(holes[0].centroid) * binsize / scale

    print("Beamshift: x={} | y={}".format(*beamshift_cent))
    print("Pixel: x={:.2f} | y={:.2f}".format(*pixel_cent))

    shifts = []
    beampos = []

    for fn in other_fn:
        img, h = load_img(fn)
        img = imgscale(img, scale)

        beamshift = np.array((h["BeamShift"]))
        print()
        print("Image:", fn)
        print("Beamshift: x={} | y={}".format(*beamshift))

        shift = cross_correlate(img_cent,
                                img,
                                upsample_factor=10,
                                verbose=False)

        beampos.append(beamshift)
        shifts.append(shift)

    # correct for binsize, store as binsize=1
    shifts = np.array(shifts) * binsize / scale
    beampos = np.array(beampos) - beamshift_cent

    c = CalibBeamShift.from_data(shifts,
                                 beampos,
                                 reference_shift=beamshift_cent,
                                 reference_pixel=pixel_cent,
                                 header=h_cent)
    c.plot()

    return c
Ejemplo n.º 9
0
def calibrate_beamshift_live(ctrl,
                             gridsize=None,
                             stepsize=None,
                             save_images=False,
                             outdir=".",
                             **kwargs):
    """
    Calibrate pixel->beamshift coordinates live on the microscope

    ctrl: instance of `TEMController`
        contains tem + cam interface
    gridsize: `int` or None
        Number of grid points to take, gridsize=5 results in 25 points
    stepsize: `float` or None
        Size of steps for beamshift along x and y
        Defined at a magnification of 2500, scales stepsize down for other mags.
    exposure: `float` or None
        exposure time
    binsize: `int` or None

    In case paramers are not defined, camera specific default parameters are retrieved

    return:
        instance of Calibration class with conversion methods
    """

    exposure = kwargs.get("exposure", ctrl.cam.default_exposure)
    binsize = kwargs.get("binsize", ctrl.cam.default_binsize)

    if not gridsize:
        gridsize = config.camera.calib_beamshift.get("gridsize", 5)
    if not stepsize:
        stepsize = config.camera.calib_beamshift.get("stepsize", 250)

    img_cent, h_cent = ctrl.getImage(exposure=exposure,
                                     binsize=binsize,
                                     comment="Beam in center of image")
    x_cent, y_cent = beamshift_cent = np.array(h_cent["BeamShift"])

    magnification = h_cent["Magnification"]
    stepsize = 2500.0 / magnification * stepsize

    print(f"Gridsize: {gridsize} | Stepsize: {stepsize:.2f}")

    img_cent, scale = autoscale(img_cent)

    outfile = os.path.join(outdir, "calib_beamcenter") if save_images else None

    pixel_cent = find_beam_center(img_cent) * binsize / scale

    print("Beamshift: x={} | y={}".format(*beamshift_cent))
    print("Pixel: x={} | y={}".format(*pixel_cent))

    shifts = []
    beampos = []

    n = int((gridsize - 1) / 2)  # number of points = n*(n+1)
    x_grid, y_grid = np.meshgrid(
        np.arange(-n, n + 1) * stepsize,
        np.arange(-n, n + 1) * stepsize)
    tot = gridsize * gridsize

    i = 0
    for dx, dy in np.stack([x_grid, y_grid]).reshape(2, -1).T:
        ctrl.beamshift.set(x=x_cent + dx, y=y_cent + dy)

        printer("Position: {}/{}: {}".format(i + 1, tot, ctrl.beamshift))

        outfile = os.path.join(
            outdir, "calib_beamshift_{i:04d}") if save_images else None

        comment = f"Calib image {i}: dx={dx} - dy={dy}"
        img, h = ctrl.getImage(exposure=exposure,
                               binsize=binsize,
                               out=outfile,
                               comment=comment,
                               header_keys="BeamShift")
        img = imgscale(img, scale)

        shift = cross_correlate(img_cent,
                                img,
                                upsample_factor=10,
                                verbose=False)

        beamshift = np.array(h["BeamShift"])
        beampos.append(beamshift)
        shifts.append(shift)

        i += 1

    print("")
    # print "\nReset to center"

    ctrl.beamshift.set(*beamshift_cent)

    # correct for binsize, store in binsize=1
    shifts = np.array(shifts) * binsize / scale
    beampos = np.array(beampos) - np.array((beamshift_cent))

    c = CalibBeamShift.from_data(shifts,
                                 beampos,
                                 reference_shift=beamshift_cent,
                                 reference_pixel=pixel_cent,
                                 header=h_cent)

    # Calling c.plot with videostream crashes program
    # if not hasattr(ctrl.cam, "VideoLoop"):
    #     c.plot()

    return c
Ejemplo n.º 10
0
def calibrate_directbeam_live(ctrl,
                              key="DiffShift",
                              gridsize=None,
                              stepsize=None,
                              save_images=False,
                              outdir=".",
                              **kwargs):
    """
    Calibrate pixel->beamshift coordinates live on the microscope

    ctrl: instance of `TEMController`
        contains tem + cam interface
    key: `str`
        Name of property to calibrate
    gridsize: `int` or None
        Number of grid points to take, gridsize=5 results in 25 points
    stepsize: `float` or None
        Size of steps for property along x and y
    exposure: `float` or None
        exposure time
    binsize: `int` or None

    In case paramers are not defined, camera specific default parameters are 

    return:
        instance of Calibration class with conversion methods
    """

    if not ctrl.mode == "diff":
        print(" >> Switching to diffraction mode")
        ctrl.mode_diffraction()

    exposure = kwargs.get("exposure", ctrl.cam.default_exposure)
    binsize = kwargs.get("binsize", ctrl.cam.default_binsize)

    if not gridsize:
        gridsize = config.camera.calib_directbeam.get(key, {}).get(
            "gridsize", 5)  # dat syntax...
    if not stepsize:
        stepsize = config.camera.calib_directbeam.get(key, {}).get(
            "stepsize", 750)  # just to fit everything on 1 line =)

    attr = getattr(ctrl, key.lower())

    outfile = os.path.join(outdir,
                           f"calib_db_{key}_0000") if save_images else None
    img_cent, h_cent = ctrl.getImage(exposure=exposure,
                                     binsize=binsize,
                                     comment="Beam in center of image",
                                     out=outfile)
    x_cent, y_cent = readout_cent = np.array(h_cent[key])

    img_cent, scale = autoscale(img_cent)

    print("{}: x={} | y={}".format(key, *readout_cent))

    shifts = []
    readouts = []

    n = int((gridsize - 1) / 2)  # number of points = n*(n+1)
    x_grid, y_grid = np.meshgrid(
        np.arange(-n, n + 1) * stepsize,
        np.arange(-n, n + 1) * stepsize)
    tot = gridsize * gridsize

    for i, (dx, dy) in enumerate(np.stack([x_grid, y_grid]).reshape(2, -1).T):
        i += 1

        attr.set(x=x_cent + dx, y=y_cent + dy)

        printer("Position: {}/{}: {}".format(i, tot, attr))

        outfile = os.path.join(
            outdir, f"calib_db_{key}_{i:04d}") if save_images else None

        comment = f"Calib image {i}: dx={dx} - dy={dy}"
        img, h = ctrl.getImage(exposure=exposure,
                               binsize=binsize,
                               out=outfile,
                               comment=comment,
                               header_keys=key)
        img = imgscale(img, scale)

        shift = cross_correlate(img_cent,
                                img,
                                upsample_factor=10,
                                verbose=False)

        readout = np.array(h[key])
        readouts.append(readout)
        shifts.append(shift)

    print("")
    # print "\nReset to center"
    attr.set(*readout_cent)

    # correct for binsize, store in binsize=1
    shifts = np.array(shifts) * binsize / scale
    readouts = np.array(readouts) - np.array((readout_cent))

    c = CalibDirectBeam.from_data(shifts,
                                  readouts,
                                  key,
                                  header=h_cent,
                                  **refine_params[key])

    # Calling c.plot with videostream crashes program
    # if not hasattr(ctrl.cam, "VideoLoop"):
    #     c.plot(key)

    return c
Ejemplo n.º 11
0
def Calibrate_Imageshift(ctrl, diff_defocus, stepsize, logger, key="IS1"):

    if key != 'S':
        inp = input(f"""Calibrate {key}
    -------------------
     1. Go to diffraction mode.
     2. Focus the diffraction spots.
     3. Center the beam with PLA.
        
     >> Press <ENTER> to start >> \n""")
    else:
        inp = input("""Calibrate stage vs camera
        ------------------
        1. Go to mag1.
        2. Find area with particles.
        
        >> Press <ENTER> to start >> \n""")

    d = {
        "IS1": ctrl.imageshift1,
        "IS2": ctrl.imageshift2,
        "BS": ctrl.beamshift,
        "S": ctrl.stageposition
    }

    if diff_defocus != 0:
        diff_focus_proper = ctrl.difffocus.value
        diff_focus_defocused = diff_focus_proper + diff_defocus
        ctrl.difffocus.value = diff_focus_defocused

    deflector = d[key]

    if key != "S":
        x0, y0 = deflector.get()
        scaling = True
    else:
        x0 = deflector.x
        y0 = deflector.y
        scaling = False

    img_cent, h_cent = ctrl.getImage(exposure=0.01,
                                     comment="Beam in center of image")

    shifts = []
    imgpos = []
    stepsize = stepsize

    for i in tqdm(range(0, 5)):
        for j in range(0, 5):
            deflector.set(x=x0 + (i - 2) * stepsize, y=y0 + (j - 2) * stepsize)
            img, h = ctrl.getImage(exposure=0.01, comment="imageshifted image")

            shift = cross_correlate(img_cent,
                                    img,
                                    upsample_factor=10,
                                    verbose=False)
            imgshift = np.array(((i - 2) * stepsize, (j - 2) * stepsize))
            imgpos.append(imgshift)
            shifts.append(shift)

    deflector.set(x=x0, y=y0)

    r, t = fit_affine_transformation(shifts, imgpos, scaling=scaling)

    result = fit_affine_transformation(shifts,
                                       imgpos,
                                       scaling=scaling,
                                       as_params=True)

    if diff_defocus != 0:
        ctrl.difffocus.value = diff_focus_proper

    print("ImageShift calibration done.")

    print("Transformation matrix: ", r)
    logger.debug(f"Transformation matrix: {r}")
    logger.debug(f"Parameters: angle: {result['angle']}")
    logger.debug(f"sx: {result['sx']}")
    logger.debug(f"sy: {result['sy']}")
    logger.debug(f"tx: {result['tx']}")
    logger.debug(f"ty: {result['ty']}")
    logger.debug(f"k1: {result['k1']}")
    logger.debug(f"k2: {result['k2']}")

    r_i = np.linalg.inv(r)
    imgpos_ = np.dot(imgpos, r_i)
    shifts = np.array(shifts)
    imgpos_ = np.array(imgpos_)

    c = [imgpos_, shifts]

    return r, c
Ejemplo n.º 12
0
def calibrate_stage_lowmag_live(ctrl, gridsize=5, stepsize=50000, save_images=False, **kwargs):
    """
    Calibrate pixel->stageposition coordinates live on the microscope

    ctrl: instance of `TEMController`
        contains tem + cam interface
    gridsize: `int`
        Number of grid points to take, gridsize=5 results in 25 points
    stepsize: `float`
        Size of steps for stage position along x and y
    exposure: `float`
        exposure time
    binsize: `int`

    return:
        instance of Calibration class with conversion methods
    """

    exposure = kwargs.get("exposure", ctrl.cam.default_exposure)
    binsize = kwargs.get("binsize", ctrl.cam.default_binsize)

    outfile = "calib_start" if save_images else None

    # Accurate reading fo the center positions is needed so that we can come back to it,
    #  because this will be our anchor point
    img_cent, h_cent = ctrl.getImage(exposure=exposure, binsize=binsize, out=outfile, comment="Center image (start)")

    x_cent, y_cent, _, _, _ = h_cent["StagePosition"]
    xy_cent = np.array([x_cent, y_cent])
    
    img_cent, scale = autoscale(img_cent)

    stagepos = []
    shifts = []
    
    n = int((gridsize - 1) / 2) # number of points = n*(n+1)
    x_grid, y_grid = np.meshgrid(np.arange(-n, n+1) * stepsize, np.arange(-n, n+1) * stepsize)
    tot = gridsize*gridsize

    i = 0
    for dx,dy in np.stack([x_grid, y_grid]).reshape(2,-1).T:
        print()
        print(f"Position {i+1}/{tot}: x: {x_cent+dx:.0f}, y: {y_cent+dy:.0f}")
        
        ctrl.stageposition.set(x=x_cent+dx, y=y_cent+dy)
        print(ctrl.stageposition)
        
        outfile = f"calib_{i:04d}" if save_images else None

        comment = comment
        img, h = ctrl.getImage(exposure=exposure, binsize=binsize, out=outfile, comment=comment, header_keys="StagePosition")
        
        img = imgscale(img, scale)

        shift = cross_correlate(img_cent, img, upsample_factor=10, verbose=False)
        
        xobs, yobs, _, _, _ = h["StagePosition"]
        stagepos.append((xobs, yobs))
        shifts.append(shift)
        
        i += 1
    
    print(" >> Reset to center")
    ctrl.stageposition.set(x=x_cent, y=y_cent)
    ctrl.stageposition.reset_xy()

    # correct for binsize, store as binsize=1
    shifts = np.array(shifts) * binsize / scale
    stagepos = np.array(stagepos) - np.array((x_cent, y_cent))

    m = gridsize**2 // 2 
    if gridsize % 2 and stagepos[m].max() > 50:
        print(f" >> Warning: Large difference between image {m}, and center image. These should be close for a good calibration.")
        print("    Difference:", stagepos[m])
        print()
    
    if save_images:
        ctrl.getImage(exposure=exposure, binsize=binsize, out="calib_end", comment="Center image (end)")

    c = CalibStage.from_data(shifts, stagepos, reference_position=xy_cent, header=h_cent)
    
    # Calling c.plot with videostream crashes program
    if not hasattr(ctrl.cam, "VideoLoop"):
        c.plot(key)

    return c