#include <TMath.h>
#include "TClass.h"
#include "AliDAQ.h"
#include "AliRawDataHeaderSim.h"
#include "AliRawReader.h"
#include "AliLog.h"
#include "AliFstream.h"
#include "AliLoader.h"
#include "AliTreeLoader.h"
#include "AliTRDrawData.h"
#include "AliTRDdigitsManager.h"
#include "AliTRDgeometry.h"
#include "AliTRDarrayDictionary.h"
#include "AliTRDarrayADC.h"
#include "AliTRDrawStream.h"
#include "AliTRDcalibDB.h"
#include "AliTRDSignalIndex.h"
#include "AliTRDfeeParam.h"
#include "AliTRDmcmSim.h"
#include "AliTRDtrackletWord.h"
#include "AliTRDtrackGTU.h"
#include "AliESDTrdTrack.h"
#include "AliTRDdigitsParam.h"
ClassImp(AliTRDrawData)
Int_t AliTRDrawData::fgDataSuppressionLevel = 0;
AliTRDrawData::AliTRDrawData()
:TObject()
,fRunLoader(NULL)
,fGeo(NULL)
,fFee(NULL)
,fNumberOfDDLs(0)
,fTrackletTree(NULL)
,fTracklets(new TClonesArray("AliTRDtrackletWord", 1000))
,fTracks(new TClonesArray("AliESDTrdTrack", 500))
,fSMindexPos(0)
,fStackindexPos(0)
,fEventCounter(0)
,fTrgFlags()
,fMcmSim(new AliTRDmcmSim)
,fDigitsParam(NULL)
{
fFee = AliTRDfeeParam::Instance();
fNumberOfDDLs = AliDAQ::NumberOfDdls("TRD");
}
AliTRDrawData::AliTRDrawData(const AliTRDrawData &r)
:TObject(r)
,fRunLoader(NULL)
,fGeo(NULL)
,fFee(NULL)
,fNumberOfDDLs(0)
,fTrackletTree(NULL)
,fTracklets(new TClonesArray("AliTRDtrackletWord", 1000))
,fTracks(new TClonesArray("AliESDTrdTrack", 500))
,fSMindexPos(0)
,fStackindexPos(0)
,fEventCounter(0)
,fTrgFlags()
,fMcmSim(new AliTRDmcmSim)
,fDigitsParam(NULL)
{
fFee = AliTRDfeeParam::Instance();
fNumberOfDDLs = AliDAQ::NumberOfDdls("TRD");
}
AliTRDrawData::~AliTRDrawData()
{
delete fTracklets;
delete fTracks;
delete fMcmSim;
}
Bool_t AliTRDrawData::Digits2Raw(TTree *digitsTree, const TTree *tracks )
{
AliTRDdigitsManager* const digitsManager = new AliTRDdigitsManager();
if (!digitsManager->ReadDigits(digitsTree)) {
delete digitsManager;
return kFALSE;
}
if (tracks != NULL) {
delete digitsManager;
AliError("Tracklet input is not supported yet.");
return kFALSE;
}
fGeo = new AliTRDgeometry();
if (!AliTRDcalibDB::Instance()) {
AliError("Could not get calibration object");
delete fGeo;
delete digitsManager;
return kFALSE;
}
Int_t retval = kTRUE;
Int_t rv = fFee->GetRAWversion();
if ( rv > 0 && rv <= 3 ) retval = Digits2Raw(digitsManager);
else {
retval = kFALSE;
AliWarning(Form("Unsupported raw version (%d).", rv));
}
delete fGeo;
delete digitsManager;
return retval;
}
Bool_t AliTRDrawData::Digits2Raw(AliTRDdigitsManager *digitsManager)
{
const Int_t kMaxHcWords = (fGeo->TBmax()/3)
* fGeo->ADCmax()
* fGeo->MCMmax()
* fGeo->ROBmaxC1()/2
+ 100 + 20;
UInt_t *hcBuffer = new UInt_t[kMaxHcWords];
Bool_t newEvent = kFALSE;
Bool_t newSM = kFALSE;
fDigitsParam = digitsManager->GetDigitsParam();
for (Int_t sect = 0; sect < fGeo->Nsector(); sect++) {
char name[1024];
snprintf(name,1024,"TRD_%d.ddl",sect + AliTRDrawStream::kDDLOffset);
AliFstream* of = new AliFstream(name);
AliRawDataHeaderSim header;
UInt_t hpos = of->Tellp();
of->WriteBuffer((char *) (& header), sizeof(header));
Int_t npayloadbyte = 0;
UInt_t *iwbuffer = new UInt_t[109];
Int_t nheader = 0;
UInt_t bStackMask = 0x0;
Bool_t bStackHasData = kFALSE;
Bool_t bSMHasData = kFALSE;
iwbuffer[nheader++] = 0x0044b020;
iwbuffer[nheader++] = 0x10404071;
for ( Int_t i=0; i<66; i++ ) iwbuffer[nheader++] = 0x00000000;
iwbuffer[nheader++] = 0x10000000;
for ( Int_t stack= 0; stack < fGeo->Nstack(); stack++) {
UInt_t linkMask = 0x0;
for( Int_t layer = 0; layer < fGeo->Nlayer(); layer++) {
Int_t iDet = fGeo->GetDetector(layer,stack,sect);
AliTRDarrayADC *digits = (AliTRDarrayADC *) digitsManager->GetDigits(iDet);
if ( fgDataSuppressionLevel==0 || digits->HasData() ) {
bStackMask = bStackMask | ( 1 << stack );
linkMask = linkMask | ( 3 << (2*layer) );
bStackHasData = kTRUE;
bSMHasData = kTRUE;
}
}
if ( fgDataSuppressionLevel==0 || bStackHasData ){
iwbuffer[nheader++] = 0x0007a000 | linkMask;
if (fgDataSuppressionLevel==0) iwbuffer[nheader-1] = 0x0007afff;
iwbuffer[nheader++] = 0x04045b01;
for (Int_t i=0;i<6;i++) iwbuffer[nheader++] = 0x00000000;
bStackHasData = kFALSE;
}
}
if ( fgDataSuppressionLevel==0 || bSMHasData ){
iwbuffer[0] = iwbuffer[0] | bStackMask;
if (fgDataSuppressionLevel==0) iwbuffer[0] = 0x0044b03f;
of->WriteBuffer((char *) iwbuffer, nheader*4);
AliDebug(11, Form("SM %d index word: %08x", sect, iwbuffer[0]));
AliDebug(11, Form("SM %d header: %08x", sect, iwbuffer[1]));
}
for( Int_t stack = 0; stack < fGeo->Nstack(); stack++) {
for( Int_t layer = 0; layer < fGeo->Nlayer(); layer++) {
Int_t iDet = fGeo->GetDetector(layer,stack,sect);
if (iDet == 0){
newEvent = kTRUE;
fEventCounter++;
AliDebug(11, Form("New event!! Event counter: %d",fEventCounter));
}
if ( stack==0 && layer==0 ) newSM = kTRUE;
AliDebug(15, Form("stack : %d, layer : %d, iDec : %d\n",stack,layer,iDet));
AliTRDarrayADC *digits = (AliTRDarrayADC *) digitsManager->GetDigits(iDet);
if (fgDataSuppressionLevel==0 || digits->HasData() ) {
if (digits->HasData()) digits->Expand();
Int_t hcwords = 0;
hcwords = ProduceHcData(digits,0,iDet,hcBuffer,kMaxHcWords,newEvent,newSM);
if ( newEvent ) newEvent = kFALSE;
of->WriteBuffer((char *) hcBuffer, hcwords*4);
npayloadbyte += hcwords*4;
hcwords = ProduceHcData(digits,1,iDet,hcBuffer,kMaxHcWords,newEvent,newSM);
of->WriteBuffer((char *) hcBuffer, hcwords*4);
npayloadbyte += hcwords*4;
}
}
}
header.fSize = UInt_t(of->Tellp()) - hpos;
header.SetAttribute(0);
of->Seekp(hpos);
of->WriteBuffer((char *) (& header), sizeof(header));
delete of;
delete [] iwbuffer;
}
delete [] hcBuffer;
return kTRUE;
}
void AliTRDrawData::ProduceSMIndexData(UInt_t *buf, Int_t& nw){
fSMindexPos = nw;
buf[nw++] = 0x0001b020;
buf[nw++] = 0x10404071;
fStackindexPos = nw;
}
void AliTRDrawData::AssignStackMask(UInt_t *buf, Int_t nStack){
buf[fSMindexPos] = buf[fSMindexPos] | ( 1 << nStack );
}
Int_t AliTRDrawData::AddStackIndexWords(UInt_t *buf, Int_t , Int_t nMax){
Int_t nAddedWords = 0;
if ( ShiftWords(buf, fStackindexPos, 8, nMax)== kFALSE ){
AliError("Adding stack header failed.");
return 0;
}
buf[fStackindexPos++] = 0x0007a000;
buf[fStackindexPos++] = 0x04045b01;
for (Int_t i=0;i<6;i++) buf[fStackindexPos++] = 0x00000000;
nAddedWords += 8;
return nAddedWords;
}
void AliTRDrawData::AssignLinkMask(UInt_t *buf, Int_t nLayer){
buf[fStackindexPos-8] = buf[fStackindexPos-8] | ( 3 << (2*nLayer) );
}
Bool_t AliTRDrawData::ShiftWords(UInt_t *buf, Int_t nStart, Int_t nWords, Int_t nMax){
for ( Int_t iw=nMax; iw>nStart-1; iw--){
buf[iw+nWords] = buf[iw];
}
return kTRUE;
}
Int_t AliTRDrawData::ProduceHcData(AliTRDarrayADC *digits, Int_t side, Int_t det, UInt_t *buf, Int_t maxSize, Bool_t , Bool_t ){
Int_t nw = 0;
Int_t of = 0;
Int_t *tempnw = &nw;
Int_t *tempof = &of;
Int_t layer = fGeo->GetLayer( det );
Int_t stack = fGeo->GetStack( det );
Int_t sect = fGeo->GetSector( det );
const Int_t kCtype = fGeo->GetStack(det) == 2 ? 0 : 1;
Bool_t trackletOn = fFee->GetTracklet();
AliDebug(1,Form("Producing raw data for sect=%d layer=%d stack=%d side=%d",sect,layer,stack,side));
UInt_t *tempBuffer = buf;
if (trackletOn) {
tempBuffer = new UInt_t[maxSize];
tempnw = new Int_t(0);
tempof = new Int_t(0);
}
WriteIntermediateWords(tempBuffer,*tempnw,*tempof,maxSize,det,side);
if (digits->HasData()) {
for (Int_t iRobRow = 0; iRobRow <= (kCtype + 3)-1; iRobRow++ ) {
Int_t iRob = iRobRow * 2 + side;
for (Int_t iMcmRB = 0; iMcmRB < fGeo->MCMmax(); iMcmRB++ ) {
Int_t iMcm = 16 - 4*(iMcmRB/4 + 1) + (iMcmRB%4);
fMcmSim->Init(det, iRob, iMcm);
fMcmSim->SetData(digits);
if (trackletOn) {
fMcmSim->Tracklet();
Int_t tempNw = fMcmSim->ProduceTrackletStream(&buf[nw], maxSize - nw);
if( tempNw < 0 ) {
of += tempNw;
nw += maxSize - nw;
AliError(Form("Buffer overflow detected. Please increase the buffer size and recompile."));
} else {
nw += tempNw;
}
}
fMcmSim->ZSMapping();
Int_t tempNw = fMcmSim->ProduceRawStream( &tempBuffer[*tempnw], maxSize - *tempnw, fEventCounter );
if ( tempNw < 0 ) {
*tempof += tempNw;
*tempnw += maxSize - nw;
AliError(Form("Buffer overflow detected. Please increase the buffer size and recompile."));
} else {
*tempnw += tempNw;
}
}
}
}
if (trackletOn) {
if (nw + *tempnw < maxSize) {
memcpy(&buf[nw], tempBuffer, *tempnw * sizeof(UInt_t));
nw += *tempnw;
}
else {
AliError("Buffer overflow detected");
}
delete [] tempBuffer;
delete tempof;
delete tempnw;
}
if (nw+3 < maxSize) {
buf[nw++] = fgkEndOfDataMarker;
buf[nw++] = fgkEndOfDataMarker;
buf[nw++] = fgkEndOfDataMarker;
buf[nw++] = fgkEndOfDataMarker;
} else {
of += 4;
}
if (of != 0) {
AliError("Buffer overflow. Data is truncated. Please increase buffer size and recompile.");
}
return nw;
}
AliTRDdigitsManager *AliTRDrawData::Raw2Digits(AliRawReader *rawReader)
{
rawReader->Select("TRD");
AliTRDarrayADC *digits = 0;
AliTRDarrayDictionary *track0 = 0;
AliTRDarrayDictionary *track1 = 0;
AliTRDarrayDictionary *track2 = 0;
AliTRDdigitsManager* digitsManager = new AliTRDdigitsManager();
digitsManager->CreateArrays();
AliTRDrawStream input(rawReader);
AliRunLoader *runLoader = AliRunLoader::Instance();
AliDataLoader *trklLoader = runLoader->GetLoader("TRDLoader")->GetDataLoader("tracklets");
if (!trklLoader) {
trklLoader = new AliDataLoader("TRD.Tracklets.root","tracklets", "tracklets");
runLoader->GetLoader("TRDLoader")->AddDataLoader(trklLoader);
}
if (!trklLoader) {
AliError("Could not get the tracklet data loader!");
return 0x0;
}
trklLoader->Load("update");
AliTreeLoader *trklTreeLoader = dynamic_cast<AliTreeLoader*> (trklLoader->GetBaseLoader("tracklets-raw"));
if (!trklTreeLoader) {
trklTreeLoader = new AliTreeLoader("tracklets-raw", trklLoader);
trklLoader->AddBaseLoader(trklTreeLoader);
}
TClonesArray *fTrackletArray = new TClonesArray("AliTRDtrackletWord", 256);
Int_t lastHC = -1;
if (trklLoader->Tree())
trklLoader->MakeTree();
TTree *trackletTree = trklTreeLoader->Tree();
if (!trackletTree) {
trklTreeLoader->MakeTree();
trackletTree = trklTreeLoader->Tree();
}
if (!trackletTree->GetBranch("hc"))
trackletTree->Branch("hc", &lastHC, "hc/I");
else
trackletTree->SetBranchAddress("hc", &lastHC);
if (!trackletTree->GetBranch("trkl"))
trackletTree->Branch("trkl", &fTrackletArray);
else
trackletTree->SetBranchAddress("trkl", &fTrackletArray);
AliDataLoader *trkLoader = 0x0;
trkLoader = runLoader->GetLoader("TRDLoader")->GetDataLoader("gtutracks");
if (!trkLoader) {
trkLoader = new AliDataLoader("TRD.GtuTracks.root","gtutracks", "gtutracks");
runLoader->GetLoader("TRDLoader")->AddDataLoader(trkLoader);
}
if (!trkLoader) {
AliError("Could not get the GTU-track data loader!");
return 0x0;
}
trkLoader->Load("UPDATE");
TTree *trackTree = trkLoader->Tree();
if (!trackTree) {
trkLoader->MakeTree();
trackTree = trkLoader->Tree();
}
AliTRDtrackGTU trk;
if (!trackTree->GetBranch("TRDtrackGTU"))
trackTree->Branch("TRDtrackGTU", "AliTRDtrackGTU", &trk, 32000);
input.SetTrackletArray(fTracklets);
input.SetTrackArray(fTracks);
Int_t det = 0;
while (det >= 0)
{
det = input.NextChamber(digitsManager);
if (det >= 0)
{
digits = (AliTRDarrayADC *) digitsManager->GetDigits(det);
track0 = (AliTRDarrayDictionary *) digitsManager->GetDictionary(det,0);
track1 = (AliTRDarrayDictionary *) digitsManager->GetDictionary(det,1);
track2 = (AliTRDarrayDictionary *) digitsManager->GetDictionary(det,2);
if (digits) digits->Compress();
if (track0) track0->Compress();
if (track1) track1->Compress();
if (track2) track2->Compress();
}
}
for (Int_t iSector = 0; iSector < fGeo->Nsector(); iSector++) {
fTrgFlags[iSector] = input.GetTriggerFlags(iSector);
}
fTrackletArray->Clear();
Int_t nTracklets = fTracklets ? fTracklets->GetEntries() : 0;
AliDebug(1, Form("Writing %i tracklets to loader", nTracklets));
for (Int_t iTracklet = 0; iTracklet < nTracklets; ++iTracklet) {
AliTRDtrackletWord *trkl = (AliTRDtrackletWord*) fTracklets->At(iTracklet);
if (trkl->GetHCId() != lastHC) {
if (fTrackletArray->GetEntriesFast() > 0) {
trackletTree->Fill();
fTrackletArray->Clear();
}
lastHC = trkl->GetHCId();
}
new ((*fTrackletArray)[fTrackletArray->GetEntriesFast()]) AliTRDtrackletWord(*trkl);
}
if (fTrackletArray->GetEntriesFast() > 0) {
trackletTree->Fill();
fTrackletArray->Clear();
}
trklTreeLoader->WriteData("OVERWRITE");
trklLoader->WriteData("OVERWRITE");
trklLoader->UnloadAll();
trklLoader->CloseFile();
Int_t nTracks = fTracks ? fTracks->GetEntriesFast() : 0;
AliDebug(1, Form("Writing %i tracks to loader", nTracks));
for (Int_t iTrack = 0; iTrack < nTracks; ++iTrack) {
AliESDTrdTrack *trkEsd = (AliESDTrdTrack*) fTracks->At(iTrack);
trk = *trkEsd;
trackTree->Fill();
}
trkLoader->WriteData("OVERWRITE");
trkLoader->UnloadAll();
trkLoader->CloseFile();
return digitsManager;
}
void AliTRDrawData::WriteIntermediateWords(UInt_t* buf, Int_t& nw, Int_t& of, const Int_t& maxSize, const Int_t& det, const Int_t& side) {
Int_t layer = fGeo->GetLayer( det );
Int_t stack = fGeo->GetStack( det );
Int_t sect = fGeo->GetSector( det );
Int_t rv = fFee->GetRAWversion();
const Int_t kNTBin = fDigitsParam->GetNTimeBins(det);
Bool_t trackletOn = fFee->GetTracklet();
UInt_t x = 0;
if (nw < maxSize){
buf[nw++] = fgkEndOfTrackletMarker;
buf[nw++] = fgkEndOfTrackletMarker;
}
else {
of++;
}
Int_t majorv = 0;
Int_t minorv = 0;
Int_t add = 1;
Int_t tp = 0;
Int_t zs = (rv==3) ? 1 : 0;
Int_t dt = (trackletOn) ? 0 : 1;
majorv = (tp<<6) | (zs<<5) | (dt<<4) | 1;
x = (1<<31) | (majorv<<24) | (minorv<<17) | (add<<14) | (sect<<9) | (layer<<6) | (stack<<3) | (side<<2) | 1;
if (nw < maxSize) buf[nw++] = x; else of++;
Int_t bcCtr = 99;
Int_t ptCtr = 15;
Int_t ptPhase = 11;
x = ((kNTBin)<<26) | (bcCtr<<10) | (ptCtr<<6) | (ptPhase<<2) | 1;
if (nw < maxSize) buf[nw++] = x; else of++;
}