CbmRoot
CbmStsSimSensorDssdStereo.cxx
Go to the documentation of this file.
1 
7 
8 #include <TGeoBBox.h>
9 #include <TGeoPhysicalNode.h>
10 #include <TMath.h>
11 
12 #include <FairLogger.h>
13 
14 #include "CbmStsElement.h"
15 #include "CbmStsParSensorCond.h"
16 #include "CbmStsParSim.h"
17 #include "CbmStsPhysics.h"
18 
19 
20 using std::stringstream;
21 
22 
23 // ----- Constructor ---------------------------------------------------
25  : CbmStsSimSensorDssd(element) {}
26 // -------------------------------------------------------------------------
27 
28 
29 // ----- Constructor ---------------------------------------------------
31  Int_t nStrips,
32  Double_t pitch,
33  Double_t stereoF,
34  Double_t stereoB,
35  CbmStsElement* element)
36  : CbmStsSimSensorDssd(element)
37  , fNofStrips(nStrips)
38  , fPitch(pitch)
39  , fStereoF(stereoF)
40  , fStereoB(stereoB)
41  , fTanStereo()
42  , fCosStereo()
43  , fStripShift()
44  , fErrorFac(0.) {
45  fDy = dy;
46 }
47 // -------------------------------------------------------------------------
48 
49 
50 // ----- Diffusion -----------------------------------------------------
52  Double_t y,
53  Double_t sigma,
54  Int_t side,
55  Double_t& fracL,
56  Double_t& fracC,
57  Double_t& fracR) {
58 
59  // Check side qualifier
60  assert(side == 0 || side == 1);
61 
62  // x coordinate at the readout edge (y = fDy/2 )
63  // This x is counted from the left edge.
64  Double_t xRo = x + fDx / 2. - (fDy / 2. - y) * fTanStereo[side];
65 
66  // Centre strip number (w/o cross connection; may be negative or large than
67  // the number of strips)
68  Int_t iStrip = TMath::FloorNint(xRo / fPitch);
69 
70  // Strip boundaries at the readout edge (y = fDy/2)
71  Double_t xLeftRo = Double_t(iStrip) * fPitch;
72  Double_t xRightRo = xLeftRo + fPitch;
73 
74  // Distance from strip boundaries across the strip
75  Double_t dLeft = (xRo - xLeftRo) * fCosStereo[side];
76  Double_t dRight = (xRightRo - xRo) * fCosStereo[side];
77 
78  // Charge fractions
79  // The value 0.707107 is 1/sqrt(2)
80  fracL = 0.;
81  if (dLeft < 3. * sigma)
82  fracL = 0.5 * (1. - TMath::Erf(0.707107 * dLeft / sigma));
83  fracR = 0.;
84  if (dRight < 3. * sigma)
85  fracR = 0.5 * (1. - TMath::Erf(0.707107 * dRight / sigma));
86  fracC = 1. - fracL - fracR;
87 }
88 // -------------------------------------------------------------------------
89 
90 
91 // ----- Get channel number in module ----------------------------------
93  Int_t side,
94  Int_t sensorId) const {
95 
96  // --- Check side argument
97  assert(side == 0 || side == 1);
98 
99  // --- Account for offset due to stereo angle
100  Int_t channel = strip - sensorId * fStripShift[side];
101 
102  // --- Account for horizontal cross-connection of strips
103  while (channel < 0)
104  channel += fNofStrips;
105  while (channel >= fNofStrips)
106  channel -= fNofStrips;
107 
108  // --- Account for front or back side
109  if (side) channel += fNofStrips;
110 
111  return channel;
112 }
113 // -------------------------------------------------------------------------
114 
115 
116 // ----- Get strip number from coordinates -----------------------------
118  Double_t y,
119  Int_t side) const {
120 
121  // Cave: This implementation assumes that the centre of the sensor volume
122  // is also the centre of the active area, i.e. that the inactive borders
123  // (guard ring) are symmetric both and x and y (not necessarily the same
124  // in x and y).
125 
126  // Check side
127  assert(side == 0 || side == 1);
128 
129  // Check whether in active area (should have been caught before)
130  assert(TMath::Abs(x) <= fDx / 2.);
131  assert(TMath::Abs(y) <= fDy / 2.);
132 
133  // Calculate distance from lower left corner of the active area.
134  // Note: the coordinates are given w.r.t. the centre of the volume.
135  Double_t xdist = x + 0.5 * fDx;
136  Double_t ydist = y + 0.5 * fDy;
137 
138  // Project coordinates to readout (top) edge
139  Double_t xro = xdist - (fDy - ydist) * fTanStereo[side];
140 
141  // Calculate corresponding strip number
142  Int_t iStrip = TMath::FloorNint(xro / fPitch);
143 
144  // Account for horizontal cross-connection of strips
145  // not extending to the top edge
146  while (iStrip < 0)
147  iStrip += fNofStrips;
148  while (iStrip >= fNofStrips)
149  iStrip -= fNofStrips;
150 
151  return iStrip;
152 }
153 // -------------------------------------------------------------------------
154 
155 
156 // ----- Initialise ----------------------------------------------------
158 
159  // Check presence of node
160  assert(fElement);
161  TGeoPhysicalNode* node = fElement->GetPnode();
162  assert(node);
163 
164  // Check whether parameters are assigned
165  assert(fNofStrips > 0);
166 
167  // Geometric shape of the sensor volume
168  TGeoBBox* shape = dynamic_cast<TGeoBBox*>(node->GetShape());
169  assert(shape);
170 
171  // Active size in x coordinate
172  fDx = Double_t(fNofStrips) * fPitch;
173  assert(fDx < 2. * shape->GetDX());
174 
175  // Active size in y coordinate
176  assert(fDy < 2. * shape->GetDY());
177 
178  // Active size in z coordinate
179  fDz = 2. * shape->GetDZ();
180 
181  // Stereo angle front side must be between -85 and 85 degrees
182  assert(TMath::Abs(fStereoF) < 85.);
183 
184  // Stereo angle back side must be between -85 and 85 degrees
185  assert(TMath::Abs(fStereoB) < 85.);
186 
187  // Derived variables
188  fTanStereo[0] = TMath::Tan(fStereoF * TMath::DegToRad());
189  fCosStereo[0] = TMath::Cos(fStereoF * TMath::DegToRad());
190  fStripShift[0] = TMath::Nint(fDy * fTanStereo[0] / fPitch);
191  fTanStereo[1] = TMath::Tan(fStereoB * TMath::DegToRad());
192  fCosStereo[1] = TMath::Cos(fStereoB * TMath::DegToRad());
193  fStripShift[1] = TMath::Nint(fDy * fTanStereo[1] / fPitch);
194 
195  // Set size of charge arrays
196  fStripCharge[0].Set(fNofStrips);
197  fStripCharge[1].Set(fNofStrips);
198 
199  // Factor for the hit position error
200  fErrorFac =
201  1. / (fTanStereo[1] - fTanStereo[0]) / (fTanStereo[1] - fTanStereo[0]);
202 
203  // --- Flag parameters to be set if test is OK
204  fIsSet = kTRUE;
205 
206  return fIsSet;
207 }
208 // -------------------------------------------------------------------------
209 
210 
211 // ----- Modify the strip pitch ----------------------------------------
213 
214  assert(fIsSet); // Parameters should have been set before
215 
216  // Set new pitch and re-calculate number of strips
217  fPitch = pitch;
218  fNofStrips = Int_t(fDx / pitch);
219  fDx = Double_t(fNofStrips) * pitch;
220 
221  // Set size of charge arrays
222  fStripCharge[0].Set(fNofStrips);
223  fStripCharge[1].Set(fNofStrips);
224 }
225 // -------------------------------------------------------------------------
226 
227 
228 // ----- Propagate charge to the readout strips ------------------------
230  Double_t y,
231  Double_t z,
232  Double_t charge,
233  Double_t bY,
234  Int_t side) {
235 
236  // Check side qualifier
237  assert(side == 0 || side == 1);
238 
239  Double_t xCharge = x;
240  Double_t yCharge = y;
241 
242  // Lorentz shift on the drift to the readout plane
243  if (fSettings->LorentzShift()) { xCharge += LorentzShift(z, side, bY); }
244 
245  // Stop if the charge after Lorentz shift is not in the active area.
246  // Diffusion into the active area is not treated.
247  if (!IsInside(xCharge, yCharge)) { return; }
248 
249  // No diffusion: all charge is in one strip
250  if (!fSettings->Diffusion()) {
251  Int_t iStrip = GetStripNumber(xCharge, yCharge, side);
252  fStripCharge[side][iStrip] += charge;
253  } //? Do not use diffusion
254 
255  // Diffusion: charge is distributed over centre strip and neighbours
256  else {
257  // Calculate diffusion width
258  Double_t diffusionWidth =
259  CbmStsPhysics::DiffusionWidth(z + fDz / 2., // distance from back side
260  fDz,
261  GetConditions()->GetVbias(),
262  GetConditions()->GetVfd(),
263  GetConditions()->GetTemperature(),
264  side);
265  assert(diffusionWidth >= 0.);
266  // Calculate charge fractions in strips
267  Double_t fracL = 0.; // fraction of charge in left neighbour
268  Double_t fracC = 1.; // fraction of charge in centre strip
269  Double_t fracR = 0.; // fraction of charge in right neighbour
270  Diffusion(xCharge, yCharge, diffusionWidth, side, fracL, fracC, fracR);
271  // Calculate strip numbers
272  // Note: In this implementation, charge can diffuse out of the sensitive
273  // area only for vertical strips. In case of stereo angle (cross-connection
274  // of strips), all charge is assigned to some strip, so the edge effects
275  // are not treated optimally.
276  Int_t iStripC = GetStripNumber(xCharge, yCharge, side); // centre strip
277  Int_t iStripL = 0; // left neighbour
278  Int_t iStripR = 0; // right neighbour
279  if (fTanStereo[side] < 0.0001) { // vertical strips, no cross connection
280  iStripL = iStripC - 1; // might be = -1
281  iStripR = iStripC + 1; // might be = nOfStrips
282  } else { // stereo angle, cross connection
283  iStripL = (iStripC == 0 ? fNofStrips - 1 : iStripC - 1);
284  iStripR = (iStripC == fNofStrips - 1 ? 0 : iStripC + 1);
285  }
286  // Collect charge on the readout strips
287  if (fracC > 0.) {
288  fStripCharge[side][iStripC] += charge * fracC; // centre strip
289  }
290  if (fracL > 0. && iStripL >= 0) {
291  fStripCharge[side][iStripL] += charge * fracL; // right neighbour
292  }
293  if (fracR > 0. && iStripR < fNofStrips) {
294  fStripCharge[side][iStripR] += charge * fracR; // left neighbour
295  }
296  } //? Use diffusion
297 }
298 // -------------------------------------------------------------------------
299 
300 
301 // ----- String output -------------------------------------------------
303  stringstream ss;
304  assert(fElement);
305  ss << fElement->GetName() << " (DssdStereo): ";
306  TGeoPhysicalNode* node = fElement->GetPnode();
307  if (!node)
308  ss << "no node assigned; ";
309  else {
310  TGeoBBox* shape = dynamic_cast<TGeoBBox*>(node->GetShape());
311  assert(shape);
312  ss << "Dimension (" << 2. * shape->GetDX() << ", " << 2. * shape->GetDY()
313  << ", " << 2. * shape->GetDZ() << ") cm, ";
314  }
315  ss << "dy " << fDy << " cm, ";
316  ss << "# strips " << fNofStrips << ", pitch " << fPitch << " cm, ";
317  ss << "stereo " << fStereoF << "/" << fStereoB << " degrees";
318  if (fConditions) ss << "\n\t Conditions: " << fConditions->ToString();
319  return ss.str();
320 }
321 // -------------------------------------------------------------------------
322 
323 
CbmStsSimSensorDssdStereo::GetStripNumber
virtual Int_t GetStripNumber(Double_t x, Double_t y, Int_t side) const
Get strip number from point coordinates.
Definition: CbmStsSimSensorDssdStereo.cxx:117
CbmStsSimSensorDssdStereo::fStripShift
Int_t fStripShift[2]
cosine of stereo angle front/back side
Definition: CbmStsSimSensorDssdStereo.h:125
CbmStsSimSensorDssd::fIsSet
Bool_t fIsSet
Flag whether sensor is properly initialised.
Definition: CbmStsSimSensorDssd.h:93
CbmStsSimSensor::fSettings
const CbmStsParSim * fSettings
Simulation module.
Definition: CbmStsSimSensor.h:168
CbmStsSimSensorDssd::fStripCharge
TArrayD fStripCharge[2]
Definition: CbmStsSimSensorDssd.h:97
CbmStsSimSensor::GetConditions
const CbmStsParSensorCond * GetConditions() const
Sensor conditions.
Definition: CbmStsSimSensor.h:63
CbmStsSimSensorDssd::LorentzShift
Double_t LorentzShift(Double_t z, Int_t chargeType, Double_t bY) const
Lorentz shift in the x coordinate.
Definition: CbmStsSimSensorDssd.cxx:141
CbmStsParSensorCond.h
CbmStsSimSensorDssd::fDy
Double_t fDy
Dimension of active area in y [cm].
Definition: CbmStsSimSensorDssd.h:91
CbmStsElement::GetPnode
TGeoPhysicalNode * GetPnode() const
Definition: CbmStsElement.h:106
CbmStsSimSensorDssdStereo::ToString
std::string ToString() const
String output.
Definition: CbmStsSimSensorDssdStereo.cxx:302
CbmStsSimSensorDssdStereo
Detector response for DSSD sensors with stereo angles and cross-connection by double metal layers.
Definition: CbmStsSimSensorDssdStereo.h:40
CbmStsParSim.h
CbmStsSimSensorDssdStereo::fNofStrips
Int_t fNofStrips
Number of strips (same for front and back)
Definition: CbmStsSimSensorDssdStereo.h:117
CbmStsSimSensorDssdStereo::fTanStereo
Double_t fTanStereo[2]
Definition: CbmStsSimSensorDssdStereo.h:123
CbmStsSimSensorDssdStereo::fPitch
Double_t fPitch
Strip pitch /same for front and back)
Definition: CbmStsSimSensorDssdStereo.h:118
CbmStsSimSensorDssdStereo::Diffusion
virtual void Diffusion(Double_t x, Double_t y, Double_t sigma, Int_t side, Double_t &fracL, Double_t &fracC, Double_t &fracR)
Used for calculation of hit errors.
Definition: CbmStsSimSensorDssdStereo.cxx:51
CbmStsSimSensorDssd::IsInside
Bool_t IsInside(Double_t x, Double_t y)
Definition: CbmStsSimSensorDssd.cxx:130
CbmStsSimSensorDssdStereo::fCosStereo
Double_t fCosStereo[2]
tangent of stereo angle front/back side
Definition: CbmStsSimSensorDssdStereo.h:124
CbmStsPhysics.h
CbmStsParSensorCond::ToString
std::string ToString() const
String output.
Definition: CbmStsParSensorCond.cxx:151
CbmStsElement.h
ClassImp
ClassImp(CbmConverterManager) InitStatus CbmConverterManager
Definition: CbmConverterManager.cxx:12
CbmStsSimSensorDssdStereo::Init
virtual Bool_t Init()
Initialisation @value kTRUE if parameters and node are consistent.
Definition: CbmStsSimSensorDssdStereo.cxx:157
CbmStsSimSensorDssdStereo::fStereoF
Double_t fStereoF
Stereo angle front side [degrees].
Definition: CbmStsSimSensorDssdStereo.h:119
CbmStsSimSensor::fConditions
const CbmStsParSensorCond * fConditions
Simulation settings.
Definition: CbmStsSimSensor.h:170
CbmStsSimSensorDssdStereo.h
CbmStsSimSensorDssd
Abstract class for the simulation of double-sided silicon strip sensors.
Definition: CbmStsSimSensorDssd.h:45
CbmStsSimSensorDssdStereo::CbmStsSimSensorDssdStereo
CbmStsSimSensorDssdStereo(CbmStsElement *element=nullptr)
Definition: CbmStsSimSensorDssdStereo.cxx:24
shape
UInt_t shape
Definition: CbmMvdSensorDigiToHitTask.cxx:73
CbmStsSimSensorDssdStereo::PropagateCharge
virtual void PropagateCharge(Double_t x, Double_t y, Double_t z, Double_t charge, Double_t bY, Int_t side)
Definition: CbmStsSimSensorDssdStereo.cxx:229
CbmStsSimSensorDssdStereo::fStereoB
Double_t fStereoB
Stereo angle front back side [degrees].
Definition: CbmStsSimSensorDssdStereo.h:120
CbmStsParSim::LorentzShift
Bool_t LorentzShift() const
Check whether Lorentz shift is applied.
Definition: CbmStsParSim.h:76
x
Double_t x
Definition: CbmMvdSensorDigiToHitTask.cxx:68
CbmStsSimSensorDssdStereo::fErrorFac
Double_t fErrorFac
Shift in number of strips from bottom to top.
Definition: CbmStsSimSensorDssdStereo.h:126
y
Double_t y
Definition: CbmMvdSensorDigiToHitTask.cxx:68
CbmStsParSim::Diffusion
Bool_t Diffusion() const
Check whether diffusion is applied.
Definition: CbmStsParSim.h:51
CbmStsPhysics::DiffusionWidth
static Double_t DiffusionWidth(Double_t z, Double_t d, Double_t vBias, Double_t vFd, Double_t temperature, Int_t chargeType)
Definition: CbmStsPhysics.cxx:58
CbmStsSimSensorDssd::fDz
Double_t fDz
Thickness in z [cm].
Definition: CbmStsSimSensorDssd.h:92
CbmStsSimSensor::fElement
CbmStsElement * fElement
Definition: CbmStsSimSensor.h:166
CbmStsSimSensorDssdStereo::GetModuleChannel
virtual Int_t GetModuleChannel(Int_t strip, Int_t side, Int_t sensorId) const
Get the readout channel in the module for a given strip.
Definition: CbmStsSimSensorDssdStereo.cxx:92
CbmStsElement
Class representing an element of the STS setup.
Definition: CbmStsElement.h:32
CbmStsSimSensorDssd::fDx
Double_t fDx
Dimension of active area in x [cm].
Definition: CbmStsSimSensorDssd.h:90
CbmStsSimSensorDssdStereo::ModifyStripPitch
virtual void ModifyStripPitch(Double_t pitch)
Modify the strip pitch.
Definition: CbmStsSimSensorDssdStereo.cxx:212