7 The module contains basic functions for generation and analysis of SVD strip data.
9 :author: Peter Kvasnicka
12 This is a set of utility functions and constant declarations for simulation of SVD strip data
13 to use in training timing networks or for other purposes. These include wave functions (gamma,
14 cubic polynomial and beta-prime).
17 Just import the module to use it.
23 from scipy.stats
import norm, uniform
31 def wexp(t, tau=wexp_default_tau):
34 wexp(t, tau) = t/tau * exp(1-t/tau) if t > 0 else 0,
35 normalized to peak value 1.
36 t - nummpy vector of times
37 tau - (scalar) waveform decay time
38 return: numpy vector of wexp(t, tau) values at times t
41 return np.clip(z * np.exp(1.0 - z), 0.0, 100.0)
47 def w3(t, tau=w3_default_tau):
49 w3(t, tau) = 27/4 * t/tau * (1-t/tau)**2 if 0 < t < tau else 0,
50 normalized to peak value 1.
51 t - numpy vector of times
52 tau - (scalar) width of the distribution
53 return - numpy vector of w3(t,tau) values at times t
55 z = np.clip(t / tau, 0, 1)
56 return 27 / 4 * z * (z - 1) * (z - 1)
62 def betaprime_wave(t, tau=bp_default_tau):
63 ''' Beta-prime waveform
64 betaprime_wave(t, tau) = 149.012 * (t/tau)**2 * (1 + t/tau)**10 if t > 0 else 0
65 t - numpy vector of times
66 tau - (scalar) width of the distribution
67 return - numpy vector of betaprime_wave values of betaprime_wave at times t
69 z = np.clip(t / tau, 0, 1000)
70 return 149.012 * z**2 / (1 + z)**10
73 def test3(s, threshold):
74 '''Test for 3 consecutive non-zero APV samples
75 A six-tuple of APV25 samples is only accepted if it has 3 consecutive samples over threshold.
77 return - True if there are 3 consecutive samples over threshold, otherwise False.
79 cons_before = np.zeros(len(s))
81 cons_before[i:] += (s > threshold)[0:6 - i]
82 return np.max(cons_before) >= 3
86 This is the list of all configurations of over-the-threhsold samples that pass the 3-over-the-threshold-samples test.
112 def gen_signal(ampl, t0, tau, sigma=1, w=betaprime_wave, tau_sigma=0.0):
113 '''Generate random sample of 6 APV signals, properly censored.
114 The produced data are normalized to sigma = 1 and the given amplitude.
116 - real_amplitude = sigma * amlitude
117 - generate waveform, add noise, and convert to integer values
118 - divide signals by sigma
119 For large amplitudes, the function adds gaussian noise to generated waveform.
120 For amplitudes around and below the threshold, the function randomly selects a
121 subset of samples over threshold and generates over-threhold noises from left-censored
122 gaussian distributions.
125 tau - decay time or width of the waveform
126 sigma - nosie (default 1: we work with S/N rather than raw signals)
127 tau_sigma - width of tau jitter
130 gen_amplitude = sigma * ampl
132 gen_thr = int(sigma * threshold_cut + 1.0 - 1.0e-9) - 0.5
136 tau += np.random.randn() * tau_sigma
137 res0 = gen_amplitude * w(np.linspace(-dt - t0, 4 * dt - t0, 6, endpoint=
True), tau)
138 if test3(res0, threshold_cut * sigma):
139 res = (res0 + sigma * np.random.randn(6) + 0.5).astype(int)
141 while not test3(res, threshold_cut * sigma):
142 res = (res0 + sigma * np.random.randn(6) + 0.5).astype(int)
143 res[res < threshold_cut * sigma] = 0
146 p_over = 1.0 - norm.cdf((gen_thr - res0) / sigma)
148 pconfs = np.array([np.prod(p_over[conf])
for conf
in residual_configs])
149 pconfs /= np.sum(pconfs)
150 cconfs = np.cumsum(pconfs)
152 u_conf = uniform.rvs()
154 while u_conf > cconfs[i_conf]:
156 u_res = uniform.rvs(0, 1, len(residual_configs[i_conf]))
158 res[residual_configs[i_conf]] = res0[residual_configs[i_conf]] + \
159 sigma * norm.ppf(1 - u_res * p_over[residual_configs[i_conf]])
160 res = (res + 0.5).astype(int)
169 A simple class to encode and decode tau values for network training
170 based on amplitude and tau ranges.
177 self.amp_min, self.
amp_max = amp_range
178 self.tau_min, self.
tau_max = tau_range
183 encoder of tau values for network training
185 return (self.amp_min + self.
at_ratio * (tau - self.tau_min))
189 decoder of tau values for network training
191 return (self.tau_min + 1.0 / self.
at_ratio * (etau - self.amp_min))
196 This class generates a Pandas dataframe with a random sample of SVD strip signals with specified size and parameters.
198 1. We generate time bins from quantiles, do we want a regular grid?
199 2. Have to think of possible irregular grid.
202 def __init__(self, t0_bounds, tau_bounds, amplitude_bounds, sigma_bounds, tau_sigma, bin_size, wf=betaprime_wave):
204 The constructor takes the following parameters:
205 t0_bounds is a tuple, (t0_min, t0_max)
206 tau_bounds is a tuple (tau_min, tau_max)
207 amplitude_bounds is a tuple (amp_min, amp_max)
208 sigma_bounds is a tuple (sigma_min, sigma_max)
209 bin_size is the % fraction of t0_min, t0_max interval corresponding to a single output t0 bin.
212 self.t0_min, self.
t0_max = t0_bounds
214 self.amp_min, self.
amp_max = amplitude_bounds
215 self.sigma_min, self.
sigma_max = sigma_bounds
223 Get t0 bounds of sampling space
225 return (self.t0_min, self.
t0_max)
229 Get amplitude bounds of sampling space
231 return (self.amp_min, self.
amp_max)
235 Get tau bounds of sampling space
241 Set width limits for the simulation.
248 Set width jitter for the simulation.
254 Get width jitter for the simulation.
266 Generate sample_size samples.
270 'test': np.random.uniform(size=self.
n_samples),
271 't0': np.random.uniform(self.t0_min, self.
t0_max, size=self.
n_samples),
274 'amplitude': np.random.uniform(self.amp_min, self.
amp_max, size=self.
n_samples),
283 orderedcols = [
'test',
'amplitude',
't0',
'tau',
'sigma',
's1',
's2',
's3',
's4',
's5',
's6',
'normed_tau']
286 self.
stockdata[[
's' + str(i)
for i
in range(1, 7)]] = self.
stockdata.apply(
lambda row: pd.Series(
287 gen_signal(row.amplitude, row.t0, row.tau, row.sigma, tau_sigma=self.
tau_sigma, w=self.
wf)), axis=1)
295 abins = np.arange(self.amp_min, self.
amp_max + 1, 1)
301 Get array of mean t0's for classifier bins
307 Get array of mean t0's for classifier bins
316 Empirical ranges of raw waveform width values from February 2017 testbeam data.
317 These values are only used for scaling and not critical.
323 def tau_hao2real(hao_tau):
325 Convert Hao's raw tau (integral, in latency units) to correct betaprime scale. Includes scaling and fit adjustment.
327 return 3.93 / 0.50305 * hao_tau
332 if __name__ ==
'__main__':
333 print(
'Basic functions for simulation of SVD strip data.\nImport to use.')