9 |
|
#include "l1menu/MenuSample.h" |
10 |
|
#include "l1menu/TriggerMenu.h" |
11 |
|
#include "l1menu/ITrigger.h" |
12 |
< |
#include "l1menu/tools.h" |
12 |
> |
#include "l1menu/IMenuRate.h" |
13 |
> |
#include "l1menu/ITriggerRate.h" |
14 |
> |
#include "l1menu/tools/tools.h" |
15 |
|
#include "protobuf/l1menu.pb.h" |
16 |
|
#include <google/protobuf/io/zero_copy_stream_impl.h> |
17 |
|
#include <google/protobuf/io/gzip_stream.h> |
40 |
|
private: |
41 |
|
int fileDescriptor_; |
42 |
|
}; |
43 |
+ |
|
44 |
+ |
class MenuRateImplementation; |
45 |
+ |
|
46 |
+ |
class TriggerRateImplementation : public l1menu::ITriggerRate |
47 |
+ |
{ |
48 |
+ |
public: |
49 |
+ |
TriggerRateImplementation( const l1menu::ITrigger& trigger, float fraction, const MenuRateImplementation& menuRate ); |
50 |
+ |
TriggerRateImplementation& operator=( TriggerRateImplementation&& otherTriggerRate ); // Move assignment |
51 |
+ |
virtual ~TriggerRateImplementation(); |
52 |
+ |
|
53 |
+ |
// Methods required by the l1menu::ITriggerRate interface |
54 |
+ |
virtual const l1menu::ITrigger& trigger() const; |
55 |
+ |
virtual float fraction() const; |
56 |
+ |
virtual float rate() const; |
57 |
+ |
protected: |
58 |
+ |
std::unique_ptr<l1menu::ITrigger> pTrigger_; |
59 |
+ |
float fraction_; |
60 |
+ |
const MenuRateImplementation& menuRate_; |
61 |
+ |
}; |
62 |
+ |
|
63 |
+ |
class MenuRateImplementation : public l1menu::IMenuRate |
64 |
+ |
{ |
65 |
+ |
public: |
66 |
+ |
void setTotalFraction( float fraction ) { totalFraction_=fraction; } |
67 |
+ |
void setScaling( float scaling ) { scaling_=scaling; } |
68 |
+ |
float scaling() const { return scaling_; } |
69 |
+ |
void addTriggerRate( const l1menu::ITrigger& trigger, float fraction ) { triggerRates_.push_back( std::move(TriggerRateImplementation(trigger,fraction,*this)) ); } |
70 |
+ |
// Methods required by the l1menu::IMenuRate interface |
71 |
+ |
virtual float totalFraction() const { return totalFraction_; } |
72 |
+ |
virtual float totalRate() const { return totalFraction_*scaling_; } |
73 |
+ |
virtual const std::vector<const l1menu::ITriggerRate*>& triggerRates() const |
74 |
+ |
{ |
75 |
+ |
// If the sizes are the same I'll assume nothing has changed and the references |
76 |
+ |
// are still valid. I don't expect this method to be called until the triggerRates_ |
77 |
+ |
// vector is complete anyway. |
78 |
+ |
if( triggerRates_.size()!=baseClassReferences_.size() ) |
79 |
+ |
{ |
80 |
+ |
baseClassReferences_.clear(); |
81 |
+ |
for( const auto& triggerRate : triggerRates_ ) |
82 |
+ |
{ |
83 |
+ |
baseClassReferences_.push_back( &triggerRate ); |
84 |
+ |
} |
85 |
+ |
} |
86 |
+ |
|
87 |
+ |
return baseClassReferences_; |
88 |
+ |
} |
89 |
+ |
|
90 |
+ |
protected: |
91 |
+ |
float totalFraction_; |
92 |
+ |
float scaling_; |
93 |
+ |
std::vector<TriggerRateImplementation> triggerRates_; |
94 |
+ |
mutable std::vector<const l1menu::ITriggerRate*> baseClassReferences_; |
95 |
+ |
}; |
96 |
+ |
|
97 |
+ |
TriggerRateImplementation::TriggerRateImplementation( const l1menu::ITrigger& trigger, float fraction, const MenuRateImplementation& menuRate ) |
98 |
+ |
: fraction_(fraction), menuRate_(menuRate) |
99 |
+ |
{ |
100 |
+ |
pTrigger_=std::move( l1menu::TriggerTable::instance().copyTrigger(trigger) ); |
101 |
+ |
} |
102 |
+ |
TriggerRateImplementation& TriggerRateImplementation::operator=( TriggerRateImplementation&& otherTriggerRate ) |
103 |
+ |
{ |
104 |
+ |
pTrigger_=std::move( otherTriggerRate.pTrigger_ ); |
105 |
+ |
fraction_=otherTriggerRate.fraction_; |
106 |
+ |
// I can't change the menuRate_ reference, but that should already be set to the right one anyway. |
107 |
+ |
return *this; |
108 |
+ |
} |
109 |
+ |
TriggerRateImplementation::~TriggerRateImplementation() {} |
110 |
+ |
const l1menu::ITrigger& TriggerRateImplementation::trigger() const { return *pTrigger_; } |
111 |
+ |
float TriggerRateImplementation::fraction() const { return fraction_; } |
112 |
+ |
float TriggerRateImplementation::rate() const { return fraction_*menuRate_.scaling(); } |
113 |
+ |
|
114 |
|
} |
115 |
|
|
116 |
|
namespace l1menu |
129 |
|
ReducedMenuSamplePrivateMembers( const std::string& filename ); |
130 |
|
void copyMenuToProtobufSample(); |
131 |
|
::ReducedEventImplementation event; |
132 |
< |
const l1menu::TriggerMenu& triggerMenu; |
132 |
> |
const l1menu::TriggerMenu& triggerMenu; // External const access to mutableTriggerMenu_ |
133 |
> |
float eventRate; |
134 |
|
l1menuprotobuf::SampleHeader protobufSampleHeader; |
135 |
|
// Protobuf doesn't implement move semantics so I'll use pointers |
136 |
|
std::vector<std::unique_ptr<l1menuprotobuf::Run> > protobufRuns; |
145 |
|
} |
146 |
|
|
147 |
|
l1menu::ReducedMenuSamplePrivateMembers::ReducedMenuSamplePrivateMembers( const l1menu::TriggerMenu& newTriggerMenu ) |
148 |
< |
: mutableTriggerMenu_( newTriggerMenu ), triggerMenu( mutableTriggerMenu_ ) |
148 |
> |
: mutableTriggerMenu_( newTriggerMenu ), triggerMenu( mutableTriggerMenu_ ), eventRate(1) |
149 |
|
{ |
150 |
|
GOOGLE_PROTOBUF_VERIFY_VERSION; |
151 |
|
|
173 |
|
|
174 |
|
// Make a note of the names of the parameters that are recorded for each event. For this |
175 |
|
// I'm just recording the parameters that refer to the thresholds. |
176 |
< |
const auto thresholdNames=l1menu::getThresholdNames(trigger); |
176 |
> |
const auto thresholdNames=l1menu::tools::getThresholdNames(trigger); |
177 |
|
for( const auto& thresholdName : thresholdNames ) pProtobufTrigger->add_varying_parameter(thresholdName); |
178 |
|
|
179 |
|
} // end of loop over triggers |
194 |
|
if( fileDescriptor==0 ) throw std::runtime_error( "ReducedMenuSample initialise from file - couldn't open file" ); |
195 |
|
::UnixFileSentry fileSentry( fileDescriptor ); // Use this as an exception safe way of closing the input file |
196 |
|
google::protobuf::io::FileInputStream fileInput( fileDescriptor ); |
197 |
+ |
|
198 |
+ |
// First read the magic number at the start of the file and make sure it |
199 |
+ |
// matches what I expect. This is uncompressed so I'll wrap it in a block |
200 |
+ |
// to make sure the CodedInputStream is destructed before creating a new |
201 |
+ |
// one with gzip input. |
202 |
+ |
{ |
203 |
+ |
google::protobuf::io::CodedInputStream codedInput( &fileInput ); |
204 |
+ |
|
205 |
+ |
// As a read buffer, I'll create a string the correct size (filled with an arbitrary |
206 |
+ |
// character) and read straight into that. |
207 |
+ |
std::string readMagicNumber; |
208 |
+ |
if( !codedInput.ReadString( &readMagicNumber, FILE_FORMAT_MAGIC_NUMBER.size() ) ) throw std::runtime_error( "ReducedMenuSample initialise from file - error reading magic number" ); |
209 |
+ |
if( readMagicNumber!=FILE_FORMAT_MAGIC_NUMBER ) throw std::runtime_error( "ReducedMenuSample - tried to initialise with a file that is not the correct format" ); |
210 |
+ |
|
211 |
+ |
google::protobuf::uint32 fileformatVersion; |
212 |
+ |
if( !codedInput.ReadVarint32( &fileformatVersion ) ) throw std::runtime_error( "ReducedMenuSample initialise from file - error reading file format version" ); |
213 |
+ |
// So far I only have (and ever expect to have) one version of the file |
214 |
+ |
// format, imaginatively versioned "1". You never know though... |
215 |
+ |
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; |
216 |
+ |
} |
217 |
+ |
|
218 |
|
google::protobuf::io::GzipInputStream gzipInput( &fileInput ); |
219 |
|
google::protobuf::io::CodedInputStream codedInput( &gzipInput ); |
220 |
|
|
224 |
|
size_t totalBytesLimit=67108864; |
225 |
|
codedInput.SetTotalBytesLimit( totalBytesLimit, -1 ); |
226 |
|
|
132 |
– |
// First read the magic number at the start of the file and make sure it |
133 |
– |
// matches what I expect. As a read buffer, I'll create a string the correct |
134 |
– |
// size (filled with an arbitrary character) and read straight into that. |
135 |
– |
std::string readMagicNumber; |
136 |
– |
if( !codedInput.ReadString( &readMagicNumber, FILE_FORMAT_MAGIC_NUMBER.size() ) ) throw std::runtime_error( "ReducedMenuSample initialise from file - error reading magic number" ); |
137 |
– |
if( readMagicNumber!=FILE_FORMAT_MAGIC_NUMBER ) throw std::runtime_error( "ReducedMenuSample - tried to initialise with a file that is not the correct format" ); |
138 |
– |
|
139 |
– |
google::protobuf::uint32 fileformatVersion; |
140 |
– |
if( !codedInput.ReadVarint32( &fileformatVersion ) ) throw std::runtime_error( "ReducedMenuSample initialise from file - error reading file format version" ); |
141 |
– |
// So far I only have (and ever expect to have) one version of the file |
142 |
– |
// format, imaginatively versioned "1". You never know though... |
143 |
– |
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; |
144 |
– |
|
227 |
|
google::protobuf::uint64 messageSize; |
228 |
|
|
229 |
|
// Read the size of the header message |
327 |
|
for( size_t triggerNumber=0; triggerNumber<pImple_->triggerMenu.numberOfTriggers(); ++triggerNumber ) |
328 |
|
{ |
329 |
|
std::unique_ptr<l1menu::ITrigger> pTrigger=pImple_->triggerMenu.getTriggerCopy(triggerNumber); |
330 |
< |
std::vector<std::string> thresholdNames=getThresholdNames(*pTrigger); |
330 |
> |
std::vector<std::string> thresholdNames=l1menu::tools::getThresholdNames(*pTrigger); |
331 |
|
|
332 |
|
try |
333 |
|
{ |
334 |
< |
setTriggerThresholdsAsTightAsPossible( event, *pTrigger, 0.001 ); |
334 |
> |
l1menu::tools::setTriggerThresholdsAsTightAsPossible( event, *pTrigger, 0.001 ); |
335 |
|
// Set all of the parameters to match the thresholds in the trigger |
336 |
|
for( const auto& thresholdName : thresholdNames ) |
337 |
|
{ |
366 |
|
|
367 |
|
// Setup the protobuf file handlers |
368 |
|
google::protobuf::io::FileOutputStream fileOutput( fileDescriptor ); |
369 |
+ |
|
370 |
+ |
// I want the magic number and file format identifier uncompressed, so |
371 |
+ |
// I'll write those before switching to using gzipped output. |
372 |
+ |
{ // Block to make sure codedOutput is destructed before the gzip version is created |
373 |
+ |
google::protobuf::io::CodedOutputStream codedOutput( &fileOutput ); |
374 |
+ |
|
375 |
+ |
// Write a magic number at the start of all files |
376 |
+ |
codedOutput.WriteString( pImple_->FILE_FORMAT_MAGIC_NUMBER ); |
377 |
+ |
// Write an integer that specifies what version of the file format I'm using. I |
378 |
+ |
// have no intention of changing the format but I might as well keep the option |
379 |
+ |
// open. |
380 |
+ |
codedOutput.WriteVarint32( 1 ); |
381 |
+ |
} |
382 |
+ |
|
383 |
|
google::protobuf::io::GzipOutputStream gzipOutput( &fileOutput ); |
384 |
|
google::protobuf::io::CodedOutputStream codedOutput( &gzipOutput ); |
385 |
|
|
290 |
– |
// Write a magic number at the start of all files |
291 |
– |
codedOutput.WriteString( pImple_->FILE_FORMAT_MAGIC_NUMBER ); |
292 |
– |
// Write an integer that specifies what version of the file format I'm using. I |
293 |
– |
// have no intention of changing the format but I might as well keep the option |
294 |
– |
// open. |
295 |
– |
codedOutput.WriteVarint32( 1 ); |
296 |
– |
|
386 |
|
// Write the size of the header message into the file... |
387 |
|
codedOutput.WriteVarint64( pImple_->protobufSampleHeader.ByteSize() ); |
388 |
|
// ...and then write the header |
451 |
|
// eta cuts or whatever. |
452 |
|
// I don't care if the thresholds don't match because that's what's stored in the |
453 |
|
// ReducedMenuSample. |
454 |
< |
std::vector<std::string> parameterNames=getNonThresholdParameterNames( trigger ); |
454 |
> |
std::vector<std::string> parameterNames=l1menu::tools::getNonThresholdParameterNames( trigger ); |
455 |
|
bool allParametersMatch=true; |
456 |
|
for( const auto& parameterName : parameterNames ) |
457 |
|
{ |
497 |
|
// ReducedMenuSample. |
498 |
|
if( triggerWasFound ) // Trigger can still fail, but no point doing this check if it already has |
499 |
|
{ |
500 |
< |
std::vector<std::string> parameterNames=getNonThresholdParameterNames( trigger ); |
500 |
> |
std::vector<std::string> parameterNames=l1menu::tools::getNonThresholdParameterNames( trigger ); |
501 |
|
for( const auto& parameterName : parameterNames ) |
502 |
|
{ |
503 |
|
if( trigger.parameter(parameterName)!=triggerInMenu.parameter(parameterName) ) triggerWasFound=false; |
504 |
|
} |
505 |
|
} |
506 |
|
|
507 |
< |
std::vector<std::string> thresholdNames=l1menu::getThresholdNames(triggerInMenu); |
507 |
> |
std::vector<std::string> thresholdNames=l1menu::tools::getThresholdNames(triggerInMenu); |
508 |
|
if( triggerWasFound ) |
509 |
|
{ |
510 |
|
for( const auto& thresholdName : thresholdNames ) |
521 |
|
// (I guess - it would be a pretty pointless trigger though). To indicate the |
522 |
|
// difference between that and a trigger that wasn't found I'll respectively |
523 |
|
// return the empty vector or throw an exception. |
524 |
< |
if( !triggerWasFound ) throw std::runtime_error( "l1menu::ReducedMenuSample::getTriggerParameterIdentifiers() called for a trigger that was not used to create the sample" ); |
524 |
> |
if( !triggerWasFound ) throw std::runtime_error( "l1menu::ReducedMenuSample::getTriggerParameterIdentifiers() called for a trigger that was not used to create the sample - "+trigger.name() ); |
525 |
|
|
526 |
|
return returnValue; |
527 |
|
} |
528 |
+ |
|
529 |
+ |
float l1menu::ReducedMenuSample::eventRate() const |
530 |
+ |
{ |
531 |
+ |
return pImple_->eventRate; |
532 |
+ |
} |
533 |
+ |
|
534 |
+ |
void l1menu::ReducedMenuSample::setEventRate( float rate ) const |
535 |
+ |
{ |
536 |
+ |
pImple_->eventRate=rate; |
537 |
+ |
} |
538 |
+ |
|
539 |
+ |
std::unique_ptr<const l1menu::IMenuRate> l1menu::ReducedMenuSample::rate( const l1menu::TriggerMenu& menu ) const |
540 |
+ |
{ |
541 |
+ |
// TODO make sure the TriggerMenu is valid for this sample |
542 |
+ |
|
543 |
+ |
// I need a non-const menu, so make a copy |
544 |
+ |
l1menu::TriggerMenu mutableMenu( menu ); |
545 |
+ |
|
546 |
+ |
// The number of events that pass each trigger |
547 |
+ |
std::vector<size_t> numberOfEventsPassed( menu.numberOfTriggers() ); |
548 |
+ |
float numberOfEventsPassingAnyTrigger; |
549 |
+ |
|
550 |
+ |
for( size_t triggerNumber=0; triggerNumber<menu.numberOfTriggers(); ++triggerNumber ) |
551 |
+ |
{ |
552 |
+ |
mutableMenu.getTrigger( triggerNumber ).initiateForReducedSample( *this ); |
553 |
+ |
} |
554 |
+ |
|
555 |
+ |
for( size_t eventNumber=0; eventNumber<numberOfEvents(); ++eventNumber ) |
556 |
+ |
{ |
557 |
+ |
const l1menu::IReducedEvent& event=getEvent(eventNumber); |
558 |
+ |
bool anyTriggerPassed=false; |
559 |
+ |
|
560 |
+ |
for( size_t triggerNumber=0; triggerNumber<menu.numberOfTriggers(); ++triggerNumber ) |
561 |
+ |
{ |
562 |
+ |
if( mutableMenu.getTrigger( triggerNumber ).apply( event ) ) |
563 |
+ |
{ |
564 |
+ |
// If the event passes the trigger, increment the counter |
565 |
+ |
++numberOfEventsPassed[triggerNumber]; |
566 |
+ |
anyTriggerPassed=true; |
567 |
+ |
} |
568 |
+ |
} |
569 |
+ |
|
570 |
+ |
if( anyTriggerPassed ) ++numberOfEventsPassingAnyTrigger; |
571 |
+ |
} |
572 |
+ |
|
573 |
+ |
::MenuRateImplementation* pRates=new ::MenuRateImplementation; |
574 |
+ |
pRates->setScaling( pImple_->eventRate ); |
575 |
+ |
// This is the value I want to return, but I still need access to the extended attributes of the subclass |
576 |
+ |
std::unique_ptr<const l1menu::IMenuRate> pReturnValue( pRates ); |
577 |
+ |
|
578 |
+ |
pRates->setTotalFraction( static_cast<float>(numberOfEventsPassingAnyTrigger)/static_cast<float>(numberOfEvents()) ); |
579 |
+ |
|
580 |
+ |
for( size_t triggerNumber=0; triggerNumber<numberOfEventsPassed.size(); ++triggerNumber ) |
581 |
+ |
{ |
582 |
+ |
float fraction=static_cast<float>(numberOfEventsPassed[triggerNumber])/static_cast<float>(numberOfEvents()); |
583 |
+ |
pRates->addTriggerRate( mutableMenu.getTrigger(triggerNumber), fraction ); |
584 |
+ |
} |
585 |
+ |
|
586 |
+ |
return pReturnValue; |
587 |
+ |
} |