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