// @(#) $Id$ // Author: Uli Frankenfeld , Anders Vestbo , Constantin Loizides //*-- Copyright © ALICE HLT Group /** \class AliHLTTPCMemHandler
//_____________________________________________________________
// AliHLTTPCMemHandler
//
// The HLT Binary File handler 
//
//  This class does all the memory I/O handling of HLT binary files.
//  
//  Examples:
//  ---------
//
//  1) Reading a binary file:
//  
//  AliHLTTPCMemHandler file;
//  file.SetBinaryInput(filename);
//  file.Init(slice,patch);
//
//  UInt_t nrowss;
//  AliHLTTPCDigitRowData *data = file.CompBinary2Memory(nrows);
//  
//  for(int i=0; ifDigitData;
//    for(int j=0; jfNDigit; j++) 
//      {
//        pad = dataPt[j].fPad;
//        time = dataPt[j].fTime;
//        charge = dataPt[j].fCharge;
//      }
//     
//    file.UpdateRowPointer(data);
//  
//    }
//  file.CloseBinaryInput();
//  ________________________
//  
//  2) Writing a binary file:
//  
//  //First of all you need to store the data in memory,
//  //and have a pointer to it of type AliHLTTPCDigitRowData.
//  //E.g. if you just want to write the data you read in example 1)
//  //into a new file, you can do the following:
//  
//  AliHLTTPCMemHandler newfile;
//  newfile.Init(slice,patch);
//  newfile.SetBinaryOutput(newfilename);
//  newfile.Memory2CompBinary((UInt_t)NumberOfRowsInPatch,(AliHLTTPCDigitRowData*)data);
//  newfile.CloseBinaryOutput();
//
//
// Compressed file format:
// -----------------------
//
// The data is RLE encoded and currently using _10_ bit range for the ADC-values.
*/ #include "AliHLTTPCRootTypes.h" #include "AliHLTTPCStandardIncludes.h" #include "AliHLTTPCDigitData.h" #include "AliHLTTPCLogging.h" #include "AliHLTTPCTransform.h" #include "AliHLTTPCTrackSegmentData.h" #include "AliHLTTPCSpacePointData.h" #include "AliHLTTPCTrackArray.h" #include "AliHLTTPCMemHandler.h" #if __GNUC__ >= 3 using namespace std; #endif ClassImp(AliHLTTPCMemHandler) AliHLTTPCMemHandler::AliHLTTPCMemHandler() { //Constructor fPt = 0; fSize =0; fInBinary = 0; fOutBinary = 0; fNRandom = 0; Init(0,0); fIsRandom = kFALSE; fRandomDigits = 0; fDPt =0; fNGenerate = 0; fNUsed = 0; fNDigits = 0; ResetROI(); } AliHLTTPCMemHandler::~AliHLTTPCMemHandler() { //Destructor if(fPt) delete[] fPt; if(fRandomDigits) delete [] fRandomDigits; if(fDPt) delete [] fDPt; } void AliHLTTPCMemHandler::Init(Int_t s,Int_t p, Int_t *r) { //init handler fSlice=s;fPatch=p; if(r) { fRowMin=r[0]; fRowMax=r[1]; }else{ fRowMin=AliHLTTPCTransform::GetFirstRow(p); fRowMax=AliHLTTPCTransform::GetLastRow(p); } ResetROI(); } void AliHLTTPCMemHandler::ResetROI() { //Resets the Look-up table for Region of Interest mode. for(Int_t i=fRowMin; i<=fRowMax; i++) { fEtaMinTimeBin[i] = 0; fEtaMaxTimeBin[i] = AliHLTTPCTransform::GetNTimeBins()-1; } } void AliHLTTPCMemHandler::SetROI(Float_t *eta,Int_t */*slice*/) { // Init the Look-up table for the Region of Interest mode. // Here you can specify a certain etaregion, - all data // outside this region will be discarded: // eta[0] = mimium eta // eta[1] = maximum eta // slice[0] = mimumum slice // slice[1] = maximum slice if(eta[1]==0) { LOG(AliHLTTPCLog::kWarning,"AliHLTTPCMemHandler::SetROI","Eta Values") <<"Bad ROI parameters. IDIOT! "<GetOutSize()); } Byte_t *AliHLTTPCMemHandler::Allocate(UInt_t size) { //Allocate memory of size in bytes. if(fPt){ LOG(AliHLTTPCLog::kWarning,"AliHLTTPCMemHandler::Allocate","Memory") <<"Delete Memory"< 1) { i = first; j = last; for (;;) { while (++i < last && CompareDigits(a[i], a[first]) < 0) ; while (--j > first && CompareDigits(a[j], a[first]) > 0) ; if (i >= j) break; tmp = a[i]; a[i] = a[j]; a[j] = tmp; } if (j == first) { ++first; continue; } tmp = a[first]; a[first] = a[j]; a[j] = tmp; if (j - first < last - (j + 1)) { QSort(a, first, j); first = j + 1; // QSort(j + 1, last); } else { QSort(a, j + 1, last); last = j; // QSort(first, j); } } } UInt_t AliHLTTPCMemHandler::GetRandomSize() const { //get random size Int_t nrandom = 0; for(Int_t r=fRowMin;r<=fRowMax;r++){ Int_t npad=AliHLTTPCTransform::GetNPads(r); nrandom += Int_t (fNGenerate * ((Double_t) npad/141.)); } return 9 * nrandom * sizeof(AliHLTTPCDigitData); } void AliHLTTPCMemHandler::Generate(Int_t row) { //Generate random data on row, if you didn't //ask for this, nothing happens here. if(!fIsRandom) return; ResetRandom(); fNDigits = 0; Int_t npad=AliHLTTPCTransform::GetNPads(row); Int_t ntime = fEtaMaxTimeBin[row] - fEtaMinTimeBin[row]; Int_t nrandom = Int_t (fNGenerate * ((Double_t) npad/141.) * (Double_t) ntime/(Double_t) AliHLTTPCTransform::GetNTimeBins() ); for(Int_t n=0;n=AliHLTTPCTransform::GetNPads(row)) continue; if(dtime<0||dtime>=AliHLTTPCTransform::GetNTimeBins()) continue; fRandomDigits[fNDigits].fCharge = dcharge; fRandomDigits[fNDigits].fRow = row; fRandomDigits[fNDigits].fPad = dpad; fRandomDigits[fNDigits].fTime = dtime; fDPt[fNDigits] = &fRandomDigits[fNDigits]; fNDigits++; } } } ///////////////////////////////////////// Digit IO Bool_t AliHLTTPCMemHandler::Memory2Binary(UInt_t nrow,AliHLTTPCDigitRowData *data) { //Write data to the outputfile as is. No run-length encoding is done. if(!fOutBinary){ LOG(AliHLTTPCLog::kWarning,"AliHLTTPCMemHandler::Memory2Binary","File") <<"No Output File"<fNDigit + sizeof(AliHLTTPCDigitRowData); outsize += size; fwrite(rowPt,size,1,fOutBinary); Byte_t *bytePt =(Byte_t *) rowPt; bytePt += size; rowPt = (AliHLTTPCDigitRowData *) bytePt; } LOG(AliHLTTPCLog::kDebug,"AliHLTTPCMemHandler::Memory2Binary","Memory") <fNDigit; //if(fread(bytePt,size,1,fInBinary)!=1) break; fread(bytePt,size,1,fInBinary); bytePt += size; outsize += size; rowPt = (AliHLTTPCDigitRowData *) bytePt; rowcount++; } nrow= rowcount; LOG(AliHLTTPCLog::kDebug,"AliHLTTPCMemHandler::Binary2Memory","Memory") <fPad; data[ndata].fTime = fDPt[fNUsed]->fTime; data[ndata].fCharge = fDPt[fNUsed]->fCharge; ndata++; fNUsed++; } void AliHLTTPCMemHandler::MergeDataRandom(AliHLTTPCDigitData *data, UInt_t & ndata, UInt_t row, UShort_t pad, UShort_t time, UShort_t charge) { //merge random data data[ndata].fPad = pad; data[ndata].fTime = time; data[ndata].fCharge = charge; while(ComparePoints(row,pad,time)==0){ Int_t ch = data[ndata].fCharge + fDPt[fNUsed]->fCharge; if(charge>=AliHLTTPCTransform::GetADCSat()) ch = AliHLTTPCTransform::GetADCSat(); data[ndata].fCharge = ch; fNUsed++; } ndata++; } void AliHLTTPCMemHandler::AddDataRandom(AliHLTTPCDigitData *data, UInt_t & ndata, UInt_t row, UShort_t pad, UShort_t time, UShort_t charge) { //add data random Int_t action; while((action=ComparePoints(row,pad,time))==1){ AddRandom(data,ndata); } if(action==0){ MergeDataRandom(data,ndata,row,pad,time,charge); } if(action<0){ AddData(data,ndata,row,pad,time,charge); } } void AliHLTTPCMemHandler::Write(UInt_t *comp, UInt_t & index, UInt_t & subindex, UShort_t value) const { //write compressed data UInt_t shift[3] = {0,10,20}; if(subindex==0) comp[index] =0; //clean up memory comp[index] |= (value&0x03ff)<>shift[subindex])&0x03ff; if(subindex == 2){ subindex = 0; index++; } else subindex++; return value; } UShort_t AliHLTTPCMemHandler::Test(UInt_t *comp, UInt_t index, UInt_t subindex) const { //supi dupi test UInt_t shift[3] = {0,10,20}; return (comp[index]>>shift[subindex])&0x03ff; } Int_t AliHLTTPCMemHandler::Memory2CompMemory(UInt_t nrow, AliHLTTPCDigitRowData *data,UInt_t *comp) { //Performs run-length encoding on data stored in memory pointed to by data. //The compressed data is written to comp. if(!comp){ LOG(AliHLTTPCLog::kWarning,"AliHLTTPCMemHandler::Memory2CompMemory","Memory") <<"Pointer to compressed data = 0x0 "<fRow; Write(comp,index,subindex,value); UShort_t maxpad=0; UShort_t npad=0; Int_t ddd[1000]; for(Int_t d=0;d<200;d++) ddd[d]=0; for(UInt_t dig=0;digfNDigit;dig++){ if(rowPt->fDigitData[dig].fPad <200){ ddd[rowPt->fDigitData[dig].fPad]++; } } for(Int_t d=0;d<200;d++){ if(ddd[d]){ npad++; maxpad =d; } } Write(comp,index,subindex,npad); UInt_t digit=0; for(UShort_t pad=0;pad <= maxpad;pad++){ if(digit>=rowPt->fNDigit || rowPt->fDigitData[digit].fPad != pad) continue; Write(comp,index,subindex,pad); // write zero if time != 0 if(digitfNDigit && rowPt->fDigitData[digit].fPad == pad){ if(rowPt->fDigitData[digit].fTime>0){ Write(comp,index,subindex,0); Write(comp,index,subindex,rowPt->fDigitData[digit].fTime); } } while(digitfNDigit && rowPt->fDigitData[digit].fPad == pad){ UShort_t charge = rowPt->fDigitData[digit].fCharge; if(charge>=1023){ charge=1023; } Write(comp,index,subindex,charge); if(digit+1fNDigit&&rowPt->fDigitData[digit+1].fPad == pad){ if(rowPt->fDigitData[digit].fTime +1 != rowPt->fDigitData[digit+1].fTime){ Write(comp,index,subindex,0); UShort_t nzero = rowPt->fDigitData[digit+1].fTime - (rowPt->fDigitData[digit].fTime +1); Write(comp,index,subindex,nzero); } } digit++; } Write(comp,index,subindex,0); Write(comp,index,subindex,0); } Int_t size = sizeof(AliHLTTPCDigitData) * rowPt->fNDigit+ sizeof(AliHLTTPCDigitRowData); Byte_t *bytePt =(Byte_t *) rowPt; bytePt += size; rowPt = (AliHLTTPCDigitRowData *) bytePt; } while(subindex) Write(comp,index,subindex,0); return index * sizeof(UInt_t); } Int_t AliHLTTPCMemHandler::CompMemory2Memory(UInt_t nrow, AliHLTTPCDigitRowData *data,UInt_t *comp) { //Uncompress the run-length encoded data in memory pointed to by comp, and // store it in data. if(!comp){ LOG(AliHLTTPCLog::kWarning,"AliHLTTPCMemHandler::CompMemory2Memory","Memory") <<"Pointer to compressed data = 0x0 "<fRow=row; Generate(row); UShort_t npad = Read(comp,index,subindex); for(UShort_t p=0;p=fEtaMinTimeBin[row]&&time<=fEtaMaxTimeBin[row]) //AddData(rowPt->fDigitData,ndigit,row,pad,time,charge); //seems we are using this function... but dont know why AddDataRandom(rowPt->fDigitData,ndigit,row,pad,time,charge); time++; } UShort_t tshift = Read(comp,index,subindex); if(tshift == 0) break; time += tshift; } } rowPt->fNDigit = ndigit; Int_t size = sizeof(AliHLTTPCDigitData) * rowPt->fNDigit+ sizeof(AliHLTTPCDigitRowData); Byte_t *bytePt =(Byte_t *) rowPt; bytePt += size; outsize += size; rowPt = (AliHLTTPCDigitRowData *) bytePt; } return outsize; } UInt_t AliHLTTPCMemHandler::GetCompMemorySize(UInt_t nrow,AliHLTTPCDigitRowData *data) const { //Return the size of RLE data, after compressing data. if(!data){ LOG(AliHLTTPCLog::kWarning,"AliHLTTPCMemHandler::GetCompMemorySize","Memory") <<"Pointer to AliHLTTPCDigitRowData = 0x0 "<fNDigit;dig++){ if(rowPt->fDigitData[dig].fPad <200){ ddd[rowPt->fDigitData[dig].fPad]++; } } for(Int_t d=0;d<200;d++){ if(ddd[d]){ npad++; maxpad =d; } } index++; UInt_t digit=0; for(UShort_t pad=0;pad <= maxpad;pad++){ if(digit>=rowPt->fNDigit || rowPt->fDigitData[digit].fPad != pad) continue; index++; // write zero if time != 0 if(digitfNDigit && rowPt->fDigitData[digit].fPad == pad){ if(rowPt->fDigitData[digit].fTime>0){ index++; index++; } } while(digitfNDigit && rowPt->fDigitData[digit].fPad == pad){ index++; if(digit+1fNDigit&&rowPt->fDigitData[digit+1].fPad == pad){ if(rowPt->fDigitData[digit].fTime +1 != rowPt->fDigitData[digit+1].fTime){ index++; index++; } } digit++; } index++; index++; } Int_t size = sizeof(AliHLTTPCDigitData) * rowPt->fNDigit+ sizeof(AliHLTTPCDigitRowData); Byte_t *bytePt =(Byte_t *) rowPt; bytePt += size; rowPt = (AliHLTTPCDigitRowData *) bytePt; } while(index%3) index++; return (index/3) * sizeof(UInt_t); } UInt_t AliHLTTPCMemHandler::GetMemorySize(UInt_t nrow,UInt_t *comp) const { //get memory size if(!comp){ LOG(AliHLTTPCLog::kWarning,"AliHLTTPCMemHandler::GetMemorySize","Memory") <<"Pointer to compressed data = 0x0 "<SetBinaryInput(fInBinary); UInt_t *comp =(UInt_t *)handler->Allocate(); handler->CompBinary2CompMemory(nrow,comp); UInt_t size = GetMemorySize(nrow,comp); AliHLTTPCDigitRowData *data = (AliHLTTPCDigitRowData *)Allocate(size); CompMemory2Memory(nrow,data,comp); handler->Free(); delete handler; return data; } Bool_t AliHLTTPCMemHandler::Memory2CompBinary(UInt_t nrow,AliHLTTPCDigitRowData *data) { //Perform RLE on the data, and write it to the output file. Bool_t out = kTRUE; AliHLTTPCMemHandler * handler = new AliHLTTPCMemHandler(); UInt_t size = GetCompMemorySize(nrow,data); UInt_t *comp =(UInt_t *)handler->Allocate(size); Memory2CompMemory(nrow,data,comp); CompMemory2CompBinary(nrow,comp,size); handler->Free(); delete handler; return out; } ///////////////////////////////////////// Point IO Bool_t AliHLTTPCMemHandler::Memory2Binary(UInt_t npoint,AliHLTTPCSpacePointData *data) { //Writing spacepoints stored in data to the outputfile. if(!fOutBinary){ LOG(AliHLTTPCLog::kWarning,"AliHLTTPCMemHandler::Memory2Binary","File") <<"No Output File"<fNPoints*sizeof(UInt_t); fwrite(trackPt,size,1,fOutBinary); Byte_t *bytePt = (Byte_t*) trackPt; bytePt += size; trackPt = (AliHLTTPCTrackSegmentData*) bytePt; } LOG(AliHLTTPCLog::kDebug,"AliHLTTPCMemHandler::Memory2Binary","File") <fNPoints*sizeof(UInt_t); if(fread(trackPt->fPointIDs,size,1,fInBinary)!=1) break; Byte_t *bytePt = (Byte_t*) trackPt; bytePt += sizeof(AliHLTTPCTrackSegmentData)+size; trackPt = (AliHLTTPCTrackSegmentData*) bytePt; ntrack++; } LOG(AliHLTTPCLog::kDebug,"AliHLTTPCMemHandler::Binary2Memory","File") <WriteTracks(ntrack,data); return kTRUE; } Bool_t AliHLTTPCMemHandler::Memory2TrackArray(UInt_t ntrack,AliHLTTPCTrackSegmentData *data,AliHLTTPCTrackArray *array) const { //Fill the tracks in data into trackarray. if(!data){ LOG(AliHLTTPCLog::kWarning,"AliHLTTPCMemHandler::Memory2TrackArray","Memory") <<"Pointer to AliHLTTPCTrackSegmentData = 0x0 "<FillTracks(ntrack,data); return kTRUE; } Bool_t AliHLTTPCMemHandler::Memory2TrackArray(UInt_t ntrack,AliHLTTPCTrackSegmentData *data,AliHLTTPCTrackArray *array,Int_t slice) const { //Fill the tracks in data into trackarray, and rotate the tracks to global coordinates. if(!data){ LOG(AliHLTTPCLog::kWarning,"AliHLTTPCMemHandler::Memory2TrackArray","Memory") <<"Pointer to AliHLTTPCTrackSegmentData = 0x0 "<FillTracks(ntrack,data,slice); return kTRUE; } void AliHLTTPCMemHandler::UpdateRowPointer(AliHLTTPCDigitRowData *&tempPt) { //Update the data pointer to the next padrow in memory. Byte_t *tmp = (Byte_t*)tempPt; Int_t size = sizeof(AliHLTTPCDigitRowData) + tempPt->fNDigit*sizeof(AliHLTTPCDigitData); tmp += size; tempPt = (AliHLTTPCDigitRowData*)tmp; } Int_t AliHLTTPCMemHandler::ComparePoints(UInt_t /*row*/,UShort_t pad,UShort_t time) const { //compare two points if(fNUsed>=fNDigits) return -2; if(pad==fDPt[fNUsed]->fPad&&time==fDPt[fNUsed]->fTime) return 0; if(padfPad) return -1; if(pad==fDPt[fNUsed]->fPad&&timefTime) return -1; return 1; } Int_t AliHLTTPCMemHandler::CompareDigits(AliHLTTPCRandomDigitData *a,AliHLTTPCRandomDigitData *b) const { //compare two digits if(a->fPad==b->fPad && a->fTime == b->fTime) return 0; if(a->fPadfPad) return -1; if(a->fPad==b->fPad && a->fTimefTime) return -1; return 1; }