Ran update_copyright.py.
[hooke.git] / hooke / plugin / cut.py
1 # Copyright (C) 2009-2012 Massimo Sandal <devicerandom@gmail.com>
2 #                         W. Trevor King <wking@drexel.edu>
3 #
4 # This file is part of Hooke.
5 #
6 # Hooke is free software: you can redistribute it and/or modify it
7 # under the terms of the GNU Lesser General Public License as
8 # published by the Free Software Foundation, either version 3 of the
9 # License, or (at your option) any later version.
10 #
11 # Hooke is distributed in the hope that it will be useful, but WITHOUT
12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General
14 # Public License for more details.
15 #
16 # You should have received a copy of the GNU Lesser General Public
17 # License along with Hooke.  If not, see
18 # <http://www.gnu.org/licenses/>.
19
20 """The `cut` module provides :class:`CutPlugin` and
21 :class:`CutCommand`.
22 """
23
24 import os.path
25
26 import numpy
27
28 from ..command import Command, Argument, Failure
29 from . import Plugin
30
31
32 class CutPlugin (Plugin):
33     def __init__(self):
34         super(CutPlugin, self).__init__(name='cut')
35         self._commands = [CutCommand(self)]
36
37
38 # Define common or complicated arguments
39
40 def current_curve_callback(hooke, command, argument, value):
41     playlist = hooke.playlists.current()
42     if playlist == None:
43         raise Failure('No playlists loaded')
44     curve = playlist.current()
45     if curve == None:
46         raise Failure('No curves in playlist %s' % playlist.name)
47     return curve
48
49 CurveArgument = Argument(
50     name='curve', type='curve', callback=current_curve_callback,
51     help="""
52 :class:`hooke.curve.Curve` to cut from.  Defaults to the current curve.
53 """.strip())
54
55
56 # Define commands
57
58 class CutCommand (Command):
59     """Cut the selected signal between two points and write it to a file.
60
61     The data is saved in TAB-delimited ASCII text.  A "#" prefixed
62     header will optionally appear at the beginning of the file naming
63     the columns.
64     """
65     def __init__(self, plugin):
66         super(CutCommand, self).__init__(
67             name='cut',
68             arguments=[
69                 CurveArgument,
70                 Argument(name='block', aliases=['set'], type='int', default=0,
71                     help="""
72 Data block to save.  For an approach/retract force curve, `0` selects
73 the approaching curve and `1` selects the retracting curve.
74 """.strip()),
75                 Argument(name='bounds', type='point', optional=False, count=2,
76                          help="""
77 Indicies of points bounding the selected data.
78 """.strip()),
79                 Argument(name='output', type='file', default='cut.dat',
80                          help="""
81 File name for the output data.
82 """.strip()),
83                 Argument(name='header', type='bool', default=True,
84                          help="""
85 True if you want the column-naming header line.
86 """.strip()),
87                 ],
88             help=self.__doc__, plugin=plugin)
89
90     def _run(self, hooke, inqueue, outqueue, params):
91         if params['curve'] == None:
92             params['curve'] = hooke.playlists.current().current()
93
94         i_min = min([p.index for p in params['points']])
95         i_max = max([p.index for p in params['points']])
96
97         data = params['curve'][params['bound']]
98         cut_data = data[i_min:i_max+1,:] # slice rows from row-major data
99         # +1 to include data[i_max] row
100
101         f = open(os.path.expanduser(params['output']), 'w')
102         if params['header'] == True:
103             f.write('# %s \n' % ('\t'.join(cut_data.info['columns'])))
104         numpy.savetxt(f, cut_data, delimiter='\t')
105         f.close()