ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/grimes/L1Menu/src/TriggerMenu.cpp
Revision: 1.3
Committed: Tue May 28 23:14:03 2013 UTC (11 years, 11 months ago) by grimes
Branch: MAIN
Changes since 1.2: +40 -36 lines
Log Message:
Numerous changes

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 } // end of the unnamed namespace
53
54
55 l1menu::TriggerMenu::TriggerMenu() : triggerTable_( l1menu::TriggerTable::instance() )
56 {
57 // No operation besides the initialiser list
58 }
59
60 l1menu::TriggerMenu::~TriggerMenu()
61 {
62 // No operation since I switched from raw pointers to unique_ptr.
63 }
64
65 l1menu::TriggerMenu::TriggerMenu( const TriggerMenu& otherTriggerMenu )
66 : triggerTable_(otherTriggerMenu.triggerTable_)
67 {
68 for( std::vector< std::unique_ptr<l1menu::ITrigger> >::const_iterator iTrigger=otherTriggerMenu.triggers_.begin(); iTrigger!=otherTriggerMenu.triggers_.end(); ++iTrigger )
69 {
70 l1menu::ITrigger& sourceTrigger=**iTrigger;
71
72 triggers_.push_back( std::move(triggerTable_.copyTrigger(sourceTrigger)) );
73 }
74
75 // Make sure triggerResults_ is always the same size as triggers_
76 triggerResults_.resize( triggers_.size() );
77 }
78
79 l1menu::TriggerMenu::TriggerMenu( TriggerMenu&& otherTriggerMenu ) noexcept
80 : triggerTable_(otherTriggerMenu.triggerTable_), triggers_( std::move(otherTriggerMenu.triggers_) ),
81 triggerResults_( std::move(otherTriggerMenu.triggerResults_) )
82 {
83 // No operation besides the initialiser list
84 }
85
86 l1menu::TriggerMenu& l1menu::TriggerMenu::operator=( const l1menu::TriggerMenu& otherTriggerMenu )
87 {
88 //
89 // First clean up whatever triggers I had before
90 //
91 triggers_.clear();
92
93 //
94 // Now copy the triggers from the other menu
95 //
96 for( std::vector< std::unique_ptr<l1menu::ITrigger> >::const_iterator iTrigger=otherTriggerMenu.triggers_.begin(); iTrigger!=otherTriggerMenu.triggers_.end(); ++iTrigger )
97 {
98 l1menu::ITrigger& sourceTrigger=**iTrigger;
99
100 triggers_.push_back( std::move(triggerTable_.copyTrigger(sourceTrigger)) );
101 }
102
103 // Make sure triggerResults_ is always the same size as triggers_
104 triggerResults_.resize( triggers_.size() );
105
106 return *this;
107 }
108
109 l1menu::TriggerMenu& l1menu::TriggerMenu::operator=( l1menu::TriggerMenu&& otherTriggerMenu ) noexcept
110 {
111 triggers_=std::move( otherTriggerMenu.triggers_ );
112 triggerResults_=std::move(otherTriggerMenu.triggerResults_);
113
114 return *this;
115 }
116
117 bool l1menu::TriggerMenu::addTrigger( const std::string& triggerName )
118 {
119 std::unique_ptr<l1menu::ITrigger> pNewTrigger=triggerTable_.getTrigger( triggerName );
120 if( pNewTrigger.get()==NULL ) return false;
121
122 triggers_.push_back( std::move(pNewTrigger) );
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::unique_ptr<l1menu::ITrigger> pNewTrigger=triggerTable_.getTrigger( triggerName, version );
132 if( pNewTrigger.get()==NULL ) return false;
133
134 triggers_.push_back( std::move(pNewTrigger) );
135
136 // Make sure triggerResults_ is always the same size as triggers_
137 triggerResults_.resize( triggers_.size() );
138 return true;
139 }
140
141 size_t l1menu::TriggerMenu::numberOfTriggers() const
142 {
143 return triggers_.size();
144 }
145
146 l1menu::ITrigger& l1menu::TriggerMenu::getTrigger( size_t position )
147 {
148 if( position>triggers_.size() ) throw std::range_error( "Trigger requested that does not exist in the menu" );
149
150 return *triggers_[position];
151 }
152
153 const l1menu::ITrigger& l1menu::TriggerMenu::getTrigger( size_t position ) const
154 {
155 if( position>triggers_.size() ) throw std::range_error( "Trigger requested that does not exist in the menu" );
156
157 return *triggers_[position];
158 }
159
160 std::unique_ptr<l1menu::ITrigger> l1menu::TriggerMenu::getTriggerCopy( size_t position ) const
161 {
162 if( position>triggers_.size() ) throw std::range_error( "Trigger requested that does not exist in the menu" );
163
164 return triggerTable_.copyTrigger(*triggers_[position]);
165 }
166
167 bool l1menu::TriggerMenu::apply( const l1menu::IEvent& event ) const
168 {
169 bool atLeastOneTriggerHasFired=false;
170
171 for( size_t triggerNumber=0; triggerNumber<triggers_.size(); ++triggerNumber )
172 {
173 bool result=triggers_[triggerNumber]->apply(event);
174 // triggerResults_[triggerNumber]=result;
175 if( result ) atLeastOneTriggerHasFired=true;
176 }
177
178 return atLeastOneTriggerHasFired;
179 }
180
181 void l1menu::TriggerMenu::loadMenuFromFile( const std::string& filename )
182 {
183 std::ifstream file( filename.c_str() );
184 if( !file.is_open() ) throw std::runtime_error( "Unable to open file "+filename );
185
186 loadMenuInOldFormat( file );
187 }
188
189 void l1menu::TriggerMenu::loadMenuInOldFormat( std::ifstream& file )
190 {
191 const size_t bufferSize=200;
192 char buffer[bufferSize];
193
194 while( file.good() )
195 {
196 try
197 {
198 // Get one line at a time
199 file.getline( buffer, bufferSize );
200
201 // split the line by whitespace into columns
202 std::vector<std::string> tableColumns=::splitByWhitespace( buffer );
203
204 if( tableColumns.size()==1 && tableColumns[0].empty() ) continue; // Allow blank lines without giving a warning
205 if( tableColumns.size()!=12 ) throw std::runtime_error( "The line does not have the correct number of columns" );
206
207 float prescale=::convertStringToFloat( tableColumns[2] );
208 if( prescale!=0 )
209 {
210 if( addTrigger( tableColumns[0] ) ) // Try and create a trigger with the name supplied
211 {
212 std::cout << "Added trigger \"" << tableColumns[0] << "\"" << std::endl;
213
214 l1menu::ITrigger& newTrigger=*(triggers_.back());
215
216 // Try and set all of the relevant parameters. I know not all triggers have these parameters
217 // so wrap in individual try/catch blocks.
218 try{ newTrigger.parameter("threshold1")=::convertStringToFloat( tableColumns[3] ); }
219 catch( std::exception& error ) { } // Do nothing, just try and convert the other parameters
220
221 try{ newTrigger.parameter("threshold2")=::convertStringToFloat( tableColumns[4] ); }
222 catch( std::exception& error ) { } // Do nothing, just try and convert the other parameters
223
224 try{ newTrigger.parameter("threshold3")=::convertStringToFloat( tableColumns[5] ); }
225 catch( std::exception& error ) { } // Do nothing, just try and convert the other parameters
226
227 try{ newTrigger.parameter("threshold4")=::convertStringToFloat( tableColumns[6] ); }
228 catch( std::exception& error ) { } // Do nothing, just try and convert the other parameters
229
230 try{ newTrigger.parameter("etaCut")=::convertStringToFloat( tableColumns[7] ); }
231 catch( std::exception& error ) { } // Do nothing, just try and convert the other parameters
232
233 try{ newTrigger.parameter("muonQuality")=::convertStringToFloat( tableColumns[8] ); }
234 catch( std::exception& error ) { } // Do nothing, just try and convert the other parameters
235
236 } // end of "if able to add trigger"
237 else std::cout << "The trigger \"" << tableColumns[0] << "\" is not registered in the trigger table" << std::endl;
238 } // end of "if( prescale!=0 )"
239 } // end of try block
240 catch( std::runtime_error& exception )
241 {
242 std::cout << "Some error occured while processing the line \"" << buffer << "\":" << exception.what() << std::endl;
243 }
244 }
245 }