BmnRoot
Loading...
Searching...
No Matches
BmnSsdStation.cxx
Go to the documentation of this file.
1
8#include "BmnSsdStation.h"
9
10#include <cassert>
11#include <sstream>
12#include "TGeoBBox.h"
13#include "TGeoManager.h"
14#include "TGeoMatrix.h"
15#include "TGeoVolume.h"
16#include "BmnSsdSensor.h"
17#include "BmnSsdSensorDssd.h"
19
20using std::stringstream;
21using std::string;
22
23
24// ----- Default constructor -------------------------------------------
26 TNamed(),
27 fZ(0.),
28 fXmin(0.), fXmax(0.), fYmin(0.), fYmax(0.), fSensorD(0.), fSensorRot(0.),
29 fNofSensors(0),
30 fDiffSensorD(kFALSE),
31 fFirstSensor(NULL),
32 fNode(NULL),
33 fLadders()
34{
35}
36// -------------------------------------------------------------------------
37
38
39
40// ----- Standard constructor ------------------------------------------
41BmnSsdStation::BmnSsdStation(const char* name, const char* title,
42 TGeoPhysicalNode* node) :
43 TNamed(name, title),
44 fZ(0.),
45 fXmin(0.), fXmax(0.), fYmin(0.), fYmax(0.), fSensorD(0.), fSensorRot(0.),
46 fNofSensors(0),
47 fDiffSensorD(kFALSE),
48 fFirstSensor(NULL),
49 fNode(node),
50 fLadders()
51{
52}
53// -------------------------------------------------------------------------
54
55
56
57// ----- Destructor ----------------------------------------------------
60// -------------------------------------------------------------------------
61
62
63// ----- Add a ladder to the station -----------------------------------
65
66 // Check whether argument really is a ladder
67 assert(ladder);
68 assert(ladder->GetLevel() == kSsdLadder);
69
70 // Add to daughter array
71 fLadders.push_back(ladder);
72
73}
74// -------------------------------------------------------------------------
75
76
77// ----- Initialise the station properties from sensors ----------------
78void BmnSsdStation::CheckSensorProperties() {
79
80 Int_t nSensors = 0; // sensor counter
81 Double_t zMin = 999999.; // sensor z minimum
82 Double_t zMax = -999999.; // sensor z maximum
83
84 // --- Loop over ladders
85 for (UInt_t iLad = 0; iLad < fLadders.size(); iLad++) {
86 BmnSsdElement* ladd = fLadders.at(iLad);
87
88 // --- Loop over half-ladders
89 for (Int_t iHla = 0; iHla < ladd->GetNofDaughters(); iHla++) {
90 BmnSsdElement* hlad = ladd->GetDaughter(iHla);
91
92 // --- Loop over modules
93 for (Int_t iMod = 0; iMod < hlad->GetNofDaughters(); iMod++) {
94 BmnSsdElement* modu = hlad->GetDaughter(iMod);
95
96 // --- Loop over sensors
97 for (Int_t iSen = 0; iSen < modu->GetNofDaughters(); iSen++) {
98 BmnSsdSensor* sensor =
99 dynamic_cast<BmnSsdSensor*>(modu->GetDaughter(iSen));
100
101 // Set first sensor
102 if ( ! nSensors ) fFirstSensor = sensor;
103
104 // Get sensor z position
105 TGeoPhysicalNode* sensorNode = sensor->GetPnode();
106 // --- Transform sensor centre into global C.S.
107 Double_t local[3] = {0., 0., 0.}; // sensor centre, local c.s.
108 Double_t global[3]; // sensor centre, global c.s.
109 sensorNode->GetMatrix()->LocalToMaster(local, global);
110 if ( ! nSensors ) { // first sensor
111 zMin = global[2];
112 zMax = global[2];
113 }
114 else {
115 zMin = TMath::Min(zMin, global[2]);
116 zMax = TMath::Max(zMax, global[2]);
117 }
118
119 // Get sensor thickness
120 TGeoBBox* sBox = dynamic_cast<TGeoBBox*>(sensorNode->GetShape());
121 if ( ! sBox )
122 LOG(fatal) << GetName() << ": sensor shape is not a box!";
123 Double_t sD = 2. * sBox->GetDZ();
124 if ( ! nSensors ) fSensorD = sD; // first sensor
125 else {
126 if ( TMath::Abs(sD - fSensorD) > 0.0001 )
127 fDiffSensorD = kTRUE;
128 }
129
130 nSensors++;
131 } // # sensors
132 } // # modules
133 } // # half-ladders
134 } // # ladders
135
136 fZ = 0.5 * (zMin + zMax);
137 fNofSensors = nSensors;
138}
139// -------------------------------------------------------------------------
140
141
142
143// ----- Strip pitch --------------------------------------------------
144Double_t BmnSsdStation::GetSensorPitch(Int_t side) const {
145
146 assert( side == 0 || side == 1);
147
148 if ( ! fFirstSensor ) {
149 LOG(WARNING) << GetName() << ": No sensors connected to station!";
150 return 0.;
151 }
152
153 // Action only for Dssd sensors
154 BmnSsdSensorDssd* sensor = dynamic_cast<BmnSsdSensorDssd*>(fFirstSensor);
155 Double_t pitch = -1.;
156 if ( sensor ) pitch = sensor->GetPitch(side);
157 else {
158 LOG(WARNING) << GetName() << ": Cannot get pitch for non-Dssd sensor.";
159 }
160
161 return pitch;
162}
163// -------------------------------------------------------------------------
164
165
166
167// ----- Stereo angle -------------------------------------------------
168Double_t BmnSsdStation::GetSensorStereoAngle(Int_t side) const {
169
170 assert ( side == 0 || side == 1);
171
172 if ( ! fFirstSensor ) {
173 LOG(WARNING) << GetName() << ": No sensors connected to station!";
174 return 0.;
175 }
176
177 // Action only for Dssd sensors
178 BmnSsdSensorDssdStereo* sensor =
179 dynamic_cast<BmnSsdSensorDssdStereo*>(fFirstSensor);
180 Double_t stereo = 0.;
181 if ( sensor ) stereo = sensor->GetStereoAngle(side);
182 else {
183 LOG(WARNING) << GetName()
184 << ": Cannot get stereo angle for non-DssdStereo sensor.";
185 }
186
187 return stereo;
188}
189// -------------------------------------------------------------------------
190
191
192
193// ----- Initialise station parameters ---------------------------------
195
196 // Determine x and y extensions of the station, in case it is present
197 // as TGeoNode (for old geometries). This implementation assumes that
198 // the shape of the station volume derives from TGeoBBox and that it is
199 // not rotated in the global c.s.
200 if ( fNode ) {
201 TGeoBBox* box = dynamic_cast<TGeoBBox*>(fNode->GetShape());
202 if ( ! box )
203 LOG(fatal) << GetName() << ": shape is not box! ";
204 Double_t local[3] = { 0., 0., 0.};
205 Double_t global[3];
206 fNode->GetMatrix()->LocalToMaster(local, global);
207 fXmin = global[0] - box->GetDX();
208 fXmax = global[0] + box->GetDX();
209 fYmin = global[1] - box->GetDY();
210 fYmax = global[1] + box->GetDY();
211 }
212
213 // For new geometries with units instead of stations, the station element
214 // is not a node in the geometry. To obtain its extensions in x and y,
215 // a station volume is transiently made as TGeoVolumeAssembly, composed
216 // of its ladder daughters.
217 else {
218 TGeoVolumeAssembly* statVol = new TGeoVolumeAssembly("myStation");
219 for (UInt_t iLadder = 0; iLadder < fLadders.size(); iLadder++) {
220 TGeoVolume* ladVol = fLadders.at(iLadder)->GetPnode()->GetVolume();
221 TGeoHMatrix* ladMat = fLadders.at(iLadder)->GetPnode()->GetMatrix();
222 statVol->AddNode(ladVol, iLadder, ladMat);
223 } // # ladders in station
224 statVol->GetShape()->ComputeBBox();
225 TGeoBBox* statShape = dynamic_cast<TGeoBBox*>(statVol->GetShape());
226 const Double_t* origin = statShape->GetOrigin();
227 fXmin = origin[0] - statShape->GetDX();
228 fXmax = origin[0] + statShape->GetDX();
229 fYmin = origin[1] - statShape->GetDY();
230 fYmax = origin[1] + statShape->GetDY();
231 }
232
233 // The z position of the station is obtained from the sensor positions,
234 // not from the station node. This is more flexible, because it does not
235 // assume the station to be symmetric.
236 CheckSensorProperties();
237
238 // Warning if varying sensor properties are found
239 if ( fDiffSensorD )
240 LOG(WARNING) << GetName() << ": Different values for sensor thickness!";
241
242 // Determine the rotation (in x-y) of the first sensor
243 assert(fFirstSensor);
244 TGeoPhysicalNode* sensorNode = fFirstSensor->GetNode();
245 assert(sensorNode);
246 // Transform unit vector on local x axis into global c.s.
247 Double_t unitLocal[3] = {1., 0., 0.};
248 Double_t unitGlobal[3];
249 sensorNode->GetMatrix()->LocalToMaster(unitLocal, unitGlobal);
250 // Subtract translation vector of local origin
251 Double_t* translation = sensorNode->GetMatrix()->GetTranslation();
252 unitGlobal[0] -= translation[0];
253 unitGlobal[1] -= translation[1];
254 unitGlobal[2] -= translation[2];
255 // Calculate angle between unit x vector in global and local c.s.
256 fSensorRot = atan2(unitGlobal[1], unitGlobal[0]);
257
258}
259// --------------------------------------------------------------------------
260
261
262
263// ----- Info -----------------------------------------------------------
265{
266 stringstream ss;
267 ss << GetName() << ": " << fNofSensors << " sensors, z = " << fZ
268 << " cm, x = " << fXmin << " to " << fXmax << " cm, y = " << fYmin
269 << " to " << fYmax << " cm " << "\n\t\t"
270 << " rotation " << fSensorRot * 180. / 3.1415927 << " degrees,"
271 << " sensor thickness " << fSensorD << " cm,"
272 << " pitch " << GetSensorPitch(0) << " cm / " << GetSensorPitch(1)
273 << " cm, stereo angle " << GetSensorStereoAngle(0) << " / "
275
276 return ss.str();
277}
278// --------------------------------------------------------------------------
@ kSsdLadder
friend F32vec4 atan2(const F32vec4 &y, const F32vec4 &x)
Definition P4_F32vec4.h:130
Class representing an element of the SSD setup.
Int_t GetNofDaughters() const
BmnSsdElement * GetDaughter(Int_t index) const
ESsdElementLevel GetLevel() const
TGeoPhysicalNode * GetPnode() const
Detector response for DSSD sensors with stereo angles and cross-connection by double metal layers.
Double_t GetStereoAngle(Int_t side) const
Stereo angle for front and back side.
Class describing double-sided silicon strip sensors.
virtual Double_t GetPitch(Int_t side) const =0
Strip pitch on front and back side.
Class representing an instance of a sensor in the BMN-SSD.
TGeoPhysicalNode * GetNode() const
Double_t GetSensorPitch(Int_t iSide) const
void Init()
Initialise the station parameters.
Double_t GetSensorStereoAngle(Int_t iSide) const
virtual ~BmnSsdStation()
void AddLadder(BmnSsdElement *ladder)
virtual std::string ToString() const