ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/grimes/L1Menu/src/ReducedMenuSample.cpp
(Generate patch)

Comparing UserCode/grimes/L1Menu/src/ReducedMenuSample.cpp (file contents):
Revision 1.1 by grimes, Wed May 29 00:01:02 2013 UTC vs.
Revision 1.4 by grimes, Tue Jun 4 08:17:37 2013 UTC

# Line 1 | Line 1
1   #include "l1menu/ReducedMenuSample.h"
2  
3   #include <vector>
4 + #include <stdexcept>
5 + #include <fstream>
6   #include "l1menu/IReducedEvent.h"
7   #include "l1menu/MenuSample.h"
8   #include "l1menu/TriggerMenu.h"
9 + #include "l1menu/ITrigger.h"
10   #include "l1menu/tools.h"
11 + #include "protobuf/l1menu.pb.h"
12  
13   namespace // unnamed namespace
14   {
# Line 12 | Line 16 | namespace // unnamed namespace
16          {
17          public:
18                  virtual ~ReducedEventImplementation() {}
19 <                virtual float parameterValue( size_t parameterNumber ) { return pThresholdValues->at(parameterNumber); }
20 <                virtual size_t parameterNumber( const l1menu::ITrigger& trigger, const std::string& parameterName ) { return 0; }
21 <                virtual float weight() const { return 1; }
19 >                virtual float parameterValue( size_t parameterNumber ) const {  return pThresholdValues->at(parameterNumber); }
20 >                virtual float weight() const { return *pWeight; }
21 >                void setWeight( float newWeight ) { *pWeight=newWeight; }
22                  std::vector<float>* pThresholdValues;
23 +                float* pWeight;
24          };
25   }
26  
# Line 29 | Line 34 | namespace l1menu
34          class ReducedMenuSamplePrivateMembers
35          {
36          public:
37 <                ReducedMenuSamplePrivateMembers( size_t newNumberOfEvents, size_t numberOfParameters )
38 <                        : thresholdsForAllEvents( newNumberOfEvents, std::vector<float>(numberOfParameters) )
37 >                ReducedMenuSamplePrivateMembers( size_t newNumberOfEvents, size_t numberOfParameters, const l1menu::TriggerMenu newTriggerMenu )
38 >                        : thresholdsForAllEvents( newNumberOfEvents, std::vector<float>(numberOfParameters) ),
39 >                          weights( newNumberOfEvents ), numberOfEvents( newNumberOfEvents ), triggerMenu( newTriggerMenu )
40                  {
41 <                        // No operation besides the initialiser list
41 >                        // Run through every event and default every weight to 1.
42 >                        for( auto& eventWeight : weights )
43 >                        {
44 >                                eventWeight=1;
45 >                        }
46                  }
47                  std::vector< std::vector<float> > thresholdsForAllEvents;
48 +                std::vector<float> weights;
49                  ::ReducedEventImplementation event;
50                  size_t numberOfEvents;
51 +                const l1menu::TriggerMenu triggerMenu;
52          };
53   }
54  
55 + #include <iostream>
56   l1menu::ReducedMenuSample::ReducedMenuSample( const l1menu::MenuSample& originalSample, const l1menu::TriggerMenu& triggerMenu )
57   {
58          size_t numberOfEvents=originalSample.numberOfEvents();
# Line 54 | Line 67 | l1menu::ReducedMenuSample::ReducedMenuSa
67  
68          // Now I know how many events there are and how many parameters, I can create the pimple
69          // with the correct parameters.
70 <        pImple_.reset( new l1menu::ReducedMenuSamplePrivateMembers( numberOfEvents, numberOfParameters ) );
70 >        pImple_.reset( new l1menu::ReducedMenuSamplePrivateMembers( numberOfEvents, numberOfParameters, triggerMenu ) );
71 >
72 >        //
73 >        // Now I've set the storage to the correct size, run through each event
74 >        // and fill with the correct values.
75 >        //
76 >        for( size_t eventNumber=0; eventNumber<numberOfEvents; ++eventNumber )
77 >        {
78 >                const l1menu::IEvent& event=originalSample.getEvent( eventNumber );
79 >                std::vector<float>& parameters=pImple_->thresholdsForAllEvents[eventNumber];
80 >
81 >                size_t parameterNumber=0;
82 >                // Loop over all of the triggers
83 >                for( size_t triggerNumber=0; triggerNumber<triggerMenu.numberOfTriggers(); ++triggerNumber )
84 >                {
85 >                        std::unique_ptr<l1menu::ITrigger> pTrigger=triggerMenu.getTriggerCopy(triggerNumber);
86 >                        std::vector<std::string> thresholdNames=getThresholdNames(*pTrigger);
87 >
88 >                        try
89 >                        {
90 >                                setTriggerThresholdsAsTightAsPossible( event, *pTrigger, 0.001 );
91 >                                // Set all of the parameters to match the thresholds in the trigger
92 >                                for( const auto& thresholdName : thresholdNames )
93 >                                {
94 >                                        parameters[parameterNumber]=pTrigger->parameter(thresholdName);
95 >                                        ++parameterNumber;
96 >                                }
97 >                        }
98 >                        catch( std::exception& error )
99 >                        {
100 >                                // setTriggerThresholdsAsTightAsPossible() couldn't find thresholds so record
101 >                                // -1 for everything.
102 >                                for( size_t index=0; index<thresholdNames.size(); ++index )
103 >                                {
104 >                                        parameters[parameterNumber]=-1;
105 >                                        ++parameterNumber;
106 >                                }
107 >                        } // end of try block that sets the trigger thresholds
108 >
109 >                } // end of loop over triggers
110 >        } // end of loop over events
111 > }
112 >
113 > l1menu::ReducedMenuSample::~ReducedMenuSample()
114 > {
115 >        // No operation. Just need one defined otherwise the default one messes up
116 >        // the unique_ptr deletion because ReducedMenuSamplePrivateMembers isn't
117 >        // defined elsewhere.
118 > }
119 >
120 > l1menu::ReducedMenuSample::ReducedMenuSample( const std::string& filename )
121 > {
122 >        GOOGLE_PROTOBUF_VERIFY_VERSION;
123 >
124 >        l1menuprotobuf::Sample inputSample;
125 >        { // new block to limit scope of variables
126 >                std::ifstream inputFile( filename );
127 >                inputSample.ParseFromIstream( &inputFile );
128 >        }
129 >
130 >        l1menu::TriggerMenu triggerMenu;
131 >
132 >        size_t totalNumberOfThresholds=0;
133 >
134 >        for( int triggerNumber=0; triggerNumber<inputSample.trigger_size(); ++triggerNumber )
135 >        {
136 >                const l1menuprotobuf::Trigger& inputTrigger=inputSample.trigger(triggerNumber);
137 >
138 >                triggerMenu.addTrigger( inputTrigger.name(), inputTrigger.version() );
139 >                // Get a reference to the trigger I just created
140 >                l1menu::ITrigger& trigger=triggerMenu.getTrigger(triggerNumber);
141 >
142 >                // Run through all of the parameters and set them to what they were
143 >                // when the sample was made.
144 >                for( int parameterNumber=0; parameterNumber<inputTrigger.parameter_size(); ++parameterNumber )
145 >                {
146 >                        const auto& inputParameter=inputTrigger.parameter(parameterNumber);
147 >                        trigger.parameter(inputParameter.name())=inputParameter.value();
148 >                }
149 >
150 >                // I should probably check the threshold names exist. At the moment I just see how
151 >                // many there are so that I can initialise the buffer that holds the event data.
152 >                totalNumberOfThresholds+=inputTrigger.threshold_size();
153 >        }
154 >
155 >        // Now I have the menu set up as much as I need it (thresholds aren't set
156 >        // but I don't care about those). I can initialise the ReducedMenuSamplePrivateMembers
157 >        // pImple_ with the menu and the correct sizes for the data buffer.
158 >        pImple_.reset( new l1menu::ReducedMenuSamplePrivateMembers( inputSample.event_size(), totalNumberOfThresholds, triggerMenu ) );
159 >
160 >        // Now run over each event from the input file
161 >        for( int eventNumber=0; eventNumber<inputSample.event_size(); ++eventNumber )
162 >        {
163 >                auto& thresholdsForEvent=pImple_->thresholdsForAllEvents[eventNumber];
164 >                const auto& inputEvent=inputSample.event(eventNumber);
165 >
166 >                for( int thresholdNumber=0; thresholdNumber<inputEvent.threshold_size(); ++thresholdNumber )
167 >                {
168 >                        thresholdsForEvent[thresholdNumber]=inputEvent.threshold(thresholdNumber);
169 >                }
170 >
171 >                // See if the weight was stored and set it if it has
172 >                if( inputEvent.has_weight() ) pImple_->weights[eventNumber]=inputEvent.weight();
173 >        }
174 > }
175 >
176 > void l1menu::ReducedMenuSample::saveToFile( const std::string& filename ) const
177 > {
178 >        GOOGLE_PROTOBUF_VERIFY_VERSION;
179 >
180 >        l1menuprotobuf::Sample outputSample;
181 >
182 >        for( size_t triggerNumber=0; triggerNumber<pImple_->triggerMenu.numberOfTriggers(); ++triggerNumber )
183 >        {
184 >                const l1menu::ITrigger& trigger=pImple_->triggerMenu.getTrigger(triggerNumber);
185 >
186 >                l1menuprotobuf::Trigger* pOutputTrigger=outputSample.add_trigger();
187 >                pOutputTrigger->set_name( trigger.name() );
188 >                pOutputTrigger->set_version( trigger.version() );
189 >
190 >                // Record all of the parameters. It's not strictly necessary to record the values
191 >                // of the parameters that are recorded for each event, but I might as well so that
192 >                // the trigger menu is loaded exactly as it was saved.
193 >                const auto parameterNames=trigger.parameterNames();
194 >                for( const auto& parameterName : parameterNames )
195 >                {
196 >                        l1menuprotobuf::Trigger_TriggerParameter* pOutputParameter=pOutputTrigger->add_parameter();
197 >                        pOutputParameter->set_name(parameterName);
198 >                        pOutputParameter->set_value( trigger.parameter(parameterName) );
199 >                }
200 >
201 >                // Make a note of the names of the parameters that are recorded for each event.
202 >                const auto thresholdNames=l1menu::getThresholdNames(trigger);
203 >                for( const auto& thresholdName : thresholdNames ) pOutputTrigger->add_threshold(thresholdName);
204 >
205 >        } // end of loop over triggers
206 >
207 >        //
208 >        // I've done everything for what is effectively the header. I now need
209 >        // to run through each event and record the thresholds for each one.
210 >        //
211 >        for( const auto& thresholdsForEvent : pImple_->thresholdsForAllEvents )
212 >        {
213 >                l1menuprotobuf::Event* pOutputEvent=outputSample.add_event();
214 >                for( const auto& threshold : thresholdsForEvent )
215 >                {
216 >                        pOutputEvent->add_threshold( threshold );
217 >                }
218 >        }
219 >
220 >        // I should have the correct number of events in the protobuf version of
221 >        // the sample now. I'll run through and set the event weights as well, but
222 >        // I'll only add it if it's different to 1. I think this saves space in
223 >        // the file.
224 >        for( int eventNumber=0; eventNumber<outputSample.event_size(); ++eventNumber )
225 >        {
226 >                if( pImple_->weights[eventNumber]!=1 )
227 >                {
228 >                        l1menuprotobuf::Event* pOutputEvent=outputSample.mutable_event(eventNumber);
229 >                        pOutputEvent->set_weight( pImple_->weights[eventNumber] );
230 >                }
231 >        }
232 >
233 >
234 >        //
235 >        // Everything should be set up in the class now, so I can open the
236 >        // output file and write to it.
237 >        //
238 >        std::ofstream outputFile( filename );
239 >        outputSample.SerializeToOstream( &outputFile );
240   }
241  
242   size_t l1menu::ReducedMenuSample::numberOfEvents() const
# Line 65 | Line 247 | size_t l1menu::ReducedMenuSample::number
247   const l1menu::IReducedEvent& l1menu::ReducedMenuSample::getEvent( size_t eventNumber ) const
248   {
249          pImple_->event.pThresholdValues=&pImple_->thresholdsForAllEvents[eventNumber];
250 +        pImple_->event.pWeight=&pImple_->weights[eventNumber];
251          return pImple_->event;
252   }
253 +
254 + const l1menu::TriggerMenu& l1menu::ReducedMenuSample::getTriggerMenu() const
255 + {
256 +        return pImple_->triggerMenu;
257 + }
258 +
259 + bool l1menu::ReducedMenuSample::containsTrigger( const l1menu::ITrigger& trigger, bool allowOlderVersion ) const
260 + {
261 +        // Loop over all of the triggers in the menu, and see if there is one
262 +        // where the name and version match.
263 +        for( size_t triggerNumber=0; triggerNumber<pImple_->triggerMenu.numberOfTriggers(); ++triggerNumber )
264 +        {
265 +                const l1menu::ITrigger& triggerInMenu=pImple_->triggerMenu.getTrigger(triggerNumber);
266 +                if( triggerInMenu.name()!=trigger.name() ) continue;
267 +                if( allowOlderVersion )
268 +                {
269 +                        if( triggerInMenu.version()>trigger.version() ) continue;
270 +                }
271 +                else
272 +                {
273 +                        if( triggerInMenu.version()!=trigger.version() ) continue;
274 +                }
275 +
276 +                // If control got this far then there is a trigger with the required name
277 +                // and sufficient version. I now need to check all of the non threshold parameters
278 +                // to make sure they match, i.e. make sure the ReducedSample was made with the same
279 +                // eta cuts or whatever.
280 +                // I don't care if the thresholds don't match because that's what's stored in the
281 +                // ReducedMenuSample.
282 +                std::vector<std::string> parameterNames=getNonThresholdParameterNames( trigger );
283 +                bool allParametersMatch=true;
284 +                for( const auto& parameterName : parameterNames )
285 +                {
286 +                        if( trigger.parameter(parameterName)!=triggerInMenu.parameter(parameterName) ) allParametersMatch=false;
287 +                }
288 +
289 +                if( allParametersMatch ) return true;
290 +        } // end of loop over triggers
291 +
292 +        // If control got this far then no trigger was found that matched
293 +        return false;
294 + }
295 +
296 + const std::map<std::string,size_t> l1menu::ReducedMenuSample::getTriggerParameterIdentifiers( const l1menu::ITrigger& trigger, bool allowOlderVersion ) const
297 + {
298 +        std::map<std::string,size_t> returnValue;
299 +
300 +        // Need to find out how many parameters there are for each event. Basically the sum
301 +        // of the number of thresholds for all triggers.
302 +        size_t parameterNumber=0;
303 +        bool triggerWasFound=true;
304 +        for( size_t triggerNumber=0; triggerNumber<pImple_->triggerMenu.numberOfTriggers(); ++triggerNumber )
305 +        {
306 +                const l1menu::ITrigger& triggerInMenu=pImple_->triggerMenu.getTrigger(triggerNumber);
307 +
308 +                triggerWasFound=true; // Set to true, then back to false if any of the tests fail
309 +                // See if this trigger in the menu is the same as the one passed as a parameter
310 +                if( triggerInMenu.name()!=trigger.name() ) triggerWasFound=false;
311 +                if( allowOlderVersion )
312 +                {
313 +                        if( triggerInMenu.version()>trigger.version() ) triggerWasFound=false;
314 +                }
315 +                else
316 +                {
317 +                        if( triggerInMenu.version()!=trigger.version() ) triggerWasFound=false;
318 +                }
319 +
320 +                // If control got this far then there is a trigger with the required name
321 +                // and sufficient version. I now need to check all of the non threshold parameters
322 +                // to make sure they match, i.e. make sure the ReducedSample was made with the same
323 +                // eta cuts or whatever.
324 +                // I don't care if the thresholds don't match because that's what's stored in the
325 +                // ReducedMenuSample.
326 +                if( triggerWasFound ) // Trigger can still fail, but no point doing this check if it already has
327 +                {
328 +                        std::vector<std::string> parameterNames=getNonThresholdParameterNames( trigger );
329 +                        for( const auto& parameterName : parameterNames )
330 +                        {
331 +                                if( trigger.parameter(parameterName)!=triggerInMenu.parameter(parameterName) ) triggerWasFound=false;
332 +                        }
333 +                }
334 +
335 +                std::vector<std::string> thresholdNames=l1menu::getThresholdNames(triggerInMenu);
336 +                if( triggerWasFound )
337 +                {
338 +                        for( const auto& thresholdName : thresholdNames )
339 +                        {
340 +                                returnValue[thresholdName]=parameterNumber;
341 +                                ++parameterNumber;
342 +                        }
343 +                        break;
344 +                }
345 +                else parameterNumber+=thresholdNames.size();
346 +        }
347 +
348 +        // There could conceivably be a trigger that was found but has no thresholds
349 +        // (I guess - it would be a pretty pointless trigger though). To indicate the
350 +        // difference between that and a trigger that wasn't found I'll respectively
351 +        // return the empty vector or throw an exception.
352 +        if( !triggerWasFound ) throw std::runtime_error( "l1menu::ReducedMenuSample::getTriggerParameterIdentifiers() called for a trigger that was not used to create the sample" );
353 +
354 +        return returnValue;
355 + }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines