3 /**************************************************************************
4 * This file is property of and copyright by the ALICE HLT Project *
5 * ALICE Experiment at CERN, All rights reserved. *
7 * Authors: Kenneth Aamodt <Kenneth.Aamodt@student.uib.no> *
8 * for The ALICE HLT Project. *
10 * Permission to use, copy, modify and distribute this software and its *
11 * documentation strictly for non-commercial purposes is hereby granted *
12 * without fee, provided that the above copyright notice appears in all *
13 * copies and that both the copyright notice and this permission notice *
14 * appear in the supporting documentation. The authors make no claims *
15 * about the suitability of this software for any purpose. It is *
16 * provided "as is" without express or implied warranty. *
17 **************************************************************************/
19 /** @file AliHLTTPCPadArray.cxx
20 @author Kenneth Aamodt
22 @brief Class containing TPC Pad objects.
25 // see header file for class documentation
27 // refer to README to build package
29 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
36 #include "AliHLTTPCPadArray.h"
37 #include "AliHLTTPCPad.h"
38 #include "AliHLTStdIncludes.h"
39 #include "AliHLTTPCTransform.h"
40 #include "AliHLTTPCDigitReader.h"
41 #include "AliHLTTPCClusters.h"
45 /** ROOT macro for the implementation of ROOT specific class methods */
46 ClassImp(AliHLTTPCPadArray)
48 AliHLTTPCPadArray::AliHLTTPCPadArray()
56 fNumberOfPadsInRow(NULL),
62 // see header file for class documentation
64 // refer to README to build package
66 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
69 AliHLTTPCPadArray::AliHLTTPCPadArray(Int_t patch)
77 fNumberOfPadsInRow(NULL),
83 // see header file for class documentation
86 AliHLTTPCPadArray::~AliHLTTPCPadArray()
88 // see header file for class documentation
91 Int_t AliHLTTPCPadArray::InitializeVector(Int_t mode)
93 // see header file for class documentation
95 if(fPatch>5||fPatch<0){
96 HLTFatal("Patch is not set");
100 fFirstRow = AliHLTTPCTransform::GetFirstRow(fPatch);
101 fLastRow = AliHLTTPCTransform::GetLastRow(fPatch);
103 fNumberOfRows=fLastRow-fFirstRow+1;
104 fNumberOfPadsInRow= new Int_t[fNumberOfRows];
106 memset( fNumberOfPadsInRow, 0, sizeof(Int_t)*(fNumberOfRows));
108 for(Int_t i=0;i<fNumberOfRows;i++){
109 fNumberOfPadsInRow[i]=AliHLTTPCTransform::GetNPads(i+fFirstRow);
110 AliHLTTPCPadVector tmpRow;
111 for(Int_t j=0;j<fNumberOfPadsInRow[i];j++){
112 AliHLTTPCPad *tmpPad = new AliHLTTPCPad();
114 tmpRow.push_back(tmpPad);
116 fRowPadVector.push_back(tmpRow);
121 Int_t AliHLTTPCPadArray::DeInitializeVector()
123 // see header file for class documentation
124 for(Int_t i=0;i<fNumberOfRows;i++){
125 for(Int_t j=0;j<fNumberOfPadsInRow[i];j++){
126 delete fRowPadVector[i][j];
128 fRowPadVector[i].clear();
130 fRowPadVector.clear();
134 void AliHLTTPCPadArray::SetPatch(Int_t patch)
136 // see header file for class documentation
140 void AliHLTTPCPadArray::SetDigitReader(AliHLTTPCDigitReader* digitReader)
142 // see header file for class documentation
143 fDigitReader=digitReader;
146 Int_t AliHLTTPCPadArray::ReadData(Int_t mode)
148 // see header file for class documentation
153 while(fDigitReader->Next()){
154 UInt_t row = fDigitReader->GetRow();
155 UInt_t pad = fDigitReader->GetPad();
156 UInt_t time = fDigitReader->GetTime();
157 if(row<fNumberOfRows){
158 if(pad<fNumberOfPadsInRow[row]&&time<AliHLTTPCTransform::GetNTimeBins()){
159 fRowPadVector[row][pad]->SetDataSignal(time,fDigitReader->GetSignal());
165 while(fDigitReader->NextChannel()){
166 while(fDigitReader->NextBunch()){
167 const UInt_t *bunchData= fDigitReader->GetSignals();
168 UInt_t row=fDigitReader->GetRow();
169 UInt_t pad=fDigitReader->GetPad();
170 UInt_t time=fDigitReader->GetTime();
171 AliHLTTPCClusters candidate;
172 for(Int_t i=0;i<fDigitReader->GetBunchSize();i++){
173 candidate.fTotalCharge+=bunchData[i];
174 candidate.fTime += time*bunchData[i];
175 candidate.fTime2 += time*time*bunchData[i];
178 if(candidate.fTotalCharge>0){
179 candidate.fMean=candidate.fTime/candidate.fTotalCharge;
180 candidate.fPad=candidate.fTotalCharge*pad;
181 candidate.fPad2=candidate.fPad*pad;
182 candidate.fLastMergedPad=pad;
183 fRowPadVector[row][pad]->AddClusterCandidate(candidate);
192 while(fDigitReader->Next()){
193 UInt_t row = fDigitReader->GetRow()-fFirstRow;
194 UInt_t pad = fDigitReader->GetPad();
195 UInt_t time = fDigitReader->GetTime();
196 if(row<fNumberOfRows){
197 if(pad<fNumberOfPadsInRow[row]&&time<AliHLTTPCTransform::GetNTimeBins()){
198 fRowPadVector[row][pad]->SetDataSignal(time,fDigitReader->GetSignal());
204 while(fDigitReader->NextChannel()){
205 while(fDigitReader->NextBunch()){
206 const UInt_t *bunchData= fDigitReader->GetSignals();
207 UInt_t row=fDigitReader->GetRow();
208 UInt_t pad=fDigitReader->GetPad();
209 UInt_t time=fDigitReader->GetTime();
210 AliHLTTPCClusters candidate;
211 for(Int_t i=0;i<fDigitReader->GetBunchSize();i++){
212 candidate.fTotalCharge+=bunchData[i];
213 candidate.fTime += time*bunchData[i];
214 candidate.fTime2 += time*time*bunchData[i];
217 if(candidate.fTotalCharge>0){
218 candidate.fMean=candidate.fTime/candidate.fTotalCharge;
219 candidate.fPad=candidate.fTotalCharge*pad;
220 candidate.fPad2=candidate.fPad*pad;
221 candidate.fLastMergedPad=pad;
222 fRowPadVector[row][pad]->AddClusterCandidate(candidate);
232 while(fDigitReader->Next()){
233 UInt_t row=fDigitReader->GetRow();
234 UInt_t pad=fDigitReader->GetPad();
235 UInt_t time= fDigitReader->GetTime();
236 if(row<fNumberOfRows){
237 if(pad<fNumberOfPadsInRow[row]&&time<AliHLTTPCTransform::GetNTimeBins()){
238 fRowPadVector[fDigitReader->GetRow()][fDigitReader->GetPad()]->SetDataSignal(fDigitReader->GetTime(),fDigitReader->GetSignal());
244 while(fDigitReader->NextChannel()){
245 while(fDigitReader->NextBunch()){
246 const UInt_t *bunchData= fDigitReader->GetSignals();
247 UInt_t row=fDigitReader->GetRow();
248 UInt_t pad=fDigitReader->GetPad();
249 UInt_t time=fDigitReader->GetTime();
250 AliHLTTPCClusters candidate;
251 for(Int_t i=0;i<fDigitReader->GetBunchSize();i++){
252 candidate.fTotalCharge+=bunchData[i];
253 candidate.fTime += time*bunchData[i];
254 candidate.fTime2 += time*time*bunchData[i];
257 if(candidate.fTotalCharge>0){
258 candidate.fMean=candidate.fTime/candidate.fTotalCharge;
259 candidate.fPad=candidate.fTotalCharge*pad;
260 candidate.fPad2=candidate.fPad*pad;
261 candidate.fLastMergedPad=pad;
262 fRowPadVector[row][pad]->AddClusterCandidate(candidate);
270 while(fDigitReader->Next()){
271 UInt_t row=fDigitReader->GetRow()-27;
272 UInt_t pad=fDigitReader->GetPad();
273 UInt_t time= fDigitReader->GetTime();
274 if(row<fNumberOfRows){
275 if(pad<fNumberOfPadsInRow[row]&&time<AliHLTTPCTransform::GetNTimeBins()){
276 fRowPadVector[row][pad]->SetDataSignal(time,fDigitReader->GetSignal());
282 while(fDigitReader->NextChannel()){
283 while(fDigitReader->NextBunch()){
284 const UInt_t *bunchData= fDigitReader->GetSignals();
285 UInt_t row=fDigitReader->GetRow();
286 UInt_t pad=fDigitReader->GetPad();
287 UInt_t time=fDigitReader->GetTime();
288 AliHLTTPCClusters candidate;
289 for(Int_t i=0;i<fDigitReader->GetBunchSize();i++){
290 candidate.fTotalCharge+=bunchData[i];
291 candidate.fTime += time*bunchData[i];
292 candidate.fTime2 += time*time*bunchData[i];
295 if(candidate.fTotalCharge>0){
296 candidate.fMean=candidate.fTime/candidate.fTotalCharge;
297 candidate.fPad=candidate.fTotalCharge*pad;
298 candidate.fPad2=candidate.fPad*pad;
299 candidate.fLastMergedPad=pad;
300 fRowPadVector[row][pad]->AddClusterCandidate(candidate);
308 while(fDigitReader->Next()){
309 UInt_t row=fDigitReader->GetRow()-54;
310 UInt_t pad=fDigitReader->GetPad();
311 UInt_t time= fDigitReader->GetTime();
312 if(row<fNumberOfRows){
313 if(pad<fNumberOfPadsInRow[row]&&time<AliHLTTPCTransform::GetNTimeBins()){
314 fRowPadVector[row][pad]->SetDataSignal(time,fDigitReader->GetSignal());
320 while(fDigitReader->NextChannel()){
321 while(fDigitReader->NextBunch()){
322 const UInt_t *bunchData= fDigitReader->GetSignals();
323 UInt_t row=fDigitReader->GetRow();
324 UInt_t pad=fDigitReader->GetPad();
325 UInt_t time=fDigitReader->GetTime();
326 AliHLTTPCClusters candidate;
327 for(Int_t i=0;i<fDigitReader->GetBunchSize();i++){
328 candidate.fTotalCharge+=bunchData[i];
329 candidate.fTime += time*bunchData[i];
330 candidate.fTime2 += time*time*bunchData[i];
333 if(candidate.fTotalCharge>0){
334 candidate.fMean=candidate.fTime/candidate.fTotalCharge;
335 candidate.fPad=candidate.fTotalCharge*pad;
336 candidate.fPad2=candidate.fPad*pad;
337 candidate.fLastMergedPad=pad;
338 fRowPadVector[row][pad]->AddClusterCandidate(candidate);
348 while(fDigitReader->Next()){
349 UInt_t row=fDigitReader->GetRow()-76;
350 UInt_t pad=fDigitReader->GetPad();
351 UInt_t time= fDigitReader->GetTime();
352 if(row<fNumberOfRows){
353 if(pad<fNumberOfPadsInRow[row]&&time<AliHLTTPCTransform::GetNTimeBins()){
354 fRowPadVector[row][pad]->SetDataSignal(time,fDigitReader->GetSignal());
360 while(fDigitReader->NextChannel()){
361 while(fDigitReader->NextBunch()){
362 const UInt_t *bunchData= fDigitReader->GetSignals();
363 UInt_t row=fDigitReader->GetRow();
364 UInt_t pad=fDigitReader->GetPad();
365 UInt_t time=fDigitReader->GetTime();
366 AliHLTTPCClusters candidate;
367 for(Int_t i=0;i<fDigitReader->GetBunchSize();i++){
368 candidate.fTotalCharge+=bunchData[i];
369 candidate.fTime += time*bunchData[i];
370 candidate.fTime2 += time*time*bunchData[i];
373 if(candidate.fTotalCharge>0){
374 candidate.fMean=candidate.fTime/candidate.fTotalCharge;
375 candidate.fPad=candidate.fTotalCharge*pad;
376 candidate.fPad2=candidate.fPad*pad;
377 candidate.fLastMergedPad=pad;
378 fRowPadVector[row][pad]->AddClusterCandidate(candidate);
390 void AliHLTTPCPadArray::FindClusters(Int_t match)
392 //see header file for documentation
394 Int_t totalChargeOfPreviousCandidate=0;
395 Int_t clusterChargeIsFalling=0;
396 for(Int_t row=0;row<fNumberOfRows;row++){
397 for(Int_t pad=0;pad<fNumberOfPadsInRow[row]-1;pad++){
398 AliHLTTPCPad *tmp1=fRowPadVector[row][pad];
399 AliHLTTPCPad *tmp2=fRowPadVector[row][pad+1];
400 for(size_t c1=0;c1<tmp1->fClusterCandidates.size();c1++){
402 if(tmp1->fUsedClusterCandidates[c1]){
406 for(size_t c2=0;c2<tmp2->fClusterCandidates.size();c2++){
408 if(tmp2->fUsedClusterCandidates[c2]){
412 Int_t diff= tmp1->fClusterCandidates[c1].fMean - tmp2->fClusterCandidates[c2].fMean;
419 if((Int_t)(tmp1->fClusterCandidates[c1].fTotalCharge - tmp2->fClusterCandidates[c2].fTotalCharge)>0){
420 clusterChargeIsFalling=1;
423 tmp1->fUsedClusterCandidates[c1]=1;
424 tmp2->fUsedClusterCandidates[c2]=1;
426 AliHLTTPCClusters tmpCluster;
427 tmpCluster.fTotalCharge = tmp1->fClusterCandidates[c1].fTotalCharge;
428 tmpCluster.fPad = tmp1->fClusterCandidates[c1].fPad;
429 tmpCluster.fPad2 = tmp1->fClusterCandidates[c1].fPad2;
430 tmpCluster.fTime = tmp1->fClusterCandidates[c1].fTime;
431 tmpCluster.fTime2 = tmp1->fClusterCandidates[c1].fTime2;
432 tmpCluster.fRowNumber = row;
434 tmpCluster.fTotalCharge += tmp2->fClusterCandidates[c2].fTotalCharge;
435 tmpCluster.fPad += tmp2->fClusterCandidates[c2].fPad;
436 tmpCluster.fPad2 += tmp2->fClusterCandidates[c2].fPad2;
437 tmpCluster.fTime += tmp2->fClusterCandidates[c2].fTime;
438 tmpCluster.fTime2 += tmp2->fClusterCandidates[c2].fTime2;
439 tmpCluster.fMean = tmp2->fClusterCandidates[c2].fMean;
440 totalChargeOfPreviousCandidate = tmp2->fClusterCandidates[c2].fTotalCharge;
446 for(Int_t morePads=pad+2;morePads<fNumberOfPadsInRow[row];morePads++){
447 AliHLTTPCPad *tmpx=fRowPadVector[row][morePads];
448 if(morePads>lastPad+1){
451 for(size_t cx=0;cx<tmpx->fClusterCandidates.size();cx++){
452 if(tmpx->fUsedClusterCandidates[cx]){
455 Int_t diffx=tmpCluster.fMean - tmpx->fClusterCandidates[cx].fMean;
461 if((Int_t)(totalChargeOfPreviousCandidate - tmpx->fClusterCandidates[cx].fTotalCharge)>0){
462 clusterChargeIsFalling=1;
465 if(clusterChargeIsFalling&&(Int_t)(totalChargeOfPreviousCandidate - tmpx->fClusterCandidates[cx].fTotalCharge)<=0){
466 //Means we have a deconvoluted cluster.
467 totalChargeOfPreviousCandidate=0;
472 tmpx->fUsedClusterCandidates[cx]=1;
473 tmpCluster.fTotalCharge += tmpx->fClusterCandidates[cx].fTotalCharge;
474 tmpCluster.fPad += tmpx->fClusterCandidates[cx].fPad;
475 tmpCluster.fPad2 += tmpx->fClusterCandidates[cx].fPad2;
476 tmpCluster.fTime += tmpx->fClusterCandidates[cx].fTime;
477 tmpCluster.fTime2 += tmpx->fClusterCandidates[cx].fTime2;
478 tmpCluster.fMean = tmpx->fClusterCandidates[cx].fMean;
481 totalChargeOfPreviousCandidate=tmpx->fClusterCandidates[cx].fTotalCharge;
489 if(tmpCluster.fTotalCharge< UInt_t(fThreshold)){
493 //Code to look for tails, TODO insert flag.
494 /* UInt_t meanTime=tmpCluster.fMean;
496 AliHLTTPCPad *tmpBefore=fRowPadVector[row][pad-1];
497 //checking the fMean -1 timebin for single timebin value in the pad before the cluster
499 Int_t charge =tmpBefore->GetDataSignal(meanTime-1);
501 tmpCluster.fTotalCharge+= charge;
502 tmpCluster.fPad += charge*(pad-1);
503 tmpCluster.fPad2 += charge*(pad-1)*(pad-1);
504 tmpCluster.fTime += meanTime*charge;
505 tmpCluster.fTime2 += meanTime*charge*charge;
508 //checking the fMean timebin for single timebin value in the pad before the cluster
509 Int_t charge2 =tmpBefore->GetDataSignal(meanTime);
511 tmpCluster.fTotalCharge+= charge2;
512 tmpCluster.fPad += charge2*(pad);
513 tmpCluster.fPad2 += charge2*(pad)*(pad);
514 tmpCluster.fTime += meanTime*charge2;
515 tmpCluster.fTime2 += meanTime*charge2*charge2;
517 //checking the fMean +1 timebin for single timebin value in the pad before the cluster
518 if(meanTime<AliHLTTPCTransform::GetNTimeBins()){
519 Int_t charge3 =tmpBefore->GetDataSignal(meanTime+1);
521 tmpCluster.fTotalCharge+= charge3;
522 tmpCluster.fPad += charge3*(pad+1);
523 tmpCluster.fPad2 += charge3*(pad+1)*(pad+1);
524 tmpCluster.fTime += meanTime*charge3;
525 tmpCluster.fTime2 += meanTime*charge3*charge3;
530 if(lastPad<fNumberOfPadsInRow[row]-2){
531 AliHLTTPCPad *tmpAfter=fRowPadVector[row][lastPad+1];
532 //checking the fMean +1 timebin for single timebin value in the pad after the cluster
534 Int_t charge4 =tmpAfter->GetDataSignal(meanTime-1);
536 tmpCluster.fTotalCharge+= charge4;
537 tmpCluster.fPad += charge4*(pad-1);
538 tmpCluster.fPad2 += charge4*(pad-1)*(pad-1);
539 tmpCluster.fTime += meanTime*charge4;
540 tmpCluster.fTime2 += meanTime*charge4*charge4;
545 //checking the fMean +1 timebin for single timebin value in the pad after the cluster
546 Int_t charge5 =tmpAfter->GetDataSignal(meanTime);
548 tmpCluster.fTotalCharge+= charge5;
549 tmpCluster.fPad += charge5*(pad);
550 tmpCluster.fPad2 += charge5*(pad)*(pad);
551 tmpCluster.fTime += meanTime*charge5;
552 tmpCluster.fTime2 += meanTime*charge5*charge5;
554 //checking the fMean +1 timebin for single timebin value in the pad after the cluster
555 if(meanTime<AliHLTTPCTransform::GetNTimeBins()){
556 Int_t charge6 =tmpAfter->GetDataSignal(meanTime+1);
558 tmpCluster.fTotalCharge+= charge6;
559 tmpCluster.fPad += charge6*(pad+1);
560 tmpCluster.fPad2 += charge6*(pad+1)*(pad+1);
561 tmpCluster.fTime += meanTime*charge6;
562 tmpCluster.fTime2 += meanTime*charge6*charge6;
567 // tmpCluster.fTime= tmpCluster.fTime/tmpCluster.fTotalCharge;
568 totalChargeOfPreviousCandidate=0;
569 clusterChargeIsFalling=0;
570 tmpCluster.fFirstPad=pad;
573 tmpCluster.fRowNumber=row;
576 tmpCluster.fRowNumber=row+30;
579 tmpCluster.fRowNumber=row+63;
582 tmpCluster.fRowNumber=row+90;
585 tmpCluster.fRowNumber=row+117;
588 tmpCluster.fRowNumber=row+139;
592 fClusters.push_back(tmpCluster);
600 HLTInfo("Found %d clusters.",nClusters);
604 void AliHLTTPCPadArray::PrintClusters()
606 // see header file for class documentation
607 for(size_t i=0;i<fClusters.size();i++){
608 cout<<"Cluster number: "<<i<<endl;
609 cout<<"Row: "<<fClusters[i].fRowNumber<<" Pad: "<<fClusters[i].fFirstPad<<endl;
610 cout<<"Total Charge: "<<fClusters[i].fTotalCharge<<endl;
611 cout<<"PadError: "<<fClusters[i].fPad2<<endl;
612 cout<<"TimeMean: "<<fClusters[i].fTime<<endl;
613 cout<<"TimeError: "<<fClusters[i].fTime2<<endl;
619 void AliHLTTPCPadArray::DataToDefault()
621 //see header file for documentation
622 for(Int_t i=0;i<fNumberOfRows;i++){
623 for(Int_t j=0;j<fNumberOfPadsInRow[i];j++){
624 fRowPadVector[i][j]->SetDataToDefault();
630 void AliHLTTPCPadArray::FindClusterCandidates()
632 //see header file for documentation
633 if(fNSigmaThreshold>0){
634 for(Int_t row=0;row<fNumberOfRows;row++){
635 for(Int_t pad=0;pad<fNumberOfPadsInRow[row];pad++){
636 fRowPadVector[row][pad]->SetNSigmaThreshold(fNSigmaThreshold);
637 fRowPadVector[row][pad]->FindClusterCandidates();
641 else if(fSignalThreshold>0){
642 for(Int_t row=0;row<fNumberOfRows;row++){
643 for(Int_t pad=0;pad<fNumberOfPadsInRow[row];pad++){
644 fRowPadVector[row][pad]->SetSignalThreshold(fSignalThreshold);
645 fRowPadVector[row][pad]->FindClusterCandidates();
650 for(Int_t row=0;row<fNumberOfRows;row++){
651 for(Int_t pad=0;pad<fNumberOfPadsInRow[row];pad++){
652 fRowPadVector[row][pad]->FindClusterCandidates();
657 Int_t AliHLTTPCPadArray::GetActivePads(AliHLTTPCActivePads * activePads,Int_t maxActivePads){
658 //see header file for documentation
661 for(Int_t row=0;row<fNumberOfRows;row++){
662 for(Int_t pad=0;pad<fNumberOfPadsInRow[row]-1;pad++){
663 if(fRowPadVector[row][pad]->fClusterCandidates.size()>0){
664 Int_t rowOffset=AliHLTTPCTransform::GetFirstRow(fPatch);
665 if (fPatch>=2) rowOffset-=AliHLTTPCTransform::GetFirstRow(2);
666 AliHLTTPCActivePads tmpAP;
667 tmpAP.fRow=row+rowOffset;
669 activePads[counter]= tmpAP;
671 if(counter>=maxActivePads){