ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/grimes/L1Menu/src/TriggerRatePlot.cpp
Revision: 1.9
Committed: Fri Jul 5 13:54:44 2013 UTC (11 years, 10 months ago) by grimes
Branch: MAIN
Changes since 1.8: +31 -35 lines
Log Message:
Moved some common code into a private method

File Contents

# User Rev Content
1 grimes 1.1 #include "l1menu/TriggerRatePlot.h"
2    
3     #include "l1menu/ITrigger.h"
4 grimes 1.5 #include "l1menu/ICachedTrigger.h"
5     #include "l1menu/L1TriggerDPGEvent.h"
6 grimes 1.1 #include "l1menu/IEvent.h"
7 grimes 1.8 #include "l1menu/ISample.h"
8 grimes 1.1 #include "l1menu/TriggerTable.h"
9     #include <TH1F.h>
10     #include <sstream>
11 grimes 1.6 #include <algorithm>
12 grimes 1.1
13 grimes 1.6 #include <iostream>
14    
15     l1menu::TriggerRatePlot::TriggerRatePlot( const l1menu::ITrigger& trigger, std::unique_ptr<TH1> pHistogram, const std::string& versusParameter, const std::vector<std::string> scaledParameters )
16 grimes 1.1 : pHistogram_( std::move(pHistogram) ), versusParameter_(versusParameter), histogramOwnedByMe_(true)
17     {
18     // Take a copy of the trigger
19     l1menu::TriggerTable& table=l1menu::TriggerTable::instance();
20     pTrigger_=table.copyTrigger( trigger );
21    
22     // Make sure the versusParameter_ supplied is valid. If it's not then this call will
23 grimes 1.6 // throw an exception. Take a pointer to the parameter so I don't need to keep performing
24     // expensive string comparisons.
25 grimes 1.2 pParameter_=&pTrigger_->parameter(versusParameter_);
26 grimes 1.1
27 grimes 1.6 // 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 grimes 1.1 // 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;
39     description << pTrigger_->name() << " rate versus " << versusParameter;
40    
41     // Loop over all of the parameters and add their values to the description
42     std::vector<std::string> parameterNames=pTrigger_->parameterNames();
43     description << " [v" << pTrigger_->version();
44     if( parameterNames.size()>1 ) 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 grimes 1.6
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 grimes 1.1 if( iName+1!=parameterNames.end() ) description << ","; // Add delimeter between parameter names
62     }
63     description << "]";
64    
65     pHistogram_->SetTitle( description.str().c_str() );
66    
67     }
68    
69     l1menu::TriggerRatePlot::TriggerRatePlot( l1menu::TriggerRatePlot&& otherTriggerRatePlot ) noexcept
70     : pTrigger_( std::move(otherTriggerRatePlot.pTrigger_) ), pHistogram_( std::move(otherTriggerRatePlot.pHistogram_) ),
71 grimes 1.6 versusParameter_( std::move(otherTriggerRatePlot.versusParameter_) ), pParameter_(&pTrigger_->parameter(versusParameter_)),
72     otherParameterScalings_( std::move(otherTriggerRatePlot.otherParameterScalings_) ), histogramOwnedByMe_(histogramOwnedByMe_)
73 grimes 1.1 {
74     // No operation besides the initaliser list
75     }
76    
77     l1menu::TriggerRatePlot& l1menu::TriggerRatePlot::operator=( l1menu::TriggerRatePlot&& otherTriggerRatePlot ) noexcept
78     {
79     // Free up whatever was there before
80     pTrigger_.reset();
81     if( histogramOwnedByMe_ ) pHistogram_.reset();
82     else pHistogram_.release();
83    
84     // Then copy from the other object
85     pTrigger_=std::move(otherTriggerRatePlot.pTrigger_);
86     pHistogram_=std::move(otherTriggerRatePlot.pHistogram_);
87     versusParameter_=std::move(otherTriggerRatePlot.versusParameter_);
88 grimes 1.6 pParameter_=&pTrigger_->parameter(versusParameter_);
89     otherParameterScalings_=std::move(otherTriggerRatePlot.otherParameterScalings_);
90 grimes 1.2 histogramOwnedByMe_=otherTriggerRatePlot.histogramOwnedByMe_;
91 grimes 1.1
92     return *this;
93     }
94    
95     l1menu::TriggerRatePlot::~TriggerRatePlot()
96     {
97     // If the flag has been set telling me that this instance doesn't own the histogram,
98     // then I need to tell the unique_ptr not to delete it.
99     if( !histogramOwnedByMe_ )
100     {
101     pHistogram_.release();
102     }
103     }
104    
105 grimes 1.7 void l1menu::TriggerRatePlot::addEvent( const l1menu::IEvent& event )
106 grimes 1.1 {
107 grimes 1.7 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 grimes 1.9 // 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 grimes 1.7 std::unique_ptr<l1menu::ICachedTrigger> pCachedTrigger=sample.createCachedTrigger( *pTrigger_ );
115    
116 grimes 1.9 addEvent( event, pCachedTrigger, weightPerEvent );
117 grimes 1.1 }
118    
119 grimes 1.5 void l1menu::TriggerRatePlot::addSample( const l1menu::ISample& sample )
120     {
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 grimes 1.9 addEvent( sample.getEvent(eventNumber), pCachedTrigger, weightPerEvent );
130     } // end of loop over events
131    
132     }
133 grimes 1.5
134 grimes 1.9 void l1menu::TriggerRatePlot::addEvent( const l1menu::IEvent& event, const std::unique_ptr<l1menu::ICachedTrigger>& pCachedTrigger, float weightPerEvent )
135     {
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_->GetBinLowEdge(binNumber);
143 grimes 1.6
144 grimes 1.9 // 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 grimes 1.6
149 grimes 1.9 if( pCachedTrigger->apply(event) ) // If the event passes the trigger
150     {
151     pHistogram_->Fill( pHistogram_->GetBinCenter(binNumber), event.weight()*weightPerEvent );
152     }
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 grimes 1.6
160 grimes 1.5 }
161    
162 grimes 1.3 const l1menu::ITrigger& l1menu::TriggerRatePlot::getTrigger() const
163     {
164     return *pTrigger_;
165     }
166    
167 grimes 1.1 TH1* l1menu::TriggerRatePlot::getPlot()
168     {
169     return pHistogram_.get();
170     }
171    
172     TH1* l1menu::TriggerRatePlot::relinquishOwnershipOfPlot()
173     {
174     // Rather than call release() on the unique_ptr, I'll set a flag so that I know
175     // to release() in the destructor instead. This way it's possible to relinquish
176     // ownership but still perform operations on the histograms.
177     histogramOwnedByMe_=false;
178     return pHistogram_.get();
179     }