ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/grimes/L1Menu/src/TriggerMenu.cpp
Revision: 1.5
Committed: Tue Jun 18 10:18:23 2013 UTC (11 years, 10 months ago) by grimes
Branch: MAIN
Changes since 1.4: +51 -12 lines
Log Message:
Fixed some bugs, and started adding functionality to calculate rates.

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 grimes 1.5 /** @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 grimes 1.1 } // end of the unnamed namespace
64    
65    
66 grimes 1.3 l1menu::TriggerMenu::TriggerMenu() : triggerTable_( l1menu::TriggerTable::instance() )
67 grimes 1.1 {
68     // No operation besides the initialiser list
69     }
70    
71     l1menu::TriggerMenu::~TriggerMenu()
72     {
73 grimes 1.3 // No operation since I switched from raw pointers to unique_ptr.
74 grimes 1.1 }
75    
76 grimes 1.3 l1menu::TriggerMenu::TriggerMenu( const TriggerMenu& otherTriggerMenu )
77 grimes 1.1 : triggerTable_(otherTriggerMenu.triggerTable_)
78     {
79 grimes 1.3 for( std::vector< std::unique_ptr<l1menu::ITrigger> >::const_iterator iTrigger=otherTriggerMenu.triggers_.begin(); iTrigger!=otherTriggerMenu.triggers_.end(); ++iTrigger )
80 grimes 1.1 {
81     l1menu::ITrigger& sourceTrigger=**iTrigger;
82    
83 grimes 1.3 triggers_.push_back( std::move(triggerTable_.copyTrigger(sourceTrigger)) );
84 grimes 1.1 }
85    
86     // Make sure triggerResults_ is always the same size as triggers_
87     triggerResults_.resize( triggers_.size() );
88     }
89    
90 grimes 1.3 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 grimes 1.1 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 grimes 1.3 for( std::vector< std::unique_ptr<l1menu::ITrigger> >::const_iterator iTrigger=otherTriggerMenu.triggers_.begin(); iTrigger!=otherTriggerMenu.triggers_.end(); ++iTrigger )
108 grimes 1.1 {
109     l1menu::ITrigger& sourceTrigger=**iTrigger;
110    
111 grimes 1.3 triggers_.push_back( std::move(triggerTable_.copyTrigger(sourceTrigger)) );
112 grimes 1.1 }
113    
114     // Make sure triggerResults_ is always the same size as triggers_
115     triggerResults_.resize( triggers_.size() );
116    
117     return *this;
118     }
119    
120 grimes 1.3 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 grimes 1.5 l1menu::ITrigger& l1menu::TriggerMenu::addTrigger( const std::string& triggerName )
129 grimes 1.1 {
130 grimes 1.3 std::unique_ptr<l1menu::ITrigger> pNewTrigger=triggerTable_.getTrigger( triggerName );
131 grimes 1.5 if( pNewTrigger.get()==NULL ) throw std::range_error( "Trigger requested that does not exist" );
132 grimes 1.1
133 grimes 1.3 triggers_.push_back( std::move(pNewTrigger) );
134 grimes 1.1
135     // Make sure triggerResults_ is always the same size as triggers_
136     triggerResults_.resize( triggers_.size() );
137 grimes 1.5 return *triggers_.back();
138 grimes 1.1 }
139    
140 grimes 1.5 l1menu::ITrigger& l1menu::TriggerMenu::addTrigger( const std::string& triggerName, unsigned int version )
141 grimes 1.1 {
142 grimes 1.3 std::unique_ptr<l1menu::ITrigger> pNewTrigger=triggerTable_.getTrigger( triggerName, version );
143 grimes 1.5 if( pNewTrigger.get()==NULL ) throw std::range_error( "Trigger requested that does not exist" );
144 grimes 1.1
145 grimes 1.3 triggers_.push_back( std::move(pNewTrigger) );
146 grimes 1.1
147     // Make sure triggerResults_ is always the same size as triggers_
148     triggerResults_.resize( triggers_.size() );
149 grimes 1.5 return *triggers_.back();
150 grimes 1.1 }
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 grimes 1.3 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 grimes 1.1 {
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 grimes 1.2 std::ifstream file( filename.c_str() );
195 grimes 1.1 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 grimes 1.5 std::string triggerName=tableColumns[0];
222    
223     try
224 grimes 1.1 {
225 grimes 1.4 //std::cout << "Added trigger \"" << tableColumns[0] << "\"" << std::endl;
226 grimes 1.5 l1menu::ITrigger& newTrigger=addTrigger( triggerName ); // Try and create a trigger with the name supplied
227 grimes 1.1
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 grimes 1.5 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("etaCut")=etaOrRegionCut;
251     newTrigger.parameter("regionCut")=convertEtaCutToRegionCut( etaOrRegionCut );
252     }
253     else if( triggerName=="L1_SingleIsoEG_CJet" )
254     {
255     newTrigger.parameter("etaCut")=etaOrRegionCut;
256     newTrigger.parameter("regionCut")=convertEtaCutToRegionCut( 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 grimes 1.1
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 grimes 1.5 catch( std::exception& error )
274     {
275     std::cerr << "Unable to add trigger \"" << tableColumns[0] << "\" because: " << error.what() << std::endl;
276     }
277 grimes 1.1 } // 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     }