QuarkNet students' results
Data processing
Trimming strips
After the data for an HV point has been collected by the data harvesting script, the noise for each APV is run over and trimmed; the categories of strips considered are "noisy", "dead", and "normal". Those strips ruled as normal will continue to the output portion of the data harvester. This is achieved by comparing each

strip's (mean) noise value to a running mean and rms, which are updated with each following strip's (mean) noise value. In this way we can cut strips which locally diverge but keep strips that may appear to the eye to be outliers, but are within the APV's noise behavior in previous strips. We perform this isntead of the individual comparison to the total APV's strips' mean noise and rms noise to speed up the data harvesting --- we can perform this as the values from each APV are read in.
For some strip's noise value

, that strip is marked as noisy if

and a strip is marked dead if
In addition to dead or noisy strips, there are also those which register a cosmic event which passes the (random) trigger; such an occurrence looks like the following example:
Sep2012
Analyzing Noise Bias Scan data for partition TECM
30 V| Dead strips: 185 | Noisy strips: 12 | Total strips: 1916416 |
45 V| Dead strips: 167 | Noisy strips: 19 | Total strips: 1916416 |
60 V| Dead strips: 169 | Noisy strips: 23 | Total strips: 1916416 |
75 V| Dead strips: 169 | Noisy strips: 26 | Total strips: 1916416 |
90 V| Dead strips: 171 | Noisy strips: 34 | Total strips: 1916416 |
105 V| Dead strips: 172 | Noisy strips: 51 | Total strips: 1916416 |
120 V| Dead strips: 162 | Noisy strips: 61 | Total strips: 1916416 |
135 V| Dead strips: 161 | Noisy strips: 76 | Total strips: 1916416 |
150 V| Dead strips: 169 | Noisy strips: 83 | Total strips: 1916416 |
165 V| Dead strips: 168 | Noisy strips: 103 | Total strips: 1916416 |
180 V| Dead strips: 159 | Noisy strips: 122 | Total strips: 1916416 |
195 V| Dead strips: 160 | Noisy strips: 123 | Total strips: 1916416 |
210 V| Dead strips: 155 | Noisy strips: 145 | Total strips: 1916416 |
225 V| Dead strips: 157 | Noisy strips: 154 | Total strips: 1916416 |
240 V| Dead strips: 153 | Noisy strips: 169 | Total strips: 1916416 |
250 V| Dead strips: 156 | Noisy strips: 179 | Total strips: 1916416 |
260 V| Dead strips: 157 | Noisy strips: 190 | Total strips: 1916416 |
275 V| Dead strips: 157 | Noisy strips: 214 | Total strips: 1916416 |
290 V| Dead strips: 156 | Noisy strips: 245 | Total strips: 1916416 |
300 V| Dead strips: 153 | Noisy strips: 265 | Total strips: 1916416 |
325 V| Dead strips: 154 | Noisy strips: 352 | Total strips: 1916416 |
350 V| Dead strips: 151 | Noisy strips: 485 | Total strips: 1916416 |
Trimmed APV post-mortem report for Sep2012 TECM :
Point-by-point: |
HV |
# empty APVs |
# dead APVs |
# noisy APVs |
# APVs with large error bars |
# APVs with large first value: |
# surviving APVs |
total # APVs |
30.0 V: |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
45.0 V: |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
60.0 V: |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
75.0 V: |
0 |
0 |
0 |
0 |
0 |
14948 |
14948 |
90.0 V: |
0 |
0 |
0 |
0 |
0 |
14956 |
14956 |
105.0 V: |
0 |
0 |
0 |
0 |
0 |
14956 |
14956 |
120.0 V: |
0 |
0 |
0 |
1 |
0 |
14956 |
14956 |
135.0 V: |
0 |
0 |
0 |
4 |
0 |
14956 |
14956 |
150.0 V: |
0 |
0 |
0 |
1 |
0 |
14956 |
14956 |
165.0 V: |
0 |
0 |
0 |
5 |
0 |
14956 |
14956 |
180.0 V: |
0 |
0 |
0 |
2 |
0 |
14956 |
14956 |
195.0 V: |
0 |
0 |
0 |
2 |
0 |
14956 |
14956 |
210.0 V: |
0 |
0 |
0 |
1 |
0 |
14956 |
14956 |
225.0 V: |
0 |
0 |
0 |
3 |
0 |
14957 |
14957 |
240.0 V: |
0 |
0 |
0 |
5 |
0 |
14956 |
14956 |
250.0 V: |
0 |
0 |
0 |
5 |
0 |
14956 |
14956 |
260.0 V: |
0 |
0 |
0 |
8 |
0 |
14955 |
14955 |
275.0 V: |
0 |
0 |
0 |
7 |
0 |
14956 |
14956 |
290.0 V: |
0 |
0 |
0 |
18 |
0 |
14956 |
14956 |
300.0 V: |
0 |
0 |
2 |
13 |
0 |
14954 |
14956 |
325.0 V: |
0 |
0 |
0 |
32 |
0 |
14954 |
14954 |
350.0 V: |
16 |
0 |
2 |
39 |
8 |
0 |
2 |
| APV profiles: | Dead APVs: 14952 | noisy APVs: 20 | survivors: 0
Analyzing Noise Bias Scan data for partition TECP
30 V| Dead strips: 186 | Noisy strips: 6 | Total strips: 1911040 |
45 V| Dead strips: 178 | Noisy strips: 15 | Total strips: 1911040 |
60 V| Dead strips: 183 | Noisy strips: 19 | Total strips: 1911040 |
75 V| Dead strips: 181 | Noisy strips: 30 | Total strips: 1911040 |
90 V| Dead strips: 179 | Noisy strips: 35 | Total strips: 1911040 |
105 V| Dead strips: 180 | Noisy strips: 44 | Total strips: 1911040 |
120 V| Dead strips: 179 | Noisy strips: 53 | Total strips: 1911040 |
135 V| Dead strips: 172 | Noisy strips: 67 | Total strips: 1911040 |
150 V| Dead strips: 174 | Noisy strips: 83 | Total strips: 1911040 |
165 V| Dead strips: 172 | Noisy strips: 97 | Total strips: 1911040 |
180 V| Dead strips: 173 | Noisy strips: 111 | Total strips: 1911040 |
195 V| Dead strips: 171 | Noisy strips: 121 | Total strips: 1911040 |
210 V| Dead strips: 170 | Noisy strips: 127 | Total strips: 1911040 |
225 V| Dead strips: 171 | Noisy strips: 140 | Total strips: 1911040 |
240 V | Dead strips: 169 | Noisy strips: 151 | Total strips: 1911040 |
250 V| Dead strips: 176 | Noisy strips: 168 | Total strips: 1911040 |
260 V| Dead strips: 178 | Noisy strips: 175 | Total strips: 1911040 |
275 V| Dead strips: 172 | Noisy strips: 191 | Total strips: 1911040 |
290 V| Dead strips: 169 | Noisy strips: 215 | Total strips: 1911040 |
300 V| Dead strips: 172 | Noisy strips: 238 | Total strips: 1911040 |
325 V| Dead strips: 173 | Noisy strips: 320 | Total strips: 1911040 |
350 V| Dead strips: 176 | Noisy strips: 452 | Total strips: 1911040 |
Trimmed APV post-mortem report for Sep2012 TECP :
Point-by-point: |
HV |
# empty APVs |
# dead APVs |
# noisy APVs |
# APVs with large error bars |
# APVs with large first value: |
# surviving APVs |
total # APVs |
30.0 V: |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
45.0 V: |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
60.0 V: |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
75.0 V: |
0 |
0 |
0 |
1 |
0 |
14927 |
14927 |
90.0 V: |
0 |
0 |
0 |
1 |
0 |
14930 |
14930 |
105.0 V: |
0 |
0 |
0 |
1 |
0 |
14930 |
14930 |
| 120.0 V: | 0 | 0 | 0 | 3 | 0 | 14930 | 14930
135.0 V: |
0 |
0 |
0 |
3 |
0 |
14930 |
14930 |
150.0 V: |
0 |
0 |
0 |
4 |
0 |
14930 |
14930 |
165.0 V: |
0 |
0 |
0 |
1 |
0 |
14930 |
14930 |
180.0 V: |
0 |
0 |
0 |
6 |
0 |
14930 |
14930 |
195.0 V: |
0 |
0 |
0 |
4 |
0 |
14930 |
14930 |
210.0 V: |
0 |
0 |
0 |
6 |
0 |
14930 |
14930 |
225.0 V: |
0 |
0 |
0 |
5 |
0 |
14930 |
14930 |
240.0 V: |
0 |
0 |
0 |
5 |
0 |
14930 |
14930 |
250.0 V: |
0 |
0 |
0 |
7 |
0 |
14930 |
14930 |
260.0 V: |
0 |
0 |
0 |
4 |
0 |
14930 |
14930 |
275.0 V: |
0 |
0 |
0 |
15 |
0 |
14930 |
14930 |
290.0 V: |
0 |
0 |
0 |
9 |
0 |
14930 |
14930 |
300.0 V: |
0 |
0 |
1 |
20 |
0 |
14929 |
14930 |
325.0 V: |
0 |
0 |
0 |
23 |
0 |
14929 |
14929 |
350.0 V: |
0 |
0 |
0 |
26 |
3 |
1 |
1 |
| APV profiles: | Dead APVs: 14920 | noisy APVs: 10 | survivors: 0
Analyzing Noise Bias Scan data for partition TIB
30 V |
Dead strips: 45 |
Noisy strips: 67 |
Total strips: 2234880 |
45 V |
Dead strips: 39 |
Noisy strips: 80 |
Total strips: 2234880 |
60 V |
Dead strips: 41 |
Noisy strips: 74 |
Total strips: 2234880 |
75 V |
Dead strips: 39 |
Noisy strips: 78 |
Total strips: 2234880 |
90 V |
Dead strips: 39 |
Noisy strips: 83 |
Total strips: 2234880 |
105 V |
Dead strips: 38 |
Noisy strips: 94 |
Total strips: 2234880 |
120 V |
Dead strips: 42 |
Noisy strips: 102 |
Total strips: 2234880 |
135 V |
Dead strips: 39 |
Noisy strips: 115 |
Total strips: 2234880 |
150 V |
Dead strips: 38 |
Noisy strips: 125 |
Total strips: 2234880 |
165 V |
Dead strips: 37 |
Noisy strips: 136 |
Total strips: 2234880 |
180 V |
Dead strips: 37 |
Noisy strips: 152 |
Total strips: 2234880 |
195 V |
Dead strips: 35 |
Noisy strips: 165 |
Total strips: 2234880 |
210 V |
Dead strips: 37 |
Noisy strips: 176 |
Total strips: 2234880 |
225 V |
Dead strips: 36 |
Noisy strips: 205 |
Total strips: 2234880 |
240 V |
Dead strips: 32 |
Noisy strips: 226 |
Total strips: 2234880 |
250 V |
Dead strips: 32 |
Noisy strips: 241 |
Total strips: 2234880 |
260 V |
Dead strips: 34 |
Noisy strips: 266 |
Total strips: 2234880 |
275 V |
Dead strips: 33 |
Noisy strips: 288 |
Total strips: 2234880 |
290 V |
Dead strips: 34 |
Noisy strips: 325 |
Total strips: 2234880 |
300 V |
Dead strips: 33 |
Noisy strips: 351 |
Total strips: 2234880 |
325 V |
Dead strips: 34 |
Noisy strips: 486 |
Total strips: 2234880 |
350 V |
Dead strips: 36 |
Noisy strips: 700 |
Total strips: 2234880 |
Cleaning noisy / dead APVs for TIB ...
Trimmed APV post-mortem report for Sep2012 TIB :
Point-by-point: |
HV |
# empty APVs |
# dead APVs |
# noisy APVs |
# APVs with large error bars |
# APVs with large first value: |
# surviving APVs |
total # APVs |
195.0 V: |
0 |
0 |
0 |
7 |
0 |
17456 |
17456 |
260.0 V: |
0 |
0 |
0 |
19 |
0 |
17456 |
17456 |
325.0 V: |
0 |
0 |
2 |
67 |
0 |
17454 |
17456 |
135.0 V: |
0 |
0 |
0 |
2 |
0 |
17456 |
17456 |
75.0 V: |
0 |
0 |
0 |
1 |
0 |
17456 |
17456 |
210.0 V: |
0 |
0 |
0 |
9 |
0 |
17456 |
17456 |
275.0 V: |
0 |
0 |
0 |
22 |
0 |
17456 |
17456 |
150.0 V: |
0 |
0 |
0 |
6 |
0 |
17456 |
17456 |
90.0 V: |
0 |
0 |
0 |
2 |
0 |
17456 |
17456 |
30.0 V: |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
225.0 V: |
0 |
0 |
0 |
9 |
0 |
17456 |
17456 |
290.0 V: |
0 |
0 |
0 |
31 |
0 |
17456 |
17456 |
165.0 V: |
0 |
0 |
0 |
2 |
0 |
17456 |
17456 |
105.0 V: |
0 |
0 |
0 |
3 |
0 |
17456 |
17456 |
300.0 V: |
0 |
0 |
0 |
40 |
0 |
17456 |
17456 |
45.0 V: |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
240.0 V: |
0 |
0 |
0 |
14 |
0 |
17456 |
17456 |
180.0 V: |
0 |
0 |
0 |
6 |
0 |
17456 |
17456 |
350.0 V: |
4 |
0 |
0 |
87 |
0 |
0 |
0 |
120.0 V: |
0 |
0 |
0 |
4 |
0 |
17456 |
17456 |
250.0 V: |
0 |
0 |
0 |
11 |
0 |
17456 |
17456 |
60.0 V: |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
| APV profiles: | Dead APVs: 17454 | noisy APVs: 6 | survivors: 0
Analyzing Noise Bias Scan data for partition TOB
30 V |
Dead strips: 82 |
Noisy strips: 26 |
Total strips: 3047424 |
45 V |
Dead strips: 81 |
Noisy strips: 17 |
Total strips: 3047424 |
60 V |
Dead strips: 83 |
Noisy strips: 20 |
Total strips: 3047424 |
75 V |
Dead strips: 80 |
Noisy strips: 24 |
Total strips: 3047424 |
90 V |
Dead strips: 73 |
Noisy strips: 30 |
Total strips: 3047424 |
105 V |
Dead strips: 76 |
Noisy strips: 37 |
Total strips: 3047424 |
120 V |
Dead strips: 75 |
Noisy strips: 47 |
Total strips: 3047424 |
135 V |
Dead strips: 76 |
Noisy strips: 50 |
Total strips: 3047424 |
150 V |
Dead strips: 80 |
Noisy strips: 57 |
Total strips: 3047424 |
165 V |
Dead strips: 77 |
Noisy strips: 61 |
Total strips: 3047424 |
180 V |
Dead strips: 78 |
Noisy strips: 65 |
Total strips: 3047424 |
195 V |
Dead strips: 83 |
Noisy strips: 78 |
Total strips: 3047424 |
210 V |
Dead strips: 80 |
Noisy strips: 97 |
Total strips: 3047424 |
225 V |
Dead strips: 85 |
Noisy strips: 110 |
Total strips: 3047424 |
240 V |
Dead strips: 83 |
Noisy strips: 120 |
Total strips: 3047424 |
250 V |
Dead strips: 83 |
Noisy strips: 133 |
Total strips: 3047424 |
260 V |
Dead strips: 81 |
Noisy strips: 149 |
Total strips: 3047424 |
275 V |
Dead strips: 82 |
Noisy strips: 171 |
Total strips: 3047424 |
290 V |
Dead strips: 73 |
Noisy strips: 181 |
Total strips: 3047424 |
300 V |
Dead strips: 78 |
Noisy strips: 206 |
Total strips: 3047424 |
325 V |
Dead strips: 80 |
Noisy strips: 240 |
Total strips: 3047424 |
350 V |
Dead strips: 77 |
Noisy strips: 280 |
Total strips: 3047424 |
Trimmed APV post-mortem report for Sep2012 TOB :
Point-by-point: |
HV |
# empty APVs |
# dead APVs |
# noisy APVs |
# APVs with large error bars |
# APVs with large first value: |
# surviving APVs |
total # APVs |
30.0 V: |
0 |
0 |
0 |
46 |
0 |
0 |
0 |
45.0 V: |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
60.0 V: |
0 |
0 |
0 |
5 |
0 |
0 |
0 |
75.0 V: |
0 |
0 |
0 |
0 |
0 |
23806 |
23806 |
90.0 V: |
0 |
0 |
0 |
0 |
0 |
23808 |
23808 |
105.0 V: |
0 |
0 |
0 |
0 |
0 |
23808 |
23808 |
120.0 V: |
0 |
0 |
0 |
0 |
0 |
23808 |
23808 |
135.0 V: |
0 |
0 |
0 |
0 |
0 |
23808 |
23808 |
150.0 V: |
0 |
0 |
0 |
1 |
0 |
23808 |
23808 |
165.0 V: |
0 |
0 |
0 |
1 |
0 |
23808 |
23808 |
180.0 V: |
0 |
0 |
0 |
0 |
0 |
23808 |
23808 |
195.0 V: |
0 |
0 |
0 |
1 |
0 |
23808 |
23808 |
210.0 V: |
0 |
0 |
0 |
1 |
0 |
23808 |
23808 |
225.0 V: |
0 |
0 |
0 |
2 |
0 |
23808 |
23808 |
240.0 V: |
0 |
0 |
0 |
2 |
0 |
23808 |
23808 |
250.0 V: |
0 |
0 |
0 |
1 |
0 |
23808 |
23808 |
260.0 V: |
0 |
0 |
0 |
4 |
0 |
23808 |
23808 |
275.0 V: |
0 |
0 |
0 |
4 |
0 |
23808 |
23808 |
290.0 V: |
0 |
0 |
0 |
10 |
0 |
23808 |
23808 |
300.0 V: |
0 |
0 |
0 |
12 |
0 |
23808 |
23808 |
325.0 V: |
0 |
0 |
0 |
18 |
0 |
23808 |
23808 |
350.0 V: |
0 |
0 |
0 |
32 |
2 |
0 |
0 |
| APV profiles: | Dead APVs: 23761 | noisy APVs: 47 | survivors: 0
Trimming APVs
The APVs' noise profiles (versus scanned HV points) exhibit some pathological behaviors; categorizing them and removing them (either completely or just singular noise values if, say, there exists a large rms on the noise at some HV value) will decrease the error bars on those APVs that only have a few errant points, and will clean up the tails of the fitted

