fixed: plot does not display on Windows at program launch (troubleshooting issue 1)
[hooke.git] / drivers / jpk.py
1 #!/usr/bin/env python
2
3 '''
4 jpk.py
5
6 Driver for jpk files.
7
8 Copyright ??? by Massimo Sandal?
9 with modifications by Dr. Rolf Schmidt (Concordia University, Canada)
10
11 This program is released under the GNU General Public License version 2.
12 '''
13
14 import os.path
15
16 import lib.curve
17 import lib.driver
18 import lib.plot
19
20 class DataChunk(list):
21     #Dummy class to provide ext and ret methods to the data list.
22
23     def ext(self):
24         halflen=(len(self)/2)
25         return self[0:halflen]
26
27     def ret(self):
28         halflen=(len(self)/2)
29         return self[halflen:]
30
31 class jpkDriver(lib.driver.Driver):
32
33     def __init__(self, filename):
34         self.filename=filename #self.filename can always be useful, and should be defined
35         self.filedata = open(filename,'r') #We open the file
36         self.filelines=self.filedata.readlines()
37         self.filedata.close()
38         '''
39         These are two strings that can be used by Hooke commands/plugins to understand what they are looking at. They have no other
40         meaning. They have to be somehow defined however - commands often look for those variables.
41
42         self.filetype should contain the name of the exact filetype defined by the driver (so that filetype-specific commands can know
43                       if they're dealing with the correct filetype)
44         self.experiment should contain instead the type of data involved (for example, various drivers can be used for force-clamp experiments,
45                       but hooke commands could like to know if we're looking at force clamp data, regardless of their origin, and not other
46                       kinds of data)
47
48         Of course, all other variables you like can be defined in the class.
49         '''
50         self.filetype = 'jpk'
51         self.experiment = 'smfs'
52
53
54
55     def __del__(self):
56         self.filedata.close()
57
58     def _read_data_segment(self):
59         #routine that actually reads the data
60
61         height_ms=[]
62         height_m=[]
63         height=[]
64         v_deflection=[]
65         h_deflection=[]
66
67         self.springconstant=0 #if we don't meet any spring constant, use deflection...
68
69         for line in self.filelines:
70             #we meet the segment defining the order of data columns
71
72             if line[0:9]=='# columns':
73                 splitline=line.split()[2:]
74                 height_ms_index=splitline.index('smoothedStrainGaugeHeight')
75                 height_m_index=splitline.index('strainGaugeHeight')
76                 height_index=splitline.index('height')
77                 v_deflection_index=splitline.index('vDeflection')
78                 #h_deflection=splitline.index('hDeflection')
79
80             if line[0:16]=='# springConstant':
81                 self.springconstant=float(line.split()[2])
82
83             if line[0] != '#' and len(line.split())>1:
84                 dataline=line.split()
85                 height_ms.append(float(dataline[height_ms_index]))
86                 height_m.append(float(dataline[height_m_index]))
87                 height.append(float(dataline[height_index]))
88                 v_deflection.append(float(dataline[v_deflection_index]))
89                 #h_deflection.append(float(dataline[h_deflection_index]))
90
91         if self.springconstant != 0:
92             force=[item*self.springconstant for item in v_deflection]
93         else: #we have measured no spring constant :(
94             force=v_deflection
95
96         height_ms=DataChunk([item*-1 for item in height_ms])
97         height_m=DataChunk([item*-1 for item in height_m])
98         height=DataChunk([item*-1 for item in height])
99         deflection=DataChunk(v_deflection)
100         force=DataChunk(force)
101
102         return height_ms,height_m,height,deflection,force
103
104     def close_all(self):
105         self.filedata.close()
106
107     def default_plots(self):
108
109         height_ms,height_m,height,deflection,force=self._read_data_segment()
110
111         height_ms_ext=height_ms.ext()
112         height_ms_ret=height_ms.ret()
113         force_ext=force.ext()
114         force_ret=force.ret()
115         #reverse the return data, to make it coherent with hooke standard
116         height_ms_ret.reverse()
117         force_ret.reverse()
118
119         if self.springconstant != 0:
120             #TODO: force is not really a unit
121             y_unit = 'force'
122         else:
123             y_unit = 'm'
124
125         extension = lib.curve.Curve()
126         retraction = lib.curve.Curve()
127
128         extension.color = 'red'
129         extension.label = 'extension'
130         extension.style = 'plot'
131         extension.title = 'Force curve'
132         extension.units.x = 'm'
133         extension.units.y = y_unit
134         extension.x = height_ms_ext
135         extension.y = force_ext
136         retraction.color = 'blue'
137         retraction.label = 'retraction'
138         retraction.style = 'plot'
139         retraction.title = 'Force curve'
140         retraction.units.x = 'm'
141         retraction.units.y = y_unit
142         retraction.x = height_ms_ret
143         retraction.y = force_ret
144
145         plot = lib.plot.Plot()
146         plot.title = os.path.basename(self.filename)
147         plot.curves.append(extension)
148         plot.curves.append(retraction)
149
150         plot.normalize()
151         return plot
152
153     def deflection(self):
154         height_ms,height_m,height,deflection,force=self._read_data_segment()
155         deflection_ext=deflection.ext()
156         deflection_ret=deflection.ret()
157         deflection_ret.reverse()
158         return deflection_ext,deflection_ret
159
160     def is_me(self):
161         '''
162         we define our magic heuristic for jpk files
163         '''
164         myfile=file(self.filename)
165         headerlines=myfile.readlines()[0:3]
166         myfile.close()
167         if headerlines[0][0:11]=='# xPosition' and headerlines[1][0:11]=='# yPosition':
168             return True
169         else:
170             return False