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