3 /**************************************************************************
4 * This file is property of and copyright by the ALICE HLT Project *
5 * ALICE Experiment at CERN, All rights reserved. *
7 * Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no> *
8 * Kenneth Aamodt <Kenneth.aamodt@ift.uib.no> *
9 * for The ALICE HLT Project. *
11 * Permission to use, copy, modify and distribute this software and its *
12 * documentation strictly for non-commercial purposes is hereby granted *
13 * without fee, provided that the above copyright notice appears in all *
14 * copies and that both the copyright notice and this permission notice *
15 * appear in the supporting documentation. The authors make no claims *
16 * about the suitability of this software for any purpose. It is *
17 * provided "as is" without express or implied warranty. *
18 **************************************************************************/
20 /** @file AliHLTTPCPad.cxx
21 @author Matthias Richter, Kenneth Aamodt
23 @brief Container Class for TPC Pads.
26 // see header file for class documentation
28 // refer to README to build package
30 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
37 #include "AliHLTTPCPad.h"
38 #include "AliHLTStdIncludes.h"
42 #include "AliHLTTPCTransform.h"
43 #include "AliHLTTPCClusters.h"
45 //------------------------------
47 /** margin for the base line be re-avaluated */
48 #define ALIHLTPAD_BASELINE_MARGIN (2*fAverage)
50 /** ROOT macro for the implementation of ROOT specific class methods */
51 ClassImp(AliHLTTPCPad)
53 AliHLTTPCPad::AliHLTTPCPad()
56 fUsedClusterCandidates(),
74 fSignalPositionArray(NULL),
75 fSizeOfSignalPositionArray(0),
79 // see header file for class documentation
81 // refer to README to build package
83 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
84 // HLTInfo("Entering default constructor");
85 fDataSignals= new AliHLTTPCSignal_t[AliHLTTPCTransform::GetNTimeBins()];
86 memset( fDataSignals, 0xFF, sizeof(Int_t)*(AliHLTTPCTransform::GetNTimeBins()));
88 fSignalPositionArray= new AliHLTTPCSignal_t[AliHLTTPCTransform::GetNTimeBins()];
89 memset( fSignalPositionArray, 0xFF, sizeof(Int_t)*(AliHLTTPCTransform::GetNTimeBins()));
90 fSizeOfSignalPositionArray=0;
93 AliHLTTPCPad::AliHLTTPCPad(Int_t offset, Int_t nofBins)
96 fUsedClusterCandidates(),
114 fSignalPositionArray(NULL),
115 fSizeOfSignalPositionArray(0),
119 // see header file for class documentation
122 AliHLTTPCPad::~AliHLTTPCPad()
124 // see header file for class documentation
126 HLTWarning("event data acquisition not stopped");
130 AliHLTTPCSignal_t* pData=fDataSignals;
134 if (fSignalPositionArray) {
135 //AliHLTTPCSignal_t* pData=fSignalPositionArray;
136 fSignalPositionArray=NULL;
142 Int_t AliHLTTPCPad::SetID(Int_t rowno, Int_t padno)
144 // see header file for class documentation
150 Int_t AliHLTTPCPad::StartEvent()
152 // see header file for class documentation
154 if (fpRawData==NULL) {
163 fpRawData=new AliHLTTPCSignal_t[fNofBins];
165 for (int i=0; i<fNofBins; i++) fpRawData[i]=-1;
167 HLTError("memory allocation failed");
172 HLTWarning("event data acquisition already started");
178 Int_t AliHLTTPCPad::CalculateBaseLine(Int_t reqMinCount)
180 // see header file for class documentation
182 AliHLTTPCSignal_t avBackup=fAverage;
183 //HLTDebug("reqMinCount=%d fCount=%d fTotal=%d fSum=%d fBLMax=%d fBLMin=%d", reqMinCount, fCount, fTotal, fSum, fBLMax, fBLMin);
184 if (fCount>=reqMinCount && fCount>=fTotal/2) {
185 fAverage=fCount>0?fSum/fCount:0;
187 //HLTDebug("average for current event %d (%d - %d)", fAverage, fBLMax, fBLMin);
189 if (fBLMax>ALIHLTPAD_BASELINE_MARGIN) {
191 //HLTDebug("maximum value %d exceeds margin for base line (%d) "
192 // "-> re-evaluate base line", fBLMax, ALIHLTPAD_BASELINE_MARGIN);
194 for (Int_t i=fFirstBLBin; i<fNofBins; i++)
195 if (fpRawData[i]>=0) AddBaseLineValue(i, fpRawData[i]);
196 if (fCount>0 && fCount>=reqMinCount && fCount>=fTotal/2) {
197 fAverage=fSum/fCount;
198 //HLTDebug("new average %d", fAverage);
200 // HLTDebug("baseline re-eveluation skipped because of to few "
201 // "contributing bins: total=%d, contributing=%d, req=%d"
202 // "\ndata might be already zero suppressed"
203 // , fTotal, fCount, reqMinCount);
208 HLTError("missing raw data for base line calculation");
213 // calculate average for all events
214 fAverage=((avBackup*fNofEvents)+fAverage)/(fNofEvents+1);
215 //HLTDebug("base line average for %d event(s): %d", fNofEvents+1, fAverage);
223 // HLTDebug("baseline calculation skipped because of to few contributing "
224 // "bins: total=%d, contributing=%d, required=%d \ndata might be "
225 // "already zero suppressed", fTotal, fCount, reqMinCount);
231 Int_t AliHLTTPCPad::StopEvent()
233 // see header file for class documentation
236 AliHLTTPCSignal_t* pData=fpRawData;
242 } else if (fNofBins>0) {
243 HLTError("event data acquisition not started");
249 Int_t AliHLTTPCPad::ResetHistory()
251 // see header file for class documentation
258 Int_t AliHLTTPCPad::SetThreshold(AliHLTTPCSignal_t thresh)
260 // see header file for class documentation
266 Int_t AliHLTTPCPad::AddBaseLineValue(Int_t bin, AliHLTTPCSignal_t value)
268 // see header file for class documentation
270 if (bin>=fFirstBLBin) {
271 if (fAverage<0 || value<ALIHLTPAD_BASELINE_MARGIN) {
272 // add to the current sum and count
276 // keep the maximum value for later quality control of the base
281 if (fBLMin<0 || fBLMin>value) {
282 // keep the minimum value for later quality control of the base
288 // HLTDebug("ignoring value %d (bin %d) for base line calculation "
289 // "(current average is %d)",
290 // value, bin, fAverage);
296 Int_t AliHLTTPCPad::SetRawData(Int_t bin, AliHLTTPCSignal_t value)
298 // see header file for class documentation
303 if (fpRawData[bin]<0) {
304 AddBaseLineValue(bin, value);
307 // ignore value for average calculation
308 HLTWarning("overriding content of bin %d (%d)", bin, fpRawData[bin]);
310 fpRawData[bin]=value;
312 HLTWarning("ignoring neg. raw data");
315 HLTWarning("bin %d out of range (%d)", bin, fNofBins);
318 } else if (fNofBins>0) {
319 HLTError("event cycle not started");
325 Int_t AliHLTTPCPad::Next(Int_t bZeroSuppression)
327 // see header file for class documentation
328 if (fpRawData==NULL) return 0;
329 Int_t iResult=fReadPos<fNofBins;
330 if (iResult>0 && (iResult=(++fReadPos<fNofBins))>0) {
331 if (bZeroSuppression) {
332 while ((iResult=(fReadPos<fNofBins))>0 &&
333 GetCorrectedData(fReadPos)<=0)
340 Int_t AliHLTTPCPad::Rewind(Int_t bZeroSuppression)
342 // see header file for class documentation
343 fReadPos=(bZeroSuppression>0?0:fFirstBLBin)-1;
344 return Next(bZeroSuppression);
347 AliHLTTPCSignal_t AliHLTTPCPad::GetRawData(Int_t bin) const
349 // see header file for class documentation
350 AliHLTTPCSignal_t data=0;
355 HLTWarning("requested bin %d out of range (%d)", bin, fNofBins);
357 } else if (fNofBins>0) {
358 HLTWarning("data only available within event cycle");
363 AliHLTTPCSignal_t AliHLTTPCPad::GetCorrectedData(Int_t bin) const
365 // see header file for class documentation
366 AliHLTTPCSignal_t data=GetRawData(bin)-GetBaseLine(bin);
367 AliHLTTPCSignal_t prev=0;
368 if (bin>1) prev=GetRawData(bin-1)-GetBaseLine(bin-1);
369 AliHLTTPCSignal_t succ=0;
370 if (bin+1<GetSize()) succ=GetRawData(bin+1)-GetBaseLine(bin+1);
378 // the signal is below the base-line and threshold
382 // the neighboring bins are both below base-line/threshold
383 // a real signal is always more than one bin wide because of the shaper
384 if (prev<=0 && succ<=0) data=0;
387 // the bin is inside the range of ignored bins
388 if (bin<fFirstBLBin) data=0;
389 //HLTDebug("fReadPos=%d data=%d threshold=%d raw data=%d base line=%d", fReadPos, data, fThreshold, GetRawData(bin), GetBaseLine(bin));
393 AliHLTTPCSignal_t AliHLTTPCPad::GetBaseLine(Int_t /*bin*/) const //TODO: Why is bin being ignored?
395 // see header file for class documentation
396 AliHLTTPCSignal_t val=0;
398 // we take the minumum value as the base line if it doesn't differ from
399 // the average to much
402 const AliHLTTPCSignal_t kMaxDifference=15;
403 if ((fAverage-fBLMin)<=kMaxDifference) val=fBLMin;
404 else val>kMaxDifference?val-=kMaxDifference:0;
408 // here we should never get
410 HLTFatal("wrong base line value");
415 AliHLTTPCSignal_t AliHLTTPCPad::GetAverage() const
417 // see header file for class documentation
418 return fAverage>0?fAverage:0;
421 Float_t AliHLTTPCPad::GetOccupancy() const
423 // see header file for class documentation
425 if (fpRawData && fNofBins>0) {
426 for (Int_t i=fFirstBLBin; i<fNofBins; i++) {
427 if (GetCorrectedData(i)>0) occupancy+=1;
429 if (fNofBins-fFirstBLBin>0)
430 occupancy/=fNofBins-fFirstBLBin;
435 Float_t AliHLTTPCPad::GetAveragedOccupancy() const
437 // see header file for class documentation
439 // history is not yet implemented
440 return GetOccupancy();
442 void AliHLTTPCPad::PrintRawData()
444 // see header file for class documentation
445 for(Int_t bin=0;bin<AliHLTTPCTransform::GetNTimeBins();bin++){
446 if(GetDataSignal(bin)>0)
447 cout<<fRowNo<<"\t"<<fPadNo<<"\t"<<bin<<"\t"<<GetDataSignal(bin)<<endl;;
449 cout<<"bins: "<<AliHLTTPCTransform::GetNTimeBins()<<endl;
452 void AliHLTTPCPad::SetDataToDefault()
454 // see header file for class documentation
456 memset( fDataSignals, 0xFF, sizeof(Int_t)*(AliHLTTPCTransform::GetNTimeBins()));
457 memset( fSignalPositionArray, 0xFF, sizeof(Int_t)*(AliHLTTPCTransform::GetNTimeBins()));
458 fSizeOfSignalPositionArray=0;
462 void AliHLTTPCPad::SetDataSignal(Int_t bin,Int_t signal)
464 // see header file for class documentation
465 fDataSignals[bin]=signal;
466 fSignalPositionArray[fSizeOfSignalPositionArray]=bin;
467 fSizeOfSignalPositionArray++;
470 Int_t AliHLTTPCPad::GetDataSignal(Int_t bin) const
472 // see header file for class documentation
473 return fDataSignals[bin];
476 void AliHLTTPCPad::ZeroSuppress(Double_t nSigma = 3,Int_t threshold = 20 ,Int_t reqMinPoint = AliHLTTPCTransform::GetNTimeBins()/2, Int_t beginTime = 50,Int_t endTime = AliHLTTPCTransform::GetNTimeBins()-1){
477 //see headerfile for documentation
479 Bool_t useSigma= kFALSE;
483 if(threshold<1 && nSigma<=0){
484 //setting the data to -1 for this pad
485 memset( fDataSignals, 0xFF, sizeof(Int_t)*(AliHLTTPCTransform::GetNTimeBins()));
486 fSizeOfSignalPositionArray=0;
489 if(endTime>=AliHLTTPCTransform::GetNTimeBins()){
490 endTime=AliHLTTPCTransform::GetNTimeBins()-1;
493 Int_t fThresholdUsed=threshold;
497 fSizeOfSignalPositionArray=0;
498 for(Int_t i=beginTime;i<endTime+1;i++){
499 if(fDataSignals[i]>0){
501 sumNAdded+=fDataSignals[i];
505 if(nAdded<reqMinPoint){
506 return; //This will ensure that no data is read in FindClusterCandidates() (since fSizeOfSignalPositionArray=0)
509 Double_t averageValue=sumNAdded/nAdded;
513 //Calculate the sigma
514 Double_t sumOfDifferenceSquared=0;
515 for(Int_t i=endTime;i>=beginTime;i--){
516 if(fDataSignals[i]>0){
517 if(fDataSignals[i]-averageValue<50){
518 sumOfDifferenceSquared+=(fDataSignals[i]-averageValue)*(fDataSignals[i]-averageValue);
525 sigma=sumOfDifferenceSquared/nAdded;
526 fThresholdUsed=(Int_t)(nSigma*sigma);
529 //For now just set the adc value outside [beginTime,endTime] to -1
530 for(Int_t i=0;i<beginTime;i++){
533 for(Int_t i=endTime+1;i<AliHLTTPCTransform::GetNTimeBins();i++){
537 // Do zero suppression on the adc values within [beginTime,endTime]
538 for(Int_t i=endTime;i>=beginTime;i--){
539 //the +1 in the if below is there to avoid getting a signal which is 0, adding to the numbers you have to loop over in the end
540 //(better to set it to -1 which is default for no signal)
541 if(fDataSignals[i]>(Int_t)(averageValue+fThresholdUsed+1) && fDataSignals[i-1]>(Int_t)(averageValue+fThresholdUsed+1)){
542 //here the signals below threshold to the right of the candidate is added
543 Bool_t contRight=kTRUE;
547 if(endRight+1<endTime){
548 // cout<<fDataSignals[endRight+1]<<" "<<fDataSignals[endRight+2]<<endl;;
549 if(fDataSignals[endRight+1]>=fDataSignals[endRight+2] && fDataSignals[endRight+1]>averageValue){
553 if(fDataSignals[endRight+1]> averageValue){
559 else if(endRight>endTime+1){
564 for(int j=i+nToAddRight;j>i;j--){
565 fDataSignals[j]=(Int_t)(fDataSignals[j]-averageValue);
566 fSignalPositionArray[fSizeOfSignalPositionArray]=j;
567 fSizeOfSignalPositionArray++;
571 //before while the two consecutive timebin values are added
572 fDataSignals[i]=(Int_t)(fDataSignals[i]-averageValue);
573 fSignalPositionArray[fSizeOfSignalPositionArray]=i;
574 fSizeOfSignalPositionArray++;
575 fDataSignals[i-1]=(Int_t)(fDataSignals[i-1]-averageValue);
576 fSignalPositionArray[fSizeOfSignalPositionArray]=i-1;
577 fSizeOfSignalPositionArray++;
580 //Here the consecutive pads after the two first are added
582 while(fDataSignals[i-1]>(Int_t)(averageValue+fThresholdUsed+1)){
583 fDataSignals[i-1]=(Int_t)(fDataSignals[i-1]-averageValue);
584 fSignalPositionArray[fSizeOfSignalPositionArray]=i-1;
585 fSizeOfSignalPositionArray++;
589 //adding the signal below threshold belonging to the total signal
590 Bool_t contLeft=kTRUE;
593 if(fDataSignals[i-1]>=fDataSignals[i-2] && fDataSignals[i-1]>averageValue){
594 fDataSignals[i-1]=(Int_t)(fDataSignals[i-1]-averageValue);
595 fSignalPositionArray[fSizeOfSignalPositionArray]=i-1;
596 fSizeOfSignalPositionArray++;
600 if(fDataSignals[i-1]> averageValue){
601 fDataSignals[i-1]=(Int_t)(fDataSignals[i-1]-averageValue);
602 fSignalPositionArray[fSizeOfSignalPositionArray]=i-1;
603 fSizeOfSignalPositionArray++;
616 Int_t nReadFromPositionArray=0;
617 for(Int_t i=endTime;i>=beginTime;i--){
618 if(i==fSignalPositionArray[nReadFromPositionArray]){
619 nReadFromPositionArray++;
627 void AliHLTTPCPad::FindClusterCandidates()
629 // see header file for class documentation
631 if(fSizeOfSignalPositionArray<2){
635 if(fNSigmaThreshold>0){
636 ZeroSuppress(fNSigmaThreshold);
638 else if(fSignalThreshold>0){
639 ZeroSuppress((Double_t)0,(Int_t)fSignalThreshold);
644 vector<Int_t> tmpPos;
645 vector<Int_t> tmpSig;
648 for(Int_t pos=fSizeOfSignalPositionArray-2;pos>=0;pos--){
649 if(fSignalPositionArray[pos]==fSignalPositionArray[pos+1]+1){
650 seqcharge+=fDataSignals[fSignalPositionArray[pos+1]];
651 seqaverage += fSignalPositionArray[pos+1]*fDataSignals[fSignalPositionArray[pos+1]];
652 seqerror += fSignalPositionArray[pos+1]*fSignalPositionArray[pos+1]*fDataSignals[fSignalPositionArray[pos+1]];
654 tmpPos.push_back(fSignalPositionArray[pos+1]);
655 tmpSig.push_back(fDataSignals[fSignalPositionArray[pos+1]]);
657 if(fDataSignals[fSignalPositionArray[pos+1]]>fDataSignals[fSignalPositionArray[pos]]){
660 if(fDataSignals[fSignalPositionArray[pos+1]]<fDataSignals[fSignalPositionArray[pos]]&&isFalling){
662 seqmean = seqaverage/seqcharge;
664 //Calculate mean in pad direction:
665 Int_t padmean = seqcharge*fPadNo;
666 Int_t paderror = fPadNo*padmean;
667 AliHLTTPCClusters candidate;
668 candidate.fTotalCharge = seqcharge;
669 candidate.fPad = padmean;
670 candidate.fPad2 = paderror;
671 candidate.fTime = seqaverage;
672 candidate.fTime2 = seqerror;
673 candidate.fMean = seqmean;
674 candidate.fLastMergedPad = fPadNo;
675 fClusterCandidates.push_back(candidate);
676 fUsedClusterCandidates.push_back(0);
689 seqcharge+=fDataSignals[fSignalPositionArray[0]];
690 seqaverage += fSignalPositionArray[0]*fDataSignals[fSignalPositionArray[0]];
691 seqerror += fSignalPositionArray[0]*fSignalPositionArray[0]*fDataSignals[fSignalPositionArray[0]];
692 tmpPos.push_back(fSignalPositionArray[0]);
693 tmpSig.push_back(fDataSignals[fSignalPositionArray[0]]);
695 //Calculate mean of sequence:
697 seqmean = seqaverage/seqcharge;
699 //Calculate mean in pad direction:
700 Int_t padmean = seqcharge*fPadNo;
701 Int_t paderror = fPadNo*padmean;
702 AliHLTTPCClusters candidate;
703 candidate.fTotalCharge = seqcharge;
704 candidate.fPad = padmean;
705 candidate.fPad2 = paderror;
706 candidate.fTime = seqaverage;
707 candidate.fTime2 = seqerror;
708 candidate.fMean = seqmean;
709 candidate.fLastMergedPad = fPadNo;
710 fClusterCandidates.push_back(candidate);
711 fUsedClusterCandidates.push_back(0);
721 else if(seqcharge>0){
722 seqcharge+=fDataSignals[fSignalPositionArray[pos+1]];
723 seqaverage += fSignalPositionArray[pos+1]*fDataSignals[fSignalPositionArray[pos+1]];
724 seqerror += fSignalPositionArray[pos+1]*fSignalPositionArray[pos+1]*fDataSignals[fSignalPositionArray[pos+1]];
725 tmpPos.push_back(fSignalPositionArray[pos+1]);
726 tmpSig.push_back(fDataSignals[fSignalPositionArray[pos+1]]);
728 //Calculate mean of sequence:
730 seqmean = seqaverage/seqcharge;
732 //Calculate mean in pad direction:
733 Int_t padmean = seqcharge*fPadNo;
734 Int_t paderror = fPadNo*padmean;
735 AliHLTTPCClusters candidate;
736 candidate.fTotalCharge = seqcharge;
737 candidate.fPad = padmean;
738 candidate.fPad2 = paderror;
739 candidate.fTime = seqaverage;
740 candidate.fTime2 = seqerror;
741 candidate.fMean = seqmean;
742 candidate.fLastMergedPad = fPadNo;
743 fClusterCandidates.push_back(candidate);
744 fUsedClusterCandidates.push_back(0);