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 :
16 : /* $Id: AliADReconstructor.cxx 20956 2007-09-26 14:22:18Z mrodrigu $ */
17 : //////////////////////////////////////////////////////////////////////////////
18 : // //
19 : // Class for AD reconstruction //
20 : //////////////////////////////////////////////////////////////////////////////
21 : #include <algorithm>
22 :
23 : #include <TParameter.h>
24 : #include <TGeoManager.h>
25 : #include <TGeoMatrix.h>
26 : #include <TGeoPhysicalNode.h>
27 :
28 : #include <TF1.h>
29 :
30 : #include <AliGeomManager.h>
31 :
32 : #include "AliRawReader.h"
33 : #include "AliGRPObject.h"
34 : #include "AliCDBManager.h"
35 : #include "AliCDBStorage.h"
36 : #include "AliCDBEntry.h"
37 : #include "AliESDEvent.h"
38 : #include "AliRunInfo.h"
39 : #include "AliCTPTimeParams.h"
40 : #include "AliLHCClockPhase.h"
41 : #include "TSpline.h"
42 :
43 : #include "AliADReconstructor.h"
44 : #include "AliADdigit.h"
45 : #include "AliESDAD.h"
46 : #include "AliESDADfriend.h"
47 : #include "AliADConst.h"
48 : #include "AliADCalibData.h"
49 : #include "AliADRawStream.h"
50 : #include "AliADDecision.h"
51 :
52 16 : ClassImp(AliADReconstructor);
53 :
54 : //_____________________________________________________________________________
55 : AliADReconstructor::AliADReconstructor()
56 0 : : AliReconstructor()
57 0 : , fESDAD(NULL)
58 0 : , fESD(NULL)
59 0 : , fESDADfriend(NULL)
60 0 : , fCalibData(NULL)
61 0 : , fDigitsArray(NULL)
62 0 : , fSaturationCorrection(NULL)
63 0 : , fCollisionMode(0)
64 0 : , fBeamEnergy(0.)
65 0 : , fCorrectForSaturation(kTRUE)
66 0 : {
67 : // Default constructor
68 :
69 : // Get calibration data
70 0 : fCalibData = GetCalibData();
71 :
72 : //Get time slewing
73 0 : GetTimeSlewingSplines();
74 :
75 0 : AliCDBManager *man = AliCDBManager::Instance();
76 : AliCDBEntry *entry = NULL;
77 :
78 : // Now get the CTP L0->L1 delay
79 0 : entry = man->Get("GRP/CTP/CTPtiming");
80 0 : if (!entry) AliFatal("CTP timing parameters are not found in OCDB !");
81 0 : AliCTPTimeParams *ctpParams = dynamic_cast<AliCTPTimeParams*>(entry->GetObject());
82 0 : Float_t l1Delay = (Float_t)ctpParams->GetDelayL1L0()*25.0;
83 :
84 0 : entry = man->Get("GRP/CTP/TimeAlign");
85 0 : if (!entry) AliFatal("CTP time-alignment is not found in OCDB !");
86 0 : AliCTPTimeParams *ctpTimeAlign = dynamic_cast<AliCTPTimeParams*>(entry->GetObject());
87 0 : l1Delay += ((Float_t)ctpTimeAlign->GetDelayL1L0()*25.0);
88 :
89 0 : entry = man->Get("AD/Calib/TimeDelays");
90 0 : if (!entry) AliFatal("AD time delays are not found in OCDB !");
91 0 : TH1F *TimeDelays = dynamic_cast<TH1F*>(entry->GetObject());
92 :
93 0 : entry = man->Get("GRP/Calib/LHCClockPhase");
94 0 : if (!entry) AliFatal("LHC clock-phase shift is not found in OCDB !");
95 0 : AliLHCClockPhase *phase = dynamic_cast<AliLHCClockPhase*>(entry->GetObject());
96 :
97 0 : for (Int_t i=0; i<16; ++i) {
98 0 : const Int_t board = AliADCalibData::GetBoardNumber(i);
99 0 : fHptdcOffset[i] = (((Float_t)fCalibData->GetRollOver(board)-
100 0 : (Float_t)fCalibData->GetTriggerCountOffset(board))*25.0
101 0 : +fCalibData->GetTimeOffset(i)
102 0 : -l1Delay
103 0 : -phase->GetMeanPhase()
104 0 : -TimeDelays->GetBinContent(i+1)
105 0 : -kADOffset);
106 : }
107 :
108 0 : const Float_t zADC1 = TMath::Abs(GetZPosition("AD/ADC1")); // outer
109 0 : const Float_t zADC2 = TMath::Abs(GetZPosition("AD/ADC2")); // inner
110 0 : const Float_t zADA1 = TMath::Abs(GetZPosition("AD/ADA1")); // inner
111 0 : const Float_t zADA2 = TMath::Abs(GetZPosition("AD/ADA2")); // outer
112 :
113 : // distance in time units from nominal vertex to AD
114 0 : fLayerDist[0] = zADC1/TMath::Ccgs()*1e9;
115 0 : fLayerDist[1] = zADC2/TMath::Ccgs()*1e9;
116 0 : fLayerDist[2] = zADA1/TMath::Ccgs()*1e9;
117 0 : fLayerDist[3] = zADA2/TMath::Ccgs()*1e9;
118 0 : }
119 : //________________________________________________________________________________
120 : void AliADReconstructor::SetOption(Option_t* opt)
121 : {
122 0 : TObjArray *oa = TString(opt).Tokenize(" ");
123 0 : for (Int_t i=0, n=oa->GetEntries(); i<n; ++i) {
124 0 : const TString s = oa->At(i)->GetName();
125 0 : if (s.Contains("SaturationCorrection")) {
126 0 : fCorrectForSaturation = !s.Contains("-");
127 0 : }
128 0 : }
129 0 : delete oa;
130 0 : AliInfo(Form("opt='%s' fCorrectForSaturation: %s", opt, fCorrectForSaturation ? "ON" : "OFF"));
131 0 : }
132 : //________________________________________________________________________________
133 : Double_t AliADReconstructor::GetZPosition(const char* symname)
134 : {
135 : // Get the global z coordinate of the given AD alignable volume
136 : //
137 : Double_t *tr;
138 0 : TGeoPNEntry *pne = gGeoManager->GetAlignableEntry(symname);
139 0 : if (!pne) {
140 0 : AliFatalClass(Form("TGeoPNEntry with symbolic name %s does not exist!", symname));
141 0 : return 0;
142 : }
143 :
144 0 : TGeoPhysicalNode *pnode = pne->GetPhysicalNode();
145 0 : if (NULL != pnode) {
146 0 : TGeoHMatrix* hm = pnode->GetMatrix();
147 0 : tr = hm->GetTranslation();
148 0 : } else {
149 0 : const char* path = pne->GetTitle();
150 0 : if (!gGeoManager->cd(path)) {
151 0 : AliFatalClass(Form("Volume path %s not valid!", path));
152 0 : return 0;
153 : }
154 0 : tr = gGeoManager->GetCurrentMatrix()->GetTranslation();
155 0 : }
156 0 : return tr[2];
157 0 : }
158 :
159 :
160 : //_____________________________________________________________________________
161 : AliADReconstructor& AliADReconstructor::operator = (const AliADReconstructor&)
162 : {
163 : // assignment operator
164 0 : Fatal("operator =", "assignment operator not implemented");
165 0 : return *this;
166 : }
167 :
168 : //_____________________________________________________________________________
169 : AliADReconstructor::~AliADReconstructor()
170 0 : {
171 : // destructor
172 0 : delete fESDAD;
173 0 : delete fESDADfriend;
174 0 : delete fDigitsArray;
175 0 : }
176 :
177 : //_____________________________________________________________________________
178 : void AliADReconstructor::Init()
179 : {
180 : // initializer
181 0 : SetOption(GetOption());
182 :
183 0 : fESDAD = new AliESDAD;
184 0 : fESDADfriend = new AliESDADfriend;
185 :
186 0 : if (fCorrectForSaturation) {
187 0 : AliCDBEntry *entry = AliCDBManager::Instance()->Get("AD/Calib/Saturation");
188 0 : if (!entry) AliFatal("AD/Calib/Saturation is not found in OCDB !");
189 0 : fSaturationCorrection = dynamic_cast<TTree*>(entry->GetObject());
190 0 : }
191 0 : }
192 :
193 : UShort_t MakeTriggerFlags(Bool_t UBA, Bool_t UBC,
194 : Bool_t UGA, Bool_t UGC) {
195 : UShort_t flags = 0;
196 0 : flags |= (1<< 0)*(UBA && UBC);
197 0 : flags |= (1<< 1)*(UBA || UBC);
198 0 : flags |= (1<< 2)*(UGA && UBC);
199 0 : flags |= (1<< 3)*UGA;
200 0 : flags |= (1<< 4)*(UGC && UBA);
201 0 : flags |= (1<< 5)*UGC;
202 : //CTA1 and CTC1
203 : //CTA1 or CTC1
204 : //CTA2 and CTC2
205 : //CTA2 or CTC2
206 : //MTA and MTC
207 : //MTA or MTC
208 0 : flags |= (1<<12)*UBA;
209 0 : flags |= (1<<13)*UBC;
210 0 : flags |= (1<<14)*(UGA || UGC);
211 0 : flags |= (1<<15)*((UGA && UBC) || (UGC && UBA));
212 0 : return flags;
213 : }
214 :
215 : //_____________________________________________________________________________
216 : void AliADReconstructor::ConvertDigits(AliRawReader* rawReader, TTree* digitsTree) const
217 : {
218 : // converts RAW to digits
219 0 : if (NULL == digitsTree) {
220 0 : AliError("No digits tree!");
221 0 : return;
222 : }
223 :
224 0 : if (NULL == fDigitsArray)
225 0 : fDigitsArray = new TClonesArray("AliADdigit", 16);
226 0 : digitsTree->Branch("ADDigit", &fDigitsArray);
227 :
228 0 : rawReader->Reset();
229 0 : AliADRawStream rawStream(rawReader);
230 0 : if (rawStream.Next()) {
231 0 : Bool_t aBBflag[16];
232 0 : Bool_t aBGflag[16];
233 :
234 0 : for (Int_t iChannel=0; iChannel<16; ++iChannel) { // iChannel -> online channel number
235 0 : const Int_t offlineCh = kOfflineChannel[iChannel];
236 : // ADC charge samples
237 0 : Short_t chargeADC[kADNClocks] = { 0 };
238 : // aBBflag[offlineCh] = kFALSE;
239 : // aBGflag[offlineCh] = kFALSE;
240 0 : for (Int_t iClock=0; iClock<kADNClocks; ++iClock) {
241 0 : chargeADC[iClock] = rawStream.GetPedestal(iChannel, iClock);
242 : // if (rawStream.GetBBFlag(iChannel, iClock)) aBBflag[offlineCh]=kTRUE;
243 : // if (rawStream.GetBGFlag(iChannel, iClock)) aBGflag[offlineCh]=kTRUE;
244 : }
245 : // Integrator flag
246 0 : const Bool_t integrator = rawStream.GetIntegratorFlag(iChannel, kADNClocks/2);
247 0 : const Bool_t BBflag = rawStream.GetBBFlag(iChannel, kADNClocks/2);
248 0 : const Bool_t BGflag = rawStream.GetBGFlag(iChannel, kADNClocks/2);
249 0 : aBBflag[offlineCh] = BBflag;
250 0 : aBGflag[offlineCh] = BGflag;
251 :
252 : // HPTDC data (leading time and width)
253 0 : const Int_t board = AliADCalibData::GetBoardNumber(offlineCh);
254 0 : const Float_t time = rawStream.GetTime(iChannel) * fCalibData->GetTimeResolution(board);
255 0 : const Float_t width = rawStream.GetWidth(iChannel) * fCalibData->GetWidthResolution(board);
256 : // Add a digit
257 0 : if(!fCalibData->IsChannelDead(offlineCh)){
258 0 : new ((*fDigitsArray)[fDigitsArray->GetEntriesFast()])
259 0 : AliADdigit(offlineCh, time, width,integrator, chargeADC, BBflag, BGflag);
260 : }
261 :
262 0 : fESDADfriend->SetBBScalers(offlineCh, rawStream.GetBBScalers(iChannel));
263 0 : fESDADfriend->SetBGScalers(offlineCh, rawStream.GetBGScalers(iChannel));
264 0 : for (Int_t iEv=0; iEv<kADNClocks; ++iEv) {
265 0 : fESDADfriend->SetBBFlag(offlineCh, iEv, rawStream.GetBBFlag(iChannel, iEv));
266 0 : fESDADfriend->SetBGFlag(offlineCh, iEv, rawStream.GetBGFlag(iChannel, iEv));
267 : }
268 0 : }
269 : //BC Unmasked triggers
270 : Int_t pBBmulADA = 0;
271 : Int_t pBBmulADC = 0;
272 : Int_t pBGmulADA = 0;
273 : Int_t pBGmulADC = 0;
274 :
275 0 : for (Int_t iChannel=0; iChannel<4; ++iChannel) {//Loop over pairs of pads
276 : //Enable time is used to turn off the coincidence
277 0 : pBBmulADC += ((!fCalibData->GetEnableTiming(iChannel+ 0) || aBBflag[iChannel+ 0]) && (!fCalibData->GetEnableTiming(iChannel+ 4) || aBBflag[iChannel+ 4]));
278 0 : pBGmulADC += ((!fCalibData->GetEnableTiming(iChannel+ 0) || aBGflag[iChannel+ 0]) && (!fCalibData->GetEnableTiming(iChannel+ 4) || aBGflag[iChannel+ 4]));
279 :
280 0 : pBBmulADA += ((!fCalibData->GetEnableTiming(iChannel+ 8) || aBBflag[iChannel+ 8]) && (!fCalibData->GetEnableTiming(iChannel+12) || aBBflag[iChannel+12]));
281 0 : pBGmulADA += ((!fCalibData->GetEnableTiming(iChannel+ 8) || aBGflag[iChannel+ 8]) && (!fCalibData->GetEnableTiming(iChannel+12) || aBGflag[iChannel+12]));
282 : }
283 :
284 0 : const Bool_t UBA = (pBBmulADA >= fCalibData->GetBBAThreshold());
285 0 : const Bool_t UBC = (pBBmulADC >= fCalibData->GetBBCThreshold());
286 0 : const Bool_t UGA = (pBGmulADA >= fCalibData->GetBGAThreshold());
287 0 : const Bool_t UGC = (pBGmulADC >= fCalibData->GetBGCThreshold());
288 :
289 0 : const UShort_t fTrigger = MakeTriggerFlags(UBA, UBC,
290 0 : UGA, UGC);
291 :
292 0 : fESDADfriend->SetTriggerInputs(fTrigger);
293 0 : fESDADfriend->SetTriggerInputsMask(rawStream.GetTriggerInputsMask());
294 :
295 0 : for (Int_t iScaler=0; iScaler<AliESDADfriend::kNScalers; ++iScaler) {
296 0 : fESDADfriend->SetTriggerScalers(iScaler, rawStream.GetTriggerScalers(iScaler));
297 : }
298 0 : digitsTree->Fill();
299 0 : }
300 :
301 0 : fDigitsArray->Clear();
302 0 : }
303 :
304 : //_____________________________________________________________________________
305 : void AliADReconstructor::FillESD(TTree* digitsTree, TTree* /*clustersTree*/,AliESDEvent* esd) const
306 : {
307 0 : printf("Running AD Reconstruction \n");
308 :
309 0 : if (!digitsTree) {
310 0 : AliError("No digits tree!");
311 0 : return;
312 : }
313 :
314 0 : TBranch* digitBranch = digitsTree->GetBranch("ADDigit");
315 0 : digitBranch->SetAddress(&fDigitsArray);
316 :
317 0 : Float_t mult[16];
318 0 : Float_t adc[16];
319 0 : Float_t tail[16];
320 0 : Float_t tailComplement[16];
321 0 : Float_t time[16];
322 0 : Float_t width[16];
323 0 : Bool_t aBBflag[16];
324 0 : Bool_t aBGflag[16];
325 0 : Float_t adcTrigger[16];
326 :
327 0 : for (Int_t i=0; i<16; i++){
328 0 : adc[i] = 0.0f;
329 0 : tail[i] = 0.0f;
330 0 : tailComplement[i] = 0.0f;
331 0 : mult[i] = 0.0f;
332 0 : time[i] = kInvalidTime;
333 0 : width[i] = 0.0f;
334 0 : aBBflag[i] = kFALSE;
335 0 : aBGflag[i] = kFALSE;
336 0 : adcTrigger[i] = 0.0f;
337 : }
338 :
339 0 : TClonesArray *f_Int0 = new TClonesArray;
340 0 : TClonesArray *f_Int1 = new TClonesArray;
341 0 : Int_t chOffline=0, chOnline=0;
342 0 : Float_t extrapolationThresholds[kADNClocks];
343 0 : Bool_t doExtrapolation[kADNClocks];
344 0 : for (Int_t i=0; i<kADNClocks; ++i) {
345 0 : extrapolationThresholds[i] = -999.0f;
346 0 : doExtrapolation[i] = kFALSE;
347 : }
348 0 : Float_t chargeEqualizationFactor = 1.0f;
349 0 : if (fCorrectForSaturation) {
350 0 : fSaturationCorrection->SetBranchAddress("f_Int0", &f_Int0);
351 0 : fSaturationCorrection->SetBranchAddress("f_Int1", &f_Int1);
352 0 : fSaturationCorrection->SetBranchAddress("chOffline", &chOffline);
353 0 : fSaturationCorrection->SetBranchAddress("chOnline", &chOnline);
354 0 : fSaturationCorrection->SetBranchAddress("extrapolationThresholds", &extrapolationThresholds);
355 0 : fSaturationCorrection->SetBranchAddress("doExtrapolation", &doExtrapolation);
356 0 : fSaturationCorrection->SetBranchAddress("chargeEqualizationFactor", &chargeEqualizationFactor);
357 0 : }
358 : Bool_t correctedForSaturation = kFALSE;
359 :
360 0 : for (Long64_t e=0, n=digitsTree->GetEntries(); e<n; ++e) {
361 0 : digitsTree->GetEvent(e);
362 :
363 0 : for (Int_t d=0, m=fDigitsArray->GetEntriesFast(); d<m; ++d) {
364 0 : const AliADdigit* digit = dynamic_cast<const AliADdigit*>(fDigitsArray->At(d));
365 0 : const Int_t pmNumber = digit->PMNumber();
366 :
367 : // Pedestal retrieval and suppression
368 0 : Bool_t integrator = digit->Integrator();
369 : Float_t maxadc = 0.0f;
370 : Int_t imax = -1;
371 0 : Float_t adcPedSub[kADNClocks] = { 0 };
372 0 : for (Int_t iClock=0; iClock<kADNClocks; ++iClock) {
373 0 : const Short_t charge = digit->ChargeADC(iClock);
374 0 : const Bool_t iIntegrator = ((iClock%2) == 0 ? integrator : !integrator);
375 :
376 0 : const Int_t k = pmNumber + 16*iIntegrator;
377 0 : adcPedSub[iClock] = static_cast<Float_t>(charge) - fCalibData->GetPedestal(k);
378 0 : if(adcPedSub[iClock] <= GetRecoParam()->GetNSigmaPed()*fCalibData->GetSigma(k)) {
379 0 : adcPedSub[iClock] = 0;
380 0 : continue;
381 : }
382 :
383 0 : if (iClock < GetRecoParam()->GetStartClock() ||
384 0 : iClock > GetRecoParam()->GetEndClock()) continue;
385 :
386 0 : if (adcPedSub[iClock] > maxadc) {
387 : maxadc = adcPedSub[iClock];
388 : imax = iClock;
389 0 : }
390 0 : }
391 :
392 : // start and end BCs for charge integration
393 0 : const Int_t start = TMath::Max( 0, imax - GetRecoParam()->GetNPreClocks());
394 0 : const Int_t end = TMath::Min(20, imax + GetRecoParam()->GetNPostClocks());
395 :
396 : // start and end BCs for tail charge integration
397 0 : const Int_t tailBegin = GetRecoParam()->GetTailBegin();
398 0 : const Int_t tailEnd = GetRecoParam()->GetTailEnd();
399 :
400 : // integrated charge without saturation correction
401 0 : adc[pmNumber] = 0.0f;
402 0 : for (Int_t iClock=start; iClock<=end; ++iClock)
403 0 : adc[pmNumber] += adcPedSub[iClock];
404 :
405 : // HPTDC leading time and width
406 : // Correction for slewing and various time delays
407 0 : time[pmNumber] = CorrectLeadingTime(pmNumber, digit->Time(), adc[pmNumber]);
408 0 : width[pmNumber] = digit->Width();
409 0 : aBBflag[pmNumber] = digit->GetBBflag();
410 0 : aBGflag[pmNumber] = digit->GetBGflag();
411 :
412 0 : if (imax != -1) {
413 : const Float_t threshold = 20.0f;
414 : Bool_t isPileUp = kFALSE;
415 0 : for (Int_t bc=13; bc<kADNClocks-1 && !isPileUp; ++bc)
416 0 : isPileUp |= (adcPedSub[bc+1] > adcPedSub[bc] + threshold);
417 :
418 :
419 0 : for (Int_t iClock=tailBegin; iClock<=tailEnd; ++iClock)
420 0 : tail[pmNumber] += adcPedSub[iClock];
421 :
422 0 : adcTrigger[pmNumber] = adcPedSub[10];
423 :
424 0 : for (Int_t iClock=end+1; iClock<kADNClocks; ++iClock)
425 0 : tailComplement[pmNumber] += adcPedSub[iClock];
426 :
427 0 : if (fCorrectForSaturation) {
428 0 : f_Int0->Clear();
429 0 : f_Int1->Clear();
430 0 : fSaturationCorrection->GetEntry(pmNumber);
431 0 : }
432 :
433 0 : AliDebug(3, Form("pmNumber=%d offlineCh=%d onlineCh=%d isPileUp=%d", pmNumber, chOffline, chOnline, isPileUp));
434 0 : adc[pmNumber] = 0.0f;
435 0 : for (Int_t iClock=start; iClock<=end; ++iClock) {
436 0 : const Bool_t iIntegrator = ((iClock%2) == 0 ? integrator : !integrator);
437 :
438 0 : const TF1* fExtrapolation = (doExtrapolation[iClock]
439 0 : ? static_cast<const TF1*>(iIntegrator
440 0 : ? f_Int1->At(iClock)
441 0 : : f_Int0->At(iClock))
442 : : NULL);
443 0 : correctedForSaturation |= doExtrapolation[iClock];
444 0 : if (doExtrapolation[iClock]) {
445 0 : AliDebug(3, Form("Ch%02d bc%02d %d tail=%6.1f thr=%6.1f adc=%6.1f adcCorr=%7.1f",
446 : pmNumber, iClock, doExtrapolation[iClock], tail[pmNumber], extrapolationThresholds[iClock],
447 : adcPedSub[iClock], fExtrapolation->Eval(tail[pmNumber])));
448 : }
449 :
450 0 : adc[pmNumber] += chargeEqualizationFactor*((doExtrapolation[iClock] && tail[pmNumber] > extrapolationThresholds[iClock])
451 0 : ? fExtrapolation->Eval(tail[pmNumber])
452 0 : : adcPedSub[iClock]
453 : );
454 : }
455 : // if the tail charge is biased by after-pulses/pileup it's sign is reversed
456 : // (this implies also that the correction for ADC saturation is biased)
457 0 : if (isPileUp)
458 0 : tail[pmNumber] *= -1;
459 0 : }
460 :
461 0 : AliDebug(3, Form("ADreco: GetRecoParam()->GetNPreClocks()=%d, GetRecoParam()->GetNPostClocks()=%d imax=%d maxadc=%.1f adc[%2d]=%.1f tail[%2d]=%.1f tailC=%.1f",
462 : GetRecoParam()->GetNPreClocks(),
463 : GetRecoParam()->GetNPostClocks(),
464 : imax,
465 : maxadc,
466 : pmNumber,
467 : adc[pmNumber],
468 : pmNumber,
469 : tail[pmNumber],
470 : tailComplement[pmNumber]));
471 :
472 : // MIP multiplicity
473 0 : const Float_t adcPerMIP = const_cast<AliADCalibData*>(fCalibData)->GetADCperMIP(pmNumber);
474 0 : mult[pmNumber] = (adcPerMIP != 0 ? adc[pmNumber]/adcPerMIP : 0.0f);
475 :
476 0 : if (adc[pmNumber] > 0) {
477 0 : AliDebug(1, Form("PM = %d ADC = %.2f (%.2f) TDC %.2f (%.2f) Int %d (%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d) %.2f %.2f %.2f %.2f %d %d",
478 : pmNumber, adc[pmNumber],
479 : digit->ChargeADC(11)+digit->ChargeADC(10)+digit->ChargeADC(9)+digit->ChargeADC(8)+
480 : digit->ChargeADC(7)+digit->ChargeADC(6)+digit->ChargeADC(5)+digit->ChargeADC(4)-
481 : 4.*fCalibData->GetPedestal(pmNumber)-4.*fCalibData->GetPedestal(pmNumber+16),
482 : digit->Time(), time[pmNumber],
483 : integrator,
484 : digit->ChargeADC(0), digit->ChargeADC(1), digit->ChargeADC(2), digit->ChargeADC(3), digit->ChargeADC(4), digit->ChargeADC(5), digit->ChargeADC(6), digit->ChargeADC(7),
485 : digit->ChargeADC(8), digit->ChargeADC(9), digit->ChargeADC(10),
486 : digit->ChargeADC(11), digit->ChargeADC(12),
487 : digit->ChargeADC(13), digit->ChargeADC(14), digit->ChargeADC(15), digit->ChargeADC(16), digit->ChargeADC(17), digit->ChargeADC(18), digit->ChargeADC(19), digit->ChargeADC(20),
488 : fCalibData->GetPedestal(pmNumber), fCalibData->GetSigma(pmNumber),
489 : fCalibData->GetPedestal(pmNumber+16), fCalibData->GetSigma(pmNumber+16),
490 : aBBflag[pmNumber], aBGflag[pmNumber]));
491 : };
492 :
493 : // Fill ESD friend object
494 0 : for (Int_t iEv=0; iEv < kADNClocks; ++iEv) {
495 0 : fESDADfriend->SetPedestal (pmNumber, iEv, static_cast<Float_t>(digit->ChargeADC(iEv)));
496 0 : fESDADfriend->SetIntegratorFlag(pmNumber, iEv, ((iEv%2) == 0 ? integrator : !integrator));
497 : }
498 0 : fESDADfriend->SetTime (pmNumber, digit->Time());
499 0 : fESDADfriend->SetWidth(pmNumber, digit->Width());
500 0 : } // end of loop over digits
501 : } // end of loop over events in digits tree
502 :
503 0 : if (fCorrectForSaturation)
504 0 : fSaturationCorrection->ResetBranchAddresses();
505 :
506 0 : fESDAD->SetBit(AliESDAD::kCorrectedLeadingTime, kTRUE);
507 0 : fESDAD->SetBit(AliESDAD::kCorrectedForSaturation, correctedForSaturation);
508 0 : fESDAD->SetMultiplicity(mult);
509 0 : fESDAD->SetADC(adc);
510 0 : fESDAD->SetTime(time);
511 0 : fESDAD->SetWidth(width);
512 0 : fESDAD->SetBBFlag(aBBflag);
513 0 : fESDAD->SetBGFlag(aBGflag);
514 0 : fESDAD->SetADCTail(tail);
515 0 : fESDAD->SetADCTrigger(adcTrigger);
516 :
517 : // Fill BB and BG flags for all channel in 21 clocks (called past-future flags)
518 0 : for (Int_t i=0; i<16; ++i) {
519 0 : for (Int_t iClock=0; iClock<kADNClocks; ++iClock) {
520 0 : fESDAD->SetPFBBFlag(i, iClock, fESDADfriend->GetBBFlag(i, iClock));
521 0 : fESDAD->SetPFBGFlag(i, iClock, fESDADfriend->GetBGFlag(i, iClock));
522 : }
523 : }
524 0 : fESDAD->SetBit(AliESDAD::kPastFutureFlagsFilled, kTRUE);
525 :
526 : Int_t pBBmulADA = 0;
527 : Int_t pBBmulADC = 0;
528 : Int_t pBGmulADA = 0;
529 : Int_t pBGmulADC = 0;
530 :
531 0 : for (Int_t iChannel=0; iChannel<4; ++iChannel) {//Loop over pairs of pads
532 : //Enable time is used to turn off the coincidence
533 0 : pBBmulADC += ((!fCalibData->GetEnableTiming(iChannel+ 0) || aBBflag[iChannel+ 0]) && (!fCalibData->GetEnableTiming(iChannel+ 4) || aBBflag[iChannel+ 4]));
534 0 : pBGmulADC += ((!fCalibData->GetEnableTiming(iChannel+ 0) || aBGflag[iChannel+ 0]) && (!fCalibData->GetEnableTiming(iChannel+ 4) || aBGflag[iChannel+ 4]));
535 :
536 0 : pBBmulADA += ((!fCalibData->GetEnableTiming(iChannel+ 8) || aBBflag[iChannel+ 8]) && (!fCalibData->GetEnableTiming(iChannel+12) || aBBflag[iChannel+12]));
537 0 : pBGmulADA += ((!fCalibData->GetEnableTiming(iChannel+ 8) || aBGflag[iChannel+ 8]) && (!fCalibData->GetEnableTiming(iChannel+12) || aBGflag[iChannel+12]));
538 : }
539 :
540 0 : const Bool_t UBA = (pBBmulADA >= fCalibData->GetBBAThreshold());
541 0 : const Bool_t UBC = (pBBmulADC >= fCalibData->GetBBCThreshold());
542 0 : const Bool_t UGA = (pBGmulADA >= fCalibData->GetBGAThreshold());
543 0 : const Bool_t UGC = (pBGmulADC >= fCalibData->GetBGCThreshold());
544 :
545 0 : const UShort_t fTrigger = MakeTriggerFlags(UBA, UBC,
546 0 : UGA, UGC);
547 :
548 0 : fESDAD->SetTriggerBits(fTrigger);
549 0 : fESDAD->SetBit(AliESDAD::kOnlineBitsFilled,kTRUE);
550 :
551 : // now fill the AD decision
552 0 : AliADDecision offlineDecision;
553 0 : offlineDecision.SetRecoParam(GetRecoParam());
554 0 : offlineDecision.FillDecisions(fESDAD);
555 :
556 0 : if (NULL != esd) {
557 0 : AliDebug(1, Form("Writing AD data to ESD tree"));
558 0 : esd->SetADData(fESDAD);
559 :
560 0 : AliESDfriend *fr = dynamic_cast<AliESDfriend*>(esd->FindListObject("AliESDfriend"));
561 0 : if (NULL != fr) {
562 0 : AliDebug(1, Form("Writing AD friend data to ESD tree"));
563 0 : fr->SetADfriend(fESDADfriend);
564 : }
565 0 : }
566 :
567 0 : fDigitsArray->Clear();
568 0 : }
569 :
570 : //_____________________________________________________________________________
571 : const AliADCalibData* AliADReconstructor::GetCalibData() const
572 : {
573 0 : AliCDBManager *man = AliCDBManager::Instance();
574 0 : AliCDBEntry *entry = man->Get("AD/Calib/Data");
575 : const AliADCalibData *calibdata = NULL;
576 :
577 0 : if (NULL != entry)
578 0 : calibdata = dynamic_cast<const AliADCalibData*>(entry->GetObject());
579 0 : if (NULL == calibdata)
580 0 : AliFatal("No calibration data from calibration database !");
581 :
582 0 : return calibdata;
583 0 : }
584 :
585 : //_____________________________________________________________________________
586 : void AliADReconstructor::GetTimeSlewingSplines()
587 : {
588 0 : AliCDBManager *man = AliCDBManager::Instance();
589 0 : AliCDBEntry *entry = man->Get("AD/Calib/TimeSlewing");
590 : TList *fListSplines = NULL;
591 :
592 0 : if (NULL != entry)
593 0 : fListSplines = dynamic_cast<TList*>(entry->GetObject());
594 0 : if (NULL == fListSplines)
595 0 : AliFatal("No time slewing correction from calibration database !");
596 :
597 0 : for (Int_t i=0; i<16; ++i)
598 0 : fTimeSlewingSpline[i] = dynamic_cast<TSpline3*>(fListSplines->At(i));
599 0 : }
600 :
601 : //_____________________________________________________________________________
602 : AliCDBStorage* AliADReconstructor::SetStorage(const char *uri)
603 : {
604 : // Sets the storage
605 : Bool_t deleteManager = kFALSE;
606 0 : AliCDBManager *manager = AliCDBManager::Instance();
607 0 : AliCDBStorage *defstorage = manager->GetDefaultStorage();
608 :
609 0 : if(!defstorage || !(defstorage->Contains("AD"))) {
610 0 : AliWarning("No default storage set or default storage doesn't contain AD!");
611 0 : manager->SetDefaultStorage(uri);
612 : deleteManager = kTRUE;
613 0 : }
614 :
615 0 : AliCDBStorage *storage = manager->GetDefaultStorage();
616 0 : if(deleteManager) {
617 0 : AliCDBManager::Instance()->UnsetDefaultStorage();
618 : defstorage = 0; // the storage is killed by AliCDBManager::Instance()->Destroy()
619 0 : }
620 :
621 0 : return storage;
622 : }
623 :
624 : //____________________________________________________________________________
625 : void AliADReconstructor::GetCollisionMode()
626 : {
627 : // Retrieval of collision mode
628 0 : const TString beamType = GetRunInfo()->GetBeamType();
629 0 : if (beamType == AliGRPObject::GetInvalidString()) {
630 0 : AliError("AD cannot retrieve beam type");
631 0 : return;
632 : }
633 0 : if((beamType.CompareTo("P-P") ==0) ||
634 0 : (beamType.CompareTo("p-p") ==0)) {
635 0 : fCollisionMode = 0;
636 0 : } else if ((beamType.CompareTo("Pb-Pb") == 0) ||
637 0 : (beamType.CompareTo("A-A") == 0)) {
638 0 : fCollisionMode = 1;
639 0 : }
640 :
641 0 : fBeamEnergy = GetRunInfo()->GetBeamEnergy();
642 0 : if (fBeamEnergy == AliGRPObject::GetInvalidFloat()) {
643 0 : AliError("Missing value for the beam energy ! Using 0");
644 0 : fBeamEnergy = 0.;
645 0 : }
646 :
647 0 : AliDebug(1, Form("\n ++++++ Beam type and collision mode retrieved as %s %d @ %1.3f GeV ++++++\n\n", beamType.Data(), fCollisionMode, fBeamEnergy));
648 0 : }
649 : //____________________________________________________________________________
650 : Float_t AliADReconstructor::CorrectLeadingTime(Int_t i, Float_t time, Float_t adc) const
651 : {
652 : // Correct the leading time
653 : // for slewing effect and
654 : // misalignment of the channels
655 0 : if (time < 1e-6)
656 0 : return kInvalidTime;
657 :
658 : // In case of pathological signals
659 0 : if (adc < 1.0)
660 0 : return time;
661 :
662 : // Slewing and offset correction
663 0 : const Int_t board = AliADCalibData::GetBoardNumber(i);
664 0 : time -= fTimeSlewingSpline[i]->Eval(TMath::Log10(1/adc))*fCalibData->GetTimeResolution(board);
665 0 : time += fLayerDist[i/4];
666 :
667 : // Channel alignment and general offset subtraction
668 : //time -= fHptdcOffset[i];
669 : return time;
670 0 : }
|