// mc2coda_compress.cc // compresses mc2coda output file by eliminating redundant and unnecessary information // still to do: // further compress TDC banks // store event time someplace // to link: // source /apps/root/PRO/setroot_CUE // setenv ROOTLIBS `$ROOTSYS/bin/root-config --libs` // g++ -I/group/da/ejw/coda/include -I${ROOTSYS}/include -Wall -fPIC -D_GNU_SOURCE -D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS -o mc2coda_compress -L/group/da/ejw/coda/Linux-x86_64/lib -levioxx -levio -let -lexpat -lieee -lrt -lpthread -lz -lm -lnsl -lresolv -ldl ${ROOTLIBS} mc2coda_compress.cc #include #include #include #include #include // root stuff #include #include #include using namespace std; using namespace evio; static int evtCount = 0; static int hitCount = 0; static int hitCountw = 0; static string crateFile = "crateMap.txt"; // holds module type for each crate, uses defs from mc2coda.h #define NOMOD 0 #define VMECPU 1 #define TID 2 #define FADC250 3 #define FADC125 4 #define F1TDC32 5 #define F1TDC48 6 #define JLDISC 10 #define USERMOD 14 static vector crateMap(128); // prototypes static void getCrateMap(string &fileName); static void compress (evioDOMTree &eventTree); //-------------------------------------------------------------- //-------------------------------------------------------------- int main(int argc, char **argv) { int inSize,outSize; try { // get crate map from file getCrateMap(crateFile); // create and open evio file evioFileChannel in(argv[1],"r"); in.open(); cout << "opened input file " << argv[1]<Fill(float(inSize),float(outSize),float(hitCount)); h1->Fill(float(inSize),float(outSize),float(hitCountw)); hx->Fill(float(inSize)); hy->Fill(float(outSize)); hz->Fill(float(hitCount)); hw->Fill(float(hitCountw)); hxy->Fill(float(inSize),float(outSize)); h1w->Fill(float(hitCount),float(hitCountw)); r->Fill(float(outSize)/float(inSize)); // cout << setw(5) << " event " << evtCount << " in size is " << setw(6) << inSize << ", out size is " // << setw(6) << outSize << ", ratio is " << setw(6) << float(outSize)/float(inSize) << endl; } // reached eof, close all files in.close(); out.close(); ROOTFile->Write(); ROOTFile->Close(); } catch (evioException *e) { cerr << endl << e->toString() << endl << endl; exit(EXIT_FAILURE); } // done cout << endl << endl << " ***All done after " << evtCount << " events***" << endl << endl; exit(EXIT_SUCCESS); } //------------------------------------------------------------------------------- void getCrateMap(string &fileName) { string line; int crate,itype; string type; ifstream in(fileName.c_str(),ifstream::in); if (in.is_open()) { while(in.good()) { getline(in,line); if(line.size()>10) { crate=atoi(line.c_str()); type=line.substr(4); if(type=="FADC250") { itype=FADC250; } else if(type=="FADC125") { itype=FADC125; } else if(type=="F1TDC32") { itype=F1TDC32; } else if(type=="F1TDC48") { itype=F1TDC48; } else if(type=="JLDISC") { itype=JLDISC; } else if(type=="USERMOD") { itype=USERMOD; } else { itype=NOMOD; } if((crate>0)&&(crate<=128))crateMap[crate]=itype; } } in.close(); } else { cerr << "Unable to open file"; } } //------------------------------------------------------------------------------- // full compression void compress(evioDOMTree &eventTree) { int crate,slot,type,nhitwords; int triggerTime = -1; // get list of all data (uint32_t) banks in event evioDOMNodeListP dataList = eventTree.getNodeList(typeIs()); // loop over each data bank, compress module data, elevate data bank onee level, delete empty banks, get trigger time evioDOMNodeList::iterator iter; for(iter=dataList->begin(); iter!=dataList->end(); iter++) { crate = (*iter)->getParent()->tag; type = crateMap[crate]; vector *vec = (*iter)->getVector(); nhitwords=0; if((vec!=NULL)&&(vec->size()>0)) { vector::iterator iter2 = vec->begin(); vector::iterator iter3; switch (type) { case FADC250: case FADC125: do { if((*iter2)>>27==0x1f) { // filler word, erase vec->erase(iter2); } else if((*iter2)>>27==0x11) { // block trailer, erase and set slot header word if there were any hits vec->erase(iter2); if(nhitwords>0) { *iter3=0xe0000000; // 5 bits slot header (*iter3)|=(slot&0x1f)<<22; // 5 bits slot number (*iter3)|=(type&0xf) <<18; // 4 bits of module type (*iter3)|=nhitwords&0xffff; // 16 bits hit count (could be smaller) hitCount+=nhitwords/2; hitCountw+=nhitwords; } else { vec->erase(iter3); } } else if(((*iter2)>>27==0x10)&&((*(iter2+3))>>27==0x11)) { // block header with trailer 3 words away, erase slot if(triggerTime<0)triggerTime=(*(iter2+2)&0xffffff); vec->erase(iter2,iter2+4); } else if((*iter2)>>27==0x10) { // block header maybe with data, erase boilerplate, remember location nhitwords=0; slot=((*iter2)>>22)&0x1f; if(triggerTime<0)triggerTime=(*(iter2+2)&0xffffff); vec->erase(iter2+1,iter2+3); iter3=iter2; ++iter2; } else { // count data words nhitwords++; ++iter2; } } while (iter2!=vec->end()); break; case F1TDC32: case F1TDC48: do { if((*iter2)>>27==0x1f) { // filler word, erase vec->erase(iter2); } else if((*iter2)>>27==0x11) { // block trailer, erase and set slot header word if there were any hits vec->erase(iter2); if(nhitwords>0) { *iter3=0xe0000000; // 5 bits slot header (*iter3)|=(slot&0x1f)<<22; // 5 bits slot number (*iter3)|=(type&0xf) <<18; // 4 bits of module type (*iter3)|=nhitwords&0xffff; // 16 bits hit count (could be smaller) hitCount +=nhitwords; hitCountw+=nhitwords; } else { vec->erase(iter3); } } else if((*iter2)>>27==0x15) { // chip trailer, erase vec->erase(iter2); } else if(((*iter2)>>27==0x10) && ((*(iter2+5))>>27==0x11)) { // block header with block trailer 5 words away, erase slot if(triggerTime<0)triggerTime=(*(iter2+2)&0xffffff); vec->erase(iter2,iter2+6); } else if((*iter2)>>27==0x10) { // block header maybe with data, erase boilerplate, remember location nhitwords=0; slot=((*iter2)>>22)&0x1f; if(triggerTime<0)triggerTime=(*(iter2+2)&0xffffff); vec->erase(iter2+1,iter2+4); iter3=iter2; ++iter2; } else { // count data words nhitwords++; ++iter2; } } while (iter2!=vec->end()); break; default: cerr << "crate " << crate << " unknown crate type " << type << endl; break; } } // drop bank if no data left after compression, if(vec->size()<=0) { (*iter)->cutAndDelete(); } } // drop container banks that have no children left after compression // I think each data bank corresponds to a single block read evioDOMNodeListP containerList = eventTree.getNodeList(isContainer()); for(iter=containerList->begin(); iter!=containerList->end(); iter++) { if((*iter)->getSize()<=0) (*iter)->cutAndDelete(); } // change outermost bank num eventTree.root->num=2; // add trigger time bank to header bank (of segments) *(eventTree.getFirstNode(tagEquals(65313))) << evioDOMNode::createEvioDOMNode(3,0,(uint32_t*)(&triggerTime),1); } //------------------------------------------------------------------------------- //-------------------------------------------------------------------------------