ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/grimes/L1Menu/src/TriggerMenu.cpp
Revision: 1.7
Committed: Mon Jun 24 14:47:38 2013 UTC (11 years, 10 months ago) by grimes
Branch: MAIN
Changes since 1.6: +2 -12 lines
Log Message:
Changes to the way trigger rates are returned

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 grimes 1.7 #include "l1menu/tools/tools.h"
9 grimes 1.1
10     namespace // Use the unnamed namespace for things only used in this file
11     {
12 grimes 1.3 /// ASCII codes of characters that are considered whitespace (space, tab, carriage return, line feed).
13 grimes 1.1 const char* whitespace="\x20\x09\x0D\x0A";
14    
15 grimes 1.3 /** @brief Converts the entire string to a float or throws an exception. */
16 grimes 1.1 float convertStringToFloat( const std::string& string )
17     {
18     float returnValue;
19     std::stringstream stringConverter( string );
20     stringConverter >> returnValue;
21     if( stringConverter.fail() || !stringConverter.eof() ) throw std::runtime_error( "Unable to convert \""+string+"\" to a float" );
22     return returnValue;
23     }
24    
25 grimes 1.3 /** @brief Splits a string into individual parts delimited by whitespace. */
26 grimes 1.1 std::vector<std::string> splitByWhitespace( const std::string& stringToSplit )
27     {
28     std::vector<std::string> returnValue;
29    
30     size_t currentPosition=0;
31     size_t nextDelimeter=0;
32     do
33     {
34     // Skip over any leading whitespace
35     size_t nextElementStart=stringToSplit.find_first_not_of( whitespace, currentPosition );
36     if( nextElementStart!=std::string::npos ) currentPosition=nextElementStart;
37    
38 grimes 1.3 // Find the next whitespace and subtract everything up to that point
39 grimes 1.1 nextDelimeter=stringToSplit.find_first_of( whitespace, currentPosition );
40     std::string element=stringToSplit.substr( currentPosition, nextDelimeter-currentPosition );
41     returnValue.push_back(element);
42    
43     // skip over any trailing whitespace
44     nextElementStart=stringToSplit.find_first_not_of( whitespace, nextDelimeter );
45     if( nextElementStart!=std::string::npos ) currentPosition=nextElementStart;
46     else nextDelimeter=std::string::npos;
47    
48     } while( nextDelimeter!=std::string::npos );
49    
50     return returnValue;
51     }
52    
53     } // end of the unnamed namespace
54    
55    
56 grimes 1.3 l1menu::TriggerMenu::TriggerMenu() : triggerTable_( l1menu::TriggerTable::instance() )
57 grimes 1.1 {
58     // No operation besides the initialiser list
59     }
60    
61     l1menu::TriggerMenu::~TriggerMenu()
62     {
63 grimes 1.3 // No operation since I switched from raw pointers to unique_ptr.
64 grimes 1.1 }
65    
66 grimes 1.3 l1menu::TriggerMenu::TriggerMenu( const TriggerMenu& otherTriggerMenu )
67 grimes 1.1 : triggerTable_(otherTriggerMenu.triggerTable_)
68     {
69 grimes 1.3 for( std::vector< std::unique_ptr<l1menu::ITrigger> >::const_iterator iTrigger=otherTriggerMenu.triggers_.begin(); iTrigger!=otherTriggerMenu.triggers_.end(); ++iTrigger )
70 grimes 1.1 {
71     l1menu::ITrigger& sourceTrigger=**iTrigger;
72    
73 grimes 1.3 triggers_.push_back( std::move(triggerTable_.copyTrigger(sourceTrigger)) );
74 grimes 1.1 }
75    
76     // Make sure triggerResults_ is always the same size as triggers_
77     triggerResults_.resize( triggers_.size() );
78     }
79    
80 grimes 1.3 l1menu::TriggerMenu::TriggerMenu( TriggerMenu&& otherTriggerMenu ) noexcept
81     : triggerTable_(otherTriggerMenu.triggerTable_), triggers_( std::move(otherTriggerMenu.triggers_) ),
82     triggerResults_( std::move(otherTriggerMenu.triggerResults_) )
83     {
84     // No operation besides the initialiser list
85     }
86    
87 grimes 1.1 l1menu::TriggerMenu& l1menu::TriggerMenu::operator=( const l1menu::TriggerMenu& otherTriggerMenu )
88     {
89     //
90     // First clean up whatever triggers I had before
91     //
92     triggers_.clear();
93    
94     //
95     // Now copy the triggers from the other menu
96     //
97 grimes 1.3 for( std::vector< std::unique_ptr<l1menu::ITrigger> >::const_iterator iTrigger=otherTriggerMenu.triggers_.begin(); iTrigger!=otherTriggerMenu.triggers_.end(); ++iTrigger )
98 grimes 1.1 {
99     l1menu::ITrigger& sourceTrigger=**iTrigger;
100    
101 grimes 1.3 triggers_.push_back( std::move(triggerTable_.copyTrigger(sourceTrigger)) );
102 grimes 1.1 }
103    
104     // Make sure triggerResults_ is always the same size as triggers_
105     triggerResults_.resize( triggers_.size() );
106    
107     return *this;
108     }
109    
110 grimes 1.3 l1menu::TriggerMenu& l1menu::TriggerMenu::operator=( l1menu::TriggerMenu&& otherTriggerMenu ) noexcept
111     {
112     triggers_=std::move( otherTriggerMenu.triggers_ );
113     triggerResults_=std::move(otherTriggerMenu.triggerResults_);
114    
115     return *this;
116     }
117    
118 grimes 1.5 l1menu::ITrigger& l1menu::TriggerMenu::addTrigger( const std::string& triggerName )
119 grimes 1.1 {
120 grimes 1.3 std::unique_ptr<l1menu::ITrigger> pNewTrigger=triggerTable_.getTrigger( triggerName );
121 grimes 1.5 if( pNewTrigger.get()==NULL ) throw std::range_error( "Trigger requested that does not exist" );
122 grimes 1.1
123 grimes 1.3 triggers_.push_back( std::move(pNewTrigger) );
124 grimes 1.1
125     // Make sure triggerResults_ is always the same size as triggers_
126     triggerResults_.resize( triggers_.size() );
127 grimes 1.5 return *triggers_.back();
128 grimes 1.1 }
129    
130 grimes 1.5 l1menu::ITrigger& l1menu::TriggerMenu::addTrigger( const std::string& triggerName, unsigned int version )
131 grimes 1.1 {
132 grimes 1.3 std::unique_ptr<l1menu::ITrigger> pNewTrigger=triggerTable_.getTrigger( triggerName, version );
133 grimes 1.5 if( pNewTrigger.get()==NULL ) throw std::range_error( "Trigger requested that does not exist" );
134 grimes 1.1
135 grimes 1.3 triggers_.push_back( std::move(pNewTrigger) );
136 grimes 1.1
137     // Make sure triggerResults_ is always the same size as triggers_
138     triggerResults_.resize( triggers_.size() );
139 grimes 1.5 return *triggers_.back();
140 grimes 1.1 }
141    
142     size_t l1menu::TriggerMenu::numberOfTriggers() const
143     {
144     return triggers_.size();
145     }
146    
147     l1menu::ITrigger& l1menu::TriggerMenu::getTrigger( size_t position )
148     {
149     if( position>triggers_.size() ) throw std::range_error( "Trigger requested that does not exist in the menu" );
150    
151     return *triggers_[position];
152     }
153    
154     const l1menu::ITrigger& l1menu::TriggerMenu::getTrigger( size_t position ) const
155     {
156     if( position>triggers_.size() ) throw std::range_error( "Trigger requested that does not exist in the menu" );
157    
158     return *triggers_[position];
159     }
160    
161 grimes 1.3 std::unique_ptr<l1menu::ITrigger> l1menu::TriggerMenu::getTriggerCopy( size_t position ) const
162     {
163     if( position>triggers_.size() ) throw std::range_error( "Trigger requested that does not exist in the menu" );
164    
165     return triggerTable_.copyTrigger(*triggers_[position]);
166     }
167    
168     bool l1menu::TriggerMenu::apply( const l1menu::IEvent& event ) const
169 grimes 1.1 {
170     bool atLeastOneTriggerHasFired=false;
171    
172     for( size_t triggerNumber=0; triggerNumber<triggers_.size(); ++triggerNumber )
173     {
174     bool result=triggers_[triggerNumber]->apply(event);
175     // triggerResults_[triggerNumber]=result;
176     if( result ) atLeastOneTriggerHasFired=true;
177     }
178    
179     return atLeastOneTriggerHasFired;
180     }
181    
182     void l1menu::TriggerMenu::loadMenuFromFile( const std::string& filename )
183     {
184 grimes 1.2 std::ifstream file( filename.c_str() );
185 grimes 1.1 if( !file.is_open() ) throw std::runtime_error( "Unable to open file "+filename );
186    
187     loadMenuInOldFormat( file );
188     }
189    
190     void l1menu::TriggerMenu::loadMenuInOldFormat( std::ifstream& file )
191     {
192     const size_t bufferSize=200;
193     char buffer[bufferSize];
194    
195     while( file.good() )
196     {
197     try
198     {
199     // Get one line at a time
200     file.getline( buffer, bufferSize );
201    
202     // split the line by whitespace into columns
203     std::vector<std::string> tableColumns=::splitByWhitespace( buffer );
204    
205     if( tableColumns.size()==1 && tableColumns[0].empty() ) continue; // Allow blank lines without giving a warning
206     if( tableColumns.size()!=12 ) throw std::runtime_error( "The line does not have the correct number of columns" );
207    
208     float prescale=::convertStringToFloat( tableColumns[2] );
209     if( prescale!=0 )
210     {
211 grimes 1.5 std::string triggerName=tableColumns[0];
212    
213     try
214 grimes 1.1 {
215 grimes 1.4 //std::cout << "Added trigger \"" << tableColumns[0] << "\"" << std::endl;
216 grimes 1.5 l1menu::ITrigger& newTrigger=addTrigger( triggerName ); // Try and create a trigger with the name supplied
217 grimes 1.1
218     // Try and set all of the relevant parameters. I know not all triggers have these parameters
219     // so wrap in individual try/catch blocks.
220     try{ newTrigger.parameter("threshold1")=::convertStringToFloat( tableColumns[3] ); }
221     catch( std::exception& error ) { } // Do nothing, just try and convert the other parameters
222    
223     try{ newTrigger.parameter("threshold2")=::convertStringToFloat( tableColumns[4] ); }
224     catch( std::exception& error ) { } // Do nothing, just try and convert the other parameters
225    
226     try{ newTrigger.parameter("threshold3")=::convertStringToFloat( tableColumns[5] ); }
227     catch( std::exception& error ) { } // Do nothing, just try and convert the other parameters
228    
229     try{ newTrigger.parameter("threshold4")=::convertStringToFloat( tableColumns[6] ); }
230     catch( std::exception& error ) { } // Do nothing, just try and convert the other parameters
231    
232 grimes 1.5 float etaOrRegionCut=::convertStringToFloat( tableColumns[7] );
233     // For most triggers, I can just try and set both the etaCut and regionCut parameters
234     // with this value. If it doesn't have either of the parameters just catch the exception
235     // and nothing will happen. Some cross triggers however have both, and need to set them
236     // both from this value which requires a conversion. Most cross triggers expect this
237     // value to be the regionCut, except for L1_SingleMu_CJet which expects it as the etaCut.
238     if( triggerName=="L1_SingleMu_CJet" )
239     {
240 grimes 1.6 newTrigger.parameter("leg1etaCut")=etaOrRegionCut;
241 grimes 1.7 newTrigger.parameter("leg2regionCut")=l1menu::tools::convertEtaCutToRegionCut( etaOrRegionCut );
242 grimes 1.5 }
243     else if( triggerName=="L1_SingleIsoEG_CJet" )
244     {
245 grimes 1.6 newTrigger.parameter("leg1regionCut")=etaOrRegionCut;
246     newTrigger.parameter("leg2regionCut")=etaOrRegionCut;
247 grimes 1.5 }
248     else
249     {
250     // Any remaining triggers should only have one of these parameters and won't
251     // need conversion. I'll just try and set them both, not a problem if one fails.
252     try{ newTrigger.parameter("etaCut")=etaOrRegionCut; }
253     catch( std::exception& error ) { } // Do nothing, just try and convert the other parameters
254    
255     try{ newTrigger.parameter("regionCut")=etaOrRegionCut; }
256     catch( std::exception& error ) { } // Do nothing, just try and convert the other parameters
257     }
258 grimes 1.1
259     try{ newTrigger.parameter("muonQuality")=::convertStringToFloat( tableColumns[8] ); }
260     catch( std::exception& error ) { } // Do nothing, just try and convert the other parameters
261    
262     } // end of "if able to add trigger"
263 grimes 1.5 catch( std::exception& error )
264     {
265     std::cerr << "Unable to add trigger \"" << tableColumns[0] << "\" because: " << error.what() << std::endl;
266     }
267 grimes 1.1 } // end of "if( prescale!=0 )"
268     } // end of try block
269     catch( std::runtime_error& exception )
270     {
271     std::cout << "Some error occured while processing the line \"" << buffer << "\":" << exception.what() << std::endl;
272     }
273     }
274     }