//////////////////////////////////////////////////////////// // $Id: ICOMETEvent.cxx,v 1.39 2011/12/07 21:53:26 mcgrew Exp $ // #include #include #include #include #include "ICOMETEvent.hxx" #include "IEventFolder.hxx" #include "IHitSelection.hxx" #include "IAlgorithmResult.hxx" #include "IOADatabase.hxx" #include "IDigitManager.hxx" #include "IDigitContainer.hxx" #include "IRawDataHeader.hxx" ClassImp(COMET::ICOMETEvent); ClassImp(COMET::ICOMETEvent::Header); COMET::ICOMETEvent::ICOMETEvent() { /// All other fields are self initializing. Build(); } COMET::ICOMETEvent::ICOMETEvent(const COMET::ICOMETContext& context) : fContext(context){ /// All other fields are self initializing. Build(); } // A utility macro to copy sub-detector information from the raw header into // the main event header. This also builds the partition code. If the MCM // time was not set, then this will copy the sub-detector clock into the MCM // clock (that's because the sub-detector board was acting as an MCM). #define COPYCLOCK(CLOCK,RAW,HEADER,PART) { \ if (RAW.Get##CLOCK##Second() != COMET::IRawDataHeader::Invalid) { \ PART |= COMET::ICOMETContext::k##CLOCK##ClockPresent; \ if (!(PART & COMET::ICOMETContext::kGlobalPartition)) { \ HEADER.fMCMSecond = RAW.Get##CLOCK##Second(); \ HEADER.fMCMSubSecond = RAW.Get##CLOCK##SubSecond(); \ HEADER.fMCMTimeSinceBusy = RAW.Get##CLOCK##TimeSinceBusy(); \ } \ HEADER.f##CLOCK##Second = RAW.Get##CLOCK##Second(); \ HEADER.f##CLOCK##SubSecond = RAW.Get##CLOCK##SubSecond(); \ HEADER.f##CLOCK##TimeSinceBusy = RAW.Get##CLOCK##TimeSinceBusy(); \ } \ } void COMET::ICOMETEvent::FillHeaderAndContext(const COMET::IRawDataHeader& rawHeader) { // Build the partition code and copy the clock data. int partition = 0; if (rawHeader.GetMCMSecond() != COMET::IRawDataHeader::Invalid) { partition |= COMET::ICOMETContext::kGlobalPartition; fHeader.fMCMSecond = rawHeader.GetMCMSecond(); fHeader.fMCMSubSecond = rawHeader.GetMCMSubSecond(); fHeader.fMCMTimeSinceBusy = rawHeader.GetMCMTimeSinceBusy(); } if (rawHeader.GetP0DSecond() != COMET::IRawDataHeader::Invalid) { // could set the MCM fields. COPYCLOCK(P0D, rawHeader, fHeader, partition); } if (rawHeader.GetTPCSecond() != COMET::IRawDataHeader::Invalid) { // could set the MCM fields. COPYCLOCK(TPC, rawHeader, fHeader, partition); } if (rawHeader.GetFGDSecond() != COMET::IRawDataHeader::Invalid) { // could set the MCM fields. COPYCLOCK(FGD, rawHeader, fHeader, partition); } if (rawHeader.GetECalSecond() != COMET::IRawDataHeader::Invalid) { // could set the MCM fields. COPYCLOCK(ECal, rawHeader, fHeader, partition); } if (rawHeader.GetSMRDSecond() != COMET::IRawDataHeader::Invalid) { // could set the MCM fields. COPYCLOCK(SMRD, rawHeader, fHeader, partition); } if (rawHeader.GetINGRIDSecond() != COMET::IRawDataHeader::Invalid) { // could set the MCM fields. COPYCLOCK(INGRID, rawHeader, fHeader, partition); } // Fill the rest of the header. fHeader.fRecordType = rawHeader.fRecordType; fHeader.fRunType = rawHeader.GetRunType(); fHeader.fTimeStamp = rawHeader.GetTimeStamp(); fHeader.fErrorCode = rawHeader.GetErrorCode(); fHeader.fTriggerWord = rawHeader.GetTriggerWord(); fHeader.fCTMTriggerPattern[0] = rawHeader.GetCTMTriggerPattern(0); fHeader.fCTMTriggerPattern[1] = rawHeader.GetCTMTriggerPattern(1); fHeader.fCTMTriggerPattern[2] = rawHeader.GetCTMTriggerPattern(2); fHeader.fFGDCTMTriggerPattern[0] = rawHeader.GetFGDCTMTriggerPattern(0); fHeader.fFGDCTMTriggerPattern[1] = rawHeader.GetFGDCTMTriggerPattern(1); fHeader.fFGDCTMTriggerPattern[2] = rawHeader.GetFGDCTMTriggerPattern(2); // Build the event context. fContext.SetRun(rawHeader.GetRun()); // Set the event number in the context. This will usually be provided by // the trigger word. If that doesn't work, then it will come from the // midas sequence number (rawHeader.GetSeqNo()). if (fHeader.GetEventNumber() == Header::Invalid && fHeader.IsData()) { static int ErrorCount = 0; if (ErrorCount<4) { COMETError("Incomplete conversion from MIDAS to oaEvent," << " check oaRawEvent availability."); ++ErrorCount; } fContext.SetEvent(rawHeader.GetSeqNo()); } else { fContext.SetEvent(fHeader.GetEventNumber()); } // Set the spill number if we have it (could be invalid). fContext.SetSpill(fHeader.GetSpillNumber()); // Set the context time. This will usually come from the XRUN bank time, // but if that is not available, then the MIDAS time stamp from the // rawHeader will be used. Note that the MIDAS time stamp is the computer // time of when the event was written to disk, not the time that the event // happened. fContext.SetTimeStamp(rawHeader.GetTimeStamp()); // Set the sub-run number. This should come from the rawHeader, but since // the DAQ doesn't know what sub-run it is writing, we need to read the // number from the file name that the DAQ generated when it changed // sub-runs. This is kludged around by providing a preliminary context // with the raw event header. The preliminary context is filled from the // MIDAS file name. if (rawHeader.GetSubRun() != COMET::IRawDataHeader::Invalid) { fContext.SetSubRun(rawHeader.GetSubRun()); } // Set the partition code. fContext.SetPartition(partition); } // Note that information in the raw event overrides information in the // preliminary context. The preliminary context is used as a back-up for any // context not in the raw header. COMET::ICOMETEvent::ICOMETEvent(const COMET::ICOMETContext& prelimContext, COMET::ICOMETRawEvent* raw) { const COMET::IRawDataHeader& rawHeader = raw->GetHeader(); fContext.SetSubRun(prelimContext.GetSubRun()); FillHeaderAndContext(rawHeader); // Build the rest of the event structure. Build(); // Finally, add the raw data. AddRaw(raw); } #undef COPYCLOCK COMET::ICOMETEvent::~ICOMETEvent() { COMET::IEventFolder::RemoveEvent(this); } void COMET::ICOMETEvent::Build(void) { if (GetRunId() == COMET::ICOMETContext::Invalid || GetEventId() == COMET::ICOMETContext::Invalid) { SetName("event.uninitialized"); } else { std::stringstream name; name << "event." << std::setw(5) << std::setfill('0') << GetRunId() << std::setw(8) << std::setfill('0') << GetEventId(); SetName(name.str().c_str()); } if (!FindDatum("digits")) { AddDatum(new COMET::IDataVector("digits","Uncalibrated digit data")); } if (!FindDatum("hits")) { AddDatum(new COMET::IDataVector("hits","Calibrated hit data")); } if (!FindDatum("fits")) { AddDatum(new COMET::IDataVector("fits","Fit results from reconstruction")); } Register(); } const unsigned int COMET::ICOMETEvent::Header::Invalid = 0xDEADBEEF; COMET::ICOMETEvent::Header::~Header() {} COMET::ICOMETEvent::Header::Header() { fRecordType = Data; fTimeStamp = Invalid; fRunType = Invalid; fErrorCode = Invalid; fTriggerWord = Invalid; fMCMSecond = Invalid; fMCMSubSecond = Invalid; fMCMTimeSinceBusy = Invalid; fP0DSecond = Invalid; fP0DSubSecond = Invalid; fP0DTimeSinceBusy = Invalid; fTPCSecond = Invalid; fTPCSubSecond = Invalid; fTPCTimeSinceBusy = Invalid; fFGDSecond = Invalid; fFGDSubSecond = Invalid; fFGDTimeSinceBusy = Invalid; fECalSecond = Invalid; fECalSubSecond = Invalid; fECalTimeSinceBusy = Invalid; fSMRDSecond = Invalid; fSMRDSubSecond = Invalid; fSMRDTimeSinceBusy = Invalid; fINGRIDSecond = Invalid; fINGRIDSubSecond = Invalid; fINGRIDTimeSinceBusy = Invalid; fCTMTriggerPattern[0] = Invalid; fCTMTriggerPattern[1] = Invalid; fCTMTriggerPattern[2] = Invalid; fFGDCTMTriggerPattern[0] = Invalid; fFGDCTMTriggerPattern[1] = Invalid; fFGDCTMTriggerPattern[2] = Invalid; } void COMET::ICOMETEvent::ls(Option_t* opt) const { COMET::IDatum::ls(opt); TROOT::IncreaseDirLevel(); TROOT::IndentLevel(); std::cout << "Context: " << GetContext() << std::endl; std::ios::fmtflags save = std::cout.flags(); 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 << " Error: " << std::hex << fHeader.GetErrorCode(); std::cout << std::endl; TROOT::IndentLevel(); std::cout << "Trigger Word::"; std::cout << std::hex << std::setfill('0') << std::setw(16) << fHeader.GetTriggerWord(); std::cout << " bits: " << std::hex << fHeader.GetTriggerBits(); std::cout << " spill: " << std::dec << fHeader.GetSpillNumber(); std::cout << " event: " << fHeader.GetEventNumber(); std::cout << std::endl; std::cout.fill(' '); std::cout.flags(save); 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; } TROOT::IndentLevel(); std::cout << "TFB CTM " << std::hex << std::setfill('0') << std::setw(16) << fHeader.GetCTMTriggerPattern(0) << std::setw(16) << fHeader.GetCTMTriggerPattern(1) << std::setw(16) << fHeader.GetCTMTriggerPattern(2) << std::endl; std::cout.fill(' '); TROOT::IndentLevel(); std::cout << "FGD CTM " << std::hex << std::setfill('0') << std::setw(16) << fHeader.GetFGDCTMTriggerPattern(0) << std::setw(16) << fHeader.GetFGDCTMTriggerPattern(1) << std::setw(16) << fHeader.GetFGDCTMTriggerPattern(2) << std::endl; std::cout.fill(' '); if (GetGeometryHash().Valid()) { TROOT::IndentLevel(); std::cout << "Geometry: " << GetGeometryHash() << std::endl; } if (GetAlignmentId().Valid()) { TROOT::IndentLevel(); std::cout << "Alignment: " << GetAlignmentId() << std::endl; } std::cout.flags(save); for (const_iterator v = begin(); v != end(); ++v) { (*v)->ls(opt); } std::cout.fill(' '); std::cout.flags(save); TROOT::DecreaseDirLevel(); } void COMET::ICOMETEvent::Register(void) { COMET::IEventFolder::RegisterEvent(this); } COMET::IHandle COMET::ICOMETEvent::GetDigits(const char* name) { return COMET::IOADatabase::Get().Digits().CacheDigits(*this,name); } COMET::IHandle COMET::ICOMETEvent::GetHitSelection(const char* name) const { std::string hitName("hits/"); hitName += name; COMET::IHandle hitsData = Get(hitName.c_str()); if (!hitsData) return COMET::IHandle(); return Get(hitName.c_str()); } COMET::IHandle COMET::ICOMETEvent::GetFit(const char* name) const { std::string fitName = "~/fits/"; return Get(fitName + name); } void COMET::ICOMETEvent::AddFit(COMET::IAlgorithmResult* fit, const char* name) { COMET::IHandle fits = Get("~/fits"); fits->AddDatum(fit,name); } void COMET::ICOMETEvent::AddFit(COMET::IHandle fit, const char* name) { COMET::IHandle fits = Get("~/fits"); fit.Release(); fits->AddDatum(GetPointer(fit),name); } void COMET::ICOMETEvent::AddRaw(COMET::ICOMETRawEvent* rawEvent) { COMET::IHandle raw = Get("~/raw"); if (!raw) { AddDatum(new COMET::IDataVector("raw","Raw MIDAS data for this event.")); raw = Get("~/raw"); } raw->AddDatum(rawEvent); } COMET::IHandle COMET::ICOMETEvent::GetRaw(int i) const { if (i<0) return COMET::IHandle(); COMET::IHandle raw = Get("~/raw"); if (!raw) return COMET::IHandle(); if ((int) raw->size()<=i) return COMET::IHandle(); return COMET::IHandle(raw->At(i), false); }