+
+void AliHLTTPCClusterFinder::ReadDataUnsorted(void* ptr,unsigned long size){
+ // see header file for class documentation
+ //set input pointer
+ fPtr = (UChar_t*)ptr;
+ fSize = size;
+
+ if(!fVectorInitialized){
+ InitializePadArray();
+ }
+
+ if (fDigitReader->InitBlock(fPtr,fSize,fFirstRow,fLastRow,fCurrentPatch,fCurrentSlice)<0) {
+ HLTError("failed setting up digit reader (InitBlock)");
+ return;
+ }
+
+ while(fDigitReader->NextChannel()){
+ UInt_t row=fDigitReader->GetRow();
+ UInt_t pad=fDigitReader->GetPad();
+
+ if(row>=fRowPadVector.size()){
+ HLTError("Row number is to large: %d, max is %d",row,fRowPadVector.size()-1);
+ continue;
+ }
+ if(pad>=fRowPadVector[row].size()){
+ HLTError("Pad number is to large: %d, max is %d",pad,fRowPadVector[row].size());
+ continue;
+ }
+
+ while(fDigitReader->NextBunch()){
+ if(fDigitReader->GetBunchSize()>1){//to remove single timebin values, this will have to change at some point
+ UInt_t time = fDigitReader->GetTime();
+ if((Int_t)time>=fFirstTimeBin && (Int_t)time+fDigitReader->GetBunchSize()<=fLastTimeBin){
+ // Kenneth: 20-04-09. The following if have been added because of inconsistency in the 40 bit decoder and the 32 bit decoder.
+ // GetSignals() in the 40 bit decoder returns an array of UInt_t while the 32 bit one returns UShort_t
+ // The same is true for the function ReadDataUnsortedDeconvoluteTime() below.
+ // In addition the signals are organized in the opposite direction
+ if(f32BitFormat){
+ const UShort_t *bunchData= fDigitReader->GetSignalsShort();
+ AliHLTTPCClusters candidate;
+ for(Int_t i=fDigitReader->GetBunchSize()-1;i>=0;i--){
+ candidate.fTotalCharge+=bunchData[i];
+ candidate.fTime += time*bunchData[i];
+ candidate.fTime2 += time*time*bunchData[i];
+ if(bunchData[i]>candidate.fQMax){
+ candidate.fQMax=bunchData[i];
+ }
+ time++;
+ }
+ if(candidate.fTotalCharge>0){
+ candidate.fMean=candidate.fTime/candidate.fTotalCharge;
+ candidate.fPad=candidate.fTotalCharge*pad;
+ candidate.fPad2=candidate.fPad*pad;
+ candidate.fLastMergedPad=pad;
+ candidate.fRowNumber=row+fDigitReader->GetRowOffset();
+ }
+ if(fRowPadVector[row][pad] != NULL){
+ fRowPadVector[row][pad]->AddClusterCandidate(candidate);
+ }
+ }
+ else{
+ const UInt_t *bunchData= fDigitReader->GetSignals();
+ AliHLTTPCClusters candidate;
+ const AliHLTTPCDigitData* digits = NULL;
+ if(fDoMC && (digits = fDigitReader->GetBunchDigits())!=NULL){
+ for(Int_t i=0;i<fDigitReader->GetBunchSize();i++){
+ candidate.fTotalCharge+=bunchData[i];
+ candidate.fTime += time*bunchData[i];
+ candidate.fTime2 += time*time*bunchData[i];
+ if(bunchData[i]>candidate.fQMax){
+ candidate.fQMax=bunchData[i];
+ }
+ fMCDigits.push_back(digits[i]);
+ time++;
+ }
+ }
+ else{
+ for(Int_t i=0;i<fDigitReader->GetBunchSize();i++){
+ candidate.fTotalCharge+=bunchData[i];
+ candidate.fTime += time*bunchData[i];
+ candidate.fTime2 += time*time*bunchData[i];
+ if(bunchData[i]>candidate.fQMax){
+ candidate.fQMax=bunchData[i];
+ }
+ time++;
+ }
+ }
+ if(candidate.fTotalCharge>0){
+ candidate.fMean=candidate.fTime/candidate.fTotalCharge;
+ candidate.fPad=candidate.fTotalCharge*pad;
+ candidate.fPad2=candidate.fPad*pad;
+ candidate.fLastMergedPad=pad;
+ candidate.fRowNumber=row+fDigitReader->GetRowOffset();
+ }
+ if(fRowPadVector[row][pad] != NULL){
+ fRowPadVector[row][pad]->AddClusterCandidate(candidate);
+ if(fDoMC){
+ fRowPadVector[row][pad]->AddCandidateDigits(fMCDigits);
+ fMCDigits.clear();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void AliHLTTPCClusterFinder::ReadDataUnsortedDeconvoluteTime(void* ptr,unsigned long size){
+ // see header file for class documentation
+
+ //set input pointer
+ fPtr = (UChar_t*)ptr;
+ fSize = size;
+
+ if(!fVectorInitialized){
+ InitializePadArray();
+ }
+
+ if (fDigitReader->InitBlock(fPtr,fSize,fFirstRow,fLastRow,fCurrentPatch,fCurrentSlice)<0) {
+ HLTError("failed setting up digit reader (InitBlock)");
+ return;
+ }
+
+ while(fDigitReader->NextChannel()){
+ UInt_t row=fDigitReader->GetRow();
+ UInt_t pad=fDigitReader->GetPad();
+
+ while(fDigitReader->NextBunch()){
+ if(fDigitReader->GetBunchSize()>1){//to remove single timebin values, this will have to change at some point
+ UInt_t time = fDigitReader->GetTime();
+ if((Int_t)time>=fFirstTimeBin && (Int_t)time+fDigitReader->GetBunchSize()<=fLastTimeBin){
+ Int_t indexInBunchData=0;
+ Bool_t moreDataInBunch=kFALSE;
+ UInt_t prevSignal=0;
+ Bool_t signalFalling=kFALSE;
+
+ // Kenneth: 20-04-09. The following if have been added because of inconsistency in the 40 bit decoder and the 32 bit decoder.
+ // GetSignals() in the 40 bit decoder returns an array of UInt_t while the 32 bit one returns UShort_t
+ // The same is true for the function ReadDataUnsorted() above.
+ // In addition the signals are organized in the opposite direction
+ if(f32BitFormat){
+ indexInBunchData = fDigitReader->GetBunchSize();
+ const UShort_t *bunchData= fDigitReader->GetSignalsShort();
+
+ do{
+ AliHLTTPCClusters candidate;
+ //for(Int_t i=indexInBunchData;i<fDigitReader->GetBunchSize();i++){
+ for(Int_t i=indexInBunchData;i>=0;i--){
+ // Checks if one need to deconvolute the signals
+ if(bunchData[i]>prevSignal && signalFalling==kTRUE){
+ if(i<fDigitReader->GetBunchSize()-1){ // means there are more than one signal left in the bunch
+ moreDataInBunch=kTRUE;
+ prevSignal=0;
+ }
+ break;
+ }
+
+ // Checks if the signal is 0, then quit processing the data.
+ if(bunchData[i]==0 && i<fDigitReader->GetBunchSize()-1){//means we have 0 data fom the rcu, might happen depending on the configuration settings
+ moreDataInBunch=kTRUE;
+ prevSignal=0;
+ break;
+ }
+
+ if(prevSignal>bunchData[i]){//means the peak of the signal has been reached and deconvolution will happen if the signal rise again.
+ signalFalling=kTRUE;
+ }
+ candidate.fTotalCharge+=bunchData[i];
+ candidate.fTime += time*bunchData[i];
+ candidate.fTime2 += time*time*bunchData[i];
+ if(bunchData[i]>candidate.fQMax){
+ candidate.fQMax=bunchData[i];
+ }
+
+ prevSignal=bunchData[i];
+ time++;
+ indexInBunchData--;
+ }
+ if(candidate.fTotalCharge>0){
+ candidate.fMean=candidate.fTime/candidate.fTotalCharge;
+ candidate.fPad=candidate.fTotalCharge*pad;
+ candidate.fPad2=candidate.fPad*pad;
+ candidate.fLastMergedPad=pad;
+ candidate.fRowNumber=row+fDigitReader->GetRowOffset();
+ }
+ fRowPadVector[row][pad]->AddClusterCandidate(candidate);
+ fRowPadVector[row][pad]->AddCandidateDigits(fMCDigits);
+ if(indexInBunchData<fDigitReader->GetBunchSize()-1){
+ moreDataInBunch=kFALSE;
+ }
+ }while(moreDataInBunch);
+ }
+ else{
+ const UInt_t *bunchData= fDigitReader->GetSignals();
+ do{
+ AliHLTTPCClusters candidate;
+ for(Int_t i=indexInBunchData;i<fDigitReader->GetBunchSize();i++){
+ // Checks if one need to deconvolute the signals
+ if(bunchData[i]>prevSignal && signalFalling==kTRUE){
+ if(i<fDigitReader->GetBunchSize()-1){ // means there are more than one signal left in the bunch
+ moreDataInBunch=kTRUE;
+ prevSignal=0;
+ }
+ break;
+ }
+
+ // Checks if the signal is 0, then quit processing the data.
+ if(bunchData[i]==0 && i<fDigitReader->GetBunchSize()-1){//means we have 0 data fom the rcu, might happen depending on the configuration settings
+ moreDataInBunch=kTRUE;
+ prevSignal=0;
+ break;
+ }
+
+ if(prevSignal>bunchData[i]){//means the peak of the signal has been reached and deconvolution will happen if the signal rise again.
+ signalFalling=kTRUE;
+ }
+
+ candidate.fTotalCharge+=bunchData[i];
+ candidate.fTime += time*bunchData[i];
+ candidate.fTime2 += time*time*bunchData[i];
+ if(bunchData[i]>candidate.fQMax){
+ candidate.fQMax=bunchData[i];
+ }
+
+ prevSignal=bunchData[i];
+ time++;
+ indexInBunchData++;
+ }
+ if(candidate.fTotalCharge>0){
+ candidate.fMean=candidate.fTime/candidate.fTotalCharge;
+ candidate.fPad=candidate.fTotalCharge*pad;
+ candidate.fPad2=candidate.fPad*pad;
+ candidate.fLastMergedPad=pad;
+ candidate.fRowNumber=row+fDigitReader->GetRowOffset();
+ }
+ fRowPadVector[row][pad]->AddClusterCandidate(candidate);
+ if(indexInBunchData<fDigitReader->GetBunchSize()-1){
+ moreDataInBunch=kFALSE;
+ }
+ }while(moreDataInBunch);
+ }
+ }
+ }
+ }
+ }
+}
+
+Bool_t AliHLTTPCClusterFinder::ComparePads(AliHLTTPCPad *nextPad,AliHLTTPCClusters* cluster,Int_t nextPadToRead){
+ // see header file for class documentation
+
+ //Checking if we have a match on the next pad
+ for(UInt_t candidateNumber=0;candidateNumber<nextPad->fClusterCandidates.size();candidateNumber++){
+ if(nextPad->fUsedClusterCandidates[candidateNumber] == 1){
+ continue;
+ }
+ AliHLTTPCClusters *candidate =&nextPad->fClusterCandidates[candidateNumber];
+ // if(cluster->fMean-candidate->fMean==1 || candidate->fMean-cluster->fMean==1 || cluster->fMean-candidate->fMean==0){
+
+ if( abs((Int_t)(cluster->fMean - candidate->fMean)) <= fTimeMeanDiff ){
+ if(fDeconvPad){
+ if(candidate->fTotalCharge<fTotalChargeOfPreviousClusterCandidate){//peak is reached
+ fChargeOfCandidatesFalling=kTRUE;
+ }
+ if(candidate->fTotalCharge>fTotalChargeOfPreviousClusterCandidate && fChargeOfCandidatesFalling==kTRUE){//we have deconvolution
+ return kFALSE;
+ }
+ }
+ cluster->fMean=candidate->fMean;
+ cluster->fTotalCharge+=candidate->fTotalCharge;
+ cluster->fTime += candidate->fTime;
+ cluster->fTime2 += candidate->fTime2;
+ cluster->fPad+=candidate->fPad;
+ cluster->fPad2+=candidate->fPad2;
+ cluster->fLastMergedPad=candidate->fPad;
+ if(candidate->fQMax>cluster->fQMax){
+ cluster->fQMax=candidate->fQMax;
+ }
+ if(fDoMC){
+ FillMCClusterVector(nextPad->GetCandidateDigits(candidateNumber));
+ }
+
+ if(fDoPadSelection){
+ UInt_t rowNo = nextPad->GetRowNumber();
+ UInt_t padNo = nextPad->GetPadNumber();
+ if(padNo-1>0){
+ fRowPadVector[rowNo][padNo-2]->fSelectedPad=kTRUE;
+ fRowPadVector[rowNo][padNo-2]->fHWAddress=(AliHLTUInt16_t)fDigitReader->GetAltroBlockHWaddr(rowNo,padNo-2);
+ }
+ fRowPadVector[rowNo][padNo-1]->fSelectedPad=kTRUE;// quick solution to set the first pad to selected
+ fRowPadVector[rowNo][padNo-1]->fHWAddress=(AliHLTUInt16_t)fDigitReader->GetAltroBlockHWaddr(rowNo,padNo-1);
+ fRowPadVector[rowNo][padNo]->fSelectedPad=kTRUE;
+ fRowPadVector[rowNo][padNo]->fHWAddress=(AliHLTUInt16_t)fDigitReader->GetAltroBlockHWaddr(rowNo,padNo);
+ }
+
+ //setting the matched pad to used
+ nextPad->fUsedClusterCandidates[candidateNumber]=1;
+ nextPadToRead++;
+ if(nextPadToRead<(Int_t)fNumberOfPadsInRow[fRowOfFirstCandidate]){
+ nextPad=fRowPadVector[fRowOfFirstCandidate][nextPadToRead];
+ ComparePads(nextPad,cluster,nextPadToRead);
+ }
+ else{
+ return kFALSE;
+ }
+ }
+ }
+ return kFALSE;
+}
+
+Int_t AliHLTTPCClusterFinder::FillHWAddressList(AliHLTUInt16_t *hwaddlist, Int_t maxHWadd){
+ // see header file for class documentation
+
+ Int_t counter=0;
+ for(UInt_t row=0;row<fNumberOfRows;row++){
+ for(UInt_t pad=0;pad<fNumberOfPadsInRow[row]-1;pad++){
+ if(fRowPadVector[row][pad]->fSelectedPad){
+ if(counter<maxHWadd){
+ hwaddlist[counter]=(AliHLTUInt16_t)fRowPadVector[row][pad]->fHWAddress;
+ counter++;
+ }
+ else{
+ HLTWarning("To many hardwareaddresses, skip adding");
+ }
+
+ }
+ }
+ }
+ return counter;
+}
+
+
+Int_t AliHLTTPCClusterFinder::FillOutputMCInfo(AliHLTTPCClusterFinder::ClusterMCInfo * outputMCInfo, Int_t maxNumberOfClusterMCInfo){
+ // see header file for class documentation
+
+ Int_t counter=0;
+
+ for(UInt_t mc=0;mc<fClustersMCInfo.size();mc++){
+ if(counter<maxNumberOfClusterMCInfo){
+ outputMCInfo[counter] = fClustersMCInfo[mc];
+ counter++;
+ }
+ else{
+ HLTWarning("To much MCInfo has been added (no more space), skip adding");
+ }
+ }
+ return counter;
+}
+
+void AliHLTTPCClusterFinder::FindClusters(){
+ // see header file for function documentation
+
+ AliHLTTPCClusters* tmpCandidate=NULL;
+ for(UInt_t row=0;row<fNumberOfRows;row++){
+ fRowOfFirstCandidate=row;
+ for(UInt_t pad=0;pad<fNumberOfPadsInRow[row];pad++){
+ AliHLTTPCPad *tmpPad=fRowPadVector[row][pad];
+ for(size_t candidate=0;candidate<tmpPad->fClusterCandidates.size();candidate++){
+ if(tmpPad->fUsedClusterCandidates[candidate]){
+ continue;
+ }
+ tmpCandidate=&tmpPad->fClusterCandidates[candidate];
+ UInt_t tmpTotalCharge=tmpCandidate->fTotalCharge;
+
+ if(fDoMC){
+ fClusterMCVector.clear();
+ FillMCClusterVector(tmpPad->GetCandidateDigits(candidate));
+ }
+
+ ComparePads(fRowPadVector[row][pad+1],tmpCandidate,pad+1);
+ if(tmpCandidate->fTotalCharge>tmpTotalCharge){
+ //we have a cluster
+ fClusters.push_back(*tmpCandidate);
+ if(fDoMC){
+ //sort the vector (large->small) according to weight and remove elements above 2 (keep 0 1 and 2)
+ sort(fClusterMCVector.begin(),fClusterMCVector.end(), MCWeight::CompareWeights );
+ ClusterMCInfo tmpClusterMCInfo;
+
+ MCWeight zeroMC;
+ zeroMC.fMCID=-1;
+ zeroMC.fWeight=0;
+
+ if(fClusterMCVector.size()>0){
+ tmpClusterMCInfo.fClusterID[0]=fClusterMCVector.at(0);
+ }
+ else{
+ tmpClusterMCInfo.fClusterID[0]=zeroMC;
+ }
+
+ if(fClusterMCVector.size()>1){
+ tmpClusterMCInfo.fClusterID[1]=fClusterMCVector.at(1);
+ }
+ else{
+ tmpClusterMCInfo.fClusterID[1]=zeroMC;
+ }
+
+ if(fClusterMCVector.size()>2){
+ tmpClusterMCInfo.fClusterID[2]=fClusterMCVector.at(2);
+ }
+ else{
+ tmpClusterMCInfo.fClusterID[2]=zeroMC;
+ }
+
+ fClustersMCInfo.push_back(tmpClusterMCInfo);
+ }
+
+ }
+ }
+ tmpPad->ClearCandidates();
+ }
+ fRowPadVector[row][fNumberOfPadsInRow[row]]->ClearCandidates();
+ }
+
+ HLTInfo("Found %d clusters.",fClusters.size());
+
+ //TODO: Change so it stores AliHLTTPCSpacePointData directly, instead of this copying
+
+ AliClusterData * clusterlist = new AliClusterData[fClusters.size()]; //Clusterlist
+ for(unsigned int i=0;i<fClusters.size();i++){
+ clusterlist[i].fTotalCharge = fClusters[i].fTotalCharge;
+ clusterlist[i].fPad = fClusters[i].fPad;
+ clusterlist[i].fPad2 = fClusters[i].fPad2;
+ clusterlist[i].fTime = fClusters[i].fTime;
+ clusterlist[i].fTime2 = fClusters[i].fTime2;
+ clusterlist[i].fMean = fClusters[i].fMean;
+ clusterlist[i].fFlags = fClusters[i].fFlags;
+ clusterlist[i].fChargeFalling = fClusters[i].fChargeFalling;
+ clusterlist[i].fLastCharge = fClusters[i].fLastCharge;
+ clusterlist[i].fLastMergedPad = fClusters[i].fLastMergedPad;
+ clusterlist[i].fRow = fClusters[i].fRowNumber;
+ clusterlist[i].fQMax = fClusters[i].fQMax;
+ }
+
+ WriteClusters(fClusters.size(),clusterlist);
+ delete [] clusterlist;
+ fClusters.clear();
+ if( fReleaseMemory ) DeInitializePadArray();// call this when the -releaseMemory flag is set
+}
+
+
+Bool_t AliHLTTPCClusterFinder::UpdateCalibDB(){
+
+ //update the db
+ AliTPCcalibDB::Instance()->Update();
+
+ Bool_t ret = 1;
+
+ //uptate the transform class
+
+ fOfflineTransform = AliTPCcalibDB::Instance()->GetTransform();
+ if(!fOfflineTransform){
+ HLTError("AliHLTTPCClusterFinder()::UpdateCAlibDB:: Offline transform not in AliTPCcalibDB.");
+ ret = 0;
+ }
+ else{
+ fOfflineTransform->SetCurrentRecoParam(&fOfflineTPCRecoParam);
+ }
+
+ fOfflineTPCParam = AliTPCcalibDB::Instance()->GetParameters();
+ if( !fOfflineTPCParam ){
+ HLTError("AliHLTTPCClusterFinder()::UpdateCAlibDB:: Offline TPC parameters not in AliTPCcalibDB.");
+ ret = 0;
+ } else {
+ fOfflineTPCParam->Update();
+ fOfflineTPCParam->ReadGeoMatrices();
+ }
+
+ return ret;
+}
+
+//---------------------------------- Under this line the old sorted clusterfinder functions can be found --------------------------------
+
+
+void AliHLTTPCClusterFinder::PrintClusters(){
+ // see header file for class documentation
+
+ for(size_t i=0;i<fClusters.size();i++){
+ HLTInfo("Cluster number: %d",i);
+ HLTInfo("Row: %d \t Pad: %d",fClusters[i].fRowNumber,fClusters[i].fPad/fClusters[i].fTotalCharge);
+ HLTInfo("Total Charge: %d",fClusters[i].fTotalCharge);
+ HLTInfo("fPad: %d",fClusters[i].fPad);
+ HLTInfo("PadError: %d",fClusters[i].fPad2);
+ HLTInfo("TimeMean: %d",fClusters[i].fTime/fClusters[i].fTotalCharge);
+ HLTInfo("TimeError: %d",fClusters[i].fTime2);
+ HLTInfo("EndOfCluster:");
+ }
+}
+
+void AliHLTTPCClusterFinder::FillMCClusterVector(vector<AliHLTTPCDigitData> digitData){
+ // see header file for class documentation
+
+ for(UInt_t d=0;d<digitData.size();d++){
+ Int_t nIDsInDigit = (digitData.at(d).fTrackID[0]>=0) + (digitData.at(d).fTrackID[1]>=0) + (digitData.at(d).fTrackID[2]>=0);
+ for(Int_t id=0; id<3; id++){
+ if(digitData.at(d).fTrackID[id]>=0){
+ Bool_t matchFound = kFALSE;
+ MCWeight mc;
+ mc.fMCID = digitData.at(d).fTrackID[id];
+ mc.fWeight = ((Float_t)digitData.at(d).fCharge)/nIDsInDigit;
+ for(UInt_t i=0;i<fClusterMCVector.size();i++){
+ if(mc.fMCID == fClusterMCVector.at(i).fMCID){
+ fClusterMCVector.at(i).fWeight += mc.fWeight;
+ matchFound = kTRUE;
+ }
+ }
+ if(matchFound == kFALSE){
+ fClusterMCVector.push_back(mc);
+ }
+ }
+ }
+ }
+}
+
+