Calibrating image size

Calibrating image size

Calibrating the number of microns per pixel

BakingTray uses the number of microns per pixel reported by ScanImage to determine where to move the stages. If this number is wrong you will get stitching problems. You will need to perform these steps when you first set up your system and also if you ever have to replace a scanner, since different scanners have slightly different gains. You may also need to repeat these steps for different versions of ScanImage. e.g. sometimes the scanner waveforms change slightly between releases.

There are two related procedures: one for "square" images, where the number of lines per frame and the number of pixels per line are the same. With square images it's pretty easy to just change the number pixels per line to change the resolution. Non-square images are discussed at the end.

Before you begin

  • Acquire bunch of copper EM grids. 1000 mesh (25 micron pitch) or 2000 mesh (12.5 micron pitch) both work well.

  • Carefully place a grid on a glass slide using forceps under a binocular dissection scope.

  • Align the square grid such that lines are parallel with the slide edges. This will be useful later on.

  • Place a coverslip over the grid and seal the edges with nail varnish such that water can't get in.

  • The metal grid will emit visible light when excited with a 2p laser at most wavelengths. e.g. 850 nm will work well.

  • Install measurePSF.

    You will use the provided Grid2MicsPerPixel function to measure the exact number of microns per pixel along the rows and columns of your grid images.

