/* This file is part of MAUS: http://micewww.pp.rl.ac.uk:8080/projects/maus
*
* MAUS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MAUS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MAUS. If not, see .
*
*/
#include "MDRebuildManager.h"
bool MDRebuildManager::Scan() {
bool data_ERR;
cout << "\n### Scanning the raw data files ###\n\n";
for(unsigned int xfile=0; xfile<_infiles.size(); xfile++) {
cout << "--- Scanning file " << _infiles[xfile]->GetFileName() << " --> ";
bool Err = this->Scan(_infiles[xfile]);
if (!Err) cout << "OK\n";
data_ERR |= Err;
}
return data_ERR;
}
int MDRebuildManager::Scan(MDdateFile *infile) {
int nEv(0), nErr(0);
unsigned char *eventBuffer;
eventBuffer = infile->GetNextEvent();
// while (nEv < 30) {
while ( eventBuffer ) {
long pos = infile->_curPos;
// cout << "\n\nEvent " << nEv << " pos: " << pos << endl;
try {
MDevent theEvent(eventBuffer);
if (theEvent.EventType()==PHYSICS_EVENT && theEvent.IsSuperEvent()) {
int nSubEvts = theEvent.NsubEvent();
// cout << "" << _infile->_curPos << " type: " << theEvent.EventType()
// << " nSub: " << nSubEvts
// << " size: " << theEvent.EventSize()
// << " hsize: " << theEvent.HeadSize() << endl;
uint32_t nPart(0), nPart_this(0);
pos += theEvent.HeadSize();
if (nSubEvts>1)
for (int iEvt=0; iEvtGetNextEvent();
}
return nErr;
}
bool MDRebuildManager::Reorder() {
std::vector newmap;
newmap.resize(_nLDCs);
EvntLabel subEv0, subEv1;
int xEvt=0;
while(1) {
if(_addresMap[0].empty() || _addresMap[1].empty())
break;
subEv0 = _addresMap[0].front();
subEv1 = _addresMap[1].front();
// cout << xEvt << " @ " << subEv0._nPartEv << " " << subEv1._nPartEv << endl;
if (subEv0._nPartEv == subEv1._nPartEv) {
newmap[0].push_back(subEv0);
newmap[1].push_back(subEv1);
_addresMap[0].pop_front();
_addresMap[1].pop_front();
} else if ( !Synchronize() ) {
cout << " ERROR: Unable to restore the event synchronization.\n"
<< " Trying again\n";
if( !Synchronize() ) {
cout << " ERROR: Unable to restore the event synchronization.\n"
<< "Give up!";
return false;
}
}
xEvt++;
}
_addresMap = newmap;
return true;
}
void printV(std::vector v) {
cout << "pt: " << v[0] << " " << v[1] << " " << v[2] << " " << v[3] << endl;
}
bool MDRebuildManager::Synchronize() {
// Remove 3 spills from the first LDC. In principle the messy spill must be only one, but ...
_addresMap[0].erase(_addresMap[0].begin(), _addresMap[0].begin()+3);
std::vector pt_vector0(4), pt_vector_this(4);
std::vector ldfc_ok(false, _nLDCs-1);
// For the first LDC - create a vector with the number of particle triggers for 4 spills.
for(int xSpill=0; xSpill<4; xSpill++)
pt_vector0[xSpill] = _addresMap[0][xSpill]._nPartEv;
// printV(pt_vector0);
// Now try to resynchronize this LDC with the other LDCs.
for(int xLDC=1;xLDC<_nLDCs;xLDC++) {
// Try 10 possible shifts.
for(int xSpill_shift=0; xSpill_shift<10; xSpill_shift++) {
// Create a vector with the number of particle triggers for this particular case.
for(int xSpill=0; xSpill<4; xSpill++)
pt_vector_this[xSpill] = _addresMap[xLDC][xSpill_shift+xSpill]._nPartEv;
// printV(pt_vector_this);
if(pt_vector0==pt_vector_this){
_addresMap[xLDC].erase(_addresMap[xLDC].begin(), _addresMap[xLDC].begin()+xSpill_shift);
ldfc_ok[xLDC] = true;
break;
}
}
}
for(int xLDC=1;xLDC<_nLDCs;xLDC++)
if(ldfc_ok[xLDC]==false)
return false;
return true;
}
void MDRebuildManager::Rebuild() {
// Get the Run Number from the name of tha first data file.
int runNum_int;
stringstream ss;
ss.str(_infiles[0]->GetFileName());
ss >> runNum_int;
for(unsigned int xfile=0; xfile<_infiles.size(); xfile++) {
if(_addresMap[0].empty() || _addresMap[1].empty() )
break;
cout << "--- Rebuilding file " << _infiles[xfile]->GetFileName() << endl;
ss.str("");
// Create a new binary file. The rebuilt data will be recorded here.
if (xfile<10) ss << runNum_int << ".90" << xfile;
else if (xfile<100) ss << runNum_int << ".9" << xfile;
else ss << runNum_int << "." << xfile;
cout << "Creating file " << ss.str() << endl;
ofstream outfile (ss.str().c_str(), ofstream::binary);
this->Rebuild(_infiles[xfile], &outfile);
outfile.close();
}
}
void MDRebuildManager::Rebuild(MDdateFile *infile, ofstream *outfile) {
// cout << "MDRebuildManager::Rebuild() " << _infile->GetFileName() << endl;
// Go back to the begining of the original binary file.
infile->Reset();
int nEvts=0;
unsigned char *eventBuffer;
eventBuffer = infile->GetNextEvent();
// while (nEvts < 30) {
while ( eventBuffer ) {
long pos = infile->_curPos;
long pos_next = infile->GetStreamPos();
MDevent theEvent(eventBuffer);
if( theEvent.EventType()!=PHYSICS_EVENT) {
outfile->write((char*)eventBuffer, theEvent.EventSize());
} else {
EvntLabel subEv0 = _addresMap[0].front();
EvntLabel subEv1 = _addresMap[1].front();
// cout << "rebuilding Event " << nEvts << " pos: " << pos << " next pos: " << pos_next << endl;
// cout << "SubEv0 pos: " << subEv0._pos << " SubEv1 pos: " << subEv1._pos << endl;
if (subEv0._pos < pos || subEv1._pos < pos) {
// This is an event in the next file. Skip few spills and continue with the next file.
while ( (subEv0._pos > pos || subEv1._pos > pos) &&
!_addresMap[0].empty() && ! _addresMap[1].empty() ) {
// cout << "Removing SubEv0 pos: " << subEv0._pos << " SubEv1 pos: " << subEv1._pos << endl;
_addresMap[0].pop_front();
_addresMap[1].pop_front();
subEv0 = _addresMap[0].front();
subEv1 = _addresMap[1].front();
}
break;
}
_addresMap[0].pop_front();
_addresMap[1].pop_front();
( *theEvent.EventSizePtr() ) = theEvent.HeadSize() + subEv0._size + subEv1._size;
outfile->write((char*)eventBuffer, theEvent.HeadSize());
unsigned char *buffer = new unsigned char[subEv0._size];
infile->GetEvent(buffer, subEv0._pos, subEv0._size);
MDevent theSubEvent0(buffer);
// cout /*<< (int*)eventBuffer */<< "SubEv0 type: " << theSubEvent0.EventType()
// << " pos: " << subEv0._pos
// << " size: " << subEv0._size << endl;
outfile->write((char*)buffer, subEv0._size);
delete[] buffer;
buffer = new unsigned char[subEv1._size];
infile->GetEvent(buffer, subEv1._pos, subEv1._size);
MDevent theSubEvent1(buffer);
// cout /*<< (int*)eventBuffer */<< "SubEv1 type: " << theSubEvent1.EventType()
// << " pos: " << subEv1._pos
// << " size: " << subEv1._size << endl;
outfile->write((char*)buffer, subEv1._size);
delete[] buffer;
// cout << nEvts << " " << subEv0._nPartEv << " " << subEv1._nPartEv << endl;
nEvts++;
infile->GoTo(pos_next);
}
// cout << "FIFO size: " <<_addresMap[0].size() << " " << _addresMap[1].size() << endl;
if(_addresMap[0].empty() || _addresMap[1].empty() )
break;
eventBuffer = infile->GetNextEvent();
}
}
void MDRebuildManager::DumpAddresMap(int LdcId) {
// int nEvts = _addresMap[LdcId];
// cout << "#### AddresMap LDC ####" << LdcId << endl;
// for (int iEvt=0; iEvt