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

# 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 grimes 1.3 /// ASCII codes of characters that are considered whitespace (space, tab, carriage return, line feed).
12 grimes 1.1 const char* whitespace="\x20\x09\x0D\x0A";
13    
14 grimes 1.3 /** @brief Converts the entire string to a float or throws an exception. */
15 grimes 1.1 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 grimes 1.3 /** @brief Splits a string into individual parts delimited by whitespace. */
25 grimes 1.1 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 grimes 1.3 // Find the next whitespace and subtract everything up to that point
38 grimes 1.1 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 grimes 1.3 l1menu::TriggerMenu::TriggerMenu() : triggerTable_( l1menu::TriggerTable::instance() )
56 grimes 1.1 {
57     // No operation besides the initialiser list
58     }
59    
60     l1menu::TriggerMenu::~TriggerMenu()
61     {
62 grimes 1.3 // No operation since I switched from raw pointers to unique_ptr.
63 grimes 1.1 }
64    
65 grimes 1.3 l1menu::TriggerMenu::TriggerMenu( const TriggerMenu& otherTriggerMenu )
66 grimes 1.1 : triggerTable_(otherTriggerMenu.triggerTable_)
67     {
68 grimes 1.3 for( std::vector< std::unique_ptr<l1menu::ITrigger> >::const_iterator iTrigger=otherTriggerMenu.triggers_.begin(); iTrigger!=otherTriggerMenu.triggers_.end(); ++iTrigger )
69 grimes 1.1 {
70     l1menu::ITrigger& sourceTrigger=**iTrigger;
71    
72 grimes 1.3 triggers_.push_back( std::move(triggerTable_.copyTrigger(sourceTrigger)) );
73 grimes 1.1 }
74    
75     // Make sure triggerResults_ is always the same size as triggers_
76     triggerResults_.resize( triggers_.size() );
77     }
78    
79 grimes 1.3 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 grimes 1.1 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 grimes 1.3 for( std::vector< std::unique_ptr<l1menu::ITrigger> >::const_iterator iTrigger=otherTriggerMenu.triggers_.begin(); iTrigger!=otherTriggerMenu.triggers_.end(); ++iTrigger )
97 grimes 1.1 {
98     l1menu::ITrigger& sourceTrigger=**iTrigger;
99    
100 grimes 1.3 triggers_.push_back( std::move(triggerTable_.copyTrigger(sourceTrigger)) );
101 grimes 1.1 }
102    
103     // Make sure triggerResults_ is always the same size as triggers_
104     triggerResults_.resize( triggers_.size() );
105    
106     return *this;
107     }
108    
109 grimes 1.3 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 grimes 1.1 bool l1menu::TriggerMenu::addTrigger( const std::string& triggerName )
118     {
119 grimes 1.3 std::unique_ptr<l1menu::ITrigger> pNewTrigger=triggerTable_.getTrigger( triggerName );
120 grimes 1.1 if( pNewTrigger.get()==NULL ) return false;
121    
122 grimes 1.3 triggers_.push_back( std::move(pNewTrigger) );
123 grimes 1.1
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 grimes 1.3 std::unique_ptr<l1menu::ITrigger> pNewTrigger=triggerTable_.getTrigger( triggerName, version );
132 grimes 1.1 if( pNewTrigger.get()==NULL ) return false;
133    
134 grimes 1.3 triggers_.push_back( std::move(pNewTrigger) );
135 grimes 1.1
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 grimes 1.3 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 grimes 1.1 {
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 grimes 1.2 std::ifstream file( filename.c_str() );
184 grimes 1.1 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 grimes 1.3 std::cout << "Added trigger \"" << tableColumns[0] << "\"" << std::endl;
213    
214 grimes 1.1 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     }