1 /**************************************************************************
2 * Copyright(c) 1998-2003, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
18 //This class conteins all the methods to create raw data
20 //It produces DDL with both compressed and uncompressed format.
21 //For compression we use the optimized table wich needs
24 #include <TObjArray.h>
25 #include <Riostream.h>
28 #include "AliTPCCompression.h"
29 #include "AliTPCBuffer160.h"
30 #include "AliTPCDDLRawData.h"
32 ClassImp(AliTPCDDLRawData)
33 ////////////////////////////////////////////////////////////////////////////////////////
35 AliTPCDDLRawData::AliTPCDDLRawData(const AliTPCDDLRawData &source):
39 fVerbose=source.fVerbose;
43 AliTPCDDLRawData& AliTPCDDLRawData::operator=(const AliTPCDDLRawData &source){
45 fVerbose=source.fVerbose;
50 ////////////////////////////////////////////////////////////////////////////
51 void AliTPCDDLRawData::RawData(Int_t LDCsNumber,Int_t EventNumber){
52 //Raw data slides generation
53 //Number of DDL=2*36+4*36=216
54 //2 DDL for each inner sector
55 //4 DDL for each outer sector
56 Int_t ddlPerFile=216/LDCsNumber;
58 if (216%LDCsNumber) ddlPerFile++;
59 cout<<"Number of DDL per slide: "<<ddlPerFile<<endl;
62 f.open("AliTPCDDL.dat",ios::binary);
64 f.open("AliTPCDDL.dat");
66 if(!f){cout<<"File doesn't exist !!"<<endl;return;}
77 //AliTPCBuffer160 is used in write mode to generate AltroFormat.dat file
80 sprintf(filename,"Ev%dTPCslice%d",EventNumber,sliceNumber);
81 cout<<" Creating "<<filename<<endl;
82 AliTPCBuffer160 *buffer=new AliTPCBuffer160(filename,1);
85 Int_t pSecNumber=-1; //Previous Sector number
86 Int_t pRowNumber=-1; //Previous Row number
87 Int_t pPadNumber=-1; //Previous Pad number
88 Int_t pTimeBin=-1; //Previous Time-Bin
89 Int_t pSubSector=-1; //Previous Sub Sector
94 while (f.read((char*)(&data),sizeof(data))){
101 pSubSector=data.SubSec;
102 //size magic word sector number sub-sector number 0 for TPC 0 for uncompressed
103 buffer->WriteMiniHeader(0,pSecNumber,pSubSector,0,0);//Dummy;
105 buffer->FillBuffer(data.Dig-offset);
109 if ( (data.Time==(pTimeBin+1)) &&
110 (pPadNumber==data.Pad) &&
111 (pRowNumber==data.Row) &&
112 (pSecNumber==data.Sec)){
116 buffer->FillBuffer(pTimeBin);
117 buffer->FillBuffer(bunchLength+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);
125 if(pSubSector!=data.SubSec){
127 if(countDDL==ddlPerFile){
128 //size magic word sector number sub-sector number 0 for TPC 0 for uncompressed
130 buffer->WriteMiniHeader(1,pSecNumber,pSubSector,0,0);
131 //cout<<"Mini header for DDL:"<<PSecNumber<<" Sub-sec:"<<PSubSector<<endl;
134 sprintf(filename,"Ev%dTPCslice%d",EventNumber,sliceNumber);
135 cout<<" Creating "<<filename<<endl;
136 buffer=new AliTPCBuffer160(filename,1);
137 buffer->WriteMiniHeader(0,data.Sec,data.SubSec,0,0);//Dummy;
142 buffer->WriteMiniHeader(1,pSecNumber,pSubSector,0,0);
143 buffer->WriteMiniHeader(0,data.Sec,data.SubSec,0,0);//Dummy;
145 pSubSector=data.SubSec;
155 buffer->FillBuffer(data.Dig-offset);
159 buffer->FillBuffer(pTimeBin);
160 buffer->FillBuffer(bunchLength+2);
162 buffer->WriteTrailer(nwords,pPadNumber,pRowNumber,pSecNumber);
165 buffer->WriteMiniHeader(1,pSecNumber,pSubSector,0,0);
166 //cout<<"Mini header for D D L:"<<pSecNumber<<" Sub-sec:"<<pSubSector<<endl;
168 cout<<"Number of digits: "<<count<<endl;
172 ////////////////////////////////////////////////////////////////////////////
173 ////////////////////////////////////////////////////////////////////////////
176 Int_t AliTPCDDLRawData::RawDataCompDecompress(Int_t LDCsNumber,Int_t EventNumber,Int_t Comp){
177 //This method is used to compress and decompress the slides
178 static const Int_t kNumTables=5;
183 //Int_t MagicWord,DDLNumber,SecNumber,SubSector,Detector;
185 for(Int_t i=1;i<=LDCsNumber;i++){
187 sprintf(filename,"Ev%dTPCslice%d",EventNumber,i);
188 sprintf(dest,"Ev%dTPCslice%d.comp",EventNumber,i);
191 sprintf(filename,"Ev%dTPCslice%d.comp",EventNumber,i);
192 sprintf(dest,"Ev%dTPCslice%d.decomp",EventNumber,i);
195 f.open(filename,ios::binary|ios::in);
197 f.open(filename,ios::in);
199 if(!f){cout<<"BE CAREFUL!! There isn't enough data to generate "<<LDCsNumber<<" slices"<<endl;break;}
201 cout<<filename<<" "<<dest<<endl;
204 fdest.open(dest,ios::binary);
208 //loop over the DDL block
209 //Each block contains a Mini Header followed by raw data (ALTRO FORMAT)
210 //The number of block is ceil(216/LDCsNumber)
211 UInt_t miniHeader[3];
212 //here the Mini Header is read
213 while( (f.read((char*)(miniHeader),sizeof(UInt_t)*3)) ){
215 // cout<<"Data size:"<<size<<endl;
216 //Int_t dim=sizeof(UInt_t)+sizeof(Int_t)*5;
217 //cout<<" Sec "<<SecNumber<<" SubSector "<<SubSector<<" size "<<size<<endl;
218 //open the temporay File
220 char temp[15]="TempFile";
222 fo.open(temp,ios::binary);
227 for(UInt_t j=0;j<size;j++){
228 f.read((char*)(&car),1);
229 fo.write((char*)(&car),1);
232 //The temp file is compressed or decompressed
233 AliTPCCompression *util = new AliTPCCompression();
236 util->CompressDataOptTables(kNumTables,temp,"TempCompDecomp");
239 util->DecompressDataOptTables(kNumTables,temp,"TempCompDecomp");
241 //the temp compressed file is open and copied to the final file fdest
244 fi.open("TempCompDecomp",ios::binary);
246 fi.open("TempCompDecomp");
248 fi.seekg(0,ios::end);
251 //The Mini Header is updated (size and Compressed flag)
252 //and written into the output file
261 miniHeader[2]=miniHeader[2]|aux;
262 fdest.write((char*)(miniHeader),sizeof(UInt_t)*3);
263 //The compressem temp file is copied into the output file fdest
264 for(UInt_t j=0;j<size;j++){
265 fi.read((char*)(&car),1);
266 fdest.write((char*)(&car),1);
274 remove("TempCompDecomp");
279 /////////////////////////////////////////////////////////////////////////////////
280 void AliTPCDDLRawData::RawDataAltro()const{
281 //This method is used to build the Altro format from AliTPCDDL.dat
282 //It is used to debug the code and creates the tables used in the compresseion phase
286 f.open("AliTPCDDL.dat",ios::binary);
288 f.open("AliTPCDDL.dat");
290 if(!f){cout<<"File doesn't exist !!"<<endl;return;}
301 //AliTPCBuffer160 is used in write mode to generate AltroFormat.dat file
302 char filename[30]="AltroFormatDDL.dat";
303 cout<<" Creating "<<filename<<endl;
304 AliTPCBuffer160 *buffer=new AliTPCBuffer160(filename,1);
307 Int_t pSecNumber=-1; //Previous Sector number
308 Int_t pRowNumber=-1; //Previous Row number
309 Int_t pPadNumber=-1; //Previous Pad number
310 Int_t pTimeBin=-1; //Previous Time-Bin
314 while (f.read((char*)(&data),sizeof(data))){
322 buffer->FillBuffer(data.Dig-offset);
326 if ( (data.Time==(pTimeBin+1)) &&
327 (pPadNumber==data.Pad) &&
328 (pRowNumber==data.Row) &&
329 (pSecNumber==data.Sec)){
333 buffer->FillBuffer(pTimeBin);
334 buffer->FillBuffer(bunchLength+2);
336 if ((pPadNumber!=data.Pad)||(pRowNumber!=data.Row)||(pSecNumber!=data.Sec)){
337 //Trailer is formatted and inserted!!
338 buffer->WriteTrailer(nwords,pPadNumber,pRowNumber,pSecNumber);
349 buffer->FillBuffer(data.Dig-offset);
353 buffer->FillBuffer(pTimeBin);
354 buffer->FillBuffer(bunchLength+2);
356 buffer->WriteTrailer(nwords,pPadNumber,pRowNumber,pSecNumber);
358 cout<<"Number of digits: "<<count<<endl;
363 /////////////////////////////////////////////////////////////////////////
364 void AliTPCDDLRawData::RawDataAltroDecode(Int_t LDCsNumber,Int_t EventNumber,Int_t Comp){
365 //This method merges the slides in only one file removing at the same
366 //time all the mini headers. The file so obtained must be Altro format
368 //It is used mainly in the debugging phase
373 sprintf(dest,"AltroDDLRecomposed.dat");
375 sprintf(dest,"AltroDDLRecomposedDec.dat");
379 fdest.open(dest,ios::binary);
384 //Int_t MagicWord,DDLNumber,SecNumber,SubSector,Detector,flag=0;
385 for(Int_t i=1;i<=LDCsNumber;i++){
387 sprintf(filename,"Ev%dTPCslice%d",EventNumber,i);
390 sprintf(filename,"Ev%dTPCslice%d.decomp",EventNumber,i);
393 f.open(filename,ios::binary|ios::in);
395 f.open(filename,ios::in);
397 if(!f){cout<<"BE CAREFUL!! There isn't enough data to generate "<<LDCsNumber<<" slices"<<endl;break;}
398 //loop over the DDL block
399 //Each block contains a Mini Header followed by raw data (ALTRO FORMAT)
400 //The number of block is ceil(216/LDCsNumber)
401 UInt_t miniHeader[3];
402 //here the Mini Header is read
403 //cout<<filename<<endl;
404 while( (f.read((char*)(miniHeader),sizeof(UInt_t)*3)) ){
407 for(UInt_t j=0;j<size;j++){
408 f.read((char*)(&car),1);
409 fdest.write((char*)(&car),1);