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

Last change on this file since 13632 was 13630, checked in by neise, 14 years ago
return_dict=True is now default
  • Property svn:executable set to *
File size: 31.2 KB
Line 
1#!/usr/bin/python -tt
2#
3# Werner Lustermann, Dominik Neise
4# ETH Zurich, TU Dortmund
5#
6from ctypes import *
7import numpy as np
8import pprint # for SlowData
9from scipy import signal
10
11# get the ROOT stuff + my shared libs
12from ROOT import gSystem
13# factfits_h.so is made from factfits.h and is used to access the data
14# make sure the location of factfits_h.so is in LD_LIBRARY_PATH.
15# having it in PYTHONPATH is *not* sufficient
16gSystem.Load('factfits_h.so')
17gSystem.Load('calfactfits_h.so')
18from ROOT import *
19
20class RawDataFeeder( object ):
21 """ Wrapper class for RawData class
22 capable of iterating over multiple RawData Files
23 """
24
25 def __init__(self, filelist):
26 """ *filelist* list of files to iterate over
27 the list should contain tuples, or sublists of two filenames
28 the first should be a data file (\*.fits.gz)
29 the second should be an amplitude calibration file(\*.drs.fits.gz)
30 """
31 # sanity check for input
32 if type(filelist) != type(list()):
33 raise TypeError('filelist should be a list')
34 for entry in filelist:
35 if len(entry) != 2:
36 raise TypeError('the entries of filelist should have length == 2')
37 for path in entry:
38 if type(path) != type(str()):
39 raise TypeError('the entries of filelist should be path, i.e. of type str()')
40 #todo check if 'path' is a valid path
41 # else: throw an Exception, or Warning?
42
43 self.filelist = filelist
44 self._current_RawData = RawData(filelist[0][0], filelist[0][1], return_dict=True)
45 del filelist[0]
46
47 def __iter__(self):
48 return self
49
50 def next():
51 """ Method being called by the iterator.
52 Since the RawData Objects are simply looped over, the event_id from the
53 RawData object will not be unique.
54 Each RawData obejct will start with event_id = 1 as usual.
55 """
56 try:
57 return self._current_RawData.next()
58 except StopIteration:
59 # current_RawData was completely processed
60 # delete it (I hope this calls the destructor of the fits file and/or closes it)
61 del self._current_RawData
62 # and remake it, if possible
63 if len(self.filelist) > 0:
64 self._current_RawData = RawData(filelist[0][0], filelist[0][1], return_dict=True)
65 del filelist[0]
66 else:
67 raise
68
69
70
71class RawData( object ):
72 """ raw data access and calibration
73
74 - open raw data file and drs calibration file
75 - performs amplitude calibration
76 - performs baseline substraction if wanted
77 - provides all data in an array:
78 row = number of pixel
79 col = length of region of interest
80
81 """
82
83
84 def __init__(self, data_file_name, calib_file_name,
85 user_action_calib=lambda acal_data, data, blm, tom, gm, scells, nroi: None,
86 baseline_file_name='',
87 return_dict = True,
88 do_calibration = True,
89 use_CalFactFits = True):
90 """ initialize object
91
92 open data file and calibration data file
93 get basic information about the data in data_file_name
94 allocate buffers for data access
95
96 data_file_name : fits or fits.gz file of the data including the path
97 calib_file_name : fits or fits.gz file containing DRS calibration data
98 baseline_file_name : npy file containing the baseline values
99 """
100 self.__module__='pyfact'
101 # manual implementation of default value, but I need to find out
102 # if the user of this class is aware of the new option
103 if return_dict == False:
104 print 'DEPRECATION WARNING:'
105 print 'you are using RawData in a way, which is nor supported anymore.'
106 print ' Please set: return_dict = True, in the __init__ call'
107 self.return_dict = return_dict
108 self.use_CalFactFits = use_CalFactFits
109
110 self.do_calibration = do_calibration
111
112 self.data_file_name = data_file_name
113 self.calib_file_name = calib_file_name
114 self.baseline_file_name = baseline_file_name
115
116 self.user_action_calib = user_action_calib
117
118 # baseline correction: True / False
119 if len(baseline_file_name) == 0:
120 self.correct_baseline = False
121 else:
122 self.correct_baseline = True
123
124 # access data file
125 if use_CalFactFits:
126 try:
127 data_file = CalFactFits(data_file_name, calib_file_name)
128 except IOError:
129 print 'problem accessing data file: ', data_file_name
130 raise # stop ! no data
131
132 self.data_file = data_file
133 self.data = np.empty( data_file.npix * data_file.nroi, np.float64)
134 data_file.SetNpcaldataPtr(self.data)
135 self.data = self.data.reshape( data_file.npix, data_file.nroi )
136 self.acal_data = self.data
137
138 self.nroi = data_file.nroi
139 self.npix = data_file.npix
140 self.nevents = data_file.nevents
141
142 # Data per event
143 self.event_id = None
144 self.trigger_type = None
145 self.start_cells = None
146 self.board_times = None
147
148 else:
149 try:
150 data_file = FactFits(self.data_file_name)
151 except IOError:
152 print 'problem accessing data file: ', data_file_name
153 raise # stop ! no data
154
155 self.data_file = data_file
156
157 # get basic information about the data file
158 #: region of interest (number of DRS slices read)
159 self.nroi = data_file.GetUInt('NROI')
160 #: number of pixels (should be 1440)
161 self.npix = data_file.GetUInt('NPIX')
162 #: number of events in the data run
163 self.nevents = data_file.GetNumRows()
164
165 # allocate the data memories
166 self.event_id = c_ulong()
167 self.trigger_type = c_ushort()
168 #: 1D array with raw data
169 self.data = np.zeros( self.npix * self.nroi, np.int16 ).reshape(self.npix ,self.nroi)
170 #: slice where drs readout started
171 self.start_cells = np.zeros( self.npix, np.int16 )
172 #: time when the FAD was triggered, in some strange units...
173 self.board_times = np.zeros( 40, np.int32 )
174
175 # set the pointers to the data++
176 data_file.SetPtrAddress('EventNum', self.event_id)
177 data_file.SetPtrAddress('TriggerType', self.trigger_type)
178 data_file.SetPtrAddress('StartCellData', self.start_cells)
179 data_file.SetPtrAddress('Data', self.data)
180 data_file.SetPtrAddress('BoardTime', self.board_times)
181
182 # open the calibration file
183 try:
184 calib_file = FactFits(self.calib_file_name)
185 except IOError:
186 print 'problem accessing calibration file: ', calib_file_name
187 raise
188 #: drs calibration file
189 self.calib_file = calib_file
190
191 baseline_mean = calib_file.GetN('BaselineMean')
192 gain_mean = calib_file.GetN('GainMean')
193 trigger_offset_mean = calib_file.GetN('TriggerOffsetMean')
194
195 self.Nblm = baseline_mean / self.npix
196 self.Ngm = gain_mean / self.npix
197 self.Ntom = trigger_offset_mean / self.npix
198
199 self.blm = np.zeros(baseline_mean, np.float32).reshape(self.npix , self.Nblm)
200 self.gm = np.zeros(gain_mean, np.float32).reshape(self.npix , self.Ngm)
201 self.tom = np.zeros(trigger_offset_mean, np.float32).reshape(self.npix , self.Ntom)
202
203 calib_file.SetPtrAddress('BaselineMean', self.blm)
204 calib_file.SetPtrAddress('GainMean', self.gm)
205 calib_file.SetPtrAddress('TriggerOffsetMean', self.tom)
206 calib_file.GetRow(0)
207
208 # make calibration constants double, so we never need to roll
209 self.blm = np.hstack((self.blm, self.blm))
210 self.gm = np.hstack((self.gm, self.gm))
211 self.tom = np.hstack((self.tom, self.tom))
212
213 self.v_bsl = np.zeros(self.npix) # array of baseline values (all ZERO)
214
215 def __iter__(self):
216 """ iterator """
217 return self
218
219 def next(self):
220 """ used by __iter__ """
221 if self.use_CalFactFits:
222 if self.data_file.GetCalEvent() == False:
223 raise StopIteration
224 else:
225 self.event_id = self.data_file.event_id
226 self.trigger_type = self.data_file.event_triggertype
227 self.start_cells = self.data_file.event_offset
228 self.board_times = self.data_file.event_boardtimes
229 #self.acal_data = self.data.copy().reshape(self.data_file.npix, self.data_file.nroi)
230 else:
231 if self.data_file.GetNextRow() == False:
232 raise StopIteration
233 else:
234 if self.do_calibration == True:
235 self.calibrate_drs_amplitude()
236
237 #print 'nevents = ', self.nevents, 'event_id = ', self.event_id.value
238 if self.return_dict:
239 return self.__dict__
240 else:
241 return self.acal_data, self.start_cells, self.trigger_type.value
242
243 def next_event(self):
244 """ load the next event from disk and calibrate it
245 """
246 if self.use_CalFactFits:
247 self.data_file.GetCalEvent()
248 else:
249 self.data_file.GetNextRow()
250 self.calibrate_drs_amplitude()
251
252 def calibrate_drs_amplitude(self):
253 """ perform the drs amplitude calibration of the event data
254
255 """
256 # shortcuts
257 blm = self.blm
258 gm = self.gm
259 tom = self.tom
260
261 to_mV = 2000./4096.
262 #: 2D array with amplitude calibrated dat in mV
263 acal_data = self.data * to_mV # convert ADC counts to mV
264
265
266 for pixel in range( self.npix ):
267 #shortcuts
268 sc = self.start_cells[pixel]
269 roi = self.nroi
270 # rotate the pixel baseline mean to the Data startCell
271 acal_data[pixel,:] -= blm[pixel,sc:sc+roi]
272 # the 'trigger offset mean' does not need to be rolled
273 # on the contrary, it seems there is an offset in the DRS data,
274 # which is related to its distance to the startCell, not to its
275 # distance to the beginning of the physical pipeline in the DRS chip
276 acal_data[pixel,:] -= tom[pixel,0:roi]
277 # rotate the pixel gain mean to the Data startCell
278 acal_data[pixel,:] /= gm[pixel,sc:sc+roi]
279
280
281 self.acal_data = acal_data * 1907.35
282
283 self.user_action_calib( self.acal_data,
284 np.reshape(self.data, (self.npix, self.nroi) ), blm, tom, gm, self.start_cells, self.nroi)
285
286
287 def baseline_read_values(self, file, bsl_hist='bsl_sum/hplt_mean'):
288 """
289
290 open ROOT file with baseline histogram and read baseline values
291 file name of the root file
292 bsl_hist path to the histogram containing the basline values
293
294 """
295
296 try:
297 f = TFile(file)
298 except:
299 print 'Baseline data file could not be read: ', file
300 return
301
302 h = f.Get(bsl_hist)
303
304 for i in range(self.npix):
305 self.v_bsl[i] = h.GetBinContent(i+1)
306
307 f.Close()
308
309 def baseline_correct(self):
310 """ subtract baseline from the data
311
312 """
313
314 for pixel in range(self.npix):
315 self.acal_data[pixel,:] -= self.v_bsl[pixel]
316
317 def info(self):
318 """ print run information
319
320 """
321
322 print 'data file: ', data_file_name
323 print 'calib file: ', calib_file_name
324 print 'calibration file'
325 print 'N baseline_mean: ', self.Nblm
326 print 'N gain mean: ', self.Ngm
327 print 'N TriggeroffsetMean: ', self.Ntom
328
329# -----------------------------------------------------------------------------
330class RawDataFake( object ):
331 """ raw data FAKE access similar to real RawData access
332 """
333
334
335 def __init__(self, data_file_name, calib_file_name,
336 user_action_calib=lambda acal_data, data, blm, tom, gm, scells, nroi: None,
337 baseline_file_name=''):
338 self.__module__='pyfact'
339
340 self.nroi = 300
341 self.npix = 9
342 self.nevents = 1000
343
344 self.simulator = None
345
346 self.time = np.ones(1024) * 0.5
347
348
349 self.event_id = c_ulong(0)
350 self.trigger_type = c_ushort(4)
351 self.data = np.zeros( self.npix * self.nroi, np.int16 ).reshape(self.npix ,self.nroi)
352 self.start_cells = np.zeros( self.npix, np.int16 )
353 self.board_times = np.zeros( 40, np.int32 )
354 def __iter__(self):
355 """ iterator """
356 return self
357
358 def next(self):
359 """ used by __iter__ """
360 self.event_id = c_ulong(self.event_id.value + 1)
361 self.board_times = self.board_times + 42
362
363 if self.event_id.value >= self.nevents:
364 raise StopIteration
365 else:
366 self._make_event_data()
367
368 return self.__dict__
369
370 def _make_event_data(self):
371 sample_times = self.time.cumsum() - time[0]
372
373 # random start cell
374 self.start_cells = np.ones( self.npix, np.int16 ) * np.random.randint(0,1024)
375
376 starttime = self.start_cells[0]
377
378 signal = self._std_sinus_simu(sample_times, starttime)
379
380 data = np.vstack( (signal,signal) )
381 for i in range(8):
382 data = np.vstack( (data,signal) )
383
384 self.data = data
385
386 def _std_sinus_simu(self, times, starttime):
387 period = 10 # in ns
388
389 # give a jitter on starttime
390 starttime = np.random.normal(startime, 0.05)
391
392 phase = 0.0
393 signal = 10 * np.sin(times * 2*np.pi/period + starttime + phase)
394
395 # add some noise
396 noise = np.random.normal(0.0, 0.5, signal.shape)
397 signal += noise
398 return signal
399
400 def info(self):
401 """ print run information
402
403 """
404
405 print 'data file: ', data_file_name
406 print 'calib file: ', calib_file_name
407 print 'calibration file'
408 print 'N baseline_mean: ', self.Nblm
409 print 'N gain mean: ', self.Ngm
410 print 'N TriggeroffsetMean: ', self.Ntom
411
412# -----------------------------------------------------------------------------
413
414class SlowData( FactFits ):
415 """ -Fact SlowData File-
416 A Python wrapper for the fits-class implemented in pyfits.h
417 provides easy access to the fits file meta data.
418 * dictionary of file metadata - self.meta
419 * dict of table metadata - self.columns
420 * variable table column access, thus possibly increased speed while looping
421 """
422 def __init__(self, path):
423 """ creates meta and columns dictionaries
424 """
425 self.path = path
426 try:
427 FactFits.__init__(self,path)
428 except IOError:
429 print 'problem accessing data file: ', data_file_name
430 raise # stop ! no data
431
432 self.meta = self._make_meta_dict()
433 self.columns = self._make_columns_dict()
434
435 self.treat_meta_dict()
436
437
438 # list of columns, which are already registered
439 # see method register()
440 self._registered_cols = []
441 # dict of column data, this is used, in order to be able to remove
442 # the ctypes of
443 self._table_cols = {}
444
445 # I need to count the rows, since the normal loop mechanism seems not to work.
446 self._current_row = 0
447
448 self.stacked_cols = {}
449
450 def _make_meta_dict(self):
451 """ This method retrieves meta information about the fits file and
452 stores this information in a dict
453 return: dict
454 key: string - all capital letters
455 value: tuple( numerical value, string comment)
456 """
457 # intermediate variables for file metadata dict generation
458 keys=self.GetPy_KeyKeys()
459 values=self.GetPy_KeyValues()
460 comments=self.GetPy_KeyComments()
461 types=self.GetPy_KeyTypes()
462
463 if len(keys) != len(values):
464 raise TypeError('len(keys)',len(keys),' != len(values)', len(values))
465 if len(keys) != len(types):
466 raise TypeError('len(keys)',len(keys),' != len(types)', len(types))
467 if len(keys) != len(comments):
468 raise TypeError('len(keys)',len(keys),' != len(comments)', len(comments))
469
470 meta_dict = {}
471 for i in range(len(keys)):
472 type = types[i]
473 if type == 'I':
474 value = int(values[i])
475 elif type == 'F':
476 value = float(values[i])
477 elif type == 'B':
478 if values[i] == 'T':
479 value = True
480 elif values[i] == 'F':
481 value = False
482 else:
483 raise TypeError("meta-type is 'B', but meta-value is neither 'T' nor 'F'. meta-value:",values[i])
484 elif type == 'T':
485 value = values[i]
486 else:
487 raise TypeError("unknown meta-type: known meta types are: I,F,B and T. meta-type:",type)
488 meta_dict[keys[i]]=(value, comments[i])
489 return meta_dict
490
491
492 def _make_columns_dict(self):
493 """ This method retrieves information about the columns
494 stored inside the fits files internal binary table.
495 returns: dict
496 key: string column name -- all capital letters
497 values: tuple(
498 number of elements in table field - integer
499 size of element in bytes -- this is not really interesting for any user
500 might be ommited in future versions
501 type - a single character code -- should be translated into
502 a comrehensible word
503 unit - string like 'mV' or 'ADC count'
504 """
505 # intermediate variables for file table-metadata dict generation
506 keys=self.GetPy_ColumnKeys()
507 #offsets=self.GetPy_ColumnOffsets() #not needed on python level...
508 nums=self.GetPy_ColumnNums()
509 sizes=self.GetPy_ColumnSizes()
510 types=self.GetPy_ColumnTypes()
511 units=self.GetPy_ColumnUnits()
512
513 # zip the values
514 values = zip(nums,sizes,types,units)
515 # create the columns dictionary
516 columns = dict(zip(keys ,values))
517 return columns
518
519 def stack(self, on=True):
520 self.next()
521 for col in self._registered_cols:
522 if isinstance( self.dict[col], type(np.array('')) ):
523 self.stacked_cols[col] = self.dict[col]
524 else:
525# elif isinstance(self.dict[col], ctypes._SimpleCData):
526 self.stacked_cols[col] = np.array(self.dict[col])
527# else:
528# raise TypeError("I don't know how to stack "+col+". It is of type: "+str(type(self.dict[col])))
529
530 def register(self, input_str):
531 columns = self.columns
532 if input_str.lower() == 'all':
533 for col in columns:
534 self._register(col)
535 else:
536 #check if colname is in columns:
537 if input_str not in columns:
538 error_msg = 'colname:'+ input_str +' is not a column in the binary table.\n'
539 error_msg+= 'possible colnames are\n'
540 for key in columns:
541 error_msg += key+'\n'
542 raise KeyError(error_msg)
543 else:
544 self._register(input_str)
545
546 # 'private' method, do not use
547 def _register( self, colname):
548 columns = self.columns
549 local = None
550
551 number_of_elements = int(columns[colname][0])
552 size_of_elements_in_bytes = int(columns[colname][1])
553 ctypecode_of_elements = columns[colname][2]
554 physical_unit_of_elements = columns[colname][3]
555
556 # snippet from the C++ source code, or header file to be precise:
557 #case 'L': gLog << "bool(8)"; break;
558 #case 'B': gLog << "byte(8)"; break;
559 #case 'I': gLog << "short(16)"; break;
560 #case 'J': gLog << "int(32)"; break;
561 #case 'K': gLog << "int(64)"; break;
562 #case 'E': gLog << "float(32)"; break;
563 #case 'D': gLog << "double(64)"; break;
564
565
566
567 # the fields inside the columns can either contain single numbers,
568 # or whole arrays of numbers as well.
569 # we treat single elements differently...
570 if number_of_elements == 1:
571 # allocate some memory for a single number according to its type
572 if ctypecode_of_elements == 'J': # J is for a 4byte int, i.e. an unsigned long
573 local = ctypes.c_ulong()
574 un_c_type = long
575 elif ctypecode_of_elements == 'I': # I is for a 2byte int, i.e. an unsinged int
576 local = ctypes.c_ushort()
577 un_c_type = int
578 elif ctypecode_of_elements == 'B': # B is for a byte
579 local = ctypes.c_ubyte()
580 un_c_type = int
581 elif ctypecode_of_elements == 'D':
582 local = ctypes.c_double()
583 un_c_type = float
584 elif ctypecode_of_elements == 'E':
585 local = ctypes.c_float()
586 un_c_type = float
587 elif ctypecode_of_elements == 'A':
588 local = ctypes.c_uchar()
589 un_c_type = chr
590 elif ctypecode_of_elements == 'K':
591 local = ctypes.c_ulonglong()
592 un_c_type = long
593 else:
594 raise TypeError('unknown ctypecode_of_elements:',ctypecode_of_elements)
595 else:
596 if ctypecode_of_elements == 'B': # B is for a byte
597 nptype = np.int8
598 elif ctypecode_of_elements == 'A': # A is for a char .. but I don't know how to handle it
599 nptype = np.int8
600 elif ctypecode_of_elements == 'I': # I is for a 2byte int
601 nptype = np.int16
602 elif ctypecode_of_elements == 'J': # J is for a 4byte int
603 nptype = np.int32
604 elif ctypecode_of_elements == 'K': # B is for a byte
605 nptype = np.int64
606 elif ctypecode_of_elements == 'E': # B is for a byte
607 nptype = np.float32
608 elif ctypecode_of_elements == 'D': # B is for a byte
609 nptype = np.float64
610 else:
611 raise TypeError('unknown ctypecode_of_elements:',ctypecode_of_elements)
612 local = np.zeros( number_of_elements, nptype)
613
614 # Set the Pointer Address
615 self.SetPtrAddress(colname, local)
616 self._table_cols[colname] = local
617 if number_of_elements > 1:
618 self.__dict__[colname] = local
619 self.dict[colname] = local
620 else:
621 # remove any traces of ctypes:
622 self.__dict__[colname] = local.value
623 self.dict[colname] = local.value
624 self._registered_cols.append(colname)
625
626
627 def treat_meta_dict(self):
628 """make 'interesting' meta information available like normal members.
629 non interesting are:
630 TFORM, TUNIT, and TTYPE
631 since these are available via the columns dict.
632 """
633
634 self.number_of_rows = self.meta['NAXIS2'][0]
635 self.number_of_columns = self.meta['TFIELDS'][0]
636
637 # there are some information in the meta dict, which are alsways there:
638 # there are regarded as not interesting:
639 uninteresting_meta = {}
640 uninteresting_meta['arraylike'] = {}
641 uninteresting = ['NAXIS', 'NAXIS1', 'NAXIS2',
642 'TFIELDS',
643 'XTENSION','EXTNAME','EXTREL',
644 'BITPIX', 'PCOUNT', 'GCOUNT',
645 'ORIGIN',
646 'PACKAGE', 'COMPILED', 'CREATOR',
647 'TELESCOP','TIMESYS','TIMEUNIT','VERSION']
648 for key in uninteresting:
649 if key in self.meta:
650 uninteresting_meta[key]=self.meta[key]
651 del self.meta[key]
652
653 # the table meta data contains
654
655
656 # shortcut to access the meta dict. But this needs to
657 # be cleaned up quickly!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
658 meta = self.meta
659
660 # loop over keys:
661 # * try to find array-like keys
662 arraylike = {}
663 singlelike = []
664 for key in self.meta:
665 stripped = key.rstrip('1234567890')
666 if stripped == key:
667 singlelike.append(key)
668 else:
669 if stripped not in arraylike:
670 arraylike[stripped] = 0
671 else:
672 arraylike[stripped] += 1
673 newmeta = {}
674 for key in singlelike:
675 newmeta[key.lower()] = meta[key]
676 for key in arraylike:
677 uninteresting_meta['arraylike'][key.lower()] = []
678 for i in range(arraylike[key]+1):
679 if key+str(i) in meta:
680 uninteresting_meta['arraylike'][key.lower()].append(meta[key+str(i)])
681 self.ui_meta = uninteresting_meta
682 # make newmeta self
683 for key in newmeta:
684 self.__dict__[key]=newmeta[key]
685
686 dict = self.__dict__.copy()
687 del dict['meta']
688 del dict['ui_meta']
689 self.dict = dict
690
691 def __iter__(self):
692 """ iterator """
693 return self
694
695 def next(self):
696 """ used by __iter__ """
697 # Here one might check, if looping makes any sense, and if not
698 # one could stop looping or so...
699 # like this:
700 #
701 # if len(self._registered_cols) == 0:
702 # print 'warning: looping without any registered columns'
703 if self._current_row < self.number_of_rows:
704 if self.GetNextRow() == False:
705 raise StopIteration
706 for col in self._registered_cols:
707 if isinstance(self._table_cols[col], ctypes._SimpleCData):
708 self.__dict__[col] = self._table_cols[col].value
709 self.dict[col] = self._table_cols[col].value
710
711 for col in self.stacked_cols:
712 if isinstance(self.dict[col], type(np.array(''))):
713 self.stacked_cols[col] = np.vstack( (self.stacked_cols[col],self.dict[col]) )
714 else:
715 self.stacked_cols[col] = np.vstack( (self.stacked_cols[col],np.array(self.dict[col])) )
716 self._current_row += 1
717 else:
718 raise StopIteration
719 return self
720
721 def show(self):
722 pprint.pprint(self.dict)
723
724
725
726
727class fnames( object ):
728 """ organize file names of a FACT data run
729
730 """
731
732 def __init__(self, specifier = ['012', '023', '2011', '11', '24'],
733 rpath = '/scratch_nfs/res/bsl/',
734 zipped = True):
735 """
736 specifier : list of strings defined as:
737 [ 'DRS calibration file', 'Data file', 'YYYY', 'MM', 'DD']
738
739 rpath : directory path for the results; YYYYMMDD will be appended to rpath
740 zipped : use zipped (True) or unzipped (Data)
741
742 """
743
744 self.specifier = specifier
745 self.rpath = rpath
746 self.zipped = zipped
747
748 self.make( self.specifier, self.rpath, self.zipped )
749
750
751 def make( self, specifier, rpath, zipped ):
752 """ create (make) the filenames
753
754 names : dictionary of filenames, tags { 'data', 'drscal', 'results' }
755 data : name of the data file
756 drscal : name of the drs calibration file
757 results : radikal of file name(s) for results (to be completed by suffixes)
758 """
759
760 self.specifier = specifier
761
762 if zipped:
763 dpath = '/data00/fact-construction/raw/'
764 ext = '.fits.gz'
765 else:
766 dpath = '/data03/fact-construction/raw/'
767 ext = '.fits'
768
769 year = specifier[2]
770 month = specifier[3]
771 day = specifier[4]
772
773 yyyymmdd = year + month + day
774 dfile = specifier[1]
775 cfile = specifier[0]
776
777 rpath = rpath + yyyymmdd + '/'
778 self.rpath = rpath
779 self.names = {}
780
781 tmp = dpath + year + '/' + month + '/' + day + '/' + yyyymmdd + '_'
782 self.names['data'] = tmp + dfile + ext
783 self.names['drscal'] = tmp + cfile + '.drs' + ext
784 self.names['results'] = rpath + yyyymmdd + '_' + dfile + '_' + cfile
785
786 self.data = self.names['data']
787 self.drscal = self.names['drscal']
788 self.results = self.names['results']
789
790 def info( self ):
791 """ print complete filenames
792
793 """
794
795 print 'file names:'
796 print 'data: ', self.names['data']
797 print 'drs-cal: ', self.names['drscal']
798 print 'results: ', self.names['results']
799
800# end of class definition: fnames( object )
801
802def _test_SlowData( filename ):
803 print '-'*70
804 print "opened :", filename, " as 'file'"
805 print
806 print '-'*70
807 print 'type file.show() to look at its contents'
808 print "type file.register( columnname ) or file.register('all') in order to register columns"
809 print
810 print " due column-registration you declare, that you would like to retrieve the contents of one of the columns"
811 print " after column-registration, the 'file' has new member variables, they are named like the columns"
812 print " PLEASE NOTE: immediatly after registration, the members exist, but they are empty."
813 print " the values are assigned only, when you call file.next() or when you loop over the 'file'"
814 print
815 print "in order to loop over it, just go like this:"
816 print "for row in file:"
817 print " print row.columnname_one, row.columnname_two"
818 print
819 print ""
820 print '-'*70
821
822
823
824def _test_iter( nevents ):
825 """ test for function __iter__ """
826
827 data_file_name = '/data00/fact-construction/raw/2011/11/24/20111124_117.fits.gz'
828 calib_file_name = '/data00/fact-construction/raw/2011/11/24/20111124_114.drs.fits.gz'
829# data_file_name = '/home/luster/win7/FACT/data/raw/20120114/20120114_028.fits.gz'
830# calib_file_name = '/home/luster/win7/FACT/data/raw/20120114/20120114_022.drs.fits.gz'
831 run = RawData( data_file_name, calib_file_name , return_dict=True)
832
833 for event in run:
834 print 'ev ', event['event_id'], 'data[0,0] = ', event['acal_data'][0,0], 'start_cell[0] = ', event['start_cells'][0], 'trigger type = ', event['trigger_type']
835 if run.event_id == nevents:
836 break
837
838if __name__ == '__main__':
839 """ tests """
840 import sys
841 if len(sys.argv) == 1:
842 print 'showing test of iterator of RawData class'
843 print 'in order to test the SlowData classe please use:', sys.argv[0], 'fits-file-name'
844 _test_iter(10)
845
846
847 else:
848 print 'showing test of SlowData class'
849 print 'in case you wanted to test the RawData class, please give no commandline arguments'
850 file = SlowData(sys.argv[1])
851 _test_SlowData(sys.argv[1])
Note: See TracBrowser for help on using the repository browser.