// Include the ROOT base classes. #include #include #include #include #include #include "Demangle.hxx" #include "IMidasBankProxyRegistry.hxx" #include "IMidasEventParser.hxx" #include "ICOMETLog.hxx" #include "ICOMETRawEvent.hxx" ClassImp(COMET::ICOMETRawEvent); Int_t COMET::ICOMETRawEvent::fgRun = 0; //_____________________________________________________________________________ COMET::ICOMETRawEvent::ICOMETRawEvent() : IDataVector("",TCOMET_RAW_EVENT_TITLE), fEventSize(0), fHasUnpromotedBanks(true) { // Default constructor COMETTrace("ICOMETRawEvent: Default ctor @" << (void*) this); this->SetNameFromHeader(); } //_____________________________________________________________________________ COMET::ICOMETRawEvent::ICOMETRawEvent(const char* name, const IRawDataHeader& header /* = IRawDataHeader() */, const char* title /* = TCOMET_RAW_EVENT_TITLE */) : IDataVector(name,title), fHeader(header), fEventSize(0), fHasUnpromotedBanks(true) { // Normal constructor COMETTrace("COMET::ICOMETRawEvent: Standard ctor @" << (void*) this); this->SetNameFromHeader(); } //_____________________________________________________________________________ COMET::ICOMETRawEvent::ICOMETRawEvent(const COMET::IMidasEventParser& mep, const char* name, const char* title /* = TCOMET_RAW_EVENT_TITLE */) : IDataVector(name,title), fEventSize(mep.GetDataSize()), fHasUnpromotedBanks(true) { COMETTrace("COMET::ICOMETRawEvent: IMidasEventParser ctor @" << (void*) this); // Drop any existing banks this->Clear(); // Add in new banks and promote them. mep.BuildMidasBanks(*this); this->PromoteMidasBanks(false); // Special treatment for begin, end and messages for which context // isn't relevant. if ( mep.IsRunBegin() ) { fgRun = mep.GetSerialNumber(); fHeader.SetRecordType(IRawDataHeader::BeginRun); } else if ( mep.IsRunEnd() ) { fHeader.SetRecordType(IRawDataHeader::EndRun); } else if ( mep.IsMessage() ){ fHeader.SetRecordType(IRawDataHeader::Message); } else { fHeader.SetRecordType(IRawDataHeader::Data); } // Provide initial values for fields. These will be over written by the // context setters (if oaRawEvent is available and XRUN is found.). fHeader.SetRun(fgRun); fHeader.SetSeqNo(mep.GetSerialNumber()); fHeader.SetTimeStamp(mep.GetTimeStamp()); // Now look for context setters banks. bool contextSet = this->FillHeader(); // No context setting banks, use IMidasEventParser information. if (!contextSet) { static Bool_t warn_once = true; if (warn_once) { warn_once = false; COMETWarn( "\n\n\nCOMET::ICOMETRawEvent::ICOMETRawEvent Caution!!!\n" "\n" "Cannot find an XRUN bank which holds context information with which to \n" "set up the IRawDataHeader. Instead the information contained within a MIDAS \n" "event header will be used even though it is inadequate, for example it contains \n" "neither run or sub-run numbers. The IRawDataHeader will only have a run number\n" "once a begin or end of run record is encountered and will use the serial number\n" "in place of the event number. Apart from that it will be essentially empty.\n" ); } } // Finally use header to construct event name. this->SetNameFromHeader(); } //_____________________________________________________________________________ COMET::ICOMETRawEvent::~ICOMETRawEvent() { COMETTrace("COMET::ICOMETRawEvent: dtor @" << (void*) this); } //_____________________________________________________________________________ void COMET::ICOMETRawEvent::NotImplemented(const char* method) const { COMETWarn("The COMET::ICOMETRawEvent method " << method << " is blocked in order to prevent it accepting " << "objects that are not TMidasBanks"); } //_____________________________________________________________________________ bool COMET::ICOMETRawEvent::FillHeader() { bool contextSet(false); // Now look for context setters banks. COMET::IHandle midasBank; while ( midasBank = this->GetMidasBank("",midasBank) ) { if ( midasBank->IsContextSetter() ) { midasBank->SetContext(fHeader); contextSet = true; } } return contextSet; } void COMET::ICOMETRawEvent::Print(const Option_t* opt /* = "" */) const { COMETLog("The COMET::ICOMETRawEvent @" << (void*) this << std::dec << " Length (" << this->GetEventSize() << "+16hdr)bytes" << " (name: " << this->GetName() << ")"); fHeader.Print(opt); COMETLog("It contains the following " << this->size() << " TMidasBanks:-"); COMETLog(""); const_iterator itr(this->IDataVector::begin()), itrEnd(this->IDataVector::end()); for (; itr != itrEnd; ++itr) (*itr)->Print(opt); } //_____________________________________________________________________________ void COMET::ICOMETRawEvent::PromoteMidasBanks(Bool_t warn /* = true */) const { // Quit if nothing to do. if ( ! fHasUnpromotedBanks ) return; // Initialise. This includes getting a non-constant version of "this" // so that we can replace objects in a "logically constant" way. // Squeamish people may want to look away now. ICOMETRawEvent* this_nc = const_cast(this); IMidasBankProxyRegistry& rdbpr = IMidasBankProxyRegistry::Instance(); iterator itr(this_nc->IDataVector::begin()), itrEnd(this_nc->IDataVector::end()); for ( ; itr != itrEnd; ++itr ) { // Pick up the current object. IDatum* datum = *itr; // Make sure that nobody has sneaked in an object that does not // inherit from IMidasBank IMidasBank* rdb = dynamic_cast(datum); if ( ! rdb ) { COMETWarn("COMET::ICOMETRawEvent: Unexpectedly found an " << datum->ClassName() << " object. It cannot be promoted."); continue; } // Skip any that are already promoted if ( typeid(*rdb) != typeid(IMidasBank) ) continue; // We have found one to promote, make sure we have a proxy for it const char* bank_name = rdb->GetName(); IMidasBankProxy* rdbp = rdbpr.LookUp(bank_name); if (! rdbp ) { if ( warn ) COMETWarn("COMET::ICOMETRawEvent: Cannot find" << " a proxy for MIDAS bank " << bank_name << " object. It cannot be promoted."); continue; } // We have a proxy, create a replacement, transfer the data and delete // the old one. IMidasBank* new_rdb = rdbp->CreateMidasBank(NULL); COMETTrace("COMET::ICOMETRawEvent: Promoting IMidasBank to " << Tools::Demangle(typeid(new_rdb))); new_rdb->SetName(rdb->GetName()); rdb->DonateDataBuffer(new_rdb); *itr = new_rdb; // Finally delete the old object delete rdb; rdb = 0; } fHasUnpromotedBanks = false; } //_____________________________________________________________________________ void COMET::ICOMETRawEvent::SetNameFromHeader() { // Assign object a unique name based on header. std::ostringstream buffer; UInt_t run(fHeader.GetRun()); UInt_t seqNo(fHeader.GetSeqNo()); buffer << std::setfill('0'); if ( fHeader.IsBeginRun() ) { buffer << "rawevent.begin_run."; buffer << std::setw(5); if (run != COMET::IRawDataHeader::Invalid) buffer << run; else buffer << "invalid"; } else if ( fHeader.IsEndRun() ) { buffer << "rawevent.end_run."; buffer << std::setw(5); if (run != COMET::IRawDataHeader::Invalid) buffer << run; else buffer << "invalid"; } else if ( fHeader.IsMessage() ) { buffer << "rawevent.message."; buffer << std::setw(8); if (seqNo != COMET::IRawDataHeader::Invalid) buffer << seqNo; else buffer << "invalid"; } else { buffer << "rawevent."; buffer << std::setw(5); if (run != COMET::IRawDataHeader::Invalid) buffer << run; else buffer << "invalid"; buffer << "."; buffer << std::setw(8); if (seqNo != COMET::IRawDataHeader::Invalid) buffer << seqNo; else buffer << "invalid"; } this->SetName(buffer.str().c_str()); } void COMET::ICOMETRawEvent::ls(Option_t* opt) const { PromoteMidasBanks(); COMET::IData::ls(opt); TROOT::IncreaseDirLevel(); std::ios::fmtflags save = std::cout.flags(); TROOT::IndentLevel(); std::cout << "Run: " << fHeader.GetRun(); std::cout << " Sub-Run: " << fHeader.GetSubRun(); std::cout << " Sequence: " << fHeader.GetSeqNo(); std::cout << std::endl; TROOT::IndentLevel(); std::cout << "Stamp: " << fHeader.GetTimeStamp(); std::cout << " Record-type: "; if (fHeader.IsData()) std::cout << "data"; else if (fHeader.IsMessage()) std::cout << "message"; else if (fHeader.IsEndRun()) std::cout << "end-run"; else if (fHeader.IsBeginRun()) std::cout << "begin-run"; else std::cout << "invalid"; std::cout << " Context: " << std::hex << fHeader.GetContext(); std::cout << " Error: " << std::hex << fHeader.GetErrorCode(); std::cout << std::endl; TROOT::IndentLevel(); std::cout << "Trigger Word: " << std::hex << fHeader.GetTriggerWord(); std::cout << std::endl; if (fHeader.GetMCMSecond() != COMET::IRawDataHeader::Invalid) { TROOT::IndentLevel(); std::cout << std::dec << std::setw(11) << "MCM second: " << fHeader.GetMCMSecond() << " Sub-Second: " << fHeader.GetMCMSubSecond() << " Busy: " << fHeader.GetMCMTimeSinceBusy() << std::endl; } if (fHeader.GetP0DSecond() != COMET::IRawDataHeader::Invalid) { TROOT::IndentLevel(); std::cout << std::dec << std::setw(11) << "P0D second: " << fHeader.GetP0DSecond() << " Sub-Second: " << fHeader.GetP0DSubSecond() << " Busy: " << fHeader.GetP0DTimeSinceBusy() << std::endl; } if (fHeader.GetTPCSecond() != COMET::IRawDataHeader::Invalid) { TROOT::IndentLevel(); std::cout << std::dec << std::setw(11) << "TPC second: " << fHeader.GetTPCSecond() << " Sub-Second: " << fHeader.GetTPCSubSecond() << " Busy: " << fHeader.GetTPCTimeSinceBusy() << std::endl; } if (fHeader.GetFGDSecond() != COMET::IRawDataHeader::Invalid) { TROOT::IndentLevel(); std::cout << std::dec << std::setw(11) << "FGD second: " << fHeader.GetFGDSecond() << " Sub-Second: " << fHeader.GetFGDSubSecond() << " Busy: " << fHeader.GetFGDTimeSinceBusy() << std::endl; } if (fHeader.GetECalSecond() != COMET::IRawDataHeader::Invalid) { TROOT::IndentLevel(); std::cout << std::dec << std::setw(11) << "ECal second: " << fHeader.GetECalSecond() << " Sub-Second: " << fHeader.GetECalSubSecond() << " Busy: " << fHeader.GetECalTimeSinceBusy() << std::endl; } if (fHeader.GetSMRDSecond() != COMET::IRawDataHeader::Invalid) { TROOT::IndentLevel(); std::cout << std::dec << std::setw(11) << "SMRD second: " << fHeader.GetSMRDSecond() << " Sub-Second: " << fHeader.GetSMRDSubSecond() << " Busy: " << fHeader.GetSMRDTimeSinceBusy() << std::endl; } if (fHeader.GetINGRIDSecond() != COMET::IRawDataHeader::Invalid) { TROOT::IndentLevel(); std::cout << std::dec << std::setw(11) << "INGRID second: " << fHeader.GetINGRIDSecond() << " Sub-Second: " << fHeader.GetINGRIDSubSecond() << " Busy: " << fHeader.GetINGRIDTimeSinceBusy() << std::endl; } std::cout.fill(' '); std::cout.flags(save); for (const_iterator v = begin(); v != end(); ++v) { (*v)->ls(opt); }; TROOT::DecreaseDirLevel(); }