Ran update_copyright.py, updating all the copyright blurbs and adding AUTHORS.
[hooke.git] / hooke / driver / jpk.py
1 # Copyright (C) 2008-2010 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
7 # modify it under the terms of the GNU Lesser General Public
8 # License as published by the Free Software Foundation, either
9 # version 3 of the License, or (at your option) any later version.
10 #
11 # Hooke is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU Lesser General 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 import string
21 from .. import curve as lhc
22
23 class DataChunk(list):
24     #Dummy class to provide ext and ret methods to the data list.
25
26     def ext(self):
27         halflen=(len(self)/2)
28         return self[0:halflen]
29
30     def ret(self):
31         halflen=(len(self)/2)
32         return self[halflen:]
33
34 class jpkDriver(lhc.Driver):
35
36     def __init__(self, filename):
37         self.filename=filename #self.filename can always be useful, and should be defined
38         self.filedata = open(filename,'r') #We open the file
39         self.filelines=self.filedata.readlines()
40         self.filedata.close()
41         '''These are two strings that can be used by Hooke commands/plugins to understand what they are looking at. They have no other
42         meaning. They have to be somehow defined however - commands often look for those variables.
43
44         self.filetype should contain the name of the exact filetype defined by the driver (so that filetype-specific commands can know
45                       if they're dealing with the correct filetype)
46         self.experiment should contain instead the type of data involved (for example, various drivers can be used for force-clamp experiments,
47                       but hooke commands could like to know if we're looking at force clamp data, regardless of their origin, and not other
48                       kinds of data)
49
50         Of course, all other variables you like can be defined in the class.
51         '''
52         self.filetype = 'jpk'
53         self.experiment = 'smfs'
54
55
56
57     def __del__(self):
58         self.filedata.close()
59
60     def is_me(self):
61         '''
62         we define our magic heuristic for jpk files
63         '''
64         myfile=file(self.filename)
65         headerlines=myfile.readlines()[0:3]
66         myfile.close()
67         if headerlines[0][0:11]=='# xPosition' and headerlines[1][0:11]=='# yPosition':
68             return True
69         else:
70             return False
71
72     def close_all(self):
73         self.filedata.close()
74
75     def _read_data_segment(self):
76         #routine that actually reads the data
77
78         height_ms=[]
79         height_m=[]
80         height=[]
81         v_deflection=[]
82         h_deflection=[]
83
84         self.springconstant=0 #if we don't meet any spring constant, use deflection...
85
86         for line in self.filelines:
87             #we meet the segment defining the order of data columns
88
89             if line[0:9]=='# columns':
90                 splitline=line.split()[2:]
91                 height_ms_index=splitline.index('smoothedStrainGaugeHeight')
92                 height_m_index=splitline.index('strainGaugeHeight')
93                 height_index=splitline.index('height')
94                 v_deflection_index=splitline.index('vDeflection')
95                 #h_deflection=splitline.index('hDeflection')
96
97             if line[0:16]=='# springConstant':
98                 self.springconstant=float(line.split()[2])
99
100             if line[0] != '#' and len(line.split())>1:
101                 dataline=line.split()
102                 height_ms.append(float(dataline[height_ms_index]))
103                 height_m.append(float(dataline[height_m_index]))
104                 height.append(float(dataline[height_index]))
105                 v_deflection.append(float(dataline[v_deflection_index]))
106                 #h_deflection.append(float(dataline[h_deflection_index]))
107
108         if self.springconstant != 0:
109             force=[item*self.springconstant for item in v_deflection]
110         else: #we have measured no spring constant :(
111             force=v_deflection
112
113         height_ms=DataChunk([item*-1 for item in height_ms])
114         height_m=DataChunk([item*-1 for item in height_m])
115         height=DataChunk([item*-1 for item in height])
116         deflection=DataChunk(v_deflection)
117         force=DataChunk(force)
118
119         return height_ms,height_m,height,deflection,force
120
121     def deflection(self):
122         height_ms,height_m,height,deflection,force=self._read_data_segment()
123         deflection_ext=deflection.ext()
124         deflection_ret=deflection.ret()
125         deflection_ret.reverse()
126         return deflection_ext,deflection_ret
127
128     def default_plots(self):
129
130         height_ms,height_m,height,deflection,force=self._read_data_segment()
131
132         height_ms_ext=height_ms.ext()
133         height_ms_ret=height_ms.ret()
134         force_ext=force.ext()
135         force_ret=force.ret()
136         #reverse the return data, to make it coherent with hooke standard
137         height_ms_ret.reverse()
138         force_ret.reverse()
139
140         main_plot=lhc.PlotObject()
141         main_plot.add_set(height_ms_ext,force_ext)
142         main_plot.add_set(height_ms_ret,force_ret)
143
144
145
146         if self.springconstant != 0:
147             main_plot.units=['meters','force']
148         else:
149             main_plot.units=['meters','meters']
150
151         main_plot.normalize_vectors()
152
153         main_plot.destination=0
154         main_plot.title=self.filename
155
156         return [main_plot]