LDMX Software
Tracking
src
Tracking
Digitization
CDFSiSensorSim.cxx
1
#include "Tracking/Digitization/CDFSiSensorSim.h"
2
3
/*
4
5
//TODO:: use ldmx logger instead
6
std::map<ChargeCarrier,SiElectrodeDataCollection> computeElectrodeData() {
7
8
if (debug_) {
9
10
//std::cout<<__PRETTY_FUNCTION__<<" sensor " <<std::endl;
11
//std::cout<<" Sense Strips: "
12
}
13
14
depositChargeOneSense();
15
transferChargeToReadout();
16
17
return readout_data_;
18
19
20
}
21
22
23
//Clear readout data
24
25
void clearReadout() {
26
27
for (auto pair : readout_data_) {
28
29
readout_data_[pair.first].clear();
30
}
31
}
32
33
//Clear sense data
34
void clearSense() {
35
36
for (auto pair : sense_dat_) {
37
sense_data[pair.first].clear();
38
}
39
40
}
41
42
//TODO Implement
43
void lorentzCorrect(const Acts::Vector3& position, const ChargeCarrier& carrier)
44
{
45
46
}
47
48
//TODO:: Implement
49
void depositChargeOnSense() {
50
//if (debug_)
51
// std::cout<<__PRETTY_FUNCTION__<<" depositChargeOnSense for sensor " <<
52
std:endl;
53
54
//for (auto& carrier : tracking::digitization::ChargeCarriers) {
55
56
57
//if (sensor_.hasElectrodesOnSide(carrier)) {
58
59
//Use local origin to compute the drift direction
60
//drift_direction_[carrier] = driftDirection(carrier,
61
Acts::Vector3(0.,0.,0.));
62
// }
63
//}
64
65
//Acts::Transform3 global_to_sensor =
66
sensor_.getGeometry().getGlobalToLocal();
67
//std::vector<ldmx::SimTrackerHit> hits = sensor_.getReadout().getHits();
68
69
for (auto& hit : hits) {
70
71
Acts::Vector3
72
hitPosition(hit.getPosition()[0],hit.getPosition()[1],hit.getPosition()[2]);
73
74
75
if (debug_) {
76
std::cout<<__PRETTY_FUNCTION__<<"Hit Point:
77
["<<hitPosition(0)<<","<<hitPosition(1)<<","<<hitPosition(2)<<std::endl;
78
79
}
80
81
TrackSegment track_segment = new TrackSegment(hit);
82
track_segment.transform(global_to_sensor);
83
84
int nsegments = 0;
85
86
for (auto& carrier : tracking::digitization::carriers) {
87
88
if (sensor_.hasElectrodeOnSide(carrier))
89
nsegments = std::max(nsegments, nSegments(track_segment, carrier,
90
deposition_granularity));
91
92
}
93
94
double segment_length = track_segment.getLength() / nsegments;
95
double segment_charge = (track_segment.getEloss() / nsegment ) /
96
sensor_.getBulk().ENERGY_EHPAIR;
97
98
Acts::Vector3 segment_step = segment_length *
99
track_segment.getDirection(); Acts::Vector3 segment_center =
100
track_segment.getP1() + (0.5 * segment_step);
101
102
if (debug_) {
103
std::cout<<"segment length " << segment_length << std::endl;
104
std::cout<<"segment charge " << segment_charge << std::endl;
105
std::cout<<"segment step " << segment_step << std::endl;
106
}
107
108
for ( int iseg = 0 ; iseg < nsegments; iseg++) {
109
if (debug_)
110
std::cout<<"segment "<< iseg<<" segment center"<<std::endl;
111
112
for (auto& carrier : tracking::digitization::carriers) {
113
114
if (sensor_.hasElectrodesOnSide(carrier)) {
115
116
SiSensorElectrodes electrodes = sensor_.getSenseElectrodes(carrier);
117
118
//Apply collection inefficiency for charge trapping: require between 0
119
and 1
120
121
double collection_efficiency = 1.0 - 10 * trapping_*
122
driftVector(segment_center,carrier).norm();
123
124
collection_efficiency = std::max(0.0,
125
std::min(1.0,collection_efficiency));
126
127
segment_charge *= collection_efficiency;
128
129
ChargeDistribution charge_distribution =
130
diffusionDistribution(segment_charge, segment_center, carrier);
131
charge_distribution.trasnform(electrodes.getParentToLocal());
132
133
std::map<int,int> sense_charge =
134
electrodes.computeElectrodeData(charge_distribution);
135
136
sense_data[carrier].add(SiElectrodeDataCollection(sense_charge,hit));
137
138
} // has electrodes
139
}//loop on carriers
140
}// loop on segments
141
}//loop on hits
142
}//deposit charge on sense
143
144
145
//Calculate charge distribution for carrier
146
ChargeDistribution diffusionDistribution(double segment_charge,
147
const Acts::Vector3& origin,
148
const ChargeCarrier& carrier) {
149
150
if (debug_)
151
std::cout<<__PRETTY_FUNCTION__<<" calculating charge distribution for
152
carrier"<<std::endl;
153
154
double distance = sensor_.distanceFromSide(origin, carrier);
155
double thickness = sensor_.getThickness();
156
157
if (distance < -distance_error_threshold || distance >
158
distance_error_threshold) { std::cout<<"ERROR::"<<__PRETTY_FUNCTION__<<"
159
Distance is outside of sensor by more than
160
"<<distance_error_threshold<<std::endl;
161
}
162
163
else if (distance < 0.)
164
distance = 0.;
165
else if (distance > thickness)
166
distance = thickness;
167
168
169
double bias_voltage = sensor_.getBiasVoltage();
170
double depletion_voltage = sensor_.getDepletionVoltage();
171
172
//Common factors
173
174
double deltaV = bias_voltage - depletionVoltage;
175
double sumV = bias_voltage + deplettionVoltage;
176
double common_factor = 2.0 * distance * depletion_voltage / thickness;
177
178
179
// Calculate charge spreading without magnetic field
180
181
double sigmaq = sensor_.getBulk().K_BOLTZMANN *
182
sensor_.getBulk().getTemperature() * thickness*thickness / depletion_voltage;
183
184
// If the bulk is n-type and the carrier are holes, then evaluate to true
185
// if the bulk is p-type and the carrier are electrons, then evaluate to true
186
// false otherwise
187
188
if (sensor_.getBulk().isNtype() == (carrier.getCharge() == 1 ))
189
sigmasq *= std::log(sumV / (sumV - common_factor));
190
else
191
sigmasq *= std::log((deltaV + common_factor) / deltaV);
192
193
double sigma = std::sqrt(sigmasq);
194
195
if (debug_)
196
std::cout<<__PRETTY_FUNCTION__<<" sigma = " << sigma<<std::endl;
197
198
// Corrections for magnetic field -- this is an approximation, may have to be
199
done better for high fields
200
201
// Special case if field is parallel to drift direction
202
203
Acts::Vector3 drift_direction = drift_direction[carrier];
204
Acts::Vector3 bias_surface_normal =
205
sensor_.getBiasSurface(carrier).getNormal();
206
207
Acts::Vector3 major_axis, minor_axis;
208
double major_axis_length, minor_axis_length;
209
210
double angular_tolerance = 1.e-9;
211
212
if ( (drift_direction.cross(bias_surface_normal)).norm() < angular_tolerance)
213
{
214
215
216
major_axis =
217
bias_surface_normal.cross(sensor_.getBiasSurface(carrier).getEdges().get(0).getDirection());
218
minor_axis = bias_surface_normal.cross(major_axis);
219
220
major_axis_length = sigma;
221
minor_axis_length = major_axis_length;
222
}
223
else {
224
225
Acts::Vector3 tmp = drift_direction_[carrier].cross(bias_surface_normal);
226
major_axis = bias_surface_normal.cross(tmp);
227
major_axis = major_axis / major_axis.norm();
228
229
minor_axis = bias_surface_normal.cross(major_axis);
230
231
// Project-to-plane would definitely be convenient here!!!
232
233
double cos_theta_lorentz =
234
drift_direction_[carrier].dot(bias_surface_normal);
235
236
//drift time correction
237
minor_axis_length = sigma * (1. / cos_theta_lorentz);
238
239
// + drift time correction
240
major_axis_length = minor_axis_length * (1. / cos_theta_lorentz);
241
242
}
243
244
major_axis = major_axis_length * major_axis;
245
minor_axis = minor_axis_length * minor_axis;
246
247
// FIXME: this has a Z component!!! (is that OK?? I think the whole thing
248
transforms into the electrode coordinates before integrating charge.)
249
250
Acts::Vector3 drift_destination = driftDestination(origin,carrier);
251
252
253
GaussianDistribution2D distribution(segment_charge,
254
drift_destination,major_axis,minor_axis);
255
256
return distribution;
257
258
}
259
260
*/
Generated by
1.9.8