Piping Images to the Loader
Subtomogram alignment usually requires a template and mask images, with
appropriate pre-processing. In acryo
, this kind of workflow is
provided as “Image Provider” and “Image Converter”, and they can directly
passed to the template
or mask
arguments in alignment functions.
Image Provider
An image provider is an object that provide an image when called. Currently,
all the image providers are named starting with from_
.
Provide an image from a file
The most commonly useful image provider is the image reading pipeline
from_file()
.
from acryo import SubtomogramLoader
from acryo.pipe import from_file
loader = SubtomogramLoader(image, molecules, scale=0.27) # create a loader
aligned = loader.align(
template=from_file("path/to/template.mrc"),
)
Image scale (nm/pixel) of the template image will be extracted from the image metadata. If you want to provide it manually, you can pass the second argument.
aligned = loader.align(
template=from_file("path/to/template.mrc", 0.18)
)
Note
The reason why we use a pipeline here is that the template image has to be rescaled differently for different images. Indeed, an image provider is a function that takes a float value as an input and returns an image.
provider = from_file("path/to/template.mrc")
type(provider(0.27)) # -> numpy.ndarray
Provid an image from an array
If you already have an image array, you can use from_array()
to create a
provider. The input array will be properly rescaled considering the scale
argument.
from acryo.pipe import from_array
arr = np.zeros((10, 10, 10))
aligned = loader.align(
template=from_array(arr, scale=0.18)
)
Image Converter
An image converter is an object that convert an image to another. This pipeline
is usually used for the mask
argument in alignment functions. When an image
converter is passed, mask images will be generated from the template image
using the converter.
from acryo import SubtomogramLoader
from acryo.pipe import from_file, soft_otsu
loader = SubtomogramLoader(image, molecules, scale=0.27) # create a loader
aligned = loader.align(
template=from_file("path/to/template.mrc"),
mask=soft_otsu(sigma=2.0, radius=1.0),
)
What is actually happening here is,
# created by user
reader_function = from_file("path/to/template.mrc")
soft_otsu_function = soft_otsu(sigma=2.0, radius=1.0)
# images are generated inside the alignment method
template = reader_function(0.27)
mask = soft_otsu_function(template, 0.27)
Custom Pipelines
To define custom pipelines, you can use decorators provider_function()
and
converter_function()
.
from acryo.pipe import provider_function, converter_function
# the first argument of a provider function must be a float
@provider_function
def my_provider_function(scale: float, arg0, arg1=0):
# do something
return image
# the first and the second argument of a converter function must be
# an array and a float respectively
@converter_function
def my_converter_function(image: np.ndarray, scale: float, arg0, arg1=0):
# do something
return image
In both cases, the first one or two arguments are to be provided inside a loader. You can create a pipeline by calling these function without the first argument(s).
from acryo import SubtomogramLoader
loader = SubtomogramLoader(image, molecules, scale=0.27) # create a loader
aligned = loader.align(
template=my_provider_function(arg0, arg1=0),
mask=my_converter_function(arg0, arg1=0),
)
Note
These decorators are similar to toolz.curry()
.
Composing Pipelines
Pipelines can be composed by @
or compose()
.
from acryo.pipe import gaussian_filter, from_file, soft_otsu
# `converter * provider` is a provider
# Functions will be called in "reading image -> filtering" order
composed = gaussian_filter(2.0) @ from_file("path/to/template.mrc")
composed(0.27) # -> numpy.ndarray
# `converter * converter` is a converter
# Functions will be called in "soft Otsu -> filtering" order
composed = gaussian_filter(2.0) @ soft_otsu(sigma=2.0, radius=1.0)
composed(np.zeros((4, 4, 4))) # -> numpy.ndarray