ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/grimes/L1Menu/src/TriggerMenu.cpp
Revision: 1.1
Committed: Sun May 5 20:37:32 2013 UTC (12 years ago) by grimes
Branch: MAIN
Log Message:
First draft of the L1 Trigger rate estimation code

File Contents

# User Rev Content
1 grimes 1.1 #include "l1menu/TriggerMenu.h"
2    
3     #include <stdexcept>
4     #include <fstream>
5     #include <sstream>
6     #include <iostream>
7     #include "l1menu/ITrigger.h"
8    
9     namespace // Use the unnamed namespace for things only used in this file
10     {
11     const char* whitespace="\x20\x09\x0D\x0A";
12    
13     float convertStringToFloat( const std::string& string )
14     {
15     float returnValue;
16     std::stringstream stringConverter( string );
17     stringConverter >> returnValue;
18     if( stringConverter.fail() || !stringConverter.eof() ) throw std::runtime_error( "Unable to convert \""+string+"\" to a float" );
19     return returnValue;
20     }
21    
22     std::vector<std::string> splitByWhitespace( const std::string& stringToSplit )
23     {
24     std::vector<std::string> returnValue;
25    
26     size_t currentPosition=0;
27     size_t nextDelimeter=0;
28     do
29     {
30     // Skip over any leading whitespace
31     size_t nextElementStart=stringToSplit.find_first_not_of( whitespace, currentPosition );
32     if( nextElementStart!=std::string::npos ) currentPosition=nextElementStart;
33    
34     // Find the next whitespace or comma and subtract everything up to that point
35     nextDelimeter=stringToSplit.find_first_of( whitespace, currentPosition );
36     std::string element=stringToSplit.substr( currentPosition, nextDelimeter-currentPosition );
37     returnValue.push_back(element);
38    
39     // skip over any trailing whitespace
40     nextElementStart=stringToSplit.find_first_not_of( whitespace, nextDelimeter );
41     if( nextElementStart!=std::string::npos ) currentPosition=nextElementStart;
42     else nextDelimeter=std::string::npos;
43    
44     } while( nextDelimeter!=std::string::npos );
45    
46     return returnValue;
47     }
48    
49     } // end of the unnamed namespace
50    
51    
52     l1menu::TriggerMenu::TriggerMenu( const TriggerTable& table ) : triggerTable_(table)
53     {
54     // No operation besides the initialiser list
55     }
56    
57     l1menu::TriggerMenu::~TriggerMenu()
58     {
59     // Because I've just held on to the raw pointers, I need to run through
60     // and delete them all.
61     for( std::vector<l1menu::ITrigger*>::iterator iTrigger=triggers_.begin(); iTrigger!=triggers_.end(); ++iTrigger )
62     {
63     delete *iTrigger;
64     }
65     }
66    
67     l1menu::TriggerMenu::TriggerMenu( const l1menu::TriggerMenu& otherTriggerMenu )
68     : triggerTable_(otherTriggerMenu.triggerTable_)
69     {
70     for( std::vector<l1menu::ITrigger*>::const_iterator iTrigger=otherTriggerMenu.triggers_.begin(); iTrigger!=otherTriggerMenu.triggers_.end(); ++iTrigger )
71     {
72     l1menu::ITrigger& sourceTrigger=**iTrigger;
73    
74     std::auto_ptr<l1menu::ITrigger> pNewTrigger=triggerTable_.copyTrigger( sourceTrigger );
75     triggers_.push_back( pNewTrigger.release() );
76     }
77    
78     // Make sure triggerResults_ is always the same size as triggers_
79     triggerResults_.resize( triggers_.size() );
80     }
81    
82     l1menu::TriggerMenu& l1menu::TriggerMenu::operator=( const l1menu::TriggerMenu& otherTriggerMenu )
83     {
84     triggerTable_=otherTriggerMenu.triggerTable_;
85    
86     //
87     // First clean up whatever triggers I had before
88     //
89     for( std::vector<l1menu::ITrigger*>::iterator iTrigger=triggers_.begin(); iTrigger!=triggers_.end(); ++iTrigger )
90     {
91     delete *iTrigger;
92     }
93     triggers_.clear();
94    
95     //
96     // Now copy the triggers from the other menu
97     //
98     for( std::vector<l1menu::ITrigger*>::const_iterator iTrigger=otherTriggerMenu.triggers_.begin(); iTrigger!=otherTriggerMenu.triggers_.end(); ++iTrigger )
99     {
100     l1menu::ITrigger& sourceTrigger=**iTrigger;
101    
102     std::auto_ptr<l1menu::ITrigger> pNewTrigger=triggerTable_.copyTrigger( sourceTrigger );
103     triggers_.push_back( pNewTrigger.release() );
104     }
105    
106     // Make sure triggerResults_ is always the same size as triggers_
107     triggerResults_.resize( triggers_.size() );
108    
109     return *this;
110     }
111    
112     bool l1menu::TriggerMenu::addTrigger( const std::string& triggerName )
113     {
114     std::auto_ptr<l1menu::ITrigger> pNewTrigger=triggerTable_.getTrigger( triggerName );
115     if( pNewTrigger.get()==NULL ) return false;
116    
117     triggers_.push_back( pNewTrigger.get() );
118    
119     // If everything has gone okay so far, the pointer will be in the vector
120     // and I can get rid of the auto_ptr. The destructor of this class will
121     // take care of deleting the pointers.
122     pNewTrigger.release();
123    
124     // Make sure triggerResults_ is always the same size as triggers_
125     triggerResults_.resize( triggers_.size() );
126     return true;
127     }
128    
129     bool l1menu::TriggerMenu::addTrigger( const std::string& triggerName, unsigned int version )
130     {
131     std::auto_ptr<l1menu::ITrigger> pNewTrigger=triggerTable_.getTrigger( triggerName, version );
132     if( pNewTrigger.get()==NULL ) return false;
133    
134     triggers_.push_back( pNewTrigger.get() );
135    
136     // If everything has gone okay so far, the pointer will be in the vector
137     // and I can get rid of the auto_ptr. The destructor of this class will
138     // take care of deleting the pointers.
139     pNewTrigger.release();
140    
141     // Make sure triggerResults_ is always the same size as triggers_
142     triggerResults_.resize( triggers_.size() );
143     return true;
144     }
145    
146     size_t l1menu::TriggerMenu::numberOfTriggers() const
147     {
148     return triggers_.size();
149     }
150    
151     l1menu::ITrigger& l1menu::TriggerMenu::getTrigger( size_t position )
152     {
153     if( position>triggers_.size() ) throw std::range_error( "Trigger requested that does not exist in the menu" );
154    
155     return *triggers_[position];
156     }
157    
158     const l1menu::ITrigger& l1menu::TriggerMenu::getTrigger( size_t position ) const
159     {
160     if( position>triggers_.size() ) throw std::range_error( "Trigger requested that does not exist in the menu" );
161    
162     return *triggers_[position];
163     }
164    
165     bool l1menu::TriggerMenu::apply( const L1Analysis::L1AnalysisDataFormat& event ) const
166     {
167     bool atLeastOneTriggerHasFired=false;
168    
169     for( size_t triggerNumber=0; triggerNumber<triggers_.size(); ++triggerNumber )
170     {
171     bool result=triggers_[triggerNumber]->apply(event);
172     // triggerResults_[triggerNumber]=result;
173     if( result ) atLeastOneTriggerHasFired=true;
174     }
175    
176     return atLeastOneTriggerHasFired;
177     }
178    
179     void l1menu::TriggerMenu::loadMenuFromFile( const std::string& filename )
180     {
181     std::ifstream file( filename );
182     if( !file.is_open() ) throw std::runtime_error( "Unable to open file "+filename );
183    
184     loadMenuInOldFormat( file );
185     }
186    
187     void l1menu::TriggerMenu::loadMenuInOldFormat( std::ifstream& file )
188     {
189     const size_t bufferSize=200;
190     char buffer[bufferSize];
191    
192     while( file.good() )
193     {
194     try
195     {
196     // Get one line at a time
197     file.getline( buffer, bufferSize );
198    
199     // split the line by whitespace into columns
200     std::vector<std::string> tableColumns=::splitByWhitespace( buffer );
201    
202     if( tableColumns.size()==1 && tableColumns[0].empty() ) continue; // Allow blank lines without giving a warning
203     if( tableColumns.size()!=12 ) throw std::runtime_error( "The line does not have the correct number of columns" );
204    
205     float prescale=::convertStringToFloat( tableColumns[2] );
206     if( prescale!=0 )
207     {
208     if( addTrigger( tableColumns[0] ) ) // Try and create a trigger with the name supplied
209     {
210     l1menu::ITrigger& newTrigger=*(triggers_.back());
211    
212     // Try and set all of the relevant parameters. I know not all triggers have these parameters
213     // so wrap in individual try/catch blocks.
214     try{ newTrigger.parameter("threshold1")=::convertStringToFloat( tableColumns[3] ); }
215     catch( std::exception& error ) { } // Do nothing, just try and convert the other parameters
216    
217     try{ newTrigger.parameter("threshold2")=::convertStringToFloat( tableColumns[4] ); }
218     catch( std::exception& error ) { } // Do nothing, just try and convert the other parameters
219    
220     try{ newTrigger.parameter("threshold3")=::convertStringToFloat( tableColumns[5] ); }
221     catch( std::exception& error ) { } // Do nothing, just try and convert the other parameters
222    
223     try{ newTrigger.parameter("threshold4")=::convertStringToFloat( tableColumns[6] ); }
224     catch( std::exception& error ) { } // Do nothing, just try and convert the other parameters
225    
226     try{ newTrigger.parameter("etaCut")=::convertStringToFloat( tableColumns[7] ); }
227     catch( std::exception& error ) { } // Do nothing, just try and convert the other parameters
228    
229     try{ newTrigger.parameter("muonQuality")=::convertStringToFloat( tableColumns[8] ); }
230     catch( std::exception& error ) { } // Do nothing, just try and convert the other parameters
231    
232     } // end of "if able to add trigger"
233     else std::cout << "The trigger \"" << tableColumns[0] << "\" is not registered in the trigger table" << std::endl;
234     } // end of "if( prescale!=0 )"
235     } // end of try block
236     catch( std::runtime_error& exception )
237     {
238     std::cout << "Some error occured while processing the line \"" << buffer << "\":" << exception.what() << std::endl;
239     }
240     }
241     }