ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/grimes/L1Menu/src/tools.cpp
Revision: 1.2
Committed: Fri May 31 01:29:10 2013 UTC (11 years, 11 months ago) by grimes
Branch: MAIN
Changes since 1.1: +21 -0 lines
Log Message:
Various improvements, including protobuf input and output for ReducedMenuSamples.

File Contents

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