1 |
|
#include "l1menu/TriggerRatePlot.h" |
2 |
|
|
3 |
|
#include "l1menu/ITrigger.h" |
4 |
+ |
#include "l1menu/ICachedTrigger.h" |
5 |
+ |
#include "l1menu/L1TriggerDPGEvent.h" |
6 |
|
#include "l1menu/IEvent.h" |
7 |
+ |
#include "l1menu/ISample.h" |
8 |
|
#include "l1menu/TriggerTable.h" |
6 |
– |
#include "l1menu/ReducedMenuSample.h" |
7 |
– |
#include "l1menu/IReducedEvent.h" |
9 |
|
#include <TH1F.h> |
9 |
– |
#include <iostream> |
10 |
|
#include <sstream> |
11 |
+ |
#include <algorithm> |
12 |
+ |
|
13 |
+ |
#include <iostream> |
14 |
|
|
15 |
< |
l1menu::TriggerRatePlot::TriggerRatePlot( const l1menu::ITrigger& trigger, std::unique_ptr<TH1> pHistogram, const std::string versusParameter ) |
15 |
> |
l1menu::TriggerRatePlot::TriggerRatePlot( const l1menu::ITrigger& trigger, std::unique_ptr<TH1> pHistogram, const std::string& versusParameter, const std::vector<std::string> scaledParameters ) |
16 |
|
: pHistogram_( std::move(pHistogram) ), versusParameter_(versusParameter), histogramOwnedByMe_(true) |
17 |
|
{ |
18 |
|
// Take a copy of the trigger |
20 |
|
pTrigger_=table.copyTrigger( trigger ); |
21 |
|
|
22 |
|
// Make sure the versusParameter_ supplied is valid. If it's not then this call will |
23 |
< |
// throw an exception. |
23 |
> |
// throw an exception. Take a pointer to the parameter so I don't need to keep performing |
24 |
> |
// expensive string comparisons. |
25 |
|
pParameter_=&pTrigger_->parameter(versusParameter_); |
26 |
|
|
27 |
+ |
// If any parameters have been requested to be scaled along with the versusParameter, figure |
28 |
+ |
// out what the scaling should be and take a note of pointers. |
29 |
+ |
for( const auto& parameterToScale : scaledParameters ) |
30 |
+ |
{ |
31 |
+ |
if( parameterToScale!=versusParameter_ ) |
32 |
+ |
{ |
33 |
+ |
otherParameterScalings_.push_back( std::make_pair( &pTrigger_->parameter(parameterToScale), pTrigger_->parameter(parameterToScale)/(*pParameter_) ) ); |
34 |
+ |
} |
35 |
+ |
} |
36 |
|
// I want to make a note of the other parameters set for the trigger. As far as I know TH1 |
37 |
|
// has no way of adding annotations so I'll tag it on the end of the title. |
38 |
|
std::stringstream description; |
45 |
|
for( std::vector<std::string>::const_iterator iName=parameterNames.begin(); iName!=parameterNames.end(); ++iName ) |
46 |
|
{ |
47 |
|
if( *iName==versusParameter ) continue; // Don't bother adding the parameter I'm plotting against |
48 |
< |
description << *iName << "=" << pTrigger_->parameter(*iName); |
48 |
> |
|
49 |
> |
// First check to see if this is one of the parameters that are being scaled |
50 |
> |
if( std::find(scaledParameters.begin(),scaledParameters.end(),*iName)==scaledParameters.end() ) |
51 |
> |
{ |
52 |
> |
// This parameter isn't being scaled, so write the absoulte value in the description |
53 |
> |
description << *iName << "=" << pTrigger_->parameter(*iName); |
54 |
> |
} |
55 |
> |
else |
56 |
> |
{ |
57 |
> |
// This parameter is being scaled, so write what the scaling is in the description |
58 |
> |
description << *iName << "=x*" << pTrigger_->parameter(*iName)/(*pParameter_); |
59 |
> |
} |
60 |
> |
|
61 |
|
if( iName+1!=parameterNames.end() ) description << ","; // Add delimeter between parameter names |
62 |
|
} |
63 |
|
description << "]"; |
68 |
|
|
69 |
|
l1menu::TriggerRatePlot::TriggerRatePlot( l1menu::TriggerRatePlot&& otherTriggerRatePlot ) noexcept |
70 |
|
: pTrigger_( std::move(otherTriggerRatePlot.pTrigger_) ), pHistogram_( std::move(otherTriggerRatePlot.pHistogram_) ), |
71 |
< |
versusParameter_( std::move(otherTriggerRatePlot.versusParameter_) ), pParameter_(otherTriggerRatePlot.pParameter_), |
72 |
< |
histogramOwnedByMe_(histogramOwnedByMe_) |
71 |
> |
versusParameter_( std::move(otherTriggerRatePlot.versusParameter_) ), pParameter_(&pTrigger_->parameter(versusParameter_)), |
72 |
> |
otherParameterScalings_( std::move(otherTriggerRatePlot.otherParameterScalings_) ), histogramOwnedByMe_(histogramOwnedByMe_) |
73 |
|
{ |
74 |
|
// No operation besides the initaliser list |
75 |
|
} |
85 |
|
pTrigger_=std::move(otherTriggerRatePlot.pTrigger_); |
86 |
|
pHistogram_=std::move(otherTriggerRatePlot.pHistogram_); |
87 |
|
versusParameter_=std::move(otherTriggerRatePlot.versusParameter_); |
88 |
< |
pParameter_=otherTriggerRatePlot.pParameter_; |
88 |
> |
pParameter_=&pTrigger_->parameter(versusParameter_); |
89 |
> |
otherParameterScalings_=std::move(otherTriggerRatePlot.otherParameterScalings_); |
90 |
|
histogramOwnedByMe_=otherTriggerRatePlot.histogramOwnedByMe_; |
91 |
|
|
92 |
|
return *this; |
104 |
|
|
105 |
|
void l1menu::TriggerRatePlot::addEvent( const l1menu::IEvent& event ) |
106 |
|
{ |
107 |
< |
// loop over all of the bins in the histogram, and see if the trigger passes |
108 |
< |
// for the value at the center of the bin. |
109 |
< |
for( int binNumber=1; binNumber<pHistogram_->GetNbinsX(); ++binNumber ) |
110 |
< |
{ |
111 |
< |
(*pParameter_)=pHistogram_->GetBinCenter(binNumber); |
112 |
< |
if( pTrigger_->apply( event ) ) |
113 |
< |
{ |
114 |
< |
pHistogram_->Fill( (*pParameter_), event.weight() ); |
115 |
< |
} |
116 |
< |
// could put an "else break" in here, but I don't know if triggers |
91 |
< |
// will run their thresholds the other way. E.g. a trigger could require |
92 |
< |
// a minimum amount of energy in the event, in which case the higher |
93 |
< |
// bins will pass. |
94 |
< |
} |
107 |
> |
const l1menu::ISample& sample=event.sample(); |
108 |
> |
float weightPerEvent=sample.eventRate()/sample.sumOfWeights(); |
109 |
> |
|
110 |
> |
// For some implementations of ISample, it is significantly faster to |
111 |
> |
// create ICachedTriggers and then loop over those. The addEvent overload |
112 |
> |
// I'm about to delegate to loops over the histogram bins, so even for |
113 |
> |
// one event this trigger can be called multiple times. |
114 |
> |
std::unique_ptr<l1menu::ICachedTrigger> pCachedTrigger=sample.createCachedTrigger( *pTrigger_ ); |
115 |
> |
|
116 |
> |
addEvent( event, pCachedTrigger, weightPerEvent ); |
117 |
|
} |
118 |
|
|
119 |
< |
void l1menu::TriggerRatePlot::initiateForReducedSample( const l1menu::ReducedMenuSample& sample ) |
119 |
> |
void l1menu::TriggerRatePlot::addSample( const l1menu::ISample& sample ) |
120 |
|
{ |
121 |
< |
pTrigger_->initiateForReducedSample( sample ); |
121 |
> |
float weightPerEvent=sample.eventRate()/sample.sumOfWeights(); |
122 |
> |
|
123 |
> |
// Create a cached trigger, which depending on the concrete type of the ISample |
124 |
> |
// may or may not significantly increase the speed at which this next loop happens. |
125 |
> |
std::unique_ptr<l1menu::ICachedTrigger> pCachedTrigger=sample.createCachedTrigger( *pTrigger_ ); |
126 |
> |
|
127 |
> |
for( size_t eventNumber=0; eventNumber<sample.numberOfEvents(); ++eventNumber ) |
128 |
> |
{ |
129 |
> |
addEvent( sample.getEvent(eventNumber), pCachedTrigger, weightPerEvent ); |
130 |
> |
} // end of loop over events |
131 |
> |
|
132 |
|
} |
133 |
|
|
134 |
< |
void l1menu::TriggerRatePlot::addEvent( const l1menu::IReducedEvent& event ) |
134 |
> |
void l1menu::TriggerRatePlot::addEvent( const l1menu::IEvent& event, const std::unique_ptr<l1menu::ICachedTrigger>& pCachedTrigger, float weightPerEvent ) |
135 |
|
{ |
136 |
< |
// Basically exactly the same as for the l1menu::IEvent version. I |
137 |
< |
// should probably template this. |
136 |
> |
// |
137 |
> |
// Loop over all of the bins and fill it if that threshold would |
138 |
> |
// have passed the trigger. |
139 |
> |
// |
140 |
|
for( int binNumber=1; binNumber<pHistogram_->GetNbinsX(); ++binNumber ) |
141 |
|
{ |
142 |
< |
(*pParameter_)=pHistogram_->GetBinCenter(binNumber); |
143 |
< |
if( pTrigger_->apply( event ) ) |
142 |
> |
(*pParameter_)=pHistogram_->GetBinLowEdge(binNumber); |
143 |
> |
|
144 |
> |
// Scale accordingly any other parameters that should be scaled. Remember that |
145 |
> |
// in parameterScalingPair, 'first' is a pointer to the threshold to be changed |
146 |
> |
// and 'second' is the ratio of the first threshold it should be. |
147 |
> |
for( const auto& parameterScalingPair : otherParameterScalings_ ) *(parameterScalingPair.first)=parameterScalingPair.second*(*pParameter_); |
148 |
> |
|
149 |
> |
if( pCachedTrigger->apply(event) ) // If the event passes the trigger |
150 |
|
{ |
151 |
< |
pHistogram_->Fill( (*pParameter_), event.weight() ); |
151 |
> |
pHistogram_->Fill( pHistogram_->GetBinCenter(binNumber), event.weight()*weightPerEvent ); |
152 |
|
} |
153 |
< |
} |
153 |
> |
else break; |
154 |
> |
// Not sure if this "else break" is a good idea. I don't know if triggers |
155 |
> |
// will run their thresholds the other way. E.g. a trigger could require |
156 |
> |
// a minimum amount of energy in the event, in which case the higher |
157 |
> |
// bins will pass. |
158 |
> |
} // end of loop over histogram bins |
159 |
> |
|
160 |
> |
} |
161 |
|
|
162 |
+ |
const l1menu::ITrigger& l1menu::TriggerRatePlot::getTrigger() const |
163 |
+ |
{ |
164 |
+ |
return *pTrigger_; |
165 |
|
} |
166 |
|
|
167 |
|
TH1* l1menu::TriggerRatePlot::getPlot() |