Bugfix in AliL3FileHandler::GetDigitsTree.
[u/mrichter/AliRoot.git] / HLT / src / AliL3FileHandler.cxx
1 //$Id$
2
3 // Author: Uli Frankenfeld <mailto:franken@fi.uib.no>, Anders Vestbo <mailto:vestbo$fi.uib.no>
4 //*-- Copyright &copy Uli 
5
6 #include <math.h>
7 #include <iostream.h>
8
9 #include "AliL3Transform.h"
10 #include "AliL3Logging.h"
11 #include "AliL3MemHandler.h"
12 #include "AliL3FileHandler.h"
13
14 #include "AliTPCDigitsArray.h"
15 #include "AliTPCClustersArray.h"
16 #include "AliTPCcluster.h"
17 #include "AliTPCClustersRow.h"
18
19 #include "AliL3DigitData.h"
20 #include "AliL3TrackSegmentData.h"
21 #include "AliL3SpacePointData.h"
22 #include "AliL3TrackArray.h"
23
24 //_____________________________________________________________
25 // AliL3FileHandler
26 //
27 // The HLT ROOT <-> binary files handling class
28 //
29 // This class provides the interface between AliROOT files,
30 // and HLT binary files. It should be used for converting 
31 // TPC data stored in AliROOT format (outputfile from a simulation),
32 // into the data format currently used by in the HLT framework. 
33 // This enables the possibility to always use the same data format, 
34 // whether you are using a binary file as an input, or a AliROOT file.
35 //
36 // For example on how to create binary files from a AliROOT simulation,
37 // see example macro exa/Binary.C.
38 //
39 // For reading a AliROOT file into HLT format in memory, do the following:
40 //
41 // AliL3FileHandler file;
42 // file.SetAliInput("galice.root");
43 // AliL3DigitRowData *dataPt = (AliL3DigitRowData*)file.AliDigits2Memory(nrows,eventnr);
44 // 
45 // All the data are then stored in memory and accessible via the pointer dataPt.
46 // Accesing the data is then identical to the example 1) showed in AliL3MemHandler class.
47 //
48 // For converting the data back, and writing it to a new AliROOT file do:
49 //
50 // AliL3FileHandler file;
51 // file.SetAliInput("galice.root");
52 // file.Init(slice,patch,NumberOfRowsInPatch);
53 // file.AliDigits2RootFile(dataPt,"new_galice.root");
54 // file.CloseAliInput();
55
56 ClassImp(AliL3FileHandler)
57
58 AliL3FileHandler::AliL3FileHandler()
59 {
60   //Default constructor
61   fInAli = 0;
62   fParam = 0;
63   fMC =0;
64   fLastIndex=0;
65   fDigits=0;
66   fDigitsTree=0;
67 }
68
69 AliL3FileHandler::~AliL3FileHandler()
70 {
71   //Destructor
72   if(fMC) CloseMCOutput();
73   FreeDigitsTree();
74   if(fInAli) CloseAliInput();
75   
76 }
77
78 void AliL3FileHandler::FreeDigitsTree()
79 {
80   if(!fDigitsTree)
81     {
82       LOG(AliL3Log::kWarning,"AliL3FileHandler::FreeDigitsTree()","Pointer")
83         <<"Cannot free digitstree, it is not present"<<ENDLOG;
84       return;
85     }
86   fDigits=0;
87   fDigitsTree->Delete();
88   fDigitsTree=0;
89 }
90
91
92 Bool_t AliL3FileHandler::SetMCOutput(char *name)
93 {
94   fMC = fopen(name,"w");
95   if(!fMC){
96     LOG(AliL3Log::kWarning,"AliL3FileHandler::SetMCOutput","File Open")
97       <<"Pointer to File = 0x0 "<<ENDLOG;
98     return kFALSE;
99   }
100   return kTRUE;
101 }
102
103 Bool_t AliL3FileHandler::SetMCOutput(FILE *file)
104 {
105   fMC = file;
106   if(!fMC){
107     LOG(AliL3Log::kWarning,"AliL3FileHandler::SetMCOutput","File Open")
108       <<"Pointer to File = 0x0 "<<ENDLOG;
109     return kFALSE;
110   }
111   return kTRUE;
112 }
113
114 void AliL3FileHandler::CloseMCOutput()
115 {
116   if(!fMC){
117     LOG(AliL3Log::kWarning,"AliL3FileHandler::CloseMCOutPut","File Close")
118       <<"Nothing to Close"<<ENDLOG;
119     return;
120   }
121   fclose(fMC);
122   fMC =0;
123 }
124
125 Bool_t AliL3FileHandler::SetAliInput()
126 {
127   if(!fInAli->IsOpen()){
128     LOG(AliL3Log::kError,"AliL3FileHandler::SetAliInput","File Open")
129       <<"Ali File "<<fInAli->GetName()<<" does not exist"<<ENDLOG;
130     return kFALSE;
131   }
132   fParam = (AliTPCParam*)fInAli->Get("75x40_100x60");
133   if(!fParam){ 
134     LOG(AliL3Log::kError,"AliL3FileHandler::SetAliInput","File Open")
135       <<"No AliTPCParam 75x40_100x60 in File "<<fInAli->GetName()<<ENDLOG;
136     return kFALSE;
137   }
138   return kTRUE;
139 }
140
141 Bool_t AliL3FileHandler::SetAliInput(char *name)
142 {
143   //Open the AliROOT file with name.
144   
145   fInAli= new TFile(name,"READ");
146   if(!fInAli){
147     LOG(AliL3Log::kWarning,"AliL3FileHandler::SetAliInput","File Open")
148     <<"Pointer to TFile = 0x0 "<<ENDLOG;
149     return kFALSE;
150   }
151   return SetAliInput();
152 }
153
154 Bool_t AliL3FileHandler::SetAliInput(TFile *file)
155 {
156   //Specify already opened AliROOT file to use as an input.
157   
158   fInAli=file;
159   if(!fInAli){
160     LOG(AliL3Log::kWarning,"AliL3FileHandler::SetAliInput","File Open")
161     <<"Pointer to TFile = 0x0 "<<ENDLOG;
162     return kFALSE;
163   }
164   return SetAliInput();
165 }
166
167 void AliL3FileHandler::CloseAliInput()
168 {
169   if(!fInAli){
170     LOG(AliL3Log::kWarning,"AliL3FileHandler::CloseAliInput","File Close")
171       <<"Nothing to Close"<<ENDLOG;
172     return;
173   }
174   if(fInAli->IsOpen()) fInAli->Close();
175   delete fInAli;
176   fInAli = 0;
177   
178 }
179
180 Bool_t AliL3FileHandler::IsDigit()
181 {
182   //Check if there is a TPC digit tree in the current file.
183   //Return kTRUE if tree was found, and kFALSE if not found.
184   
185   if(!fInAli){
186     LOG(AliL3Log::kWarning,"AliL3FileHandler::IsDigit","File")
187     <<"Pointer to TFile = 0x0 "<<ENDLOG;
188     return kTRUE;  //may you are use binary input which is Digits!!
189   }
190   TTree *t=(TTree*)fInAli->Get("TreeD_75x40_100x60_0");
191   if(t){
192     LOG(AliL3Log::kInformational,"AliL3FileHandler::IsDigit","File Type")
193     <<"Found Digit Tree -> Use Fast Cluster Finder"<<ENDLOG;
194     return kTRUE;
195   }
196   else{
197     LOG(AliL3Log::kInformational,"AliL3FileHandler::IsDigit","File Type")
198     <<"No Digit Tree -> Use Cluster Tree"<<ENDLOG;
199     return kFALSE;
200   }
201 }
202
203 ///////////////////////////////////////// Digit IO  
204 Bool_t AliL3FileHandler::AliDigits2Binary(Int_t event)
205 {
206   
207   Bool_t out = kTRUE;
208   UInt_t nrow;
209   AliL3DigitRowData* data = AliDigits2Memory(nrow,event);
210   out = Memory2Binary(nrow,data);
211   Free();
212   return out;
213 }
214
215
216 Bool_t AliL3FileHandler::AliDigits2CompBinary(Int_t event)
217 {
218   //Convert AliROOT TPC data, into HLT data format.
219   //event specifies the event you want in the aliroot file.
220   
221   Bool_t out = kTRUE;
222   UInt_t ndigits=0;
223   AliL3DigitRowData* digits = AliDigits2Memory(ndigits,event);
224   out = Memory2CompBinary(ndigits,digits);
225   Free();
226   return out;
227 }
228
229
230 AliL3DigitRowData * AliL3FileHandler::AliDigits2Memory(UInt_t & nrow,Int_t event)
231 {
232   //Read data from AliROOT file into memory, and store it in the HLT data format.
233   //Returns a pointer to the data.
234
235   AliL3DigitRowData *data = 0;
236   nrow=0;
237   if(!fInAli){
238     LOG(AliL3Log::kWarning,"AliL3FileHandler::AliDigits2Memory","File")
239     <<"No Input avalible: no object TFile"<<ENDLOG;
240     return 0; 
241   }
242   if(!fInAli->IsOpen()){
243     LOG(AliL3Log::kWarning,"AliL3FileHandler::AliDigits2Memory","File")
244     <<"No Input avalible: TFile not opend"<<ENDLOG;
245     return 0;
246   }
247   
248   if(!fDigitsTree)
249     GetDigitsTree(event);
250   
251   UShort_t dig;
252   Int_t time,pad,sector,row;
253   Int_t nrows=0;
254   Int_t ndigitcount=0;
255   Int_t entries = (Int_t)fDigitsTree->GetEntries();
256   Int_t ndigits[entries];
257   Int_t lslice,lrow;
258   
259   for(Int_t n=fLastIndex; n<fDigitsTree->GetEntries(); n++)
260     {
261       fDigitsTree->GetEvent(n);
262       fParam->AdjustSectorRow(fDigits->GetID(),sector,row);
263       AliL3Transform::Sector2Slice(lslice,lrow,sector,row);
264       //if(fSlice != lslice || lrow<fRowMin || lrow>fRowMax) continue;
265       if(lslice < fSlice) continue;
266       if(lslice != fSlice) break;
267       if(lrow < fRowMin) continue;
268       if(lrow > fRowMax) break;
269       
270       Float_t xyz[3];
271       ndigits[lrow] = 0;
272       fDigits->First();
273       do {
274         time=fDigits->CurrentRow();
275         pad=fDigits->CurrentColumn();
276         dig = fDigits->GetDigit(time,pad);
277         if(dig<=fParam->GetZeroSup()) continue;
278         
279         /*
280           if(time < fParam->GetMaxTBin()-1 && time > 0)
281           if(fDigits->GetDigit(time+1,pad) <= fParam->GetZeroSup()
282           && fDigits->GetDigit(time-1,pad) <= fParam->GetZeroSup())
283           continue;
284         */
285         
286         AliL3Transform::Raw2Local(xyz,sector,row,pad,time);
287         if(fParam->GetPadRowRadii(sector,row)<230./250.*fabs(xyz[2]))
288           continue;
289
290         ndigits[lrow]++; //for this row only
291         ndigitcount++;  //total number of digits to be published
292
293       } while (fDigits->Next());
294
295       nrows++;
296     }
297   Int_t size = sizeof(AliL3DigitData)*ndigitcount
298     + nrows*sizeof(AliL3DigitRowData);
299
300   LOG(AliL3Log::kDebug,"AliL3FileHandler::AliDigits2Memory","Digits")
301     <<AliL3Log::kDec<<"Found "<<ndigitcount<<" Digits"<<ENDLOG;
302   
303   data=(AliL3DigitRowData*) Allocate(size);
304   nrow = (UInt_t)nrows;
305   AliL3DigitRowData *tempPt = data;
306   for(Int_t n=fLastIndex; n<fDigitsTree->GetEntries(); n++)
307     {
308       fDigitsTree->GetEvent(n);
309       Float_t xyz[3];
310       fParam->AdjustSectorRow(fDigits->GetID(),sector,row);
311       AliL3Transform::Sector2Slice(lslice,lrow,sector,row);
312       //if(fSlice != lslice || lrow<fRowMin || lrow>fRowMax) continue;
313       if(lslice < fSlice) continue;
314       if(lslice != fSlice) break;
315       if(lrow < fRowMin) continue;
316       if(lrow > fRowMax) break;
317
318       tempPt->fRow = lrow;
319       tempPt->fNDigit = ndigits[lrow];
320
321       Int_t localcount=0;
322       fDigits->First();
323       do {
324         //dig=fDigits->CurrentDigit();
325         //if (dig<=fParam->GetZeroSup()) continue;
326         time=fDigits->CurrentRow();
327         pad=fDigits->CurrentColumn();
328         dig = fDigits->GetDigit(time,pad);
329         if (dig <= fParam->GetZeroSup()) continue;
330         
331         /*
332           if(time < fParam->GetMaxTBin()-1 && time > 0)
333           if(fDigits->GetDigit(time-1,pad) <= fParam->GetZeroSup() &&
334           fDigits->GetDigit(time+1,pad) <= fParam->GetZeroSup()) continue;
335         */
336         
337         //Exclude data outside cone:
338         AliL3Transform::Raw2Local(xyz,sector,row,pad,time);
339         if(fParam->GetPadRowRadii(sector,row)<230./250.*fabs(xyz[2]))
340           continue;
341
342         if(localcount >= ndigits[lrow])
343           LOG(AliL3Log::kFatal,"AliL3FileHandler::AliDigits2Binary","Memory")
344             <<AliL3Log::kDec<<"Mismatch: localcount "<<localcount<<" ndigits "
345             <<ndigits[lrow]<<ENDLOG;
346         
347         tempPt->fDigitData[localcount].fCharge=dig;
348         tempPt->fDigitData[localcount].fPad=pad;
349         tempPt->fDigitData[localcount].fTime=time;
350 #ifdef do_mc
351         tempPt->fDigitData[localcount].fTrackID[0] = fDigits->GetTrackID(time,pad,0);
352         tempPt->fDigitData[localcount].fTrackID[1] = fDigits->GetTrackID(time,pad,1);
353         tempPt->fDigitData[localcount].fTrackID[2] = fDigits->GetTrackID(time,pad,2);
354 #endif
355         localcount++;
356       } while (fDigits->Next());
357
358       Byte_t *tmp = (Byte_t*)tempPt;
359       Int_t size = sizeof(AliL3DigitRowData)
360                                       + ndigits[lrow]*sizeof(AliL3DigitData);
361       tmp += size;
362       tempPt = (AliL3DigitRowData*)tmp;
363       //fLastIndex=n;
364     }
365   //fLastIndex++;
366   return data;
367 }
368
369
370 Bool_t AliL3FileHandler::GetDigitsTree(Int_t event)
371 {
372   //Connects to the TPC digit tree in the AliROOT file.
373   
374   fInAli->cd();
375   Char_t dname[100];
376   sprintf(dname,"TreeD_75x40_100x60_%d",event);
377   fDigitsTree = (TTree*)fInAli->Get(dname);
378   if(!fDigitsTree) 
379     {
380       LOG(AliL3Log::kError,"AliL3FileHandler::GetDigitsTree","Digits Tree")
381         <<AliL3Log::kHex<<"Error getting digitstree "<<(Int_t)fDigitsTree<<ENDLOG;
382       return kFALSE;
383     }
384   fDigitsTree->GetBranch("Segment")->SetAddress(&fDigits);
385   return kTRUE;
386 }
387
388 void AliL3FileHandler::AliDigits2RootFile(AliL3DigitRowData *rowPt,Char_t *new_digitsfile)
389 {
390   //Write the data stored in rowPt, into a new AliROOT file.
391   //The data is stored in the AliROOT format 
392   //This is specially a nice thing if you have modified data, and wants to run it  
393   //through the offline reconstruction chain.
394   //The arguments is a pointer to the data, and the name of the new AliROOT file.
395   //Remember to pass the original AliROOT file (the one that contains the original
396   //simulated data) to this object, in order to retrieve the MC id's of the digits.
397   
398   if(!fInAli)
399     {
400       printf("AliL3FileHandler::AliDigits2RootFile : No rootfile\n");
401       return;
402     }
403   if(!fParam)
404     {
405       printf("AliL3FileHandler::AliDigits2RootFile : No parameter object. Run on rootfile\n");
406       return;
407     }
408   
409   //Get the original digitstree:
410   fInAli->cd();
411   AliTPCDigitsArray *old_array = new AliTPCDigitsArray();
412   old_array->Setup(fParam);
413   old_array->SetClass("AliSimDigits");
414   Bool_t ok = old_array->ConnectTree("TreeD_75x40_100x60_0");
415   if(!ok)
416     {
417       printf("AliL3FileHandler::AliDigits2RootFile : No digits tree object\n");
418       return;
419     }
420   
421   Bool_t create=kFALSE;
422   TFile *digFile;
423   
424   digFile = TFile::Open(new_digitsfile,"NEW");
425   if(digFile->IsOpen())
426     {    
427       create = kTRUE;
428       fParam->Write(fParam->GetTitle());
429     }
430   else
431     {
432       LOG(AliL3Log::kDebug,"AliL3FileHandler::AliDigits2RootFile","Rootfile")
433         <<"Rootfile did already exist, so I will just open it for updates"<<ENDLOG;
434       digFile = TFile::Open(new_digitsfile,"UPDATE");
435       create=kFALSE;
436     }
437   if(!digFile->IsOpen())
438     {
439       LOG(AliL3Log::kError,"AliL3FileHandler::AliDigits2RootFile","Rootfile")
440         <<"Error opening rootfile "<<new_digitsfile<<ENDLOG;
441       return;
442     }
443   
444   digFile->cd();
445     
446   //setup a new one, or connect it to the existing one:
447   AliTPCDigitsArray *arr = new AliTPCDigitsArray; 
448   arr->SetClass("AliSimDigits");
449   arr->Setup(fParam);
450   if(create)
451     arr->MakeTree();
452   else
453     {
454       Bool_t ok = arr->ConnectTree("TreeD_75x40_100x60_0");
455       if(!ok)
456         {
457           printf("AliL3FileHandler::AliDigits2RootFile : No digits tree object in existing file\n");
458           return;
459         }
460     }
461   Int_t digcounter=0;
462
463   for(Int_t i=fRowMin; i<=fRowMax; i++)
464     {
465       
466       if((Int_t)rowPt->fRow != i) printf("AliL3FileHandler::AliDigits2RootFile : Mismatching row numbering!!!\n");
467             
468       Int_t sector,row;
469       AliL3Transform::Slice2Sector(fSlice,i,sector,row);
470       AliSimDigits * dig = (AliSimDigits*)arr->CreateRow(sector,row);
471       AliSimDigits *old_dig = (AliSimDigits*)old_array->LoadRow(sector,row);
472       if(!old_dig)
473         printf("AliL3FileHandler::AliDigits2RootFile : No padrow %d %d\n",sector,row);
474       
475       AliL3DigitData *digPt = rowPt->fDigitData;
476       digcounter=0;
477       for(UInt_t j=0; j<rowPt->fNDigit; j++)
478         {
479           Int_t charge = (Int_t)digPt[j].fCharge;
480           Int_t pad = (Int_t)digPt[j].fPad;
481           Int_t time = (Int_t)digPt[j].fTime;
482           
483           if(charge == 0) //Only write the digits that has not been removed
484             continue;
485           digcounter++;
486           dig->SetDigitFast(charge,time,pad);
487           
488           Int_t trackID[3] = {old_dig->GetTrackID(time,pad,0),old_dig->GetTrackID(time,pad,1),old_dig->GetTrackID(time,pad,2)};
489           Int_t s_pad = pad;
490           Int_t s_time = time - 1;
491           while(trackID[0] < 0)
492             {
493               if(s_time >= 0 && s_time < AliL3Transform::GetNTimeBins() && s_pad >= 0 && s_pad < AliL3Transform::GetNPads(i))
494                 {
495                   if(old_dig->GetTrackID(s_time,s_pad,0) > 0)
496                     {
497                       trackID[0]=old_dig->GetTrackID(s_time,s_pad,0); 
498                       trackID[1]=old_dig->GetTrackID(s_time,s_pad,1); 
499                       trackID[2]=old_dig->GetTrackID(s_time,s_pad,2); 
500                     }
501                 }
502               if(s_pad == pad && s_time == time - 1)
503                 s_time = time + 1;
504               else if(s_pad == pad && s_time == time + 1)
505                 {s_pad = pad - 1; s_time = time;}
506               else if(s_pad == pad - 1 && s_time == time)
507                 s_time = time - 1;
508               else if(s_pad == pad - 1 && s_time == time - 1)
509                 s_time = time + 1;
510               else if(s_pad == pad - 1 && s_time == time + 1)
511                 {s_pad = pad + 1; s_time = time;}
512               else if(s_pad == pad + 1 && s_time == time)
513                 s_time = time - 1;
514               else if(s_pad == pad + 1 && s_time == time - 1)
515                 s_time = time + 1;
516               else 
517                 break;
518             }
519           
520           dig->SetTrackIDFast(trackID[0],time,pad,0);
521           dig->SetTrackIDFast(trackID[1],time,pad,1);
522           dig->SetTrackIDFast(trackID[2],time,pad,2);
523           
524         }
525       //cout<<"Wrote "<<digcounter<<" on row "<<i<<endl;
526       UpdateRowPointer(rowPt);
527       arr->StoreRow(sector,row);
528       arr->ClearRow(sector,row);  
529       old_array->ClearRow(sector,row);
530     }
531   digFile->cd();
532   char treeName[100];
533   sprintf(treeName,"TreeD_%s_0",fParam->GetTitle());
534   printf("Writing tree to file.....");
535   arr->GetTree()->Write(treeName,TObject::kOverwrite);
536   printf("done\n");
537   digFile->Close();
538   //arr->GetTree()->Delete();
539   //delete arr;
540 }
541
542 ///////////////////////////////////////// Point IO  
543 Bool_t AliL3FileHandler::AliPoints2Binary(){
544   Bool_t out = kTRUE;
545   UInt_t npoint;
546   AliL3SpacePointData *data = AliPoints2Memory(npoint);
547   out = Memory2Binary(npoint,data);
548   Free();
549   return out;
550 }
551
552 AliL3SpacePointData * AliL3FileHandler::AliPoints2Memory(UInt_t & npoint){
553   AliL3SpacePointData *data = 0;
554   npoint=0;
555   if(!fInAli){
556     LOG(AliL3Log::kWarning,"AliL3FileHandler::AliPoints2Memory","File")
557     <<"No Input avalible: no object TFile"<<ENDLOG;
558     return 0;
559   }
560   if(!fInAli->IsOpen()){
561     LOG(AliL3Log::kWarning,"AliL3FileHandler::AliPoints2Memory","File")
562     <<"No Input avalible: TFile not opend"<<ENDLOG;
563     return 0;
564   }
565
566   TDirectory *savedir = gDirectory;
567   fInAli->cd();
568   
569   Char_t cname[100];
570   Int_t eventn = 0;
571   sprintf(cname,"TreeC_TPC_%d",eventn);
572   AliTPCClustersArray carray;
573   carray.Setup(fParam);
574   carray.SetClusterType("AliTPCcluster");
575   Bool_t clusterok = carray.ConnectTree(cname);
576   if(!clusterok) return 0;
577
578   AliTPCClustersRow ** clusterrow = 
579                new AliTPCClustersRow*[ (int)carray.GetTree()->GetEntries()];
580   Int_t *rows = new int[ (int)carray.GetTree()->GetEntries()];
581   Int_t *sects = new int[  (int)carray.GetTree()->GetEntries()];
582   Int_t sum=0;
583
584   Int_t lslice,lrow;
585   for(Int_t i=0; i<carray.GetTree()->GetEntries(); i++){
586     AliSegmentID *s = carray.LoadEntry(i);
587     Int_t sector,row;
588     fParam->AdjustSectorRow(s->GetID(),sector,row);
589     rows[i] = row;
590     sects[i] = sector;
591     clusterrow[i] = 0;
592     AliL3Transform::Sector2Slice(lslice,lrow,sector,row);
593     if(fSlice != lslice || lrow<fRowMin || lrow>fRowMax) continue;
594     clusterrow[i] = carray.GetRow(sector,row);
595     if(clusterrow[i])
596       sum+=clusterrow[i]->GetArray()->GetEntriesFast();
597   }
598   UInt_t size = sum*sizeof(AliL3SpacePointData);
599
600   LOG(AliL3Log::kDebug,"AliL3FileHandler::AliPoints2Memory","File")
601   <<AliL3Log::kDec<<"Found "<<sum<<" SpacePoints"<<ENDLOG;
602
603   data = (AliL3SpacePointData *) Allocate(size);
604   npoint = sum;
605   UInt_t n=0; 
606   for(Int_t i=0; i<carray.GetTree()->GetEntries(); i++){
607     if(!clusterrow[i]) continue;
608     Int_t row = rows[i];
609     Int_t sector = sects[i];
610     AliL3Transform::Sector2Slice(lslice,lrow,sector,row);
611     Int_t entries_in_row = clusterrow[i]->GetArray()->GetEntriesFast();
612     for(Int_t j = 0;j<entries_in_row;j++){
613       AliTPCcluster *c = (AliTPCcluster*)(*clusterrow[i])[j];
614       data[n].fZ = c->GetZ();
615       data[n].fY = c->GetY();
616       data[n].fX = fParam->GetPadRowRadii(sector,row);
617       data[n].fID = n+((fSlice&0x7f)<<25)+((fPatch&0x7)<<22);//uli
618       data[n].fPadRow = lrow;
619       data[n].fXYErr = c->GetSigmaY2();
620       data[n].fZErr = c->GetSigmaZ2();
621       if(fMC) fprintf(fMC,"%d %d\n",data[n].fID,c->GetLabel(0));
622       n++;
623     }
624   }
625   for(Int_t i=0;i<carray.GetTree()->GetEntries();i++){
626     Int_t row = rows[i];
627     Int_t sector = sects[i];
628     if(carray.GetRow(sector,row))
629       carray.ClearRow(sector,row);
630   }
631
632   delete [] clusterrow;
633   delete [] rows;
634   delete [] sects;
635   savedir->cd();   
636
637   return data;
638 }
639