8f3ec3655f1baa52034e620ad4b9698885b03dbc
[hooke.git] / hooke / plugin / curvetools.py
1 # Copyright
2
3 from ..libhooke import WX_GOOD, ClickedPoint
4
5 import wxversion
6 wxversion.select(WX_GOOD)
7 from wx import PostEvent
8 import numpy as np
9 import scipy as sp
10 import copy
11 import os.path
12 import time
13
14
15 class curvetoolsCommands:
16
17       def fit_interval_nm(self,start_index,plot,nm,backwards):
18           '''
19           Calculates the number of points to fit, given a fit interval in nm
20           start_index: index of point
21           plot: plot to use
22           backwards: if true, finds a point backwards.
23           '''
24           whatset=1 #FIXME: should be decidable
25           x_vect=plot.vectors[1][0]
26           
27           c=0
28           i=start_index
29           start=x_vect[start_index]
30           maxlen=len(x_vect)
31           while abs(x_vect[i]-x_vect[start_index])*(10**9) < nm:
32               if i==0 or i==maxlen-1: #we reached boundaries of vector!
33                   return c
34               
35               if backwards:
36                   i-=1
37               else:
38                   i+=1
39               c+=1
40           return c
41
42
43
44       def find_current_peaks(self,noflatten, a=True, maxpeak=True):
45             #Find peaks.
46             if a==True:
47                   a=self.convfilt_config['mindeviation']
48             try:
49                   abs_devs=float(a)
50             except:
51                   print "Bad input, using default."
52                   abs_devs=self.convfilt_config['mindeviation']
53
54             defplot=self.current.curve.default_plots()[0]
55             if not noflatten:
56                 flatten=self._find_plotmanip('flatten') #Extract flatten plotmanip
57                 defplot=flatten(defplot, self.current, customvalue=1) #Flatten curve before feeding it to has_peaks
58             pk_location,peak_size=self.has_peaks(defplot, abs_devs, maxpeak)
59             return pk_location, peak_size
60
61
62       def pickup_contact_point(self,N=1,whatset=1):
63             '''macro to pick up the contact point by clicking'''
64             contact_point=self._measure_N_points(N=1, whatset=1)[0]
65             contact_point_index=contact_point.index
66             self.wlccontact_point=contact_point
67             self.wlccontact_index=contact_point.index
68             self.wlccurrent=self.current.path
69             return contact_point, contact_point_index
70
71
72
73       def baseline_points(self,peak_location, displayed_plot):
74             clicks=self.config['baseline_clicks']
75             if clicks==0:
76                 self.basepoints=[]
77                 base_index_0=peak_location[-1]+self.fit_interval_nm(peak_location[-1], displayed_plot, self.config['auto_right_baseline'],False)
78                 self.basepoints.append(self._clickize(displayed_plot.vectors[1][0],displayed_plot.vectors[1][1],base_index_0))
79                 base_index_1=self.basepoints[0].index+self.fit_interval_nm(self.basepoints[0].index, displayed_plot, self.config['auto_left_baseline'],False)
80                 self.basepoints.append(self._clickize(displayed_plot.vectors[1][0],displayed_plot.vectors[1][1],base_index_1))
81             elif clicks>0:
82                 print 'Select baseline'
83                 if clicks==1:
84                     self.basepoints=self._measure_N_points(N=1, whatset=1)
85                     base_index_1=self.basepoints[0].index+self.fit_interval_nm(self.basepoints[0].index, displayed_plot, self.config['auto_left_baseline'], False)
86                     self.basepoints.append(self._clickize(displayed_plot.vectors[1][0],displayed_plot.vectors[1][1],base_index_1))
87                 else:
88                     self.basepoints=self._measure_N_points(N=2, whatset=1)
89             
90             self.basecurrent=self.current.path
91             return self.basepoints
92
93
94
95 class InfoCommand (Command):
96     """Execute a system command and report the output.
97     """
98     def __init__(self):
99         super(SystemCommand, self).__init__(
100             name='system',
101             arguments=[
102                 Argument(
103     name='command', type='string', optional=False, count=-1,
104     help="""
105 Command line to execute.
106 """.strip())
107 ],
108             help=self.__doc__)
109
110     def _run(self, hooke, inqueue, outqueue, params):
111         os.system(params['command'])
112
113     def do_info(self,args):
114         '''
115         INFO
116         ----
117         Returns informations about the current curve.
118         '''
119         print 'Path: ',self.current.path
120         print 'Experiment: ',self.current.curve.experiment
121         print 'Filetype: ',self.current.curve.filetype
122         for plot in self.current.curve.default_plots():
123             for set in plot.vectors:
124                 lengths=[len(item) for item in set]
125                 print 'Data set size: ',lengths
126
127
128     def help_current(self):
129         print '''
130 CURRENT
131 Prints the current curve path.
132 ------
133 Syntax: current
134         '''
135     def do_current(self,args):
136         print self.current.path
137
138
139     def help_txt(self):
140         print '''
141 TXT
142 Saves the current curve as a text file
143 Columns are, in order:
144 X1 , Y1 , X2 , Y2 , X3 , Y3 ...
145
146 -------------
147 Syntax: txt [filename] {plot to export}
148         '''
149     def do_txt(self,args):
150
151         def transposed2(lists, defval=0):
152             '''
153             transposes a list of lists, i.e. from [[a,b,c],[x,y,z]] to [[a,x],[b,y],[c,z]] without losing
154             elements
155             (by Zoran Isailovski on the Python Cookbook online)
156             '''
157             if not lists: return []
158             return map(lambda *row: [elem or defval for elem in row], *lists)
159
160         whichplot=0
161         args=args.split()
162         if len(args)==0:
163             filename=linp.safeinput('Filename?',[self.current.path+'.txt'])
164         else:
165             filename=linp.checkalphainput(args[0],self.current.path+'.txt',[])
166             try:
167                 whichplot=int(args[1])
168             except:
169                 pass
170
171         try:
172             outofplot=self.plots[whichplot].vectors
173         except:
174             print "Plot index out of range."
175             return 0
176
177         columns=[]     
178         for dataset in self.plots[whichplot].vectors:
179             for i in range(0,len(dataset)):
180                 columns.append([])
181                 for value in dataset[i]:
182                     columns[-1].append(str(value))
183
184         rows=transposed2(columns, 'nan')
185         rows=[' , '.join(item) for item in rows]
186         text='\n'.join(rows)
187
188         txtfile=open(filename,'w+')
189         #Save units of measure in header
190         txtfile.write('X:'+self.plots[whichplot].units[0]+'\n')
191         txtfile.write('Y:'+self.plots[whichplot].units[1]+'\n')
192         txtfile.write(text)
193         txtfile.close()