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.11 by grimes, Mon Jun 24 14:47:38 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/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"
# Line 18 | Line 22
22  
23   namespace // unnamed namespace
24   {
21        class ReducedEventImplementation : public l1menu::IReducedEvent
22        {
23        public:
24                virtual ~ReducedEventImplementation() {}
25                virtual float parameterValue( size_t parameterNumber ) const {  return pProtobufEvent->threshold(parameterNumber); }
26                virtual float weight() const { if( pProtobufEvent->has_weight() ) return pProtobufEvent->weight(); else return 1; }
27                void setWeight( float newWeight ) { pProtobufEvent->set_weight(newWeight); }
28                l1menuprotobuf::Event* pProtobufEvent;
29        };
30
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 94 | Line 88 | namespace // unnamed namespace
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          {
# Line 111 | Line 143 | namespace // unnamed namespace
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 125 | 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;
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 144 | 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_ ), eventRate(1)
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 184 | 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 194 | 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  
# Line 203 | Line 267 | l1menu::ReducedMenuSamplePrivateMembers:
267          size_t totalBytesLimit=67108864;
268          codedInput.SetTotalBytesLimit( totalBytesLimit, -1 );
269  
206        // First read the magic number at the start of the file and make sure it
207        // matches what I expect. As a read buffer, I'll create a string the correct
208        // size (filled with an arbitrary character) and read straight into that.
209        std::string readMagicNumber;
210        if( !codedInput.ReadString( &readMagicNumber, FILE_FORMAT_MAGIC_NUMBER.size() ) ) throw std::runtime_error( "ReducedMenuSample initialise from file - error reading magic number" );
211        if( readMagicNumber!=FILE_FORMAT_MAGIC_NUMBER ) throw std::runtime_error( "ReducedMenuSample - tried to initialise with a file that is not the correct format" );
212
213        google::protobuf::uint32 fileformatVersion;
214        if( !codedInput.ReadVarint32( &fileformatVersion ) ) throw std::runtime_error( "ReducedMenuSample initialise from file - error reading file format version" );
215        // So far I only have (and ever expect to have) one version of the file
216        // format, imaginatively versioned "1". You never know though...
217        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;
218
270          google::protobuf::uint64 messageSize;
271  
272          // Read the size of the header message
# Line 253 | 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 277 | 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 312 | 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
# Line 340 | 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  
346 l1menu::ReducedMenuSample::ReducedMenuSample( const std::string& filename )
347        : pImple_( new l1menu::ReducedMenuSamplePrivateMembers( filename ) )
348 {
349        // No operation except the initialiser list
350 }
351
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 358 | 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  
364        // Write a magic number at the start of all files
365        codedOutput.WriteString( pImple_->FILE_FORMAT_MAGIC_NUMBER );
366        // Write an integer that specifies what version of the file format I'm using. I
367        // have no intention of changing the format but I might as well keep the option
368        // open.
369        codedOutput.WriteVarint32( 1 );
370
436          // Write the size of the header message into the file...
437          codedOutput.WriteVarint64( pImple_->protobufSampleHeader.ByteSize() );
438          // ...and then write the header
# Line 389 | Line 454 | size_t l1menu::ReducedMenuSample::number
454          return numberOfEvents;
455   }
456  
392 const l1menu::IReducedEvent& l1menu::ReducedMenuSample::getEvent( size_t eventNumber ) const
393 {
394        for( const auto& pRun : pImple_->protobufRuns )
395        {
396                if( eventNumber<static_cast<size_t>(pRun->event_size()) )
397                {
398                        pImple_->event.pProtobufEvent=pRun->mutable_event(eventNumber);
399                        return pImple_->event;
400                }
401                // Event must be in a later run, so reduce the number by how many events
402                // were in this run and look again.
403                eventNumber-=pRun->event_size();
404        }
405
406        // Should always find the event before getting to this point, so throw an
407        // exception if this happens.
408        throw std::runtime_error( "ReducedMenuSample::getEvent(eventNumber) was asked for an invalid eventNumber" );
409 }
410
457   const l1menu::TriggerMenu& l1menu::ReducedMenuSample::getTriggerMenu() const
458   {
459          return pImple_->triggerMenu;
# Line 511 | Line 557 | const std::map<std::string,size_t> l1men
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 ) const
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
# Line 539 | Line 615 | std::unique_ptr<const l1menu::IMenuRate>
615  
616          for( size_t eventNumber=0; eventNumber<numberOfEvents(); ++eventNumber )
617          {
618 <                const l1menu::IReducedEvent& event=getEvent(eventNumber);
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( mutableMenu.getTrigger( triggerNumber ).apply( event ) )
623 >                        if( event.passesTrigger( mutableMenu.getTrigger(triggerNumber) ) )
624                          {
625                                  // If the event passes the trigger, increment the counter
626                                  ++numberOfEventsPassed[triggerNumber];

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines