-# Copyright (C) 2008-2010 Alberto Gomez-Kasai
-# Fabiano's Benedetti
+# Copyright (C) 2008-2010 Alberto Gomez-Casado
+# Fabrizio Benedetti
# Massimo Sandal <devicerandom@gmail.com>
# W. Trevor King <wking@drexel.edu>
#
import numpy
from ..command import Command, Argument, Failure
+from ..command_stack import CommandStack
from ..curve import Data
+from ..engine import CommandMessage
from ..util.calculus import derivative
from ..util.fft import unitary_avg_power_spectrum
from ..util.si import ppSI, join_data_label, split_data_label
# Define common or complicated arguments
-def current_curve_callback(hooke, command, argument, value):
+def current_curve_callback(hooke, command, argument, value, load=True):
if value != None:
return value
playlist = current_playlist_callback(hooke, command, argument, value)
- curve = playlist.current()
+ curve = playlist.current(load=load)
if curve == None:
raise Failure('No curves in %s' % playlist)
return curve
+def unloaded_current_curve_callback(hooke, command, argument, value):
+ return current_curve_callback(
+ hooke=hooke, command=command, argument=argument, value=value,
+ load=False)
+
CurveArgument = Argument(
name='curve', type='curve', callback=current_curve_callback,
help="""
super(CurveCommand, self).__init__(**kwargs)
def _curve(self, hooke, params):
+ """Get the selected curve.
+
+ Notes
+ -----
+ `hooke` is intended to attach the selected curve to the local
+ playlist; the returned curve should not be effected by the
+ state of `hooke`. This is important for reliable
+ :class:`~hooke.command_stack.CommandStack`\s.
+ """
# HACK? rely on params['curve'] being bound to the local hooke
# playlist (i.e. not a copy, as you would get by passing a
# curve through the queue). Ugh. Stupid queues. As an
# queue...
return params['curve']
+ def _add_to_command_stack(self, params):
+ """Store the command name and current `params` values in the
+ curve's `.command_stack`.
+
+ If this would duplicate the command currently on top of the
+ stack, no action is taken. Call early on, or watch out for
+ repeated param processing.
+
+ Recommended practice is to *not* lock in argument values that
+ are loaded from the plugin's :attr:`.config`.
+
+ Notes
+ -----
+ Perhaps we should subclass :meth:`_run` and use :func:`super`,
+ or embed this in :meth:`run` to avoid subclasses calling this
+ method explicitly, with all the tedium and brittality that
+ implies. On the other hand, the current implemtnation allows
+ CurveCommands that don't effect the curve itself
+ (e.g. :class:`GetCommand`) to avoid adding themselves to the
+ stack entirely.
+ """
+ if params['stack'] == True:
+ curve = self._curve(hooke=None, params=params)
+ if (len(curve.command_stack) > 0
+ and curve.command_stack[-1].command == self.name
+ and curve.command_stack[-1].arguments == params):
+ pass # no need to place duplicate calls on the stack.
+ else:
+ curve.command_stack.append(CommandMessage(
+ self.name, dict(params)))
+
class BlockCommand (CurveCommand):
"""A :class:`CurveCommand` operating on a :class:`~hooke.curve.Data` block.
self._commands = [
GetCommand(self), InfoCommand(self), DeltaCommand(self),
ExportCommand(self), DifferenceCommand(self),
- DerivativeCommand(self), PowerSpectrumCommand(self)]
+ DerivativeCommand(self), PowerSpectrumCommand(self),
+ ClearStackCommand(self)]
# Define commands
Argument(name='all', type='bool', default=False, count=1,
help='Get all curve information.'),
]
- self.fields = ['name', 'path', 'experiment', 'driver', 'filetype', 'note',
- 'blocks', 'block sizes']
+ self.fields = ['name', 'path', 'experiment', 'driver', 'filetype',
+ 'note', 'command stack', 'blocks', 'block sizes']
for field in self.fields:
args.append(Argument(
name=field, type='bool', default=False, count=1,
fields = {}
for key in self.fields:
fields[key] = params[key]
- if reduce(lambda x,y: x and y, fields.values()) == False:
+ if reduce(lambda x,y: x or y, fields.values()) == False:
params['all'] = True # No specific fields set, default to 'all'
if params['all'] == True:
for key in self.fields:
def _get_note(self, curve):
return curve.info.get('note', None)
+ def _get_command_stack(self, curve):
+ return curve.command_stack
+
def _get_blocks(self, curve):
return len(curve.data)
help=self.__doc__, plugin=plugin)
def _run(self, hooke, inqueue, outqueue, params):
- params = self.__setup_params(hooke=hooke, params=params)
+ self._add_to_command_stack(params)
+ params = self._setup_params(hooke=hooke, params=params)
data_A = self._get_column(hooke=hooke, params=params,
block_name='block A',
column_name='column A')
column_name='output column',
values=out)
- def __setup_params(self, hooke, params):
+ def _setup_params(self, hooke, params):
curve = self._curve(hooke, params)
if params['block A'] == None:
params['block A'] = curve.data[0].info['name']
help=self.__doc__, plugin=plugin)
def _run(self, hooke, inqueue, outqueue, params):
- params = self.__setup_params(hooke=hooke, params=params)
+ self._add_to_command_stack(params)
+ params = self._setup_params(hooke=hooke, params=params)
x_data = self._get_column(hooke=hooke, params=params,
column_name='x column')
f_data = self._get_column(hooke=hooke, params=params,
column_name='output column',
values=d)
- def __setup_params(self, hooke, params):
+ def _setup_params(self, hooke, params):
curve = self._curve(hooke, params)
x_name,x_unit = split_data_label(params['x column'])
f_name,f_unit = split_data_label(params['f column'])
help=self.__doc__, plugin=plugin)
def _run(self, hooke, inqueue, outqueue, params):
- params = self.__setup_params(hooke=hooke, params=params)
+ self._add_to_command_stack(params)
+ params = self._setup_params(hooke=hooke, params=params)
data = self._get_column(hooke=hooke, params=params)
bounds = params['bounds']
if bounds != None:
values=power)
outqueue.put(b)
- def __setup_params(self, hooke, params):
+ def _setup_params(self, hooke, params):
if params['output block'] in self._block_names(hooke, params):
raise Failure('output block %s already exists in %s.'
% (params['output block'],
return params
+class ClearStackCommand (CurveCommand):
+ """Empty a curve's command stack.
+ """
+ def __init__(self, plugin):
+ super(ClearStackCommand, self).__init__(
+ name='clear curve command stack',
+ help=self.__doc__, plugin=plugin)
+ i,arg = [(i,arg) for i,arg in enumerate(self.arguments)
+ if arg.name == 'curve'][0]
+ arg = copy.copy(arg)
+ arg.callback = unloaded_current_curve_callback
+ self.arguments[i] = arg
+
+ def _run(self, hooke, inqueue, outqueue, params):
+ curve = self._curve(hooke, params)
+ curve.command_stack = CommandStack()
+
+
class OldCruft (object):
def do_forcebase(self,args):