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
Log Message:
Big commit of lots of changes before migrating to Git.

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 grimes 1.7 #include "l1menu/tools/tools.h"
9 grimes 1.11 #include "l1menu/tools/stringManipulation.h"
10 grimes 1.1
11 grimes 1.3 l1menu::TriggerMenu::TriggerMenu() : triggerTable_( l1menu::TriggerTable::instance() )
12 grimes 1.1 {
13     // No operation besides the initialiser list
14     }
15    
16     l1menu::TriggerMenu::~TriggerMenu()
17     {
18 grimes 1.3 // No operation since I switched from raw pointers to unique_ptr.
19 grimes 1.1 }
20    
21 grimes 1.3 l1menu::TriggerMenu::TriggerMenu( const TriggerMenu& otherTriggerMenu )
22 grimes 1.1 : triggerTable_(otherTriggerMenu.triggerTable_)
23     {
24 grimes 1.3 for( std::vector< std::unique_ptr<l1menu::ITrigger> >::const_iterator iTrigger=otherTriggerMenu.triggers_.begin(); iTrigger!=otherTriggerMenu.triggers_.end(); ++iTrigger )
25 grimes 1.1 {
26     l1menu::ITrigger& sourceTrigger=**iTrigger;
27    
28 grimes 1.3 triggers_.push_back( std::move(triggerTable_.copyTrigger(sourceTrigger)) );
29 grimes 1.1 }
30    
31     // Make sure triggerResults_ is always the same size as triggers_
32     triggerResults_.resize( triggers_.size() );
33     }
34    
35 grimes 1.3 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 grimes 1.1 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 grimes 1.3 for( std::vector< std::unique_ptr<l1menu::ITrigger> >::const_iterator iTrigger=otherTriggerMenu.triggers_.begin(); iTrigger!=otherTriggerMenu.triggers_.end(); ++iTrigger )
53 grimes 1.1 {
54     l1menu::ITrigger& sourceTrigger=**iTrigger;
55    
56 grimes 1.3 triggers_.push_back( std::move(triggerTable_.copyTrigger(sourceTrigger)) );
57 grimes 1.1 }
58    
59     // Make sure triggerResults_ is always the same size as triggers_
60     triggerResults_.resize( triggers_.size() );
61    
62     return *this;
63     }
64    
65 grimes 1.3 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 grimes 1.5 l1menu::ITrigger& l1menu::TriggerMenu::addTrigger( const std::string& triggerName )
74 grimes 1.1 {
75 grimes 1.3 std::unique_ptr<l1menu::ITrigger> pNewTrigger=triggerTable_.getTrigger( triggerName );
76 grimes 1.5 if( pNewTrigger.get()==NULL ) throw std::range_error( "Trigger requested that does not exist" );
77 grimes 1.1
78 grimes 1.3 triggers_.push_back( std::move(pNewTrigger) );
79 grimes 1.1
80     // Make sure triggerResults_ is always the same size as triggers_
81     triggerResults_.resize( triggers_.size() );
82 grimes 1.5 return *triggers_.back();
83 grimes 1.1 }
84    
85 grimes 1.5 l1menu::ITrigger& l1menu::TriggerMenu::addTrigger( const std::string& triggerName, unsigned int version )
86 grimes 1.1 {
87 grimes 1.3 std::unique_ptr<l1menu::ITrigger> pNewTrigger=triggerTable_.getTrigger( triggerName, version );
88 grimes 1.5 if( pNewTrigger.get()==NULL ) throw std::range_error( "Trigger requested that does not exist" );
89 grimes 1.1
90 grimes 1.3 triggers_.push_back( std::move(pNewTrigger) );
91 grimes 1.1
92     // Make sure triggerResults_ is always the same size as triggers_
93     triggerResults_.resize( triggers_.size() );
94 grimes 1.5 return *triggers_.back();
95 grimes 1.1 }
96    
97 grimes 1.9 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 grimes 1.1 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 grimes 1.3 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 grimes 1.9 bool l1menu::TriggerMenu::apply( const l1menu::L1TriggerDPGEvent& event ) const
136 grimes 1.1 {
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 grimes 1.2 std::ifstream file( filename.c_str() );
152 grimes 1.1 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 grimes 1.11 std::vector<std::string> tableColumns=l1menu::tools::splitByWhitespace( buffer );
171 grimes 1.1
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 grimes 1.11 addTriggerFromOldFormat( tableColumns );
176 grimes 1.5
177 grimes 1.1 } // 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 grimes 1.11
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     }