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.8 by grimes, Fri Jun 7 14:22:05 2013 UTC vs.
Revision 1.13 by grimes, Fri Jun 28 14:30:08 2013 UTC

# Line 5 | Line 5
5   #include <fcntl.h>
6   #include <algorithm>
7   #include <iostream>
8 < #include "l1menu/IReducedEvent.h"
8 > #include <sstream>
9 > #include "l1menu/ReducedEvent.h"
10   #include "l1menu/MenuSample.h"
11   #include "l1menu/TriggerMenu.h"
12   #include "l1menu/ITrigger.h"
13 < #include "l1menu/tools.h"
13 > #include "l1menu/ICachedTrigger.h"
14 > #include "l1menu/L1TriggerDPGEvent.h"
15 > #include "l1menu/IEvent.h"
16 > #include "l1menu/IMenuRate.h"
17 > #include "l1menu/ITriggerRate.h"
18 > #include "l1menu/tools/tools.h"
19   #include "protobuf/l1menu.pb.h"
20   #include <google/protobuf/io/zero_copy_stream_impl.h>
21   #include <google/protobuf/io/gzip_stream.h>
22  
23   namespace // unnamed namespace
24   {
19        class ReducedEventImplementation : public l1menu::IReducedEvent
20        {
21        public:
22                virtual ~ReducedEventImplementation() {}
23                virtual float parameterValue( size_t parameterNumber ) const {  return pProtobufEvent->threshold(parameterNumber); }
24                virtual float weight() const { if( pProtobufEvent->has_weight() ) return pProtobufEvent->weight(); else return 1; }
25                void setWeight( float newWeight ) { pProtobufEvent->set_weight(newWeight); }
26                l1menuprotobuf::Event* pProtobufEvent;
27        };
28
25          /** @brief Sentry that closes a Unix file descriptor when it goes out of scope.
26           * @author Mark Grimes (mark.grimes@bristol.ac.uk)
27           * @date 07/Jun/2013
# Line 38 | Line 34 | namespace // unnamed namespace
34          private:
35                  int fileDescriptor_;
36          };
37 +
38 +        class MenuRateImplementation;
39 +
40 +        class TriggerRateImplementation : public l1menu::ITriggerRate
41 +        {
42 +        public:
43 +                TriggerRateImplementation( const l1menu::ITrigger& trigger, float fraction, const MenuRateImplementation& menuRate );
44 +                TriggerRateImplementation& operator=( TriggerRateImplementation&& otherTriggerRate ); // Move assignment
45 +                virtual ~TriggerRateImplementation();
46 +
47 +                // Methods required by the l1menu::ITriggerRate interface
48 +                virtual const l1menu::ITrigger& trigger() const;
49 +                virtual float fraction() const;
50 +                virtual float rate() const;
51 +        protected:
52 +                std::unique_ptr<l1menu::ITrigger> pTrigger_;
53 +                float fraction_;
54 +                const MenuRateImplementation& menuRate_;
55 +        };
56 +
57 +        class MenuRateImplementation : public l1menu::IMenuRate
58 +        {
59 +        public:
60 +                void setTotalFraction( float fraction ) { totalFraction_=fraction; }
61 +                void setScaling( float scaling ) { scaling_=scaling; }
62 +                float scaling() const { return scaling_; }
63 +                void addTriggerRate( const l1menu::ITrigger& trigger, float fraction ) { triggerRates_.push_back( std::move(TriggerRateImplementation(trigger,fraction,*this)) ); }
64 +                // Methods required by the l1menu::IMenuRate interface
65 +                virtual float totalFraction() const { return totalFraction_; }
66 +                virtual float totalRate() const { return totalFraction_*scaling_; }
67 +                virtual const std::vector<const l1menu::ITriggerRate*>& triggerRates() const
68 +                {
69 +                        // If the sizes are the same I'll assume nothing has changed and the references
70 +                        // are still valid. I don't expect this method to be called until the triggerRates_
71 +                        // vector is complete anyway.
72 +                        if( triggerRates_.size()!=baseClassReferences_.size() )
73 +                        {
74 +                                baseClassReferences_.clear();
75 +                                for( const auto& triggerRate : triggerRates_ )
76 +                                {
77 +                                        baseClassReferences_.push_back( &triggerRate );
78 +                                }
79 +                        }
80 +
81 +                        return baseClassReferences_;
82 +                }
83 +
84 +        protected:
85 +                float totalFraction_;
86 +                float scaling_;
87 +                std::vector<TriggerRateImplementation> triggerRates_;
88 +                mutable std::vector<const l1menu::ITriggerRate*> baseClassReferences_;
89 +        };
90 +
91 +        /** @brief An object that stores pointers to trigger parameters to avoid costly string comparisons.
92 +         *
93 +         * @author Mark Grimes (mark.grimes@bristol.ac.uk)
94 +         * @date 26/Jun/2013
95 +         */
96 +        class CachedTriggerImplementation : public l1menu::ICachedTrigger
97 +        {
98 +        public:
99 +                CachedTriggerImplementation( const l1menu::ReducedMenuSample& sample, const l1menu::ITrigger& trigger )
100 +                {
101 +                        const auto& parameterIdentifiers=sample.getTriggerParameterIdentifiers(trigger);
102 +
103 +                        for( const auto& identifier : parameterIdentifiers )
104 +                        {
105 +                                identifiers_.push_back( std::make_pair( identifier.second, &trigger.parameter(identifier.first) ) );
106 +                        }
107 +                }
108 +                virtual bool apply( const l1menu::IEvent& event )
109 +                {
110 +                        // Not happy using a static_cast, but this method is called in many, many loops.
111 +                        // I should probably find out how much faster this is than a dynamic_cast, maybe
112 +                        // it's not even worth it. Anyway, I'm banking that no one will ever pass an
113 +                        // event that wasn't created with the same sample that this proxy was created
114 +                        // with.
115 +                        const l1menu::ReducedEvent* pEvent=static_cast<const l1menu::ReducedEvent*>(&event);
116 +                        for( const auto& identifier : identifiers_ )
117 +                        {
118 +                                if( pEvent->parameterValue(identifier.first) < *identifier.second ) return false;
119 +                        }
120 +
121 +                        // If control got this far then all of the thresholds passed, and
122 +                        // I can pass the event.
123 +                        return true;
124 +                }
125 +        protected:
126 +                std::vector< std::pair<l1menu::ReducedEvent::ParameterID,const float*> > identifiers_;
127 +        }; // end of class ReducedSampleCachedTrigger
128 +
129 +        TriggerRateImplementation::TriggerRateImplementation( const l1menu::ITrigger& trigger, float fraction, const MenuRateImplementation& menuRate )
130 +                : fraction_(fraction), menuRate_(menuRate)
131 +        {
132 +                pTrigger_=std::move( l1menu::TriggerTable::instance().copyTrigger(trigger) );
133 +        }
134 +        TriggerRateImplementation& TriggerRateImplementation::operator=( TriggerRateImplementation&& otherTriggerRate )
135 +        {
136 +                pTrigger_=std::move( otherTriggerRate.pTrigger_ );
137 +                fraction_=otherTriggerRate.fraction_;
138 +                // I can't change the menuRate_ reference, but that should already be set to the right one anyway.
139 +                return *this;
140 +        }
141 +        TriggerRateImplementation::~TriggerRateImplementation() {}
142 +        const l1menu::ITrigger& TriggerRateImplementation::trigger() const { return *pTrigger_; }
143 +        float TriggerRateImplementation::fraction() const { return fraction_; }
144 +        float TriggerRateImplementation::rate() const { return fraction_*menuRate_.scaling(); }
145 +
146 +        float sumWeights( const l1menuprotobuf::Run& run )
147 +        {
148 +                float returnValue=0;
149 +                for( const auto& event : run.event() )
150 +                {
151 +                        if( event.has_weight() ) returnValue+=event.weight();
152 +                        else returnValue+=1;
153 +                }
154 +                return returnValue;
155 +        }
156   }
157  
158   namespace l1menu
# Line 52 | Line 167 | namespace l1menu
167          private:
168                  l1menu::TriggerMenu mutableTriggerMenu_;
169          public:
170 <                ReducedMenuSamplePrivateMembers( const l1menu::TriggerMenu& newTriggerMenu );
171 <                ReducedMenuSamplePrivateMembers( const std::string& filename );
172 <                void copyMenuToProtobufSample();
173 <                ::ReducedEventImplementation event;
174 <                const l1menu::TriggerMenu& triggerMenu;
170 >                ReducedMenuSamplePrivateMembers( const l1menu::ReducedMenuSample& thisObject, const l1menu::TriggerMenu& newTriggerMenu );
171 >                ReducedMenuSamplePrivateMembers( const l1menu::ReducedMenuSample& thisObject, const std::string& filename );
172 >                //void copyMenuToProtobufSample();
173 >                l1menu::ReducedEvent event;
174 >                const l1menu::TriggerMenu& triggerMenu; // External const access to mutableTriggerMenu_
175 >                float eventRate;
176 >                float sumOfWeights;
177                  l1menuprotobuf::SampleHeader protobufSampleHeader;
178                  // Protobuf doesn't implement move semantics so I'll use pointers
179                  std::vector<std::unique_ptr<l1menuprotobuf::Run> > protobufRuns;
# Line 70 | Line 187 | namespace l1menu
187          const std::string ReducedMenuSamplePrivateMembers::FILE_FORMAT_MAGIC_NUMBER="l1menuReducedMenuSample";
188   }
189  
190 < l1menu::ReducedMenuSamplePrivateMembers::ReducedMenuSamplePrivateMembers( const l1menu::TriggerMenu& newTriggerMenu )
191 <        : mutableTriggerMenu_( newTriggerMenu ), triggerMenu( mutableTriggerMenu_ )
190 > l1menu::ReducedMenuSamplePrivateMembers::ReducedMenuSamplePrivateMembers( const l1menu::ReducedMenuSample& thisObject, const l1menu::TriggerMenu& newTriggerMenu )
191 >        : mutableTriggerMenu_( newTriggerMenu ), event(thisObject), triggerMenu( mutableTriggerMenu_ ), eventRate(1), sumOfWeights(0)
192   {
193          GOOGLE_PROTOBUF_VERIFY_VERSION;
194  
# Line 99 | Line 216 | l1menu::ReducedMenuSamplePrivateMembers:
216  
217                  // Make a note of the names of the parameters that are recorded for each event. For this
218                  // I'm just recording the parameters that refer to the thresholds.
219 <                const auto thresholdNames=l1menu::getThresholdNames(trigger);
219 >                const auto thresholdNames=l1menu::tools::getThresholdNames(trigger);
220                  for( const auto& thresholdName : thresholdNames ) pProtobufTrigger->add_varying_parameter(thresholdName);
221  
222          } // end of loop over triggers
# Line 110 | Line 227 | l1menu::ReducedMenuSamplePrivateMembers:
227  
228   }
229  
230 < l1menu::ReducedMenuSamplePrivateMembers::ReducedMenuSamplePrivateMembers( const std::string& filename )
231 <        : triggerMenu(mutableTriggerMenu_)
230 > l1menu::ReducedMenuSamplePrivateMembers::ReducedMenuSamplePrivateMembers( const l1menu::ReducedMenuSample& thisObject, const std::string& filename )
231 >        : event(thisObject), triggerMenu(mutableTriggerMenu_), eventRate(1), sumOfWeights(0)
232   {
233          GOOGLE_PROTOBUF_VERIFY_VERSION;
234  
# Line 120 | Line 237 | l1menu::ReducedMenuSamplePrivateMembers:
237          if( fileDescriptor==0 ) throw std::runtime_error( "ReducedMenuSample initialise from file - couldn't open file" );
238          ::UnixFileSentry fileSentry( fileDescriptor ); // Use this as an exception safe way of closing the input file
239          google::protobuf::io::FileInputStream fileInput( fileDescriptor );
240 +
241 +        // First read the magic number at the start of the file and make sure it
242 +        // matches what I expect. This is uncompressed so I'll wrap it in a block
243 +        // to make sure the CodedInputStream is destructed before creating a new
244 +        // one with gzip input.
245 +        {
246 +                google::protobuf::io::CodedInputStream codedInput( &fileInput );
247 +
248 +                // As a read buffer, I'll create a string the correct size (filled with an arbitrary
249 +                // character) and read straight into that.
250 +                std::string readMagicNumber;
251 +                if( !codedInput.ReadString( &readMagicNumber, FILE_FORMAT_MAGIC_NUMBER.size() ) ) throw std::runtime_error( "ReducedMenuSample initialise from file - error reading magic number" );
252 +                if( readMagicNumber!=FILE_FORMAT_MAGIC_NUMBER ) throw std::runtime_error( "ReducedMenuSample - tried to initialise with a file that is not the correct format" );
253 +
254 +                google::protobuf::uint32 fileformatVersion;
255 +                if( !codedInput.ReadVarint32( &fileformatVersion ) ) throw std::runtime_error( "ReducedMenuSample initialise from file - error reading file format version" );
256 +                // So far I only have (and ever expect to have) one version of the file
257 +                // format, imaginatively versioned "1". You never know though...
258 +                if( fileformatVersion>1 ) std::cerr << "Warning: Attempting to read a ReducedMenuSample with version " << fileformatVersion << " with code that only knows up to version 1." << std::endl;
259 +        }
260 +
261          google::protobuf::io::GzipInputStream gzipInput( &fileInput );
262          google::protobuf::io::CodedInputStream codedInput( &gzipInput );
263  
264 <        // First read the magic number at the start of the file and make sure it
265 <        // matches what I expect. As a read buffer, I'll create a string the correct
266 <        // size (filled with an arbitrary character) and read straight into that.
267 <        std::string readMagicNumber;
268 <        if( !codedInput.ReadString( &readMagicNumber, FILE_FORMAT_MAGIC_NUMBER.size() ) ) throw std::runtime_error( "ReducedMenuSample initialise from file - error reading magic number" );
131 <        if( readMagicNumber!=FILE_FORMAT_MAGIC_NUMBER ) throw std::runtime_error( "ReducedMenuSample - tried to initialise with a file that is not the correct format" );
132 <
133 <        google::protobuf::uint32 fileformatVersion;
134 <        if( !codedInput.ReadVarint32( &fileformatVersion ) ) throw std::runtime_error( "ReducedMenuSample initialise from file - error reading file format version" );
135 <        // So far I only have (and ever expect to have) one version of the file
136 <        // format, imaginatively versioned "1". You never know though...
137 <        if( fileformatVersion>1 ) std::cerr << "Warning: Attempting to read a ReducedMenuSample with version " << fileformatVersion << " with code that only knows up to version 1." << std::endl;
264 >        // Disable warnings on this input stream (second parameter, -1). The
265 >        // first parameter is the default. I'll change this if necessary in
266 >        // the loop later.
267 >        size_t totalBytesLimit=67108864;
268 >        codedInput.SetTotalBytesLimit( totalBytesLimit, -1 );
269  
270          google::protobuf::uint64 messageSize;
271  
# Line 149 | Line 280 | l1menu::ReducedMenuSamplePrivateMembers:
280          {
281                  readLimit=codedInput.PushLimit(messageSize);
282  
283 +                // Make sure the CodedInputStream doesn't refuse to read the message because it's
284 +                // read too much already. I'll also add an arbitrary 50 on to always make sure
285 +                // I can read the next messageSize if there is one.
286 +                if( gzipInput.ByteCount()+messageSize+50 > totalBytesLimit )
287 +                {
288 +                        totalBytesLimit+=messageSize*5; // Might as well set it a little higher than necessary while I'm at it.
289 +                        codedInput.SetTotalBytesLimit( totalBytesLimit, -1 );
290 +                }
291                  std::unique_ptr<l1menuprotobuf::Run> pNewRun( new l1menuprotobuf::Run );
292                  if( !pNewRun->ParseFromCodedStream( &codedInput ) ) throw std::runtime_error( "ReducedMenuSample initialise from file - some unknown error while reading run" );
293                  protobufRuns.push_back( std::move( pNewRun ) );
# Line 165 | Line 304 | l1menu::ReducedMenuSamplePrivateMembers:
304                  protobufRuns.push_back( std::move( pNewRun ) );
305          }
306  
307 +        // Count up the sum of the weights of all events
308 +        for( const auto& pRun : protobufRuns )
309 +        {
310 +                sumOfWeights+=sumWeights( *pRun );
311 +        }
312 +
313          // I have all of the information in the protobuf members, but I also need the trigger information
314          // in the form of l1menu::TriggerMenu. Copy out the required information.
315          for( int triggerNumber=0; triggerNumber<protobufSampleHeader.trigger_size(); ++triggerNumber )
# Line 189 | Line 334 | l1menu::ReducedMenuSamplePrivateMembers:
334   }
335  
336   l1menu::ReducedMenuSample::ReducedMenuSample( const l1menu::MenuSample& originalSample, const l1menu::TriggerMenu& triggerMenu )
337 <        : pImple_( new l1menu::ReducedMenuSamplePrivateMembers( triggerMenu ) )
337 >        : pImple_( new l1menu::ReducedMenuSamplePrivateMembers( *this, triggerMenu ) )
338   {
339          addSample( originalSample );
340   }
341  
342   l1menu::ReducedMenuSample::ReducedMenuSample( const l1menu::TriggerMenu& triggerMenu )
343 <        : pImple_( new l1menu::ReducedMenuSamplePrivateMembers( triggerMenu ) )
343 >        : pImple_( new l1menu::ReducedMenuSamplePrivateMembers( *this, triggerMenu ) )
344   {
345          // No operation besides the initialiser list
346   }
347  
348 + l1menu::ReducedMenuSample::ReducedMenuSample( const std::string& filename )
349 +        : pImple_( new l1menu::ReducedMenuSamplePrivateMembers( *this, filename ) )
350 + {
351 +        // No operation except the initialiser list
352 + }
353 +
354   l1menu::ReducedMenuSample::~ReducedMenuSample()
355   {
356          // No operation. Just need one defined otherwise the default one messes up
# Line 215 | Line 366 | void l1menu::ReducedMenuSample::addSampl
366          {
367                  // Split the events up into groups in arbitrary numbers. This is to get around
368                  // a protobuf aversion to long messages.
369 <                if( pCurrentRun->event_size() > pImple_->EVENTS_PER_RUN )
369 >                if( pCurrentRun->event_size() >= pImple_->EVENTS_PER_RUN )
370                  {
371                          // Gone over the arbitrary limit, so create a new protobuf Run and start
372                          // using that instead.
# Line 224 | Line 375 | void l1menu::ReducedMenuSample::addSampl
375                          pCurrentRun=pImple_->protobufRuns.back().get();
376                  }
377  
378 <                const l1menu::IEvent& event=originalSample.getEvent( eventNumber );
378 >                const l1menu::L1TriggerDPGEvent& event=originalSample.getEvent( eventNumber );
379                  l1menuprotobuf::Event* pProtobufEvent=pCurrentRun->add_event();
380  
381                  // Loop over all of the triggers
382                  for( size_t triggerNumber=0; triggerNumber<pImple_->triggerMenu.numberOfTriggers(); ++triggerNumber )
383                  {
384                          std::unique_ptr<l1menu::ITrigger> pTrigger=pImple_->triggerMenu.getTriggerCopy(triggerNumber);
385 <                        std::vector<std::string> thresholdNames=getThresholdNames(*pTrigger);
385 >                        std::vector<std::string> thresholdNames=l1menu::tools::getThresholdNames(*pTrigger);
386  
387                          try
388                          {
389 <                                setTriggerThresholdsAsTightAsPossible( event, *pTrigger, 0.001 );
389 >                                l1menu::tools::setTriggerThresholdsAsTightAsPossible( event, *pTrigger, 0.001 );
390                                  // Set all of the parameters to match the thresholds in the trigger
391                                  for( const auto& thresholdName : thresholdNames )
392                                  {
# Line 252 | Line 403 | void l1menu::ReducedMenuSample::addSampl
403  
404                  } // end of loop over triggers
405  
406 +                pImple_->sumOfWeights+=event.weight();
407          } // end of loop over events
408   }
409  
258 l1menu::ReducedMenuSample::ReducedMenuSample( const std::string& filename )
259        : pImple_( new l1menu::ReducedMenuSamplePrivateMembers( filename ) )
260 {
261        // No operation except the initialiser list
262 }
263
410   void l1menu::ReducedMenuSample::saveToFile( const std::string& filename ) const
411   {
412          // Open the file. Parameters are filename, write ability and create, rw-r--r-- permissions.
# Line 270 | Line 416 | void l1menu::ReducedMenuSample::saveToFi
416  
417          // Setup the protobuf file handlers
418          google::protobuf::io::FileOutputStream fileOutput( fileDescriptor );
419 +
420 +        // I want the magic number and file format identifier uncompressed, so
421 +        // I'll write those before switching to using gzipped output.
422 +        { // Block to make sure codedOutput is destructed before the gzip version is created
423 +                google::protobuf::io::CodedOutputStream codedOutput( &fileOutput );
424 +
425 +                // Write a magic number at the start of all files
426 +                codedOutput.WriteString( pImple_->FILE_FORMAT_MAGIC_NUMBER );
427 +                // Write an integer that specifies what version of the file format I'm using. I
428 +                // have no intention of changing the format but I might as well keep the option
429 +                // open.
430 +                codedOutput.WriteVarint32( 1 );
431 +        }
432 +
433          google::protobuf::io::GzipOutputStream gzipOutput( &fileOutput );
434          google::protobuf::io::CodedOutputStream codedOutput( &gzipOutput );
435  
276        // Write a magic number at the start of all files
277        codedOutput.WriteString( pImple_->FILE_FORMAT_MAGIC_NUMBER );
278        // Write an integer that specifies what version of the file format I'm using. I
279        // have no intention of changing the format but I might as well keep the option
280        // open.
281        codedOutput.WriteVarint32( 1 );
282
436          // Write the size of the header message into the file...
437          codedOutput.WriteVarint64( pImple_->protobufSampleHeader.ByteSize() );
438          // ...and then write the header
# Line 301 | Line 454 | size_t l1menu::ReducedMenuSample::number
454          return numberOfEvents;
455   }
456  
304 const l1menu::IReducedEvent& l1menu::ReducedMenuSample::getEvent( size_t eventNumber ) const
305 {
306        for( const auto& pRun : pImple_->protobufRuns )
307        {
308                if( eventNumber<static_cast<size_t>(pRun->event_size()) )
309                {
310                        pImple_->event.pProtobufEvent=pRun->mutable_event(eventNumber);
311                        return pImple_->event;
312                }
313                // Event must be in a later run, so reduce the number by how many events
314                // were in this run and look again.
315                eventNumber-=pRun->event_size();
316        }
317
318        // Should always find the event before getting to this point, so throw an
319        // exception if this happens.
320        throw std::runtime_error( "ReducedMenuSample::getEvent(eventNumber) was asked for an invalid eventNumber" );
321 }
322
457   const l1menu::TriggerMenu& l1menu::ReducedMenuSample::getTriggerMenu() const
458   {
459          return pImple_->triggerMenu;
# Line 348 | Line 482 | bool l1menu::ReducedMenuSample::contains
482                  // eta cuts or whatever.
483                  // I don't care if the thresholds don't match because that's what's stored in the
484                  // ReducedMenuSample.
485 <                std::vector<std::string> parameterNames=getNonThresholdParameterNames( trigger );
485 >                std::vector<std::string> parameterNames=l1menu::tools::getNonThresholdParameterNames( trigger );
486                  bool allParametersMatch=true;
487                  for( const auto& parameterName : parameterNames )
488                  {
# Line 394 | Line 528 | const std::map<std::string,size_t> l1men
528                  // ReducedMenuSample.
529                  if( triggerWasFound ) // Trigger can still fail, but no point doing this check if it already has
530                  {
531 <                        std::vector<std::string> parameterNames=getNonThresholdParameterNames( trigger );
531 >                        std::vector<std::string> parameterNames=l1menu::tools::getNonThresholdParameterNames( trigger );
532                          for( const auto& parameterName : parameterNames )
533                          {
534                                  if( trigger.parameter(parameterName)!=triggerInMenu.parameter(parameterName) ) triggerWasFound=false;
535                          }
536                  }
537  
538 <                std::vector<std::string> thresholdNames=l1menu::getThresholdNames(triggerInMenu);
538 >                std::vector<std::string> thresholdNames=l1menu::tools::getThresholdNames(triggerInMenu);
539                  if( triggerWasFound )
540                  {
541                          for( const auto& thresholdName : thresholdNames )
# Line 418 | Line 552 | const std::map<std::string,size_t> l1men
552          // (I guess - it would be a pretty pointless trigger though). To indicate the
553          // difference between that and a trigger that wasn't found I'll respectively
554          // return the empty vector or throw an exception.
555 <        if( !triggerWasFound ) throw std::runtime_error( "l1menu::ReducedMenuSample::getTriggerParameterIdentifiers() called for a trigger that was not used to create the sample" );
555 >        if( !triggerWasFound ) throw std::runtime_error( "l1menu::ReducedMenuSample::getTriggerParameterIdentifiers() called for a trigger that was not used to create the sample - "+trigger.name() );
556  
557          return returnValue;
558   }
559 +
560 + const l1menu::IEvent& l1menu::ReducedMenuSample::getEvent( size_t eventNumber ) const
561 + {
562 +        for( const auto& pRun : pImple_->protobufRuns )
563 +        {
564 +                if( eventNumber<static_cast<size_t>(pRun->event_size()) )
565 +                {
566 +                        pImple_->event.pProtobufEvent_=pRun->mutable_event(eventNumber);
567 +                        return pImple_->event;
568 +                }
569 +                // Event must be in a later run, so reduce the number by how many events
570 +                // were in this run and look again.
571 +                eventNumber-=pRun->event_size();
572 +        }
573 +
574 +        // Should always find the event before getting to this point, so throw an
575 +        // exception if this happens.
576 +        throw std::runtime_error( "ReducedMenuSample::getEvent(eventNumber) was asked for an invalid eventNumber" );
577 +
578 + }
579 +
580 + std::unique_ptr<l1menu::ICachedTrigger> l1menu::ReducedMenuSample::createCachedTrigger( const l1menu::ITrigger& trigger ) const
581 + {
582 +        return std::unique_ptr<l1menu::ICachedTrigger>( new CachedTriggerImplementation(*this,trigger) );
583 + }
584 +
585 + float l1menu::ReducedMenuSample::eventRate() const
586 + {
587 +        return pImple_->eventRate;
588 + }
589 +
590 + void l1menu::ReducedMenuSample::setEventRate( float rate )
591 + {
592 +        pImple_->eventRate=rate;
593 + }
594 +
595 + float l1menu::ReducedMenuSample::sumOfWeights() const
596 + {
597 +        return pImple_->sumOfWeights;
598 + }
599 +
600 + std::unique_ptr<const l1menu::IMenuRate> l1menu::ReducedMenuSample::rate( const l1menu::TriggerMenu& menu ) const
601 + {
602 +        // TODO make sure the TriggerMenu is valid for this sample
603 +
604 +        // I need a non-const menu, so make a copy
605 +        l1menu::TriggerMenu mutableMenu( menu );
606 +
607 +        // The number of events that pass each trigger
608 +        std::vector<size_t> numberOfEventsPassed( menu.numberOfTriggers() );
609 +        float numberOfEventsPassingAnyTrigger;
610 +
611 +        for( size_t triggerNumber=0; triggerNumber<menu.numberOfTriggers(); ++triggerNumber )
612 +        {
613 +                mutableMenu.getTrigger( triggerNumber ).initiateForReducedSample( *this );
614 +        }
615 +
616 +        for( size_t eventNumber=0; eventNumber<numberOfEvents(); ++eventNumber )
617 +        {
618 +                const l1menu::IEvent& event=getEvent(eventNumber);
619 +                bool anyTriggerPassed=false;
620 +
621 +                for( size_t triggerNumber=0; triggerNumber<menu.numberOfTriggers(); ++triggerNumber )
622 +                {
623 +                        if( event.passesTrigger( mutableMenu.getTrigger(triggerNumber) ) )
624 +                        {
625 +                                // If the event passes the trigger, increment the counter
626 +                                ++numberOfEventsPassed[triggerNumber];
627 +                                anyTriggerPassed=true;
628 +                        }
629 +                }
630 +
631 +                if( anyTriggerPassed ) ++numberOfEventsPassingAnyTrigger;
632 +        }
633 +
634 +        ::MenuRateImplementation* pRates=new ::MenuRateImplementation;
635 +        pRates->setScaling( pImple_->eventRate );
636 +        // This is the value I want to return, but I still need access to the extended attributes of the subclass
637 +        std::unique_ptr<const l1menu::IMenuRate> pReturnValue( pRates );
638 +
639 +        pRates->setTotalFraction( static_cast<float>(numberOfEventsPassingAnyTrigger)/static_cast<float>(numberOfEvents()) );
640 +
641 +        for( size_t triggerNumber=0; triggerNumber<numberOfEventsPassed.size(); ++triggerNumber )
642 +        {
643 +                float fraction=static_cast<float>(numberOfEventsPassed[triggerNumber])/static_cast<float>(numberOfEvents());
644 +                pRates->addTriggerRate( mutableMenu.getTrigger(triggerNumber), fraction );
645 +        }
646 +
647 +        return pReturnValue;
648 + }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines