-
Notifications
You must be signed in to change notification settings - Fork 5
Calibrating the number of microns per pixel with ScanImage
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.
- 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.
- 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 control signal is at 5V
- Confirm that the grid looks close to square by eye.
- If the grid does not look near-square then you should edit the number of volts per optical degree for the Y mirror (galvo) in the ScanImage machine data file. You'll need to save it then re-start
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.
- Right-click on the Channel's image and select the option to copy the current image to the base workspace as the variable
ImageData
. - Run
Grid2MicsPerPixel(ImageData)
. 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.
Once the grid looks roughly square:
- Run
hSI.hScan2D.plotFov2VoltageCurve
and try to generate a square-looking image by adding and moving the control points up and down with buttons at the bottom right. Measure each time withGrid2MicsPerPixel
. - If you find you need a larger amplitude than the maximum resonant mirror control signal to generate a square-looking image then lower the FOV=1 point to, say, 4.5 then decrease the slow scan multiplier (MAIN CONTROLS) by a bit. Say, to 0.8. The other multiplier will change to 0.8 also. (Alternative: go back and tweak the Y galvo Volts per Optical Degree)
- Play with these parameters until the grid looks square at a zoom of 1 and a maximum resonant mirror control signal.
- Once this is done it should then be possible to zoom in and the grid remains square (or mostly square, you might need to add more control points on you graph). For our purposes, however, we won't be zooming in. We'll always want to be maximally zoomed out to allow the sample to be tiled with as few stage motions as possible.
ScanImage now needs to be told how many microns correspond to one optical degree of scan angle. You can see the current scan parameters in two ways. One is to do it via BakingTray. Start BakingTray after ScanImage and run:
>> hBT.scanner.returnScanSettings
If you haven't set up BakingTray you can try:
>> S=SIBT
>> S.returnScanSettings
Finally, you can access the values directly (but in a harder to read format) from the ScanImage API:
>> hSI.hRoiManager.imagingFovDeg
>> hSI.hRoiManager.imagingFovUm
Likely the reported image size will be different to that which you measured.
This is because you need to tell ScanImage how the number of optical degrees relates to the number of microns at the sample.
This is achieved by setting the property hSI.objectiveResolution
which is the number of microns per degree of scan angle.
You can just do this at the command line and the value persists across sessions (no need to explicitly save it).
Don't worry right now if ScanImage reports a slightly different value for the number of microns per pixel in X and Y. We will deal with this at the end.
- Leave the resonant scanner on the whole time so that it settles down.
- Average 10 frames to improve SNR.
- Right-click on the channel window and copy data to the base workspace to feed to the measurement function
- If the galvo waveform exceeds +/-10 V you will get a cryptic error about the output buffer being empty.
The FOV along the fast (X) resonant axis is likely smaller than that along the slow (galvo) axis. With an 8 kHz scanner the difference will be small, but with a 12 kHz scanner it will be large. In our system the fast axis has a range almost three times smaller than the slow axis. After setting up rectangular images we get 400 microns along the fast axis and 1100 microns along the slow axis. This greatly speeds up tile scanning because three times fewer stage motions are needed.
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.
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.
Generating this table in advance is important because the hSI.objectiveResolution
value seems to vary slightly (but significantly) between different image resolutions.
Furthermore, some image resolutions produce square images for a given set of scan settings and others do not.
So you want to choose good parameters that be easily re-loaded.
The goal is to end up with a .yml
file that looks like this:
setA:
objective: nikon16x
pixelsPerLine: 512
linesPerFrame: 512
zoomFactor: 1.0
nominalMicronsPerPixel: 2.5
fastMult: 1
slowMult: 1
objRes: 54.7
setB:
objective: nikon16x
pixelsPerLine: 750
linesPerFrame: 750
zoomFactor: 1.0
nominalMicronsPerPixel: 1.667
fastMult: 1
slowMult: 1
objRes: 53.44
If you have linear scanners (galvo/galvo) then you will have two extra fields: the sample rate and pixel bin factor. Your settings will therefore look like:
setA:
objective: nikon16x
pixelsPerLine: 512
linesPerFrame: 512
zoomFactor: 1.0
nominalMicronsPerPixel: 2.5
fastMult: 1
slowMult: 1
objRes: 54.7
pixBin: 2
sampRate: 2500000
The above is for square frames.
You should place the above file in the SETTINGS
folder and call it frameSizes.yml
.
To populate the file, do the following:
- Set the resolution using parameters you already know generate a square image.
- Image the grid and read off the number of microns per pixel.
- If the image isn't quite square try a similar resolution until square image is returned. For instance, on our rig the 500 pixels per line setting did not quite measure square but 512 pixels per line does. You could also tweak the scan angle multipliers if needed.
- 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, scan angle multipliers, and number of microns per pixel into the
csv
file.
You now need to ensure ScanImage returns the correct number of microns per pixel for each of these settings. This step is a little awkward, but it's not hard:
- Use the
SIBT
class to return the number of microns per pixel ScanImage thinks you have:hBT.scanner.returnScanSettings
. Read themicronsPerPixel_cols
field. - Tweak
hSI.objectiveResolution
at the command line and re-run above until the nominal number of microns per pixel for this setting matches the value returned bymicronsPerPixel_cols
. - Enter the
hSI.objectiveResolution
value in theobjRes
field of the.yml
file. - Repeat for other desired image resolutions.
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.
There is only one number for linking scan angle to microns so you need both axes to have the same value. There are two options for dealing with this. One way is to change the scaling factor for the slow axis.
Let's say we have 0.781 microns per pixel along the fast axis and 0.735 microns per pixel along the slow axis. This means that the slow axis is moving by less than we expect. To start with we will change the V/optical degree value by:
new_value = orig_value * (0.781/0.735)
Then re-image and check. After this process your slow axis microns per pixel will equal your fast axis microns per pixel.
NOTE 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.
You can perform a fine tuning of the number of microns per pixel using the StitchIt chess-board stitching feature.
Installation: Getting Started
Hardware requirements
Setting up: Overview
Verifying hardware operation
Starting BakingTray
Setting up ScanImage
Settings Files
Achieving high stitching accuracy
Installation: Calibration
Basic calibrating procedures
Calibrating the stages
Fine-tuning positioning accuracy
Further User Instructions
FAQ
Problems & Solutions