source: fact/tools/pyscripts/pyfact/pyfact.py@ 13329

Last change on this file since 13329 was 13329, checked in by neise, 13 years ago
added automodule support
  • Property svn:executable set to *
File size: 12.0 KB
Line 
1#!/usr/bin/python -tt
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('fits_h.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
30 def __init__(self, data_file_name, calib_file_name,
31 user_action_calib=lambda acal_data, data, blm, tom, gm, scells, nroi: None,
32 baseline_file_name='',
33 return_dict = None):
34 """ initialize object
35
36 open data file and calibration data file
37 get basic information about the data in data_file_name
38 allocate buffers for data access
39
40 data_file_name : fits or fits.gz file of the data including the path
41 calib_file_name : fits or fits.gz file containing DRS calibration data
42 baseline_file_name : npy file containing the baseline values
43 """
44 self.__module__='pyfact'
45 # manual implementation of default value, but I need to find out
46 # if the user of this class is aware of the new option
47 if return_dict == None:
48 print 'Warning: Rawdata.__init__() has a new option "return_dict"'
49 print 'the default value of this option is False, so nothing changes for you at the moment.'
50 print
51 print 'you probably want, to get a dictionary out of the next() method anyway'
52 print ' so please change your scripts and set this option to True, for the moment'
53 print 'e.g. like this: run = RawData(data_filename, calib_filename, return_dict = True)'
54 print "after a while, the default value, will turn to True .. so you don't have to give the option anymore"
55 print 'and some time later, the option will not be supported anymore'
56 return_dict = False
57
58 self.return_dict = return_dict
59
60 self.data_file_name = data_file_name
61 self.calib_file_name = calib_file_name
62 self.baseline_file_name = baseline_file_name
63
64 self.user_action_calib = user_action_calib
65
66 # baseline correction: True / False
67 if len(baseline_file_name) == 0:
68 self.correct_baseline = False
69 else:
70 self.correct_baseline = True
71
72 # access data file
73 try:
74 data_file = fits(self.data_file_name)
75 except IOError:
76 print 'problem accessing data file: ', data_file_name
77 raise # stop ! no data
78 #: data file (fits object)
79 self.data_file = data_file
80
81 # get basic information about the data file
82 #: region of interest (number of DRS slices read)
83 self.nroi = data_file.GetUInt('NROI')
84 #: number of pixels (should be 1440)
85 self.npix = data_file.GetUInt('NPIX')
86 #: number of events in the data run
87 self.nevents = data_file.GetNumRows()
88
89 # allocate the data memories
90 self.event_id = c_ulong()
91 self.trigger_type = c_ushort()
92 #: 1D array with raw data
93 self.data = np.zeros( self.npix * self.nroi, np.int16 )
94 #: slice where drs readout started
95 self.start_cells = np.zeros( self.npix, np.int16 )
96 #: time when the FAD was triggered, in some strange units...
97 self.board_times = np.zeros( 40, np.int32 )
98
99 # set the pointers to the data++
100 data_file.SetPtrAddress('EventNum', self.event_id)
101 data_file.SetPtrAddress('TriggerType', self.trigger_type)
102 data_file.SetPtrAddress('StartCellData', self.start_cells)
103 data_file.SetPtrAddress('Data', self.data)
104 data_file.SetPtrAddress('BoardTime', self.board_times)
105
106 # open the calibration file
107 try:
108 calib_file = fits(self.calib_file_name)
109 except IOError:
110 print 'problem accessing calibration file: ', calib_file_name
111 raise
112 #: drs calibration file
113 self.calib_file = calib_file
114
115 baseline_mean = calib_file.GetN('BaselineMean')
116 gain_mean = calib_file.GetN('GainMean')
117 trigger_offset_mean = calib_file.GetN('TriggerOffsetMean')
118
119 self.blm = np.zeros(baseline_mean, np.float32)
120 self.gm = np.zeros(gain_mean, np.float32)
121 self.tom = np.zeros(trigger_offset_mean, np.float32)
122
123 self.Nblm = baseline_mean / self.npix
124 self.Ngm = gain_mean / self.npix
125 self.Ntom = trigger_offset_mean / self.npix
126
127 calib_file.SetPtrAddress('BaselineMean', self.blm)
128 calib_file.SetPtrAddress('GainMean', self.gm)
129 calib_file.SetPtrAddress('TriggerOffsetMean', self.tom)
130 calib_file.GetRow(0)
131
132 self.v_bsl = np.zeros(self.npix) # array of baseline values (all ZERO)
133
134 def __iter__(self):
135 """ iterator """
136 return self
137
138 def __add__(self, jump_over):
139 self.data_file.GetRow(jump_over)
140 return self
141
142 def next(self):
143 """ used by __iter__ """
144
145 if self.data_file.GetNextRow() == False:
146 raise StopIteration
147 else:
148 self.calibrate_drs_amplitude()
149
150 #print 'nevents = ', self.nevents, 'event_id = ', self.event_id.value
151 if self.return_dict:
152 return self.__dict__
153 else:
154 return self.acal_data, self.start_cells, self.trigger_type.value
155
156 def next_event(self):
157 """ load the next event from disk and calibrate it
158
159 """
160
161 self.data_file.GetNextRow()
162 self.calibrate_drs_amplitude()
163
164 def calibrate_drs_amplitude(self):
165 """ perform the drs amplitude calibration of the event data
166
167 """
168
169 to_mV = 2000./4096.
170 #: 2D array with amplitude calibrated dat in mV
171 acal_data = self.data * to_mV # convert ADC counts to mV
172
173 # make 2D arrays: row = pixel, col = drs_slice
174 acal_data = np.reshape(acal_data, (self.npix, self.nroi) )
175 blm = np.reshape(self.blm, (self.npix, self.Nblm) )
176 tom = np.reshape(self.tom, (self.npix, self.Ntom) )
177 gm = np.reshape(self.gm, (self.npix, self.Ngm) )
178
179 for pixel in range( self.npix ):
180 # rotate the pixel baseline mean to the Data startCell
181 blm_pixel = np.roll( blm[pixel,:], -self.start_cells[pixel] )
182 # rotate the pixel gain mean to the Data startCell
183 gm_pixel = np.roll( gm[pixel,:], -self.start_cells[pixel] )
184 # the 'trigger offset mean' does not need to be rolled
185 # on the contrary, it seems there is an offset in the DRS data,
186 # which is related to its distance to the startCell, not to its
187 # distance to the beginning of the physical pipeline in the DRS chip
188 tom_pixel = tom[pixel,:]
189
190 acal_data[pixel,:] -= blm_pixel[0:self.nroi]
191 acal_data[pixel,:] -= tom_pixel[0:self.nroi]
192 acal_data[pixel,:] /= gm_pixel[0:self.nroi]
193
194 self.acal_data = acal_data * 1907.35
195
196 #print 'blm _pyfact', blm[0,0:20]
197 #t = np.roll( blm[0,:], -self.start_cells[0] )
198 #print 'blm _pyfact', t[0:20]
199 #print 'start_pyfact: ', self.start_cells[0]
200 #print 'acal _pyfact: ', self.acal_data[0,0:10]
201 #t = np.roll( gm[0,:], -self.start_cells[0] )
202 #print 'gm _pyfact: ', t[0:10]
203 self.user_action_calib( self.acal_data,
204 np.reshape(self.data, (self.npix, self.nroi) ), blm, tom, gm, self.start_cells, self.nroi)
205
206
207 def baseline_read_values(self, file, bsl_hist='bsl_sum/hplt_mean'):
208 """
209
210 open ROOT file with baseline histogram and read baseline values
211 file name of the root file
212 bsl_hist path to the histogram containing the basline values
213
214 """
215
216 try:
217 f = TFile(file)
218 except:
219 print 'Baseline data file could not be read: ', file
220 return
221
222 h = f.Get(bsl_hist)
223
224 for i in range(self.npix):
225 self.v_bsl[i] = h.GetBinContent(i+1)
226
227 f.Close()
228
229 def baseline_correct(self):
230 """ subtract baseline from the data
231
232 """
233
234 for pixel in range(self.npix):
235 self.acal_data[pixel,:] -= self.v_bsl[pixel]
236
237 def info(self):
238 """ print run information
239
240 """
241
242 print 'data file: ', data_file_name
243 print 'calib file: ', calib_file_name
244 print 'calibration file'
245 print 'N baseline_mean: ', self.Nblm
246 print 'N gain mean: ', self.Ngm
247 print 'N TriggeroffsetMean: ', self.Ntom
248
249# -----------------------------------------------------------------------------
250class fnames( object ):
251 """ organize file names of a FACT data run
252
253 """
254
255 def __init__(self, specifier = ['012', '023', '2011', '11', '24'],
256 rpath = '/scratch_nfs/res/bsl/',
257 zipped = True):
258 """
259 specifier : list of strings defined as:
260 [ 'DRS calibration file', 'Data file', 'YYYY', 'MM', 'DD']
261
262 rpath : directory path for the results; YYYYMMDD will be appended to rpath
263 zipped : use zipped (True) or unzipped (Data)
264
265 """
266
267 self.specifier = specifier
268 self.rpath = rpath
269 self.zipped = zipped
270
271 self.make( self.specifier, self.rpath, self.zipped )
272
273
274 def make( self, specifier, rpath, zipped ):
275 """ create (make) the filenames
276
277 names : dictionary of filenames, tags { 'data', 'drscal', 'results' }
278 data : name of the data file
279 drscal : name of the drs calibration file
280 results : radikal of file name(s) for results (to be completed by suffixes)
281 """
282
283 self.specifier = specifier
284
285 if zipped:
286 dpath = '/data00/fact-construction/raw/'
287 ext = '.fits.gz'
288 else:
289 dpath = '/data03/fact-construction/raw/'
290 ext = '.fits'
291
292 year = specifier[2]
293 month = specifier[3]
294 day = specifier[4]
295
296 yyyymmdd = year + month + day
297 dfile = specifier[1]
298 cfile = specifier[0]
299
300 rpath = rpath + yyyymmdd + '/'
301 self.rpath = rpath
302 self.names = {}
303
304 tmp = dpath + year + '/' + month + '/' + day + '/' + yyyymmdd + '_'
305 self.names['data'] = tmp + dfile + ext
306 self.names['drscal'] = tmp + cfile + '.drs' + ext
307 self.names['results'] = rpath + yyyymmdd + '_' + dfile + '_' + cfile
308
309 self.data = self.names['data']
310 self.drscal = self.names['drscal']
311 self.results = self.names['results']
312
313 def info( self ):
314 """ print complete filenames
315
316 """
317
318 print 'file names:'
319 print 'data: ', self.names['data']
320 print 'drs-cal: ', self.names['drscal']
321 print 'results: ', self.names['results']
322
323# end of class definition: fnames( object )
324
325def _test_iter( nevents ):
326 """ test for function __iter__ """
327
328 data_file_name = '/data00/fact-construction/raw/2011/11/24/20111124_117.fits.gz'
329 calib_file_name = '/data00/fact-construction/raw/2011/11/24/20111124_114.drs.fits.gz'
330# data_file_name = '/home/luster/win7/FACT/data/raw/20120114/20120114_028.fits.gz'
331# calib_file_name = '/home/luster/win7/FACT/data/raw/20120114/20120114_022.drs.fits.gz'
332 run = RawData( data_file_name, calib_file_name )
333
334 for data, scell, tt in run:
335 print 'ev ', run.event_id.value, 'data[0,0] = ', data[0,0], 'start_cell[0] = ', scell[0], 'trigger type = ', tt
336 if run.event_id.value == nevents:
337 break
338
339
340if __name__ == '__main__':
341 """ tests """
342
343 _test_iter(10)
Note: See TracBrowser for help on using the repository browser.