1 |
""" |
2 |
ba: Biosensor Array class for storing SPRI data. |
3 |
Christopher Lausted, Institute for Systems Biology, |
4 |
Yuhang Wan, OSPRAI developers |
5 |
Last modified on 100517 (yymmdd) |
6 |
|
7 |
Examples: |
8 |
#ba1 = BiosensorArray(800,1500) ## Allocate object with 800 spots of 1500 time points. |
9 |
#ba1.roi[799].time[1499] = 7502.1 ## Set time in seconds. |
10 |
#ba1.roi[799].value[1499] = 0.50 ## Set SPR reflectance signal. |
11 |
#ba1.roi[799].name = "anti-IgG" ## Set name of microarray feature. |
12 |
""" |
13 |
__version__ = "100517" |
14 |
|
15 |
## Import libraries. |
16 |
import numpy as np |
17 |
#import matplotlib.pyplot as plt |
18 |
from datetime import date |
19 |
|
20 |
|
21 |
class BiosensorArray(object): |
22 |
""" |
23 |
The Biosensor Array class holds all ROIs (spots) |
24 |
from an SPRI microarray run. |
25 |
|
26 |
Property Type Description |
27 |
-------- -------------- --------------------------------------- |
28 |
roi list of object List of RegOfInterest objects. |
29 |
rois integer Size of roi (Number of ROIs). |
30 |
dpoints integer Number of datapoints in each ROI. |
31 |
primarydatafiles List of file names. |
32 |
comments list of string List of comments regarding experiments. |
33 |
""" |
34 |
|
35 |
def __init__(self, roi_size, datapoint_size): |
36 |
"""This object is dimensioned upon initialization.""" ## Might improve speed. |
37 |
## Use a list comprehension to dimension list of classes. |
38 |
self.roi = [RegOfInterest(i,datapoint_size) for i in range(roi_size)] |
39 |
## Remember the dimensions for quick bounds-checking later. |
40 |
self.rois = roi_size |
41 |
self.dpoints = datapoint_size |
42 |
## Use these to keep track of laboratory notes. |
43 |
self.primarydatafiles = [""] ## Like "spritdata.txt" |
44 |
self.comments = [""] ## Like "Antibody data from 1 Jan 2010" |
45 |
|
46 |
def xy2uid(self, gx, gy, x, y): |
47 |
"""Given roi coordinates, find corresponding uid (index).""" |
48 |
coor1 = (gx, gy, x, y) |
49 |
for ob in self.roi: |
50 |
coor2 = (ob.gridx, ob.gridy, ob.spotx, ob.spoty) |
51 |
if (coor1==coor2): return ob.uid ## Success. |
52 |
return -1 ## Failure. |
53 |
|
54 |
def set_plot_all(self): |
55 |
"""Choose to plot every sensorgram.""" |
56 |
for ob in self.roi: ob.plottable = True |
57 |
|
58 |
def set_plot_list(self, ilist): |
59 |
"""Choose a list of sensorgrams to plot""" |
60 |
for ob in self.roi: ob.plottable = False |
61 |
for i in ilist: self.roi[i].plottable = True |
62 |
|
63 |
## A pyplot feature for testing purposes. |
64 |
def plot(self): |
65 |
"""Show plot of the selected sensorgrams.""" |
66 |
plt.clf() |
67 |
plt.title('SPR Data plotted %s' % date.today().isoformat()) |
68 |
plt.xlabel('Time (s)') |
69 |
plt.ylabel('SPR Response') |
70 |
plt.grid(True) |
71 |
## Plot traces. |
72 |
for ob in self.roi: |
73 |
if (ob.plottable==True): |
74 |
mylabel = "%i:%s" % (ob.index,ob.name) |
75 |
plt.plot(ob.time, ob.value, label=mylabel) |
76 |
plt.legend(loc='best') |
77 |
plt.show() |
78 |
### End of BiosensorArray class definition. |
79 |
|
80 |
|
81 |
class RegOfInterest(object): |
82 |
""" |
83 |
This Region Of Interest class can hold one SPR sensorgram. |
84 |
|
85 |
Property Type Description |
86 |
-------- -------------- --------------------------------------------- |
87 |
uid integer Unique ID integer. Never changes. |
88 |
index integer Changes if ba size changes (add/remove rois). |
89 |
time nparray Usually seconds. |
90 |
value nparray Arbitrary units. |
91 |
dpoints integer Can use for bounds checking. |
92 |
name string Name of ROI. |
93 |
desc string Description of ROI |
94 |
|
95 |
gridx integer Can be Block number from GAL file. |
96 |
gridy integer Unused? |
97 |
spotx integer ROI column number. |
98 |
spoty integer ROI row number. |
99 |
bgroi list of integer One or more background ROIs. |
100 |
calibM float Slope used for calibration |
101 |
calibB float Intercept used for calibration. |
102 |
plottable boolean Whether to plot |
103 |
|
104 |
injconc list of float One or more analyte concentrations. |
105 |
injstart list of float One or more injection start times. |
106 |
injstop list of float One or more injection start times. |
107 |
injrind list of float One or more expected refractive index jumps. |
108 |
|
109 |
flow float Flowrate of injection. |
110 |
model ref to funct Model describing this ROI. |
111 |
params dict of dict Parameters for this model. |
112 |
""" |
113 |
|
114 |
def __init__(self, i, datapoint_size): |
115 |
""" |
116 |
Each ROI in a list needs a unique ID number which will be i+1. |
117 |
The time and value arrays must be allocated using datapoint_size. |
118 |
""" |
119 |
self.uid = i+1 ## Unique ID integer. Never changes. |
120 |
self.index = i ## Changes if ba size changes (add/remove rois). |
121 |
self.time = np.zeros(datapoint_size, dtype=float) ## Usually seconds. |
122 |
self.value = np.zeros(datapoint_size, dtype=float) ## Arbitrary units. |
123 |
self.dpoints = datapoint_size ## Can use for bounds checking. |
124 |
## Useful optional information. Usually from GAL or Key files. |
125 |
self.name = "Spot%i" % (i+1) |
126 |
self.desc = "Description" |
127 |
self.gridx = 0 ## Can be Block number from GAL file. |
128 |
self.gridy = 0 ## Unused? |
129 |
self.spotx = 0 ## ROI column number. |
130 |
self.spoty = 0 ## ROI row number. |
131 |
self.bgroi = [0] ## One or more background ROIs. |
132 |
self.calibM = 1 ## Slope used for calibration |
133 |
self.calibB = 0 ## Intercept used for calibration. |
134 |
self.plottable = True ## Whether to plot |
135 |
## Optional injection information. Usually from Clamp or ICM Method files. |
136 |
self.injconc = [0.0] ## One or more analyte concentrations. |
137 |
self.injstart = [0.0] ## One or more injection start times. |
138 |
self.injstop = [0.0] ## One or more injection start times. |
139 |
self.injrind = [0.0] ## One or more expected refractive index jumps. |
140 |
self.flow = 0 ## Flowrate of injection. |
141 |
## Curve fitting information. Model and model parameters. |
142 |
## Example model is reference to function like data=simple1to1(times,params) |
143 |
## Example params = {'Rmax': {'value':1, 'min':0, 'max':10, 'fixed':'float'} } |
144 |
self.model = None ## Model describing this roi. Reference to a function. |
145 |
self.params = [] ## Parameters for this model. A dictionary of dictionaries. |
146 |
|
147 |
def time2dp(self, t): |
148 |
"""Find datapoint closest to given time.""" |
149 |
pos2 = self.time.searchsorted(t) ## Time point just after t. |
150 |
pos2 = min(pos2, len(self.time)-1) ## Avoid indexing error. |
151 |
pos1 = max(pos2-1,0) ## Time point just before t. |
152 |
t2 = abs(self.time[pos2] - t) |
153 |
t1 = abs(self.time[pos1] - t) |
154 |
## Decide if time point just before or just after is closer. |
155 |
if (t2<t1): |
156 |
return pos2 |
157 |
else: |
158 |
return pos1 |
159 |
|
160 |
def time2val(self, t1, t2): |
161 |
"""Return list of SPR values between t1 and t2""" |
162 |
dp1, dp2 = self.time2dp(t1), self.time2dp(t2) |
163 |
return [self.value[i] for i in range(dp1, dp2)] |
164 |
|
165 |
## End of RegOfInterest definition. |
166 |
|
167 |
''' |
168 |
## Here are a few lines to test this class. |
169 |
if __name__ == '__main__': |
170 |
print "Starting demo..." |
171 |
print "Test plotting..." |
172 |
x = BiosensorArray(10,10) |
173 |
x.roi[0].time = np.arange(10) |
174 |
x.roi[0].value = np.arange(10)**2 |
175 |
x.roi[1].time = np.arange(10) |
176 |
x.roi[1].value = np.arange(10)**1.5 |
177 |
x.roi[9].time = np.arange(10) |
178 |
x.roi[9].value = np.arange(10)**1 |
179 |
#x.set_plot_all() |
180 |
x.set_plot_list([0,1,9]) |
181 |
x.plot() |
182 |
print "Test xy2uid... 9 =", |
183 |
x.roi[9].gridx = 2 |
184 |
print x.xy2uid(2,0,0,0) |
185 |
print "Test time2dp... 5.6 =>", |
186 |
print x.roi[9].time2dp(5.6) |
187 |
print "Demo finished." |
188 |
''' |
189 |
|
190 |
|
191 |
################################# End of module ################################# |