1 package org.hps.recon.tracking;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5
6 import org.apache.commons.math3.special.Gamma;
7 import org.hps.readout.svt.HPSSVTConstants;
8
9 import org.lcsim.detector.tracker.silicon.HpsSiSensor;
10 import org.lcsim.event.RawTrackerHit;
11
12
13
14
15
16
17
18 public class ShaperAnalyticFitAlgorithm implements ShaperFitAlgorithm {
19
20 private boolean debug = false;
21
22 public void setDebug(boolean debug) {
23 this.debug = debug;
24 }
25
26 @Override
27 public Collection<ShapeFitParameters> fitShape(RawTrackerHit rth, PulseShape shape) {
28 short[] samples = rth.getADCValues();
29 HpsSiSensor sensor = (HpsSiSensor) rth.getDetectorElement();
30 int channel = rth.getIdentifierFieldValue("strip");
31 return this.fitShape(channel, samples, sensor);
32
33 }
34
35 public Collection<ShapeFitParameters> fitShape(int channel, short[] samples, HpsSiSensor sensor) {
36 double minChisq = Double.POSITIVE_INFINITY;
37 int bestStart = 0;
38 ShapeFitParameters fit = new ShapeFitParameters();
39 for (int i = 0; i < samples.length - 2; i++) {
40 double chisq = fitSection(channel, samples, sensor, fit, i);
41
42 if (chisq < minChisq) {
43 minChisq = chisq;
44 bestStart = i;
45 }
46 }
47 fitSection(channel, samples, sensor, fit, bestStart);
48
49
50
51
52
53 ArrayList<ShapeFitParameters> fits = new ArrayList<ShapeFitParameters>();
54 fits.add(fit);
55 return fits;
56 }
57
58 private double fitSection(int channel, short[] samples, HpsSiSensor sensor, ShapeFitParameters fit, int start) {
59 int length = samples.length - start;
60 double[] y = new double[length];
61 double[] t = new double[length];
62
63 double tp = 2.5*Math.pow(sensor.getShapeFitParameters(channel)[HpsSiSensor.TP_INDEX], 0.25) * Math.pow(sensor.getShapeFitParameters(channel)[HpsSiSensor.TP_INDEX + 1], 0.75);
64
65 for (int i = 0; i < length; i++) {
66
67 y[i] = samples[start + i] - sensor.getPedestal(channel, i);
68 t[i] = HPSSVTConstants.SAMPLING_INTERVAL * i;
69 }
70
71 double[] p = new double[length];
72 double[] a = new double[length];
73 for (int i = 0; i < length; i++) {
74
75 p[i] = y[i] / sensor.getNoise(channel, i);
76
77
78 a[i] = Math.exp(1 - t[i] / tp) / (tp * sensor.getNoise(channel, i));
79 }
80
81 double pa, aatt, pat, aat, aa;
82 pa = 0;
83 aatt = 0;
84 pat = 0;
85 aat = 0;
86 aa = 0;
87 for (int i = 0; i < length; i++) {
88 pa += p[i] * a[i];
89 aatt += a[i] * a[i] * t[i] * t[i];
90 pat += p[i] * a[i] * t[i];
91 aat += a[i] * a[i] * t[i];
92 aa += a[i] * a[i];
93 }
94
95 double t0 = (pa * aatt - pat * aat) / (pa * aat - aa * pat);
96
97 double A = pa / ((Math.exp(t0 / tp) * (aat - t0 * aa)));
98
99 double time_var = 0;
100 double height_var = 0;
101 for (int i = 0; i < length; i++) {
102 double dt_dp = a[i] * (aatt - t[i] * aat - t0 * (aat - t[i] * aa)) / (pa * aat - aa * pat);
103
104 double dh_dp = (a[i] * Math.exp(-1.0 * t0 / tp) + A * dt_dp * aa) / (aat - t0 * aa) - A * dt_dp / tp;
105 time_var += dt_dp * dt_dp;
106 height_var += dh_dp * dh_dp;
107 }
108 t0 += HPSSVTConstants.SAMPLING_INTERVAL * start;
109 fit.setAmp(A);
110 fit.setAmpErr(Math.sqrt(height_var));
111 fit.setT0(t0);
112 fit.setT0Err(Math.sqrt(time_var));
113
114 double chisq = 0;
115 for (int i = 0; i < samples.length; i++) {
116 double ti = HPSSVTConstants.SAMPLING_INTERVAL * i;
117
118 double fit_y = A * (Math.max(0, (ti - t0)) / tp) * Math.exp(1 - (ti - t0) / tp) + sensor.getPedestal(channel, i);
119
120 chisq += Math.pow((fit_y - samples[i]) / sensor.getNoise(channel, i), 2);
121 }
122
123 if (A > 0 && chisq < Double.POSITIVE_INFINITY) {
124
125 fit.setChiProb(Gamma.regularizedGammaQ(samples.length - 2, chisq));
126 return chisq / (samples.length - 2);
127 } else {
128 return Double.POSITIVE_INFINITY;
129 }
130 }
131 }