3f34bfbb403c51a858f6eea5db25a87b40ebf787
[hooke.git] / hooke / driver / mcs.py
1 # Copyright (C) 2009-2012 Allen Chen
2 #                         Massimo Sandal <devicerandom@gmail.com>
3 #                         W. Trevor King <wking@drexel.edu>
4 #
5 # This file is part of Hooke.
6 #
7 # Hooke is free software: you can redistribute it and/or modify it under the
8 # terms of the GNU Lesser General Public License as published by the Free
9 # Software Foundation, either version 3 of the License, or (at your option) any
10 # later version.
11 #
12 # Hooke is distributed in the hope that it will be useful, but WITHOUT ANY
13 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14 # A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
15 # details.
16 #
17 # You should have received a copy of the GNU Lesser General Public License
18 # along with Hooke.  If not, see <http://www.gnu.org/licenses/>.
19
20 """Driver for mcs fluorescence files.
21 """
22
23 import os.path
24
25 import lib.curve
26 import lib.driver
27 import lib.plot
28 import struct
29
30 class mcsDriver(lib.driver.Driver):
31
32     def __init__(self, filename):
33         '''
34         Open the RED (A) ones; the BLUE (D) mirror ones will be automatically opened
35         '''
36         #obtain name of blue files
37         othername=filename
38         if othername[-8]=='a': #fixme: how to make it general? (maybe should not be in driverspace but in environment...)
39             oth=list(othername)
40             oth[-8]='d'
41             othername=''.join(oth)
42         self.filename=filename
43         self.othername=othername
44
45         #print self.filename, self.othername
46
47         self.filedata=open(filename,'rb')
48         self.reddata=self.filedata.read()
49         self.filedata.close()
50
51         self.filebluedata=open(othername,'rb') #open also the blue ones
52         self.bluedata=self.filebluedata.read()
53         self.filebluedata.close()
54
55     def close_all(self):
56         self.filedata.close()
57         self.filebluedata.close()
58
59     def default_plots(self):
60         #TODO: rename blue and red data to something more appropriate if possible
61         red_data=self.read_file(self.reddata)
62         blue_data=self.read_file(self.bluedata)
63         blue_data=[-1*float(item) for item in blue_data] #visualize blue as "mirror" of red
64
65         extension = lib.curve.Curve()
66         retraction = lib.curve.Curve()
67
68         extension.color = 'red'
69         extension.label = 'extension'
70         extension.style = 'plot'
71         extension.title = 'Force curve'
72         #FIXME: if there's an header saying something about the time count, should be used
73         #TODO: time is not really a unit
74         extension.units.x = 'time'
75         extension.units.y = 'count'
76         extension.x = range(len(red_data))
77         extension.y = red_data
78         retraction.color = 'blue'
79         retraction.label = 'retraction'
80         retraction.style = 'plot'
81         retraction.title = 'Force curve'
82         #FIXME: if there's an header saying something about the time count, should be used
83         #TODO: time is not really a unit
84         retraction.units.x = 'time'
85         retraction.units.y = 'count'
86         retraction.x = range(len(blue_data))
87         retraction.y = blue_data
88
89         plot = lib.plot.Plot()
90         plot.title = os.path.basename(self.filename)
91         plot.curves.append(extension)
92         plot.curves.append(retraction)
93
94         plot.normalize()
95         return plot
96
97     def is_me(self):
98         if os.path.isdir(path):
99             return False
100         if self.filename[-3:].lower()=='mcs':
101             return True
102         else:
103             return False
104
105     def read_file(self, raw_data):
106         real_data=[]
107         intervalsperfile=struct.unpack('h', raw_data[10:12])[0] #read in number of intervals in this file
108                                                                 #this data is contained in bit offset 10-12 in mcs file
109         #see http://docs.python.org/library/struct.html#module-struct for additional explanation
110
111         numbytes=len(raw_data) #data is stored in 4-byte chunks, starting with pos 256
112         for j in range(0,intervalsperfile): #read in all intervals in file
113             temp=raw_data[256+j*4:256+j*4+4]    #data starts at byte offset 256
114             real_data.append(struct.unpack('i', temp)[0]) #[0] because it returns a 1-element tuple
115         return real_data