distribution.
We can categorize the various pathologies of APVs as follows:
1. dead APVs

2. noisy APVs

and also

3. non-constantly noisy / dead (that is, high or low noise values at a few HV points (high values at one point may point to a cosmic event which passes the random trigger)).
Noise fitting model
To detect those charge carriers disturbed by minimum-ionizing traversing radiation (as well as transient, internal currents, etc.) we need to have a charge-carrier-depleted (neutral) zone in the bulk of the detector -- this is achieved by applying a reverse-biased potential across a p-n junction, and so on. < this can be fleshed out, I think.> This is intuitively model-able as a capacitance, which, as in Prokhorets [2], is modeled in the piecewise, inverse-square-root-in-HV, just like the above equation. For a more macroscopic view of the treatment of readout noise in pedestal bias runs, see chapter 3 of Richard Bremer's dissertation [1].
The relevant code:
def fitting_function(x, par):
import math
import ROOT
if x[0] <= par[2]:
return par[0] + par[1] * math.sqrt(par[2]) * 1. / math.sqrt(x[0])
else:
return par[0] + par[1]
There are, however, some difficulties encountered in fitting this function to the pesestal-noise data retrieved during noise (pedestal) bias runs. In short, the fits' reduced chi-squared values are either large (~50) or very small (~0.001), which indicates the fitting routine is "missing" the data points and their respective error bars, or our system is somehow overdetermined (i.e., tiny reduced chi-squared means the fit is very nearly intersecting the data points, which means that either we're really good at guessing the functional form, or that something's awry).
[1] R. Bremer, Ph.D. thesis, RWTH Aachen University, 2008
bremer_ch3.pdf: Bremer's dissertation, chapter 3
[2] I.M. Prokhorets, et. al. Nucl. Exp. Techn.
46 24 (2003)
2003_Prokhorets.pdf
Obtaining fit parameter spaces
Before we get to the parameter spaces and what they can tell us, first, how does one get these contours? Using
the contour tutorial
as a basis, the general recipe is a) make a
TFitResults object with the usual .Fit() routine, and b) call gMinuit explicitly. Note that in the below code snippet, gMinuit is altered in its fitting strategy to its most "careful" setting; see
http://wwwasdoc.web.cern.ch/wwwasdoc/minuit/node18.html
for details.
# Set up the function with 3 fitting parameters, using the "fitting_function" function, in the range
# [func_min, func_max], with initial guesses for the fit parameters:
fit_for_plot = ROOT.TF1("fit", fitting_function, func_min, func_max, 3)
fit_for_plot.SetParameters(par0_guess, par1_guess, par2_guess)
fit_for_plot.SetParLimits(2, par2_min, par2_max)
fit_for_plot.SetParLimits(1, par1_min, par1_max)
fit_for_plot.SetParNames('a', 'b', 'vdepl') #Make the var names understandable.
output_canvas = ROOT.TCanvas(date+'_contours_'+profile.GetName(), 'Testing n-sigma contours', 10, 10, 1200, 800)
results = profile.Fit(fit_for_plot, 'RSQ') #Fitting the current profile with the TF1 defined above
output_canvas.Update()
outputted_a_par = fit_for_plot.GetParameter(0)
outputted_delta_a_par = fit_for_plot.GetParError(0)
outputted_b_par = fit_for_plot.GetParameter(1)
outputted_delta_b_par = fit_for_plot.GetParError(1)
outputted_vdepl = fit_for_plot.GetParameter(2)
outputted_delta_vdepl = fit_for_plot.GetParError(2)
outputted_chi2 = fit_for_plot.GetChisquare()
## Setting up the first plot: b(Vdepl) contour at 2 sigma.
output_canvas.cd(1)
ROOT.gMinuit.SetErrorDef(4) # TMinuit goes by n_{sigma}^2; 2^2 (sigma^2) = 4.
# The below two commands are somewhat arcane. Here's a try at an explanation.
# Because the fits are so tricky, I want TMinuit to really work at finding
# as best it can local minima and not get stuck (hopefully...). So I need to
# explicitly access TMinuit's options through gMinuit. Then things like fitting
# strategy
p0vp2 = ROOT.gMinuit; p0vp2.Command('SET STR 2')
# With gMinuit set up, let's make the contour now, for param. b against Vdepl:
p0_v_p2 = p0vp2.Contour(80,2,1)
leg_1 = ROOT.TLegend(0.55, 0.55, 0.8, 0.8)
if p0_v_p2 != None:
#This set of loops catches any failed fitting.
# If the fit "fails" or gMinuit decides it's gone too far, no TGraph is returned.
if p0_v_p2.ClassName() != 'TObject':
p0_v_p2.SetFillColor(42)
p0_v_p2.Draw('alf')
p0_v_p2.SetTitle('2 #sigma')
leg_1.AddEntry(p0_v_p2)
p0_v_p2.SetTitle('Parameter b vs V_{depl};V_{depl} [V]; parameter b [V]')
Parameter space naïve fit
The contour plot script is derived from the tutorial ROOT macro found on most computers under
$ROOTSYS/tutorials/fit/fitcont.C
The contour plot script used to generate the parameter-space contour seen on this page can be found on AFS under:
/afs/cern.ch/work/e/eorcutt/public/noise/test_parameter_contours.py
As the fits are finicky, our chi-squared hypersurface is, instead of the tractable smooth as with polynomial functions, very irregular, with many local chi-squared minima, and enormous global minima -- hence the large number of fits converging to nearly 10.0 and 350.0 V. Below is a composite graphic of contour plots of the fit parameters against each other, with a comparison plot of the fitted data (replete with fitting function).
This is a "well-behaved" APV; note, however, the small reduced chi-squared value, and the absence of a two-

