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