CbmRoot
CbmStsSimSensorDssdOrtho.cxx
Go to the documentation of this file.
1 
7 
8 #include <cassert>
9 
10 #include "TGeoBBox.h"
11 #include "TGeoMatrix.h"
12 #include "TMath.h"
13 #include <TGeoPhysicalNode.h>
14 
15 #include "CbmMatch.h"
16 #include "CbmStsParSim.h"
17 #include "CbmStsPhysics.h"
18 #include "CbmStsSetup.h"
19 
20 
21 using namespace std;
22 
23 
24 // ----- Constructor ---------------------------------------------------
26  : CbmStsSimSensorDssd(element) {}
27 // -------------------------------------------------------------------------
28 
29 
30 // ----- Constructor ---------------------------------------------------
32  Double_t pitchF,
33  Int_t nStripsB,
34  Double_t pitchB,
35  CbmStsElement* element)
36  : CbmStsSimSensorDssd(element)
37  , fNofStrips {nStripsF, nStripsB}
38  , fPitch {pitchF, pitchB} {}
39 // -------------------------------------------------------------------------
40 
41 
42 // ----- Diffusion -----------------------------------------------------
44  Double_t y,
45  Double_t sigma,
46  Int_t side,
47  Double_t& fracL,
48  Double_t& fracC,
49  Double_t& fracR) {
50 
51  // Check side qualifier
52  assert(side == 0 || side == 1);
53 
54  // Coordinate at the readout edge (y = fDy/2 ).
55  // This x is counted from the left / bottom corner.
56  Double_t aRo = (side == 0 ? x + fDx / 2. : y + fDy / 2.);
57 
58  // Centre strip number
59  Int_t iStrip = TMath::FloorNint(aRo / fPitch[side]);
60 
61  // Strip boundaries at the readout edge
62  Double_t aLeftRo = Double_t(iStrip) * fPitch[side];
63  Double_t aRightRo = aLeftRo + fPitch[side];
64 
65  // Distance from strip boundaries across the strip
66  Double_t dLeft = aRo - aLeftRo;
67  Double_t dRight = aRightRo - aRo;
68 
69  // Charge fractions
70  // The value 0.707107 is 1/sqrt(2)
71  fracL = 0.;
72  if (dLeft < 3. * sigma)
73  fracL = 0.5 * (1. - TMath::Erf(0.707107 * dLeft / sigma));
74  fracR = 0.;
75  if (dRight < 3. * sigma)
76  fracR = 0.5 * (1. - TMath::Erf(0.707107 * dRight / sigma));
77  fracC = 1. - fracL - fracR;
78 
79  LOG(debug4) << GetName() << ": Distances to next strip " << dLeft << " / "
80  << dRight << ", charge fractions " << fracL << " / " << fracC
81  << " / " << fracR;
82 }
83 // -------------------------------------------------------------------------
84 
85 
86 // ----- Get channel number in module ----------------------------------
88  Int_t side,
89  Int_t) const {
90 
91  // --- Check side
92  assert(side == 0 || side == 1);
93 
94  // --- Account for front or back side
95  Int_t channel = strip;
96  if (side) channel += fNofStrips[0];
97 
98  return channel;
99 }
100 // -------------------------------------------------------------------------
101 
102 
103 // ----- Get strip number from coordinates -----------------------------
105  Double_t y,
106  Int_t side) const {
107 
108  // Cave: This implementation assumes that the centre of the sensor volume
109  // is also the centre of the active area, i.e. that the inactive borders
110  // (guard ring) are symmetric both and x and y (not necessarily the same
111  // in x and y).
112 
113  // Check side
114  assert(side == 0 || side == 1);
115 
116  // Check whether in active area (should have been caught before)
117  assert(TMath::Abs(x) < 0.5 * fDx);
118  assert(TMath::Abs(y) < 0.5 * fDy);
119 
120  // Calculate distance from lower left corner of the active area,
121  // in x for the front side, in y for the back side.
122  // Note: the coordinates are given w.r.t. the centre of the volume.
123  Double_t dist = (side == 0 ? x + 0.5 * fDx : y + 0.5 * fDy);
124 
125  // Calculate corresponding strip number
126  Int_t iStrip = TMath::FloorNint(dist / fPitch[side]);
127 
128  return iStrip;
129 }
130 // -------------------------------------------------------------------------
131 
132 
133 // ----- Initialise ----------------------------------------------------
135 
136  // Check whether parameters are assigned
137  if (fNofStrips[0] <= 0) {
138  LOG(error) << GetName() << ": Parameters are not set!";
139  return kFALSE;
140  }
141 
142  // Geometric shape of the sensor volume
143  assert(fElement);
144  TGeoPhysicalNode* node = fElement->GetPnode();
145  assert(node);
146  TGeoBBox* shape = dynamic_cast<TGeoBBox*>(node->GetShape());
147  assert(shape);
148 
149  // Active size in x coordinate
150  fDx = Double_t(fNofStrips[0]) * fPitch[0];
151  assert(fDx < 2. * shape->GetDX()); // The strips fit into the volume
152 
153  // Active size in y coordinate
154  fDy = Double_t(fNofStrips[1]) * fPitch[1];
155  assert(fDy < 2. * shape->GetDY());
156 
157  // Active size in z coordinate
158  fDz = 2. * shape->GetDZ();
159 
160  // Set size of charge arrays
161  fStripCharge[0].Set(fNofStrips[0]);
162  fStripCharge[1].Set(fNofStrips[1]);
163 
164  // Daisy chains are not allowed. Make sure that this is the only sensor
165  // connected to the module.
166  assert(GetSensorId() == 0);
167 
168  // --- Flag parameters to be set if test is OK
169  fIsSet = kTRUE;
170 
171  LOG(info) << ToString();
172 
173  return fIsSet;
174 }
175 // -------------------------------------------------------------------------
176 
177 
178 // ----- Modify the strip pitch ----------------------------------------
180 
181  assert(fIsSet); // Parameters should have been set before
182 
183  // Set new pitch and re-calculate number of strips on both sides
184  fPitch[0] = pitch;
185  fNofStrips[0] = Int_t(fDx / pitch);
186  fDx = Double_t(fNofStrips[0]) * pitch;
187  fPitch[1] = pitch;
188  fNofStrips[1] = Int_t(fDy / pitch);
189  fDy = Double_t(fNofStrips[1]) * pitch;
190 
191  // Set size of charge arrays
192  fStripCharge[0].Set(fNofStrips[0]);
193  fStripCharge[1].Set(fNofStrips[1]);
194 }
195 // -------------------------------------------------------------------------
196 
197 
198 // ----- Propagate charge to the readout strips ------------------------
200  Double_t y,
201  Double_t z,
202  Double_t charge,
203  Double_t bY,
204  Int_t side) {
205 
206  // Check side qualifier
207  assert(side == 0 || side == 1);
208 
209  Double_t xCharge = x;
210  Double_t yCharge = y;
211  Double_t zCharge = z;
212 
213  // Debug
214  LOG(debug4) << GetName() << ": Propagating charge " << charge << " from ("
215  << x << ", " << y << ", " << z << ") on side " << side
216  << " of sensor " << GetName();
217 
218  // Lorentz shift on the drift to the readout plane
219  if (fSettings->LorentzShift()) { xCharge += LorentzShift(z, side, bY); }
220 
221  LOG(debug4) << GetName() << ": After Lorentz shift: (" << xCharge << ", "
222  << yCharge << ", " << zCharge << ") cm";
223 
224  // Stop if the charge after Lorentz shift is not in the active area.
225  // Diffusion into the active area is not treated.
226  if (!IsInside(xCharge, yCharge)) {
227  LOG(debug4) << GetName() << ": Charge outside active area";
228  return;
229  }
230 
231  // No diffusion: all charge is in one strip
232  if (!fSettings->Diffusion()) {
233  Int_t iStrip = GetStripNumber(xCharge, yCharge, side);
234  fStripCharge[side][iStrip] += charge;
235  LOG(debug4) << GetName() << ": Adding charge " << charge << " to strip "
236  << iStrip;
237  } //? Do not use diffusion
238 
239  // Diffusion: charge is distributed over centre strip and neighbours
240  else {
241  // Calculate diffusion width
242  Double_t diffusionWidth =
243  CbmStsPhysics::DiffusionWidth(z + fDz / 2., // distance from back side
244  fDz,
245  GetConditions()->GetVbias(),
246  GetConditions()->GetVfd(),
247  GetConditions()->GetTemperature(),
248  side);
249  assert(diffusionWidth >= 0.);
250  LOG(debug4) << GetName() << ": Diffusion width = " << diffusionWidth
251  << " cm";
252  // Calculate charge fractions in strips
253  Double_t fracL = 0.; // fraction of charge in left neighbour
254  Double_t fracC = 1.; // fraction of charge in centre strip
255  Double_t fracR = 0.; // fraction of charge in right neighbour
256  Diffusion(xCharge, yCharge, diffusionWidth, side, fracL, fracC, fracR);
257  // Calculate strip numbers
258  // Note: In this implementation, charge can diffuse out of the sensitive
259  // area only for vertical strips. In case of stereo angle (cross-connection
260  // of strips), all charge is assigned to some strip, so the edge effects
261  // are not treated optimally.
262  Int_t iStripC = GetStripNumber(xCharge, yCharge, side); // centre strip
263  Int_t iStripL = iStripC - 1; // left neighbour
264  Int_t iStripR = iStripC + 1; // right neighbour
265  // Collect charge on the readout strips
266  if (fracC > 0.) {
267  fStripCharge[side][iStripC] += charge * fracC; // centre strip
268  LOG(debug4) << GetName() << ": Adding charge " << charge * fracC
269  << " to strip " << iStripC;
270  }
271  if (fracL > 0. && iStripL >= 0) {
272  fStripCharge[side][iStripL] += charge * fracL; // right neighbour
273  LOG(debug4) << GetName() << ": Adding charge " << charge * fracL
274  << " to strip " << iStripL;
275  }
276  if (fracR > 0. && iStripR < fNofStrips[side]) {
277  fStripCharge[side][iStripR] += charge * fracR; // left neighbour
278  LOG(debug4) << GetName() << ": Adding charge " << charge * fracR
279  << " to strip " << iStripR;
280  }
281  } //? Use diffusion
282 }
283 // -------------------------------------------------------------------------
284 
285 
286 // ----- Set internal sensor parameters --------------------------------
288  Double_t pitchF,
289  Int_t nStripsB,
290  Double_t pitchB) {
291 
292  // Geometric shape of the sensor volume
293  assert(fElement);
294  TGeoPhysicalNode* node = fElement->GetPnode();
295  TGeoBBox* shape = dynamic_cast<TGeoBBox*>(node->GetShape());
296 
297  // Active size in x coordinate
298  fDx = Double_t(nStripsF) * pitchF;
299  assert(fDx < 2. * shape->GetDX()); // The strips fit into the volume
300 
301  // Active size in y coordinate
302  fDy = Double_t(nStripsB) * pitchB;
303  assert(fDy < 2. * shape->GetDY());
304 
305  // Active size in z coordinate
306  fDz = 2. * shape->GetDZ();
307 
308  // Number of strips, pitch and stereo angles
309  fNofStrips[0] = nStripsF;
310  fPitch[0] = pitchF;
311  fNofStrips[1] = nStripsB;
312  fPitch[1] = pitchB;
313 
314  // Set size of charge arrays
315  fStripCharge[0].Set(fNofStrips[0]);
316  fStripCharge[1].Set(fNofStrips[1]);
317 
318  // Daisy chains are not allowed. Make sure that this is the only sensor
319  // connected to the module.
320  assert(GetSensorId() == 0);
321 
322  // --- Flag parameters to be set if test is OK
323  fIsSet = kTRUE;
324 
325  return fIsSet;
326 }
327 // -------------------------------------------------------------------------
328 
329 
330 // ----- String output -------------------------------------------------
332  stringstream ss;
333  assert(fElement);
334  ss << fElement->GetName() << " (DssdOrtho): ";
335  TGeoPhysicalNode* node = fElement->GetPnode();
336  if (!node)
337  ss << "no node assigned; ";
338  else {
339  ss << "Dimension (" << fDx << ", " << fDy << ", " << fDz << ") cm, ";
340  ss << "# strips " << fNofStrips[0] << "/" << fNofStrips[1] << ", ";
341  ss << "pitch " << fPitch[0] << "/" << fPitch[1] << " cm, ";
342  }
343  return ss.str();
344 }
345 // -------------------------------------------------------------------------
346 
CbmStsSimSensorDssdOrtho::fNofStrips
Int_t fNofStrips[2]
Number of strips on front/back side.
Definition: CbmStsSimSensorDssdOrtho.h:108
CbmStsSetup.h
CbmStsSimSensorDssd::fIsSet
Bool_t fIsSet
Flag whether sensor is properly initialised.
Definition: CbmStsSimSensorDssd.h:93
CbmStsSimSensorDssdOrtho::GetStripNumber
virtual Int_t GetStripNumber(Double_t x, Double_t y, Int_t side) const
Get strip number from point coordinates.
Definition: CbmStsSimSensorDssdOrtho.cxx:104
CbmStsSimSensorDssdOrtho::Init
virtual Bool_t Init()
Initialisation @value kTRUE if parameters and node are consistent.
Definition: CbmStsSimSensorDssdOrtho.cxx:134
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
CbmMatch.h
CbmStsSimSensorDssdOrtho::PropagateCharge
virtual void PropagateCharge(Double_t x, Double_t y, Double_t z, Double_t charge, Double_t bY, Int_t side)
Definition: CbmStsSimSensorDssdOrtho.cxx:199
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
CbmStsSimSensorDssdOrtho::ModifyStripPitch
virtual void ModifyStripPitch(Double_t pitch)
Modify the strip pitch.
Definition: CbmStsSimSensorDssdOrtho.cxx:179
CbmStsParSim.h
CbmStsSimSensorDssdOrtho::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: CbmStsSimSensorDssdOrtho.cxx:87
CbmStsSimSensorDssd::IsInside
Bool_t IsInside(Double_t x, Double_t y)
Definition: CbmStsSimSensorDssd.cxx:130
CbmStsSimSensorDssdOrtho::SetParameters
Bool_t SetParameters(Int_t nStripsF, Double_t pitchF, Int_t nStripsB, Double_t pitchB)
Set the internal sensor parameters.
Definition: CbmStsSimSensorDssdOrtho.cxx:287
CbmStsPhysics.h
ClassImp
ClassImp(CbmConverterManager) InitStatus CbmConverterManager
Definition: CbmConverterManager.cxx:12
CbmStsSimSensorDssdOrtho::fPitch
Double_t fPitch[2]
Strip pitch front/back side [cm].
Definition: CbmStsSimSensorDssdOrtho.h:109
CbmStsSimSensorDssd
Abstract class for the simulation of double-sided silicon strip sensors.
Definition: CbmStsSimSensorDssd.h:45
shape
UInt_t shape
Definition: CbmMvdSensorDigiToHitTask.cxx:73
CbmStsSimSensorDssdOrtho
Detector response for DSSD sensors with orthogonal strips.
Definition: CbmStsSimSensorDssdOrtho.h:27
CbmStsParSim::LorentzShift
Bool_t LorentzShift() const
Check whether Lorentz shift is applied.
Definition: CbmStsParSim.h:76
x
Double_t x
Definition: CbmMvdSensorDigiToHitTask.cxx:68
y
Double_t y
Definition: CbmMvdSensorDigiToHitTask.cxx:68
CbmStsSimSensorDssdOrtho::ToString
std::string ToString() const
Definition: CbmStsSimSensorDssdOrtho.cxx:331
CbmStsParSim::Diffusion
Bool_t Diffusion() const
Check whether diffusion is applied.
Definition: CbmStsParSim.h:51
CbmStsSimSensor::GetSensorId
Int_t GetSensorId() const
Sensor ID.
Definition: CbmStsSimSensor.cxx:44
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
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
CbmStsSimSensorDssdOrtho::CbmStsSimSensorDssdOrtho
CbmStsSimSensorDssdOrtho(CbmStsElement *element=nullptr)
Standard constructor.
Definition: CbmStsSimSensorDssdOrtho.cxx:25
CbmStsSimSensorDssdOrtho.h
CbmStsSimSensorDssdOrtho::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)
Definition: CbmStsSimSensorDssdOrtho.cxx:43