contour in the contour of a(b). This hints already that the fit isn't working so well; also look to the very small reduced

value -- we do not know the model nearly so precisely, as can be verified by looking at the fit function -- it doesn't pass through every data point.
An example of a not-as-good fit is given below:
Notice that the double knee phenomenon occurs here and noticeably throws off the fitter. This also hints at the notion that perhaps the double knee is not an optical noise phenomenon: the two above contour plots are for consecutive APVs (that is, they're on the same opto-pair).
Linearised fittings:
-
- with this parameterization, we get the piecewise-defined function
With this linearization it is hoped we can avoid the difficulty TMinuit is experiencing with an inverse-root-defined, region-defining parameter (i.e.,

) by refactoring it so that it is not weighted as much in defining the quadratic and linear regions. This linearization preserves one of the inequalities and keeps the inverse square root.
The related Python code is:
def fitting_function(x, par):
import math
import ROOT
if x[0] <= par[2]:
return par[0] + par[1] / math.sqrt(x[0])
else:
return par[0] + par[1] / math.sqrt(par[2])
This has shown fit convergence rates and fitted

values and their corresponding uncertainties similar to those of the "old" fitting method (i.e., the naïve fitting using the "standard"

function.
Parameter space for
-
- with this other parameterization, we get the piecewise-defined function
The code for this is
def fitting_function(x, par):
import math
import ROOT
if x[0] >= 1./math.sqrt(par[2]):
return par[0] + par[1] * math.sqrt(par[2]) * x[0]
else:
return par[0] + par[1]
Here, it is hoped we can avoid the quadratic behavior of

altogether, and work with a function linear in

; note, however, that the quadratic behavior is shifted to the region bounds and the

itself (as in the "original" noise function).
Parameter space for
As for the quadratic behavior being offset, let's see what the fit-parameter spaces tell us:
A more adjustable (and accurate) fitting scheme
Another approach which seems (need to check on whether this is T/F, and remove the subjunctive) to work well is making the

a parameter over which we loop. From these we can find which

gives the best fit; some examples of this behavior are shown below.
The code which effects this is quite simple:
vd_list = [x for x in range(10,460,20)]
# The Fitted() class is simply allowing one-line access to a fit, its results, and so its chi-squared value.
min_list = [ Fitted(new_profile, x, 25).getChiSquared() for x in vd_list ]
# Now, just take the built-in STL .min() method Python provides to get the smallest chi-squared.
minchi = min(min_list)
# Next, find the Vdepl that gave us this chi-squared, using the list
# of chi-squareds as our guide.
for x,y in zip(min_list, vd_list):
if x == minchi:
best_vdepl = y
best_index = min_list.index(x)
best_results = Fitted(new_profile, x_list[best_index]-1, 25).getResults()
a_param = best_results.Value(0)
delta_a = best_results.ParError(0)
b_param = best_results.Value(1)
delta_b = best_results.ParError(1)
chi2 = minchi ##Just relabelling...
delta_vdepl = 0.
fit_success = int(best_results)
Just below is the first

in the loop (for the December dataset, anyway...) notice the overall

is not so great:
This second plot shows another

point: notice the improvement in visual fit, and in

:
This third plot corresponds to the optimal

(ie, the

is the least out of the set of

values). Note that since we're working with the overall

, the nonlinear portion begins to extend into a region that it may not well describe -- so we see that visually the goodness of fit decreases as the

cutoff increases:
Note, though, that the best

for this APV corresponds to a goodness-of-fit of ~4. My current hypothesis (this will be tested soon) is that this optimization is over the
overall
so we can likely squeeze some more goodness-of-fit from the data if I optimize to the

for the exponential piece and the linear piece.
APV behaviors
Using September as a "standard candle" for kinds of misbehaving / damaged APVs' behavior, we can both develop tools to clean up the Vdepl signal in the July and December datasets, and have a better understanding of the most-irradiated (up to this point) silicon detectors (as of September, the SSD has suffered the most luminosity -- this will change when the January 2013 bias scan is made available).
A simple starting point is trying to understand the APVs and modules in the right-hand-side tail of the APV-distribution of fitted Vdepl, >= 325 V:
Another simple starting point is the fit parameter "A", or the noise value (in ADC counts) corresponding to a fully-depleted module. Looking at all three of the datasets, we see an interesting structure to the full-depleted noise distributions:

There are several significant features: 1. The double-Gaussian appearance for all the datasets, and 2. The peaks' central values for December 2010 and September 2012 are at higher ADC count values than the July 2011 dataset is -- because December and September's readout modes were set to deconvolution mode, the noise read out tends to be higher in comparison to peak mode (which is the readout mode the SSD tracker was set to for the July noise bias scan).
A partition-by-partition look at this fit parameter examine above for the standard candle September 2012 dataset shows more interesting structure:

Namely, that the double-Gaussian behavior is limited to the endcap partitions -- the barrels and tracker inner disks (TID) are singly-peaked. This suggests many possible reasons for the tendendcy for the endcap APVs to have a fully-depleted noise value of ~4.5 or ~6 ADCc -- for example, geometry (radial values correlate in some way to A), bulk volume, EC disk #, ring/wheel # are parameters that should be investigated; these coordinates can be translated to Python (nearly done with that), transliterating the methods and classes found at
http://cmslxr.fnal.gov/lxr/source/DataFormats/SiStripDetId/src/SiStripSubStructure.cc.
For a satisfying checkover, we'll look at July 2011 and December 2010's "A" parameter plots, partition-by-partition, as well. Note again, the same encap/double-Gaussian occurrence.
"Old" to "new"
From the older, more-bug-ridden analysis / data-harvesting code, we saw some odd features, such as comparatively large error bars on the mean noise measurements, irregularly masked tracker-map regions, and problematic noise fitting. Examples of these are below
.
The newer data-harvesting and analysis has (hopefully) repaired the error bars, and has regularized the tracker map-making code (and made it so that the problematic dictionaries occasionally handed to the mapping function are no longer problematic, and so that "capping" (arbitrarily-chosen by the user) high fitted full depletion voltages or other quantities is possible [this allows us a better 'resolution' for the mapped values as there's a more-visible color variance among differing values when there's no large value at "red"]). The fitting, however, remains another matter.
In the plot below, notice 1) that the mean noise between the two "datasets" is the same (not surprising, but reassuring), and that 2) the error bars for the "new" are on the whole smaller (this is not a guarantee for those noisier APVs):
So, what in the fit behaviors has changed? Below is a plot of the
distributions for "old" and "new", with another plot which shows a zoomed-in view of the first plot from 0 to 50 V HV:

