BUILTIN_MODULES = [
'config',
+ 'curve',
'debug',
'note',
'playlist',
--- /dev/null
+# Copyright (C) 2010 Fibrin's Benedetti
+# W. Trevor King <wking@drexel.edu>
+#
+# This file is part of Hooke.
+#
+# Hooke is free software: you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation, either
+# version 3 of the License, or (at your option) any later version.
+#
+# Hooke is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with Hooke. If not, see
+# <http://www.gnu.org/licenses/>.
+
+"""The ``curve`` module provides :class:`CurvePlugin` and several
+associated :class:`hooke.command.Command`\s for handling
+:mod:`hooke.curve` classes.
+"""
+
+from ..command import Command, Argument, Failure
+from ..plugin import Builtin
+from ..plugin.playlist import current_playlist_callback
+
+
+class CurvePlugin (Builtin):
+ def __init__(self):
+ super(CurvePlugin, self).__init__(name='curve')
+
+ def commands(self):
+ return [InfoCommand(), ]
+
+
+# Define common or complicated arguments
+
+def current_curve_callback(hooke, command, argument, value):
+ if value != None:
+ return value
+ playlist = current_playlist_callback(hooke, command, argument, value)
+ curve = playlist.current()
+ if curve == None:
+ raise Failure('No curves in %s' % playlist)
+ return curve
+
+CurveArgument = Argument(
+ name='curve', type='curve', callback=current_curve_callback,
+ help="""
+:class:`hooke.curve.Curve` to act on. Defaults to the current curve
+of the current playlist.
+""".strip())
+
+
+# Define commands
+
+class InfoCommand (Command):
+ """Print selected information about a :class:`hooke.curve.Curve`.
+ """
+ def __init__(self):
+ args = [
+ CurveArgument,
+ Argument(name='all', type='bool', default=False, count=1,
+ help='Print all curve information.'),
+ ]
+ self.fields = ['name', 'path', 'experiment', 'driver', 'filetype', 'note',
+ 'blocks', 'block sizes']
+ for field in self.fields:
+ args.append(Argument(
+ name=field, type='bool', default=False, count=1,
+ help='Print curve %s' % field))
+ super(InfoCommand, self).__init__(
+ name='curve info', arguments=args, help=self.__doc__)
+
+ def _run(self, hooke, inqueue, outqueue, params):
+ fields = {}
+ for key in self.fields:
+ fields[key] = params[key]
+ if reduce(lambda x,y: x and y, fields.values()) == False:
+ params['all'] = True # No specific fields set, default to 'all'
+ if params['all'] == True:
+ for key in self.fields:
+ fields[key] = True
+ lines = []
+ for key in self.fields:
+ if fields[key] == True:
+ get = getattr(self, '_get_%s' % key.replace(' ', '_'))
+ lines.append('%s: %s' % (key, get(params['curve'])))
+ outqueue.put('\n'.join(lines))
+
+ def _get_name(self, curve):
+ return curve.name
+
+ def _get_path(self, curve):
+ return curve.path
+
+ def _get_experiment(self, curve):
+ return curve.info.get('experiment', None)
+
+ def _get_driver(self, curve):
+ return curve.driver
+
+ def _get_filetype(self, curve):
+ return curve.info.get('filetype', None)
+
+ def _get_note(self, curve):
+ return curve.info.get('note', None)
+
+ def _get_blocks(self, curve):
+ return len(curve.data)
+
+ def _get_block_sizes(self, curve):
+ return [block.shape for block in curve.data]
+
+
+class ExportCommand (Command):
+ """Export a :class:`hooke.curve.Curve` data block as TAB-delimeted
+ ASCII text.
+ """
+ def __init__(self):
+ self.fields = ['name', 'path', 'experiment', 'driver', 'filetype', 'note',
+ 'blocks', 'block sizes']
+ for field in self.fields:
+ args.append(Argument(
+ name=field, type='bool', default=False, count=1,
+ help='Print curve %s' % field))
+ super(InfoCommand, self).__init__(
+ name='curve info',
+ arguments=[
+ CurveArgument,
+ Argument(name='block', aliases=['set'], type='int', default=0,
+ help="""
+Data block to save. For an approach/retract force curve, `0` selects
+the approacing curve and `1` selects the retracting curve.
+""".strip()),
+ Argument(name='output', type='file', default='curve.dat',
+ help="""
+File name for the output data. Defaults to 'curve.dat'
+""".strip()),
+ ],
+ help=self.__doc__)
+
+ def _run(self, hooke, inqueue, outqueue, params):
+ data = params['curve'].data[params['index']]
+ f = open(params['output'], 'w')
+ data.tofile(f, sep='\t')
+ f.close()
+++ /dev/null
-# Copyright (C) 2010 Fabrizio Benedetti
-# W. Trevor King <wking@drexel.edu>
-#
-# This file is part of Hooke.
-#
-# Hooke is free software: you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation, either
-# version 3 of the License, or (at your option) any later version.
-#
-# Hooke is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with Hooke. If not, see
-# <http://www.gnu.org/licenses/>.
-
-from ..libhooke import WX_GOOD, ClickedPoint
-
-import wxversion
-wxversion.select(WX_GOOD)
-from wx import PostEvent
-import numpy as np
-import scipy as sp
-import copy
-import os.path
-import time
-
-
-class curvetoolsCommands:
-
- def fit_interval_nm(self,start_index,plot,nm,backwards):
- '''
- Calculates the number of points to fit, given a fit interval in nm
- start_index: index of point
- plot: plot to use
- backwards: if true, finds a point backwards.
- '''
- whatset=1 #FIXME: should be decidable
- x_vect=plot.vectors[1][0]
-
- c=0
- i=start_index
- start=x_vect[start_index]
- maxlen=len(x_vect)
- while abs(x_vect[i]-x_vect[start_index])*(10**9) < nm:
- if i==0 or i==maxlen-1: #we reached boundaries of vector!
- return c
-
- if backwards:
- i-=1
- else:
- i+=1
- c+=1
- return c
-
-
-
- def find_current_peaks(self,noflatten, a=True, maxpeak=True):
- #Find peaks.
- if a==True:
- a=self.convfilt_config['mindeviation']
- try:
- abs_devs=float(a)
- except:
- print "Bad input, using default."
- abs_devs=self.convfilt_config['mindeviation']
-
- defplot=self.current.curve.default_plots()[0]
- if not noflatten:
- flatten=self._find_plotmanip('flatten') #Extract flatten plotmanip
- defplot=flatten(defplot, self.current, customvalue=1) #Flatten curve before feeding it to has_peaks
- pk_location,peak_size=self.has_peaks(defplot, abs_devs, maxpeak)
- return pk_location, peak_size
-
-
- def pickup_contact_point(self,N=1,whatset=1):
- '''macro to pick up the contact point by clicking'''
- contact_point=self._measure_N_points(N=1, whatset=1)[0]
- contact_point_index=contact_point.index
- self.wlccontact_point=contact_point
- self.wlccontact_index=contact_point.index
- self.wlccurrent=self.current.path
- return contact_point, contact_point_index
-
-
-
- def baseline_points(self,peak_location, displayed_plot):
- clicks=self.config['baseline_clicks']
- if clicks==0:
- self.basepoints=[]
- base_index_0=peak_location[-1]+self.fit_interval_nm(peak_location[-1], displayed_plot, self.config['auto_right_baseline'],False)
- self.basepoints.append(self._clickize(displayed_plot.vectors[1][0],displayed_plot.vectors[1][1],base_index_0))
- base_index_1=self.basepoints[0].index+self.fit_interval_nm(self.basepoints[0].index, displayed_plot, self.config['auto_left_baseline'],False)
- self.basepoints.append(self._clickize(displayed_plot.vectors[1][0],displayed_plot.vectors[1][1],base_index_1))
- elif clicks>0:
- print 'Select baseline'
- if clicks==1:
- self.basepoints=self._measure_N_points(N=1, whatset=1)
- base_index_1=self.basepoints[0].index+self.fit_interval_nm(self.basepoints[0].index, displayed_plot, self.config['auto_left_baseline'], False)
- self.basepoints.append(self._clickize(displayed_plot.vectors[1][0],displayed_plot.vectors[1][1],base_index_1))
- else:
- self.basepoints=self._measure_N_points(N=2, whatset=1)
-
- self.basecurrent=self.current.path
- return self.basepoints
-
-
-
-class InfoCommand (Command):
- """Execute a system command and report the output.
- """
- def __init__(self):
- super(SystemCommand, self).__init__(
- name='system',
- arguments=[
- Argument(
- name='command', type='string', optional=False, count=-1,
- help="""
-Command line to execute.
-""".strip())
-],
- help=self.__doc__)
-
- def _run(self, hooke, inqueue, outqueue, params):
- os.system(params['command'])
-
- def do_info(self,args):
- '''
- INFO
- ----
- Returns informations about the current curve.
- '''
- print 'Path: ',self.current.path
- print 'Experiment: ',self.current.curve.experiment
- print 'Filetype: ',self.current.curve.filetype
- for plot in self.current.curve.default_plots():
- for set in plot.vectors:
- lengths=[len(item) for item in set]
- print 'Data set size: ',lengths
-
-
- def help_current(self):
- print '''
-CURRENT
-Prints the current curve path.
-------
-Syntax: current
- '''
- def do_current(self,args):
- print self.current.path
-
-
- def help_txt(self):
- print '''
-TXT
-Saves the current curve as a text file
-Columns are, in order:
-X1 , Y1 , X2 , Y2 , X3 , Y3 ...
-
--------------
-Syntax: txt [filename] {plot to export}
- '''
- def do_txt(self,args):
-
- def transposed2(lists, defval=0):
- '''
- transposes a list of lists, i.e. from [[a,b,c],[x,y,z]] to [[a,x],[b,y],[c,z]] without losing
- elements
- (by Zoran Isailovski on the Python Cookbook online)
- '''
- if not lists: return []
- return map(lambda *row: [elem or defval for elem in row], *lists)
-
- whichplot=0
- args=args.split()
- if len(args)==0:
- filename=linp.safeinput('Filename?',[self.current.path+'.txt'])
- else:
- filename=linp.checkalphainput(args[0],self.current.path+'.txt',[])
- try:
- whichplot=int(args[1])
- except:
- pass
-
- try:
- outofplot=self.plots[whichplot].vectors
- except:
- print "Plot index out of range."
- return 0
-
- columns=[]
- for dataset in self.plots[whichplot].vectors:
- for i in range(0,len(dataset)):
- columns.append([])
- for value in dataset[i]:
- columns[-1].append(str(value))
-
- rows=transposed2(columns, 'nan')
- rows=[' , '.join(item) for item in rows]
- text='\n'.join(rows)
-
- txtfile=open(filename,'w+')
- #Save units of measure in header
- txtfile.write('X:'+self.plots[whichplot].units[0]+'\n')
- txtfile.write('Y:'+self.plots[whichplot].units[1]+'\n')
- txtfile.write(text)
- txtfile.close()
linefit=np.polyfit(xtofit,ytofit,1)
return (linefit[0],linefit[1],xtofit,ytofit)
+
+
+ def fit_interval_nm(self,start_index,plot,nm,backwards):
+ '''
+ Calculates the number of points to fit, given a fit interval in nm
+ start_index: index of point
+ plot: plot to use
+ backwards: if true, finds a point backwards.
+ '''
+ whatset=1 #FIXME: should be decidable
+ x_vect=plot.vectors[1][0]
+
+ c=0
+ i=start_index
+ start=x_vect[start_index]
+ maxlen=len(x_vect)
+ while abs(x_vect[i]-x_vect[start_index])*(10**9) < nm:
+ if i==0 or i==maxlen-1: #we reached boundaries of vector!
+ return c
+
+ if backwards:
+ i-=1
+ else:
+ i+=1
+ c+=1
+ return c
+
+
+
+ def find_current_peaks(self,noflatten, a=True, maxpeak=True):
+ #Find peaks.
+ if a==True:
+ a=self.convfilt_config['mindeviation']
+ try:
+ abs_devs=float(a)
+ except:
+ print "Bad input, using default."
+ abs_devs=self.convfilt_config['mindeviation']
+
+ defplot=self.current.curve.default_plots()[0]
+ if not noflatten:
+ flatten=self._find_plotmanip('flatten') #Extract flatten plotmanip
+ defplot=flatten(defplot, self.current, customvalue=1) #Flatten curve before feeding it to has_peaks
+ pk_location,peak_size=self.has_peaks(defplot, abs_devs, maxpeak)
+ return pk_location, peak_size
+
+
+ def pickup_contact_point(self,N=1,whatset=1):
+ '''macro to pick up the contact point by clicking'''
+ contact_point=self._measure_N_points(N=1, whatset=1)[0]
+ contact_point_index=contact_point.index
+ self.wlccontact_point=contact_point
+ self.wlccontact_index=contact_point.index
+ self.wlccurrent=self.current.path
+ return contact_point, contact_point_index
+
+
+
+ def baseline_points(self,peak_location, displayed_plot):
+ clicks=self.config['baseline_clicks']
+ if clicks==0:
+ self.basepoints=[]
+ base_index_0=peak_location[-1]+self.fit_interval_nm(peak_location[-1], displayed_plot, self.config['auto_right_baseline'],False)
+ self.basepoints.append(self._clickize(displayed_plot.vectors[1][0],displayed_plot.vectors[1][1],base_index_0))
+ base_index_1=self.basepoints[0].index+self.fit_interval_nm(self.basepoints[0].index, displayed_plot, self.config['auto_left_baseline'],False)
+ self.basepoints.append(self._clickize(displayed_plot.vectors[1][0],displayed_plot.vectors[1][1],base_index_1))
+ elif clicks>0:
+ print 'Select baseline'
+ if clicks==1:
+ self.basepoints=self._measure_N_points(N=1, whatset=1)
+ base_index_1=self.basepoints[0].index+self.fit_interval_nm(self.basepoints[0].index, displayed_plot, self.config['auto_left_baseline'], False)
+ self.basepoints.append(self._clickize(displayed_plot.vectors[1][0],displayed_plot.vectors[1][1],base_index_1))
+ else:
+ self.basepoints=self._measure_N_points(N=2, whatset=1)
+
+ self.basecurrent=self.current.path
+ return self.basepoints
# License along with Hooke. If not, see
# <http://www.gnu.org/licenses/>.
-"""The `playlist` module provides :class:`PlaylistPlugin` several
-associated :class:`hooke.command.Command`\s for handling
+"""The ``playlist`` module provides :class:`PlaylistPlugin` and
+several associated :class:`hooke.command.Command`\s for handling
:mod:`hooke.playlist` classes.
"""
PlaylistArgument = Argument(
name='playlist', type='playlist', callback=current_playlist_callback,
help="""
-:class:`hooke.plugin.playlist.Playlist` to act on. Defaults to the
-current playlist.
+:class:`hooke.playlist.Playlist` to act on. Defaults to the current
+playlist.
""".strip())
def playlist_name_callback(hooke, command, argument, value):
--- /dev/null
+# Copyright (C) 2010 W. Trevor King <wking@drexel.edu>
+#
+# This file is part of Hooke.
+#
+# Hooke is free software: you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation, either
+# version 3 of the License, or (at your option) any later version.
+#
+# Hooke is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with Hooke. If not, see
+# <http://www.gnu.org/licenses/>.
+
+"""
+>>> from hooke.hooke import Hooke, HookeRunner
+>>> h = Hooke()
+>>> r = HookeRunner()
+>>> h = r.run_lines(h, ['load_playlist test/data/test']) # doctest: +ELLIPSIS
+<FilePlaylist test.hkp>
+Success
+<BLANKLINE>
+>>> h = r.run_lines(h, ['curve_info'])
+name: picoforce.000
+path: test/data/picoforce.000
+experiment: None
+driver: picoforce
+filetype: None
+note:
+blocks: 0
+block sizes: []
+Success
+<BLANKLINE>
+"""