3 // Author: Anders Vestbo <mailto:vestbo@fi.uib.no>
4 //*-- Copyright © ASV
6 #include "AliL3StandardIncludes.h"
8 #include "AliL3Modeller.h"
9 #include "AliL3MemHandler.h"
11 #include "AliL3FileHandler.h"
13 #include "AliL3TrackArray.h"
14 #include "AliL3ModelTrack.h"
15 #include "AliL3DigitData.h"
16 #include "AliL3Transform.h"
22 //_____________________________________________________________
25 // Class for modeling TPC data.
27 // This performs the cluster finding, based on track parameters.
28 // Basically it propagates the tracks to all padrows, and looks
29 // for a corresponding cluster. For the moment only cog is calculated,
30 // and no deconvolution is done.
32 ClassImp(AliL3Modeller)
34 AliL3Modeller::AliL3Modeller()
45 AliL3Modeller::~AliL3Modeller()
53 void AliL3Modeller::Init(Int_t slice,Int_t patch,Char_t *trackdata,Char_t *path,Bool_t houghtracks,Bool_t binary)
58 sprintf(fPath,"%s",path);
60 fTracks = new AliL3TrackArray("AliL3ModelTrack");
63 AliL3MemHandler *file = new AliL3MemHandler();
64 //sprintf(fname,"%s/tracks_tr_%d_0.raw",trackdata,fSlice); //output tracks from the tracker (no merging)
65 sprintf(fname,"%s/tracks_ho_%d.raw",trackdata,fSlice);
66 if(!file->SetBinaryInput(fname))
68 cerr<<"AliL3Modeller::Init : Error opening trackfile: "<<fname<<endl;
71 file->Binary2TrackArray(fTracks);
72 file->CloseBinaryInput();
79 for(Int_t i=0; i<fTracks->GetNTracks(); i++)
81 AliL3ModelTrack *track = (AliL3ModelTrack*)fTracks->GetCheckedTrack(i);
83 track->Init(fSlice,fPatch);
85 //Only if the tracks has been merged across sector boundaries:
87 //track->Rotate(fSlice,kTRUE); //!!!!!!!!!!!!!!!!!!!
89 track->CalculateHelix();
92 CalculateCrossingPoints();
97 AliL3DigitRowData *digits=0;
99 fMemHandler = new AliL3FileHandler();
100 fMemHandler->Init(slice,patch);
103 sprintf(fname,"%s/digitfile.root",fPath);
104 fMemHandler->SetAliInput(fname);
105 digits = fMemHandler->AliDigits2Memory(ndigits);
109 sprintf(fname,"%sdigits_%d_%d.raw",fPath,fSlice,fPatch);
110 if(!fMemHandler->SetBinaryInput(fname))
112 cerr<<"AliL3Modeller::Init : Error opening file "<<fname<<endl;
115 digits=(AliL3DigitRowData*)fMemHandler->CompBinary2Memory(ndigits);
118 fMemHandler = new AliL3MemHandler();
119 fMemHandler->Init(slice,patch);
122 cerr<<"AliL3Modeller::Init : Compile with AliROOT if you want rootfile as input"<<endl;
127 sprintf(fname,"%sdigits_%d_%d.raw",fPath,fSlice,fPatch);
128 if(!fMemHandler->SetBinaryInput(fname))
130 cerr<<"AliL3Modeller::Init : Error opening file "<<fname<<endl;
134 digits=(AliL3DigitRowData*)fMemHandler->CompBinary2Memory(ndigits);
137 SetInputData(digits);
140 void AliL3Modeller::FindClusters()
142 cout<<"AliL3Modeller::FindClusters : Processing slice "<<fSlice<<" patch "<<fPatch<<endl;
145 cerr<<"AliL3Modeller::Process : No tracks"<<endl;
150 cerr<<"AliL3Modeller::Process : No data "<<endl;
154 AliL3DigitRowData *rowPt = fRowData;
155 AliL3DigitData *digPt=0;
157 Int_t ntimes = AliL3Transform::GetNTimeBins()+1;
158 Int_t npads = AliL3Transform::GetNPads(AliL3Transform::GetLastRow(fPatch))+1;//Max num of pads.
159 Int_t bounds = ntimes*npads;
160 Digit *row = new Digit[bounds];
163 Int_t pad,time,index;
167 for(Int_t i=AliL3Transform::GetFirstRow(fPatch); i<=AliL3Transform::GetLastRow(fPatch); i++)
170 memset((void*)row,0,ntimes*npads*sizeof(Digit));
171 digPt = (AliL3DigitData*)rowPt->fDigitData;
172 //cout<<"Loading row "<<i<<" with "<<(Int_t)rowPt->fNDigit<<" digits"<<endl;
173 for(UInt_t j=0; j<rowPt->fNDigit; j++)
176 time = digPt[j].fTime;
177 charge = digPt[j].fCharge;
178 row[ntimes*pad+time].fCharge = charge;
179 row[ntimes*pad+time].fUsed = kFALSE;
180 //cout<<"Row "<<i<<" pad "<<pad<<" time "<<time<<" charge "<<charge<<endl;
183 for(Int_t k=0; k<fTracks->GetNTracks(); k++)
185 AliL3ModelTrack *track = (AliL3ModelTrack*)fTracks->GetCheckedTrack(k);
188 if(track->GetPadHit(i)<0 || track->GetTimeHit(i)<0 || track->GetOverlap(i)>=0)
190 track->SetCluster(i,0,0,0,0,0,0); //The track has left the patch.
194 Int_t hitpad = (Int_t)rint(track->GetPadHit(i));
195 Int_t hittime = (Int_t)rint(track->GetTimeHit(i));
197 if(!CheckCluster(row,hitpad,hittime)) //Not a good cluster.
199 track->SetCluster(i,0,0,0,0,0,0);
203 //cout<<"Checking track on row "<<i<<" with pad "<<hitpad<<" time "<<hittime<<endl;
210 memset(&cluster,0,sizeof(Cluster));
211 //cout<<"Processing padrow "<<i<<" with hittime "<<hittime<<" hitpad "<<hitpad<<" charge "<<row[ntimes*pad + time].fCharge<<" index "<<ntimes*pad + time<<endl;
213 Int_t last_mean = hittime;
214 while(1)//Process this padrow
216 if(pad < 0 || pad >= AliL3Transform::GetNPads(i))
218 //cout<<"Pad = "<<pad<<" on row "<<i<<endl;
219 FillCluster(track,&cluster,i,npads);
226 while(1) //Process sequence on this pad:
228 if(time < 0 || time >= AliL3Transform::GetNTimeBins())
231 index = ntimes*pad + time;
232 if(index < 0 || index >= bounds)
234 cerr<<"AliL3Modeller::FindClusters : Index out of range : "<<index
235 <<" on row "<<i<<" pad "<<pad<<" time "<<time<<endl;
239 charge = row[index].fCharge;
241 if(charge==0) //Empty timebin, so try and expand the search within the limits on this pad
243 if(seq_charge==0 && abs(time-hittime) <= fTimeSearch)//No sequence yet, keep looking
251 else if(timesign==-1) //Switch search direction
257 else //ok, boundary reached, this pad is done.
261 if(row[ntimes*pad+time].fUsed==kTRUE) //Don't use digits several times. This leads to mult. rec.tracks.
267 seq_charge += charge;
269 //Update the cluster parameters with this timebin
270 cluster.fTime += time*charge;
271 cluster.fPad += pad*charge;
272 cluster.fCharge += charge;
273 cluster.fSigmaY2 += pad*pad*charge;
274 cluster.fSigmaZ2 += time*time*charge;
276 row[ntimes*pad+time].fUsed = kTRUE;
280 //Always compare with the current mean in time of the cluster under construction.
282 last_mean = (Int_t)rint((Float_t)(cluster.fTime/cluster.fCharge));
284 if(seq_charge)//There was something on this pad, so keep looking on the neighbouring pad
291 if(cluster.fCharge==0 && abs(pad-hitpad) <= fPadSearch && pad > 0)
307 FillCluster(track,&cluster,i,npads);
312 //cout<<"done"<<endl;
314 FillZeros(rowPt,row);
315 fMemHandler->UpdateRowPointer(rowPt);
318 //cout<<"done processing"<<endl;
322 for(Int_t i=0; i<fTracks->GetNTracks(); i++)
324 AliL3ModelTrack *track = (AliL3ModelTrack*)fTracks->GetCheckedTrack(i);
326 if(track->GetNClusters() != AliL3Transform::GetNRows(fPatch))
327 cerr<<endl<<"Mismatching hitcounts; nclusters: "<<track->GetNClusters()<<" nrows "<<AliL3Transform::GetNRows(fPatch)<<endl<<endl;
332 Bool_t AliL3Modeller::CheckCluster(Digit *row,Int_t hitpad,Int_t hittime)
334 Int_t ntimes = AliL3Transform::GetNTimeBins()+1;
335 Bool_t seq_was_falling=kFALSE;
336 Int_t last_seq_charge=0;
337 Int_t cluster_charge=0;
338 Int_t time,pad,charge,padsign=-1,timesign=-1;
341 //cout<<"Checking cluster "<<hitpad<<" hittime "<<hittime<<endl;
345 Bool_t last_was_falling=kFALSE;
351 charge = row[(ntimes*pad+time)].fCharge;
352 //cout<<"Charge "<<charge<<" on pad "<<pad<<" time "<<time<<endl;
355 if(seq_charge==0 && abs(time-hittime) <= fTimeSearch)
363 else if(timesign==-1)
365 last_charge = row[(ntimes*hitpad+hittime)].fCharge;
368 if(last_charge < row[(ntimes*hitpad+(hittime-1))].fCharge)
369 last_was_falling=kTRUE;
371 last_was_falling=kFALSE;
378 if(charge > last_charge)
380 if(last_was_falling) //This is a overlapping cluster.
384 last_was_falling = kTRUE;
386 cluster_charge+=charge;
387 seq_charge += charge;
388 last_charge = charge;
396 if(cluster_charge==0 && abs(pad-hitpad)<=fPadSearch && pad > 0)
408 seq_was_falling=kFALSE;
415 if(seq_charge > last_seq_charge)
420 seq_was_falling=kTRUE;
422 last_seq_charge = seq_charge;
428 void AliL3Modeller::FillCluster(AliL3ModelTrack *track,Cluster *cluster,Int_t row,Int_t npads)
430 if(cluster->fCharge==0)
432 track->SetCluster(row,0,0,0,0,0,0);
435 Float_t fcharge = (Float_t)cluster->fCharge;
436 Float_t fpad = ((Float_t)cluster->fPad/fcharge);
437 Float_t ftime = ((Float_t)cluster->fTime/fcharge);
438 Float_t sigmaY2,sigmaZ2;
439 CalcClusterWidth(cluster,sigmaY2,sigmaZ2);
440 track->SetCluster(row,fpad,ftime,fcharge,sigmaY2,sigmaZ2,npads);
443 void AliL3Modeller::FillZeros(AliL3DigitRowData *rowPt,Digit *row)
445 //Fill zero where data has been used.
447 Int_t ntimes = AliL3Transform::GetNTimeBins()+1;
448 AliL3DigitData *digPt = (AliL3DigitData*)rowPt->fDigitData;
449 for(UInt_t j=0; j<rowPt->fNDigit; j++)
451 Int_t pad = digPt[j].fPad;
452 Int_t time = digPt[j].fTime;
453 if(row[ntimes*pad+time].fUsed==kTRUE)
454 digPt[j].fCharge = 0;
458 void AliL3Modeller::WriteRemaining()
460 //Write remaining (nonzero) digits to file.
462 AliL3DigitRowData *rowPt;
463 rowPt = (AliL3DigitRowData*)fRowData;
465 Int_t ndigits[(AliL3Transform::GetNRows(fPatch))];
466 for(Int_t i=AliL3Transform::GetFirstRow(fPatch); i<=AliL3Transform::GetLastRow(fPatch); i++)
468 AliL3DigitData *digPt = (AliL3DigitData*)rowPt->fDigitData;
469 ndigits[(i-AliL3Transform::GetFirstRow(fPatch))]=0;
470 for(UInt_t j=0; j<rowPt->fNDigit; j++)
472 if(digPt[j].fCharge==0) continue;
474 ndigits[(i-AliL3Transform::GetFirstRow(fPatch))]++;
476 //cout<<"Difference "<<(int)ndigits[(i-AliL3Transform::GetFirstRow(fPatch))]<<" "<<(int)rowPt->fNDigit<<endl;
477 fMemHandler->UpdateRowPointer(rowPt);
480 Int_t size = digitcount*sizeof(AliL3DigitData) + AliL3Transform::GetNRows(fPatch)*sizeof(AliL3DigitRowData);
481 Byte_t *data = new Byte_t[size];
483 AliL3DigitRowData *tempPt = (AliL3DigitRowData*)data;
484 rowPt = (AliL3DigitRowData*)fRowData;
486 for(Int_t i=AliL3Transform::GetFirstRow(fPatch); i<=AliL3Transform::GetLastRow(fPatch); i++)
490 tempPt->fNDigit = ndigits[(i-AliL3Transform::GetFirstRow(fPatch))];
491 AliL3DigitData *digPt = (AliL3DigitData*)rowPt->fDigitData;
492 for(UInt_t j=0; j<rowPt->fNDigit; j++)
494 if(digPt[j].fCharge==0) continue;
495 if(localcount >= ndigits[(i-AliL3Transform::GetFirstRow(fPatch))])
497 cerr<<"AliL3Modeller::WriteRemaining : Digitarray out of range!!"<<endl;
500 tempPt->fDigitData[localcount].fCharge = digPt[j].fCharge;
501 tempPt->fDigitData[localcount].fPad = digPt[j].fPad;
502 tempPt->fDigitData[localcount].fTime = digPt[j].fTime;
506 if(ndigits[(i-AliL3Transform::GetFirstRow(fPatch))] != localcount)
508 cerr<<"AliL3Modeller::WriteRemaining : Mismatch in digitcount"<<endl;
511 fMemHandler->UpdateRowPointer(rowPt);
512 Byte_t *tmp = (Byte_t*)tempPt;
513 Int_t size = sizeof(AliL3DigitRowData) + ndigits[(i-AliL3Transform::GetFirstRow(fPatch))]*sizeof(AliL3DigitData);
515 tempPt = (AliL3DigitRowData*)tmp;
519 AliL3MemHandler *mem = new AliL3MemHandler();
520 sprintf(fname,"%s/comp/remains_%d_%d.raw",fPath,fSlice,fPatch);
521 mem->SetBinaryOutput(fname);
522 mem->Memory2CompBinary((UInt_t)AliL3Transform::GetNRows(fPatch),(AliL3DigitRowData*)data);
523 mem->CloseBinaryOutput();
529 void AliL3Modeller::CalculateCrossingPoints()
531 //cout<<"Calculating crossing points on "<<fTracks->GetNTracks()<<" tracks"<<endl;
534 cerr<<"AliL3Modeller::CalculateCrossingPoints(): No tracks"<<endl;
540 for(Int_t i=AliL3Transform::GetLastRow(fPatch); i>=AliL3Transform::GetFirstRow(fPatch); i--)
542 for(Int_t j=0; j<fTracks->GetNTracks(); j++)
544 AliL3ModelTrack *track = (AliL3ModelTrack*)fTracks->GetCheckedTrack(j);
547 if(!track->GetCrossingPoint(i,hit))
549 //cerr<<"AliL3Modeller::CalculateCrossingPoints : Track "<<j<<" does not intersect row "<<i<<" :"<<endl<<
550 //" pt "<<track->GetPt()<<
551 //" tgl "<<track->GetTgl()<<" psi "<<track->GetPsi()<<" charge "<<track->GetCharge()<<endl;
552 //"Center "<<track->GetCenterX()<<" "<<track->GetCenterY()<<endl<<endl<<
557 //cout<<"X "<<hit[0]<<" Y "<<hit[1]<<" Z "<<hit[2]<<" tgl "<<track->GetTgl()<<endl;
559 AliL3Transform::Slice2Sector(fSlice,i,sector,row);
560 AliL3Transform::Local2Raw(hit,sector,row);
561 //cout<<"Pad "<<hit[1]<<" time "<<hit[2]<<" in sector "<<sector<<" row "<<row<<endl;
562 if(hit[1]<0 || hit[1]>AliL3Transform::GetNPads(i) ||
563 hit[2]<0 || hit[2]>AliL3Transform::GetNTimeBins())
564 {//Track is leaving the patch, so flag the track hits (<0)
565 track->SetPadHit(i,-1);
566 track->SetTimeHit(i,-1);
571 track->SetPadHit(i,hit[1]);
572 track->SetTimeHit(i,hit[2]);
574 //if(hit[1]<0 || hit[2]>445)
575 //if(hit[2]<0 || hit[2]>445)
576 //cout<<"pad "<<hit[1]<<" time "<<hit[2]<<" pt "<<track->GetPt()<<" psi "<<track->GetPsi()<<" tgl "<<track->GetTgl()<<" firstpoint "<<track->GetFirstPointX()<<" "<<track->GetFirstPointY()<<" "<<track->GetFirstPointZ()<<endl;
577 //cout<<"Crossing pad "<<hit[1]<<" time "<<hit[2]<<endl;
581 //cout<<"And there are "<<fTracks->GetNTracks()<<" tracks remaining"<<endl;
584 void AliL3Modeller::CheckForOverlaps()
586 //Flag the tracks that overlap
588 //cout<<"Checking for overlaps...";
590 for(Int_t i=0; i<fTracks->GetNTracks(); i++)
592 AliL3ModelTrack *track1 = (AliL3ModelTrack*)fTracks->GetCheckedTrack(i);
593 if(!track1) continue;
594 for(Int_t j=i+1; j<fTracks->GetNTracks(); j++)
596 AliL3ModelTrack *track2 = (AliL3ModelTrack*)fTracks->GetCheckedTrack(j);
597 if(!track2) continue;
598 for(Int_t k=AliL3Transform::GetFirstRow(fPatch); k<=AliL3Transform::GetLastRow(fPatch); k++)
600 if(track1->GetPadHit(k)<0 || track1->GetTimeHit(k)<0 ||
601 track2->GetPadHit(k)<0 || track2->GetTimeHit(k)<0)
604 if(track1->GetOverlap(k)>=0 || track2->GetOverlap(k)>=0) continue;
606 if(abs((Int_t)rint(track1->GetPadHit(k))-(Int_t)rint(track2->GetPadHit(k))) <= fPadOverlap &&
607 abs((Int_t)rint(track1->GetTimeHit(k))-(Int_t)rint(track2->GetTimeHit(k))) <= fTimeOverlap)
609 track2->SetOverlap(k,i);
610 //track1->SetOverlap(k,j);
616 //cout<<"found "<<counter<<" done"<<endl;
620 void AliL3Modeller::CalcClusterWidth(Cluster *cl,Float_t &sigmaY2,Float_t &sigmaZ2)
625 padw = AliL3Transform::GetPadPitchWidth(fPatch);
627 Float_t charge = (Float_t)cl->fCharge;
628 Float_t pad = (Float_t)cl->fPad/charge;
629 Float_t time = (Float_t)cl->fTime/charge;
630 Float_t s2 = (Float_t)cl->fSigmaY2/charge - pad*pad;
632 //Save the sigmas in pad and time:
634 sigmaY2 = (s2);// + 1./12);//*padw*padw;
636 /*Constants added by offline
639 sigmaY2 = sigmaY2*0.108;
641 sigmaY2 = sigmaY2*2.07;
645 s2 = (Float_t)cl->fSigmaZ2/charge - time*time;
646 timew = AliL3Transform::GetZWidth();
647 sigmaZ2 = (s2);// +1./12);//*timew*timew;
651 /*Constants added by offline
654 sigmaZ2 = sigmaZ2*0.169;
656 sigmaZ2 = sigmaZ2*1.77;