Finding the TID modules
One glaring problem in the "old" outputted tracker maps was the absence of the tracker inner disk (TID) modules. In the end, they were easy to add back in. The problem lies in the bundling of TID module data in the tracker inner barrel (TIB) pedestal bias run output files. Because the data harvester separated data based on the partitions which were derived from the input filenames, and because the input file names included only tracker end caps (TECM, TECP), and the barrel (TIB, TOB), TID was excluded.
The code fragment used to generate a list of detIDs for a given partition is:
detid_list = [detid for detid in detidPathDict.keys() if list(strip_detid_alias_dict[int(detid)])[0].upper().startswith(partition)]
That is, from the files (these are examples only)
(for December 2010 and July 2011 data):
tecm185.root
tecp185.root
tib185.root
tob185.root
(for September 2012 data):
TECM_203270_180.root
TECP_203244_180.root
TIB_203243_180.root
TOB_203245_180.root
we will get (voltage points 185 and 180 V) the same partitions: TEC(M,P) and T(I,O)B. So how is TID added back in? With the following simple addendum:
for detid in detidPathDict.keys():
if list(strip_detid_alias_dict[int(detid)])[0].split('_')[0].startswith('TID'):
tidDict.update({detid:detidPathDict[detid]})
tid_list = [ x for x in tidDict.keys() ]
if partition == 'TIB':
detid_list = detid_list.append(tid_list)
Workflow
Check-out the noise-bias-scan data-harvesting and analysis scripts:
cd CMSSW_X_Y_Z/src
cvs co UserCode/eorcutt/NoiseBiasScan
Current noise bias scan data
Noise bias scan run date |
Partition |
NBS data location |
Run #s |
APV 25 readout mode |
Elogs |
December 2010 |
TEC- |
eos/cms/store/user/gbenelli/NoiseBiasScan/Dec2010/TECM |
|
deco |
|
|
TEC+ |
eos/cms/store/user/gbenelli/NoiseBiasScan/Dec2010/TECP |
|
|
|
TIB |
eos/cms/store/user/gbenelli/NoiseBiasScan/Dec2010/TIB |
|
|
|
TOB |
eos/cms/store/user/gbenelli/NoiseBiasScan/Dec2010/TOB |
|
|
July 2011 |
TEC- |
eos/cms/store/user/gbenelli/NoiseBiasScan/Jul2011/TECM |
|
peak |
http://cmsonline.cern.ch/cms-elog/598844 |
|
TEC+ |
eos/cms/store/user/gbenelli/NoiseBiasScan/Jul2011/TECP |
|
|
|
|
TIB |
eos/cms/store/user/gbenelli/NoiseBiasScan/Jul2011/TIB |
|
|
|
TOB |
eos/cms/store/user/gbenelli/NoiseBiasScan/Jul2011/TOB |
|
|
September 2012 |
TEC- |
eos/cms/store/user/gbenelli/NoiseBiasScan/Sep2012/TECM |
|
deco |
http://cmsonline.cern.ch/cms-elog/785673 |
|
TEC+ |
eos/cms/store/user/gbenelli/NoiseBiasScan/Sep2012/TECP |
|
|
|
TIB |
eos/cms/store/user/gbenelli/NoiseBiasScan/Sep2012/TIB |
|
|
|
TOB |
eos/cms/store/user/gbenelli/NoiseBiasScan/Sep2012/TOB |
|
|
External condition timeline
Time |
Condition (September 2012) |
Link |
0000 |
|
|
0100 |
|
|
0200 |
|
|
0300 |
|
|
0400 |
|
|
0500 |
|
|
0600 |
|
|
0700 |
|
|
0800 |
begin noise scan |
|
0900 |
|
|
1000 |
|
|
1100 |
|
|
1200 |
|
|
1300 |
|
|
1400 |
|
|
1500 |
end noise scan |
|
1600 |
|
|
1700 |
|
|
1800 |
|
|
1900 |
|
|
|
2000 |
|
|
|
Purpose
The purpose of this project is to be able to extract from noise bias scan data the (full) depletion voltage for each module in the cms silicon strip detectors (the inner and outer barrels, and the +z and -z end cap detectors); from multiple bias scans, we can determine the modules' depletion voltage time evolution. We should be able to determine the modules' responses to radiation damage; from this we can answer questions such as where the detectors are on the type-inversion plot.
Analysis
The pedestal bias noise for a given strip is the rms of the pedestal value for that strip; this is taken during pedestal bias runs, in which the silicon strip detectors are not forward biased (or indeed, biased at all), but rather the readout is "listening" to the machine noise (phrasing? correctness?).
The results of the pedestal bias run are shown below:
And the RMS of the pedestals extracted for each strip, over 2 APVs is:
This figure shows the pedestal values for 256 strips; since there are 128 strips / APV, there are 2 APVs in this profile. It is worthwhile to note that there are two APVs per optical link (aka laser channel). There are designed an "upper" and a "lower" APV per opto-link (APV pair).
As of mid to late December, it was noticed that the error bars on the fitted depletion voltage were overlarge: ~ 1 V. This gives the fit more "room" to find a "good" fit (from the viewpoint of chi-squared only; other parameters and their sigmas can give a better picture); there was a noticeable propensity for modules (and APVs) to skew towards the 350 V end of the fitted depletion voltage (i.e., get pushed to the best possible "minimum" value for the noise function):
[plots go here showing the "old" method's skewed outcomes]
Depletion voltage
First are the distributions of (mean untrimmed) V_{depl} for December and July, for all APVs [NB: shift around to keep Dec with Dec and July with July?]:
Notice the 'spike' at ~450 V, especially in December (!!). What does the chi2 distribution of these fitted V_{depl} look like?
Once the data have been fitted with the above fitting function [need to add the details on fitting function and motivations (if there exist) for the given damage model], we need to decide what constitutes a 'good' versus a 'bad' fit.
Given 31 degrees of freedom for the December 2010 dataset (34 HV points - 3 fit parameters), a (non-reduced) chi-squared value of 50 will give us a set of fitted V_{depl} with a ~98% confidence level; for 18 degrees of freedom for the December 2010 dataset (21 HV points - 3 fit parameters), a (non-reduced) chi-squared value of 33 will give us a set of fitted V_{depl} with a ~98% confidence level.
December 2010, fitted V_{depl}, averaged across n APVs for each module (where n is between 4 and 6)
July 2011, fitted V_{depl}, averaged across n APVs for each module (where n is between 4 and 6)
What are the effects of the cuts on the number of APV1's in each module?
For December:
December 2010 |
# APVS passed chi2 cut |
# APVs passed V_{depl} cut |
#APVs passed both Vd and chi2 |
Total # APVs |
TOB |
5120 |
4636 |
4628 |
5130 |
TECM |
3180 |
2198 |
2198 |
3181 |
TECP |
3166 |
2082 |
2082 |
3166 |
TIB |
2549 |
2408 |
2408 |
2553 |
For July:
July 2011 |
# APVS passed chi2 cut |
# APVs passed V_{depl} cut |
#APVs passed both Vd and chi2 |
Total # APVs |
TOB |
5112 |
3486 |
3209 |
5114 |
TECM |
3181 |
2306 |
2211 |
3181 |
TECP |
3166 |
2321 |
2203 |
3166 |
TIB |
2555 |
2159 |
2146 |
2555 |
Spread in depletion voltage
currently using the standard deviation from the mean fitted V_{depl} across all APVs in a given module, for all modules. This may change.
December 2010, spread in fitted V_{depl}
December 2010, spread in fitted V_{depl},
distribution
Jul 2011, spread in fitted V_{depl}
Jul 2011, spread in fitted V_{depl},
distribution
Golden modules
One potentially useful handle on determining the goings-on in a dataset is finding a set of "golden" modules: those which have "good" fit values and Vdepl fitted values for 4 / 4 or 6 / 6 APVs in the modules. From there we may get a better picture of the fitted Vdepl distribution, see which modules remain as constants across the cumulative datasets, which change, etc.
%------+++ Mean noise versus median noise
Double knees
Instead of the "expected" inverse root, asymptotic behavior expected from the capacitance noise model, we see a "double" of the decrease; an example is seen below:
So, how many modules (and how many APVs in a given module) are affected by this? Does this cause some of our fits to converge to the local minimum (which is the endpoint on the high voltage bias axis, hence the proportionately large number of fitted 450-V modules)? Below are tables for the December 2010 and the July 2011 bias runs, on how many modules report 1, 2, 3, ..., 6 APVs with a double knee. Note that the numbers of modules with /n/ double knees is exclusive -- that is, if a module reports 4 APVs with a double knee, then it will not be counted as one with 3, 2, or 1 double-kneed modules (this is also checked by matching the sums).
Number of modules in each detector with [0,6] APVs reporting a DK:
[NB: the following tables were computed by hand. As is plain to see, the results are tedious and horrendous. Add in a LaTeX-table-generating portion to the analysis script.]
December 2010:
# Modules with n DK |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
Total # |
TECM |
2842 |
251 |
78 |
6 |
4 |
0 |
0 |
3184 |
Percentage of total |
89.3% |
7.9% |
1.9% |
0% |
0% |
-- |
TECP |
2856 |
222 |
70 |
11 |
7 |
0 |
0 |
3166 |
Percentage of total |
90.2% |
7.00% |
2.2% |
0% |
0% |
-- |
TIB |
1668 |
483 |
229 |
102 |
63 |
8 |
0 |
2555 |
Percentage of total |
66.1% |
18.9% |
4.0% |
2.5% |
0% |
-- |
TOB |
4081 |
637 |
328 |
64 |
17 |
3 |
0 |
5130 |
Percentage of total |
79.6% |
6.4% |
1.2% |
0.1% |
0% |
-- |
July 2011:
# Modules with n DK |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
Total # |
TECM |
2558 |
393 |
174 |
42 |
14 |
0 |
0 |
3184 |
TECP |
2567 |
383 |
153 |
51 |
11 |
1 |
0 |
3166 |
TIB |
1369 |
662 |
387 |
112 |
23 |
2 |
0 |
2555 |
TOB |
4646 |
335 |
96 |
28 |
8 |
0 |
0 |
5130 |
From the above numbers, it (naively at least) seems that the double knee issue is a non-issue. It wouldn't hurt to check correlations further down the line, when cuts and such have been applied. Also, need to investigate whether plots which fail the fit (and also those which "pass" the fit) exhibit double knee behavior.
December 2010: modules with a double knee (using "old" test currently)

NB: for map above (Dec 2010 double knee TM), keep in mind this is a map for APV #6 in each module; I'll be fixing this oversight soon.
July 2011: modules with a double knee (using "old" test currently)

NB: for map above (Jul 2010 double knee TM), keep in mind this is a map for APV #6 in each module; I'll be fixing this oversight soon.
Construction database
NB: There are some discrepancies in the provided construction database total depletion voltage values (i.e., those modules that are white) and the December, July, or August datasets. Any "missing" modules w.r.t.t. pedestal bias runs are not considered with anything construction DB-related.
Notice in the below tracker map and distribution, the approximate mean of Vdepl ~ 200 V.
Tracker map of full depletion voltage values from construction DB
Distribution of full depletion voltage values from construction DB
Software
The repository for the data harvester and analysis code is
here
. It can be checked out on an lxplus machine via 'cvs co /UserCode/eorcutt/NoiseScan'.
1. The
DataHarvester_rc.py script takes the noise bias run data from EOS and extracts and calculates the quantities we want, and stores this in
ROOT files, divided by detector (this is due to memory concerns when generating each detector's dictionary). It can be found at
http://cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/UserCode/eorcutt/NoiseScan/ModifiedDataHarvester_rc.py?view=log
and on AFS at the directory
/afs/cern.ch/work/e/eorcutt/public/noise/ModifiedDataHarvester_rc.py
2. The analyze_again.py script fits the V_{depl} found in the
ROOT files output by the data harvester (linked above), if the script is run with the command-line argument "--fit". If it is instead "--nofit", then the analysis script portion is run instead, and analysis histograms and correlation plots and a bash script to generate tracker maps is created. The output file is analysisOutput.root. It can be found at
http://cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/UserCode/eorcutt/NoiseScan/ModifiedDataHarvester_rc.py?view=log
and on AFS at the location
/afs/cern.ch/work/e/eorcutt/public/noise/analyze_again.py
Data flow [rough section]
Pedestal bias run data -> (1)
DataHarvester -> (2) analyze.py (dk flagging, vdepl fitting -- fitting flag set to "True") -> (3) analyze.py (analysis script mode -- fitting flag set to "False")
The pedestal bias scan data is our starting point (link to example file on AFS/EOS here); the bias voltage for each strip is monitored over 2000 events; the rms of this is our noise. So we grab this noise from each strip using TProfile's
GetBinError() method.
-- JamesOrcutt - 24-Oct-2012Error during latex2img:
ERROR: problems during latex
INPUT:
\documentclass[fleqn,12pt]{article}
\usepackage{amsmath}
\usepackage[normal]{xcolor}
\setlength{\mathindent}{0cm}
\definecolor{teal}{rgb}{0,0.5,0.5}
\definecolor{navy}{rgb}{0,0,0.5}
\definecolor{aqua}{rgb}{0,1,1}
\definecolor{lime}{rgb}{0,1,0}
\definecolor{maroon}{rgb}{0.5,0,0}
\definecolor{silver}{gray}{0.75}
\usepackage{latexsym}
\begin{document}
\pagestyle{empty}
\pagecolor{white}
{
\color{black}
\begin{math}\displaystyle B'\end{math}
}
\clearpage
{
\color{black}
\begin{math}\displaystyle \sigma\end{math}
}
\clearpage
{
\color{black}
\begin{math}\displaystyle \chi^{2}\end{math}
}
\clearpage
{
\color{black}
\begin{math}\displaystyle x \rightarrow x' = x^{-\frac{1}{2}}\end{math}
}
\clearpage
{
\color{black}
\begin{math}\displaystyle \chi^2\end{math}
}
\clearpage
{
\color{black}
\begin{math}\displaystyle B \rightarrow B' = B\sqrt{C}\end{math}
}
\clearpage
{
\color{black}
\begin{math}\displaystyle x'\end{math}
}
\clearpage
{
\color{black}
\begin{math}\displaystyle n(V)\end{math}
}
\clearpage
{
\color{black}
\begin{math}\displaystyle sigma_i \gt \bar{\sigma}_{APV} + 5 * \text{rms}(\sigma_{APV}),\end{math}
}
\clearpage
{
\color{black}
\begin{math}\displaystyle \sigma_i \lt \bar{\sigma}_{APV} - 5 * \text{rms}(\sigma_{APV})\end{math}
}
\clearpage
{
\color{black}
\begin{math}\displaystyle V_{depl}\end{math}
}
\clearpage
{
\color{black}
\begin{math}\displaystyle x\end{math}
}
\clearpage
\end{document}
STDERR:
This is pdfTeX, Version 3.1415926-2.5-1.40.14 (TeX Live 2013)
restricted \write18 enabled.
entering extended mode
(/tmp/KhlzIW63ks/oz8BNj8Rk5
LaTeX2e <2011/06/27>
Babel and hyphenation patterns for english, dumylang, nohyphenation, lo
aded.
(/usr/share/texlive/texmf-dist/tex/latex/base/article.cls
Document Class: article 2007/10/19 v1.4h Standard LaTeX document class
(/usr/share/texlive/texmf-dist/tex/latex/base/fleqn.clo)
(/usr/share/texlive/texmf-dist/tex/latex/base/size12.clo))
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty
For additional information on amsmath, use the `?' option.
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty))
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty)
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty))
(/usr/share/texlive/texmf-dist/tex/latex/xcolor/xcolor.sty
(/usr/share/texlive/texmf-dist/tex/latex/latexconfig/color.cfg)
(/usr/share/texlive/texmf-dist/tex/latex/graphics/dvips.def))
(/usr/share/texlive/texmf-dist/tex/latex/base/latexsym.sty)
No file oz8BNj8Rk5.aux.
(/usr/share/texlive/texmf-dist/tex/latex/base/ulasy.fd) [1] [2] [3] [4]
[5] [6] [7] [8]
! Undefined control sequence.
l.57 \begin{math}\displaystyle sigma_i \gt
\bar{\sigma}_{APV} + 5 * \text{rm...
[9]
! Undefined control sequence.
l.62 \begin{math}\displaystyle \sigma_i \lt
\bar{\sigma}_{APV} - 5 * \text{r...
[10] [11] [12] (./oz8BNj8Rk5.aux) )
(see the transcript file for additional information)
Output written on oz8BNj8Rk5.dvi (12 pages, 3308 bytes).
Transcript written on oz8BNj8Rk5.log.