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"
47 //------------------------------
49 /** margin for the base line be re-avaluated */
50 #define ALIHLTPAD_BASELINE_MARGIN (2*fAverage)
52 /** ROOT macro for the implementation of ROOT specific class methods */
53 ClassImp(AliHLTTPCPad)
55 AliHLTTPCPad::AliHLTTPCPad()
58 fUsedClusterCandidates(),
76 fSignalPositionArray(NULL),
77 fSizeOfSignalPositionArray(0),
82 fDebugHistoBeforeZS(NULL),
83 fDebugHistoAfterZS(NULL)
85 // see header file for class documentation
87 // refer to README to build package
89 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
90 // HLTInfo("Entering default constructor");
91 fDataSignals= new AliHLTTPCSignal_t[AliHLTTPCTransform::GetNTimeBins()];
92 memset( fDataSignals, 0xFF, sizeof(Int_t)*(AliHLTTPCTransform::GetNTimeBins()));
94 fSignalPositionArray= new AliHLTTPCSignal_t[AliHLTTPCTransform::GetNTimeBins()];
95 memset( fSignalPositionArray, 0xFF, sizeof(Int_t)*(AliHLTTPCTransform::GetNTimeBins()));
96 fSizeOfSignalPositionArray=0;
100 AliHLTTPCPad::AliHLTTPCPad(Int_t mode)
102 fClusterCandidates(0),
103 fUsedClusterCandidates(0),
121 fSignalPositionArray(NULL),
122 fSizeOfSignalPositionArray(0),
126 fNGoodSignalsSent(0),
127 fDebugHistoBeforeZS(NULL),
128 fDebugHistoAfterZS(NULL)
130 // see header file for class documentation
132 // refer to README to build package
134 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
137 AliHLTTPCPad::AliHLTTPCPad(Int_t offset, Int_t nofBins)
139 fClusterCandidates(),
140 fUsedClusterCandidates(),
158 fSignalPositionArray(NULL),
159 fSizeOfSignalPositionArray(0),
163 fNGoodSignalsSent(0),
164 fDebugHistoBeforeZS(NULL),
165 fDebugHistoAfterZS(NULL)
167 // see header file for class documentation
170 AliHLTTPCPad::~AliHLTTPCPad()
172 // see header file for class documentation
174 HLTWarning("event data acquisition not stopped");
178 delete [] fDataSignals;
181 if (fSignalPositionArray) {
182 delete [] fSignalPositionArray;
183 fSignalPositionArray=NULL;
185 if(fDebugHistoBeforeZS){
186 delete fDebugHistoBeforeZS;
187 fDebugHistoBeforeZS=NULL;
189 if(fDebugHistoAfterZS){
190 delete fDebugHistoAfterZS;
191 fDebugHistoAfterZS=NULL;
195 Int_t AliHLTTPCPad::SetID(Int_t rowno, Int_t padno)
197 // see header file for class documentation
203 sprintf(nameBefore,"beforeRow%dPad%d",fRowNo,fPadNo);
205 sprintf(nameAfter,"afterRow%dPad%d",fRowNo,fPadNo);
206 fDebugHistoBeforeZS = new TH1F(nameBefore,nameBefore,1024,0,1024);
207 fDebugHistoAfterZS = new TH1F(nameAfter,nameAfter,1024,0,1024);
213 Int_t AliHLTTPCPad::StartEvent()
215 // see header file for class documentation
217 if (fpRawData==NULL) {
226 fpRawData=new AliHLTTPCSignal_t[fNofBins];
228 for (int i=0; i<fNofBins; i++) fpRawData[i]=-1;
230 HLTError("memory allocation failed");
235 HLTWarning("event data acquisition already started");
241 Int_t AliHLTTPCPad::CalculateBaseLine(Int_t reqMinCount)
243 // see header file for class documentation
245 AliHLTTPCSignal_t avBackup=fAverage;
246 //HLTDebug("reqMinCount=%d fCount=%d fTotal=%d fSum=%d fBLMax=%d fBLMin=%d", reqMinCount, fCount, fTotal, fSum, fBLMax, fBLMin);
247 if (fCount>=reqMinCount && fCount>=fTotal/2) {
248 fAverage=fCount>0?fSum/fCount:0;
250 //HLTDebug("average for current event %d (%d - %d)", fAverage, fBLMax, fBLMin);
252 if (fBLMax>ALIHLTPAD_BASELINE_MARGIN) {
254 //HLTDebug("maximum value %d exceeds margin for base line (%d) "
255 // "-> re-evaluate base line", fBLMax, ALIHLTPAD_BASELINE_MARGIN);
257 for (Int_t i=fFirstBLBin; i<fNofBins; i++)
258 if (fpRawData[i]>=0) AddBaseLineValue(i, fpRawData[i]);
259 if (fCount>0 && fCount>=reqMinCount && fCount>=fTotal/2) {
260 fAverage=fSum/fCount;
261 //HLTDebug("new average %d", fAverage);
263 // HLTDebug("baseline re-eveluation skipped because of to few "
264 // "contributing bins: total=%d, contributing=%d, req=%d"
265 // "\ndata might be already zero suppressed"
266 // , fTotal, fCount, reqMinCount);
271 HLTError("missing raw data for base line calculation");
276 // calculate average for all events
277 fAverage=((avBackup*fNofEvents)+fAverage)/(fNofEvents+1);
278 //HLTDebug("base line average for %d event(s): %d", fNofEvents+1, fAverage);
286 // HLTDebug("baseline calculation skipped because of to few contributing "
287 // "bins: total=%d, contributing=%d, required=%d \ndata might be "
288 // "already zero suppressed", fTotal, fCount, reqMinCount);
294 Int_t AliHLTTPCPad::StopEvent()
296 // see header file for class documentation
299 AliHLTTPCSignal_t* pData=fpRawData;
305 } else if (fNofBins>0) {
306 HLTError("event data acquisition not started");
312 Int_t AliHLTTPCPad::ResetHistory()
314 // see header file for class documentation
321 Int_t AliHLTTPCPad::SetThreshold(AliHLTTPCSignal_t thresh)
323 // see header file for class documentation
329 Int_t AliHLTTPCPad::AddBaseLineValue(Int_t bin, AliHLTTPCSignal_t value)
331 // see header file for class documentation
333 if (bin>=fFirstBLBin) {
334 if (fAverage<0 || value<ALIHLTPAD_BASELINE_MARGIN) {
335 // add to the current sum and count
339 // keep the maximum value for later quality control of the base
344 if (fBLMin<0 || fBLMin>value) {
345 // keep the minimum value for later quality control of the base
351 // HLTDebug("ignoring value %d (bin %d) for base line calculation "
352 // "(current average is %d)",
353 // value, bin, fAverage);
359 Int_t AliHLTTPCPad::SetRawData(Int_t bin, AliHLTTPCSignal_t value)
361 // see header file for class documentation
362 // printf("Row: %d Pad: %d Time: %d Charge %d", fRowNo, fPadNo, bin, value);
367 if (fpRawData[bin]<0) {
368 AddBaseLineValue(bin, value);
371 // ignore value for average calculation
372 HLTWarning("overriding content of bin %d (%d)", bin, fpRawData[bin]);
374 fpRawData[bin]=value;
376 HLTWarning("ignoring neg. raw data");
379 HLTWarning("bin %d out of range (%d)", bin, fNofBins);
382 } else if (fNofBins>0) {
383 HLTError("event cycle not started");
389 Int_t AliHLTTPCPad::Next(Int_t bZeroSuppression)
391 // see header file for class documentation
392 if (fpRawData==NULL) return 0;
393 Int_t iResult=fReadPos<fNofBins;
394 if (iResult>0 && (iResult=(++fReadPos<fNofBins))>0) {
395 if (bZeroSuppression) {
396 while ((iResult=(fReadPos<fNofBins))>0 &&
397 GetCorrectedData(fReadPos)<=0)
404 Int_t AliHLTTPCPad::Rewind(Int_t bZeroSuppression)
406 // see header file for class documentation
407 fReadPos=(bZeroSuppression>0?0:fFirstBLBin)-1;
408 return Next(bZeroSuppression);
411 AliHLTTPCSignal_t AliHLTTPCPad::GetRawData(Int_t bin) const
413 // see header file for class documentation
414 AliHLTTPCSignal_t data=0;
419 HLTWarning("requested bin %d out of range (%d)", bin, fNofBins);
421 } else if (fNofBins>0) {
422 HLTWarning("data only available within event cycle");
427 AliHLTTPCSignal_t AliHLTTPCPad::GetCorrectedData(Int_t bin) const
429 // see header file for class documentation
430 AliHLTTPCSignal_t data=GetRawData(bin)-GetBaseLine(bin);
431 AliHLTTPCSignal_t prev=0;
432 if (bin>1) prev=GetRawData(bin-1)-GetBaseLine(bin-1);
433 AliHLTTPCSignal_t succ=0;
434 if (bin+1<GetSize()) succ=GetRawData(bin+1)-GetBaseLine(bin+1);
442 // the signal is below the base-line and threshold
446 // the neighboring bins are both below base-line/threshold
447 // a real signal is always more than one bin wide because of the shaper
448 if (prev<=0 && succ<=0) data=0;
451 // the bin is inside the range of ignored bins
452 if (bin<fFirstBLBin) data=0;
453 //HLTDebug("fReadPos=%d data=%d threshold=%d raw data=%d base line=%d", fReadPos, data, fThreshold, GetRawData(bin), GetBaseLine(bin));
457 AliHLTTPCSignal_t AliHLTTPCPad::GetBaseLine(Int_t /*bin*/) const //TODO: Why is bin being ignored?
459 // see header file for class documentation
460 AliHLTTPCSignal_t val=0;
462 // we take the minumum value as the base line if it doesn't differ from
463 // the average to much
466 const AliHLTTPCSignal_t kMaxDifference=15;
467 if ((fAverage-fBLMin)<=kMaxDifference) val=fBLMin;
468 else val>kMaxDifference?val-=kMaxDifference:0;
472 // here we should never get
474 HLTFatal("wrong base line value");
479 AliHLTTPCSignal_t AliHLTTPCPad::GetAverage() const
481 // see header file for class documentation
482 return fAverage>0?fAverage:0;
485 Float_t AliHLTTPCPad::GetOccupancy() const
487 // see header file for class documentation
489 if (fpRawData && fNofBins>0) {
490 for (Int_t i=fFirstBLBin; i<fNofBins; i++) {
491 if (GetCorrectedData(i)>0) occupancy+=1;
493 if (fNofBins-fFirstBLBin>0)
494 occupancy/=fNofBins-fFirstBLBin;
499 Float_t AliHLTTPCPad::GetAveragedOccupancy() const
501 // see header file for class documentation
503 // history is not yet implemented
504 return GetOccupancy();
506 void AliHLTTPCPad::PrintRawData()
508 // see header file for class documentation
509 for(Int_t bin=0;bin<AliHLTTPCTransform::GetNTimeBins();bin++){
510 if(GetDataSignal(bin)>0)
511 cout<<fRowNo<<"\t"<<fPadNo<<"\t"<<bin<<"\t"<<GetDataSignal(bin)<<endl;;
513 // cout<<"bins: "<<AliHLTTPCTransform::GetNTimeBins()<<endl;
516 void AliHLTTPCPad::ClearCandidates(){
517 fClusterCandidates.clear();
518 fUsedClusterCandidates.clear();
521 void AliHLTTPCPad::SetDataToDefault()
523 // see header file for class documentation
524 if(fDataSignals && fSignalPositionArray){
525 for(Int_t i =0;i<fSizeOfSignalPositionArray;i++){
526 fDataSignals[fSignalPositionArray[i]]=-1;
528 fSizeOfSignalPositionArray=0;
532 void AliHLTTPCPad::SetDataSignal(Int_t bin,Int_t signal)
534 // see header file for class documentation
535 fDataSignals[bin]=signal;
536 fSignalPositionArray[fSizeOfSignalPositionArray]=bin;
537 fSizeOfSignalPositionArray++;
539 fDebugHistoBeforeZS->Fill(bin,signal);
543 Bool_t AliHLTTPCPad::GetNextGoodSignal(Int_t &time, Int_t &signal ){
544 /* for(Int_t i=70;i<900;i++){
545 if(fDataSignals[i]>0){
546 printf("Signals which are good: Bin: %d Signal: %d\n",i,fDataSignals[i]);
549 if(fNGoodSignalsSent<fSizeOfSignalPositionArray&&fSizeOfSignalPositionArray>0){
550 time = fSignalPositionArray[fNGoodSignalsSent];
551 signal = GetDataSignal(time);
552 // printf("GoodSignal: Row: %d Pad: %d time %d signal %d signalsSent: %d\n",fRowNo,fPadNo,fSignalPositionArray[fNGoodSignalsSent],GetDataSignal(time), fNGoodSignalsSent);
559 Int_t AliHLTTPCPad::GetDataSignal(Int_t bin) const
561 // see header file for class documentation
562 return fDataSignals[bin];
565 void AliHLTTPCPad::ZeroSuppress(Double_t nRMS, Int_t threshold, Int_t reqMinPoint, Int_t beginTime, Int_t endTime, Int_t timebinsLeft, Int_t timebinsRight, Int_t valueUnderAverage){
566 //see headerfile for documentation
568 //HLTDebug("In Pad: nRMS=%d, threshold=%d, reqMinPoint=%d, beginTime=%d, endTime=%d, timebinsLeft=%d timebinsRight=%d valueUnderAverage=%d \n",nRMS,threshold,reqMinPoint,beginTime,endTime,timebinsLeft,timebinsRight,valueUnderAverage);
570 Bool_t useRMS= kFALSE;
574 HLTInfo("Both RMSThreshold and SignalThreshold defined, using RMSThreshold");
577 if(threshold<1 && nRMS<=0){
578 //setting the data to -1 for this pad
579 HLTInfo("Neither of RMSThreshold and SignalThreshold set, zerosuppression aborted");
583 Int_t fThresholdUsed=threshold;
587 fSizeOfSignalPositionArray=0;
589 for(Int_t i=beginTime;i<endTime+1;i++){
590 if(fDataSignals[i]>0){
592 sumNAdded+=fDataSignals[i]*fDataSignals[i];
596 else if(threshold>0){
597 for(Int_t i=beginTime;i<endTime+1;i++){
598 if(fDataSignals[i]>0){
600 sumNAdded+=fDataSignals[i];
605 HLTFatal("This should never happen because this is tested earlier in the code.(nRMSThreshold<1&&signal-threshold<1)");
607 if(nAdded<reqMinPoint){
608 HLTInfo("Number of signals is less than required, zero suppression aborted");
613 HLTInfo("No signals added for this pad, zerosuppression aborted: pad %d row %d",fPadNo,fRowNo);
616 // HLTInfo("sumNAdded=%d nAdded=%d pad %d ",sumNAdded,nAdded,fPadNo);
617 Double_t averageValue=(Double_t)sumNAdded/nAdded;//true average for threshold approach, average of signals squared for rms approach
623 fThresholdUsed =(Int_t)(TMath::Sqrt(averageValue)*nRMS);
626 HLTFatal("average value in ZeroSuppression less than 0, investigation needed. This should never happen");
630 fThresholdUsed = (Int_t)(averageValue + threshold);
634 // Do zero suppression on the adc values within [beginTime,endTime]
635 for(Int_t i=beginTime;i<endTime;i++){
636 if(fDataSignals[i]>fThresholdUsed){
637 // HLTInfo("Signal Larger in pad %d time %d signal %d , threshold: %d averageValue %e",fPadNo,i,fDataSignals[i],fThresholdUsed, averageValue);
638 Int_t firstSignalTime=i;
639 for(Int_t left=1;left<timebinsLeft;left++){//looking 5 to the left of the signal to add tail
640 if(fDataSignals[i-left]-averageValue+valueUnderAverage>0&&i-left>=beginTime){
647 Int_t lastSignalTime=i;
648 for(Int_t right=1;right<timebinsRight;right++){//looking 5 to the left of the signal to add tail
649 if(fDataSignals[i+right]-averageValue+valueUnderAverage>0&&i+right<endTime){
656 for(Int_t t=firstSignalTime;t<lastSignalTime;t++){
657 // cout<<"Row: "<<fRowNo<<" Pad: "<<fPadNo<<" Adding to tmebin: "<<t<<" signal: "<<(AliHLTTPCSignal_t)(fDataSignals[t]-averageValue + valueUnderAverage)<<endl;
658 fDataSignals[t]=(AliHLTTPCSignal_t)(fDataSignals[t]-averageValue + valueUnderAverage);
659 // cout<<"Adding to signalPosition array bin number: "<<fSizeOfSignalPositionArray<<" timebin number: "<<t<<endl;
660 fSignalPositionArray[fSizeOfSignalPositionArray]=t;
661 fSizeOfSignalPositionArray++;
662 // cout<<"Number of signals added so far: "<<fSizeOfSignalPositionArray<<" firstSignalTimeBin: "<<firstSignalTime<<" lastSignalTimeBin: "<<lastSignalTime<<endl;
663 /* if(fRowNo==29&&fPadNo==58){
664 cout<<"Signal added: Row: "<<fRowNo<<" Pad: "<<fPadNo<<" Time: "<<t<<" signal: "<<fDataSignals[t]<<" #signals: "<<fSizeOfSignalPositionArray<<endl;
668 fDebugHistoAfterZS->Fill(t,fDataSignals[t]);
679 void AliHLTTPCPad::AddClusterCandidate(AliHLTTPCClusters candidate){
680 fClusterCandidates.push_back(candidate);
681 fUsedClusterCandidates.push_back(0);
684 void AliHLTTPCPad::SaveHistograms(){
686 if(fSizeOfSignalPositionArray==0){
690 sprintf(filename,"/afsuser/kenneth/SimpleComponentWrapper/histos/HistogramsRow%dPad%d.root",fRowNo,fPadNo);
691 TFile file(filename,"RECREATE");
692 fDebugHistoBeforeZS->Write();
693 fDebugHistoAfterZS->Write();
698 void AliHLTTPCPad::FindClusterCandidates()
700 // see header file for class documentation
702 if(fSizeOfSignalPositionArray<2){
706 if(fNSigmaThreshold>0){
707 ZeroSuppress(fNSigmaThreshold);
709 else if(fSignalThreshold>0){
710 ZeroSuppress((Double_t)0,(Int_t)fSignalThreshold);
715 vector<Int_t> tmpPos;
716 vector<Int_t> tmpSig;
719 for(Int_t pos=fSizeOfSignalPositionArray-2;pos>=0;pos--){
720 if(fSignalPositionArray[pos]==fSignalPositionArray[pos+1]+1){
721 seqcharge+=fDataSignals[fSignalPositionArray[pos+1]];
722 seqaverage += fSignalPositionArray[pos+1]*fDataSignals[fSignalPositionArray[pos+1]];
723 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 if(fDataSignals[fSignalPositionArray[pos+1]]>fDataSignals[fSignalPositionArray[pos]]){
731 if(fDataSignals[fSignalPositionArray[pos+1]]<fDataSignals[fSignalPositionArray[pos]]&&isFalling){
733 seqmean = seqaverage/seqcharge;
735 //Calculate mean in pad direction:
736 Int_t padmean = seqcharge*fPadNo;
737 Int_t paderror = fPadNo*padmean;
738 AliHLTTPCClusters candidate;
739 candidate.fTotalCharge = seqcharge;
740 candidate.fPad = padmean;
741 candidate.fPad2 = paderror;
742 candidate.fTime = seqaverage;
743 candidate.fTime2 = seqerror;
744 candidate.fMean = seqmean;
745 candidate.fLastMergedPad = fPadNo;
746 fClusterCandidates.push_back(candidate);
747 fUsedClusterCandidates.push_back(0);
760 seqcharge+=fDataSignals[fSignalPositionArray[0]];
761 seqaverage += fSignalPositionArray[0]*fDataSignals[fSignalPositionArray[0]];
762 seqerror += fSignalPositionArray[0]*fSignalPositionArray[0]*fDataSignals[fSignalPositionArray[0]];
763 tmpPos.push_back(fSignalPositionArray[0]);
764 tmpSig.push_back(fDataSignals[fSignalPositionArray[0]]);
766 //Calculate mean of sequence:
768 seqmean = seqaverage/seqcharge;
770 //Calculate mean in pad direction:
771 Int_t padmean = seqcharge*fPadNo;
772 Int_t paderror = fPadNo*padmean;
773 AliHLTTPCClusters candidate;
774 candidate.fTotalCharge = seqcharge;
775 candidate.fPad = padmean;
776 candidate.fPad2 = paderror;
777 candidate.fTime = seqaverage;
778 candidate.fTime2 = seqerror;
779 candidate.fMean = seqmean;
780 candidate.fLastMergedPad = fPadNo;
781 fClusterCandidates.push_back(candidate);
782 fUsedClusterCandidates.push_back(0);
792 else if(seqcharge>0){
793 seqcharge+=fDataSignals[fSignalPositionArray[pos+1]];
794 seqaverage += fSignalPositionArray[pos+1]*fDataSignals[fSignalPositionArray[pos+1]];
795 seqerror += fSignalPositionArray[pos+1]*fSignalPositionArray[pos+1]*fDataSignals[fSignalPositionArray[pos+1]];
796 tmpPos.push_back(fSignalPositionArray[pos+1]);
797 tmpSig.push_back(fDataSignals[fSignalPositionArray[pos+1]]);
799 //Calculate mean of sequence:
801 seqmean = seqaverage/seqcharge;
803 //Calculate mean in pad direction:
804 Int_t padmean = seqcharge*fPadNo;
805 Int_t paderror = fPadNo*padmean;
806 AliHLTTPCClusters candidate;
807 candidate.fTotalCharge = seqcharge;
808 candidate.fPad = padmean;
809 candidate.fPad2 = paderror;
810 candidate.fTime = seqaverage;
811 candidate.fTime2 = seqerror;
812 candidate.fMean = seqmean;
813 candidate.fLastMergedPad = fPadNo;
814 fClusterCandidates.push_back(candidate);
815 fUsedClusterCandidates.push_back(0);