1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
19 ///////////////////////////////////////////////////////////////////////////////
23 ///////////////////////////////////////////////////////////////////////////////
28 #include "AliTRDcluster.h"
29 #include "AliTRDgeometry.h"
30 #include "AliTRDCommonParam.h"
32 ClassImp(AliTRDcluster)
34 //___________________________________________________________________________
35 AliTRDcluster::AliTRDcluster()
48 // Default constructor
51 for (Int_t i = 0; i < 7; i++) {
57 //___________________________________________________________________________
58 AliTRDcluster::AliTRDcluster(Int_t det, Float_t q
59 , Float_t *pos, Float_t *sig
60 , Int_t *tracks, Char_t npads, Short_t *signals
61 , UChar_t col, UChar_t row, UChar_t time
62 , Char_t timebin, Float_t center, UShort_t volid)
63 :AliCluster(volid,pos[0],pos[1],pos[2],sig[0],sig[1],0.0,0x0)
67 ,fLocalTimeBin(timebin)
78 for (Int_t i = 0; i < 7; i++) {
79 fSignals[i] = signals[i];
83 AddTrackIndex(tracks);
88 //_____________________________________________________________________________
89 AliTRDcluster::AliTRDcluster(const AliTRDcluster &c)
94 ,fLocalTimeBin(c.fLocalTimeBin)
96 ,fClusterMasking(c.fClusterMasking)
97 ,fDetector(c.fDetector)
105 SetBit(kInChamber, c.IsInChamber());
106 SetLabel(c.GetLabel(0),0);
107 SetLabel(c.GetLabel(1),1);
108 SetLabel(c.GetLabel(2),2);
112 SetSigmaY2(c.GetSigmaY2());
113 SetSigmaZ2(c.GetSigmaZ2());
115 for (Int_t i = 0; i < 7; i++) {
116 fSignals[i] = c.fSignals[i];
121 //_____________________________________________________________________________
122 void AliTRDcluster::AddTrackIndex(Int_t *track)
125 // Adds track index. Currently assumed that track is an array of
126 // size 9, and up to 3 track indexes are stored in fTracks[3].
127 // Indexes are sorted according to:
128 // 1) index of max number of appearances is stored first
129 // 2) if two or more indexes appear equal number of times, the lowest
130 // ones are stored first;
133 const Int_t kSize = 9;
134 Int_t entries[kSize][2];
142 for (i = 0; i < kSize; i++) {
147 for (k = 0; k < kSize; k++) {
154 while ((!indexAdded) && (j < kSize)) {
155 if ((entries[j][0] == index) ||
156 (entries[j][1] == 0)) {
157 entries[j][0] = index;
158 entries[j][1] = entries[j][1] + 1;
167 // Sort by number of appearances and index value
173 for (i = 0; i < (kSize - 1); i++) {
174 if ((entries[i][0] >= 0) &&
175 (entries[i+1][0] >= 0)) {
176 if ((entries[i][1] < entries[i+1][1]) ||
177 ((entries[i][1] == entries[i+1][1]) &&
178 (entries[i][0] > entries[i+1][0]))) {
179 tmp0 = entries[i][0];
180 tmp1 = entries[i][1];
181 entries[i][0] = entries[i+1][0];
182 entries[i][1] = entries[i+1][1];
183 entries[i+1][0] = tmp0;
184 entries[i+1][1] = tmp1;
192 for (i = 0; i < 3; i++) {
193 SetLabel(entries[i][0],i);
200 //_____________________________________________________________________________
201 void AliTRDcluster::Clear(Option_t *)
204 // Reset all member to the default value
213 for (Int_t i=0; i < 7; i++) fSignals[i]=0;
216 for (Int_t i = 0; i < 3; i++) SetLabel(0,i);
225 //_____________________________________________________________________________
226 Float_t AliTRDcluster::GetSumS() const
229 // Returns the total charge from a not unfolded cluster
233 for (Int_t i = 0; i < 7; i++) {
241 //_____________________________________________________________________________
242 Float_t AliTRDcluster::GetXloc(Double_t t0, Double_t vd, Double_t *const /*q*/, Double_t *const /*xq*/, Double_t z)
245 // (Re)Calculate cluster position in the x direction in local chamber coordinates (with respect to the anode wire
246 // position) using all available information from tracking.
248 // t0 - calibration aware trigger delay [us]
249 // vd - drift velocity in the region of the cluster [cm/us]
250 // z - distance to the anode wire [cm]. By default 0.2 !!
251 // q & xq - array of charges and cluster positions from previous clusters in the tracklet [a.u.]
253 // return x position of the cluster with respect to the
254 // anode wire using all tracking information
256 // The estimation of the radial position is based on calculating the drift time and the drift velocity at the point of
257 // estimation. The drift time can be estimated according to the expression:
259 // t_{drift} = t_{bin} - t_{0} - t_{cause}(x) - t_{TC}(q_{i-1}, q_{i-2}, ...)
261 // where t_0 is the delay of the trigger signal. t_cause is the causality delay between ionisation electrons hitting
262 // the anode and the registration of maximum signal by the electronics - it is due to the rising time of the TRF
263 // convoluted with the diffusion width. t_TC is the residual charge from previous bins due to residual tails after tail
266 // The drift velocity is considered to vary linearly with the drift length (independent of the distance to the anode wire
267 // in the z direction). Thus one can write the calculate iteratively the drift length from the expression:
269 // x = t_{drift}(x)*v_{drfit}(x)
273 // Alex Bercuci <A.Bercuci@gsi.de>
276 AliTRDCommonParam *cp = AliTRDCommonParam::Instance();
277 Double_t fFreq = cp->GetSamplingFrequency();
278 //drift time corresponding to the center of the time bin
279 Double_t td = (fPadTime + .5)/fFreq; // [us]
282 // calculate radial posion of clusters in the drift region
283 if(td < .2 || td > 2.4) return 0.;
284 // correction for TRF rising time 0.2us
287 // invert drift time function
288 Double_t xM= AliTRDgeometry::CamHght()+AliTRDgeometry::CdrHght(),
289 x = vd*td + .5*AliTRDgeometry::CamHght(),
290 t = cp->TimeStruct(vd, x, z), dx1=0.,dx2;
291 while(TMath::Abs(td-t)>1.e-4){ // convergence on 100ps
293 if(TMath::Abs(TMath::Abs(dx2)-TMath::Abs(dx1))<1.e-6){
298 if(x<0. || x>xM) return 0.;
299 t = cp->TimeStruct(vd, x, z);
303 return x-.5*AliTRDgeometry::CamHght();
306 //_____________________________________________________________________________
307 Float_t AliTRDcluster::GetYloc(Double_t s2, Double_t W, Double_t xd, Double_t wt, Double_t *const y1, Double_t *const y2)
310 // (Re)Calculate cluster position in the y direction in local chamber coordinates using all available information from tracking.
313 // s2 - sigma of gaussian parameterization (see bellow for the exact parameterization)
315 // xd - drift length (with respect to the anode wire) [cm]
316 // wt - omega*tau = tg(a_L)
318 // y1 and y2 - partial positions based on 2 pads clusters
319 // return y position of the cluster from all information
321 // Estimation of y coordinate is based on the gaussian approximation of the PRF. Thus one may
322 // calculate the y position knowing the signals q_i-1, q_i and q_i+1 in the 3 adiacent pads by:
324 // y = #frac{1}{w_{1}+w_{2}}#[]{w_{1}#(){y_{0}-#frac{W}{2}+#frac{s^{2}}{W}ln#frac{q_{i}}{q_{i-1}}}+w_{2}#(){y_{0}+ #frac{W}{2}+#frac{s^{2}}{W}ln#frac{q_{i+1}}{q_{i}}}}
326 // where W is the pad width, y_0 is the position of the center pad and s^2 is given by
328 // s^{2} = s^{2}_{0} + s^{2}_{diff} (x,B) + #frac{tg^{2}(#phi-#alpha_{L})*l^{2}}{12}
330 // with s_0 being the PRF for 0 drift and track incidence phi equal to the lorentz angle a_L and the diffusion term
331 // being described by:
333 // s_{diff} (x,B) = #frac{D_{L}#sqrt{x}}{1+#(){#omega#tau}^{2}}
335 // with x being the drift length. The weights w_1 and w_2 are taken to be q_i-1^2 and q_i+1^2 respectively
338 // Alex Bercuci <A.Bercuci@gsi.de>
339 // Theodor Rascanu <trascanu@stud.uni-frankfurt.de>
341 Float_t y0 = GetY()-W*fCenter;
342 Double_t w1 = fSignals[2]*fSignals[2];
343 Double_t w2 = fSignals[4]*fSignals[4];
344 Float_t y1r = fSignals[2]>0 ? (y0 - .5*W + s2*TMath::Log(fSignals[3]/(Float_t)fSignals[2])/W) : 0.;
345 Float_t y2r = fSignals[4]>0 ? (y0 + .5*W + s2*TMath::Log(fSignals[4]/(Float_t)fSignals[3])/W) : 0.;
350 Double_t ld = TMath::Max(xd - 0.*AliTRDgeometry::CamHght(), 0.);
352 return (w1*y1r+w2*y2r)/(w1+w2) - ld*wt;
355 //_____________________________________________________________________________
356 Bool_t AliTRDcluster::IsEqual(const TObject *o) const
359 // Compare relevant information of this cluster with another one
362 const AliTRDcluster *inCluster = dynamic_cast<const AliTRDcluster*>(o);
363 if (!o || !inCluster) return kFALSE;
365 if ( AliCluster::GetX() != inCluster->GetX() ) return kFALSE;
366 if ( AliCluster::GetY() != inCluster->GetY() ) return kFALSE;
367 if ( AliCluster::GetZ() != inCluster->GetZ() ) return kFALSE;
368 if ( fQ != inCluster->fQ ) return kFALSE;
369 if ( fDetector != inCluster->fDetector ) return kFALSE;
370 if ( fPadCol != inCluster->fPadCol ) return kFALSE;
371 if ( fPadRow != inCluster->fPadRow ) return kFALSE;
372 if ( fPadTime != inCluster->fPadTime ) return kFALSE;
373 if ( fClusterMasking != inCluster->fClusterMasking ) return kFALSE;
374 if ( IsInChamber() != inCluster->IsInChamber() ) return kFALSE;
375 if ( IsShared() != inCluster->IsShared() ) return kFALSE;
376 if ( IsUsed() != inCluster->IsUsed() ) return kFALSE;
381 //_____________________________________________________________________________
382 void AliTRDcluster::Print(Option_t *o) const
384 AliInfo(Form("Det[%3d] LTrC[%7.2f %7.2f %7.2f] Q[%f] Stat[in(%c) use(%c) sh(%c)]",
385 fDetector, GetX(), GetY(), GetZ(), fQ,
386 IsInChamber() ? 'y' : 'n', IsUsed() ? 'y' : 'n', IsShared() ? 'y' : 'n'));
388 if(strcmp(o, "a")!=0) return;
389 AliInfo(Form("LChC[c(%3d) r(%2d) t(%2d)] t-t0[%2d] Npad[%d] cen[%5.3f] mask[%d]", fPadCol, fPadRow, fPadTime, fLocalTimeBin, fNPads, fCenter, fClusterMasking));
390 AliInfo(Form("Signals[%3d %3d %3d %3d %3d %3d %3d]", fSignals[0], fSignals[1], fSignals[2], fSignals[3], fSignals[4], fSignals[5], fSignals[6]));
394 //_____________________________________________________________________________
395 void AliTRDcluster::SetPadMaskedPosition(UChar_t position)
398 // store the pad corruption position code
400 // Code: 1 = left cluster
401 // 2 = middle cluster;
404 for(Int_t ipos = 0; ipos < 3; ipos++)
405 if(TESTBIT(position, ipos))
406 SETBIT(fClusterMasking, ipos);
409 //_____________________________________________________________________________
410 void AliTRDcluster::SetPadMaskedStatus(UChar_t status)
413 // store the status of the corrupted pad
418 // 32 = Not Connected
419 for(Int_t ipos = 0; ipos < 5; ipos++)
420 if(TESTBIT(status, ipos))
421 SETBIT(fClusterMasking, ipos + 3);