SpecTcl Application note: Checking gates from within the user's Unpacker code. DISCLAIMER: The code fragments in this application note are believed to be correct but have not been tested. The concepts have been tested by other users of the system, however. Some modification of the actual fragments may be required to get them work. Theory: The event analysis pipeline is invoked from a CAnalyzer object. Each operator() of the CAnalyzer is passed a reference to the analyzer which invoked it. Each CAnalyzer has a CEventSink attached to it as well. Lists of events are sent to this sink by the analyzer. In SpecTcl, The sink is a CHistogrammer which in turn contains a dictionary of all of the gates currently defined. One can query the dictionary for a gate by name and receive an object which is a handle (CGateContainer) for the gate. The gate container is invariant under changes of the gate it contains, it therefore only needs to be fetched once. The Gate container is a pointer like class allowing all of the functionality of gates themselves to be accessed. Note that due to gate caching it will be necessary to clear the gate prior to checking it. Strategy: At SpecTcl startup, create a gate which is always TRUE (or FALSE if you prefer to disable the your gate until it is well defined). Hold a pointer to the container of this gate and use that within the event processor to reference the gate as desired. Details. Add: (for reference, headers below are in the Include subdir of the SpecTcl distribution you are using). #include #include #include #include To MySpecTclApp.h Create and register the gate in CreateHistogrammer() as follows; add after: CTclGrammerApp::CreateHistogrammer(); CHistogrammer* pHist = getHistogrammer(); CGateFactory Factory(pHist); // Create a gate factory CGate* pMyGate=Factory.CreateTrueGate(); // Make a gate.. always true. pHist->AddGate("NameOfGate", // Enter gate in histogrammer CGatePackage::AssignId(), // Change first parameter to *pGate); // match your name. Now the processor which wants to use the gate must: 1. Add a gate container to reference the gate through. 1. Implement OnAttach to get a handle to the gate. 2. Use the gate in its operator() member: #include class MyProcessor : public CEventProcessor { CGateContainer* m_pMyGate; CHistogrammer* m_pHistogrammer; public: ... virtual Bool_t OnAttach(CAnalyzer& rAnalyzer); ... }; Bool_t MyProcessor::OnAttach(CAnalyzer& rAnalyzer) { m_pHistogrammer = (CHistogrammer*)gpEventSink; m_pMyGate = m_pHistogrammer->FindGate("NameOfGate"); // Use your name. if(!m_pMyGate) { cerr << "Unable to find my gate in the histogrammer's"; cerr << "Gate dictionary. Failing registration of MyProcessor"; cerr << endl; return kfFALSE; } return kfTRUE; } Bool_t MyProcessor::operator()(const Address_t pEvent, CEvent& rEvent, CAnalyzer& rAnalyzer, CBufferDecoder& rDecoder) { ... // Check the gate based on the current contents of rEvent: // Since your gate may be a compound gate and gate resets are not // recursive... we need to clear >all< the gates known to the histogrammer. // It is important that by the time this code is executed the // parameters this gate depends on have already been unpacked into rEvent // otherwise the gate will evaluate false!!! CGateDictionaryIterator p = m_pHistogrammer->GateBegin(); CGateDictionaryIterator e = m_pHistogrammer->GateEnd(); for(;p != e; p++) { p->second->Reset(); } // Now evaluate the gate: if(m_pMyGate->operator()(rEvent)) { // Gate was made. ... } else { // Gate was not made. ... } ... }