source: fact/tools/pyscripts/pyfact/extractor.py@ 13230

Last change on this file since 13230 was 13230, checked in by neise, 13 years ago
moved matplotlib import statement to __main__, so it is only imported, when needed
File size: 6.0 KB
Line 
1#!/usr/bin/python -tt
2#
3# Dominik Neise, Werner Lustermann
4# TU Dortmund, ETH Zurich
5#
6import numpy as np
7from generator import *
8from fir_filter import *
9
10class GlobalMaxFinder(object):
11 """ Pulse Extractor
12 Finds the global maximum in the given window.
13 (Best used with filtered data)
14 """
15
16 def __init__(self, min=30, max=250 , name = 'GlobalMaxFinder'):
17 """ initialize search Window
18
19 """
20 self.min = min
21 self.max = max
22 self.name = name
23
24 def __call__(self, data):
25 if data.ndim > 1:
26 time = np.argmax( data[ : , self.min:self.max ], 1)
27 amplitude = np.max( data[ : , self.min:self.max], 1)
28 else:
29 time = np.argmax( data[self.min:self.max])
30 amplitude = np.max( data[self.min:self.max])
31 return amplitude, time+self.min
32
33 def __str__(self):
34 s = self.name + '\n'
35 s += 'window:\n'
36 s += '(min,max) = (' + str(self.min) + ',' + str(self.max) + ')'
37 return s
38
39 def test(self):
40 pass
41
42
43class WindowIntegrator(object):
44 """ Integrates in a given intergration window around the given position
45 """
46
47 def __init__(self, min=13, max=23 , name = 'WindowIntegrator'):
48 """ initialize integration Window
49 """
50 self.min = min
51 self.max = max
52 self.name = name
53
54 def __call__(self, data, pos):
55 integral = np.empty( data.shape[0] )
56 for pixel in range( data.shape[0] ):
57 integral[pixel] = data[pixel, (pos[pixel]-self.min):(pos[pixel]+self.max)].sum()
58 return integral
59
60 def __str__(self):
61 s = self.name + '\n'
62 s += 'window:\n'
63 s += '(min,max) = (' + str(self.min) + ',' + str(self.max) + ')'
64 return s
65
66class FixedWindowIntegrator(object):
67 """ Integrates in a given intergration window
68 """
69
70 def __init__(self, min=55, max=105 , name = 'FixedWindowIntegrator'):
71 """ initialize integration Window
72 """
73 self.min = min
74 self.max = max
75 self.name = name
76
77 def __call__(self, data):
78 integral = np.empty( data.shape[0] )
79 for pixel in range( data.shape[0] ):
80 integral[pixel] = data[pixel, self.min:self.max].sum()
81 return integral
82
83 def __str__(self):
84 s = self.name + '\n'
85 s += 'window:\n'
86 s += '(min,max) = (' + str(self.min) + ',' + str(self.max) + ')'
87 return s
88
89class ZeroXing(object):
90 """ Finds zero crossings in given data
91 (should be used on CFD output for peak finding)
92 returns list of lists of time_of_zero_crossing
93 """
94 def __init__(self, slope=1, name = 'ZeroXing'):
95 if (slope >= 0):
96 self.slope = 1 # search for rising edge crossing
97 elif (slope < 0):
98 self.slope = -1 # search for falling edge crossing
99 self.name = name
100
101
102 def __call__(self, data):
103 all_hits = []
104 for pix_data in data:
105 hits = []
106 for i in range( data.shape[1]-1 ):
107 if ( self.slope > 0 ):
108 if ( pix_data[i] > 0 ):
109 continue
110 else:
111 if ( pix_data[i] < 0):
112 continue
113 if ( pix_data[i] * pix_data[i+1] <= 0 ):
114 # interpolate time of zero crossing with
115 # linear polynomial: y = ax + b
116 a = (pix_data[i+1] - pix_data[i]) / ((i+1) - i)
117 time = -1.0/a * pix_data[i] + i
118 hits.append(time)
119 all_hits.append(hits)
120 return all_hits
121
122 def __str__(self):
123 s = self.name + '\n'
124 if (self.slope == 1):
125 s += 'search for rising edge crossing.\n'
126 else:
127 s += 'search for falling edge crossing.\n'
128 return s
129
130
131
132def _test_GlobalMaxFinder():
133 gmf = GlobalMaxFinder(30,250)
134 print gmf
135 amplitude, time = gmf(event)
136 if abs(amplitude.mean() - 10) < 0.5:
137 print "Test 1: OK GlobalMaxFinder found amplitude correctly", amplitude.mean()
138 if abs(time.mean() - 65) < 2:
139 print "Test 1: OK GlobalMaxFinder found time correctly", time.mean()
140 else:
141 print "BAD: time mean:", time.mean()
142
143def _test_FixedWindowIntegrator():
144 fwi = FixedWindowIntegrator(50,200)
145 print fwi
146 integral = fwi(event)
147 #value of integral should be: 150*bsl + 8*10/2 + 100*10/2 = 465
148 if abs( integral.mean() - 465) < 2:
149 print "Test 2: OK FixedWindowIntegrator found integral correctly", integral.mean()
150 else:
151 print "Test 2: X FixedWindowIntegrator integral.mean failed:", integral.mean()
152
153def _test_ZeroXing():
154 cfd = CFD()
155 sa = SlidingAverage(8)
156 print sa
157 cfd_out = sa(event)
158 cfd_out = cfd(cfd_out )
159 cfd_out = sa(cfd_out)
160 zx = ZeroXing()
161 print zx
162 list_of_list_of_times = zx(cfd_out)
163 times = []
164 for list_of_times in list_of_list_of_times:
165 times.extend(list_of_times)
166 times = np.array(times)
167
168 hist,bins = np.histogram(times,3000,(0,300))
169 most_probable_time = np.argmax(hist)
170 print 'most probable time of zero-crossing', most_probable_time/10.
171 print 'this includes filter delays ... for average filter setting 8 this turns out to be 78.8 most of the time'
172
173if __name__ == '__main__':
174 import matplotlib.pyplot as plt
175 """ test the extractors """
176
177 # Generate a fake event, with a triangular pulse at slice 65
178 sg = SignalGenerator()
179 pulse_str = 'len 300 bsl -0.5 noise 0.5 triangle 65 10 8 100'
180 pulse = sg(pulse_str)
181 event = []
182 for i in range(1440):
183 event.append(sg(pulse_str))
184 event = np.array(event)
185 print 'test event with 1000 pixel generated, like this:'
186 print pulse_str
187 print
188
189 print '_test_GlobalMaxFinder()'
190 _test_GlobalMaxFinder()
191 print
192 print
193 print '_test_FixedWindowIntegrator()'
194 _test_FixedWindowIntegrator()
195 print
196 print
197 print '_test_ZeroXing()'
198 _test_ZeroXing()
199 print
Note: See TracBrowser for help on using the repository browser.