Line data Source code
1 : /**************************************************************************
2 : * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 : * *
4 : * Author: The ALICE Off-line Project. *
5 : * Contributors are mentioned in the code where appropriate. *
6 : * *
7 : * Permission to use, copy, modify and distribute this software and its *
8 : * documentation strictly for non-commercial purposes is hereby granted *
9 : * without fee, provided that the above copyright notice appears in all *
10 : * copies and that both the copyright notice and this permission notice *
11 : * appear in the supporting documentation. The authors make no claims *
12 : * about the suitability of this software for any purpose. It is *
13 : * provided "as is" without express or implied warranty. *
14 : **************************************************************************/
15 : #include <Riostream.h>
16 : #include <TMath.h>
17 : #include <TGeoManager.h>
18 : #include <TGeoVolume.h>
19 : #include <TGeoBBox.h>
20 : #include "AliITSsegmentationSDD.h"
21 : #include "AliITSDriftSpeedSDD.h"
22 :
23 : /////////////////////////////////////////////////////////////////////////////
24 : // Segmentation class for drift detectors //
25 : // //
26 : // microcables microcables //
27 : // /\ /\ //
28 : // || || //
29 : // || || //
30 : // || || //
31 : // 0 256 0 //
32 : // 0 |----------------------|---------------------| 511 //
33 : // | time-bins | time-bins | //
34 : // | a | a | //
35 : // | n | n | //
36 : // X <_|_o____________________|___________________o_|__ //
37 : // | d | d | //
38 : // | e LEFT SIDE | RIGHT SIDE e | //
39 : // | s CHANNEL 0 | CHANNEL 1 s | //
40 : // | Xlocal > 0 | Xlocal < 0 | //
41 : // 255 |----------------------|---------------------| 256 //
42 : // | //
43 : // | //
44 : // V //
45 : // Z //
46 : /////////////////////////////////////////////////////////////////////////////
47 :
48 : /* $Id$ */
49 :
50 : const Float_t AliITSsegmentationSDD::fgkDxDefault = 35085.;
51 : const Float_t AliITSsegmentationSDD::fgkDzDefault = 75264.;
52 : const Float_t AliITSsegmentationSDD::fgkDyDefault = 300.;
53 : const Float_t AliITSsegmentationSDD::fgkPitchDefault = 294.;
54 : const Float_t AliITSsegmentationSDD::fgkClockDefault = 40.;
55 : const Int_t AliITSsegmentationSDD::fgkHalfNanodesDefault = 256;
56 : const Int_t AliITSsegmentationSDD::fgkNsamplesDefault = 256;
57 : const Int_t AliITSsegmentationSDD::fgkNchipsPerHybrid = 4;
58 : const Int_t AliITSsegmentationSDD::fgkNanodesPerChip = 64;
59 : const Float_t AliITSsegmentationSDD::fgkCm2Micron = 10000.;
60 : const Float_t AliITSsegmentationSDD::fgkMicron2Cm = 1.0E-04;
61 :
62 : using std::endl;
63 : using std::cout;
64 118 : ClassImp(AliITSsegmentationSDD)
65 :
66 : //______________________________________________________________________
67 179 : AliITSsegmentationSDD::AliITSsegmentationSDD(Option_t *opt) : AliITSsegmentation(),
68 179 : fNsamples(0),
69 179 : fNanodes(0),
70 179 : fPitch(0),
71 179 : fTimeStep(0),
72 179 : fDriftSpeed(0),
73 1074 : fSetDriftSpeed(0){
74 : // Default constructor
75 179 : Init();
76 358 : if(strstr(opt,"TGeo")){
77 0 : if(!gGeoManager){
78 0 : AliError("Geometry is not initialized\n");
79 : return;
80 : }
81 : TGeoVolume *v=NULL;
82 0 : v = gGeoManager->GetVolume("ITSsddSensitivL3");
83 0 : if(!v){
84 0 : AliWarning("TGeo volume ITSsddSensitivL3 not found (hint: use v11Hybrid geometry)\n Using hardwired default values");
85 : }
86 : else {
87 0 : TGeoBBox *s=(TGeoBBox*)v->GetShape();
88 0 : SetDetSize(s->GetDX()*10000.,s->GetDZ()*20000.,s->GetDY()*20000.);
89 : }
90 0 : }
91 358 : }
92 :
93 : //______________________________________________________________________
94 : void AliITSsegmentationSDD::Copy(TObject &obj) const {
95 : // protected method. copy this to obj
96 0 : AliITSsegmentation::Copy(obj);
97 0 : ((AliITSsegmentationSDD& ) obj).fNsamples = fNsamples;
98 0 : ((AliITSsegmentationSDD& ) obj).fNanodes = fNanodes;
99 0 : ((AliITSsegmentationSDD& ) obj).fPitch = fPitch;
100 0 : ((AliITSsegmentationSDD& ) obj).fTimeStep = fTimeStep;
101 0 : ((AliITSsegmentationSDD& ) obj).fDriftSpeed = fDriftSpeed;
102 0 : ((AliITSsegmentationSDD& ) obj).fSetDriftSpeed = fSetDriftSpeed;
103 0 : }
104 :
105 : //______________________________________________________________________
106 : AliITSsegmentationSDD& AliITSsegmentationSDD::operator=(const AliITSsegmentationSDD &source){
107 : // = operator
108 0 : if(this==&source) return *this;
109 0 : source.Copy(*this);
110 0 : return *this;
111 0 : }
112 :
113 : //____________________________________________________________________________
114 : AliITSsegmentationSDD::AliITSsegmentationSDD(const AliITSsegmentationSDD &source) :
115 0 : AliITSsegmentation(source),
116 0 : fNsamples(0),
117 0 : fNanodes(0),
118 0 : fPitch(0),
119 0 : fTimeStep(0),
120 0 : fDriftSpeed(0),
121 0 : fSetDriftSpeed(0){
122 : // copy constructor
123 0 : source.Copy(*this);
124 0 : }
125 :
126 : //----------------------------------------------------------------------
127 : void AliITSsegmentationSDD::Init(){
128 : // Standard initilisation routine
129 358 : fDriftSpeed=AliITSDriftSpeedSDD::DefaultDriftSpeed();
130 179 : fCorr=0;
131 179 : SetDetSize(fgkDxDefault,fgkDzDefault,fgkDyDefault);
132 179 : SetPadSize(fgkPitchDefault,fgkClockDefault);
133 179 : SetNPads(fgkHalfNanodesDefault,fgkNsamplesDefault);
134 179 : }
135 :
136 : //----------------------------------------------------------------------
137 : void AliITSsegmentationSDD::
138 : Neighbours(Int_t iX, Int_t iZ, Int_t* Nlist, Int_t Xlist[8], Int_t Zlist[8]) const {
139 : // returns neighbours for use in Cluster Finder routines and the like
140 :
141 0 : if(iX >= fNanodes) printf("iX > fNanodes %d %d\n",iX,fNanodes);
142 0 : if(iZ >= fNsamples) printf("iZ > fNsamples %d %d\n",iZ,fNsamples);
143 0 : *Nlist=4;
144 0 : Xlist[0]=Xlist[1]=iX;
145 0 : if(iX && (iX != fNanodes/2)) Xlist[2]=iX-1;
146 0 : else Xlist[2]=iX;
147 0 : if ((iX !=fNanodes/2 -1) && (iX != fNanodes)) Xlist[3]=iX+1;
148 0 : else Xlist[3]=iX;
149 0 : if(iZ) Zlist[0]=iZ-1;
150 0 : else Zlist[0]=iZ;
151 0 : if (iZ < fNsamples) Zlist[1]=iZ+1;
152 0 : else Zlist[1]=iZ;
153 0 : Zlist[2]=Zlist[3]=iZ;
154 0 : }
155 : //----------------------------------------------------------------------
156 : Float_t AliITSsegmentationSDD::GetAnodeFromLocal(Float_t xloc,Float_t zloc) const {
157 : // returns anode coordinate (as float) starting from local coordinates
158 3494 : Float_t xAnode=zloc*fgkCm2Micron/fPitch;
159 3494 : if(xloc>0){ // left side (anodes 0-255, anode 0 at zloc<0)
160 2634 : xAnode+=(Float_t)fNanodes/4;
161 887 : }else{ // right side (anodes 256-511, anode 0 at zloc>0)
162 860 : xAnode=3*fNanodes/4-xAnode;
163 : }
164 1747 : return xAnode;
165 : }
166 :
167 : //----------------------------------------------------------------------
168 : Float_t AliITSsegmentationSDD::GetLocalZFromAnode(Int_t nAnode) const{
169 : // returns local Z coordinate from anode number (integer)
170 0 : Float_t zAnode=(Float_t)nAnode+0.5;
171 0 : return GetLocalZFromAnode(zAnode);
172 : }
173 :
174 : //----------------------------------------------------------------------
175 : Float_t AliITSsegmentationSDD::GetLocalZFromAnode(Float_t zAnode) const{
176 : // returns local Z coordinate from anode number (float)
177 : Float_t zloc=0.;
178 460 : if(zAnode<fNanodes/2){ // left side
179 122 : zloc=(zAnode*fPitch-fDz/2)*fgkMicron2Cm;
180 122 : }else{ // right side
181 108 : zAnode-=fNanodes/2;
182 108 : zloc=-(zAnode*fPitch-fDz/2)*fgkMicron2Cm;
183 : }
184 230 : return zloc;
185 : }
186 : //----------------------------------------------------------------------
187 : Int_t AliITSsegmentationSDD::GetChipFromChannel(Int_t ix, Int_t iz) const {
188 : // returns chip number (in range 0-7) starting from channel number
189 0 : if(iz>=fNanodes || iz<0 || ix>fNsamples){
190 0 : AliError("Bad cell number");
191 0 : return -1;
192 : }
193 0 : Int_t theChip=iz/fgkNanodesPerChip;
194 : return theChip;
195 0 : }
196 : //----------------------------------------------------------------------
197 : Int_t AliITSsegmentationSDD::GetChipFromLocal(Float_t xloc, Float_t zloc) const {
198 : // returns chip number (in range 0-7) starting from local coordinates
199 6652 : Float_t detsize=fDz*fgkMicron2Cm;
200 3326 : Float_t chipsize=detsize/(Float_t)fgkNchipsPerHybrid;
201 3326 : zloc+=detsize/2.;
202 6652 : if(zloc<-0.01 || zloc>detsize+0.01){ // 100 micron tolerance around edges
203 0 : AliError("Z local value out of sensitive SDD area");
204 0 : return -1;
205 : }
206 3326 : Int_t iChip=int(zloc/chipsize);
207 3326 : if(zloc<0.) iChip=0;
208 3326 : if(zloc>=detsize) iChip=fgkNchipsPerHybrid-1;
209 3326 : if(iChip>=fgkNchipsPerHybrid || iChip<0){
210 0 : AliError(Form("Bad chip number %d",iChip));
211 0 : return -1;
212 : }
213 3326 : Int_t iSide=GetSideFromLocalX(xloc);
214 4884 : if(iSide==1) iChip=fgkNchipsPerHybrid-iChip+3; // i.e. 7-iChip
215 : return iChip;
216 3326 : }
217 : //----------------------------------------------------------------------
218 : Int_t AliITSsegmentationSDD::GetChipsInLocalWindow(Int_t* array, Float_t zmin, Float_t zmax, Float_t xmin, Float_t xmax) const {
219 : // returns the numbers of the chips that read channels in a given region
220 : // of the module defined in local coordinates by zmin-zmax, xmin-max
221 :
222 : Int_t nChipInW = 0;
223 2184 : Float_t zminDet=-fDz*fgkMicron2Cm/2.;
224 1092 : Float_t zmaxDet=fDz*fgkMicron2Cm/2.;
225 1092 : if(zmin<zminDet) zmin=zminDet;
226 1092 : if(zmax>zmaxDet) zmax=zmaxDet;
227 1092 : Float_t xminDet=-fDx*fgkMicron2Cm;
228 1092 : Float_t xmaxDet=fDx*fgkMicron2Cm;
229 1092 : if(xmin<xminDet) xmin=xminDet;
230 1092 : if(xmax>xmaxDet) xmax=xmaxDet;
231 1092 : Int_t n1=GetChipFromLocal(xmin,zmin);
232 1092 : array[nChipInW]=n1;
233 : nChipInW++;
234 1092 : Int_t n2=GetChipFromLocal(xmin,zmax);
235 1092 : if(n2!=n1){
236 179 : Int_t imin=TMath::Min(n1,n2);
237 179 : Int_t imax=TMath::Max(n1,n2);
238 1146 : for(Int_t ichip=imin; ichip<=imax; ichip++){
239 394 : if(ichip==n1) continue;
240 215 : array[nChipInW]=ichip;
241 215 : nChipInW++;
242 215 : }
243 179 : }
244 1092 : Int_t n3=GetChipFromLocal(xmax,zmin);
245 1092 : if(n3!=n1){
246 50 : array[nChipInW]=n3;
247 50 : nChipInW++;
248 50 : Int_t n4=GetChipFromLocal(xmax,zmax);
249 50 : if(n4!=n3){
250 33 : Int_t imin=TMath::Min(n3,n4);
251 33 : Int_t imax=TMath::Max(n3,n4);
252 222 : for(Int_t ichip=imin; ichip<=imax; ichip++){
253 78 : if(ichip==n3) continue;
254 45 : array[nChipInW]=ichip;
255 45 : nChipInW++;
256 45 : }
257 33 : }
258 50 : }
259 1092 : return nChipInW;
260 : }
261 : //----------------------------------------------------------------------
262 : void AliITSsegmentationSDD::GetPadIxz(Float_t x,Float_t z,
263 : Int_t &timebin,Int_t &anode) const {
264 : // Returns cell coordinates (time sample,anode)
265 : // for given real local coordinates (x,z)
266 :
267 : // expects x, z in cm
268 :
269 768 : Float_t driftpath=fDx-TMath::Abs(x*fgkCm2Micron);
270 384 : timebin=(Int_t)(driftpath/fDriftSpeed/fTimeStep);
271 384 : anode=(Int_t)GetAnodeFromLocal(x,z);
272 384 : if(!fSetDriftSpeed){
273 0 : timebin=-999;
274 0 : AliWarning("Drift speed not set: timebin is dummy");
275 0 : }
276 :
277 384 : }
278 : //----------------------------------------------------------------------
279 : void AliITSsegmentationSDD::GetPadCxz(Int_t timebin,Int_t anode,
280 : Float_t &x ,Float_t &z) const{
281 : // Transform from cell to real local coordinates
282 : // returns x, z in cm
283 :
284 : // the +0.5 means that an # and time bin # should start from 0 !!!
285 : // the +0.5 means that an # and time bin # should start from 0 !!!
286 :
287 0 : Float_t driftpath=GetDriftTimeFromTb(timebin)*fDriftSpeed;
288 0 : if (anode < fNanodes/2){ // left side, positive x
289 0 : x=(fDx-driftpath)*fgkMicron2Cm;
290 0 : }else{ // right side, negative x
291 0 : x = -(fDx-driftpath)*fgkMicron2Cm;
292 : }
293 0 : z=GetLocalZFromAnode(anode);
294 0 : if(!fSetDriftSpeed){
295 0 : x=-9999.;
296 0 : AliWarning("Drift speed not set: x coord. is dummy");
297 0 : }
298 0 : }
299 : //----------------------------------------------------------------------
300 : void AliITSsegmentationSDD::GetPadTxz(Float_t &x,Float_t &z) const{
301 : // Get anode and time bucket as floats - numbering from 0
302 :
303 : // expects x, z in cm
304 :
305 0 : Float_t xloc=x;
306 0 : Float_t zloc=z;
307 0 : Float_t driftpath=fDx-TMath::Abs(fgkCm2Micron*xloc);
308 0 : x=driftpath/fDriftSpeed/fTimeStep;
309 0 : if (xloc < 0) x = -x;
310 0 : z=GetAnodeFromLocal(xloc,zloc);
311 0 : if(!fSetDriftSpeed){
312 0 : x=-9999.;
313 0 : AliWarning("Drift speed not set: x coord. is dummy");
314 0 : }
315 0 : }
316 : //----------------------------------------------------------------------
317 : void AliITSsegmentationSDD::Print(Option_t *opt) const {
318 : // Print SDD segmentation Parameters
319 :
320 0 : cout << "**************************************************" << endl;
321 0 : cout << " Silicon Drift Detector Segmentation Parameters " << opt << endl;
322 0 : cout << "**************************************************" << endl;
323 0 : cout << "Number of Time Samples: " << fNsamples << endl;
324 0 : cout << "Number of Anodes: " << fNanodes << endl;
325 0 : cout << "Time Step (ns): " << fTimeStep << endl;
326 0 : cout << "Anode Pitch (um): " << fPitch << endl;
327 0 : cout << "Full Detector Width (x): " << fDx;
328 0 : cout<<" (Default is "<<fgkDxDefault<<") "<<endl;
329 0 : cout << "Half Detector Length (z): " << fDz;
330 0 : cout<<" (Default is "<<fgkDzDefault<<") "<<endl;
331 0 : cout << "Full Detector Thickness (y): " << fDy;
332 0 : cout<<" (Default is "<<fgkDyDefault<<") "<<endl;
333 0 : cout << "**************************************************" << endl;
334 :
335 0 : }
336 :
337 : //----------------------------------------------------------------------
338 : void AliITSsegmentationSDD::PrintDefaultParameters() const {
339 : // print SDD parameters defined as static const data members
340 :
341 0 : cout << "**************************************************" << endl;
342 0 : cout << " Silicon Drift Detector Segmentation Parameters " << endl;
343 0 : cout << " Default values defined as static const data members"<< endl;
344 0 : cout << " Actual values can be set with the relevant setters"<< endl;
345 0 : cout << "**************************************************" << endl;
346 0 : cout<<"fgkDxDefault = "<<fgkDxDefault<<endl;
347 0 : cout<<"fgkDzDefault = "<<fgkDzDefault<<endl;
348 0 : cout<<"fgkDyDefault = "<<fgkDyDefault<<endl;
349 0 : cout<<"fgkPitchDefault = "<<fgkPitchDefault<<endl;
350 0 : cout<<"fgkClockDefault = "<<fgkClockDefault<<endl;
351 0 : cout<<"fgkHalfNanodesDefault = "<<fgkHalfNanodesDefault<<endl;
352 0 : cout<<"fgkNsamplesDefault = "<<fgkNsamplesDefault<<endl;
353 0 : cout << "**************************************************" << endl;
354 :
355 0 : }
356 :
357 : //______________________________________________________________________
358 : Bool_t AliITSsegmentationSDD::LocalToDet(Float_t x,Float_t z,
359 : Int_t &ix,Int_t &iz) const {
360 : // Transformation from Geant detector centered local coordinates (cm) to
361 : // time bucket numbers ix and anode number iz.
362 : // Input:
363 : // Float_t x detector local coordinate x in cm with respect to the
364 : // center of the sensitive volume.
365 : // Float_t z detector local coordinate z in cm with respect to the
366 : // center of the sensitive volulme.
367 : // Output:
368 : // Int_t ix detector x time coordinate. Has the range 0<=ix<fNsamples.
369 : // Int_t iz detector z anode coordinate. Has the range 0<=iz<fNandoes.
370 : // A value of -1 for ix or iz indecates that this point is outside of the
371 : // detector segmentation as defined.
372 :
373 : Float_t dx,dz;
374 :
375 768 : ix = -1; // default values
376 384 : iz = -1; // default values
377 384 : dx = -fgkMicron2Cm*Dx(); // lower left edge in cm.
378 384 : dz = -0.5*fgkMicron2Cm*Dz(); // lower left edge in cm.
379 768 : if(x<dx || x>-dx) {
380 0 : AliWarning(Form("Input argument %f out of range (%f, %f)",x,dx,-dx));
381 0 : return kFALSE; // outside of defined volume.
382 : }
383 768 : if(z<dz || z>-dz) {
384 0 : AliWarning(Form("Input argument %f out of range (%f, %f)",z,dz,-dz));
385 0 : return kFALSE; // outside of defined volume.
386 : }
387 384 : GetPadIxz(x,z,ix,iz);
388 384 : if(!fSetDriftSpeed){
389 0 : ix=-999;
390 0 : AliWarning("Drift speed not set: timebin is dummy");
391 0 : return kFALSE;
392 : }
393 384 : return kTRUE; // Found ix and iz, return.
394 384 : }
395 : //______________________________________________________________________
396 : void AliITSsegmentationSDD::DetToLocal(Int_t ix,Int_t iz,Float_t &x,Float_t &z) const
397 : {
398 : // Transformation from Detector time bucket and anode coordiantes to Geant
399 : // detector centerd local coordinates (cm).
400 : // Input:
401 : // Int_t ix detector x time coordinate. Has the range 0<=ix<fNsamples.
402 : // Int_t iz detector z anode coordinate. Has the range 0<=iz<fNandoes.
403 : // Output:
404 : // Float_t x detector local coordinate x in cm with respect to the
405 : // center of the sensitive volume.
406 : // Float_t z detector local coordinate z in cm with respect to the
407 : // center of the sensitive volulme.
408 : // If ix and or iz is outside of the segmentation range a value of -Dx()
409 : // or -0.5*Dz() is returned.
410 :
411 0 : x=-Dx();
412 0 : z=-0.5*Dz();
413 0 : if(ix<0 || ix>=Npx()) {
414 0 : AliWarning(Form("Input argument %d out of range (0, %d)",ix,Npx()));
415 0 : return; // outside of detector
416 : }
417 0 : if(iz<0 || iz>=Npz()) {
418 0 : AliWarning(Form("Input argument %d out of range (0, %d)",iz,Npz()));
419 0 : return; // outside of detctor
420 : }
421 0 : GetPadCxz(ix,iz,x,z);
422 0 : if(!fSetDriftSpeed){
423 0 : x=-9999.;
424 0 : AliWarning("Drift speed not set: x coord. is dummy");
425 0 : }
426 : return; // Found x and z, return.
427 0 : }
|