ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/grimes/L1Menu/src/TriggerMenu.cpp
Revision: 1.6
Committed: Tue Jun 18 10:33:24 2013 UTC (11 years, 10 months ago) by grimes
Branch: MAIN
Changes since 1.5: +4 -4 lines
Log Message:
Updates to the menu file loader

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