ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/grimes/L1Menu/src/ReducedMenuSample.cpp
Revision: 1.3
Committed: Sun Jun 2 22:40:57 2013 UTC (11 years, 11 months ago) by grimes
Branch: MAIN
Changes since 1.2: +4 -0 lines
Log Message:
A few changes, and added skeleton files for all of the triggers.

File Contents

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