''' Converter classes that wrap multiple conversion steps under one class. '''
from pliers.stimuli.base import Stim
from pliers.stimuli.audio import AudioStim
from pliers.stimuli.video import VideoStim
from pliers.stimuli.text import TextStim, ComplexTextStim
from .base import Converter, get_converter
class MultiStepConverter(Converter):
''' Base class for Converters doing more than one step.
Args:
steps (list): Ordered list describing the sequence of desired
conversions. Each element in the list can be either a Converter or
a Stim class. If the former, the exact Converter provided is used
as the step. If a Stim subclass is passed (e.g., AudioStim), then
the first matching Converter class will be used.
'''
_loggable = False
def __init__(self, steps=None):
self.steps = self._steps if steps is None else steps
super().__init__()
def _convert(self, stim):
for i, step in enumerate(self.steps):
if issubclass(step, Stim):
converter = get_converter(type(stim), step)
if converter is None:
msg = ("Conversion failed at step %d; unable to find a "
"Converter capable of transforming a %s into a %s.") \
% (i, stim.__class__.__name__, step.__name__)
raise ValueError(msg)
else:
converter = step
stim = converter.transform(stim)
return stim
# Current approach requires explicit naming of every possible path. This is
# not ideal and could get big in a hurry. We should probably switch to
# walking the inheritance hierarchy of each Stim instance and using the first
# MultiStepConverter that matches (e.g., a VideoFrameCollectionStim that needs
# to be converted to a TextStim should use the VideoToTextConverter).
[docs]class VideoToTextConverter(MultiStepConverter):
''' Converts a VideoStim directly to a TextStim. '''
_input_type = VideoStim
_output_type = TextStim
_steps = [AudioStim, TextStim]
[docs]class VideoToComplexTextConverter(MultiStepConverter):
''' Converts a VideoStim directly to a ComplexTextStim. '''
_input_type = VideoStim
_output_type = ComplexTextStim
_steps = [AudioStim, TextStim]