Protocol for calibrating ScanImage with square images

  • In the ScanImage CONFIGURATION window check "Pix=Lin" and "Square Pix"

  • Copy the scan waveforms to an osciloscope with BNC cables and T-connectors

  • Place the grid slide under the objective and obtain an image.

  • Orient the EM grid so that the grid axes run parallel to the imaging axes (it's OK to be a couple of degrees out).

  • Set zoom to 1

  • Choose 512 x 512 pixels

The goal is to obtain the largest FOV possible with the same number of microns per pixel along each axis. When you hit "Focus" you get an image and also you see the amplitude of the scan waveforms. You want a square image of the grid with the resonant mirror control signal at its maximum (probably +5V).

  • Confirm the resonant resonant control signal is at the expected maximum value (probably 5V, but check with the spec sheet or manufacturer. e.g. CamTech 4 kHz scanners have a maximum control value <5 V).

  • Confirm that the grid looks close to square by eye.

  • If the grid does not look near-square then you should stop scanning and edit the number of volts per optical degree for the Y mirror (galvo) in via the ScanImage settings. Editing the value will have an impact immediately, so you can test your new settings right away.

To measure the number of microns per pixel:

  • Correct the bidirectional scanning artifact.

  • Average on-screen about 10 or 20 frames to get a nice image then stop scanning.

  • Run Grid2MicsPerPixel, which pulls the data directly from ScanImage. A new window will appear with the grid fitted and the number of microns per pixel in X and Y reported.

  • It doesn't matter if not all grid lines are detected, the reported values are based on the median number of pixels between adjacent grid lines.

  • Tweak the galvo control signal again if needed.

  • The Grid2MicsPerPixel allows you to re-import a new image from ScanImage as needed.

  • Play with the galvo amplitude parameter until the grid looks square at a zoom of 1 and a maximum resonant mirror control signal. Don't worry if you can not get the image perfectly square. Being out by 1% or 2% is no big deal and we will deal with this later.

Setting the FoV size in ScanImage

Once the image is square, press the "Apply FOV" in the "Grid2MicsPerPixel" GUI. This button correctly sets the ScanImage property hSI.objectiveResolution so that ScanImage reports the number of microns per pixel correctly. The FoV size and the value of hSI.objectiveResolution are printed the MATLAB command line.

Hints:

  • Leave the resonant scanner on the whole time so that it settles down.

  • Average 10 frames to improve SNR.

  • If the galvo waveform exceeds +/-10 V you will get a cryptic error about the output buffer being empty.

Setting up rectangular images

The following instructions are relevant for systems that have a reduced scan angle along one axis, for instance a 12 kHz resonant scanner. These instructions are not relevant for systems with 8 kHz or 4 kHz resonant scanners. To set up rectangular images that use the whole Y range:

  • First perform the steps for square images because you want the number of volts per degree to be equal for two scan axes.

  • Now uncheck pix=line in the CONFIGURATION window.

  • Set the slow scan multiplier to a number that's as large as possible.

    On our setup this is about 1.9 to 2.1V (it may vary between ScanImage releases due to differences in the galvo waveform shape).

    If you set this value to too large a number you'll get an error about the output buffer being empty.

  • Press focus. Note that ScanImage automatically sets the number of lines so that the pixels remain square

  • Image the grid and measure.

    You may need to take a small Z stack if not all of the grid is visible over the whole image.

    Alternatively manually average three or four depths at the command line with the right-click and export.

  • You should get the same number of microns per pixel as before.

You'll now have rectangular frames with a certain number of microns per pixel. You can go to "File > Save Configuration As" in ScanImage to allow you allow you to re-load this in the future. E.g. you could call your file "rectangle_078.cfg" for 0.78 micron/pixel images.

Creating a calibration lookup table for different image sizes

You likely will not always want to use the same resolution for all your samples. In this step you will create a calibration table that allows you to quickly choose the desired image resolution from BakingTray. This is done via a .yml file called frameSizes.yml. This file contains a series of sections -- one for each resolution -- that are independent of each other. This allows you to, for example, set different hSI.objectiveResolution values should that become necessary to get square images with the correct number of microns per pixel. This file is what makes the resolution drop-down menu in BakingTray. Some of the settings in it (such as affineMat and stitchingVoxelSize) are used by StitchIt when assembling the stitched images. We tweak those values later.

The goal is to end up with a .yml file that looks like this:

setA:
  objective: nikon16x
  pixelsPerLine: 300
  linesPerFrame: 300
  zoomFactor: 1.0
  nominalMicronsPerPixel: 4.25
  fastMult: 1
  slowMult: 1
  objRes: 51.7
  lensDistort: {rows: 0, cols: 0.03}
  affineMat:
    - [1, 0,  0]
    - [0, 1,  0]
    - [0, 0,  1]
  stitchingVoxelSize: {X: 4.1, Y: 4.39}
setB:
  objective: nikon16x
  pixelsPerLine: 562
  linesPerFrame: 562
  zoomFactor: 1.0
  nominalMicronsPerPixel: 2.2
  fastMult: 1
  slowMult: 1
  objRes: 54.7
  lensDistort: {rows: 0, cols: 0.0}
  affineMat:
    - [1, 0,  0]
    - [0, 1,  0]
    - [0, 0,  1]
  stitchingVoxelSize: {X: 2.23, Y: 2.335}
setC:
  objective: nikon16x
  pixelsPerLine: 750
  linesPerFrame: 750
  zoomFactor: 1.0
  nominalMicronsPerPixel: 1.7
  fastMult: 1
  slowMult: 1
  objRes: 53.44
  lensDistort: {rows: 0, cols: 0.01}
  affineMat:
    - [1, 0,  0]
    - [0, 1,  0]
    - [0, 0,  1]
  stitchingVoxelSize: {X: 1.66, Y: 1.755}

If you have linear scanners (galvo/galvo) then you will have two extra fields: the sample rate (sampRate) and pixel bin factor (pixBin).

To populate the file, do the following:

  • Set the number pixels in ScanImage with the help of hBT.scanner.returnScanSettings to choose a suitable image size.

  • The number lines per frame must be an even number or you will get weird illumination artifacts if you do Z stacks..

  • Enter the image size and the nominal number of microns per pixel this corresponds to in a settings section.

  • Enter the hSI.objectiveResolution value in the objRes field of the .yml file. Use the value obtained above.

  • For now set the stitchingVoxelSize values to the nominal value. These will be tweaked later.

  • Repeat for other desired image resolutions. Typical useful image resolutions can be found in the user instructions under "Choosing Imaging Settings".

BakingTray will find your file when it starts and add these resolutions to the recipe section in the main view window. You can then select them and the settings will be applied. The method that does this is hBT.scanner.setImageSize (a method of SIBT), should you want to apply this at the command line. The hSI.objectiveResolution is not cached in the ScanImage .cfg file.

You must use an even number of scan lines!

Ensure that the number of scan lines is an even number or you will get a an illumination artifact that looks like this if you have Z stacks and change the laser power with depth:

What you are seeing is that the higher laser power for the optical plane below this one is happening one line earlier in each tile.

Last updated