1
2
3
4
5
6 """
7 ICP data reader.
8
9 summary(filename) - reads the header information
10 read(filename) - reads header information and data
11 """
12
13 import numpy as N
14 import datetime,sys
15 from reflectometry.reduction import _reduction
16
18 """
19 Read ICP data, including PSD data if lines contain commas.
20 """
21 rows = []
22 blocks = []
23
24 line = fh.readline().rstrip()
25 linenum = 1
26 while line != '':
27
28
29
30
31
32
33
34
35 rows.append([float(val) for val in line.split()])
36 line = fh.readline().rstrip()
37 linenum += 1
38
39
40
41 b = []
42 while ',' in line:
43 b.append(line)
44 line = fh.readline()
45 linenum += 1
46
47
48
49 if b != [] and b[-1].rstrip()[-1] == ",":
50 b.append(line)
51 line = fh.readline()
52 linenum += 1
53
54 if b != []:
55
56 s = "".join(b)
57
58
59
60 if blocks != []:
61
62 z = N.empty(blocks[0].shape,'i')
63 i,j = _reduction.str2imat(s,z)
64 if i*j != z.size:
65 raise IOError,"Inconsistent dims at line %d"%linenum
66 else:
67
68 n = int(len(s)/2+1)
69 z = N.empty(n,'i')
70 i,j = _reduction.str2imat(s,z)
71
72 if i==1 or j==1:
73 z = z[:i*j].reshape(i*j)
74 else:
75 z = z[:i*j].reshape(i,j)
76 blocks.append(z)
77
78 elif blocks != []:
79
80
81 blocks.append(N.zeros(blocks[-1].shape,'i'))
82
83
84
85
86
87 if blocks != [] and len(blocks) < len(rows):
88 blank = N.zeros(blocks[0].shape,'i')
89 blocks = [blank]*(len(blocks)-len(rows)) + blocks
90
91
92 X = N.array(rows, 'd')
93 Z = N.array(blocks)
94 return X,Z
95
96
98 """
99 Read the next line of text into a set of words.
100 """
101 line=file.readline()
102 return line.split()
103
105 """
106 Build a token list from a line which can be a mix of quoted strings
107 and unquoted values separated by spaces. Uses single quotes only.
108 Does not test for escaped single quotes.
109 """
110 line = file.readline()
111 tokens = []
112 curtoken=None
113 inquote = False
114 for c in line:
115 if c == "'":
116 if inquote:
117 tokens.append("".join(curtoken))
118 curtoken = None
119 inquote = False
120 else:
121 curtoken = []
122 inquote = True
123 elif inquote:
124 curtoken.append(c)
125 elif c.isspace():
126 if curtoken != None:
127 tokens.append("".join(curtoken))
128 curtoken = None
129 else:
130 if curtoken == None:
131 curtoken = [c]
132 else:
133 curtoken.append(c)
134
135 return tokens
136
138 -class Motor(object): pass
143
147
149 """
150 Read the tow line summary at the start of the ICP data files.
151 """
152
153 file = self.file
154 tokens = get_quoted_tokens(file)
155 self.filename=tokens[0]
156 self.timestamp = datetime.datetime(2000,1,1)
157 self.date=self.timestamp.strptime(tokens[1],'%b %d %Y %H:%M')
158 self.scantype = tokens[2]
159 self.prefactor = float(tokens[3])
160 self.monitor=float(tokens[4])
161 self.count_type=tokens[5]
162 self.points=int(tokens[6])
163 self.data_type=tokens[7]
164
165
166 file.readline()
167
168
169 line = file.readline()
170 polarized_index = line.find("F1: O", 52)
171 if polarized_index > 0:
172 self.comment = line[:polarized_index].rstrip()
173 F1 = '+' if line.find("F1: ON", 52)>0 else '-'
174 F2 = '+' if line.find("F2: ON", 52)>0 else '-'
175 self.polarization = F1+F2
176 else:
177 self.comment = line.rstrip()
178 self.polarization = ""
179
180
182 """
183 Read I-buffer structure, excluding motors.
184 """
185 file = self.file
186
187
188 tokenized=get_tokenized_line(file)
189 fieldnames = file.readline()
190
191
192
193
194 self.collimations = [float(s) for s in tokenized[0:4]]
195 self.mosaic = [float(s) for s in tokenized[4:7]]
196 self.wavelength=float(tokenized[7])
197 self.Tstart=float(tokenized[8])
198 self.Tstep=float(tokenized[9])
199 self.Hfield=float(tokenized[10])
200
202 """
203 Read R-buffer structure, excluding motors.
204 """
205 file = self.file
206
207 tokenized=get_tokenized_line(file)
208 fieldnames = file.readline()
209
210
211
212
213 self.Mon1=float(tokenized[0])
214 self.Exp=float(tokenized[1])
215 self.Dm=float(tokenized[2])
216 self.wavelength=float(tokenized[3])
217 self.Tstart=float(tokenized[4])
218 self.Tstep=float(tokenized[5])
219 self.Hfield=float(tokenized[6])
220 self.numDet=float(tokenized[7])
221 self.SclFac=float(tokenized[8])
222
224 """
225 Read Q-buffer structure.
226 """
227 file = self.file
228
229 tokenized=get_tokenized_line(file)
230 self.collimations=[float(s) for s in tokenized[0:4]]
231 self.mosaic=[float(s) for s in tokenized[4:7]]
232 orient1=[float(s) for s in tokenized[7:10]]
233
234 orient2=[float(s) for s in tokenized[11:14]]
235
236 file.readline()
237 tokenized=get_tokenized_line(file)
238 lattice=Lattice()
239 lattice.a=float(tokenized[0])
240 lattice.b=float(tokenized[1])
241 lattice.c=float(tokenized[2])
242 lattice.alpha=float(tokenized[3])
243 lattice.beta=float(tokenized[4])
244 lattice.gamma=float(tokenized[5])
245 self.lattice=lattice
246
247 file.readline()
248 tokenized=get_tokenized_line(file)
249 self.ecenter=float(tokenized[0])
250 self.deltae=float(tokenized[1])
251 self.ef=float(tokenized[2])
252 self.monochromator_dspacing=float(tokenized[3])
253 self.analyzer_dspacing=float(tokenized[4])
254 self.tstart=float(tokenized[5])
255 self.tstep=float(tokenized[6])
256 tokenized=get_tokenized_line(file)
257 self.Efixed=tokenized[4]
258 tokenized=get_tokenized_line(file)
259 self.qcenter=[float(s) for s in tokenized[0:3]]
260 self.qstep=[float(s) for s in tokenized[3:6]]
261 self.hfield=float(tokenized[6])
262
263 file.readline()
264
266 """
267 ICP sometimes records the incorrect wavelength in the file. Make
268 sure the right value is being used. Be annoying about it so that
269 if the wavelength was changed for a legitimate reason the user can
270 override. L is the value in the file. dectector.wavelength should
271 already be set to the default for the instrument.
272 """
273 dataset = self.filename[:5]
274 wavelength = self.wavelength
275 if dataset in overrides:
276
277
278 wavelength = overrides[dataset]
279 message("Using wavelength %s for %s"%(wavelength,dataset))
280 elif wavelength == 0:
281
282 wavelength = default
283 message("Using default wavelength %s for %s"\
284 %(wavelength,self.path))
285 elif abs(default-wavelength)/default > 0.01:
286
287 if question("ICP recorded a wavelength of %s in %s. \
288 Do you want to use the default wavelength %s instead?"\
289 %(wavelength,self.path,default)):
290 wavelength = default
291
292
293 return wavelength
294
295
297 """
298 Read the 6 motor lines, returning a dictionary of
299 motor names and start-step-stop values.
300 E.g.,
301
302 M = _readmotors(file)
303 print M['a1'].start
304 """
305 self.motor = MotorSet()
306 while True:
307 words=get_tokenized_line(self.file)
308 if words[0] == 'Mot:': break
309 motor = Motor()
310 motor.start=float(words[1])
311 motor.step=float(words[2])
312 motor.stop=float(words[3])
313 name = words[0] if not words[0].isdigit() else 'a'+words[0]
314 setattr(self.motor,name,motor)
315
317 """
318 Get a list of column names. Transform the names of certain
319 columns to make our lives easier elsewhere:
320 #1 COUNTS -> counts
321 #2 COUNTS -> counts2
322 MON -> monitor
323 MIN -> time
324 Q(x) -> qx, Q(y) -> qy, Q(z) -> qz
325 All column names are uppercase.
326 """
327 line = self.file.readline()
328 line = line.lower()
329 for (old,new) in (('#1 counts','counts'),
330 ('#2 counts','counts2'),
331 (' mon ',' monitor '),
332 (' min ',' time '),
333 ('(',''),
334 (')',''),
335 ):
336 line = line.replace(old,new)
337 self.columnnames = line.split()
338
339
341 '''
342 Read and parse ICP data columns listed in columns. Return a dict of
343 column name: vector. If using a position sensitive detector, return
344 an array of detector values x scan points.
345 '''
346 values,detector = readdata(self.file)
347 self.column = ColumnSet()
348 for (c,v) in zip(self.columnnames,values.T):
349 setattr(self.column,c,v)
350 self.detector = detector
351 self.counts = detector if detector.size > 0 else self.column.counts
352 self.points = len(self.column.counts)
353
355 """
356 Generate vectors for each of the motors if a vector is not
357 already stored in the file.
358 """
359 for (M,R) in self.motor.__dict__.iteritems():
360 if not hasattr(self.column,M):
361 if R.step != 0.:
362 vector = N.arange(R.start,R.step,R.stop)
363
364 vector = vector[:self.points]+0
365 else:
366 vector = R.start * N.ones(self.points)
367 setattr(self.column,M,vector)
368 pass
369
391
393 """
394 Read header from file, returning a dict of fields.
395 """
396 self.file = gzopen(self.path)
397 self.parseheader()
398 data1 = self.file.readline()
399 data2 = self.file.readline()
400 self.PSD = (',' in data2)
401 self.file.close()
402
418
420 return hasattr(self.column,column)
421
423 if self.detector.size > 1:
424 return self.detector
425 else:
426 return self.column.counts
427
429 """Read an ICP file and return the corresponding ICP file object"""
430 icp = ICP(filename)
431 icp.read()
432 return icp
433
435 """Read an ICP file header and return the corresponding ICP file object"""
436 icp = ICP(filename)
437 icp.summary()
438 return icp
439
440 -def gzopen(filename,mode='r'):
441 """
442 Open file or gzip file
443 """
444 if filename.endswith('.gz'):
445 import gzip
446 file = gzip.open(filename, mode)
447 else:
448 file = open(filename, mode)
449 return file
450
452 import numpy
453 import data
454 d = data.Data()
455 d.vlabel = 'Counts'
456 d.v = icp.counts
457 d.xlabel = icp.columnnames[0].capitalize()
458 d.x = icp.column[icp.columnnames[0]]
459 if len(d.v.shape) > 1:
460 d.ylabel = 'Pixel'
461 d.y = numpy.arange(d.v.shape[0])
462 return d
463
468
469
472
474 """
475 Read and print all command line arguments
476 """
477 import sys
478 if len(sys.argv) < 2:
479 print "usage: python icpformat.py file*"
480 for file in sys.argv[1:]:
481 fields = read(file)
482 keys = fields.__dict__.keys()
483 keys.sort()
484 for k in keys: print k,getattr(fields,k)
485
503
505 import sys
506 if len(sys.argv) != 2:
507 print "usage: python icpformat.py file"
508 else:
509 plot(sys.argv[1])
510
511 if __name__=='__main__':
512 plot_demo()
513
514