# Achieving high stitching accuracy

Data will be stitched using [StitchIt](https://github.com/SWC-Advanced-Microscopy/StitchIt). StitchIt assembles stitched sections out of individual tiles by placing images according to their position in the image grid and the number of microns per pixel of the images. If the number of microns per pixel is not accurate, the tile placement will also not be accurate. Furthermore, StitchIt will assume images are undistorted and that the stage motions are perfectly in line with the scan axes. Deviations from the above will cause imperfections in stitching accuracy. These instructions explain how to create tweaked microns per pixel values and correct for any image distortion prior to stitching.

It assumed that you have already:

* [Calibrated the number of microns per pixel](https://github.com/SWC-Advanced-Microscopy/BakingTray/wiki/Calibrating-the-number-of-microns-per-pixel-with-ScanImage).
* [Aligned the scanners and stages correctly](https://github.com/SWC-Advanced-Microscopy/BakingTray/wiki/Basic-calibrating-procedures) and you should already know if imaging a grid results in non-square grid lines.

You will need to install StitchIt before proceeding.

## Measuring and correcting for image distortion

### Note before you start

The following instructions explain how to use an EM grid to measure barrel/pincushion distortion and correct for independently along the two scan axes. It is not completely clear at present whether this is necessary. You can go through the following instructions, determine correction values, then try them out. Be open to the possibility that you might get better stitching accuracy without this correction applied: try both with and without.

### Measuring distortion

Acquire a uniform EM grid. Part number 2145C from [2spi](https://github.com/raacampbell/bakingtray_docs/tree/aa53947efba18b64e6d15320116ffccf214adfb7/getting_started/finishing_the_installation/calibration/www.2spi.com/category/grids/README.md) works well. This grid has a pitch of 25 microns, a hole width of 19 microns, and a bar width of 6 microns. Place the grid on a slide and seal with a coverslip and nail varnish. Image the grid at low power: the copper will auto-fluoresce under a 2-photon laser. Align the grid with the image axes. Use a higher image resolution (1 micron per pixel should do). This will make easiest to see any barrel or pincushion distortion. Inspect the image. If you see noticeable distortion then do the following:

1\) Right click on the channel window and copy the image to the base workspace. 2) The `stitchit.tools.lensdistort` command to correct for the distortion. e.g. see what `imagesc(stitchit.tools.lensdistort(ImageData,0.2))` looks like. You will need to experiment and see the function help: note that `k` can be vector.

Once you have settings that look reasonable to the eye, note down the values.

Modify the scan settings file so it contains these numbers under a field called `lensDistort`. You will also want to add the fields `affineMat` and `stitchingVoxelSize` to handle shear and to get exact numbers for the stitching accuracy. **File an issue if you need help with this now. Docs to come.**

```
 setB:
  objective: nikon16x
  pixelsPerLine: 750
  linesPerFrame: 750
  zoomFactor: 1.0
  nominalMicronsPerPixel: 1.667
  fastMult: 1
  slowMult: 1
  objRes: 53.44
  lensDistort: {rows: 0, cols: 0.03}
  affineMat: 
    - [1, -0.014,   0]
    - [0.0,    1,   0]
    - [0,      0,   1]
  stitchingVoxelSize: {X: 0.673, Y: 0.658}
```

You will likely need to repeat the measurements for different zoom values but not for different image resolutions.

## Tweaking the number of microns per pixel

Acquire a small tile of scan of a sample with structure. Agar with dissolved fluorescent marker pen will do. You can acquire just one small 9 by 9 grid with one section and one optical plane. Make sure you uncheck the boxes to turn off the laser and to slice. The laser box you will have to uncheck ***after*** the acquisition starts. Use imaging settings where you have entered a `lensDistort` value in the `yml` if needed. Once the acquisition is done you can verify that indeed you can see the `lensDistort` value in the recipe yml file. Stitch the data with chessboard stitching. e.g.

```
stitchSection([1,1],2,'chessboard',1,'overwrite',1)
```

Visualise and look at the overlap regions. If you see too much overlap you need to decrease the number of microns per pixel. Too little overlap means you need to increase it. The settings you need to change are:

```
StitchingParameters: 
  VoxelSize: {X: 1.2212, Y: 1.221}
```

Play with one at a time to see which affects which axis.

If you continue to see offsets that seem like sideways offsets then you can add an affine term. e.g. these parameters will add some distortion along the columns and perform a skew along one axis.

```
StitchingParameters:
  VoxelSize: {X: 1.654, Y: 1.615}
  lensDistort: {rows: 0.0, cols: 0.03}
  affineMat:
  - [1.0, -0.011, 0.0]
  - [0.0, 1.0, 0.0]
  - [0.0, 0.0, 1.0]
```

Save the recipe and re-stitch after each attempt.

This affine matrix is equivalent to doing `imrotate` by -0.75 degrees:

```
  - [0.9999, -0.0131, 0.0]
  - [0.0131, 0.9999,  0.0]
  - [0.0,      0.0,   1.0]
```

This is because:

```
>> cos(deg2rad(-0.75))
ans =
    0.9999

>> sin(deg2rad(-0.75))   
ans =
   -0.0131
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://bakingtray.mouse.vision/getting-started/finishing-the-install/calibration/achieving-high-stitching-accuracy.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
