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