ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/grimes/L1Menu/src/TriggerMenu.cpp
Revision: 1.11
Committed: Wed Jul 24 11:48:55 2013 UTC (11 years, 9 months ago) by grimes
Branch: MAIN
CVS Tags: HEAD
Changes since 1.10: +102 -134 lines
Error occurred while calculating annotation data.
Log Message:
Big commit of lots of changes before migrating to Git.

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