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

# Content
1 #include "l1menu/TriggerMenu.h"
2
3 #include <stdexcept>
4 #include <fstream>
5 #include <sstream>
6 #include <iostream>
7 #include "l1menu/ITrigger.h"
8 #include "l1menu/tools/tools.h"
9
10 namespace // Use the unnamed namespace for things only used in this file
11 {
12 /// ASCII codes of characters that are considered whitespace (space, tab, carriage return, line feed).
13 const char* whitespace="\x20\x09\x0D\x0A";
14
15 /** @brief Converts the entire string to a float or throws an exception. */
16 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 /** @brief Splits a string into individual parts delimited by whitespace. */
26 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 // Find the next whitespace and subtract everything up to that point
39 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 l1menu::TriggerMenu::TriggerMenu() : triggerTable_( l1menu::TriggerTable::instance() )
57 {
58 // No operation besides the initialiser list
59 }
60
61 l1menu::TriggerMenu::~TriggerMenu()
62 {
63 // No operation since I switched from raw pointers to unique_ptr.
64 }
65
66 l1menu::TriggerMenu::TriggerMenu( const TriggerMenu& otherTriggerMenu )
67 : triggerTable_(otherTriggerMenu.triggerTable_)
68 {
69 for( std::vector< std::unique_ptr<l1menu::ITrigger> >::const_iterator iTrigger=otherTriggerMenu.triggers_.begin(); iTrigger!=otherTriggerMenu.triggers_.end(); ++iTrigger )
70 {
71 l1menu::ITrigger& sourceTrigger=**iTrigger;
72
73 triggers_.push_back( std::move(triggerTable_.copyTrigger(sourceTrigger)) );
74 }
75
76 // Make sure triggerResults_ is always the same size as triggers_
77 triggerResults_.resize( triggers_.size() );
78 }
79
80 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 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 for( std::vector< std::unique_ptr<l1menu::ITrigger> >::const_iterator iTrigger=otherTriggerMenu.triggers_.begin(); iTrigger!=otherTriggerMenu.triggers_.end(); ++iTrigger )
98 {
99 l1menu::ITrigger& sourceTrigger=**iTrigger;
100
101 triggers_.push_back( std::move(triggerTable_.copyTrigger(sourceTrigger)) );
102 }
103
104 // Make sure triggerResults_ is always the same size as triggers_
105 triggerResults_.resize( triggers_.size() );
106
107 return *this;
108 }
109
110 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 l1menu::ITrigger& l1menu::TriggerMenu::addTrigger( const std::string& triggerName )
119 {
120 std::unique_ptr<l1menu::ITrigger> pNewTrigger=triggerTable_.getTrigger( triggerName );
121 if( pNewTrigger.get()==NULL ) throw std::range_error( "Trigger requested that does not exist" );
122
123 triggers_.push_back( std::move(pNewTrigger) );
124
125 // Make sure triggerResults_ is always the same size as triggers_
126 triggerResults_.resize( triggers_.size() );
127 return *triggers_.back();
128 }
129
130 l1menu::ITrigger& l1menu::TriggerMenu::addTrigger( const std::string& triggerName, unsigned int version )
131 {
132 std::unique_ptr<l1menu::ITrigger> pNewTrigger=triggerTable_.getTrigger( triggerName, version );
133 if( pNewTrigger.get()==NULL ) throw std::range_error( "Trigger requested that does not exist" );
134
135 triggers_.push_back( std::move(pNewTrigger) );
136
137 // Make sure triggerResults_ is always the same size as triggers_
138 triggerResults_.resize( triggers_.size() );
139 return *triggers_.back();
140 }
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 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 {
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 std::ifstream file( filename.c_str() );
185 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 std::string triggerName=tableColumns[0];
212
213 try
214 {
215 //std::cout << "Added trigger \"" << tableColumns[0] << "\"" << std::endl;
216 l1menu::ITrigger& newTrigger=addTrigger( triggerName ); // Try and create a trigger with the name supplied
217
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 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 newTrigger.parameter("leg1etaCut")=etaOrRegionCut;
241 newTrigger.parameter("leg2regionCut")=l1menu::tools::convertEtaCutToRegionCut( etaOrRegionCut );
242 }
243 else if( triggerName=="L1_SingleIsoEG_CJet" )
244 {
245 newTrigger.parameter("leg1regionCut")=etaOrRegionCut;
246 newTrigger.parameter("leg2regionCut")=etaOrRegionCut;
247 }
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
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 catch( std::exception& error )
264 {
265 std::cerr << "Unable to add trigger \"" << tableColumns[0] << "\" because: " << error.what() << std::endl;
266 }
267 } // 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 }