source: fact/tools/pyscripts/pyfact/pyfact_rename.py@ 12975

Last change on this file since 12975 was 12975, checked in by lusterma, 13 years ago
added iterator to RawData, _test_iter function gives an example on usage, ./pyfact.py can be run directly
  • Property svn:executable set to *
File size: 12.4 KB
Line 
1#!/usr/bin/python
2#
3# Werner Lustermann
4# ETH Zurich
5#
6from ctypes import *
7import numpy as np
8from scipy import signal
9
10# get the ROOT stuff + my shared libs
11from ROOT import gSystem
12# fitslib.so is made from fits.h and is used to access the data
13gSystem.Load('~/py/fitslib.so')
14from ROOT import *
15
16
17class RawData( object ):
18 """ raw data access and calibration
19
20 - open raw data file and drs calibration file
21 - performs amplitude calibration
22 - performs baseline substraction if wanted
23 - provides all data in an array:
24 row = number of pixel
25 col = length of region of interest
26
27 """
28
29 def __init__(self, data_file_name,
30 calib_file_name, baseline_file_name=''):
31 """ initialize object
32
33 open data file and calibration data file
34 get basic information about the data in data_file_name
35 allocate buffers for data access
36
37 data_file_name : fits or fits.gz file of the data including the path
38 calib_file_name : fits or fits.gz file containing DRS calibration data
39 baseline_file_name : npy file containing the baseline values
40
41 """
42
43 self.data_file_name = data_file_name
44 self.calib_file_name = calib_file_name
45 self.baseline_file_name = baseline_file_name
46
47 # baseline correction: True / False
48 if len(baseline_file_name) == 0:
49 self.correct_baseline = False
50 else:
51 self.correct_baseline = True
52
53 # access data file
54 try:
55 data_file = fits(self.data_file_name)
56 except IOError:
57 print 'problem accessing data file: ', data_file_name
58 raise # stop ! no data
59 #: data file (fits object)
60 self.data_file = data_file
61
62 # get basic information about the data file
63 #: region of interest (number of DRS slices read)
64 self.nroi = data_file.GetUInt('NROI')
65 #: number of pixels (should be 1440)
66 self.npix = data_file.GetUInt('NPIX')
67 #: number of events in the data run
68 self.nevents = data_file.GetNumRows()
69
70 # allocate the data memories
71 self.event_id = c_ulong()
72 self.trigger_type = c_ushort()
73 #: 1D array with raw data
74 self.data = np.zeros( self.npix * self.nroi, np.int16 )
75 #: slice where drs readout started
76 self.start_cells = np.zeros( self.npix, np.int16 )
77
78 # set the pointers to the data++
79 data_file.SetPtrAddress('EventNum', self.event_id)
80 data_file.SetPtrAddress('TriggerType', self.trigger_type)
81 data_file.SetPtrAddress('StartCellData', self.start_cells)
82 data_file.SetPtrAddress('Data', self.data)
83
84 # open the calibration file
85 try:
86 calib_file = fits(self.calib_file_name)
87 except IOError:
88 print 'problem accessing calibration file: ', calib_file_name
89 raise
90 #: drs calibration file
91 self.calib_file = calib_file
92
93 baseline_mean = calib_file.GetN('BaselineMean')
94 gain_mean = calib_file.GetN('GainMean')
95 trigger_offset_mean = calib_file.GetN('TriggerOffsetMean')
96
97 self.blm = np.zeros(baseline_mean, np.float32)
98 self.gm = np.zeros(gain_mean, np.float32)
99 self.tom = np.zeros(trigger_offset_mean, np.float32)
100
101 self.Nblm = baseline_mean / self.npix
102 self.Ngm = gain_mean / self.npix
103 self.Ntom = trigger_offset_mean / self.npix
104
105 calib_file.SetPtrAddress('BaselineMean', self.blm)
106 calib_file.SetPtrAddress('GainMean', self.gm)
107 calib_file.SetPtrAddress('TriggerOffsetMean', self.tom)
108 calib_file.GetRow(0)
109
110 self.v_bsl = np.zeros(self.npix) # array of baseline values (all ZERO)
111 self.data_saverage_out = None
112 self.pulse_time_of_maximum = None
113 self.pulse_amplitude = None
114
115 def __iter__(self):
116 """ iterator """
117 return self
118
119 def next(self):
120 """ used by __iter__ """
121 if self.event_id.value == self.nevents:
122 raise StopIteration
123 else:
124 self.data_file.GetNextRow()
125 self.calibrate_drs_amplitude()
126 return self.acal_data, self.start_cells, self.trigger_type.value
127
128 def next_event(self):
129 """ load the next event from disk and calibrate it
130
131 """
132
133 self.data_file.GetNextRow()
134 self.calibrate_drs_amplitude()
135
136 def calibrate_drs_amplitude(self):
137 """ perform the drs amplitude calibration of the event data
138
139 """
140
141 to_mV = 2000./4096.
142 #: 2D array with amplitude calibrated dat in mV
143 acal_data = self.data * to_mV # convert ADC counts to mV
144
145 # make 2D arrays: row = pixel, col = drs_slice
146 acal_data = np.reshape(acal_data, (self.npix, self.nroi) )
147 blm = np.reshape(self.blm, (self.npix, 1024) )
148 tom = np.reshape(self.tom, (self.npix, 1024) )
149 gm = np.reshape(self.gm, (self.npix, 1024) )
150
151 for pixel in range( self.npix ):
152 # rotate the pixel baseline mean to the Data startCell
153 blm_pixel = np.roll( blm[pixel,:], -self.start_cells[pixel] )
154 acal_data[pixel,:] -= blm_pixel[0:self.nroi]
155 acal_data[pixel,:] -= tom[pixel, 0:self.nroi]
156 acal_data[pixel,:] /= gm[pixel, 0:self.nroi]
157
158 self.acal_data = acal_data * 1907.35
159
160
161 def filter_sliding_average(self, window_size=4):
162 """ sliding average filter
163
164 using:
165 self.acal_data
166 filling array:
167 self.data_saverage_out
168
169 """
170
171 #scipy.signal.lfilter(b, a, x, axis=-1, zi=None)
172 data_saverage_out = self.acal_data.copy()
173 b = np.ones( window_size )
174 a = np.zeros( window_size )
175 a[0] = len(b)
176 data_saverage_out[:,:] = signal.lfilter(b, a, data_saverage_out[:,:])
177
178 #: data output of sliding average filter
179 self.data_saverage_out = data_saverage_out
180
181
182 def filter_CFD(self, length=10, ratio=0.75):
183 """ constant fraction discriminator (implemented as FIR)
184
185 using:
186 self.data_saverage_out
187 filling array:
188 self.data_CFD_out
189
190 """
191
192 if self.data_saverage_out == None:
193 print """error pyfact.filter_CFD was called without
194 prior call to filter_sliding_average
195 variable self.data_saverage_out is needed
196 """
197
198 data_CFD_out = self.data_saverage_out.copy()
199 b = np.zeros(length)
200 a = np.zeros(length)
201 b[0] = -1. * ratio
202 b[length-1] = 1.
203 a[0] = 1.
204 data_CFD_out[:,:] = signal.lfilter(b, a, data_CFD_out[:,:])
205
206 #: data output of the constant fraction discriminator
207 self.data_CFD_out = data_CFD_out
208
209 def find_peak(self, min=30, max=250):
210 """ find maximum in search window
211
212 using:
213 self.data_saverage_out
214 filling arrays:
215 self.pulse_time_of_maximum
216 self.pulse_amplitude
217
218 """
219
220 if self.data_saverage_out == None:
221 print """error pyfact.find_peakMax was called without \
222 prior call to filter_sliding_average
223 variable self.data_saverage_out is needed"""
224 pass
225
226 pulse_time_of_maximum = np.argmax( self.data_saverage_out[:,min:max],
227 1)
228 pulse_amplitude = np.max( self.data_saverage_out[:,min:max], 1)
229 self.pulse_time_of_maximum = pulse_time_of_maximum
230 self.pulse_amplitude = pulse_amplitude
231
232 def sum_around_peak(self, left=13, right=23):
233 """ integrate signal in gate around Peak
234
235 using:
236 self.pulse_time_of_maximum
237 self.acal_data
238 filling array:
239 self.pulse_integral_simple
240
241 """
242
243 if self.pulse_time_of_maximum == None:
244 print """error pyfact.sum_around_peak was called \
245 without prior call of find_peak
246 variable self.pulse_time_of_maximum is needed"""
247 pass
248
249 # find left and right limit and sum the amplitudes in the range
250 pulse_integral_simple = np.empty(self.npix)
251 for pixel in range(self.npix):
252 min = self.pulse_time_of_maximum[pixel]-left
253 max = self.pulse_time_of_maximum[pixel]+right
254 pulse_integral_simple[pixel] = self.acal_data[pixel,min:max].sum()
255
256 self.pulse_integral_simple = pulse_integral_simple
257
258 def baseline_read_values(self, file, bsl_hist='bsl_sum/hplt_mean'):
259 """
260
261 open ROOT file with baseline histogram and read baseline values
262 file name of the root file
263 bsl_hist path to the histogram containing the basline values
264
265 """
266
267 try:
268 f = TFile(file)
269 except:
270 print 'Baseline data file could not be read: ', file
271 return
272
273 h = f.Get(bsl_hist)
274
275 for i in range(self.npix):
276 self.v_bsl[i] = h.GetBinContent(i+1)
277
278 f.Close()
279
280 def baseline_correct(self):
281 """ subtract baseline from the data
282
283 """
284
285 for pixel in range(self.npix):
286 self.acal_data[pixel,:] -= self.v_bsl[pixel]
287
288 def info(self):
289 """ print run information
290
291 """
292
293 print 'data file: ', data_file_name
294 print 'calib file: ', calib_file_name
295 print 'calibration file'
296 print 'N baseline_mean: ', self.Nblm
297 print 'N gain mean: ', self.Ngm
298 print 'N TriggeroffsetMean: ', self.Ntom
299
300# -----------------------------------------------------------------------------
301class fnames( object ):
302 """ organize file names of a FACT data run
303
304 """
305
306 def __init__(self, specifier = ['012', '023', '2011', '11', '24'],
307 rpath = '/scratch_nfs/res/bsl/',
308 zipped = True):
309 """
310 specifier : list of strings defined as:
311 [ 'DRS calibration file', 'Data file', 'YYYY', 'MM', 'DD']
312
313 rpath : directory path for the results; YYYYMMDD will be appended to rpath
314 zipped : use zipped (True) or unzipped (Data)
315
316 """
317
318 self.specifier = specifier
319 self.rpath = rpath
320 self.zipped = zipped
321
322 self.make( self.specifier, self.rpath, self.zipped )
323
324
325 def make( self, specifier, rpath, zipped ):
326 """ create (make) the filenames
327
328 names : dictionary of filenames, tags { 'data', 'drscal', 'results' }
329 data : name of the data file
330 drscal : name of the drs calibration file
331 results : radikal of file name(s) for results (to be completed by suffixes)
332 """
333
334 self.specifier = specifier
335
336 if zipped:
337 dpath = '/data00/fact-construction/raw/'
338 ext = '.fits.gz'
339 else:
340 dpath = '/data03/fact-construction/raw/'
341 ext = '.fits'
342
343 year = specifier[2]
344 month = specifier[3]
345 day = specifier[4]
346
347 yyyymmdd = year + month + day
348 dfile = specifier[1]
349 cfile = specifier[0]
350
351 rpath = rpath + yyyymmdd + '/'
352 self.rpath = rpath
353 self.names = {}
354
355 tmp = dpath + year + '/' + month + '/' + day + '/' + yyyymmdd + '_'
356 self.names['data'] = tmp + dfile + ext
357 self.names['drscal'] = tmp + cfile + '.drs' + ext
358 self.names['results'] = rpath + yyyymmdd + '_' + dfile + '_' + cfile
359
360 self.data = self.names['data']
361 self.drscal = self.names['drscal']
362 self.results = self.names['results']
363
364 def info( self ):
365 """ print complete filenames
366
367 """
368
369 print 'file names:'
370 print 'data: ', self.names['data']
371 print 'drs-cal: ', self.names['drscal']
372 print 'results: ', self.names['results']
373
374# end of class definition: fnames( object )
375
376def _test_iter():
377 """ test for function __iter__ """
378
379 data_file_name = '/data00/fact-construction/raw/2011/11/24/20111124_111.fits.gz'
380 calib_file_name = '/data00/fact-construction/raw/2011/11/24/20111124_111.drs.fits.gz'
381 run = RawData( data_file_name, calib_file_name )
382
383 for data, scell, tt in run:
384 print 'data[0,0] = ', data[0,0], "start_cell[0] =", scell[0], "trigger type = ", tt
385
386
387if __name__ == '__main__':
388 """ tests """
389
390 _test_iter()
Note: See TracBrowser for help on using the repository browser.