ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/osprai/osprai/trunk/io_module.py
Revision: 47
Committed: Fri Feb 4 19:06:37 2011 UTC (8 years, 4 months ago) by clausted
File size: 15254 byte(s)
Log Message:
Changes only to the docstrings of four modules so that Sphinx can use them.  Update references in mainapi.rst.  
Line File contents
1 """
2 io_module
3 ---------
4
5 Input/Output module for converting files to Biosensor Array class.
6 Supported sensorgram types include Biosensor, CLAMP, SPRit, and Plexera ICM.
7 Supported microarray types include GAL and ISB Map.
8
9 .. moduleauthor:: Christopher Lausted,
10 Institute for Systems Biology,
11 OSPRAI developers.
12 Examples::
13
14 >>> import io_module as io
15 >>> ba1 = io.readsprit("spritdata.txt")
16 >>> ba1 = io.readclamp("spritdata.txt")
17 >>> ba1 = io.readicmtxt("icmdata.txt")
18 >>> ba1 = io.readbiosensor("icmdata.txt")
19 >>> ba2 = io.applygal(ba1, "galfile.gal")
20 >>> ba2 = io.applykey(ba1, "keyfile.tsv")
21 >>> ba3 = io.applymethod(ba2, "icmmethod.xls")
22 >>> io.writesprit(ba3, "newspritfile.txt")
23 >>> io.writeclamp(ba3, "newclampfile.txt")
24 """
25 __version__ = "110204"
26
27
28 ## Import libraries.
29 from copy import deepcopy
30 from os import getcwd
31 from time import mktime
32 import numpy as np ## Numpy array library.
33 import ba_class as ba ## Our Biosensor Array class.
34 reload(ba)
35
36 def readsprit(fname):
37 """
38 Read a SPRit text file into a ba class.
39 It has two tab-delimited columns and two header lines.
40 Here is a very simple example with 2 rois and 3 datapoints::
41
42 Elapsed Time (Seconds) Average Intensity (Pixel Intensity)
43 BEGIN
44 0.000000e+000 2.863145e+003
45 5.013000e+000 2.863367e+003
46 1.002500e+001 2.862950e+003
47 0.000000e+000 2.862875e+003
48 5.013000e+000 2.862510e+003
49 """
50
51 ## Try to open file. Return tiny ba object if it fails.
52 ba0 = ba.BiosensorArray(1,1)
53 try:
54 fp = open(fname, "r")
55 except IOError:
56 print 'Error: Cannot open file %s for reading' % fname
57 return ba0
58
59 ## Check header lines for signature text.
60 txt = fp.readline() # 'Elapsed Time...'
61 txt = fp.readline() # 'BEGIN'
62 if ('BEGIN' not in txt):
63 print "Error: Second line is not BEGIN."
64 fp.close()
65 return ba0
66
67 ## Put data into one big text string and close.
68 txtfile = fp.readlines()
69 fp.close()
70
71 ## Change text into array
72 sprtable = np.zeros((len(txtfile),2), dtype=float) ## Redimension Nx2
73 for i in range(len(txtfile)):
74 txt = txtfile[i].split('\t')
75 sprtable[i,0] = float(txt[0]) ## Time column.
76 sprtable[i,1] = float(txt[1]) ## Signal column.
77
78 ## Find number of ROIs in file.
79 for i in range(1,len(sprtable)):
80 ## See when the time drops back to zero.
81 if (sprtable[i,0] < sprtable[i-1,0]): break
82 rows = i ## Datapoints or new array rows.
83 rois = int(len(sprtable) / rows)
84
85 ## Move data the old-fashioned iterative way.
86 ba0 = ba.BiosensorArray(rois,rows)
87 k = 0
88 for i in range(rois):
89 for j in range(rows):
90 ba0.roi[i].time[j] = sprtable[k,0]
91 ba0.roi[i].value[j] = sprtable[k,1]
92 k +=1
93
94 return ba0
95 """End of readsprit() function"""
96
97
98 def writesprit(ba0, fname):
99 """
100 Write a ba class to a SPRit text file.
101 """
102 fp=file(fname,'w')
103 fp.write("Elapsed Time (Seconds)\tAverage Intensity (Pixel Intensity)\r\n")
104 fp.write("BEGIN\r\n")
105 for roi in range(len(ba0.roi)): ## Could also use ba.rois.
106 for dpoint in range(len(ba0.roi[0].time)): ## Could also use ba.dpoints.
107 txt = "%f\t%f\r\n" % (ba0.roi[roi].time[dpoint], ba0.roi[roi].value[dpoint])
108 fp.write(txt)
109 fp.close
110 print "File %s saved in %s." % (fname, getcwd())
111 return
112 """End of writesprit() function"""
113
114
115 def readclamp(fname):
116 """
117 Read a Clamp text file into a ba class.
118 It has two tab-delimited columns per SPR flowcell/roi..
119 It has a varying number of header lines with injection information.
120 Here is a very simple example with 2 rois and 3 datapoints::
121
122 Vers 3.41 Data
123 Conc1 0 0 0 0
124 Start1 301.5 301.5 301.5 301.5
125 Stop1 949.8 949.8 949.8 949.8
126 RInd1 0 0 0 0
127 Conc2 0 0 0 0
128 Start2 986.4 0 0 0
129 Stop2 1626 0 0 0
130 RInd2 0 0 0 0
131 Flow 1 1 1 1
132 Time1 Data1 Time2 Data2
133 0.094 0.062 0.094 0.053
134 1.094 0.026 1.094 0.05
135 2.094 0.119 2.094 0.055
136 """
137
138 print "This feature is under construction."
139 return
140 """"End of readclamp() function"""
141
142
143 def writeclamp(ba0, fname):
144 """
145 Write a ba class to a Clamp text file.
146 """
147
148 fp=file(fname,'w')
149 ## First header line.
150 fp.write("Vers 3.41 Data\r\n")
151
152 ## Next write injection information.
153 for inj in range(len(ba0.roi[0].injconc)):
154 fp.write("Conc%i" % (inj+1))
155 for roi in ba0.roi: fp.write("\t%.3f" % roi.injconc[inj])
156 fp.write("\r\nStart%i" % (inj+1))
157 for roi in ba0.roi: fp.write("\t%.3f" % roi.injstart[inj])
158 fp.write("\r\nStop%i" % (inj+1))
159 for roi in ba0.roi: fp.write("\t%.3f" % roi.injstop[inj])
160 fp.write("\r\nRInd%i" % (inj+1))
161 for roi in ba0.roi: fp.write("\t%.3f" % roi.injrind[inj])
162 ## Next write flowrate line.
163 fp.write("\r\nFlow")
164 for roi in ba0.roi: fp.write("\t%.3f" % roi.flow)
165 fp.write("\r\n")
166
167 ## Write sensorgram data header line.
168 for i,roi in enumerate(ba0.roi):
169 if (i>0): fp.write("\t")
170 fp.write("Time%i" % (i+1))
171 fp.write("\t")
172 fp.write(roi.name)
173 fp.write("\r\n")
174 ## Write sensorgram data lines. Three decimal places.
175 for dpoint in range(len(ba0.roi[0].time)):
176 for i,roi in enumerate(ba0.roi):
177 if (i>0): fp.write("\t")
178 fp.write("%.3f\t%.3f" % (roi.time[dpoint], roi.value[dpoint]))
179 fp.write("\r\n")
180
181 ## Close file handle and print message.
182 fp.close
183 print "File %s saved in %s." % (fname, getcwd())
184 return
185 """End of writeclamp() function"""
186
187
188 def readicmtxt(fname):
189 """
190 Read a ICM text file into a ba class.
191 Here is a very simple example of the tab-delimited format::
192
193 03/05/2010 13:37:21.312 249.408 0.000 0.000
194 03/05/2010 13:37:22.312 249.306 0.000 0.000
195 """
196
197 ## Try to open file. Return tiny ba object if it fails.
198 ba0 = ba.BiosensorArray(1,1)
199 try:
200 fp = open(fname, "r")
201 except IOError:
202 print 'Error: Cannot open file %s for reading' % fname
203 return ba0
204
205 ## Put data into one big text string and close.
206 txtfile = fp.readlines()
207 fp.close()
208 dpoints = len(txtfile)
209 rois = txtfile[0].count("\t") ## Usually 25.
210
211 ## Create and size ba object.
212 print "This ICM file has %i datapoints for %i ROIs." % (dpoints, rois)
213 ba0 = ba.BiosensorArray(rois, dpoints)
214
215 ## Determine experiment start time so we can make other times relative.
216 x = txtfile[0].split("\t") ## E.g. "03/05/2010 13:37:20.218"
217 t0 = icmtime2sec(x[0]) ## E.g. 1267825040.22
218
219 ## Move the data from txtfile to ba0.
220 for i, txtline in enumerate(txtfile):
221 x = txtline.split("\t")
222 tx = icmtime2sec(x[0]) - t0
223 for j in range(1,rois):
224 ba0.roi[j].time[i] = tx
225 ba0.roi[j].value[i] = float(x[j])
226
227 return ba0
228 """End of readicmtxt"""
229
230
231 def icmtime2sec(timetxt):
232 """
233 Take a time of the form "03/05/2010 15:19:27.312" and return seconds.
234 """
235 cal, clock = timetxt.split(" ")
236 mm, dd, yy = cal.split("/")
237 hh, min, ss = clock.split(":")
238 stime = (int(yy), int(mm), int(dd), int(hh), int(min), 0, 0, 0, 0)
239 return mktime(stime) + float(ss)
240 """End of icmtime2sec"""
241
242
243 def readbiosensor(fname):
244 """
245 Read a Biacore-style text file into a ba class.
246 Here is a very simple example of the tab-delimited format::
247
248 Ab1 Fc=4- 1_X Ab1 Fc=4 -1_Y Ab2 Fc=4 -1_X Ab2 Fc=4 -1_Y
249 13.1 23.7644 93.1 0.713912
250 13.6 23.4265 93.6 0.0541172
251 14.1 23.1625 94.1 0.332768
252 14.6 23.5752 94.6 0.849459
253 """
254
255 ## Try to open file. Return tiny ba object if it fails.
256 ba0 = ba.BiosensorArray(1,1)
257 try:
258 fp = open(fname, "r")
259 except IOError:
260 print 'Error: Cannot open file %s for reading' % fname
261 return ba0
262
263 ## Read header line. Check number of pairs of _X and _Y labels.
264 txthdr = fp.readline()
265 cols = txthdr.count("Fc=")
266 xys = txthdr.count("_X\t") + txthdr.count("_Y\t")+1
267 if ((cols != xys) or ((cols%2) != 0)):
268 print "Error: This is not a valid Biosensor file."
269 return ba0
270
271 ## Put data into one big text string and close.
272 txtfile = fp.readlines()
273 fp.close()
274 dpoints = len(txtfile)
275 rois = int(cols/2)
276
277 ## Create and size ba object.
278 print "This Biosensor file has %i datapoints for %i ROIs." % (dpoints, rois)
279 ba0 = ba.BiosensorArray(rois, dpoints)
280
281 ## Get names of ROIs from header like "Ab1 Fc=4 - 1_Y"
282 txthdr = txthdr.replace(" -","-").replace("- ","-") ## Remove unwanted spaces.
283 names = txthdr.split("\t") ## Use tab delimiter.
284 for j in range(rois):
285 name = names[j*2+1].replace("_Y","").strip(" -")
286 name = name.partition("Fc=") ## Now a 3-tuple.
287 ba0.roi[j].name = name[0] ## Text left of Fc.
288 ba0.roi[j].desc = ("Fc=" + name[2]) ## Text right of Fc.
289
290 ## Move the data from txtfile to ba0.
291 for i, txtline in enumerate(txtfile):
292 x = txtline.split("\t")
293 for j in range(rois):
294 ba0.roi[j].time[i] = float(x[j*2+0])
295 ba0.roi[j].value[i] = float(x[j*2+1])
296
297 return ba0
298 """End of readbiosensor()"""
299
300
301 def writebiosensor(ba0, fname):
302 """
303 Write a ba class to a Biosensor text file.
304 """
305
306 ## This is like a simplified Clamp file.
307 fp=file(fname,'w')
308 ## Write sensorgram data header line.
309 for i,roi in enumerate(ba0.roi):
310 if (i>0): fp.write("\t")
311 name = roi.name.strip() + " " + roi.desc.strip()
312 fp.write("%s_X\t%s_Y" % (name, name))
313 ## Write sensorgram data lines. Three decimal places.
314 for dpoint in range(len(ba0.roi[0].time)):
315 fp.write("\r\n")
316 for i,roi in enumerate(ba0.roi):
317 if (i>0): fp.write("\t")
318 fp.write("%.3f\t%.3f" % (roi.time[dpoint], roi.value[dpoint]))
319
320 ## Close file handle and print message.
321 fp.close
322 print "File %s saved in %s." % (fname, getcwd())
323 return
324 """End of writebiosensor()"""
325
326
327 def applygal(ba0, fname):
328 """
329 Read a Gal file and apply its microarray information.
330
331 *(This function is under construction)*
332 """
333 print "This feature is under construction."
334 return
335 """End of applygal()"""
336
337
338 def applykey(ba0, fname):
339 """
340 Read a Key file and apply its microarray information.
341 Multiple background ROIs are not yet supported.
342 Here is a very simple example::
343
344 No. Description1 Description2 Background ROI Col Row
345 1 Rat TNF Antibody01 2 1 1
346 2 ratIgG Antibody02 4 2 1
347 3 Hum TNF Antibody03 4 3 1
348 4 humIgG Antibody04 2 4 1
349 """
350
351 ## Try to open file. Return unchanged ba object if it fails.
352 try:
353 fp = open(fname, "r")
354 except IOError:
355 print 'Cannot open file %s for reading' % fname
356 return ba0
357 ## Check header lines for signature text.
358 txt = fp.readline()
359 if ("No." not in txt):
360 print "Error: The header line is unfamiliar."
361 fp.close()
362 return ba0
363
364 ## Read all text, convert to 2d list, then six lists (one for each column).
365 ## There's probably an easier way to do this. Maybe in CSV module.
366 txtfile = fp.readlines()
367 fp.close()
368 ## Change text into array
369 keytable = txtfile[:] ## Dimension rows in new 2d list.
370 for i in range(len(txtfile)):
371 txt = str(txtfile[i].strip())
372 keytable[i] = txt.split('\t')
373 ## Use list comprehensions to get one list for each column.
374 id = [int(x[0]) for x in keytable] ## First column is integer.
375 desc1 = [x[1] for x in keytable] ## Second column is text.
376 desc2 = [x[2] for x in keytable] ## Third column is text.
377 bg = [int(x[3]) for x in keytable] ## Fourth column is integer. Change base1 to base0?
378 col = [int(x[4]) for x in keytable] ## Fifth column is integer.
379 row = [int(x[5]) for x in keytable] ## Sixth column is integer.
380
381 ## Check if key file looks valid. These tests are not very thorough!
382 keys = 1 + max(id) - min(id)
383 if (ba0.rois != keys):
384 print "Error: We have %i ROIs but %i keyfile entries." % (ba0.rois, keys)
385 return ba0
386 if ((min(bg) < min(id)) or (max(bg) > max (id))):
387 print "Error: at least one specified background ROI does not exist"
388 print "Identifiers (id) range from %i to %i." % (min(id), max(id))
389 print "Background references range from %i to %i." % (min(bg), max(bg))
390 return ba0
391
392 ## Create new object and put data in it.
393 ba1 = deepcopy(ba0)
394 for i in range(len(id)):
395 ba1.roi[id[i]-1].name = desc1[i]
396 ba1.roi[id[i]-1].desc = desc2[i]
397 ba1.roi[id[i]-1].bgroi = [bg[i]] ## ToDo: Decide if bg will be id or index. Base1 now.
398 ba1.roi[id[i]-1].spotx = col[i]
399 ba1.roi[id[i]-1].spoty = row[i]
400
401 print "Successfully loaded information for %i ROIs." % keys
402 return ba1
403 """End of applykey()"""
404
405
406 def applymethod(ba0, fname):
407 """
408 Read a ICM Analyte/Method xls file and apply its information.
409
410 *(This feature is under construction.)*
411 """
412 print "This feature is under construction."
413 return
414 """End of applymethod()"""
415
416
417
418 def outputbindinglevels(ba0, fname, interval, *baselines):
419 """
420 Measure the binding level changes at multiple intervals along a sensorgram.
421 Write the data to a file. If interval is 500 and baselines are [100, 1100] then
422 binding levels are changes between 100-600s and between 1100-01600s.
423 Average 30s of data.
424 """
425 fp=file(fname,'w')
426
427 ## Measurements
428 for iroi in ba0.roi:
429 fp.write("%i\t%s" % (iroi.index, iroi.name))
430 for j in baselines:
431 t1 = j
432 t2 = j + interval
433 y1 = np.average(iroi.time2val(t1-15, t1+15))
434 y2 = np.average(iroi.time2val(t2-15, t2+15))
435 fp.write("\t%.3f" % (y2-y1))
436 fp.write("\n")
437 fp.close
438 print "File %s saved in %s." % (fname, getcwd())
439 return
440 """End of outputbindinglevels()"""
441
442
443 ## Here are a few lines to test this module.
444 if __name__ == '__main__':
445 print "This module isn't a stand-alone app."
446
447 ################################# End of module #################################