Added README and reorganized directory structure (breaks code)
[hooke.git] / hooke / driver / jpk.py
1 #!/usr/bin/env python
2
3 import string
4 import libhookecurve as lhc 
5
6 class DataChunk(list):
7     #Dummy class to provide ext and ret methods to the data list.
8     
9     def ext(self):
10         halflen=(len(self)/2)
11         return self[0:halflen]
12         
13     def ret(self):
14         halflen=(len(self)/2)
15         return self[halflen:]
16
17 class jpkDriver(lhc.Driver):
18
19     def __init__(self, filename):
20         self.filename=filename #self.filename can always be useful, and should be defined
21         self.filedata = open(filename,'r') #We open the file
22         self.filelines=self.filedata.readlines()
23         self.filedata.close()        
24         '''These are two strings that can be used by Hooke commands/plugins to understand what they are looking at. They have no other
25         meaning. They have to be somehow defined however - commands often look for those variables.
26         
27         self.filetype should contain the name of the exact filetype defined by the driver (so that filetype-specific commands can know
28                       if they're dealing with the correct filetype)
29         self.experiment should contain instead the type of data involved (for example, various drivers can be used for force-clamp experiments,
30                       but hooke commands could like to know if we're looking at force clamp data, regardless of their origin, and not other 
31                       kinds of data)
32         
33         Of course, all other variables you like can be defined in the class.
34         '''
35         self.filetype = 'jpk'
36         self.experiment = 'smfs'
37                   
38         
39
40     def __del__(self):
41         self.filedata.close()   
42     
43     def is_me(self):
44         '''
45         we define our magic heuristic for jpk files
46         '''
47         myfile=file(self.filename)
48         headerlines=myfile.readlines()[0:3]
49         myfile.close()
50         if headerlines[0][0:11]=='# xPosition' and headerlines[1][0:11]=='# yPosition':
51             return True
52         else:
53             return False
54         
55     def close_all(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 deflection(self):
105         height_ms,height_m,height,deflection,force=self._read_data_segment()
106         deflection_ext=deflection.ext()
107         deflection_ret=deflection.ret()
108         deflection_ret.reverse()
109         return deflection_ext,deflection_ret
110         
111     def default_plots(self):
112         
113         height_ms,height_m,height,deflection,force=self._read_data_segment()
114         
115         height_ms_ext=height_ms.ext()
116         height_ms_ret=height_ms.ret()
117         force_ext=force.ext()
118         force_ret=force.ret()
119         #reverse the return data, to make it coherent with hooke standard
120         height_ms_ret.reverse()
121         force_ret.reverse()
122         
123         main_plot=lhc.PlotObject()  
124         main_plot.add_set(height_ms_ext,force_ext)
125         main_plot.add_set(height_ms_ret,force_ret)
126         
127         
128         
129         if self.springconstant != 0:
130             main_plot.units=['meters','force']
131         else:
132             main_plot.units=['meters','meters']
133         
134         main_plot.normalize_vectors()
135         
136         main_plot.destination=0
137         main_plot.title=self.filename
138         
139         return [main_plot]