ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/grimes/L1Menu/src/tools.cpp
Revision: 1.5
Committed: Mon Jun 24 14:47:40 2013 UTC (11 years, 10 months ago) by grimes
Branch: MAIN
CVS Tags: HEAD
Changes since 1.4: +0 -0 lines
State: FILE REMOVED
Log Message:
Changes to the way trigger rates are returned

File Contents

# Content
1 #include "l1menu/tools.h"
2
3 #include <sstream>
4 #include <exception>
5 #include <map>
6 #include <stdexcept>
7 #include <algorithm>
8 #include "l1menu/ITrigger.h"
9 #include "l1menu/IEvent.h"
10 #include "l1menu/TriggerTable.h"
11
12 std::vector<std::string> l1menu::getThresholdNames( const l1menu::ITrigger& trigger )
13 {
14 std::vector<std::string> returnValue;
15
16 //
17 // I don't know how many thresholds there are, so I'll try and get every possible one and catch
18 // the exception when I eventually hit a threshold that doesn't exist.
19 //
20
21 std::stringstream stringConverter;
22 // I plan in the future to implement cross triggers with "leg1threshold1", "leg2threshold1" etcetera,
23 // so I'll loop over those possible prefixes.
24 for( size_t legNumber=0; true; ++legNumber ) // Loop continuously until the exception handler calls "break"
25 {
26 size_t thresholdNumber;
27 try
28 {
29 // Loop over all possible numbers of thresholds
30 for( thresholdNumber=1; true; ++thresholdNumber ) // Loop continuously until I hit an exception
31 {
32 stringConverter.str("");
33 if( legNumber!=0 ) stringConverter << "leg" << legNumber; // For triggers with only one leg I don't want to prefix anything.
34
35 stringConverter << "threshold" << thresholdNumber;
36
37 trigger.parameter(stringConverter.str());
38 // If the threshold doesn't exist the statement above will throw an exception, so
39 // I've reached this far then the threshold name must exist.
40 returnValue.push_back( stringConverter.str() );
41 }
42
43 }
44 catch( std::exception& error )
45 {
46 // If this exception is from the first threshold tried then the prefix (e.g. "leg1") does not
47 // exist, so I know I've finished. If it isn't from the first threshold then there could be
48 // other prefixes (e.g. "leg2") that have thresholds that can be modified, in which case I
49 // need to continue.
50 if( thresholdNumber==1 && legNumber!=0 ) break;
51 }
52 }
53
54 return returnValue;
55 }
56
57 std::vector<std::string> l1menu::getNonThresholdParameterNames( const l1menu::ITrigger& trigger )
58 {
59 std::vector<std::string> returnValue;
60
61 // It'll be easier to get the threshold names and then copy
62 // everything that's not in there to the return value.
63 std::vector<std::string> allParameterNames=trigger.parameterNames();
64 std::vector<std::string> thresholdNames=getThresholdNames(trigger);
65
66 for( const auto& parameterName : allParameterNames )
67 {
68 const auto& iFindResult=std::find( thresholdNames.begin(), thresholdNames.end(), parameterName );
69 // If the current parameter name isn't one of the thresholds add
70 // it the vector which I'm going to return.
71 if( iFindResult==thresholdNames.end() ) returnValue.push_back(parameterName);
72 }
73
74 return returnValue;
75 }
76
77 void l1menu::setTriggerThresholdsAsTightAsPossible( const l1menu::IEvent& event, l1menu::ITrigger& trigger, float tolerance )
78 {
79 std::vector<std::string> thresholdNames=l1menu::getThresholdNames( trigger );
80 std::map<std::string,float> tightestPossibleThresholds;
81
82 // First set all of the thresholds to zero
83 for( const auto& thresholdName : thresholdNames ) trigger.parameter(thresholdName)=0;
84
85 // Now run through each threshold at a time and figure out how low it can be and still
86 // pass the event.
87 for( const auto& thresholdName : thresholdNames )
88 {
89 // Note that this is a reference, so when this is changed the trigger is modified
90 float& threshold=trigger.parameter(thresholdName);
91
92 float lowThreshold=0;
93 float highThreshold=500;
94 // See if an indication of the range of the trigger has been set
95 try // These calls will throw an exception if no suggestion has been set
96 {
97 lowThreshold=l1menu::TriggerTable::instance().getSuggestedLowerEdge( trigger.name(), thresholdName );
98 highThreshold=l1menu::TriggerTable::instance().getSuggestedUpperEdge( trigger.name(), thresholdName );
99 highThreshold*=5; // Make sure the high threshold is very high, to catch all tails
100 }
101 catch( std::exception& error ) { /* No indication set. Do nothing and just use the defaults I set previously. */ }
102
103 threshold=lowThreshold;
104 bool lowTest=trigger.apply( event );
105
106 threshold=highThreshold;
107 bool highTest=trigger.apply( event );
108
109 if( lowTest==highTest ) std::runtime_error( "l1menu::setTriggerThresholdsAsTightAsPossible() - couldn't find a set of thresholds to pass the given event.");
110
111 // Try and find the turn on point by bisection
112 while( highThreshold-lowThreshold > tolerance )
113 {
114 threshold=(highThreshold+lowThreshold)/2;
115 bool midTest=trigger.apply(event);
116
117 if( lowTest==midTest && highTest!=midTest ) lowThreshold=threshold;
118 else if( highTest==midTest ) highThreshold=threshold;
119 else throw std::runtime_error( std::string("Something fucked up while testing ")+trigger.name() );
120 }
121
122 // Record what this value was for the parameter named
123 tightestPossibleThresholds[thresholdName]=highThreshold;
124 // Then set back to zero ready to test the other thresholds
125 threshold=0;
126 }
127
128 //
129 // Now that I've figured out what all of the thresholds need to be, run
130 // through and set the trigger up with these thresholds.
131 //
132 for( const auto& parameterValuePair : tightestPossibleThresholds )
133 {
134 trigger.parameter(parameterValuePair.first)=parameterValuePair.second;
135 }
136 }