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.6 by grimes, Wed Jun 5 11:02:36 2013 UTC vs.
Revision 1.7 by grimes, Thu Jun 6 15:05:04 2013 UTC

# Line 3 | Line 3
3   #include <vector>
4   #include <stdexcept>
5   #include <fstream>
6 + #include <algorithm>
7   #include "l1menu/IReducedEvent.h"
8   #include "l1menu/MenuSample.h"
9   #include "l1menu/TriggerMenu.h"
# Line 16 | Line 17 | namespace // unnamed namespace
17          {
18          public:
19                  virtual ~ReducedEventImplementation() {}
20 <                virtual float parameterValue( size_t parameterNumber ) const {  return pThresholdValues->at(parameterNumber); }
21 <                virtual float weight() const { return *pWeight; }
22 <                void setWeight( float newWeight ) { *pWeight=newWeight; }
23 <                std::vector<float>* pThresholdValues;
23 <                float* pWeight;
20 >                virtual float parameterValue( size_t parameterNumber ) const {  return pProtobufEvent->threshold(parameterNumber); }
21 >                virtual float weight() const { if( pProtobufEvent->has_weight() ) return pProtobufEvent->weight(); else return 1; }
22 >                void setWeight( float newWeight ) { pProtobufEvent->set_weight(newWeight); }
23 >                l1menuprotobuf::Event* pProtobufEvent;
24          };
25   }
26  
# Line 33 | Line 33 | namespace l1menu
33           */
34          class ReducedMenuSamplePrivateMembers
35          {
36 +        private:
37 +                l1menu::TriggerMenu mutableTriggerMenu_;
38          public:
39 <                ReducedMenuSamplePrivateMembers( size_t newNumberOfEvents, size_t newNumberOfParameters, const l1menu::TriggerMenu newTriggerMenu )
40 <                        : numberOfEvents( newNumberOfEvents ), numberOfParameters( newNumberOfParameters ),
41 <                          thresholdsForAllEvents( numberOfEvents, std::vector<float>(numberOfParameters) ),
40 <                          weights( newNumberOfEvents, 1 ), triggerMenu( newTriggerMenu )
41 <                {
42 <                        // No operation besides the initialiser list
43 <                }
44 <                ReducedMenuSamplePrivateMembers( size_t newNumberOfParameters, const l1menu::TriggerMenu newTriggerMenu )
45 <                        : numberOfEvents( 0 ), numberOfParameters( newNumberOfParameters ), triggerMenu( newTriggerMenu )
46 <                {
47 <                        // No operation besides the initialiser list
48 <                }
49 <                size_t numberOfEvents;
50 <                const size_t numberOfParameters;
51 <                std::vector< std::vector<float> > thresholdsForAllEvents;
52 <                std::vector<float> weights;
39 >                ReducedMenuSamplePrivateMembers( const l1menu::TriggerMenu& newTriggerMenu );
40 >                ReducedMenuSamplePrivateMembers( const std::string& filename );
41 >                void copyMenuToProtobufSample();
42                  ::ReducedEventImplementation event;
43 <                const l1menu::TriggerMenu triggerMenu;
43 >                const l1menu::TriggerMenu& triggerMenu;
44 >                l1menuprotobuf::Sample protobufSample;
45          };
46   }
47  
48 < l1menu::ReducedMenuSample::ReducedMenuSample( const l1menu::MenuSample& originalSample, const l1menu::TriggerMenu& triggerMenu )
48 > l1menu::ReducedMenuSamplePrivateMembers::ReducedMenuSamplePrivateMembers( const l1menu::TriggerMenu& newTriggerMenu )
49 >        : mutableTriggerMenu_( newTriggerMenu ), triggerMenu( mutableTriggerMenu_ )
50   {
51 <        size_t numberOfEvents=originalSample.numberOfEvents();
52 <        // Need to find out how many parameters there are for each event. Basically the sum
53 <        // of the number of thresholds for all triggers.
54 <        size_t numberOfParameters=0;
51 >        GOOGLE_PROTOBUF_VERIFY_VERSION;
52 >
53 >        // I need to copy the details of the trigger menu into the protobuf storage.
54 >        // This means I'm holding a duplicate, but I need it to write the Sample message
55 >        // so I might as well do it now.
56          for( size_t triggerNumber=0; triggerNumber<triggerMenu.numberOfTriggers(); ++triggerNumber )
57          {
58                  const l1menu::ITrigger& trigger=triggerMenu.getTrigger(triggerNumber);
67                numberOfParameters+=l1menu::getThresholdNames(trigger).size();
68        }
59  
60 <        // Now I know how many events there are and how many parameters, I can create the pimple
61 <        // with the correct parameters.
62 <        pImple_.reset( new l1menu::ReducedMenuSamplePrivateMembers( numberOfEvents, numberOfParameters, triggerMenu ) );
73 <
74 <        //
75 <        // Now I've set the storage to the correct size, run through each event
76 <        // and fill with the correct values.
77 <        //
78 <        for( size_t eventNumber=0; eventNumber<numberOfEvents; ++eventNumber )
79 <        {
80 <                const l1menu::IEvent& event=originalSample.getEvent( eventNumber );
81 <                std::vector<float>& parameters=pImple_->thresholdsForAllEvents[eventNumber];
60 >                l1menuprotobuf::Trigger* pProtobufTrigger=protobufSample.add_trigger();
61 >                pProtobufTrigger->set_name( trigger.name() );
62 >                pProtobufTrigger->set_version( trigger.version() );
63  
64 <                size_t parameterNumber=0;
65 <                // Loop over all of the triggers
66 <                for( size_t triggerNumber=0; triggerNumber<triggerMenu.numberOfTriggers(); ++triggerNumber )
64 >                // Record all of the parameters. It's not strictly necessary to record the values
65 >                // of the parameters that are recorded for each event, but I might as well so that
66 >                // the trigger menu is loaded exactly as it was saved.
67 >                const auto parameterNames=trigger.parameterNames();
68 >                for( const auto& parameterName : parameterNames )
69                  {
70 <                        std::unique_ptr<l1menu::ITrigger> pTrigger=triggerMenu.getTriggerCopy(triggerNumber);
71 <                        std::vector<std::string> thresholdNames=getThresholdNames(*pTrigger);
70 >                        l1menuprotobuf::Trigger_TriggerParameter* pProtobufParameter=pProtobufTrigger->add_parameter();
71 >                        pProtobufParameter->set_name(parameterName);
72 >                        pProtobufParameter->set_value( trigger.parameter(parameterName) );
73 >                }
74  
75 <                        try
76 <                        {
77 <                                setTriggerThresholdsAsTightAsPossible( event, *pTrigger, 0.001 );
78 <                                // Set all of the parameters to match the thresholds in the trigger
79 <                                for( const auto& thresholdName : thresholdNames )
80 <                                {
96 <                                        parameters[parameterNumber]=pTrigger->parameter(thresholdName);
97 <                                        ++parameterNumber;
98 <                                }
99 <                        }
100 <                        catch( std::exception& error )
101 <                        {
102 <                                // setTriggerThresholdsAsTightAsPossible() couldn't find thresholds so record
103 <                                // -1 for everything.
104 <                                for( size_t index=0; index<thresholdNames.size(); ++index )
105 <                                {
106 <                                        parameters[parameterNumber]=-1;
107 <                                        ++parameterNumber;
108 <                                }
109 <                        } // end of try block that sets the trigger thresholds
75 >                // Make a note of the names of the parameters that are recorded for each event. For this
76 >                // I'm just recording the parameters that refer to the thresholds.
77 >                const auto thresholdNames=l1menu::getThresholdNames(trigger);
78 >                for( const auto& thresholdName : thresholdNames ) pProtobufTrigger->add_threshold(thresholdName);
79 >
80 >        } // end of loop over triggers
81  
111                } // end of loop over triggers
112        } // end of loop over events
82   }
83  
84 < l1menu::ReducedMenuSample::ReducedMenuSample( const l1menu::TriggerMenu& triggerMenu )
84 > l1menu::ReducedMenuSamplePrivateMembers::ReducedMenuSamplePrivateMembers( const std::string& filename )
85 >        : triggerMenu(mutableTriggerMenu_)
86   {
87 <        // Need to find out how many parameters there are for each event. Basically the sum
88 <        // of the number of thresholds for all triggers.
89 <        size_t numberOfParameters=0;
90 <        for( size_t triggerNumber=0; triggerNumber<triggerMenu.numberOfTriggers(); ++triggerNumber )
87 >        GOOGLE_PROTOBUF_VERIFY_VERSION;
88 >
89 >        { // new block to limit scope of variables, so that the file is closed immediately after reading
90 >                std::ifstream inputFile( filename );
91 >                protobufSample.ParseFromIstream( &inputFile );
92 >        }
93 >
94 >
95 >        // I have all of the information in the protobuf Sample, but I also need the trigger information
96 >        // in the form of l1menu::TriggerMenu. Copy out the required information.
97 >        for( int triggerNumber=0; triggerNumber<protobufSample.trigger_size(); ++triggerNumber )
98          {
99 <                const l1menu::ITrigger& trigger=triggerMenu.getTrigger(triggerNumber);
100 <                numberOfParameters+=l1menu::getThresholdNames(trigger).size();
99 >                const l1menuprotobuf::Trigger& inputTrigger=protobufSample.trigger(triggerNumber);
100 >
101 >                mutableTriggerMenu_.addTrigger( inputTrigger.name(), inputTrigger.version() );
102 >                // Get a reference to the trigger I just created
103 >                l1menu::ITrigger& trigger=mutableTriggerMenu_.getTrigger(triggerNumber);
104 >
105 >                // Run through all of the parameters and set them to what they were
106 >                // when the sample was made.
107 >                for( int parameterNumber=0; parameterNumber<inputTrigger.parameter_size(); ++parameterNumber )
108 >                {
109 >                        const auto& inputParameter=inputTrigger.parameter(parameterNumber);
110 >                        trigger.parameter(inputParameter.name())=inputParameter.value();
111 >                }
112 >
113 >                // I should probably check the threshold names exist. I'll do it another time.
114          }
115  
116 <        // Now I know how many events there are and how many parameters, I can create the pimple
117 <        // with the correct parameters.
118 <        // I get a bad_alloc exception if I pass 0 numberOfEvents, so I'll
119 <        pImple_.reset( new l1menu::ReducedMenuSamplePrivateMembers( numberOfParameters, triggerMenu ) );
116 > }
117 >
118 > l1menu::ReducedMenuSample::ReducedMenuSample( const l1menu::MenuSample& originalSample, const l1menu::TriggerMenu& triggerMenu )
119 >        : pImple_( new l1menu::ReducedMenuSamplePrivateMembers( triggerMenu ) )
120 > {
121 >        addSample( originalSample );
122 > }
123 >
124 > l1menu::ReducedMenuSample::ReducedMenuSample( const l1menu::TriggerMenu& triggerMenu )
125 >        : pImple_( new l1menu::ReducedMenuSamplePrivateMembers( triggerMenu ) )
126 > {
127 >        // No operation besides the initialiser list
128   }
129  
130   l1menu::ReducedMenuSample::~ReducedMenuSample()
# Line 138 | Line 136 | l1menu::ReducedMenuSample::~ReducedMenuS
136  
137   void l1menu::ReducedMenuSample::addSample( const l1menu::MenuSample& originalSample )
138   {
141        size_t oldNumberEvents=pImple_->numberOfEvents;
142        pImple_->numberOfEvents=oldNumberEvents+originalSample.numberOfEvents();
143
144        // Resize the containers to make space for the new events
145        pImple_->thresholdsForAllEvents.resize( pImple_->numberOfEvents, std::vector<float>(pImple_->numberOfParameters) );
146        pImple_->weights.resize( pImple_->numberOfEvents, 1 );
147
148        //
149        // Now I've set the storage to the correct size, run through each event
150        // and fill with the correct values.
151        //
139          for( size_t eventNumber=0; eventNumber<originalSample.numberOfEvents(); ++eventNumber )
140          {
154                size_t bufferEventNumber=eventNumber+oldNumberEvents;
155
141                  const l1menu::IEvent& event=originalSample.getEvent( eventNumber );
142 <                std::vector<float>& parameters=pImple_->thresholdsForAllEvents[bufferEventNumber];
142 >                l1menuprotobuf::Event* pProtobufEvent=pImple_->protobufSample.add_event();
143  
159                size_t parameterNumber=0;
144                  // Loop over all of the triggers
145                  for( size_t triggerNumber=0; triggerNumber<pImple_->triggerMenu.numberOfTriggers(); ++triggerNumber )
146                  {
# Line 169 | Line 153 | void l1menu::ReducedMenuSample::addSampl
153                                  // Set all of the parameters to match the thresholds in the trigger
154                                  for( const auto& thresholdName : thresholdNames )
155                                  {
156 <                                        parameters[parameterNumber]=pTrigger->parameter(thresholdName);
173 <                                        ++parameterNumber;
156 >                                        pProtobufEvent->add_threshold( pTrigger->parameter(thresholdName) );
157                                  }
158                          }
159                          catch( std::exception& error )
160                          {
161                                  // setTriggerThresholdsAsTightAsPossible() couldn't find thresholds so record
162                                  // -1 for everything.
163 <                                for( size_t index=0; index<thresholdNames.size(); ++index )
164 <                                {
182 <                                        parameters[parameterNumber]=-1;
183 <                                        ++parameterNumber;
184 <                                }
163 >                                // Range based for loop gives me a warning because I don't use the thresholdName.
164 >                                for( size_t index=0; index<thresholdNames.size(); ++index ) pProtobufEvent->add_threshold(-1);
165                          } // end of try block that sets the trigger thresholds
166  
167                  } // end of loop over triggers
188        } // end of loop over events
168  
169 +        } // end of loop over events
170   }
171  
172   l1menu::ReducedMenuSample::ReducedMenuSample( const std::string& filename )
173 +        : pImple_( new l1menu::ReducedMenuSamplePrivateMembers( filename ) )
174   {
175 <        GOOGLE_PROTOBUF_VERIFY_VERSION;
195 <
196 <        l1menuprotobuf::Sample inputSample;
197 <        { // new block to limit scope of variables
198 <                std::ifstream inputFile( filename );
199 <                inputSample.ParseFromIstream( &inputFile );
200 <        }
201 <
202 <        l1menu::TriggerMenu triggerMenu;
203 <
204 <        size_t totalNumberOfThresholds=0;
205 <
206 <        for( int triggerNumber=0; triggerNumber<inputSample.trigger_size(); ++triggerNumber )
207 <        {
208 <                const l1menuprotobuf::Trigger& inputTrigger=inputSample.trigger(triggerNumber);
209 <
210 <                triggerMenu.addTrigger( inputTrigger.name(), inputTrigger.version() );
211 <                // Get a reference to the trigger I just created
212 <                l1menu::ITrigger& trigger=triggerMenu.getTrigger(triggerNumber);
213 <
214 <                // Run through all of the parameters and set them to what they were
215 <                // when the sample was made.
216 <                for( int parameterNumber=0; parameterNumber<inputTrigger.parameter_size(); ++parameterNumber )
217 <                {
218 <                        const auto& inputParameter=inputTrigger.parameter(parameterNumber);
219 <                        trigger.parameter(inputParameter.name())=inputParameter.value();
220 <                }
221 <
222 <                // I should probably check the threshold names exist. At the moment I just see how
223 <                // many there are so that I can initialise the buffer that holds the event data.
224 <                totalNumberOfThresholds+=inputTrigger.threshold_size();
225 <        }
226 <
227 <
228 <        // Now I have the menu set up as much as I need it (thresholds aren't set
229 <        // but I don't care about those). I can initialise the ReducedMenuSamplePrivateMembers
230 <        // pImple_ with the menu and the correct sizes for the data buffer.
231 <        pImple_.reset( new l1menu::ReducedMenuSamplePrivateMembers( inputSample.event_size(), totalNumberOfThresholds, triggerMenu ) );
232 <
233 <        // Now run over each event from the input file
234 <        for( int eventNumber=0; eventNumber<inputSample.event_size(); ++eventNumber )
235 <        {
236 <                auto& thresholdsForEvent=pImple_->thresholdsForAllEvents[eventNumber];
237 <                const auto& inputEvent=inputSample.event(eventNumber);
238 <
239 <                for( int thresholdNumber=0; thresholdNumber<inputEvent.threshold_size(); ++thresholdNumber )
240 <                {
241 <                        thresholdsForEvent[thresholdNumber]=inputEvent.threshold(thresholdNumber);
242 <                }
243 <
244 <                // See if the weight was stored and set it if it has
245 <                if( inputEvent.has_weight() ) pImple_->weights[eventNumber]=inputEvent.weight();
246 <        }
175 >        // No operation except the initialiser list
176   }
177  
178   void l1menu::ReducedMenuSample::saveToFile( const std::string& filename ) const
179   {
251        GOOGLE_PROTOBUF_VERIFY_VERSION;
252
253        l1menuprotobuf::Sample outputSample;
254
255        for( size_t triggerNumber=0; triggerNumber<pImple_->triggerMenu.numberOfTriggers(); ++triggerNumber )
256        {
257                const l1menu::ITrigger& trigger=pImple_->triggerMenu.getTrigger(triggerNumber);
258
259                l1menuprotobuf::Trigger* pOutputTrigger=outputSample.add_trigger();
260                pOutputTrigger->set_name( trigger.name() );
261                pOutputTrigger->set_version( trigger.version() );
262
263                // Record all of the parameters. It's not strictly necessary to record the values
264                // of the parameters that are recorded for each event, but I might as well so that
265                // the trigger menu is loaded exactly as it was saved.
266                const auto parameterNames=trigger.parameterNames();
267                for( const auto& parameterName : parameterNames )
268                {
269                        l1menuprotobuf::Trigger_TriggerParameter* pOutputParameter=pOutputTrigger->add_parameter();
270                        pOutputParameter->set_name(parameterName);
271                        pOutputParameter->set_value( trigger.parameter(parameterName) );
272                }
273
274                // Make a note of the names of the parameters that are recorded for each event.
275                const auto thresholdNames=l1menu::getThresholdNames(trigger);
276                for( const auto& thresholdName : thresholdNames ) pOutputTrigger->add_threshold(thresholdName);
277
278        } // end of loop over triggers
279
280        //
281        // I've done everything for what is effectively the header. I now need
282        // to run through each event and record the thresholds for each one.
283        //
284        for( const auto& thresholdsForEvent : pImple_->thresholdsForAllEvents )
285        {
286                l1menuprotobuf::Event* pOutputEvent=outputSample.add_event();
287                for( const auto& threshold : thresholdsForEvent )
288                {
289                        pOutputEvent->add_threshold( threshold );
290                }
291        }
292
293        // I should have the correct number of events in the protobuf version of
294        // the sample now. I'll run through and set the event weights as well, but
295        // I'll only add it if it's different to 1. I think this saves space in
296        // the file.
297        for( int eventNumber=0; eventNumber<outputSample.event_size(); ++eventNumber )
298        {
299                if( pImple_->weights[eventNumber]!=1 )
300                {
301                        l1menuprotobuf::Event* pOutputEvent=outputSample.mutable_event(eventNumber);
302                        pOutputEvent->set_weight( pImple_->weights[eventNumber] );
303                }
304        }
305
306
307        //
308        // Everything should be set up in the class now, so I can open the
309        // output file and write to it.
310        //
180          std::ofstream outputFile( filename );
181 <        outputSample.SerializeToOstream( &outputFile );
181 >        pImple_->protobufSample.SerializeToOstream( &outputFile );
182   }
183  
184   size_t l1menu::ReducedMenuSample::numberOfEvents() const
185   {
186 <        return pImple_->numberOfEvents;
186 >        return pImple_->protobufSample.event_size();
187   }
188  
189   const l1menu::IReducedEvent& l1menu::ReducedMenuSample::getEvent( size_t eventNumber ) const
190   {
191 <        pImple_->event.pThresholdValues=&pImple_->thresholdsForAllEvents[eventNumber];
323 <        pImple_->event.pWeight=&pImple_->weights[eventNumber];
191 >        pImple_->event.pProtobufEvent=pImple_->protobufSample.mutable_event(eventNumber);
192          return pImple_->event;
193   }
194  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines