1
2
3
4
5
6
7
8 package org.lcsim.recon.tracking.seedtracker;
9
10 import hep.physics.vec.BasicHep3Vector;
11 import hep.physics.vec.Hep3Vector;
12 import hep.physics.vec.VecOp;
13
14 import java.util.ArrayList;
15 import java.util.Collections;
16 import java.util.List;
17 import java.util.Map;
18
19 import org.lcsim.fit.helicaltrack.HelicalTrackFit;
20 import org.lcsim.fit.helicaltrack.HelicalTrackHit;
21 import org.lcsim.fit.helicaltrack.HelixUtils;
22 import org.lcsim.fit.helicaltrack.MultipleScatter;
23
24
25
26
27
28
29
30 public class MultipleScattering {
31 protected MaterialManager _materialmanager;
32 protected double _bfield = 0.;
33 private int _mxint = 10;
34 protected boolean _debug = false;
35
36
37
38
39
40 public MultipleScattering(MaterialManager materialmanager) {
41 _materialmanager = materialmanager;
42 }
43
44
45
46
47
48
49
50 public List<ScatterAngle> FindScatters(HelicalTrackFit helix) {
51
52
53 if (_bfield == 0.) throw new RuntimeException("B Field must be set before calling FindScatters method");
54
55
56 List<ScatterAngle> scatters = new ArrayList<ScatterAngle>();
57
58
59 List<MaterialCylinder> matcyl = _materialmanager.getMaterialCylinders();
60 List<MaterialDisk> matdsk = _materialmanager.getMaterialDisks();
61 List<MaterialXPlane> matxpl = _materialmanager.getMaterialXPlanes();
62
63
64 double smax = 9999.;
65
66
67 double rmax = _materialmanager.getRMax();
68 List<Double> slist = HelixUtils.PathToCylinder(helix, rmax, smax, 1);
69 if (slist.size() > 0) smax = Math.min(smax, slist.get(0));
70 double zmax = _materialmanager.getZMax();
71 if (helix.slope() < 0.) zmax = -zmax;
72 smax = Math.min(smax, HelixUtils.PathToZPlane(helix, zmax));
73
74 for (MaterialDisk disk : matdsk) {
75 double s = HelixUtils.PathToZPlane(helix, disk.z());
76 if (s > 0. && s < smax) {
77 Hep3Vector pos = HelixUtils.PointOnHelix(helix, s);
78 double r = Math.sqrt(Math.pow(pos.x(), 2) + Math.pow(pos.y(),2));
79 if (r >= disk.rmin() && r <= disk.rmax()) {
80 double cth = Math.abs(helix.cth());
81 double radlen = disk.ThicknessInRL() / Math.max(cth, .001);
82 double angle = msangle(helix.p(_bfield), radlen);
83 scatters.add(new ScatterAngle(s, angle));
84 }
85 }
86 }
87
88 for (MaterialCylinder cyl : matcyl) {
89 double r = cyl.radius();
90 double scmin = HelixUtils.PathToZPlane(helix, cyl.zmin());
91 double scmax = HelixUtils.PathToZPlane(helix, cyl.zmax());
92 if (scmin > scmax) {
93 double temp = scmin;
94 scmin = scmax;
95 scmax = temp;
96 }
97 List<Double> pathlist = HelixUtils.PathToCylinder(helix, r, smax, _mxint);
98 for (Double s : pathlist) {
99 if (s > scmin && s < scmax) {
100 Hep3Vector dir = HelixUtils.Direction(helix, s);
101 Hep3Vector pos = HelixUtils.PointOnHelix(helix, s);
102 Hep3Vector rhat = VecOp.unit(new BasicHep3Vector(pos.x(), pos.y(), 0.));
103 double cth = Math.abs(VecOp.dot(dir, rhat));
104 double radlen = cyl.ThicknessInRL() / Math.max(cth, 0.001);
105 double angle = msangle(helix.p(_bfield), radlen);
106 scatters.add(new ScatterAngle(s, angle));
107 }
108 }
109 }
110
111 for (MaterialXPlane xpl : matxpl) {
112 List<Double> pathlist = HelixUtils.PathToXPlane(helix, xpl.x(), smax, _mxint);
113 for (Double s : pathlist) {
114 Hep3Vector dir = HelixUtils.Direction(helix, s);
115 Hep3Vector pos = HelixUtils.PointOnHelix(helix, s);
116 double y=pos.y();
117 double z=pos.z();
118 if (y >= xpl.ymin() && y <= xpl.ymax()&&z >= xpl.zmin() && z <= xpl.zmax()) {
119 Hep3Vector xhat = VecOp.unit(new BasicHep3Vector(pos.x(),0. , 0.));
120 double cth = Math.abs(VecOp.dot(dir, xhat));
121 double radlen = xpl.ThicknessInRL() / Math.max(cth, .001);
122 double angle = msangle(helix.p(_bfield), radlen);
123 scatters.add(new ScatterAngle(s, angle));
124 }
125 }
126 }
127
128 Collections.sort(scatters);
129 return scatters;
130 }
131
132 public static MultipleScatter CalculateScatter(HelicalTrackHit hit, HelicalTrackFit helix, List<ScatterAngle> scatters) {
133
134
135 double sth2 = Math.pow(helix.sth(), 2);
136
137
138
139 Map<HelicalTrackHit, Double> pathmap = helix.PathMap();
140 if (!pathmap.containsKey(hit)) {
141 pathmap.put(hit, (Double) HelixUtils.PathLength(helix, hit));
142 }
143
144 double hitpath = pathmap.get(hit);
145
146
147
148 double rphi_ms2 = 0.;
149 double z_ms2 = 0.;
150 for (ScatterAngle scat : scatters) {
151
152
153 double scatpath = scat.PathLen();
154
155
156 if (scatpath > hitpath) break;
157
158
159 double angle = scat.Angle();
160
161
162
163
164 rphi_ms2 += Math.pow((hitpath - scatpath) * angle, 2);
165
166
167
168
169
170
171 z_ms2 += Math.pow((hitpath - scatpath) * angle, 2)/sth2;
172 }
173
174
175 return new MultipleScatter(Math.sqrt(rphi_ms2), Math.sqrt(z_ms2));
176 }
177
178 public void setBField(double bfield) {
179 _bfield = bfield;
180 }
181
182
183 public double msangle(double p, double radlength) {
184 double angle = (0.0136 / p) * Math.sqrt(radlength) * (1.0 + 0.038 * Math.log(radlength));
185 return angle;
186 }
187
188 public void setDebug(boolean debug) {
189 _debug = debug;
190 }
191 }