Bug fix in MiniHeader (D.Favretto)
[u/mrichter/AliRoot.git] / TPC / AliTPCDDLRawData.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-2003, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15 /* $Id$ */
16
17
18 //This class conteins all the methods to create raw data 
19 //as par a given DDL.
20 //It produces DDL with both compressed and uncompressed format.
21 //For compression we use the optimized table wich needs 
22 //to be provided.
23
24
25 #include "TObjArray.h"
26 #include "Riostream.h"
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include "AliTPCCompression.h"
30 #include "AliTPCBuffer160.h"
31 #include "AliTPCDDLRawData.h"
32
33 ClassImp(AliTPCDDLRawData)
34 ////////////////////////////////////////////////////////////////////////////////////////
35
36 AliTPCDDLRawData::AliTPCDDLRawData(const AliTPCDDLRawData &source){
37   // Copy Constructor
38   return;
39 }
40
41 AliTPCDDLRawData& AliTPCDDLRawData::operator=(const AliTPCDDLRawData &source){
42   //Assigment operator
43   return *this;
44 }
45
46
47 ////////////////////////////////////////////////////////////////////////////
48 void AliTPCDDLRawData::RawData(Int_t LDCsNumber){
49   //Raw data slides generation
50   //Number of DDL=2*36+4*36=216
51   //2 DDL for each inner sector
52   //4 DDL for each outer sector
53   Int_t ddlPerFile=216/LDCsNumber;
54   Int_t offset=1;
55   if (216%LDCsNumber) ddlPerFile++;
56   cout<<"Number of DDL per slide: "<<ddlPerFile<<endl;
57   ifstream f;
58 #ifndef __DECCXX
59   f.open("AliTPCDDL.dat",ios::binary);
60 #else
61   f.open("AliTPCDDL.dat");
62 #endif
63   if(!f){cout<<"File doesn't exist !!"<<endl;return;}
64   struct DataPad{
65     Int_t Sec;
66     Int_t SubSec;
67     Int_t Row;
68     Int_t Pad;
69     Int_t Dig;
70     Int_t Time;
71   };
72   DataPad data;
73
74   //AliTPCBuffer160 is used in write mode to generate AltroFormat.dat file
75   Int_t sliceNumber=1;
76   char  filename[15];
77   sprintf(filename,"TPCslice%d",sliceNumber); 
78   cout<<"   Creating "<<filename<<endl;
79   AliTPCBuffer160 *buffer=new AliTPCBuffer160(filename,1);
80
81   ULong_t count=0;
82   Int_t pSecNumber=-1;  //Previous Sector number
83   Int_t pRowNumber=-1;  //Previous Row number  
84   Int_t pPadNumber=-1;  //Previous Pad number
85   Int_t pTimeBin=-1;    //Previous Time-Bin
86   Int_t pSubSector=-1;  //Previous Sub Sector
87   Int_t bunchLength=0;
88   Int_t countDDL=0;
89   Int_t nwords=0;
90   ULong_t numPackets=0;
91   while (f.read((char*)(&data),sizeof(data))){
92     count++;
93     if (pPadNumber==-1){
94       pSecNumber=data.Sec;
95       pRowNumber=data.Row;
96       pPadNumber=data.Pad;
97       pTimeBin=data.Time;
98       pSubSector=data.SubSec;
99       //size magic word sector number sub-sector number 0 for TPC 0 for uncompressed
100       buffer->WriteMiniHeader(0,pSecNumber,pSubSector,0,0);//Dummy;
101       bunchLength=1;
102       buffer->FillBuffer(data.Dig-offset);
103       nwords++;
104     }//end if
105     else{
106       if ( (data.Time==(pTimeBin+1)) &&
107            (pPadNumber==data.Pad) &&
108            (pRowNumber==data.Row) &&
109            (pSecNumber==data.Sec)){
110         bunchLength++;
111       }//end if
112       else{
113         buffer->FillBuffer(pTimeBin);
114         buffer->FillBuffer(bunchLength+2);
115         nwords+=2;
116         if ((pPadNumber!=data.Pad)||(pRowNumber!=data.Row)||(pSecNumber!=data.Sec)){
117           //Trailer is formatted and inserted!!
118           buffer->WriteTrailer(nwords,pPadNumber,pRowNumber,pSecNumber);
119           numPackets++;
120           nwords=0;
121
122           if(pSubSector!=data.SubSec){
123             countDDL++;
124             if(countDDL==ddlPerFile){
125               //size magic word sector number sub-sector number 0 for TPC 0 for uncompressed
126               buffer->Flush();
127               buffer->WriteMiniHeader(1,pSecNumber,pSubSector,0,0);
128               //cout<<"Mini header for DDL:"<<PSecNumber<<" Sub-sec:"<<PSubSector<<endl;
129               delete buffer;
130               sliceNumber++;
131               sprintf(filename,"TPCslice%d",sliceNumber);
132               cout<<"   Creating "<<filename<<endl;
133               buffer=new AliTPCBuffer160(filename,1);
134               buffer->WriteMiniHeader(0,data.Sec,data.SubSec,0,0);//Dummy;
135               countDDL=0;
136             }//end if
137             else{
138               buffer->Flush();
139               buffer->WriteMiniHeader(1,pSecNumber,pSubSector,0,0);
140               buffer->WriteMiniHeader(0,data.Sec,data.SubSec,0,0);//Dummy;
141             }
142             pSubSector=data.SubSec;
143           }//end if
144         }//end if
145         
146         bunchLength=1;
147         pPadNumber=data.Pad;
148         pRowNumber=data.Row;
149         pSecNumber=data.Sec;
150       }//end else
151       pTimeBin=data.Time;
152       buffer->FillBuffer(data.Dig-offset);
153       nwords++;
154     }//end else
155   }//end while
156   buffer->FillBuffer(pTimeBin);
157   buffer->FillBuffer(bunchLength+2);
158   nwords+=2;
159   buffer->WriteTrailer(nwords,pPadNumber,pRowNumber,pSecNumber);
160   //write the  M.H.
161   buffer->Flush();
162   buffer->WriteMiniHeader(1,pSecNumber,pSubSector,0,0);
163   //cout<<"Mini header for D D L:"<<pSecNumber<<" Sub-sec:"<<pSubSector<<endl;
164   delete buffer;
165   cout<<"Number of digits: "<<count<<endl;
166   f.close();
167   return;
168 }
169 ////////////////////////////////////////////////////////////////////////////
170 ////////////////////////////////////////////////////////////////////////////
171
172
173 Int_t AliTPCDDLRawData::RawDataCompDecompress(Int_t LDCsNumber,Int_t Comp){
174   //This method is used to compress and decompress the slides
175   static const Int_t kNumTables=5;
176   char filename[20];
177   char dest[20];
178   fstream f;
179   ULong_t size=0;
180   //Int_t MagicWord,DDLNumber,SecNumber,SubSector,Detector;
181   Int_t flag=0;
182   for(Int_t i=1;i<=LDCsNumber;i++){
183     if(!Comp){
184       sprintf(filename,"TPCslice%d",i);
185       sprintf(dest,"TPCslice%d.comp",i);
186     }
187     else{
188       sprintf(filename,"TPCslice%d.comp",i);
189       sprintf(dest,"TPCslice%d.decomp",i);
190     }
191 #ifndef __DECCXX
192     f.open(filename,ios::binary|ios::in);
193 #else
194     f.open(filename,ios::in);
195 #endif
196     if(!f){cout<<"File doesn't exist \n";exit(1);}
197     cout<<filename<<"  "<<dest<<endl;
198     ofstream fdest;
199 #ifndef __DECCXX
200     fdest.open(dest,ios::binary);
201 #else
202     fdest.open(dest);
203 #endif
204     //loop over the DDL block 
205     //Each block contains a Mini Header followed by raw data (ALTRO FORMAT)
206     //The number of block is ceil(216/LDCsNumber)
207     ULong_t miniHeader[3];
208     //here the Mini Header is read
209     while( (f.read((char*)(miniHeader),sizeof(ULong_t)*3)) ){
210       size=miniHeader[0];
211       //Int_t dim=sizeof(ULong_t)+sizeof(Int_t)*5;
212       //cout<<" Sec "<<SecNumber<<" SubSector "<<SubSector<<" size "<<size<<endl;
213       //open the temporay File
214       ofstream fo;
215       char temp[15]="TempFile";
216 #ifndef __DECCXX
217       fo.open(temp,ios::binary);
218 #else
219       fo.open(temp);
220 #endif
221       Int_t car=0;
222       for(ULong_t j=0;j<size;j++){
223         f.read((char*)(&car),1);
224         fo.write((char*)(&car),1);
225       }//end for
226       fo.close();
227       //The temp file is compressed or decompressed
228       AliTPCCompression *util = new AliTPCCompression();
229       //      util->SetVerbose(1);
230       if(!Comp)
231         util->CompressDataOptTables(kNumTables,temp,"TempCompDecomp");
232       else
233         util->DecompressDataOptTables(kNumTables,temp,"TempCompDecomp");
234       delete util;
235       //the temp compressed file is open and copied to the final file fdest
236       ifstream fi;
237 #ifndef __DECCXX
238       fi.open("TempCompDecomp",ios::binary);
239 #else
240       fi.open("TempCompDecomp");
241 #endif
242       fi.seekg(0,ios::end);
243       size=fi.tellg();
244       fi.seekg(0);
245       //The Mini Header is updated (size and Compressed flag) 
246       //and written into the output file
247       miniHeader[0]=size;
248       if(!Comp)
249         flag=1;
250       else
251         flag=0;
252       ULong_t aux=0x0;
253       flag<<=8;
254       aux|=flag;
255       miniHeader[2]=miniHeader[2]|aux;
256       fdest.write((char*)(miniHeader),sizeof(ULong_t)*3);
257       //The compressem temp file is copied into the output file fdest
258       for(ULong_t j=0;j<size;j++){
259         fi.read((char*)(&car),1);
260         fdest.write((char*)(&car),1);
261       }//end for
262       fi.close();
263     }//end while
264     f.clear();
265     f.close();
266     fdest.close();
267     remove("TempFile");
268     remove("TempCompDecomp");
269   }//end for
270   return 0;
271 }
272
273 /////////////////////////////////////////////////////////////////////////////////
274 void AliTPCDDLRawData::RawDataAltro()const{
275   //This method is used to build the Altro format from AliTPCDDL.dat
276   //It is used to debug the code and create the tables used in the compresseion phase
277   Int_t offset=1;
278   ifstream f;
279 #ifndef __DECCXX
280   f.open("AliTPCDDL.dat",ios::binary);
281 #else
282   f.open("AliTPCDDL.dat");
283 #endif
284   if(!f){cout<<"File doesn't exist !!"<<endl;return;}
285   struct DataPad{
286     Int_t Sec;
287     Int_t SubSec;
288     Int_t Row;
289     Int_t Pad;
290     Int_t Dig;
291     Int_t Time;
292   };
293   DataPad data;
294
295   //AliTPCBuffer160 is used in write mode to generate AltroFormat.dat file
296   char  filename[30]="AltroFormatDDL.dat";
297   cout<<"   Creating "<<filename<<endl;
298   AliTPCBuffer160 *buffer=new AliTPCBuffer160(filename,1);
299
300   ULong_t count=0;
301   Int_t pSecNumber=-1;  //Previous Sector number
302   Int_t pRowNumber=-1;  //Previous Row number  
303   Int_t pPadNumber=-1;  //Previous Pad number
304   Int_t pTimeBin=-1;    //Previous Time-Bin
305   Int_t bunchLength=0;
306   Int_t nwords=0;
307   ULong_t numPackets=0;
308   while (f.read((char*)(&data),sizeof(data))){
309     count++;
310     if (pPadNumber==-1){
311       pSecNumber=data.Sec;
312       pRowNumber=data.Row;
313       pPadNumber=data.Pad;
314       pTimeBin=data.Time;
315       bunchLength=1;
316       buffer->FillBuffer(data.Dig-offset);
317       nwords++;
318     }//end if
319     else{
320       if ( (data.Time==(pTimeBin+1)) &&
321            (pPadNumber==data.Pad) &&
322            (pRowNumber==data.Row) &&
323            (pSecNumber==data.Sec)){
324         bunchLength++;
325       }//end if
326       else{
327         buffer->FillBuffer(pTimeBin);
328         buffer->FillBuffer(bunchLength+2);
329         nwords+=2;
330         if ((pPadNumber!=data.Pad)||(pRowNumber!=data.Row)||(pSecNumber!=data.Sec)){
331           //Trailer is formatted and inserted!!
332           buffer->WriteTrailer(nwords,pPadNumber,pRowNumber,pSecNumber);
333           numPackets++;
334           nwords=0;
335         }//end if
336         
337         bunchLength=1;
338         pPadNumber=data.Pad;
339         pRowNumber=data.Row;
340         pSecNumber=data.Sec;
341       }//end else
342       pTimeBin=data.Time;
343       buffer->FillBuffer(data.Dig-offset);
344       nwords++;
345     }//end else
346   }//end while
347   buffer->FillBuffer(pTimeBin);
348   buffer->FillBuffer(bunchLength+2);
349   nwords+=2;
350   buffer->WriteTrailer(nwords,pPadNumber,pRowNumber,pSecNumber);
351   delete buffer;
352   cout<<"Number of digits: "<<count<<endl;
353   f.close(); 
354   return;
355 }
356
357 /////////////////////////////////////////////////////////////////////////
358 void AliTPCDDLRawData::RawDataAltroDecode(Int_t LDCsNumber,Int_t Comp){
359   //This method merges the slides in only one file removing at the same 
360   //time all the mini headers. The file so obtained must be Altro format
361   //complaiant.
362   //It is used mainly in the debugging phase 
363   char filename[15];
364   char dest[30];
365   fstream f;
366   if(!Comp)
367     sprintf(dest,"AltroDDLRecomposed.dat");
368   else
369     sprintf(dest,"AltroDDLRecomposedDec.dat");
370   ofstream fdest;
371
372 #ifndef __DECCXX
373   fdest.open(dest,ios::binary);
374 #else
375   fdest.open(dest);
376 #endif
377   ULong_t size=0;
378   //Int_t MagicWord,DDLNumber,SecNumber,SubSector,Detector,flag=0;
379   for(Int_t i=1;i<=LDCsNumber;i++){
380     if(!Comp)
381       sprintf(filename,"TPCslice%d",i);  
382     else
383       sprintf(filename,"TPCslice%d.decomp",i);  
384 #ifndef __DECCXX
385     f.open(filename,ios::binary|ios::in);
386 #else
387     f.open(filename,ios::in);
388 #endif
389     if(!f){cout<<"The file doesn't exist"<<endl;exit(1);}
390     //loop over the DDL block 
391     //Each block contains a Mini Header followed by raw data (ALTRO FORMAT)
392     //The number of block is ceil(216/LDCsNumber)
393     ULong_t miniHeader[3];
394     //here the Mini Header is read
395     while( (f.read((char*)(miniHeader),sizeof(ULong_t)*3)) ){
396       //cout<<"Mini header dimension "<<miniHeader[0]<<endl;
397       Int_t car=0;
398       size=miniHeader[0];
399       for(ULong_t j=0;j<size;j++){
400         f.read((char*)(&car),1);
401         fdest.write((char*)(&car),1);
402       }//end for
403     }//end while
404     f.clear();
405     f.close();
406   }//end for
407   fdest.close();
408   return;
409 }
410