1b0633478f8540d60330943e4f2cf252c56096df
[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 #include <TObjArray.h>
25 #include <Riostream.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include "AliTPCCompression.h"
29 #include "AliTPCBuffer160.h"
30 #include "AliTPCDDLRawData.h"
31 #include "AliRawDataHeader.h"
32
33 ClassImp(AliTPCDDLRawData)
34 ////////////////////////////////////////////////////////////////////////////////////////
35
36 AliTPCDDLRawData::AliTPCDDLRawData(const AliTPCDDLRawData &source):
37   TObject(source)
38 {
39   // Copy Constructor
40   fVerbose=source.fVerbose;
41   return;
42 }
43
44 AliTPCDDLRawData& AliTPCDDLRawData::operator=(const AliTPCDDLRawData &source){
45   //Assigment operator
46   fVerbose=source.fVerbose;
47   return *this;
48 }
49
50
51 ////////////////////////////////////////////////////////////////////////////
52 void AliTPCDDLRawData::RawData(const char* inputFileName){
53   //Raw data generation
54   //Number of DDL=2*36+4*36=216
55   //2 DDL for each inner sector
56   //4 DDL for each outer sector
57   Int_t offset=1;
58   ifstream f;
59 #ifndef __DECCXX
60   f.open(inputFileName,ios::binary);
61 #else
62   f.open(inputFileName);
63 #endif
64   if(!f){Error("RawData", "File doesn't exist !!");return;}
65   struct DataPad{
66     Int_t Sec;
67     Int_t SubSec;
68     Int_t Row;
69     Int_t Pad;
70     Int_t Dig;
71     Int_t Time;
72   };
73   DataPad data;
74
75   //AliTPCBuffer160 is used in write mode to generate raw data file
76   char  filename[15];
77   Int_t ddlNumber=0;
78   AliTPCBuffer160 *buffer=NULL;
79   Int_t pSecNumber=-1;  //Previous Sector number
80   Int_t pRowNumber=-1;  //Previous Row number  
81   Int_t pPadNumber=-1;  //Previous Pad number
82   Int_t pTimeBin=-1;    //Previous Time-Bin
83   Int_t pSubSector=-1;  //Previous Sub Sector
84   Int_t bunchLength=0;
85   Int_t nwords=0;
86   UInt_t numPackets=0;
87
88   while (f.read((char*)(&data),sizeof(data))){
89     if (pPadNumber==-1){
90       pSecNumber=data.Sec;
91       pRowNumber=data.Row;
92       pPadNumber=data.Pad;
93       pTimeBin=data.Time;
94       pSubSector=data.SubSec;
95
96       if(data.Sec<36)
97         ddlNumber=data.Sec*2+data.SubSec;
98       else
99         ddlNumber=72+(data.Sec-36)*4+data.SubSec;
100       sprintf(filename,"TPC_%d.ddl",ddlNumber+kDDLOffset); 
101       buffer=new AliTPCBuffer160(filename,1);
102       //size magic word sector number sub-sector number 0 for TPC 0 for uncompressed
103       buffer->WriteDataHeader(kTRUE,kFALSE);//Dummy;
104       bunchLength=1;
105       buffer->FillBuffer(data.Dig-offset);
106       nwords++;
107     }//end if
108     else{
109       if ( (data.Time==(pTimeBin+1)) &&
110            (pPadNumber==data.Pad) &&
111            (pRowNumber==data.Row) &&
112            (pSecNumber==data.Sec)){
113         bunchLength++;
114       }//end if
115       else{
116         buffer->FillBuffer(pTimeBin);
117         buffer->FillBuffer(bunchLength+2);
118         nwords+=2;
119         if ((pPadNumber!=data.Pad)||(pRowNumber!=data.Row)||(pSecNumber!=data.Sec)){
120           //Trailer is formatted and inserted!!
121           buffer->WriteTrailer(nwords,pPadNumber,pRowNumber,pSecNumber);
122           numPackets++;
123           nwords=0;
124
125           if(pSubSector!=data.SubSec){
126             //size magic word sector number sub-sector number 0 for TPC 0 for uncompressed
127             buffer->Flush();
128             buffer->WriteDataHeader(kFALSE,kFALSE);
129             //cout<<"Data header for DDL:"<<PSecNumber<<" Sub-sec:"<<PSubSector<<endl;
130             delete buffer;
131
132             if(data.Sec<36)
133               ddlNumber=data.Sec*2+data.SubSec;
134             else
135               ddlNumber=72+(data.Sec-36)*4+data.SubSec;
136             sprintf(filename,"TPC_%d.ddl",ddlNumber+kDDLOffset); 
137             buffer=new AliTPCBuffer160(filename,1);
138             buffer->WriteDataHeader(kTRUE,kFALSE);//Dummy;
139             pSubSector=data.SubSec;
140           }//end if
141         }//end if
142         
143         bunchLength=1;
144         pPadNumber=data.Pad;
145         pRowNumber=data.Row;
146         pSecNumber=data.Sec;
147       }//end else
148       pTimeBin=data.Time;
149       buffer->FillBuffer(data.Dig-offset);
150       nwords++;
151     }//end else
152   }//end while
153   if (buffer) {
154     buffer->FillBuffer(pTimeBin);
155     buffer->FillBuffer(bunchLength+2);
156     nwords+=2;
157     buffer->WriteTrailer(nwords,pPadNumber,pRowNumber,pSecNumber);
158     //write the  D.H.
159     buffer->Flush();
160     buffer->WriteDataHeader(kFALSE,kFALSE);
161     //cout<<"Data header for D D L:"<<pSecNumber<<" Sub-sec:"<<pSubSector<<endl;
162     delete buffer;
163   }
164   f.close();
165   return;
166 }
167 ////////////////////////////////////////////////////////////////////////////
168 ////////////////////////////////////////////////////////////////////////////
169
170
171 Int_t AliTPCDDLRawData::RawDataCompDecompress(Bool_t compress){
172   //This method is used to compress and decompress the slides
173   static const Int_t kNumTables=5;
174   char filename[20];
175   fstream f;
176   UInt_t size=0;
177   AliTPCCompression util;
178   util.SetVerbose(0);
179
180   for(Int_t i=0;i<216;i++){
181     sprintf(filename,"TPC_%d.ddl",i+kDDLOffset);
182 #ifndef __DECCXX
183     f.open(filename,ios::binary|ios::in);
184 #else
185     f.open(filename,ios::in);
186 #endif
187     if(!f.is_open()){f.clear(); continue;}
188     if (fVerbose)
189       Info("RawDataCompDecompress", "&s -> dest.ddl", filename);
190     ofstream fdest;
191 #ifndef __DECCXX
192     fdest.open("dest.ddl",ios::binary);
193 #else
194     fdest.open("dest.ddl");
195 #endif
196     //loop over the DDL block 
197     //Each block contains a Data Header followed by raw data (ALTRO FORMAT)
198     //The number of block is ceil(216/LDCsNumber)
199     AliRawDataHeader header;
200     //here the Data Header is read
201     while( f.read((char*)(&header),sizeof(header)) ){
202       size=header.fSize-sizeof(header);
203       // cout<<"Data size:"<<size<<endl;
204       //Int_t dim=sizeof(UInt_t)+sizeof(Int_t)*5;
205       //cout<<" Sec "<<SecNumber<<" SubSector "<<SubSector<<" size "<<size<<endl;
206       Bool_t compressed = header.TestAttribute(1);
207       if ((compressed && compress) ||
208           (!compressed && !compress)) continue;
209       //open the temporay File
210       ofstream fo;
211       char temp[15]="TempFile";
212 #ifndef __DECCXX
213       fo.open(temp,ios::binary);
214 #else
215       fo.open(temp);
216 #endif
217       Int_t car=0;
218       for(UInt_t j=0;j<size;j++){
219         f.read((char*)(&car),1);
220         fo.write((char*)(&car),1);
221       }//end for
222       fo.close();
223       //The temp file is compressed or decompressed
224       Int_t result=0;
225       if(compress){
226         result=util.CompressDataOptTables(kNumTables,temp,"TempCompDecomp");
227       }
228       else
229         result=util.DecompressDataOptTables(kNumTables,temp,"TempCompDecomp");
230       if (result != 0) break;
231       //the temp compressed file is open and copied to the final file fdest
232       ifstream fi;
233 #ifndef __DECCXX
234       fi.open("TempCompDecomp",ios::binary);
235 #else
236       fi.open("TempCompDecomp");
237 #endif
238       fi.seekg(0,ios::end);
239       size=fi.tellg();
240       fi.seekg(0);
241       //The Data Header is updated (size and Compressed flag) 
242       //and written into the output file
243       header.fSize=size+sizeof(header);
244       if (compress) header.SetAttribute(1);
245       else header.ResetAttribute(1);
246       fdest.write((char*)(&header),sizeof(header));
247       //The compressem temp file is copied into the output file fdest
248       for(UInt_t j=0;j<size;j++){
249         fi.read((char*)(&car),1);
250         fdest.write((char*)(&car),1);
251       }//end for
252       fi.close();
253     }//end while
254     f.clear();
255     f.close();
256     fdest.close();
257     remove("TempFile");
258     remove("TempCompDecomp");
259     rename("dest.ddl",filename);
260   }//end for
261   return 0;
262 }
263
264 /////////////////////////////////////////////////////////////////////////////////
265 void AliTPCDDLRawData::RawDataAltro(const char* inputFileName, const char* outputFileName)const{
266   //This method is used to build the Altro format from AliTPCDDL.dat
267   //It is used to debug the code and creates the tables used in the compresseion phase
268   Int_t offset=1;
269   ifstream f;
270 #ifndef __DECCXX
271   f.open(inputFileName,ios::binary);
272 #else
273   f.open(inputFileName);
274 #endif
275   if(!f){
276     Error("RawDataAltro", "File doesn't exist !!");
277     return;
278   }
279   struct DataPad{
280     Int_t Sec;
281     Int_t SubSec;
282     Int_t Row;
283     Int_t Pad;
284     Int_t Dig;
285     Int_t Time;
286   };
287   DataPad data;
288
289   //AliTPCBuffer160 is used in write mode to generate AltroFormat.dat file
290   Info("RawDataAltro", "Creating &s", outputFileName);
291   AliTPCBuffer160 *buffer=new AliTPCBuffer160(outputFileName,1);
292
293   UInt_t count=0;
294   Int_t pSecNumber=-1;  //Previous Sector number
295   Int_t pRowNumber=-1;  //Previous Row number  
296   Int_t pPadNumber=-1;  //Previous Pad number
297   Int_t pTimeBin=-1;    //Previous Time-Bin
298   Int_t bunchLength=0;
299   Int_t nwords=0;
300   UInt_t numPackets=0;
301   while (f.read((char*)(&data),sizeof(data))){
302     count++;
303     if (pPadNumber==-1){
304       pSecNumber=data.Sec;
305       pRowNumber=data.Row;
306       pPadNumber=data.Pad;
307       pTimeBin=data.Time;
308       bunchLength=1;
309       buffer->FillBuffer(data.Dig-offset);
310       nwords++;
311     }//end if
312     else{
313       if ( (data.Time==(pTimeBin+1)) &&
314            (pPadNumber==data.Pad) &&
315            (pRowNumber==data.Row) &&
316            (pSecNumber==data.Sec)){
317         bunchLength++;
318       }//end if
319       else{
320         buffer->FillBuffer(pTimeBin);
321         buffer->FillBuffer(bunchLength+2);
322         nwords+=2;
323         if ((pPadNumber!=data.Pad)||(pRowNumber!=data.Row)||(pSecNumber!=data.Sec)){
324           //Trailer is formatted and inserted!!
325           buffer->WriteTrailer(nwords,pPadNumber,pRowNumber,pSecNumber);
326           numPackets++;
327           nwords=0;
328         }//end if
329         
330         bunchLength=1;
331         pPadNumber=data.Pad;
332         pRowNumber=data.Row;
333         pSecNumber=data.Sec;
334       }//end else
335       pTimeBin=data.Time;
336       buffer->FillBuffer(data.Dig-offset);
337       nwords++;
338     }//end else
339   }//end while
340   buffer->FillBuffer(pTimeBin);
341   buffer->FillBuffer(bunchLength+2);
342   nwords+=2;
343   buffer->WriteTrailer(nwords,pPadNumber,pRowNumber,pSecNumber);
344   delete buffer;
345   Info("RawDataAltro", "Number of digits: %d", count);
346   f.close(); 
347   return;
348 }
349
350 /////////////////////////////////////////////////////////////////////////
351 void AliTPCDDLRawData::RawDataAltroDecode(const char* outputFileName){
352   //This method merges the slides in only one file removing at the same 
353   //time all the data headers. The file so obtained must be Altro format
354   //complaiant.
355   //It is used mainly in the debugging phase 
356   char filename[15];
357   fstream f;
358   ofstream fdest;
359
360 #ifndef __DECCXX
361   fdest.open(outputFileName,ios::binary);
362 #else
363   fdest.open(outputFileName);
364 #endif
365   UInt_t size=0;
366   AliRawDataHeader header;
367   for(Int_t i=0;i<216;i++){
368     sprintf(filename,"TPC_%d.ddl",i+kDDLOffset);
369 #ifndef __DECCXX
370     f.open(filename,ios::binary|ios::in);
371 #else
372     f.open(filename,ios::in);
373 #endif
374     if(!f)continue;
375     //loop over the DDL block 
376     //Each block contains a Data Header followed by raw data (ALTRO FORMAT)
377     while( (f.read((char*)(&header),sizeof(header))) ){
378       Int_t car=0;
379       size=header.fSize-sizeof(header);
380       for(UInt_t j=0;j<size;j++){
381         f.read((char*)(&car),1);
382         fdest.write((char*)(&car),1);
383       }//end for
384     }//end while
385     f.clear();
386     f.close();
387   }//end for
388   fdest.close();
389   return;
390 }
391