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