Export
PciSeq
For probabilistic cell typing with pciSeq, a DAPI background image and gene spot positions must be exported.
Filtered DAPI
To export the anchor's filtered DAPI stitched image
from coppafisher import Notebook
from coppafisher.results import export_pciseq_dapi_image
nb = Notebook("/path/to/notebook")
export_pciseq_dapi_image(nb)
The DAPI image can then be loaded into memory by
import numpy as np
dapi_image = np.load("/path/to/dapi_image.npz")["arr_0"]
Unfiltered DAPI
To export the anchor's unfiltered DAPI stitched image
from coppafisher import Notebook
from coppafisher.results import export_pciseq_unfiltered_dapi_image
nb = Notebook("/path/to/notebook")
config_path = "/path/to/config.ini"
export_pciseq_unfiltered_dapi_image(nb, config_path)
The DAPI image can then be loaded into memory by
import numpy as np
dapi_image = np.load("/path/to/dapi_image.npz")["arr_0"]
Export gene reads into a compatible csv file by
from coppafisher import Notebook
from coppafisher.results import export_to_pciseq
nb = Notebook("/path/to/notebook")
export_to_pciseq(nb, method)
where method can be "omp"
, "prob"
, or "anchor"
for each gene calling method. To set a score and/or intensity
minimum threshold:
from coppafisher import Notebook
from coppafisher.results import export_to_pciseq
nb = Notebook("/path/to/notebook")
export_to_pciseq(nb, method, score_thresh, intensity_thresh)
score_thresh and intensity_thresh must be numbers. Use the Viewer to help decide on thresholds.
intensity_thresh is set to 0.15
for OMP in the Viewer by default.
Custom Images
Additional custom images can be aligned with coppafisher images and gene spots provided that you have a dapi channel (or something similar to align with the anchor-DAPI image).
Extract the additional image(s)
The additional images must be extracted from ND2 files. You will likely require the DAPI channel for best results. They are saved as tiff files. If you do not have ND2 input files, you need to first manually convert them to tiff files.
from coppafisher.custom_alignment import extract_raw
from coppafisher import Notebook
config_file = "/path/to/used/config.ini"
custom_nd2 = "/path/to/input/file.nd2"
output_dir = "/path/to/extract/directory/"
nb = Notebook("/path/to/notebook")
extract_raw(
nb,
config_file,
save_dir=output_dir,
read_dir=custom_nd2,
use_tiles=nb.basic_info.use_tiles,
use_channels=[nb.basic_info.dapi_channel, 9, 23],
reverse_custom_z=False,
)
use_channels
can be any valid channel(s) inside the custom image .nd2 file. This will also extract the anchor round in
the DAPI channel. You can reverse the z planes in the custom image by setting reverse_custom_z
to True
.
Config File
The config file must be a valid configuration, like the one used during the experiment. Therefore, the input_dir
must point to a real input directory.
Stitch
The extracted raw anchor-DAPI images are stitched using coppafisher's stitch method. The custom image is stitched by the same method separately. This then needs to be registered with the anchor-DAPI in the next step. Do this for each custom image channel separately. I suggest starting with the dapi channels first
from coppafisher.custom_alignment import fuse_custom_and_dapi
fused_custom_dapi_image, fused_anchor_dapi_image = fuse_custom_and_dapi(nb, output_dir, channel=nb.basic_info.dapi_channel)
Dapi Register
Alignment is done using the package LineStuffUp
maintained by Max Shinn
(m.shinn@ucl.ac.uk). This allows control over the type of transformation to apply based on their custom images. Install
via pip
python -m pip install LineStuffUp
Then start the interactive alignment process
import linestuffup.gui
from linestuffup.base import TranslateRotate
round_transform = linestuffup.gui.alignment_gui(
fused_custom_dapi_image, fused_anchor_dapi_image, transform_type=TranslateRotate
)
Press Add new point
and click twice to place two corresponding points. Do this a few times, preferably in various z
planes too. Press Perform transform
to see the resulting transform. Once you are happy with the result, close the
napari window.
Type of Transform
You can change the type of transform you wish to find, please see the transfrom readme for details.
For example, you could use the more robust transform type of TranslateRotateRescale
. It requires four
points in every corner of the image on both edges of the z stack for best results.
Save and Load Transforms
Every transform can be saved and reloaded at a later point. You just need to save the text representation of the transform which can be found by
str(round_transform)
You can save it using Python
with open("/path/to/saved/transform.txt", "w") as file:
file.write(str(round_transform))
It can be reloaded by
from linestuffup.base import *
with open("/path/to/saved/transform.txt", "r") as file:
exec("round_transform = " + "\n".join(file.readlines()))
You can rename the variable from round_transform
to anything.
Do not run exec
on stranger's code (it could be malicious)!
You can now apply the resulting transform to the custom dapi image and save the result as a .tif
file
import numpy as np
import tifffile
fused_custom_dapi_image_transformed = round_transform.transform_image(
fused_custom_dapi_image, relative=fused_anchor_dapi_image.shape, force_size=True, labels=True
)
tifffile.imwrite("/path/to/saved/custom_dapi_image_transformed.tif", fused_custom_dapi_image_transformed)
del fused_custom_dapi_image_transformed
del fused_anchor_dapi_image
Non-Dapi Register
For a non-dapi custom image channel c
, it is recommended to find a specific transform to move to the dapi channel for
best registration. To do this, first find a transform to move into the dapi custom image's frame
from coppafisher.custom_alignment import fuse_custom_and_dapi
import linestuffup.gui
from linestuffup.base import TranslateRotate
fused_custom_channel_image, _ = fuse_custom_and_dapi(nb, output_dir, channel=c)
channel_transform = linestuffup.gui.alignment_gui(
fused_custom_channel_image, fused_custom_dapi_image, transform_type=TranslateRotate
)
Now save the fully registered channel image
import tifffile
fused_custom_channel_image_transformed = (channel_transform + round_transform).transform_image(
fused_custom_channel_image, relative=fused_custom_channel_image.shape, force_size=True, labels=True
)
tifffile.imwrite(f"/path/to/saved/custom_channel_{c}_image_transformed.tif", fused_custom_channel_image_transformed)
del fused_custom_channel_image_transformed
del fused_custom_channel_image