CMS 3D CMS Logo

BackgroundHandler.cc
Go to the documentation of this file.
1 #ifndef BackgroundHandler_cc
2 #define BackgroundHandler_cc
3 
5 #include <algorithm>
6 #include <TF1.h>
7 #include <iostream>
8 #include <boost/foreach.hpp>
9 
11 
12 BackgroundHandler::BackgroundHandler( const std::vector<int> & identifiers,
13  const std::vector<double> & leftWindowBorders,
14  const std::vector<double> & rightWindowBorders,
15  const double * ResMass,
16  const double * massWindowHalfWidth )
17 {
18  // : leftWindowFactors_(leftWindowFactors),
19  // rightWindowFactors_(rightWindowFactors)
20 
21  // Define the correspondence between regions and halfWidth to use
22  // Defines also the function type to use (but they are checked to be consistent over a region)
23  regToResHW_[0] = 0; // Region 0 use the one from Z
24  regToResHW_[1] = 3; // Region 1 use the one from Upsilon1S
25  regToResHW_[2] = 5; // Region 2 use the one from J/Psi
26 
27  // Define the correspondence between resonances and regions
28  resToReg_[0] = 0; // Z
29  resToReg_[1] = 1; // Upsilon3S
30  resToReg_[2] = 1; // Upsilon2S
31  resToReg_[3] = 1; // Upsilon1S
32  resToReg_[4] = 2; // Psi2S
33  resToReg_[5] = 2; // J/Psi
34 
35  // Throws cms::Exception("Configuration") in case the parameters are not what is expected
36  consistencyCheck(identifiers, leftWindowBorders, rightWindowBorders);
37 
38  // Build the resonance windows
39  for( unsigned int i=0; i<6; ++i ) {
40  double mass = ResMass[i];
41  double lowerLimit = mass - massWindowHalfWidth[i];
42  double upperLimit = mass + massWindowHalfWidth[i];
43  resonanceWindow_.push_back( MassWindow( mass, lowerLimit, upperLimit,
44  std::vector<unsigned int>(1,i),
46  lowerLimit,
47  upperLimit) ) );
48  }
49 
50  // Build the background windows
51  // ----------------------------
52  // Compute the mass center of each region
53  double resMassForRegion[3];
54  resMassForRegion[0] = ResMass[0];
55  resMassForRegion[1] = (ResMass[1]+ResMass[2]+ResMass[3])/3;
56  resMassForRegion[2] = (ResMass[4]+ResMass[5])/2;
57 
58  // Define which resonance is in which background window
59  std::vector<std::vector<unsigned int> > indexes;
60  indexes.push_back(std::vector<unsigned int>(1,0));
61  indexes.push_back(std::vector<unsigned int>());
62  for( int i=1; i<=3; ++i ) { indexes[1].push_back(i); }
63  indexes.push_back(std::vector<unsigned int>());
64  for( int i=4; i<=5; ++i ) { indexes[2].push_back(i); }
65 
66  unsigned int i=0;
67  typedef std::vector<unsigned int> indexVec;
68  BOOST_FOREACH(const indexVec & index, indexes) {
69  // double lowerLimit = resMassForRegion[i] - massWindowHalfWidth[regToResHW_[i]]*leftWindowFactors[i];
70  // double upperLimit = resMassForRegion[i] + massWindowHalfWidth[regToResHW_[i]]*rightWindowFactors[i];
71  // backgroundWindow_.push_back( MassWindow( resMassForRegion[i], lowerLimit, upperLimit, index,
72  // backgroundFunctionService(identifiers[i], lowerLimit, upperLimit ) ) );
73  backgroundWindow_.push_back( MassWindow( resMassForRegion[i], leftWindowBorders[i], rightWindowBorders[i], index,
74  backgroundFunctionService(identifiers[i], leftWindowBorders[i], rightWindowBorders[i] ) ) );
75  ++i;
76  }
77  // Initialize the parNums to be used in the shifts of parval
79 }
80 
82 {
83 }
84 
86 {
87  // Initialize the parNums to be used in the shifts of parval
88  parNumsRegions_[0] = 0;
89  for( unsigned int i=1; i<backgroundWindow_.size() ; ++i ) {
90  parNumsRegions_[i] = parNumsRegions_[i-1] + backgroundWindow_[i-1].backgroundFunction()->parNum();
91  }
92  parNumsResonances_[0] = parNumsRegions_[2]+backgroundWindow_[2].backgroundFunction()->parNum();
93  for( unsigned int i=1; i<resonanceWindow_.size() ; ++i ) {
94  parNumsResonances_[i] = parNumsResonances_[i-1] + resonanceWindow_[i-1].backgroundFunction()->parNum();
95  }
96 }
97 
98 void BackgroundHandler::setParameters(double* Start, double* Step, double* Mini, double* Maxi, int* ind, TString* parname, const std::vector<double> & parBgr, const std::vector<int> & parBgrOrder, const int muonType)
99 {
100  std::vector<double>::const_iterator parBgrIt = parBgr.begin();
101  std::vector<int>::const_iterator parBgrOrderIt = parBgrOrder.begin();
102  // Set the parameters for the regions only if this is not a rescaling
103  for( int iReg = 0; iReg < 3; ++iReg ) {
104  int shift = parNumsRegions_[iReg];
105  backgroundWindow_[iReg].backgroundFunction()->setParameters( &(Start[shift]), &(Step[shift]), &(Mini[shift]),
106  &(Maxi[shift]), &(ind[shift]), &(parname[shift]),
107  parBgrIt+shift, parBgrOrderIt+shift, muonType );
108  }
109  for( int iRes = 0; iRes < 6; ++iRes ) {
110  // parNumsResonances is already shifted for the regions parameters
111  int shift = parNumsResonances_[iRes];
112  resonanceWindow_[iRes].backgroundFunction()->setParameters( &(Start[shift]), &(Step[shift]), &(Mini[shift]),
113  &(Maxi[shift]), &(ind[shift]), &(parname[shift]),
114  parBgrIt+shift, parBgrOrderIt+shift, muonType );
115  }
116 }
117 
118 bool BackgroundHandler::unlockParameter(const std::vector<int> & resfind, const unsigned int ipar)
119 {
120  // parNumsRegions_ are shifted: [1] contains the number of parameters for 0 and so on.
121  if( ipar < unsigned(parNumsRegions_[1]) && resfind[0] > 0 ) {
122  return true;
123  }
124  if( ipar >= unsigned(parNumsRegions_[1]) && ipar < unsigned(parNumsRegions_[2]) && ( resfind[1] > 0 || resfind[2] > 0 || resfind[3] > 0 ) ) {
125  return true;
126  }
127  // The first of parNumsResonances_ has the sum of parNums of the regions.
128  if( ipar >= unsigned(parNumsRegions_[2]) && ipar < unsigned(parNumsResonances_[0]) && ( resfind[4] > 0 || resfind[5] > 0 ) ) {
129  return true;
130  }
131  return false;
132 }
133 
134 // std::pair<double, double> BackgroundHandler::windowFactors( const bool doBackgroundFit, const int ires )
135 // {
136 // if( doBackgroundFit ) {
137 // // Fitting the background: use the regions
138 // return std::make_pair(leftWindowFactors_[resToReg_[ires]], rightWindowFactors_[resToReg_[ires]]);
139 // }
140 // else {
141 // // Not fitting the background: use the resonances
142 // return std::make_pair(1.,1.);
143 // }
144 // }
145 
146 std::pair<double, double> BackgroundHandler::windowBorders( const bool doBackgroundFit, const int ires )
147 {
148  if( doBackgroundFit ) {
149  // Fitting the background: use the regions
150  return std::make_pair(backgroundWindow_[resToReg_[ires]].lowerBound(), backgroundWindow_[resToReg_[ires]].upperBound());
151  }
152  else {
153  // Not fitting the background: use the resonances
154  // return std::make_pair(1.,1.);
155  return std::make_pair(resonanceWindow_[ires].lowerBound(), resonanceWindow_[ires].upperBound());
156  }
157 }
158 
159 double BackgroundHandler::resMass( const bool doBackgroundFit, const int ires )
160 {
161  if( doBackgroundFit ) {
162  // Fitting the background: use the regions
163  return backgroundWindow_[resToReg_[ires]].mass();
164  }
165  else {
166  // Not fitting the background: use the resonances
167  return resonanceWindow_[ires].mass();
168  }
169 }
170 
171 void BackgroundHandler::rescale( std::vector<double> & parBgr, const double * ResMass, const double * massWindowHalfWidth,
172  const std::vector<std::pair<reco::Particle::LorentzVector,reco::Particle::LorentzVector> > & muonPairs,
173  const double & weight )
174 {
175  countEventsInAllWindows(muonPairs, weight);
176 
177  // Loop on all regions and on all the resonances of each region and compute the background fraction
178  // for each resonance window.
179  unsigned int iRegion = 0;
180  BOOST_FOREACH(MassWindow & backgroundWindow, backgroundWindow_)
181  {
182  // Iterator pointing to the first parameter of this background function in the full set of parameters
183  std::vector<double>::const_iterator parBgrIt = (parBgr.begin()+parNumsRegions_[iRegion]);
184  TF1 * backgroundFunctionForIntegral = backgroundWindow.backgroundFunction()->functionForIntegral(parBgrIt);
185  // WARNING: this expects the background fraction parameter to be parBgr[0] for all the background functions.
186  double kOld = *parBgrIt;
187  double Nbw = backgroundWindow.events();
188  double Ibw = backgroundFunctionForIntegral->Integral(backgroundWindow.lowerBound(),
189  backgroundWindow.upperBound());
190 
191  // index is the index of the resonance in the background window
192  BOOST_FOREACH( unsigned int index, *(backgroundWindow.indexes()) )
193  {
194  // First set all parameters of the resonance window background function to those of the corresponding region
195  for( int iPar = 0; iPar < resonanceWindow_[index].backgroundFunction()->parNum(); ++iPar ) {
196  parBgr[parNumsResonances_[index]+iPar] = parBgr[parNumsRegions_[resToReg_[index]]+iPar];
197  }
198  // Estimated fraction of events in the resonance window
199  double Irw = backgroundFunctionForIntegral->Integral(resonanceWindow_[index].lowerBound(),
200  resonanceWindow_[index].upperBound());
201  double Nrw = resonanceWindow_[index].events();
202 
203  // Ibw is 1 (to avoid effects from approximation errors we set it to 1 and do not include it in the computation).
204  if( Nrw != 0 ) parBgr[parNumsResonances_[index]] = kOld*Nbw/Nrw*Irw;
205  else parBgr[parNumsResonances_[index]] = 0.;
206 
207  // Protect against fluctuations of number of events which could cause the fraction to go above 1.
208  if( parBgr[parNumsResonances_[index]] > 1. ) parBgr[parNumsResonances_[index]] = 1.;
209 
210  double kNew = parBgr[parNumsResonances_[index]];
211  std::cout << "For resonance = " << index << std::endl;
212  std::cout << "backgroundWindow.lowerBound = " << backgroundWindow.lowerBound() << std::endl;
213  std::cout << "backgroundWindow.upperBound = " << backgroundWindow.upperBound() << std::endl;
214  std::cout << "parNumsResonances_["<<index<<"] = " << parNumsResonances_[index] << std::endl;
215  std::cout << "Nbw = " << Nbw << ", Ibw = " << Ibw << std::endl;
216  std::cout << "Nrw = " << Nrw << ", Irw = " << Irw << std::endl;
217  std::cout << "k = " << kOld << ", k' = " << parBgr[parNumsResonances_[index]] << std::endl;
218  std::cout << "background fraction in background window = Nbw*k = " << Nbw*kOld << std::endl;
219  std::cout << "background fraction in resonance window = Nrw*k' = " << Nrw*kNew << std::endl;
220  }
221  ++iRegion;
222  delete backgroundFunctionForIntegral;
223  }
224 }
225 
226 std::pair<double, double> BackgroundHandler::backgroundFunction( const bool doBackgroundFit,
227  const double * parval, const int resTotNum, const int ires,
228  const bool * resConsidered, const double * ResMass, const double ResHalfWidth[],
229  const int MuonType, const double & mass,
230  const double & eta1, const double & eta2 )
231 {
232  if( doBackgroundFit ) {
233  // Return the values for the region
234  int iReg = resToReg_[ires];
235  // return std::make_pair( parval[parNumsRegions_[iReg]] * backgroundWindow_[iReg].backgroundFunction()->fracVsEta(&(parval[parNumsRegions_[iReg]]), resEta),
236  return std::make_pair( parval[parNumsRegions_[iReg]] * backgroundWindow_[iReg].backgroundFunction()->fracVsEta(&(parval[parNumsRegions_[iReg]]), eta1, eta2 ),
237  (*(backgroundWindow_[iReg].backgroundFunction()))( &(parval[parNumsRegions_[iReg]]), mass, eta1, eta2 ) );
238  // return std::make_pair( backgroundWindow_[iReg].backgroundFunction()->fracVsEta(&(parval[parNumsRegions_[iReg]]), eta1, eta2),
239  // (*(backgroundWindow_[iReg].backgroundFunction()))( &(parval[parNumsRegions_[iReg]]), mass, eta1, eta2 ) );
240  }
241  // Return the values for the resonance
242  // return std::make_pair( parval[parNumsResonances_[ires]] * resonanceWindow_[ires].backgroundFunction()->fracVsEta(&(parval[parNumsResonances_[ires]]), resEta),
243  // (*(resonanceWindow_[ires].backgroundFunction()))( &(parval[parNumsResonances_[ires]]), mass, resEta ) );
244  return std::make_pair( parval[parNumsResonances_[ires]] * resonanceWindow_[ires].backgroundFunction()->fracVsEta(&(parval[parNumsResonances_[ires]]), eta1, eta2),
245  (*(resonanceWindow_[ires].backgroundFunction()))( &(parval[parNumsResonances_[ires]]), mass, eta1, eta2 ) );
246 }
247 
248 void BackgroundHandler::countEventsInAllWindows(const std::vector<std::pair<reco::Particle::LorentzVector,reco::Particle::LorentzVector> > & muonPairs,
249  const double & weight)
250 {
251  // First reset all the counters
252  BOOST_FOREACH(MassWindow & resonanceWindow, resonanceWindow_) {
253  resonanceWindow.resetCounter();
254  }
255  // Count events in background windows
256  BOOST_FOREACH(MassWindow & backgroundWindow, backgroundWindow_) {
257  backgroundWindow.resetCounter();
258  }
259 
260  // Now count the events in each window
261  std::pair<lorentzVector,lorentzVector> muonPair;
262  BOOST_FOREACH(muonPair, muonPairs) {
263  // Count events in resonance windows
264  BOOST_FOREACH(MassWindow & resonanceWindow, resonanceWindow_) {
265  resonanceWindow.count((muonPair.first + muonPair.second).mass(), weight);
266  }
267  // Count events in background windows
268  BOOST_FOREACH(MassWindow & backgroundWindow, backgroundWindow_) {
269  backgroundWindow.count((muonPair.first + muonPair.second).mass(), weight);
270  }
271  }
272 }
273 
274 void BackgroundHandler::consistencyCheck(const std::vector<int> & identifiers,
275  const std::vector<double> & leftWindowBorders,
276  const std::vector<double> & rightWindowBorders) const noexcept(false)
277 {
278  if( leftWindowBorders.size() != rightWindowBorders.size() ) {
279  throw cms::Exception("Configuration") << "BackgroundHandler::BackgroundHandler: leftWindowBorders.size() = " << leftWindowBorders.size()
280  << " != rightWindowBorders.size() = " << rightWindowBorders.size() << std::endl;
281  }
282  if( leftWindowBorders.size() != 3 ) {
283  throw cms::Exception("Configuration") << "BackgroundHandler::BackgroundHandler: leftWindowBorders.size() = rightWindowBorders.size() = "
284  << leftWindowBorders.size() << " != 3" << std::endl;
285  }
286  if( identifiers.size() != 3 ) {
287  throw cms::Exception("Configuration") << "BackgroundHandler::BackgroundHandler: identifiers must match the number of regions = 3" << std::endl;
288  }
289 }
290 
291 #endif // BackgroundHandler_cc
std::vector< MassWindow > backgroundWindow_
virtual TF1 * functionForIntegral(const std::vector< double >::const_iterator &parBgrIt) const
Definition: Functions.h:1148
std::vector< MassWindow > resonanceWindow_
void consistencyCheck(const std::vector< int > &identifiers, const std::vector< double > &leftWindowBorders, const std::vector< double > &rightWindowBorders) const (false)
Used to check the consistency of passed parameters.
double upperBound() const
Definition: MassWindow.h:37
std::pair< double, double > backgroundFunction(const bool doBackgroundFit, const double *parval, const int resTotNum, const int ires, const bool *resConsidered, const double *ResMass, const double ResHalfWidth[], const int MuonType, const double &mass, const double &eta1, const double &eta2)
#define noexcept
reco::Particle::LorentzVector lorentzVector
Definition: weight.py:1
double events() const
Definition: MassWindow.h:38
void count(const double &mass, const double &weight=1.)
Definition: MassWindow.h:27
double lowerBound() const
Definition: MassWindow.h:36
void rescale(std::vector< double > &parBgr, const double *ResMass, const double *massWindowHalfWidth, const std::vector< std::pair< reco::Particle::LorentzVector, reco::Particle::LorentzVector > > &muonPairs, const double &weight=1.)
double resMass(const bool doBackgroundFit, const int ires)
void setParameters(double *Start, double *Step, double *Mini, double *Maxi, int *ind, TString *parname, const std::vector< double > &parBgr, const std::vector< int > &parBgrOrder, const int muonType)
Sets initial parameters for all the functions.
const std::vector< unsigned int > * indexes() const
Definition: MassWindow.h:40
void resetCounter()
Definition: MassWindow.h:33
backgroundFunctionBase * backgroundFunction() const
Definition: MassWindow.h:39
std::pair< double, double > windowBorders(const bool doBackgroundFit, const int ires)
Returns the appropriate window borders depending on whether the background is being fitted and on the...
bool unlockParameter(const std::vector< int > &resfind, const unsigned int ipar)
returns true if the parameter is to be unlocked
void countEventsInAllWindows(const std::vector< std::pair< reco::Particle::LorentzVector, reco::Particle::LorentzVector > > &muonPairs, const double &weight)
static unsigned int const shift
BackgroundHandler(const std::vector< int > &identifiers, const std::vector< double > &leftWindowBorders, const std::vector< double > &rightWindowBorders, const double *ResMass, const double *massWindowHalfWidth)
backgroundFunctionBase * backgroundFunctionService(const int identifier, const double &lowerLimit, const double &upperLimit)
Service to build the background functor corresponding to the passed identifier.
Definition: Functions.cc:62
math::XYZTLorentzVector LorentzVector
Lorentz vector.
Definition: Particle.h:21
void initializeParNums()
Initialize the parNums to be used in the shifts of parval.