"""
The detection of features within an image with spotlob is split up into
an abstract but fixed sequence of processes. Any of these process steps is
applied onto a Spim and returns a new Spim. The new Spim contains the
information added by the process step.
.. graphviz::
digraph seq {
rankdir="LR";
"spim1" -> "spim2" [label="spim1.function(process)"];
}
For example, a `Spim` at stage `SpimStage.loaded` can be converted, using
a concrete subclass of `Converter`, named `process_opencv.GreyscaleConverter`
in the following way:
.. code-block:: python
from spotlob.defaults import load_image
from spotlob.process_opencv import GreyscaleConverter
loaded_spim = load_image("color_image.jpg")
my_converter = GreyscaleConverter()
converted_spim = loaded_spim.convert(my_converter)
"""
import numpy as np
from .spim import SpimStage
from .parameters import SpotlobParameterSet
[docs]class SpotlobProcessStep(object):
"""An abstract super class for process steps. A process step can be
applied to bring a spim from one stage to another. It is supposed to save
as internal state, if it has already been applied or needs to be applied
again, because the parameters have changed. This is stored in the
`outdated` parameter"""
# stage that a spim should have before this Process can be applied
input_stage = None
# a process is outdated, if it has not been
# applied since the parameters changed
outdated = True
def __init__(self, function, parameters, add_to_register=True):
"""
A process step can be applied to bring a spim from one stage
to another
Parameters
----------
function : callable
a function to be applied on spim with optional additional
parameters
parameters : list of SpotlobParameter
the parameters that will be used for the function as soon as
it is applied
add_to_register : bool, optional
if this is True, the process will be registered centrally now, i.e.
upon creation of the SpotlobProcessStep object. This allows the
user to know which processes are available (the default is True)
"""
self.function = function
self.parameters = SpotlobParameterSet(parameters)
# import needs to be delayed to avoid circular imports
from .register import PROCESS_REGISTER
if add_to_register:
PROCESS_REGISTER.register_process(self)
[docs] def preview(self, spim):
"""
This function takes spim at an undefined stage and draws
the effect of the process on top, to provide a preview for the
user on how the funciton will work. No storage or sideeffects
should take place.
In contrast to the apply function it must always return an image
Parameters
----------
spim : Spim
Spim to draw the preview on. It must contain an image
"""
raise NotImplementedError("abstract: to be implemented by subclass")
[docs] def apply(self, *input_args):
"""Apply the process step onto input data (eg. images or contours)
and yield the output data (again, could be a modified image or gathered
data). The actual return values depend on the concrete implementation
of the function. Additional arguments for the function are the
parameters of the process as stored in the `parameters` field of each
process.
Returns
-------
Contours or images
Output of the concrete process implementation
"""
output = self.function(*input_args, **self.parameters.to_dict())
self.outdated = False
return output
def __str__(self):
classname = str(type(self).__name__)
parameters_str = str(self.parameters)
return "%s\n%s" % (classname, parameters_str)