diff --git a/src/Lau1DCubicSpline.cc b/src/Lau1DCubicSpline.cc index c1eb757..4d94fcd 100644 --- a/src/Lau1DCubicSpline.cc +++ b/src/Lau1DCubicSpline.cc @@ -1,343 +1,342 @@ /* Copyright 2015 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file Lau1DCubicSpline.cc \brief File containing implementation of Lau1DCubicSpline class. */ #include #include #include #include #include #include "Lau1DCubicSpline.hh" -ClassImp(Lau1DCubicSpline) Lau1DCubicSpline::Lau1DCubicSpline(const std::vector& xs, const std::vector& ys, LauSplineType type, LauSplineBoundaryType leftBound, LauSplineBoundaryType rightBound, Double_t dydx0, Double_t dydxn) : nKnots_(xs.size()), x_(xs), y_(ys), type_(type), leftBound_(leftBound), rightBound_(rightBound), dydx0_(dydx0), dydxn_(dydxn) { init(); } Lau1DCubicSpline::~Lau1DCubicSpline() { } Double_t Lau1DCubicSpline::evaluate(Double_t x) const { // do not attempt to extrapolate the spline if( xx_[nKnots_-1] ) { std::cout << "WARNING in Lau1DCubicSpline::evaluate : function is only defined between " << x_[0] << " and " << x_[nKnots_-1] << std::endl; std::cout << " value at " << x << " returned as 0" << std::endl; return 0.; } // first determine which 'cell' of the spline x is in // cell i runs from knot i to knot i+1 Int_t cell(0); while( x > x_[cell+1] ) { ++cell; } // obtain x- and y-values of the neighbouring knots Double_t xLow = x_[cell]; Double_t xHigh = x_[cell+1]; Double_t yLow = y_[cell]; Double_t yHigh = y_[cell+1]; if(type_ == Lau1DCubicSpline::LinearInterpolation) { return yHigh*(x-xLow)/(xHigh-xLow) + yLow*(xHigh-x)/(xHigh-xLow); } // obtain t, the normalised x-coordinate within the cell, // and the coefficients a and b, which are defined in cell i as: // // a_i = k_i *(x_i+1 - x_i) - (y_i+1 - y_i), // b_i = -k_i+1*(x_i+1 - x_i) + (y_i+1 - y_i) // // where k_i is (by construction) the first derivative at knot i Double_t t = (x - xLow) / (xHigh - xLow); Double_t a = dydx_[cell] * (xHigh - xLow) - (yHigh - yLow); Double_t b = -1.*dydx_[cell+1] * (xHigh - xLow) + (yHigh - yLow); Double_t retVal = (1 - t) * yLow + t * yHigh + t * (1 - t) * ( a * (1 - t) + b * t ); return retVal; } void Lau1DCubicSpline::updateYValues(const std::vector& ys) { y_ = ys; this->calcDerivatives(); } void Lau1DCubicSpline::updateType(LauSplineType type) { if(type_ != type) { type_ = type; this->calcDerivatives(); } } void Lau1DCubicSpline::updateBoundaryConditions(LauSplineBoundaryType leftBound, LauSplineBoundaryType rightBound, Double_t dydx0, Double_t dydxn) { Bool_t updateDerivatives(kFALSE); if(leftBound_ != leftBound || rightBound_ != rightBound) { leftBound_ = leftBound; rightBound_ = rightBound; updateDerivatives = kTRUE; } if(dydx0_ != dydx0) { dydx0_ = dydx0; if(leftBound_ == Lau1DCubicSpline::Clamped) updateDerivatives = kTRUE; } if(dydxn_ != dydxn) { dydxn_ = dydxn; if(rightBound_ == Lau1DCubicSpline::Clamped) updateDerivatives = kTRUE; } if(updateDerivatives) { this->calcDerivatives(); } } void Lau1DCubicSpline::init() { if( y_.size() != x_.size()) { std::cout << "ERROR in Lau1DCubicSpline::init : The number of y-values given does not match the number of x-values" << std::endl; std::cout << " Found " << y_.size() << ", expected " << x_.size() << std::endl; gSystem->Exit(EXIT_FAILURE); } dydx_.insert(dydx_.begin(),nKnots_,0.); a_.insert(a_.begin(),nKnots_,0.); b_.insert(b_.begin(),nKnots_,0.); c_.insert(c_.begin(),nKnots_,0.); d_.insert(d_.begin(),nKnots_,0.); this->calcDerivatives(); } void Lau1DCubicSpline::calcDerivatives() { switch ( type_ ) { case Lau1DCubicSpline::StandardSpline : this->calcDerivativesStandard(); break; case Lau1DCubicSpline::AkimaSpline : this->calcDerivativesAkima(); break; case Lau1DCubicSpline::LinearInterpolation : //derivatives not needed for linear interpolation break; } } void Lau1DCubicSpline::calcDerivativesStandard() { // derivatives are determined such that the second derivative is continuous at internal knots // derivatives, k_i, are the solutions to a set of linear equations of the form: // a_i * k_i-1 + b_i * k+i + c_i * k_i+1 = d_i with a_0 = 0, c_n-1 = 0 // this is solved using the tridiagonal matrix algorithm as on en.wikipedia.org/wiki/Tridiagonal_matrix_algorithm // first and last equations give boundary conditions // - for natural boundary, require f''(x) = 0 at end knot // - for 'not a knot' boundary, require f'''(x) continuous at second knot // - for clamped boundary, require predefined value of f'(x) at end knot // non-zero values of a_0 and c_n-1 would give cyclic boundary conditions a_[0] = 0.; c_[nKnots_-1] = 0.; // set left boundary condition if(leftBound_ == Lau1DCubicSpline::Natural) { b_[0] = 2./(x_[1]-x_[0]); c_[0] = 1./(x_[1]-x_[0]); d_[0] = 3.*(y_[1]-y_[0])/((x_[1]-x_[0])*(x_[1]-x_[0])); } else if(leftBound_ == Lau1DCubicSpline::NotAKnot) { // define the width, h, and the 'slope', delta, of the first cell Double_t h1(x_[1]-x_[0]), h2(x_[2]-x_[0]); Double_t delta1((y_[1]-y_[0])/h1), delta2((y_[2]-y_[1])/h2); // these coefficients can be determined by requiring f'''_0(x_1) = f'''_1(x_1) // the requirement f''_0(x_1) = f''_1(x_1) has been used to remove the dependence on k_2 b_[0] = h2; c_[0] = h1+h2; d_[0] = delta1*(2.*h2*h2 + 3.*h1*h2)/(h1+h2) + delta2*5.*h1*h1/(h1+h2); } else { //Clamped b_[0] = 1.; c_[0] = 0.; d_[0] = dydx0_; } // set right boundary condition if(rightBound_ == Lau1DCubicSpline::Natural) { a_[nKnots_-1] = 1./(x_[nKnots_-1]-x_[nKnots_-2]); b_[nKnots_-1] = 2./(x_[nKnots_-1]-x_[nKnots_-2]); d_[nKnots_-1] = 3.*(y_[nKnots_-1]-y_[nKnots_-2])/((x_[nKnots_-1]-x_[nKnots_-2])*(x_[nKnots_-1]-x_[nKnots_-2])); } else if(rightBound_ == Lau1DCubicSpline::NotAKnot) { // define the width, h, and the 'slope', delta, of the last cell Double_t hnm1(x_[nKnots_-1]-x_[nKnots_-2]), hnm2(x_[nKnots_-2]-x_[nKnots_-3]); Double_t deltanm1((y_[nKnots_-1]-y_[nKnots_-2])/hnm1), deltanm2((y_[nKnots_-2]-y_[nKnots_-3])/hnm2); // these coefficients can be determined by requiring f'''_n-3(x_n-2) = f'''_n-2(x_n-2) // the requirement f''_n-3(x_n-2) = f''_n-2(x_n-2) has been used to remove // the dependence on k_n-3 a_[nKnots_-1] = hnm2 + hnm1; b_[nKnots_-1] = hnm1; d_[nKnots_-1] = deltanm2*hnm1*hnm1/(hnm2+hnm1) + deltanm1*(2.*hnm2*hnm2 + 3.*hnm2*hnm1)/(hnm2+hnm1); } else { //Clamped a_[nKnots_-1] = 0.; b_[nKnots_-1] = 1.; d_[nKnots_-1] = dydxn_; } // the remaining equations ensure that f_i-1''(x_i) = f''_i(x_i) for all internal knots for(UInt_t i=1; i=0; --i) { dydx_[i] = d_[i] - c_[i]*dydx_[i+1]; } } void Lau1DCubicSpline::calcDerivativesAkima() { //derivatives are calculated according to the Akima method // J.ACM vol. 17 no. 4 pp 589-602 Double_t am1(0.), an(0.), anp1(0.); // a[i] is the slope of the segment from point i-1 to point i // // n.b. segment 0 is before point 0 and segment n is after point n-1 // internal segments are numbered 1 - n-1 for(UInt_t i=1; i #include #include #include "TAxis.h" #include "TH1.h" #include "TRandom.h" #include "TSystem.h" #include "Lau1DHistPdf.hh" #include "LauRandom.hh" class LauParameter; -ClassImp(Lau1DHistPdf) Lau1DHistPdf::Lau1DHistPdf(const TString& theVarName, const TH1* hist, Double_t minAbscissa, Double_t maxAbscissa, Bool_t useInterpolation, Bool_t fluctuateBins) : LauAbsPdf(theVarName, std::vector(), minAbscissa, maxAbscissa), hist_(hist ? dynamic_cast(hist->Clone()) : 0), useInterpolation_(useInterpolation), fluctuateBins_(fluctuateBins), nBins_(0), axisMin_(0.0), axisMax_(0.0), axisRange_(0.0) { // Constructor // Set the directory for the histogram hist_->SetDirectory(0); // Save various attributes of the histogram nBins_ = hist_->GetNbinsX(); TAxis* xAxis = hist_->GetXaxis(); axisMin_ = xAxis->GetXmin(); axisMax_ = xAxis->GetXmax(); axisRange_ = axisMax_ - axisMin_; // Check that axis range corresponds to range of abscissa if (TMath::Abs(this->getMinAbscissa() - axisMin_)>1e-6) { std::cerr << "ERROR in Lau1DHistPdf::Lau1DHistPdf : Histogram axis minimum: " << axisMin_ << " does not correspond to abscissa minimum: " << this->getMinAbscissa() << "." << std::endl; gSystem->Exit(EXIT_FAILURE); } if (TMath::Abs(this->getMaxAbscissa() - axisMax_)>1e-6) { std::cerr << "ERROR in Lau1DHistPdf::Lau1DHistPdf : Histogram axis maximum: " << axisMax_ << " does not correspond to abscissa maximum: " << this->getMaxAbscissa() << "." << std::endl; gSystem->Exit(EXIT_FAILURE); } // If the bins are to be fluctuated then do so now before // calculating anything that depends on the bin content. if (fluctuateBins) { this->doBinFluctuation(); } // Calculate the PDF normalisation. this->calcNorm(); // And check it is OK. this->checkNormalisation(); } Lau1DHistPdf::~Lau1DHistPdf() { // Destructor delete hist_; hist_ = 0; } void Lau1DHistPdf::calcPDFHeight( const LauKinematics* /*kinematics*/ ) { if (this->heightUpToDate()) { return; } // Get the maximum height of the histogram Int_t maxBin = hist_->GetMaximumBin(); Double_t height = hist_->GetBinContent(maxBin); this->setMaxHeight(height); } void Lau1DHistPdf::calcNorm() { // Calculate the histogram normalisation. // Loop over the range to get the total area. // Just sum the contributions up using 1e-3 increments of the range. // Multiply the end result by dx. Double_t dx(1e-3*axisRange_); Double_t area(0.0); Double_t x(axisMin_ + dx/2.0); while (x > axisMin_ && x < axisMax_) { area += this->interpolate(x); x += dx; } Double_t norm = area*dx; this->setNorm(norm); } void Lau1DHistPdf::checkNormalisation() { Double_t dx(1e-3*axisRange_); Double_t area(0.0); Double_t areaNoNorm(0.0); Double_t x(axisMin_ + dx/2.0); while (x > axisMin_ && x < axisMax_) { area += this->interpolateNorm(x); useInterpolation_ = kFALSE; areaNoNorm += this->interpolate(x); useInterpolation_ = kTRUE; x += dx; } Double_t norm = area*dx; std::cout << "INFO in Lau1DHistPdf::checkNormalisation : Area = " << area << ", dx = " << dx << std::endl; std::cout << " : Area with no norm = " << areaNoNorm << "*dx = " << areaNoNorm*dx << std::endl; std::cout << " : The total area of the normalised histogram PDF is " << norm << std::endl; } Double_t Lau1DHistPdf::getBinHistValue(Int_t bin) const { // Check that bin is in range [1 , nBins_] if ((bin < 1) || (bin > nBins_)) { return 0.0; } Double_t value = static_cast(hist_->GetBinContent(bin)); // protect against negative values if ( value < 0.0 ) { std::cerr << "WARNING in Lau1DHistPdf::getBinHistValue : Negative bin content set to zero!" << std::endl; value = 0.0; } return value; } Double_t Lau1DHistPdf::interpolateNorm(Double_t x) const { // Get the normalised interpolated value. Double_t value = this->interpolate(x); Double_t norm = this->getNorm(); return value/norm; } void Lau1DHistPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Get our abscissa Double_t abscissa = abscissas[0]; // Calculate the interpolated value Double_t value = this->interpolate(abscissa); this->setUnNormPDFVal(value); } Double_t Lau1DHistPdf::interpolate(Double_t x) const { // This function returns the interpolated value of the histogram function // for the given value of x by finding the adjacent bins and extrapolating // using weights based on the inverse distance of the point from the adajcent // bin centres. // Find the histogram bin Int_t bin = hist_->FindFixBin(x); // Ask whether we want to do the interpolation, since this method is // not reliable for low statistics histograms. if (useInterpolation_ == kFALSE) { return this->getBinHistValue(bin); } // Find the bin centres (actual co-ordinate positions, not histogram indices) Double_t cbinx = hist_->GetBinCenter(bin); // Find the adjacent bins Double_t deltax = x - cbinx; Int_t bin_adj(0); if (deltax > 0.0) { bin_adj = bin + 1; } else { bin_adj = bin - 1; } Bool_t isBoundary(kFALSE); if ( bin_adj > nBins_ || bin_adj < 1 ) { isBoundary = kTRUE; } // At the edges, do no interpolation, use entry in bin. if (isBoundary == kTRUE) { return this->getBinHistValue(bin); } // Linear interpolation using inverse distance as weights. // Find the adjacent bin centre Double_t cbinx_adj = hist_->GetBinCenter(bin_adj); Double_t deltax_adj = cbinx_adj - x; Double_t dx0 = TMath::Abs(deltax); Double_t dx1 = TMath::Abs(deltax_adj); Double_t denom = dx0 + dx1; Double_t value0 = this->getBinHistValue(bin); Double_t value1 = this->getBinHistValue(bin_adj); Double_t value = value0*dx1 + value1*dx0; value /= denom; return value; } void Lau1DHistPdf::doBinFluctuation() { TRandom* random = LauRandom::randomFun(); for (Int_t bin(0); binGetBinContent(bin+1); Double_t currentError = hist_->GetBinError(bin+1); Double_t newContent = random->Gaus(currentContent,currentError); if (newContent<0.0) { hist_->SetBinContent(bin+1,0.0); } else { hist_->SetBinContent(bin+1,newContent); } } } diff --git a/src/Lau2DAbsHistDP.cc b/src/Lau2DAbsHistDP.cc index 26fa795..da6e84a 100644 --- a/src/Lau2DAbsHistDP.cc +++ b/src/Lau2DAbsHistDP.cc @@ -1,195 +1,194 @@ /* Copyright 2013 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file Lau2DAbsHistDP.cc \brief File containing implementation of Lau2DAbsHistDP class. */ #include #include "TAxis.h" #include "TH2.h" #include "TRandom.h" #include "TSystem.h" #include "Lau2DAbsHistDP.hh" #include "LauBifurcatedGaussPdf.hh" #include "LauDaughters.hh" #include "LauKinematics.hh" #include "LauRandom.hh" -ClassImp(Lau2DAbsHistDP) Lau2DAbsHistDP::Lau2DAbsHistDP(const LauDaughters* daughters, Bool_t useUpperHalfOnly, Bool_t squareDP) : kinematics_( (daughters!=0) ? daughters->getKinematics() : 0 ), upperHalf_(useUpperHalfOnly), squareDP_(squareDP) { if ( squareDP && ! daughters->squareDP() ) { // The histogram provided is defined in the square DP but the // kinematics object has calculation of the square DP // co-ordinates disabled, so need to enable it, // which requires a bit of a unpleasant const_cast std::cerr << "WARNING in Lau2DAbsHistDP constructor : forcing kinematics to calculate the required square DP co-ordinates" << std::endl; LauKinematics* kine = const_cast( kinematics_ ); kine->squareDP(kTRUE); } } Lau2DAbsHistDP::~Lau2DAbsHistDP() { } void Lau2DAbsHistDP::doBinFluctuation(TH2* hist) { TRandom* random = LauRandom::randomFun(); Int_t nBinsX = static_cast(hist->GetNbinsX()); Int_t nBinsY = static_cast(hist->GetNbinsY()); for (Int_t i(0); iGetBinContent(i+1,j+1); Double_t currentError = hist->GetBinError(i+1,j+1); Double_t newContent = random->Gaus(currentContent,currentError); if (newContent<0.0) { hist->SetBinContent(i+1,j+1,0.0); } else { hist->SetBinContent(i+1,j+1,newContent); } } } } void Lau2DAbsHistDP::doBinFluctuation(TH2* hist, const TH2* errorHi, const TH2* errorLo) { LauParameter* mean = new LauParameter("mean", 0.5, 0.0, 1.0, kFALSE); LauParameter* sigL = new LauParameter("sigmaL", 0.5, 0.0, 1.0, kFALSE); LauParameter* sigR = new LauParameter("sigmaR", 0.5, 0.0, 1.0, kFALSE); std::vector pars(3); pars[0] = mean; pars[1] = sigL; pars[2] = sigR; const TString varName("tmp"); Int_t nBinsX = static_cast(hist->GetNbinsX()); Int_t nBinsY = static_cast(hist->GetNbinsY()); LauFitData genData; for (Int_t i(0); iGetBinContent(i+1,j+1); const Double_t currentErrorLo = errorLo->GetBinContent(i+1,j+1); const Double_t currentErrorHi = errorHi->GetBinContent(i+1,j+1); mean->value( currentContent ); sigL->value( currentErrorLo ); sigR->value( currentErrorHi ); const Double_t minVal = TMath::Max( 0.0, currentContent-5.0*currentErrorLo ); const Double_t maxVal = TMath::Min( 1.0, currentContent+5.0*currentErrorHi ); LauBifurcatedGaussPdf bfgaus(varName, pars, minVal, maxVal); bfgaus.heightUpToDate(kFALSE); genData = bfgaus.generate(0); const Double_t newContent = genData[varName]; hist->SetBinContent(i+1,j+1,newContent); } } delete pars[0]; delete pars[1]; delete pars[2]; pars.clear(); } void Lau2DAbsHistDP::raiseOrLowerBins(TH2* hist, const Double_t avEff, const Double_t avEffError) { TRandom* random = LauRandom::randomFun(); Double_t curAvg = this->computeAverageContents(hist); Double_t newAvg = random->Gaus(avEff,avEffError); hist->Scale( newAvg / curAvg ); } Double_t Lau2DAbsHistDP::computeAverageContents(const TH2* hist) const { Double_t totalContent(0.0); Int_t binsWithinDPBoundary(0); Int_t nBinsX = static_cast(hist->GetNbinsX()); Int_t nBinsY = static_cast(hist->GetNbinsY()); // Loop through the bins and include any that have their centre or any // of the four corners within the kinematic boundary for ( Int_t i(0); iGetXaxis()->GetBinCenter(i+1); Double_t binXLowerEdge = hist->GetXaxis()->GetBinLowEdge(i+1); Double_t binXUpperEdge = hist->GetXaxis()->GetBinUpEdge(i+1); for ( Int_t j(0); jGetYaxis()->GetBinCenter(i+1); Double_t binYLowerEdge = hist->GetYaxis()->GetBinLowEdge(i+1); Double_t binYUpperEdge = hist->GetYaxis()->GetBinUpEdge(i+1); if ( this->withinDPBoundaries( binXCentre, binYCentre ) || this->withinDPBoundaries( binXLowerEdge, binYLowerEdge ) || this->withinDPBoundaries( binXUpperEdge, binYUpperEdge ) || this->withinDPBoundaries( binXLowerEdge, binYUpperEdge ) || this->withinDPBoundaries( binXUpperEdge, binYLowerEdge ) ) { totalContent += hist->GetBinContent(i+1, j+1); ++binsWithinDPBoundary; } } } return totalContent/binsWithinDPBoundary; } Bool_t Lau2DAbsHistDP::withinDPBoundaries(Double_t x, Double_t y) const { return squareDP_ ? kinematics_->withinSqDPLimits(x,y) : kinematics_->withinDPLimits(x,y); } void Lau2DAbsHistDP::getUpperHalf(Double_t& x, Double_t& y) const { if ( upperHalf_ == kTRUE ) { if ( squareDP_ == kFALSE && x > y ) { Double_t temp = y; y = x; x = temp; } else if ( squareDP_ == kTRUE && y > 0.5 ) { y = 1.0 - y; } } } diff --git a/src/Lau2DAbsHistDPPdf.cc b/src/Lau2DAbsHistDPPdf.cc index 9e71168..fec3c57 100644 --- a/src/Lau2DAbsHistDPPdf.cc +++ b/src/Lau2DAbsHistDPPdf.cc @@ -1,124 +1,123 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file Lau2DAbsHistDPPdf.cc \brief File containing implementation of Lau2DAbsHistDPPdf class. */ #include #include "TAxis.h" #include "TH2.h" #include "TRandom.h" #include "Lau2DAbsHistDPPdf.hh" #include "LauKinematics.hh" #include "LauRandom.hh" #include "LauVetoes.hh" -ClassImp(Lau2DAbsHistDPPdf) Lau2DAbsHistDPPdf::Lau2DAbsHistDPPdf(LauKinematics* kinematics, const LauVetoes* vetoes, Bool_t useUpperHalfOnly, Bool_t squareDP) : kinematics_(kinematics), vetoes_(vetoes), upperHalf_(useUpperHalfOnly), squareDP_(squareDP) { if ( squareDP && ! kinematics->squareDP() ) { // The histogram provided is defined in the square DP but the // kinematics object has calculation of the square DP // co-ordinates disabled, so need to enable it, std::cerr << "WARNING in Lau2DAbsHistDPPdf constructor : forcing kinematics to calculate the required square DP co-ordinates" << std::endl; kinematics->squareDP(kTRUE); } } Lau2DAbsHistDPPdf::~Lau2DAbsHistDPPdf() { } void Lau2DAbsHistDPPdf::calcMaxHeight(TH2* hist) { // Get the maximum height of the 2D histogram maxHeight_ = 1.0; if ( hist ) { Int_t maxBin = hist->GetMaximumBin(); maxHeight_ = hist->GetBinContent(maxBin); } std::cout << "INFO in Lau2DAbsHistDPPdf::calcMaxHeight : Max height = " << maxHeight_ << std::endl; } void Lau2DAbsHistDPPdf::doBinFluctuation(TH2* hist) { if ( !hist ) { return; } TRandom* random = LauRandom::randomFun(); Int_t nBinsX = static_cast(hist->GetNbinsX()); Int_t nBinsY = static_cast(hist->GetNbinsY()); for (Int_t i(0); iGetBinContent(i+1,j+1); Double_t currentError = hist->GetBinError(i+1,j+1); Double_t newContent = random->Gaus(currentContent,currentError); if (newContent<0.0) { hist->SetBinContent(i+1,j+1,0.0); } else { hist->SetBinContent(i+1,j+1,newContent); } } } } Bool_t Lau2DAbsHistDPPdf::withinDPBoundaries(Double_t x, Double_t y) const { return squareDP_ ? kinematics_->withinSqDPLimits(x,y) : kinematics_->withinDPLimits(x,y); } void Lau2DAbsHistDPPdf::getUpperHalf(Double_t& x, Double_t& y) const { if ( upperHalf_ == kTRUE ) { if ( squareDP_ == kFALSE && x > y ) { Double_t temp = y; y = x; x = temp; } else if ( squareDP_ == kTRUE && y > 0.5 ) { y = 1.0 - y; } } } void Lau2DAbsHistDPPdf::updateKinematics(Double_t x, Double_t y) const { if (squareDP_ == kTRUE) { kinematics_->updateSqDPKinematics(x,y); } else { kinematics_->updateKinematics(x,y); } } diff --git a/src/Lau2DCubicSpline.cc b/src/Lau2DCubicSpline.cc index 775beb2..116f1e8 100644 --- a/src/Lau2DCubicSpline.cc +++ b/src/Lau2DCubicSpline.cc @@ -1,374 +1,373 @@ /* Copyright 2013 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file Lau2DCubicSpline.cc \brief File containing implementation of Lau2DCubicSpline class. Class for defining a 2D cubic spline based on RooBinned2DBicubicBase by Manuel Tobias Schiller (2012-08-29). */ #include #include #include #include #include #include "Lau2DCubicSpline.hh" -ClassImp(Lau2DCubicSpline) Lau2DCubicSpline::~Lau2DCubicSpline() { } inline Double_t Lau2DCubicSpline::histcont( const TH2& h, Int_t xbin, Int_t ybin) const { //reflect until we're in range while(xbin < 0 || xbin >= nBinsX - 1) { if(xbin < 0) xbin = -xbin-1; if(xbin >= nBinsX -1) xbin = 2*(nBinsX-1) - xbin - 1; } while(ybin < 0 || ybin >= nBinsY - 1) { if(ybin < 0) ybin = -ybin-1; if(ybin >= nBinsY -1) ybin = 2*(nBinsY-1) - ybin - 1; } return h.GetBinContent(1 + xbin, 1 + ybin); } inline Double_t Lau2DCubicSpline::dhistdx( const TH2& h, Int_t xbin, Int_t ybin) const { return 0.5 * (histcont(h, xbin + 1, ybin) - histcont(h, xbin - 1, ybin)); } inline Double_t Lau2DCubicSpline::dhistdy( const TH2& h, Int_t xbin, Int_t ybin) const { return 0.5 * (histcont(h, xbin, ybin + 1) - histcont(h, xbin, ybin - 1)); } inline Double_t Lau2DCubicSpline::d2histdxdy( const TH2& h, Int_t xbin, Int_t ybin) const { return 0.5 * (histcont(h, xbin - 1, ybin - 1) - histcont(h, xbin + 1, ybin - 1) + histcont(h, xbin + 1, ybin + 1) - histcont(h, xbin - 1, ybin + 1)); } Lau2DCubicSpline::Lau2DCubicSpline(const TH2& h) : nBinsX(1 + h.GetNbinsX()), nBinsY(1 + h.GetNbinsY()), binSizeX(h.GetXaxis()->GetBinWidth(1)), binSizeY(h.GetYaxis()->GetBinWidth(1)), xmin(h.GetXaxis()->GetBinCenter(1) - binSizeX), xmax(h.GetXaxis()->GetBinCenter(nBinsX - 1) + binSizeX), ymin(h.GetYaxis()->GetBinCenter(1) - binSizeY), ymax(h.GetYaxis()->GetBinCenter(nBinsY - 1) + binSizeY), coeffs(CoeffRecLen * nBinsX * nBinsY) { const TAxis* xaxis = h.GetXaxis(); const TAxis* yaxis = h.GetYaxis(); // verify that all bins have same size for (Int_t i = 1; i < nBinsX; ++i) { if (std::abs(xaxis->GetBinWidth(i) / binSizeX - 1.) > 1e-9) { std::cerr << "ERROR in Lau2DCubicSpline constructor : the histogram has variable bin sizes." << std::endl; gSystem->Exit(EXIT_FAILURE); } } for (Int_t i = 1; i < nBinsY; ++i) { if (std::abs(yaxis->GetBinWidth(i) / binSizeY - 1.) > 1e-9) { std::cerr << "ERROR in Lau2DCubicSpline constructor : the histogram has variable bin sizes." << std::endl; gSystem->Exit(EXIT_FAILURE); } } // ok, go through histogram to precalculate the interpolation coefficients // in rectangles between bin centres // // for that purpose, we map each of those rectangles to the unit square for (Int_t j = -1; j < nBinsY - 1; ++j) { for (Int_t i = -1; i < nBinsX - 1; ++i) { const Double_t rhs[NCoeff] = { // function values in bin centres histcont(h, i, j), histcont(h, i + 1, j), histcont(h, i, j + 1), histcont(h, i + 1, j + 1), // df/dx in bin centres (finite difference approximation) dhistdx(h, i, j), dhistdx(h, i + 1, j), dhistdx(h, i, j + 1), dhistdx(h, i + 1, j + 1), // df/dy in bin centres (finite difference approximation) dhistdy(h, i, j), dhistdy(h, i + 1, j), dhistdy(h, i, j + 1), dhistdy(h, i + 1, j + 1), // d^2f/dxdy in bin centres (finite difference approximation) d2histdxdy(h, i, j), d2histdxdy(h, i + 1, j), d2histdxdy(h, i, j + 1), d2histdxdy(h, i + 1, j + 1) }; // work out solution - strange array placement is due to the fact // that terms with x/y to high powers can be small, so they should // be added up first during evaluation to avoid cancellation // issues; at the same time you want to access them in order to // not confuse the CPU cache, so they're stored back to front // // a_00 ... a_30 coeff(1 + i, 1 + j, 15) = rhs[0]; coeff(1 + i, 1 + j, 14) = rhs[4]; coeff(1 + i, 1 + j, 13) = 3. * (-rhs[0] + rhs[1]) - 2. * rhs[4] - rhs[5]; coeff(1 + i, 1 + j, 12) = 2. * (rhs[0] - rhs[1]) + rhs[4] + rhs[5]; // a_31 ... a_31 coeff(1 + i, 1 + j, 11) = rhs[8]; coeff(1 + i, 1 + j, 10) = rhs[12]; coeff(1 + i, 1 + j, 9) = 3. * (-rhs[8] + rhs[9]) - 2. * rhs[12] - rhs[13]; coeff(1 + i, 1 + j, 8) = 2. * (rhs[8] - rhs[9]) + rhs[12] + rhs[13]; // a_02 ... a_32 coeff(1 + i, 1 + j, 7) = 3. * (-rhs[0] + rhs[2]) - 2. * rhs[8] - rhs[10]; coeff(1 + i, 1 + j, 6) = 3. * (-rhs[4] + rhs[6]) - 2. * rhs[12] - rhs[14]; coeff(1 + i, 1 + j, 5) = 9. * (rhs[0] - rhs[1] - rhs[2] + rhs[3]) + 6. * (rhs[4] - rhs[6] + rhs[8] - rhs[9]) + 4. * rhs[12] + 3. * (rhs[5] - rhs[7] + rhs[10] - rhs[11]) + 2. * (rhs[13] + rhs[14]) + rhs[15]; coeff(1 + i, 1 + j, 4) = 6. * (-rhs[0] + rhs[1] + rhs[2] - rhs[3]) + 4. * (-rhs[8] + rhs[9]) + 3. * (-rhs[4] - rhs[5] + rhs[6] + rhs[7]) + 2. * (-rhs[10] + rhs[11] - rhs[12] - rhs[13]) - rhs[14] - rhs[15]; // a_03 ... a_33 coeff(1 + i, 1 + j, 3) = 2. * (rhs[0] - rhs[2]) + rhs[8] + rhs[10]; coeff(1 + i, 1 + j, 2) = 2. * (rhs[4] - rhs[6]) + rhs[12] + rhs[14]; coeff(1 + i, 1 + j, 1) = 6. * (-rhs[0] + rhs[1] + rhs[2] - rhs[3]) + 4. * (-rhs[4] + rhs[6]) + 3. * (-rhs[8] + rhs[9] - rhs[10] + rhs[11]) + 2. * (- rhs[5] + rhs[7] - rhs[12] - rhs[14]) - rhs[13] - rhs[15]; coeff(1 + i, 1 + j, 0) = 4. * (rhs[0] - rhs[1] - rhs[2] + rhs[3]) + 2. * (rhs[4] + rhs[5] - rhs[6] - rhs[7] + rhs[8] - rhs[9] + rhs[10] - rhs[11]) + rhs[12] + rhs[13] + rhs[14] + rhs[15]; // coeff(1 + i, 1 + j, 17) contains integral of function over the // square in "unit square coordinates", i.e. neglecting bin widths // this is done to help speed up calculations of 2D integrals Double_t sum = 0.; for (Int_t k = 0; k < NCoeff; ++k) sum += coeff(1 + i, 1 + j, k) / Double_t((4 - (k % 4)) * (4 - (k / 4))); coeff(1 + i, 1 + j, NCoeff) = sum; } } } Double_t Lau2DCubicSpline::evaluate(Double_t x, Double_t y) const { // protect against NaN and out of range if (x <= xmin || x >= xmax || y <= ymin || y >= ymax || x != x || y != y) return 0.; // find the bin in question const Int_t binx = Int_t(Double_t(nBinsX) * (x - xmin) / (xmax - xmin)); const Int_t biny = Int_t(Double_t(nBinsY) * (y - ymin) / (ymax - ymin)); // get low edge of bin const Double_t xlo = Double_t(nBinsX - binx) / Double_t(nBinsX) * xmin + Double_t(binx) / Double_t(nBinsX) * xmax; const Double_t ylo = Double_t(nBinsY - biny) / Double_t(nBinsY) * ymin + Double_t(biny) / Double_t(nBinsY) * ymax; // normalise to coordinates in unit sqare const Double_t hx = (x - xlo) / binSizeX; const Double_t hy = (y - ylo) / binSizeY; // monomials const Double_t hxton[4] = { hx * hx * hx, hx * hx, hx, 1. }; const Double_t hyton[4] = { hy * hy * hy, hy * hy, hy, 1. }; // sum up Double_t retVal = 0.; for (Int_t k = 0; k < NCoeff; ++k) retVal += coeff(binx, biny, k) * hxton[k % 4] * hyton[k / 4]; return retVal; } Double_t Lau2DCubicSpline::analyticalIntegral() const { return evalXY(xmin,xmax,ymin,ymax); } Double_t Lau2DCubicSpline::analyticalIntegral(Double_t x1, Double_t x2, Double_t y1, Double_t y2) const { if(y1==y2) return evalX(x1, x2, y1); if(x1==x2) return evalY(x1, y1, y2); return evalXY(x1, x2, y1, y2); } Double_t Lau2DCubicSpline::evalX(Double_t x1, Double_t x2, Double_t y) const { // protect against NaN if (x1 != x1 || x2 != x2 || y != y) return 0.; // find the bin in question const Int_t biny = Int_t(Double_t(nBinsY) * (y - ymin) / (ymax - ymin)); // get low edge of bin const Double_t ylo = Double_t(nBinsY - biny) / Double_t(nBinsY) * ymin + Double_t(biny) / Double_t(nBinsY) * ymax; // normalise to coordinates in unit sqare const Double_t hy = (y - ylo) / binSizeY; // monomials const Double_t hyton[4] = { hy * hy * hy, hy * hy, hy, 1. }; // integral Double_t sum = 0.; for (Int_t binx = 0; binx < nBinsX; ++binx) { // get low/high edge of bin const Double_t xhi = Double_t(nBinsX - binx - 1) / Double_t(nBinsX) * xmin + Double_t(binx + 1) / Double_t(nBinsX) * xmax; if (xhi < x1) continue; const Double_t xlo = Double_t(nBinsX - binx) / Double_t(nBinsX) * xmin + Double_t(binx) / Double_t(nBinsX) * xmax; if (xlo > x2) break; // work out integration range const Double_t a = ((xlo > x1) ? 0. : (x1 - xlo)) / binSizeX; const Double_t b = ((xhi < x2) ? binSizeX : (x2 - xlo)) / binSizeX; // integrated monomials const Double_t hxton[4] = { 0.25 * (b * b * b * b - a * a * a * a), (b * b * b - a * a * a) / 3., 0.5 * (b * b - a * a), b - a }; Double_t lsum = 0.; for (Int_t k = 0; k < NCoeff; ++k) lsum += coeff(binx, biny, k) * hxton[k % 4] * hyton[k / 4]; sum += lsum; } // move from unit square coordinates to user coordinates return sum * binSizeX; } Double_t Lau2DCubicSpline::evalY(Double_t x, Double_t y1, Double_t y2) const { // protect against NaN if (x != x || y1 != y1 || y2 != y2) return 0.; // find the bin in question const Int_t binx = Int_t(Double_t(nBinsX) * (x - xmin) / (xmax - xmin)); // get low edge of bin const Double_t xlo = Double_t(nBinsX - binx) / Double_t(nBinsX) * xmin + Double_t(binx) / Double_t(nBinsX) * xmax; // normalise to coordinates in unit sqare const Double_t hx = (x - xlo) / binSizeX; // monomials const Double_t hxton[4] = { hx * hx * hx, hx * hx, hx, 1. }; // integral Double_t sum = 0.; for (Int_t biny = 0; biny < nBinsY; ++biny) { // get low/high edge of bin const Double_t yhi = Double_t(nBinsY - biny - 1) / Double_t(nBinsY) * ymin + Double_t(biny + 1) / Double_t(nBinsY) * ymax; if (yhi < y1) continue; const Double_t ylo = Double_t(nBinsY - biny) / Double_t(nBinsY) * ymin + Double_t(biny) / Double_t(nBinsY) * ymax; if (ylo > y2) break; // work out integration range const Double_t a = ((ylo > y1) ? 0. : (y1 - ylo)) / binSizeY; const Double_t b = ((yhi < y2) ? binSizeY : (y2 - ylo)) / binSizeY; // integrated monomials const Double_t hyton[4] = { 0.25 * (b * b * b * b - a * a * a * a), (b * b * b - a * a * a) / 3., 0.5 * (b * b - a * a), b - a }; Double_t lsum = 0.; for (Int_t k = 0; k < NCoeff; ++k) lsum += coeff(binx, biny, k) * hxton[k % 4] * hyton[k / 4]; sum += lsum; } // move from unit square coordinates to user coordinates return sum * binSizeY; } Double_t Lau2DCubicSpline::evalXY( Double_t x1, Double_t x2, Double_t y1, Double_t y2) const { // protect against NaN if (x1 != x1 || x2 != x2 || y1 != y1 || y2 != y2) return 0.; // integral Double_t sum = 0.; for (Int_t biny = 0; biny < nBinsY; ++biny) { // get low/high edge of bin const Double_t yhi = Double_t(nBinsY - biny - 1) / Double_t(nBinsY) * ymin + Double_t(biny + 1) / Double_t(nBinsY) * ymax; if (yhi < y1) continue; const Double_t ylo = Double_t(nBinsY - biny) / Double_t(nBinsY) * ymin + Double_t(biny) / Double_t(nBinsY) * ymax; if (ylo > y2) break; // work out integration range const Double_t ay = ((ylo > y1) ? 0. : (y1 - ylo)) / binSizeY; const Double_t by = ((yhi < y2) ? binSizeY : (y2 - ylo)) / binSizeY; const Bool_t yFullyContained = std::abs(by - ay - 1.0) < 1e-15; // integrated monomials const Double_t hyton[4] = { 0.25 * (by * by * by * by - ay * ay * ay * ay), (by * by * by - ay * ay * ay) / 3., 0.5 * (by * by - ay * ay), by - ay }; for (Int_t binx = 0; binx < nBinsX; ++binx) { // get low/high edge of bin const Double_t xhi = Double_t(nBinsX - binx - 1) / Double_t(nBinsX) * xmin + Double_t(binx + 1) / Double_t(nBinsX) * xmax; if (xhi < x1) continue; const Double_t xlo = Double_t(nBinsX - binx) / Double_t(nBinsX) * xmin + Double_t(binx) / Double_t(nBinsX) * xmax; if (xlo > x2) break; // work out integration range const Double_t ax = ((xlo > x1) ? 0. : (x1 - xlo)) / binSizeX; const Double_t bx = ((xhi < x2) ? binSizeX : (x2 - xlo)) / binSizeX; const Bool_t xFullyContained = std::abs(bx - ax - 1.0) < 1e-15; if (xFullyContained && yFullyContained) { // for fully contained bins, we have cached the integral sum += coeff(binx, biny, NCoeff); continue; } // integrated monomials const Double_t hxton[4] = { 0.25 * (bx * bx * bx * bx - ax * ax * ax * ax), (bx * bx * bx - ax * ax * ax) / 3., 0.5 * (bx * bx - ax * ax), bx - ax }; // integrate over bin Double_t lsum = 0.; for (Int_t k = 0; k < NCoeff; ++k) lsum += coeff(binx, biny, k) * hxton[k % 4] * hyton[k / 4]; sum += lsum; } } // move from unit square coordinates to user coordinates return sum * binSizeX * binSizeY; } diff --git a/src/Lau2DHistDP.cc b/src/Lau2DHistDP.cc index 7d1ef4a..1148164 100644 --- a/src/Lau2DHistDP.cc +++ b/src/Lau2DHistDP.cc @@ -1,360 +1,359 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file Lau2DHistDP.cc \brief File containing implementation of Lau2DHistDP class. */ #include #include "TAxis.h" #include "TH2.h" #include "TRandom.h" #include "TSystem.h" #include "Lau2DHistDP.hh" #include "LauDaughters.hh" #include "LauKinematics.hh" #include "LauRandom.hh" -ClassImp(Lau2DHistDP) Lau2DHistDP::Lau2DHistDP(const TH2* hist, const LauDaughters* daughters, Bool_t useInterpolation, Bool_t fluctuateBins, Double_t avEff, Double_t avEffError, Bool_t useUpperHalfOnly, Bool_t squareDP) : Lau2DAbsHistDP(daughters,useUpperHalfOnly,squareDP), hist_(hist ? dynamic_cast(hist->Clone()) : 0), errorHi_(0), errorLo_(0), minX_(0.0), maxX_(0.0), minY_(0.0), maxY_(0.0), rangeX_(0.0), rangeY_(0.0), binXWidth_(0.0), binYWidth_(0.0), nBinsX_(0), nBinsY_(0), useInterpolation_(useInterpolation) { if ( ! hist_ ) { std::cerr << "ERROR in Lau2DHistDP constructor : the histogram pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } // Save various attributes of the histogram // (axis ranges, number of bins, areas) TAxis* xAxis = hist_->GetXaxis(); minX_ = static_cast(xAxis->GetXmin()); maxX_ = static_cast(xAxis->GetXmax()); rangeX_ = maxX_ - minX_; TAxis* yAxis = hist_->GetYaxis(); minY_ = static_cast(yAxis->GetXmin()); maxY_ = static_cast(yAxis->GetXmax()); rangeY_ = maxY_ - minY_; nBinsX_ = static_cast(hist_->GetNbinsX()); nBinsY_ = static_cast(hist_->GetNbinsY()); binXWidth_ = static_cast(TMath::Abs(rangeX_)/(nBinsX_*1.0)); binYWidth_ = static_cast(TMath::Abs(rangeY_)/(nBinsY_*1.0)); if (fluctuateBins) { this->doBinFluctuation(hist_); } if (avEff > 0.0 && avEffError > 0.0) { this->raiseOrLowerBins(hist_,avEff,avEffError); } } Lau2DHistDP::Lau2DHistDP(const TH2* hist, const TH2* errorHi, const TH2* errorLo, const LauDaughters* daughters, Bool_t useInterpolation, Bool_t fluctuateBins, Double_t avEff, Double_t avEffError, Bool_t useUpperHalfOnly, Bool_t squareDP) : Lau2DAbsHistDP(daughters,useUpperHalfOnly,squareDP), hist_(hist ? dynamic_cast(hist->Clone()) : 0), errorHi_(errorHi ? dynamic_cast(errorHi->Clone()) : 0), errorLo_(errorLo ? dynamic_cast(errorLo->Clone()) : 0), minX_(0.0), maxX_(0.0), minY_(0.0), maxY_(0.0), rangeX_(0.0), rangeY_(0.0), binXWidth_(0.0), binYWidth_(0.0), nBinsX_(0), nBinsY_(0), useInterpolation_(useInterpolation) { if ( ! hist_ ) { std::cerr << "ERROR in Lau2DHistDP constructor : the histogram pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } if ( ! errorHi_ ) { std::cerr << "ERROR in Lau2DHistDP constructor : the upper error histogram pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } if ( ! errorLo_ ) { std::cerr << "ERROR in Lau2DHistDP constructor : the lower error histogram pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } // Save various attributes of the histogram // (axis ranges, number of bins, areas) TAxis* xAxis = hist_->GetXaxis(); minX_ = static_cast(xAxis->GetXmin()); maxX_ = static_cast(xAxis->GetXmax()); rangeX_ = maxX_ - minX_; TAxis* yAxis = hist_->GetYaxis(); minY_ = static_cast(yAxis->GetXmin()); maxY_ = static_cast(yAxis->GetXmax()); rangeY_ = maxY_ - minY_; nBinsX_ = static_cast(hist_->GetNbinsX()); nBinsY_ = static_cast(hist_->GetNbinsY()); binXWidth_ = static_cast(TMath::Abs(rangeX_)/(nBinsX_*1.0)); binYWidth_ = static_cast(TMath::Abs(rangeY_)/(nBinsY_*1.0)); if(static_cast(errorLo_->GetNbinsX()) != nBinsX_ || static_cast(errorLo_->GetNbinsY()) != nBinsY_) { std::cerr << "ERROR in Lau2DHistDP constructor : the lower error histogram has a different number of bins to the main histogram." << std::endl; gSystem->Exit(EXIT_FAILURE); } if(static_cast(errorHi_->GetNbinsX()) != nBinsX_ || static_cast(errorHi_->GetNbinsY()) != nBinsY_) { std::cerr << "ERROR in Lau2DHistDP constructor : the upper error histogram has a different number of bins to the main histogram." << std::endl; gSystem->Exit(EXIT_FAILURE); } xAxis = errorLo_->GetXaxis(); yAxis = errorLo_->GetYaxis(); if(static_cast(xAxis->GetXmin()) != minX_ || static_cast(xAxis->GetXmax()) != maxX_) { std::cerr << "ERROR in Lau2DHistDP constructor : the lower error histogram has a different x range to the main histogram." << std::endl; gSystem->Exit(EXIT_FAILURE); } if(static_cast(yAxis->GetXmin()) != minY_ || static_cast(yAxis->GetXmax()) != maxY_) { std::cerr << "ERROR in Lau2DHistDP constructor : the lower error histogram has a different y range to the main histogram." << std::endl; gSystem->Exit(EXIT_FAILURE); } xAxis = errorHi_->GetXaxis(); yAxis = errorHi_->GetYaxis(); if(static_cast(xAxis->GetXmin()) != minX_ || static_cast(xAxis->GetXmax()) != maxX_) { std::cerr << "ERROR in Lau2DHistDP constructor : the upper error histogram has a different x range to the main histogram." << std::endl; gSystem->Exit(EXIT_FAILURE); } if(static_cast(yAxis->GetXmin()) != minY_ || static_cast(yAxis->GetXmax()) != maxY_) { std::cerr << "ERROR in Lau2DHistDP constructor : the upper error histogram has a different y range to the main histogram." << std::endl; gSystem->Exit(EXIT_FAILURE); } if (fluctuateBins) { this->doBinFluctuation(hist_,errorHi_,errorLo_); } if (avEff > 0.0 && avEffError > 0.0) { this->raiseOrLowerBins(hist_,avEff,avEffError); } } Lau2DHistDP::~Lau2DHistDP() { delete hist_; hist_ = 0; if(errorHi_) { delete errorHi_; errorHi_=0; } if(errorLo_) { delete errorLo_; errorLo_=0; } } Double_t Lau2DHistDP::getBinHistValue(Int_t xBinNo, Int_t yBinNo) const { if (xBinNo < 0) { xBinNo = 0; } else if (xBinNo >= nBinsX_) { return 0.0; } if (yBinNo < 0) { yBinNo = 0; } else if (yBinNo >= nBinsY_) { return 0.0; } Double_t value = hist_->GetBinContent(xBinNo+1, yBinNo+1); return value; } Double_t Lau2DHistDP::interpolateXY(Double_t x, Double_t y) const { // This function returns the interpolated value of the histogram function // for the given values of x and y by finding the adjacent bins and extrapolating // using weights based on the inverse distance of the point from the adajcent // bin centres. // Here, x = m13^2, y = m23^2, or m', theta' for square DP co-ordinates // If we're only using one half then flip co-ordinates // appropriately for conventional or square DP this->getUpperHalf(x,y); // First ask whether the point is inside the kinematic region. if (this->withinDPBoundaries(x,y) == kFALSE) { std::cerr << "WARNING in Lau2DHistDP::interpolateXY : Given position is outside the DP boundary, returning 0.0." << std::endl; return 0.0; } // Find the 2D histogram bin for x and y Int_t i = Int_t((x - minX_)*nBinsX_/rangeX_); Int_t j = Int_t((y - minY_)*nBinsY_/rangeY_); if (i >= nBinsX_) {i = nBinsX_ - 1;} if (j >= nBinsY_) {j = nBinsY_ - 1;} // Ask whether we want to do the interpolation, since this method is // not reliable for low statistics histograms. if (useInterpolation_ == kFALSE) {return this->getBinHistValue(i,j);} // Find the bin centres (actual co-ordinate positions, not histogram indices) Double_t cbinx = Double_t(i+0.5)*rangeX_/nBinsX_ + minX_; Double_t cbiny = Double_t(j+0.5)*rangeY_/nBinsY_ + minY_; // If bin centres are outside kinematic region, do not extrapolate if (this->withinDPBoundaries(cbinx,cbiny) == kFALSE) {return this->getBinHistValue(i,j);} // Find the adjacent bins Double_t deltax = x - cbinx; Double_t deltay = y - cbiny; Int_t i_adj(0), j_adj(0); if (deltax > 0.0) { i_adj = i + 1; } else { i_adj = i - 1; } if (deltay > 0.0) { j_adj = j + 1; } else { j_adj = j - 1; } Bool_t isXBoundary(kFALSE), isYBoundary(kFALSE); Double_t value(0.0); if (i_adj >= nBinsX_ || i_adj < 0) {isYBoundary = kTRUE;} if (j_adj >= nBinsY_ || j_adj < 0) {isXBoundary = kTRUE;} // In the corners, do no interpolation. Use entry in bin (i,j) if (isXBoundary == kTRUE && isYBoundary == kTRUE) { value = this->getBinHistValue(i,j); } else if (isXBoundary == kTRUE && isYBoundary == kFALSE) { // Find the adjacent x bin centre Double_t cbinx_adj = Double_t(i_adj+0.5)*rangeX_/nBinsX_ + minX_; if (this->withinDPBoundaries(cbinx_adj, y) == kFALSE) { // The adjacent bin is outside the DP range. Don't extrapolate. value = this->getBinHistValue(i,j); } else { Double_t dx0 = TMath::Abs(x - cbinx); Double_t dx1 = TMath::Abs(cbinx_adj - x); Double_t inter_denom = dx0 + dx1; Double_t value1 = this->getBinHistValue(i,j); Double_t value2 = this->getBinHistValue(i_adj,j); value = (value1*dx1 + value2*dx0)/inter_denom; } } else if (isYBoundary == kTRUE && isXBoundary == kFALSE) { // Find the adjacent y bin centre Double_t cbiny_adj = Double_t(j_adj+0.5)*rangeY_/nBinsY_ + minY_; if (this->withinDPBoundaries(x, cbiny_adj) == kFALSE) { // The adjacent bin is outside the DP range. Don't extrapolate. value = this->getBinHistValue(i,j); } else { Double_t dy0 = TMath::Abs(y - cbiny); Double_t dy1 = TMath::Abs(cbiny_adj - y); Double_t inter_denom = dy0 + dy1; Double_t value1 = this->getBinHistValue(i,j); Double_t value2 = this->getBinHistValue(i,j_adj); value = (value1*dy1 + value2*dy0)/inter_denom; } } else { // 2D linear interpolation using inverse distance as weights. // Find the adjacent x and y bin centres Double_t cbinx_adj = Double_t(i_adj+0.5)*rangeX_/nBinsX_ + minX_; Double_t cbiny_adj = Double_t(j_adj+0.5)*rangeY_/nBinsY_ + minY_; if (this->withinDPBoundaries(cbinx_adj, cbiny_adj) == kFALSE) { // The adjacent bin is outside the DP range. Don't extrapolate. value = this->getBinHistValue(i,j); } else { Double_t dx0 = TMath::Abs(x - cbinx); Double_t dx1 = TMath::Abs(cbinx_adj - x); Double_t dy0 = TMath::Abs(y - cbiny); Double_t dy1 = TMath::Abs(cbiny_adj - y); Double_t inter_denom = (dx0 + dx1)*(dy0 + dy1); Double_t value1 = this->getBinHistValue(i,j); Double_t value2 = this->getBinHistValue(i_adj,j); Double_t value3 = this->getBinHistValue(i,j_adj); Double_t value4 = this->getBinHistValue(i_adj,j_adj); value = value1*dx1*dy1 + value2*dx0*dy1 + value3*dx1*dy0 + value4*dx0*dy0; value /= inter_denom; } } return value; } diff --git a/src/Lau2DHistDPPdf.cc b/src/Lau2DHistDPPdf.cc index f46a51f..1fd4c8a 100644 --- a/src/Lau2DHistDPPdf.cc +++ b/src/Lau2DHistDPPdf.cc @@ -1,371 +1,370 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file Lau2DHistDPPdf.cc \brief File containing implementation of Lau2DHistDPPdf class. */ #include #include "TAxis.h" #include "TH2.h" #include "TRandom.h" #include "Lau2DHistDPPdf.hh" #include "LauKinematics.hh" #include "LauRandom.hh" #include "LauVetoes.hh" -ClassImp(Lau2DHistDPPdf) Lau2DHistDPPdf::Lau2DHistDPPdf(const TH2* hist, LauKinematics* kinematics, const LauVetoes* vetoes, Bool_t useInterpolation, Bool_t fluctuateBins, Bool_t useUpperHalfOnly, Bool_t squareDP) : Lau2DAbsHistDPPdf(kinematics,vetoes,useUpperHalfOnly,squareDP), hist_(hist ? dynamic_cast(hist->Clone()) : 0), minX_(0.0), maxX_(0.0), minY_(0.0), maxY_(0.0), rangeX_(0.0), rangeY_(0.0), binXWidth_(0.0), binYWidth_(0.0), invBinXWidth_(0.0), invBinYWidth_(0.0), nBinsX_(0), nBinsY_(0), norm_(0.0), useInterpolation_(useInterpolation) { // For square Dalitz plots, the co-ordinates must be m', theta' // The input data to the fit is still in m13^2, m23^2 co-ords, and a // transformation is applied to go from one co-ordinate system to the // other. // Save various attributes of the histogram // (axis ranges, number of bins, areas) if ( hist_ ) { TAxis* xAxis = hist_->GetXaxis(); minX_ = xAxis->GetXmin(); maxX_ = xAxis->GetXmax(); TAxis* yAxis = hist_->GetYaxis(); minY_ = yAxis->GetXmin(); maxY_ = yAxis->GetXmax(); nBinsX_ = hist_->GetNbinsX(); nBinsY_ = hist_->GetNbinsY(); } else { minX_ = getKinematics()->getm13SqMin(); maxX_ = getKinematics()->getm13SqMax(); minY_ = getKinematics()->getm23SqMin(); maxY_ = getKinematics()->getm23SqMax(); nBinsX_ = 1; nBinsY_ = 1; } rangeX_ = maxX_ - minX_; rangeY_ = maxY_ - minY_; if (nBinsX_ > 0) { binXWidth_ = TMath::Abs(rangeX_)/(nBinsX_*1.0); } if (nBinsY_ > 0) { binYWidth_ = TMath::Abs(rangeY_)/(nBinsY_*1.0); } if (binXWidth_ > 1e-10) { invBinXWidth_ = 1.0/binXWidth_; } if (binYWidth_ > 1e-10) { invBinYWidth_ = 1.0/binYWidth_; } // If the bins are to be fluctuated then do so now before // calculating anything that depends on the bin content. if (fluctuateBins) { this->doBinFluctuation(hist_); } // Calculate the PDF normalisation. this->calcHistNorm(); // And check it is OK. this->checkNormalisation(); // Also obtain the maximum height this->calcMaxHeight(hist_); } Lau2DHistDPPdf::~Lau2DHistDPPdf() { // Destructor delete hist_; hist_ = 0; } void Lau2DHistDPPdf::calcHistNorm() { // Calculate the histogram normalisation. We must integrate // over the allowed kinematic DP region. // Loop over the total x and y range to get the total area // under x and y. Just sum the contributions up using 1e-3 increments // of the range in x and y. Multiply the end result by dx and dy. const Double_t axisMin = TMath::Min( minX_, minY_ ); const Double_t axisMax = TMath::Max( maxX_, maxY_ ); const Double_t axisRange = axisMax - axisMin; const Double_t dx(1e-3 * axisRange); const Double_t dy(dx); Double_t area(0.0); Double_t x(axisMin + dx/2.0); while (x < axisMax) { Double_t y(axisMin + dy/2.0); while (y < axisMax) { area += this->interpolateXY(x,y); y += dy; } // y while loop x += dx; } // x while loop norm_ = area*dx*dy; std::cout << "INFO in Lau2DHistDPPdf::calcHistNorm : Norm = " << norm_ << ", bX*bY = " << binXWidth_ << "*" << binYWidth_ << " = " << binXWidth_*binYWidth_ << std::endl; } Double_t Lau2DHistDPPdf::getBinHistValue(Int_t xBinNo, Int_t yBinNo) const { if (xBinNo < 0) { xBinNo = 0; } else if (xBinNo >= nBinsX_) { return 0.0; } if (yBinNo < 0) { yBinNo = 0; } else if (yBinNo >= nBinsY_) { return 0.0; } if ( hist_ == 0 ) { return 1.0; } Double_t value = hist_->GetBinContent(xBinNo+1, yBinNo+1); return value; } Double_t Lau2DHistDPPdf::interpolateXYNorm(Double_t x, Double_t y) const { // Get the normalised interpolated value. Double_t value = this->interpolateXY(x,y); return value/norm_; } Double_t Lau2DHistDPPdf::interpolateXY(Double_t x, Double_t y) const { // This function returns the interpolated value of the histogram function // for the given values of x and y by finding the adjacent bins and extrapolating // using weights based on the inverse distance of the point from the adajcent // bin centres. // Here, x = m13^2, y = m23^2, or m', theta' for square DP co-ordinates // If we're only using one half then flip co-ordinates // appropriately for conventional or square DP getUpperHalf(x,y); // First ask whether the point is inside the kinematic region. if (withinDPBoundaries(x,y) == kFALSE) {return 0.0;} // Update the kinematics to the position of interest. updateKinematics(x,y); // Check that we're not inside a veto Bool_t vetoOK(kTRUE); if (getVetoes()) { vetoOK = getVetoes()->passVeto(getKinematics()); } if (vetoOK == kFALSE) {return 0.0;} // Find the 2D histogram bin for x and y Int_t i = TMath::FloorNint((x - minX_)*invBinXWidth_); Int_t j = TMath::FloorNint((y - minY_)*invBinYWidth_); if (i >= nBinsX_) {i = nBinsX_ - 1;} if (j >= nBinsY_) {j = nBinsY_ - 1;} // Ask whether we want to do the interpolation, since this method is // not reliable for low statistics histograms. if (useInterpolation_ == kFALSE) { return this->getBinHistValue(i,j); } // Find the bin centres (actual co-ordinate positions, not histogram indices) Double_t cbinx = (i+0.5)*binXWidth_ + minX_; Double_t cbiny = (j+0.5)*binYWidth_ + minY_; // If bin centres are outside kinematic region, do not extrapolate if (withinDPBoundaries(cbinx, cbiny) == kFALSE) { return this->getBinHistValue(i,j); } // Find the adjacent bins Double_t deltax = x - cbinx; Double_t deltay = y - cbiny; Int_t i_adj(0), j_adj(0); if (deltax > 0.0) { i_adj = i + 1; } else { i_adj = i - 1; } if (deltay > 0.0) { j_adj = j + 1; } else { j_adj = j - 1; } Bool_t isXBoundary(kFALSE), isYBoundary(kFALSE); Double_t value(0.0); if (i_adj >= nBinsX_ || i_adj < 0) {isYBoundary = kTRUE;} if (j_adj >= nBinsY_ || j_adj < 0) {isXBoundary = kTRUE;} // In the corners, do no interpolation. Use entry in bin (i,j) if (isXBoundary == kTRUE && isYBoundary == kTRUE) { value = this->getBinHistValue(i,j); } else if (isXBoundary == kTRUE && isYBoundary == kFALSE) { // Find the adjacent x bin centre Double_t cbinx_adj = Double_t(i_adj+0.5)*binXWidth_ + minX_; if (withinDPBoundaries(cbinx_adj, y) == kFALSE) { // The adjacent bin is outside the DP range. Don't extrapolate. value = this->getBinHistValue(i,j); } else { Double_t dx0 = TMath::Abs(x - cbinx); Double_t dx1 = TMath::Abs(cbinx_adj - x); Double_t inter_denom = dx0 + dx1; Double_t value1 = this->getBinHistValue(i,j); Double_t value2 = this->getBinHistValue(i_adj,j); value = (value1*dx1 + value2*dx0)/inter_denom; } } else if (isYBoundary == kTRUE && isXBoundary == kFALSE) { // Find the adjacent y bin centre Double_t cbiny_adj = Double_t(j_adj+0.5)*binYWidth_ + minY_; if (withinDPBoundaries(x, cbiny_adj) == kFALSE) { // The adjacent bin is outside the DP range. Don't extrapolate. value = this->getBinHistValue(i,j); } else { Double_t dy0 = TMath::Abs(y - cbiny); Double_t dy1 = TMath::Abs(cbiny_adj - y); Double_t inter_denom = dy0 + dy1; Double_t value1 = this->getBinHistValue(i,j); Double_t value2 = this->getBinHistValue(i,j_adj); value = (value1*dy1 + value2*dy0)/inter_denom; } } else { // 2D linear interpolation using inverse distance as weights. // Find the adjacent x and y bin centres Double_t cbinx_adj = Double_t(i_adj+0.5)*binXWidth_ + minX_; Double_t cbiny_adj = Double_t(j_adj+0.5)*binYWidth_ + minY_; if (withinDPBoundaries(cbinx_adj, cbiny_adj) == kFALSE) { // The adjacent bin is outside the DP range. Don't extrapolate. value = this->getBinHistValue(i,j); } else { Double_t dx0 = TMath::Abs(x - cbinx); Double_t dx1 = TMath::Abs(cbinx_adj - x); Double_t dy0 = TMath::Abs(y - cbiny); Double_t dy1 = TMath::Abs(cbiny_adj - y); Double_t inter_denom = (dx0 + dx1)*(dy0 + dy1); Double_t value1 = this->getBinHistValue(i,j); Double_t value2 = this->getBinHistValue(i_adj,j); Double_t value3 = this->getBinHistValue(i,j_adj); Double_t value4 = this->getBinHistValue(i_adj,j_adj); value = value1*dx1*dy1 + value2*dx0*dy1 + value3*dx1*dy0 + value4*dx0*dy0; value /= inter_denom; } } return value; } void Lau2DHistDPPdf::checkNormalisation() { // Loop over the total x and y range to get the total area // under x and y. Just sum the contributions up using 1e-3 increments // of the range in x and y. Multiply the end result by dx and dy. const Double_t axisMin = TMath::Min( minX_, minY_ ); const Double_t axisMax = TMath::Max( maxX_, maxY_ ); const Double_t axisRange = axisMax - axisMin; const Double_t dx(1e-3 * axisRange); const Double_t dy(dx); Double_t area(0.0); Double_t areaNoNorm(0.0); // Preserve the value of a variable we change temporarily Bool_t interpolate = useInterpolation_; Double_t x(axisMin + dx/2.0); while (x < axisMax) { Double_t y(axisMin + dy/2.0); while (y < axisMax) { area += this->interpolateXYNorm(x,y); useInterpolation_ = kFALSE; areaNoNorm += this->interpolateXY(x,y); useInterpolation_ = kTRUE; y += dy; } // y while loop x += dx; } // x while loop Double_t norm = area*dx*dy; useInterpolation_ = interpolate; //Restore old value std::cout << "INFO in Lau2DHistDPPdf::checkNormalisation : Area = " << area << ", dx = " << dx << ", dy = " << dy << ", dx*dy = " << dx*dy << std::endl; std::cout << " : Area with no norm = " << areaNoNorm << "*dx*dy = " << areaNoNorm*dx*dy << std::endl; std::cout << " : The total area of the normalised histogram PDF is " << norm << std::endl; } diff --git a/src/Lau2DHistPdf.cc b/src/Lau2DHistPdf.cc index 9bc41bc..b7c52d3 100644 --- a/src/Lau2DHistPdf.cc +++ b/src/Lau2DHistPdf.cc @@ -1,486 +1,485 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file Lau2DHistPdf.cc \brief File containing implementation of Lau2DHistPdf class. */ #include #include #include #include "TAxis.h" #include "TH2.h" #include "TRandom.h" #include "TSystem.h" #include "Lau1DHistPdf.hh" #include "Lau2DHistPdf.hh" #include "LauRandom.hh" class LauParameter; -ClassImp(Lau2DHistPdf) Lau2DHistPdf::Lau2DHistPdf(const std::vector& theVarNames, const TH2* hist, const LauFitData& minVals, const LauFitData& maxVals, Bool_t useInterpolation, Bool_t fluctuateBins) : LauAbsPdf(theVarNames, std::vector(), minVals, maxVals), hist_(hist ? dynamic_cast(hist->Clone()) : 0), xProj_(0), yProj_(0), xVarPdf_(0), yVarPdf_(0), xName_(""), yName_(""), nBinsX_(0), nBinsY_(0), minX_(0.0), maxX_(0.0), minY_(0.0), maxY_(0.0), rangeX_(0.0), rangeY_(0.0), binXWidth_(0.0), binYWidth_(0.0), invBinXWidth_(0.0), invBinYWidth_(0.0), useInterpolation_(useInterpolation), fluctuateBins_(fluctuateBins) { // Constructor // Check that we have two variables if ( this->nInputVars() != 2 ) { std::cerr << "ERROR in Lau2DHistPdf::Lau2DHistPdf : Have not been provided with exactly two variables." << std::endl; gSystem->Exit(EXIT_FAILURE); } // Set the variable names from the abstract class xName_ = this->varNames()[0]; yName_ = this->varNames()[1]; // Set the variable limits from the abstract class minX_ = this->getMinAbscissa(xName_); maxX_ = this->getMaxAbscissa(xName_); minY_ = this->getMinAbscissa(yName_); maxY_ = this->getMaxAbscissa(yName_); rangeX_ = maxX_ - minX_; rangeY_ = maxY_ - minY_; // Have we got a valid histogram if ( hist_ == 0 ) { std::cerr << "ERROR in Lau2DHistPdf::Lau2DHistPdf : Histogram pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } // Set the directory for the histogram hist_->SetDirectory(0); // Save various attributes of the histogram nBinsX_ = hist_->GetNbinsX(); nBinsY_ = hist_->GetNbinsY(); TAxis* xAxis = hist_->GetXaxis(); Double_t xAxisMin = xAxis->GetXmin(); Double_t xAxisMax = xAxis->GetXmax(); TAxis* yAxis = hist_->GetYaxis(); Double_t yAxisMin = yAxis->GetXmin(); Double_t yAxisMax = yAxis->GetXmax(); // Check that axis ranges corresponds to ranges of abscissas if (TMath::Abs(minX_ - xAxisMin)>1e-6) { std::cerr << "ERROR in Lau2DHistPdf::Lau2DHistPdf : Histogram x-axis minimum: " << xAxisMin << " does not correspond to " << xName_ << " minimum: " << minX_ << "." << std::endl; gSystem->Exit(EXIT_FAILURE); } if (TMath::Abs(maxX_ - xAxisMax)>1e-6) { std::cerr << "ERROR in Lau2DHistPdf::Lau2DHistPdf : Histogram x-axis maximum: " << xAxisMax << " does not correspond to " << xName_ << " maximum: " << maxX_ << "." << std::endl; gSystem->Exit(EXIT_FAILURE); } if (TMath::Abs(minY_ - yAxisMin)>1e-6) { std::cerr << "ERROR in Lau2DHistPdf::Lau2DHistPdf : Histogram y-axis minimum: " << yAxisMin << " does not correspond to " << yName_ << " minimum: " << minY_ << "." << std::endl; gSystem->Exit(EXIT_FAILURE); } if (TMath::Abs(maxY_ - yAxisMax)>1e-6) { std::cerr << "ERROR in Lau2DHistPdf::Lau2DHistPdf : Histogram y-axis maximum: " << yAxisMax << " does not correspond to " << yName_ << " maximum: " << maxY_ << "." << std::endl; gSystem->Exit(EXIT_FAILURE); } // Calculate the bin widths and inverse bin widths binXWidth_ = static_cast(TMath::Abs(rangeX_)/(nBinsX_*1.0)); binYWidth_ = static_cast(TMath::Abs(rangeY_)/(nBinsY_*1.0)); if (binXWidth_ > 1e-10) {invBinXWidth_ = 1.0/binXWidth_;} if (binYWidth_ > 1e-10) {invBinYWidth_ = 1.0/binYWidth_;} // If the bins are to be fluctuated then do so now before // calculating anything that depends on the bin content. if (fluctuateBins) { this->doBinFluctuation(); } // Create the projections and 1D PDFs from those xProj_ = hist_->ProjectionX(); yProj_ = hist_->ProjectionY(); if ( !xProj_ || !yProj_ ) { std::cerr << "ERROR in Lau2DHistPdf::Lau2DHistPdf : Can't get X or Y projection from 2D histogram." << std::endl; gSystem->Exit(EXIT_FAILURE); } xVarPdf_ = new Lau1DHistPdf(xName_, xProj_, minX_, maxX_, useInterpolation_, fluctuateBins_); yVarPdf_ = new Lau1DHistPdf(yName_, yProj_, minY_, maxY_, useInterpolation_, fluctuateBins_); // Calculate the PDF normalisation. this->calcNorm(); // And check it is OK. this->checkNormalisation(); } Lau2DHistPdf::~Lau2DHistPdf() { // Destructor delete hist_; hist_ = 0; delete xProj_; xProj_ = 0; delete yProj_; yProj_ = 0; delete xVarPdf_; xVarPdf_ = 0; delete yVarPdf_; yVarPdf_ = 0; } void Lau2DHistPdf::calcPDFHeight( const LauKinematics* /*kinematics*/ ) { if (this->heightUpToDate()) { return; } // Get the maximum height of the histogram Int_t maxBin = hist_->GetMaximumBin(); Double_t height = hist_->GetBinContent(maxBin); this->setMaxHeight(height); } void Lau2DHistPdf::calcNorm() { // Calculate the histogram normalisation. // Loop over the total x and y range to get the total area under x // and y. Just sum the contributions up using 1e-3 increments of // the range in x and y. Multiply the end result by dx and dy. Double_t dx(1e-3*rangeX_), dy(1e-3*rangeY_); Double_t area(0.0); Double_t x(minX_ + dx/2.0); while (x > minX_ && x < maxX_) { Double_t y(minY_ + dy/2.0); while (y > minY_ && y < maxY_) { area += this->interpolateXY(x,y); y += dy; } // y while loop x += dx; } // x while loop Double_t norm = area*dx*dy; this->setNorm(norm); } void Lau2DHistPdf::checkNormalisation() { Double_t dx(1e-3*rangeX_), dy(1e-3*rangeY_); Double_t area(0.0); Double_t areaNoNorm(0.0); // Preserve the value of a variable we change temporarily Bool_t interpolate = useInterpolation_; Double_t x(minX_ + dx/2.0); while (x > minX_ && x < maxX_) { Double_t y(minY_ + dy/2.0); while (y > minY_ && y < maxY_) { area += this->interpolateXYNorm(x,y); useInterpolation_ = kFALSE; areaNoNorm += this->interpolateXY(x,y); useInterpolation_ = kTRUE; y += dy; } // y while loop x += dx; } // x while loop Double_t norm = area*dx*dy; useInterpolation_ = interpolate; //Restore old value std::cout << "INFO in Lau2DHistPdf::checkNormalisation : Area = " << area << ", dx = " << dx << ", dy = " << dy << ", dx*dy = " << dx*dy << std::endl; std::cout << " : Area with no norm = " << areaNoNorm << "*dx*dy = " << areaNoNorm*dx*dy << std::endl; std::cout << " : The total area of the normalised histogram PDF is " << norm << std::endl; } Double_t Lau2DHistPdf::getBinHistValue(Int_t i, Int_t j) const { // Check that x co-ord is in range [1 , nBinsX_] if ((i < 1) || (i > nBinsX_)) { return 0.0; } // Check that y co-ord is in range [1 , nBinsY_] if ((j < 1) || (j > nBinsY_)) { return 0.0; } Double_t value = hist_->GetBinContent(i,j); // protect against negative values if ( value < 0.0 ) { std::cerr << "WARNING in Lau2DHistPdf::getBinHistValue : Negative bin content set to zero!" << std::endl; value = 0.0; } return value; } Double_t Lau2DHistPdf::interpolateXYNorm(Double_t x, Double_t y) const { // Get the normalised interpolated value. Double_t value = this->interpolateXY(x,y); Double_t norm = this->getNorm(); return value/norm; } Double_t Lau2DHistPdf::interpolateXY(Double_t x, Double_t y) const { // This function returns the interpolated value of the histogram // function for the given values of x and y by finding the adjacent // bins and extrapolating using weights based on the inverse // distance of the point from the adajcent bin centres. // Find the 2D histogram bin for x and y Int_t i = static_cast((x - minX_)*invBinXWidth_)+1; Int_t j = static_cast((y - minY_)*invBinYWidth_)+1; if (i > nBinsX_) {i = nBinsX_;} if (j > nBinsY_) {j = nBinsY_;} // Ask whether we want to do the interpolation, since this method is // not reliable for low statistics histograms. if (useInterpolation_ == kFALSE) { return this->getBinHistValue(i,j); } // Find the bin centres (actual co-ordinate positions, not histogram indices) Double_t cbinx = static_cast(i-0.5)*binXWidth_ + minX_; Double_t cbiny = static_cast(j-0.5)*binYWidth_ + minY_; // Find the adjacent bins Double_t deltax = x - cbinx; Double_t deltay = y - cbiny; Int_t i_adj(0), j_adj(0); if (deltax > 0.0) { i_adj = i + 1; } else { i_adj = i - 1; } if (deltay > 0.0) { j_adj = j + 1; } else { j_adj = j - 1; } Bool_t isXBoundary(kFALSE), isYBoundary(kFALSE); Double_t value(0.0); if (i_adj > nBinsX_ || i_adj < 1) {isYBoundary = kTRUE;} if (j_adj > nBinsY_ || j_adj < 1) {isXBoundary = kTRUE;} // In the corners, do no interpolation. Use entry in bin (i,j) if (isXBoundary == kTRUE && isYBoundary == kTRUE) { value = this->getBinHistValue(i,j); } else if (isXBoundary == kTRUE && isYBoundary == kFALSE) { // Find the adjacent x bin centre Double_t cbinx_adj = static_cast(i_adj-0.5)*binXWidth_ + minX_; Double_t dx0 = TMath::Abs(x - cbinx); Double_t dx1 = TMath::Abs(cbinx_adj - x); Double_t inter_denom = dx0 + dx1; Double_t value1 = this->getBinHistValue(i,j); Double_t value2 = this->getBinHistValue(i_adj,j); value = (value1*dx1 + value2*dx0)/inter_denom; } else if (isYBoundary == kTRUE && isXBoundary == kFALSE) { // Find the adjacent y bin centre Double_t cbiny_adj = static_cast(j_adj-0.5)*binYWidth_ + minY_; Double_t dy0 = TMath::Abs(y - cbiny); Double_t dy1 = TMath::Abs(cbiny_adj - y); Double_t inter_denom = dy0 + dy1; Double_t value1 = this->getBinHistValue(i,j); Double_t value2 = this->getBinHistValue(i,j_adj); value = (value1*dy1 + value2*dy0)/inter_denom; } else { // 2D linear interpolation using inverse distance as weights. // Find the adjacent x and y bin centres Double_t cbinx_adj = static_cast(i_adj-0.5)*binXWidth_ + minX_; Double_t cbiny_adj = static_cast(j_adj-0.5)*binYWidth_ + minY_; Double_t dx0 = TMath::Abs(x - cbinx); Double_t dx1 = TMath::Abs(cbinx_adj - x); Double_t dy0 = TMath::Abs(y - cbiny); Double_t dy1 = TMath::Abs(cbiny_adj - y); Double_t inter_denom = (dx0 + dx1)*(dy0 + dy1); Double_t value1 = this->getBinHistValue(i,j); Double_t value2 = this->getBinHistValue(i_adj,j); Double_t value3 = this->getBinHistValue(i,j_adj); Double_t value4 = this->getBinHistValue(i_adj,j_adj); value = value1*dx1*dy1 + value2*dx0*dy1 + value3*dx1*dy0 + value4*dx0*dy0; value /= inter_denom; } return value; } void Lau2DHistPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Calculate the interpolated value Double_t x = abscissas[0]; Double_t y = abscissas[1]; Double_t value = this->interpolateXY(x,y); this->setUnNormPDFVal(value); // TODO - do we need this? I think probably not. // Have the 1D PDFs calculate their likelihoods as well //xVarPdf_->calcLikelihoodInfo(x); //yVarPdf_->calcLikelihoodInfo(y); } void Lau2DHistPdf::calcLikelihoodInfo(UInt_t iEvt) { // Call the base class method this->LauAbsPdf::calcLikelihoodInfo(iEvt); // Have the 1D PDFs retrieve their values as well xVarPdf_->calcLikelihoodInfo(iEvt); yVarPdf_->calcLikelihoodInfo(iEvt); } Double_t Lau2DHistPdf::getLikelihood( const TString& theVarName ) const { if ( theVarName == xName_ ) { return xVarPdf_->getLikelihood(); } else if ( theVarName == yName_ ) { return yVarPdf_->getLikelihood(); } else { std::cerr << "ERROR in Lau2DHistPdf::getLikelihood : Unrecognised variable name \"" << theVarName << "\", cannot determine likelihood." << std::endl; return 0.0; } } void Lau2DHistPdf::cacheInfo(const LauFitDataTree& inputData) { // Call the base class method this->LauAbsPdf::cacheInfo(inputData); // Have the 1D PDFs cache their info as well xVarPdf_->cacheInfo(inputData); yVarPdf_->cacheInfo(inputData); } void Lau2DHistPdf::doBinFluctuation() { TRandom* random(LauRandom::randomFun()); for (Int_t i(0); iGetBinContent(i+1,j+1); Double_t currentError = hist_->GetBinError(i+1,j+1); Double_t newContent = random->Gaus(currentContent,currentError); if (newContent<0.0) { hist_->SetBinContent(i+1,j+1,0.0); } else { hist_->SetBinContent(i+1,j+1,newContent); } } } } LauFitData Lau2DHistPdf::generate(const LauKinematics* kinematics) { this->withinGeneration(kTRUE); // Check that the PDF height is up to date this->calcPDFHeight( kinematics ); // Generate the value of the abscissa. Bool_t gotAbscissa(kFALSE); if (this->getRandomFun() == 0) { std::cerr << "ERROR in Lau2DHistPdf::generate : Please set the random number generator for this PDF by using the setRandomFun(TRandom*) function." << std::endl; this->withinGeneration(kFALSE); gSystem->Exit(EXIT_FAILURE); } Double_t genPDFVal(0.0); LauAbscissas genAbscissas(2); Double_t PDFheight = this->getMaxHeight()*(1.0+1e-11); while (!gotAbscissa) { genAbscissas[0] = this->getRandomFun()->Rndm()*this->getRange(xName_) + this->getMinAbscissa(xName_); genAbscissas[1] = this->getRandomFun()->Rndm()*this->getRange(yName_) + this->getMinAbscissa(yName_); this->calcLikelihoodInfo(genAbscissas); genPDFVal = this->getUnNormLikelihood(); if (this->getRandomFun()->Rndm() <= genPDFVal/PDFheight) {gotAbscissa = kTRUE;} if (genPDFVal > PDFheight) { std::cerr << "WARNING in LauAbsPdf::generate : genPDFVal = " << genPDFVal << " is larger than the specified PDF height " << this->getMaxHeight() << " for (x,y) = (" << genAbscissas[0] << "," << genAbscissas[1] << ")." << std::endl; std::cerr << " : Need to reset height to be larger than " << genPDFVal << " by using the setMaxHeight(Double_t) function and re-run the Monte Carlo generation!" << std::endl; } } LauFitData genData; genData[ xName_ ] = genAbscissas[0]; genData[ yName_ ] = genAbscissas[1]; this->withinGeneration(kFALSE); return genData; } diff --git a/src/Lau2DSplineDP.cc b/src/Lau2DSplineDP.cc index dc609d9..a21edd5 100644 --- a/src/Lau2DSplineDP.cc +++ b/src/Lau2DSplineDP.cc @@ -1,189 +1,188 @@ /* Copyright 2013 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file Lau2DSplineDP.cc \brief File containing implementation of Lau2DSplineDP class. */ #include #include "TAxis.h" #include "TH2.h" #include "TRandom.h" #include "TSystem.h" #include "Lau2DSplineDP.hh" #include "Lau2DCubicSpline.hh" #include "LauDaughters.hh" #include "LauKinematics.hh" #include "LauRandom.hh" -ClassImp(Lau2DSplineDP) Lau2DSplineDP::Lau2DSplineDP(const TH2* hist, const LauDaughters* daughters, Bool_t fluctuateBins, Double_t avEff, Double_t avEffError, Bool_t useUpperHalfOnly, Bool_t squareDP) : Lau2DAbsHistDP(daughters,useUpperHalfOnly,squareDP), spline_(0) { //We may need to modify the histogram so clone it TH2* tempHist(hist ? dynamic_cast(hist->Clone()) : 0); if ( ! tempHist ) { std::cerr << "ERROR in Lau2DSplineDP constructor : the histogram pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } if (fluctuateBins) { this->doBinFluctuation(tempHist); } if (avEff > 0.0 && avEffError > 0.0) { this->raiseOrLowerBins(tempHist,avEff,avEffError); } spline_ = new Lau2DCubicSpline(*tempHist); delete tempHist; } Lau2DSplineDP::Lau2DSplineDP(const TH2* hist, const TH2* errorHi, const TH2* errorLo, const LauDaughters* daughters, Bool_t fluctuateBins, Double_t avEff, Double_t avEffError, Bool_t useUpperHalfOnly, Bool_t squareDP) : Lau2DAbsHistDP(daughters,useUpperHalfOnly,squareDP), spline_(0) { //We may need to modify the histogram so clone it TH2* tempHist(hist ? dynamic_cast(hist->Clone()) : 0); TH2* tempErrorHi(errorHi ? dynamic_cast(errorHi->Clone()) : 0); TH2* tempErrorLo(errorLo ? dynamic_cast(errorLo->Clone()) : 0); if ( ! tempHist ) { std::cerr << "ERROR in Lau2DSplineDP constructor : the histogram pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } if ( ! tempErrorHi ) { std::cerr << "ERROR in Lau2DHistDP constructor : the upper error histogram pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } if ( ! tempErrorLo ) { std::cerr << "ERROR in Lau2DHistDP constructor : the lower error histogram pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } TAxis* xAxis = tempHist->GetXaxis(); Double_t minX = static_cast(xAxis->GetXmin()); Double_t maxX = static_cast(xAxis->GetXmax()); TAxis* yAxis = tempHist->GetYaxis(); Double_t minY = static_cast(yAxis->GetXmin()); Double_t maxY = static_cast(yAxis->GetXmax()); Int_t nBinsX = static_cast(tempHist->GetNbinsX()); Int_t nBinsY = static_cast(tempHist->GetNbinsY()); if(static_cast(tempErrorLo->GetNbinsX()) != nBinsX || static_cast(tempErrorLo->GetNbinsY()) != nBinsY) { std::cerr << "ERROR in Lau2DHistDP constructor : the lower error histogram has a different number of bins to the main histogram." << std::endl; gSystem->Exit(EXIT_FAILURE); } if(static_cast(tempErrorHi->GetNbinsX()) != nBinsX || static_cast(tempErrorHi->GetNbinsY()) != nBinsY) { std::cerr << "ERROR in Lau2DHistDP constructor : the upper error histogram has a different number of bins to the main histogram." << std::endl; gSystem->Exit(EXIT_FAILURE); } xAxis = tempErrorLo->GetXaxis(); yAxis = tempErrorLo->GetYaxis(); if(static_cast(xAxis->GetXmin()) != minX || static_cast(xAxis->GetXmax()) != maxX) { std::cerr << "ERROR in Lau2DHistDP constructor : the lower error histogram has a different x range to the main histogram." << std::endl; gSystem->Exit(EXIT_FAILURE); } if(static_cast(yAxis->GetXmin()) != minY || static_cast(yAxis->GetXmax()) != maxY) { std::cerr << "ERROR in Lau2DHistDP constructor : the lower error histogram has a different y range to the main histogram." << std::endl; gSystem->Exit(EXIT_FAILURE); } xAxis = tempErrorHi->GetXaxis(); yAxis = tempErrorHi->GetYaxis(); if(static_cast(xAxis->GetXmin()) != minX || static_cast(xAxis->GetXmax()) != maxX) { std::cerr << "ERROR in Lau2DHistDP constructor : the upper error histogram has a different x range to the main histogram." << std::endl; gSystem->Exit(EXIT_FAILURE); } if(static_cast(yAxis->GetXmin()) != minY || static_cast(yAxis->GetXmax()) != maxY) { std::cerr << "ERROR in Lau2DHistDP constructor : the upper error histogram has a different y range to the main histogram." << std::endl; gSystem->Exit(EXIT_FAILURE); } if (fluctuateBins) { this->doBinFluctuation(tempHist,tempErrorHi,tempErrorLo); } if (avEff > 0.0 && avEffError > 0.0) { this->raiseOrLowerBins(tempHist,avEff,avEffError); } spline_ = new Lau2DCubicSpline(*tempHist); delete tempHist; delete tempErrorHi; delete tempErrorLo; } Lau2DSplineDP::~Lau2DSplineDP() { delete spline_; spline_ = 0; } Double_t Lau2DSplineDP::interpolateXY(Double_t x, Double_t y) const { // This function returns the interpolated value of the histogram function // for the given values of x and y by finding the adjacent bins and extrapolating // using weights based on the inverse distance of the point from the adajcent // bin centres. // Here, x = m13^2, y = m23^2, or m', theta' for square DP co-ordinates // If we're only using one half then flip co-ordinates // appropriately for conventional or square DP this->getUpperHalf(x,y); // First ask whether the point is inside the kinematic region. if (this->withinDPBoundaries(x,y) == kFALSE) { std::cerr << "WARNING in Lau2DSplineDP::interpolateXY : Given position is outside the DP boundary, returning 0.0." << std::endl; return 0.0; } return spline_->evaluate(x,y); } diff --git a/src/Lau2DSplineDPPdf.cc b/src/Lau2DSplineDPPdf.cc index 15259ea..86327b9 100644 --- a/src/Lau2DSplineDPPdf.cc +++ b/src/Lau2DSplineDPPdf.cc @@ -1,112 +1,111 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file Lau2DSplineDPPdf.cc \brief File containing implementation of Lau2DSplineDPPdf class. */ #include #include "TAxis.h" #include "TH2.h" #include "TRandom.h" #include "TSystem.h" #include "Lau2DSplineDPPdf.hh" #include "Lau2DCubicSpline.hh" #include "LauDaughters.hh" #include "LauKinematics.hh" #include "LauRandom.hh" -ClassImp(Lau2DSplineDPPdf) Lau2DSplineDPPdf::Lau2DSplineDPPdf(const TH2* hist, LauKinematics* kinematics, const LauVetoes* vetoes, Bool_t fluctuateBins, Bool_t useUpperHalfOnly, Bool_t squareDP) : Lau2DAbsHistDPPdf(kinematics,vetoes,useUpperHalfOnly,squareDP), spline_(0) { //We may need to modify the histogram so clone it TH2* tempHist(hist ? dynamic_cast(hist->Clone()) : 0); if ( ! tempHist ) { std::cerr << "ERROR in Lau2DSplineDPPdf constructor : the histogram pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } if (fluctuateBins) { this->doBinFluctuation(tempHist); } spline_ = new Lau2DCubicSpline(*tempHist); // Calculate the PDF normalisation. this->calcHistNorm(); // Also obtain the maximum height this->calcMaxHeight(tempHist); delete tempHist; } Lau2DSplineDPPdf::~Lau2DSplineDPPdf() { delete spline_; spline_ = 0; } Double_t Lau2DSplineDPPdf::interpolateXYNorm(Double_t x, Double_t y) const { // Get the normalised interpolated value. Double_t value = this->interpolateXY(x,y); return value/norm_; } Double_t Lau2DSplineDPPdf::interpolateXY(Double_t x, Double_t y) const { // This function returns the interpolated value of the histogram function // for the given values of x and y by finding the adjacent bins and extrapolating // using weights based on the inverse distance of the point from the adajcent // bin centres. // Here, x = m13^2, y = m23^2, or m', theta' for square DP co-ordinates // If we're only using one half then flip co-ordinates // appropriately for conventional or square DP getUpperHalf(x,y); // First ask whether the point is inside the kinematic region. if (withinDPBoundaries(x,y) == kFALSE) { std::cerr << "WARNING in Lau2DSplineDPPdf::interpolateXY : Given position is outside the DP boundary, returning 0.0." << std::endl; return 0.0; } return spline_->evaluate(x,y); } void Lau2DSplineDPPdf::calcHistNorm() { norm_ = spline_->analyticalIntegral(); } diff --git a/src/LauAbsBkgndDPModel.cc b/src/LauAbsBkgndDPModel.cc index 9ed44f7..86f56d1 100644 --- a/src/LauAbsBkgndDPModel.cc +++ b/src/LauAbsBkgndDPModel.cc @@ -1,41 +1,40 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauAbsBkgndDPModel.cc \brief File containing implementation of LauAbsBkgndDPModel class. */ #include "LauAbsBkgndDPModel.hh" #include "LauDaughters.hh" -ClassImp(LauAbsBkgndDPModel) LauAbsBkgndDPModel::LauAbsBkgndDPModel(LauDaughters* daughters, LauVetoes* vetoes) : daughters_(daughters), kinematics_(daughters ? daughters->getKinematics() : 0), vetoes_(vetoes) { } diff --git a/src/LauAbsCoeffSet.cc b/src/LauAbsCoeffSet.cc index 66110b3..3a86174 100644 --- a/src/LauAbsCoeffSet.cc +++ b/src/LauAbsCoeffSet.cc @@ -1,211 +1,210 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauAbsCoeffSet.cc \brief File containing implementation of LauAbsCoeffSet class. */ #include #include "TString.h" #include "LauAbsCoeffSet.hh" #include "LauConstants.hh" #include "LauParameter.hh" #include "LauRandom.hh" -ClassImp(LauAbsCoeffSet); TRandom* LauAbsCoeffSet::randomiser_ = 0; Double_t LauAbsCoeffSet::minMagnitude_ = -10.0; Double_t LauAbsCoeffSet::maxMagnitude_ = 10.0; Double_t LauAbsCoeffSet::minPhase_ = -LauConstants::threePi; Double_t LauAbsCoeffSet::maxPhase_ = LauConstants::threePi; Double_t LauAbsCoeffSet::minRealImagPart_ = -10.0; Double_t LauAbsCoeffSet::maxRealImagPart_ = 10.0; Double_t LauAbsCoeffSet::minDelta_ = -2.0; Double_t LauAbsCoeffSet::maxDelta_ = 2.0; LauAbsCoeffSet::LauAbsCoeffSet(const TString& theName, const TString& theBaseName) : name_(theName), basename_(theBaseName), index_(0) { } LauAbsCoeffSet::LauAbsCoeffSet(const LauAbsCoeffSet& rhs) : name_(rhs.name_), basename_(rhs.basename_), index_(rhs.index_) { } LauAbsCoeffSet& LauAbsCoeffSet::operator=(const LauAbsCoeffSet& rhs) { if ( &rhs != this ) { name_ = rhs.name_; basename_ = rhs.basename_; index_ = rhs.index_; } return *this; } TRandom* LauAbsCoeffSet::getRandomiser() { if ( randomiser_ == 0 ) { randomiser_ = LauRandom::zeroSeedRandom(); } return randomiser_; } void LauAbsCoeffSet::index(UInt_t newIndex) { index_ = newIndex; const TString oldBaseName( this->baseName() ); TString basename( oldBaseName ); if ( basename.Length() != 1 ) { basename.Remove(1); } basename += newIndex; basename += "_"; this->baseName(basename); std::vector pars = this->getParameters(); for ( std::vector::iterator iter = pars.begin(); iter != pars.end(); ++iter ) { this->adjustName( *iter, oldBaseName ); } } void LauAbsCoeffSet::adjustName(LauParameter* par, const TString& oldBaseName) { TString theName(par->name()); if ( theName.BeginsWith( oldBaseName ) && theName != oldBaseName ) { theName.Remove(0,oldBaseName.Length()); } theName.Prepend(this->baseName()); par->name(theName); } void LauAbsCoeffSet::setParameterValue(const TString& parName, Double_t value, Bool_t init) { LauParameter* par = this->findParameter( parName ); if ( par == 0 ) { std::cerr << "ERROR in LauAbsCoeffSet::setParameterValue : Unable to find parameter \"" << parName << "\"" << std::endl; return; } par->value( value ); if ( init ) { par->genValue( value ); par->initValue( value ); } } void LauAbsCoeffSet::setParameterError(const TString& parName, Double_t error) { LauParameter* par = this->findParameter( parName ); if ( par == 0 ) { std::cerr << "ERROR in LauAbsCoeffSet::setParameterError : Unable to find parameter \"" << parName << "\"" << std::endl; return; } par->error( error ); } void LauAbsCoeffSet::fixParameter(const TString& parName) { LauParameter* par = this->findParameter( parName ); if ( par == 0 ) { std::cerr << "ERROR in LauAbsCoeffSet::fixParameter : Unable to find parameter \"" << parName << "\"" << std::endl; return; } par->fixed( kTRUE ); } void LauAbsCoeffSet::floatParameter(const TString& parName) { LauParameter* par = this->findParameter( parName ); if ( par == 0 ) { std::cerr << "ERROR in LauAbsCoeffSet::floatParameter : Unable to find parameter \"" << parName << "\"" << std::endl; return; } par->fixed( kFALSE ); } void LauAbsCoeffSet::blindParameter(const TString& parName, const TString& blindingString, const Double_t width) { LauParameter* par = this->findParameter( parName ); if ( par == 0 ) { std::cerr << "ERROR in LauAbsCoeffSet::blindParameter : Unable to find parameter \"" << parName << "\"" << std::endl; return; } par->blindParameter( blindingString, width ); } void LauAbsCoeffSet::addGaussianConstraint(const TString& parName, const Double_t mean, const Double_t width) { LauParameter* par = this->findParameter( parName ); if ( par == 0 ) { std::cerr << "ERROR in LauAbsCoeffSet::addGaussianConstraint : Unable to find parameter \"" << parName << "\"" << std::endl; return; } par->addGaussianConstraint( mean, width ); } void LauAbsCoeffSet::addSuffixToParameterName(const TString& parName, const TString& suffix) { LauParameter* par = this->findParameter( parName ); if ( par == 0 ) { std::cerr << "ERROR in LauAbsCoeffSet::addSuffixToParameterName : Unable to find parameter \"" << parName << "\"" << std::endl; return; } TString newName( par->name() ); if ( ! suffix.BeginsWith('_') ) { newName += "_"; } newName += suffix; par->name( newName ); } LauParameter* LauAbsCoeffSet::findParameter(const TString& parName) { std::vector pars = this->getParameters(); for ( std::vector::iterator iter = pars.begin(); iter != pars.end(); ++iter ) { const TString& iName = (*iter)->name(); if ( iName.EndsWith( parName ) ) { return (*iter); } } return 0; } diff --git a/src/LauAbsFitModel.cc b/src/LauAbsFitModel.cc index 6bd4899..fe86a5a 100644 --- a/src/LauAbsFitModel.cc +++ b/src/LauAbsFitModel.cc @@ -1,1090 +1,1089 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauAbsFitModel.cc \brief File containing implementation of LauAbsFitModel class. */ #include #include #include #include "TMessage.h" #include "TMonitor.h" #include "TServerSocket.h" #include "TSocket.h" #include "TSystem.h" #include "TVirtualFitter.h" #include "LauAbsFitModel.hh" #include "LauAbsFitter.hh" #include "LauAbsPdf.hh" #include "LauComplex.hh" #include "LauFitter.hh" #include "LauFitDataTree.hh" #include "LauGenNtuple.hh" #include "LauParameter.hh" #include "LauParamFixed.hh" #include "LauPrint.hh" #include "LauSPlot.hh" -ClassImp(LauAbsFitModel) LauAbsFitModel::LauAbsFitModel() : fixParams_(kFALSE), compareFitData_(kFALSE), savePDF_(kFALSE), writeLatexTable_(kFALSE), writeSPlotData_(kFALSE), storeDPEff_(kFALSE), randomFit_(kFALSE), emlFit_(kFALSE), poissonSmear_(kFALSE), enableEmbedding_(kFALSE), usingDP_(kTRUE), pdfsDependOnDP_(kFALSE), inputFitData_(0), genNtuple_(0), sPlotNtuple_(0), nullString_(""), doSFit_(kFALSE), sWeightBranchName_(""), sWeightScaleFactor_(1.0), outputTableName_(""), fitToyMCFileName_("fitToyMC.root"), fitToyMCTableName_("fitToyMCTable"), fitToyMCScale_(10), fitToyMCPoissonSmear_(kFALSE), sPlotFileName_(""), sPlotTreeName_(""), sPlotVerbosity_("") { } LauAbsFitModel::~LauAbsFitModel() { delete inputFitData_; inputFitData_ = 0; delete genNtuple_; genNtuple_ = 0; delete sPlotNtuple_; sPlotNtuple_ = 0; // Remove the components created to apply constraints to fit parameters for (std::vector::iterator iter = conVars_.begin(); iter != conVars_.end(); ++iter){ if ( !(*iter)->isLValue() ){ delete (*iter); (*iter) = 0; } } } void LauAbsFitModel::run(const TString& applicationCode, const TString& dataFileName, const TString& dataTreeName, const TString& histFileName, const TString& tableFileName) { // Chose whether you want to generate or fit events in the Dalitz plot. // To generate events choose applicationCode = "gen", to fit events choose // applicationCode = "fit". TString runCode(applicationCode); runCode.ToLower(); TString histFileNameCopy(histFileName); TString tableFileNameCopy(tableFileName); TString dataFileNameCopy(dataFileName); TString dataTreeNameCopy(dataTreeName); // Initialise the fit par vectors. Each class that inherits from this one // must implement this sensibly for all vectors specified in clearFitParVectors, // i.e. specify parameter names, initial, min, max and fixed values this->initialise(); // Add variables to Gaussian constrain to a list this->addConParameters(); if (dataFileNameCopy == "") {dataFileNameCopy = "data.root";} if (dataTreeNameCopy == "") {dataTreeNameCopy = "genResults";} if (runCode.Contains("gen")) { if (histFileNameCopy == "") {histFileNameCopy = "parInfo.root";} if (tableFileNameCopy == "") {tableFileNameCopy = "genResults";} this->setGenValues(); this->generate(dataFileNameCopy, dataTreeNameCopy, histFileNameCopy, tableFileNameCopy); } else if (runCode.Contains("fit")) { if (histFileNameCopy == "") {histFileNameCopy = "parInfo.root";} if (tableFileNameCopy == "") {tableFileNameCopy = "fitResults";} this->fit(dataFileNameCopy, dataTreeNameCopy, histFileNameCopy, tableFileNameCopy); } else if (runCode.Contains("plot")) { this->savePDFPlots("plot"); } else if (runCode.Contains("weight")) { this->weightEvents(dataFileNameCopy, dataTreeNameCopy); } } void LauAbsFitModel::doSFit( const TString& sWeightBranchName, Double_t scaleFactor ) { if ( sWeightBranchName == "" ) { std::cerr << "WARNING in LauAbsFitModel::doSFit : sWeight branch name is empty string, not setting-up sFit." << std::endl; return; } doSFit_ = kTRUE; sWeightBranchName_ = sWeightBranchName; sWeightScaleFactor_ = scaleFactor; } void LauAbsFitModel::setBkgndClassNames( const std::vector& names ) { if ( !bkgndClassNames_.empty() ) { std::cerr << "WARNING in LauAbsFitModel::setBkgndClassNames : Names already stored, not changing them." << std::endl; return; } UInt_t nBkgnds = names.size(); for ( UInt_t i(0); i < nBkgnds; ++i ) { bkgndClassNames_.insert( std::make_pair( i, names[i] ) ); } this->setupBkgndVectors(); } Bool_t LauAbsFitModel::validBkgndClass( const TString& className ) const { if ( bkgndClassNames_.empty() ) { return kFALSE; } Bool_t found(kFALSE); for ( LauBkgndClassMap::const_iterator iter = bkgndClassNames_.begin(); iter != bkgndClassNames_.end(); ++iter ) { if ( iter->second == className ) { found = kTRUE; break; } } return found; } UInt_t LauAbsFitModel::bkgndClassID( const TString& className ) const { if ( ! this->validBkgndClass( className ) ) { std::cerr << "ERROR in LauAbsFitModel::bkgndClassID : Request for ID for invalid background class \"" << className << "\"." << std::endl; return (bkgndClassNames_.size() + 1); } UInt_t bgID(0); for ( LauBkgndClassMap::const_iterator iter = bkgndClassNames_.begin(); iter != bkgndClassNames_.end(); ++iter ) { if ( iter->second == className ) { bgID = iter->first; break; } } return bgID; } const TString& LauAbsFitModel::bkgndClassName( UInt_t classID ) const { LauBkgndClassMap::const_iterator iter = bkgndClassNames_.find( classID ); if ( iter == bkgndClassNames_.end() ) { std::cerr << "ERROR in LauAbsFitModel::bkgndClassName : Request for name of invalid background class ID " << classID << "." << std::endl; return nullString_; } return iter->second; } void LauAbsFitModel::clearFitParVectors() { std::cout << "INFO in LauAbsFitModel::clearFitParVectors : Clearing fit variable vectors" << std::endl; // Remove the components created to apply constraints to fit parameters for (std::vector::iterator iter = conVars_.begin(); iter != conVars_.end(); ++iter){ if ( !(*iter)->isLValue() ){ delete (*iter); (*iter) = 0; } } conVars_.clear(); fitVars_.clear(); } void LauAbsFitModel::clearExtraVarVectors() { std::cout << "INFO in LauAbsFitModel::clearExtraVarVectors : Clearing extra ntuple variable vectors" << std::endl; extraVars_.clear(); } void LauAbsFitModel::setGenValues() { // makes sure each parameter holds its genValue as its current value for (LauParameterPList::iterator iter = fitVars_.begin(); iter != fitVars_.end(); ++iter) { (*iter)->value((*iter)->genValue()); } this->propagateParUpdates(); } void LauAbsFitModel::writeSPlotData(const TString& fileName, const TString& treeName, Bool_t storeDPEfficiency, const TString& verbosity) { if (this->writeSPlotData()) { std::cerr << "ERROR in LauAbsFitModel::writeSPlotData : Already have an sPlot ntuple setup, not doing it again." << std::endl; return; } writeSPlotData_ = kTRUE; sPlotFileName_ = fileName; sPlotTreeName_ = treeName; sPlotVerbosity_ = verbosity; storeDPEff_ = storeDPEfficiency; } // TODO : histFileName isn't used here at the moment but could be used for // storing the values of the parameters used in the generation. // These could then be read and used for setting the "true" values // in a subsequent fit. void LauAbsFitModel::generate(const TString& dataFileName, const TString& dataTreeName, const TString& /*histFileName*/, const TString& tableFileNameBase) { // Create the ntuple for storing the results std::cout << "INFO in LauAbsFitModel::generate : Creating generation ntuple." << std::endl; if (genNtuple_ != 0) {delete genNtuple_; genNtuple_ = 0;} genNtuple_ = new LauGenNtuple(dataFileName,dataTreeName); // add branches for storing the experiment number and the number of // the event within the current experiment this->addGenNtupleIntegerBranch("iExpt"); this->addGenNtupleIntegerBranch("iEvtWithinExpt"); this->setupGenNtupleBranches(); // Start the cumulative timer cumulTimer_.Start(); const UInt_t firstExp = this->firstExpt(); const UInt_t nExp = this->nExpt(); Bool_t genOK(kTRUE); do { // Loop over the number of experiments for (UInt_t iExp = firstExp; iExp < (firstExp+nExp); ++iExp) { // Start the timer to see how long each experiment takes to generate timer_.Start(); // Store the experiment number in the ntuple this->setGenNtupleIntegerBranchValue("iExpt",iExp); // Do the generation for this experiment std::cout << "INFO in LauAbsFitModel::generate : Generating experiment number " << iExp << std::endl; genOK = this->genExpt(); // Stop the timer and see how long the program took so far timer_.Stop(); timer_.Print(); if (!genOK) { // delete and recreate an empty tree genNtuple_->deleteAndRecreateTree(); // then break out of the experiment loop std::cerr << "WARNING in LauAbsFitModel::generate : Problem in toy MC generation. Starting again with updated parameters..." << std::endl; break; } if (this->writeLatexTable()) { TString tableFileName(tableFileNameBase); tableFileName += "_"; tableFileName += iExp; tableFileName += ".tex"; this->writeOutTable(tableFileName); } } // Loop over number of experiments } while (!genOK); // Print out total timing info. cumulTimer_.Stop(); std::cout << "INFO in LauAbsFitModel::generate : Finished generating all experiments." << std::endl; std::cout << "INFO in LauAbsFitModel::generate : Cumulative timing:" << std::endl; cumulTimer_.Print(); // Build the event index std::cout << "INFO in LauAbsFitModel::generate : Building experiment:event index." << std::endl; // TODO - can test this return value? //Int_t nIndexEntries = genNtuple_->buildIndex("iExpt","iEvtWithinExpt"); // Write out toy MC ntuple std::cout << "INFO in LauAbsFitModel::generate : Writing data to file " << dataFileName << "." << std::endl; genNtuple_->writeOutGenResults(); } void LauAbsFitModel::addGenNtupleIntegerBranch(const TString& name) { genNtuple_->addIntegerBranch(name); } void LauAbsFitModel::addGenNtupleDoubleBranch(const TString& name) { genNtuple_->addDoubleBranch(name); } void LauAbsFitModel::setGenNtupleIntegerBranchValue(const TString& name, Int_t value) { genNtuple_->setIntegerBranchValue(name,value); } void LauAbsFitModel::setGenNtupleDoubleBranchValue(const TString& name, Double_t value) { genNtuple_->setDoubleBranchValue(name,value); } Int_t LauAbsFitModel::getGenNtupleIntegerBranchValue(const TString& name) const { return genNtuple_->getIntegerBranchValue(name); } Double_t LauAbsFitModel::getGenNtupleDoubleBranchValue(const TString& name) const { return genNtuple_->getDoubleBranchValue(name); } void LauAbsFitModel::fillGenNtupleBranches() { genNtuple_->fillBranches(); } void LauAbsFitModel::addSPlotNtupleIntegerBranch(const TString& name) { sPlotNtuple_->addIntegerBranch(name); } void LauAbsFitModel::addSPlotNtupleDoubleBranch(const TString& name) { sPlotNtuple_->addDoubleBranch(name); } void LauAbsFitModel::setSPlotNtupleIntegerBranchValue(const TString& name, Int_t value) { sPlotNtuple_->setIntegerBranchValue(name,value); } void LauAbsFitModel::setSPlotNtupleDoubleBranchValue(const TString& name, Double_t value) { sPlotNtuple_->setDoubleBranchValue(name,value); } void LauAbsFitModel::fillSPlotNtupleBranches() { sPlotNtuple_->fillBranches(); } void LauAbsFitModel::fit(const TString& dataFileName, const TString& dataTreeName, const TString& histFileName, const TString& tableFileNameBase) { // Routine to perform the total fit. const UInt_t firstExp = this->firstExpt(); const UInt_t nExp = this->nExpt(); std::cout << "INFO in LauAbsFitModel::fit : First experiment = " << firstExp << std::endl; std::cout << "INFO in LauAbsFitModel::fit : Number of experiments = " << nExp << std::endl; // Start the cumulative timer cumulTimer_.Start(); this->resetFitCounters(); // Create and setup the fit results ntuple this->setupResultsOutputs( histFileName, tableFileNameBase ); // Create and setup the sPlot ntuple if (this->writeSPlotData()) { std::cout << "INFO in LauAbsFitModel::fit : Creating sPlot ntuple." << std::endl; if (sPlotNtuple_ != 0) {delete sPlotNtuple_; sPlotNtuple_ = 0;} sPlotNtuple_ = new LauGenNtuple(sPlotFileName_,sPlotTreeName_); this->setupSPlotNtupleBranches(); } // This reads in the given dataFile and creates an input // fit data tree that stores them for all events and experiments. Bool_t dataOK = this->verifyFitData(dataFileName,dataTreeName); if (!dataOK) { std::cerr << "ERROR in LauAbsFitModel::fit : Problem caching the fit data." << std::endl; gSystem->Exit(EXIT_FAILURE); } // Loop over the number of experiments for (UInt_t iExp = firstExp; iExp < (firstExp+nExp); ++iExp) { // Start the timer to see how long each fit takes timer_.Start(); this->setCurrentExperiment( iExp ); UInt_t nEvents = this->readExperimentData(); if (nEvents < 1) { std::cerr << "WARNING in LauAbsFitModel::fit : Zero events in experiment " << iExp << ", skipping..." << std::endl; timer_.Stop(); continue; } // Now the sub-classes must implement whatever they need to do // to cache any more input fit data they need in order to // calculate the likelihoods during the fit. // They need to use the inputFitData_ tree as input. For example, // inputFitData_ contains m13Sq and m23Sq. The appropriate fit model // then caches the resonance dynamics for the signal model, as // well as the background likelihood values in the Dalitz plot this->cacheInputFitVars(); if ( this->doSFit() ) { this->cacheInputSWeights(); } // Do the fit for this experiment this->fitExpt(); // Write the results into the ntuple this->finaliseFitResults( outputTableName_ ); // Stop the timer and see how long the program took so far timer_.Stop(); timer_.Print(); // Store the per-event likelihood values if ( this->writeSPlotData() ) { this->storePerEvtLlhds(); } // Create a toy MC sample using the fitted parameters so that // the user can compare the fit to the data. if (compareFitData_ == kTRUE && this->statusCode() == 3) { this->createFitToyMC(fitToyMCFileName_, fitToyMCTableName_); } } // Loop over number of experiments // Print out total timing info. cumulTimer_.Stop(); std::cout << "INFO in LauAbsFitModel::fit : Cumulative timing:" << std::endl; cumulTimer_.Print(); // Print out stats on OK fits. const UInt_t nOKFits = this->numberOKFits(); const UInt_t nBadFits = this->numberBadFits(); std::cout << "INFO in LauAbsFitModel::fit : Number of OK Fits = " << nOKFits << std::endl; std::cout << "INFO in LauAbsFitModel::fit : Number of Failed Fits = " << nBadFits << std::endl; Double_t fitEff(0.0); if (nExp != 0) {fitEff = nOKFits/(1.0*nExp);} std::cout << "INFO in LauAbsFitModel::fit : Fit efficiency = " << fitEff*100.0 << "%." << std::endl; // Write out any fit results (ntuples etc...). this->writeOutAllFitResults(); if ( this->writeSPlotData() ) { this->calculateSPlotData(); } } void LauAbsFitModel::setupResultsOutputs( const TString& histFileName, const TString& tableFileName ) { this->LauSimFitSlave::setupResultsOutputs( histFileName, tableFileName ); outputTableName_ = tableFileName; } Bool_t LauAbsFitModel::verifyFitData(const TString& dataFileName, const TString& dataTreeName) { // From the input data stream, store the variables into the // internal tree inputFitData_ that can be used by the sub-classes // in calculating their likelihood functions for the fit delete inputFitData_; inputFitData_ = new LauFitDataTree(dataFileName,dataTreeName); Bool_t dataOK = inputFitData_->findBranches(); if (!dataOK) { delete inputFitData_; inputFitData_ = 0; } return dataOK; } void LauAbsFitModel::cacheInputSWeights() { Bool_t hasBranch = inputFitData_->haveBranch( sWeightBranchName_ ); if ( ! hasBranch ) { std::cerr << "ERROR in LauAbsFitModel::cacheInputSWeights : Input data does not contain variable \"" << sWeightBranchName_ << "\".\n"; std::cerr << " : Turning off sFit!" << std::endl; doSFit_ = kFALSE; return; } UInt_t nEvents = this->eventsPerExpt(); sWeights_.clear(); sWeights_.reserve( nEvents ); for (UInt_t iEvt = 0; iEvt < nEvents; ++iEvt) { const LauFitData& dataValues = inputFitData_->getData(iEvt); LauFitData::const_iterator iter = dataValues.find( sWeightBranchName_ ); sWeights_.push_back( iter->second * sWeightScaleFactor_ ); } } void LauAbsFitModel::fitExpt() { // Routine to perform the actual fit for the given experiment // Update initial fit parameters if required (e.g. if using random numbers). this->checkInitFitParams(); // Initialise the fitter LauFitter::fitter()->useAsymmFitErrors( this->useAsymmFitErrors() ); LauFitter::fitter()->twoStageFit( this->twoStageFit() ); LauFitter::fitter()->initialise( this, fitVars_ ); this->startNewFit( LauFitter::fitter()->nParameters(), LauFitter::fitter()->nFreeParameters() ); // Now ready for minimisation step std::cout << "\nINFO in LauAbsFitModel::fitExpt : Start minimisation...\n"; LauAbsFitter::FitStatus fitResult = LauFitter::fitter()->minimise(); // If we're doing a two stage fit we can now release (i.e. float) // the 2nd stage parameters and re-fit if (this->twoStageFit()) { if ( fitResult.status != 3 ) { std::cerr << "WARNING in LauAbsFitModel:fitExpt : Not running second stage fit since first stage failed." << std::endl; LauFitter::fitter()->releaseSecondStageParameters(); } else { LauFitter::fitter()->releaseSecondStageParameters(); this->startNewFit( LauFitter::fitter()->nParameters(), LauFitter::fitter()->nFreeParameters() ); fitResult = LauFitter::fitter()->minimise(); } } const TMatrixD& covMat = LauFitter::fitter()->covarianceMatrix(); this->storeFitStatus( fitResult, covMat ); // Store the final fit results and errors into protected internal vectors that // all sub-classes can use within their own finalFitResults implementation // used below (e.g. putting them into an ntuple in a root file) LauFitter::fitter()->updateParameters(); } void LauAbsFitModel::calculateSPlotData() { if (sPlotNtuple_ != 0) { sPlotNtuple_->addFriendTree(inputFitData_->fileName(), inputFitData_->treeName()); sPlotNtuple_->writeOutGenResults(); LauSPlot splot(sPlotNtuple_->fileName(), sPlotNtuple_->treeName(), this->firstExpt(), this->nExpt(), this->variableNames(), this->freeSpeciesNames(), this->fixdSpeciesNames(), this->twodimPDFs(), this->splitSignal(), this->scfDPSmear()); splot.runCalculations(sPlotVerbosity_); splot.writeOutResults(); } } void LauAbsFitModel::compareFitData(UInt_t toyMCScale, const TString& mcFileName, const TString& tableFileName, Bool_t poissonSmearing) { compareFitData_ = kTRUE; fitToyMCScale_ = toyMCScale; fitToyMCFileName_ = mcFileName; fitToyMCTableName_ = tableFileName; fitToyMCPoissonSmear_ = poissonSmearing; } void LauAbsFitModel::createFitToyMC(const TString& mcFileName, const TString& tableFileName) { // Create a toy MC sample so that the user can compare the fitted // result with the data. // Generate more toy MC to reduce statistical fluctuations: // - use the rescaling value fitToyMCScale_ // Store the info on the number of experiments, first expt and current expt const UInt_t oldNExpt(this->nExpt()); const UInt_t oldFirstExpt(this->firstExpt()); const UInt_t oldIExpt(this->iExpt()); // Turn off Poisson smearing if required const Bool_t poissonSmearing(this->doPoissonSmearing()); this->doPoissonSmearing(fitToyMCPoissonSmear_); // Turn off embedding, since we need toy MC, not reco'ed events const Bool_t enableEmbeddingOrig(this->enableEmbedding()); this->enableEmbedding(kFALSE); // Need to make sure that the generation of the DP co-ordinates is // switched on if any of our PDFs depend on it const Bool_t origUseDP = this->useDP(); if ( !origUseDP && this->pdfsDependOnDP() ) { this->useDP( kTRUE ); this->initialiseDPModels(); } // Construct a unique filename for this experiment TString exptString("_expt"); exptString += oldIExpt; TString fileName( mcFileName ); fileName.Insert( fileName.Last('.'), exptString ); // Generate the toy MC std::cout << "INFO in LauAbsFitModel::createFitToyMC : Generating toy MC in " << fileName << " to compare fit with data..." << std::endl; std::cout << " : Number of experiments to generate = " << fitToyMCScale_ << "." << std::endl; std::cout << " : This is to allow the toy MC to be made with reduced statistical fluctuations." << std::endl; // Set the genValue of each parameter to its current (fitted) value // but first store the original genValues for restoring later std::vector origGenValues; origGenValues.reserve(this->nTotParams()); Bool_t blind(kFALSE); for (LauParameterPList::iterator iter = fitVars_.begin(); iter != fitVars_.end(); ++iter) { origGenValues.push_back((*iter)->genValue()); (*iter)->genValue((*iter)->unblindValue()); if ( (*iter)->blind() ) { blind = kTRUE; } } if ( blind ) { std::cerr << "WARNING in LauAbsFitModel::createFitToyMC : One or more parameters are blind but the toy will be created using the unblind values - use with caution!!" << std::endl; } // If we're asked to generate more than 100 experiments then split it // up into multiple files since otherwise can run into memory issues // when building the index // TODO - this obviously depends on the number of events per experiment as well, so should do this properly UInt_t totalExpts = fitToyMCScale_; if ( totalExpts > 100 ) { UInt_t nFiles = totalExpts/100; if ( totalExpts%100 ) { nFiles += 1; } TString fileNameBase {fileName}; for ( UInt_t iFile(0); iFile < nFiles; ++iFile ) { UInt_t firstExp( iFile*100 ); // Set number of experiments and first experiment to generate UInt_t nExp = ((firstExp + 100)>totalExpts) ? totalExpts-firstExp : 100; this->setNExpts(nExp, firstExp); // Create a unique filename and generate the events fileName = fileNameBase; TString extraname = "_file"; extraname += iFile; fileName.Insert( fileName.Last('.'), extraname ); this->generate(fileName, "genResults", "dummy.root", tableFileName); } } else { // Set number of experiments to new value this->setNExpts(fitToyMCScale_, 0); // Generate the toy this->generate(fileName, "genResults", "dummy.root", tableFileName); } // Reset number of experiments to original value this->setNExpts(oldNExpt, oldFirstExpt); this->setCurrentExperiment(oldIExpt); // Restore the Poisson smearing to its former value this->doPoissonSmearing(poissonSmearing); // Restore the embedding status this->enableEmbedding(enableEmbeddingOrig); // Restore "useDP" to its former status this->useDP( origUseDP ); // Restore the original genValue to each parameter for (UInt_t i(0); inTotParams(); ++i) { fitVars_[i]->genValue(origGenValues[i]); } std::cout << "INFO in LauAbsFitModel::createFitToyMC : Finished in createFitToyMC." << std::endl; } Double_t LauAbsFitModel::getTotNegLogLikelihood() { // Calculate the total negative log-likelihood over all events. // This function assumes that the fit parameters and data tree have // already been set-up correctly. // Loop over the data points to calculate the log likelihood Double_t logLike = this->getLogLikelihood( 0, this->eventsPerExpt() ); // Include the Poisson term in the extended likelihood if required if (this->doEMLFit()) { logLike -= this->getEventSum(); } // Calculate any penalty terms from Gaussian constrained variables if ( ! conVars_.empty() ){ logLike -= this->getLogLikelihoodPenalty(); } Double_t totNegLogLike = -logLike; return totNegLogLike; } Double_t LauAbsFitModel::getLogLikelihoodPenalty() { Double_t penalty(0.0); for ( LauAbsRValuePList::const_iterator iter = conVars_.begin(); iter != conVars_.end(); ++iter ) { Double_t val = (*iter)->unblindValue(); Double_t mean = (*iter)->constraintMean(); Double_t width = (*iter)->constraintWidth(); Double_t term = ( val - mean )*( val - mean ); penalty += term/( 2*width*width ); } return penalty; } Double_t LauAbsFitModel::getLogLikelihood( UInt_t iStart, UInt_t iEnd ) { // Calculate the total negative log-likelihood over all events. // This function assumes that the fit parameters and data tree have // already been set-up correctly. // Loop over the data points to calculate the log likelihood Double_t logLike(0.0); const Double_t worstLL = this->worstLogLike(); // Loop over the number of events in this experiment Bool_t ok(kTRUE); for (UInt_t iEvt = iStart; iEvt < iEnd; ++iEvt) { Double_t likelihood = this->getTotEvtLikelihood(iEvt); if (likelihood > std::numeric_limits::min()) { // Is the likelihood zero? Double_t evtLogLike = TMath::Log(likelihood); if ( doSFit_ ) { evtLogLike *= sWeights_[iEvt]; } logLike += evtLogLike; } else { ok = kFALSE; std::cerr << "WARNING in LauAbsFitModel::getLogLikelihood : Strange likelihood value for event " << iEvt << ": " << likelihood << "\n"; this->printEventInfo(iEvt); this->printVarsInfo(); //Write the values of the floated variables for which the likelihood is zero break; } } if (!ok) { std::cerr << " : Returning worst NLL found so far to force MINUIT out of this region." << std::endl; logLike = worstLL; } else if (logLike < worstLL) { this->worstLogLike( logLike ); } return logLike; } void LauAbsFitModel::setParsFromMinuit(Double_t* par, Int_t npar) { // This function sets the internal parameters based on the values // that Minuit is using when trying to minimise the total likelihood function. // MINOS reports different numbers of free parameters depending on the // situation, so disable this check if ( ! this->withinAsymErrorCalc() ) { const UInt_t nFreePars = this->nFreeParams(); if (static_cast(npar) != nFreePars) { std::cerr << "ERROR in LauAbsFitModel::setParsFromMinuit : Unexpected number of free parameters: " << npar << ".\n"; std::cerr << " Expected: " << nFreePars << ".\n" << std::endl; gSystem->Exit(EXIT_FAILURE); } } // Despite npar being the number of free parameters // the par array actually contains all the parameters, // free and floating... // Update all the floating ones with their new values // Also check if we have any parameters on which the DP integrals depend // and whether they have changed since the last iteration Bool_t recalcNorm(kFALSE); const LauParameterPSet::const_iterator resVarsEnd = resVars_.end(); for (UInt_t i(0); inTotParams(); ++i) { if (!fitVars_[i]->fixed()) { if ( resVars_.find( fitVars_[i] ) != resVarsEnd ) { if ( fitVars_[i]->value() != par[i] ) { recalcNorm = kTRUE; } } fitVars_[i]->value(par[i]); } } // If so, then recalculate the normalisation if (recalcNorm) { this->recalculateNormalisation(); } this->propagateParUpdates(); } UInt_t LauAbsFitModel::addFitParameters(LauPdfList& pdfList) { UInt_t nParsAdded(0); for (LauPdfList::iterator pdf_iter = pdfList.begin(); pdf_iter != pdfList.end(); ++pdf_iter) { LauAbsPdf* pdf = (*pdf_iter); if ( pdf->isDPDependent() ) { this->pdfsDependOnDP( kTRUE ); } LauAbsRValuePList& pars = pdf->getParameters(); for (LauAbsRValuePList::iterator pars_iter = pars.begin(); pars_iter != pars.end(); ++pars_iter) { LauParameterPList params = (*pars_iter)->getPars(); for (LauParameterPList::iterator params_iter = params.begin(); params_iter != params.end(); ++params_iter) { if ( !(*params_iter)->clone() && ( !(*params_iter)->fixed() || ( this->twoStageFit() && (*params_iter)->secondStage() ) ) ) { fitVars_.push_back(*params_iter); ++nParsAdded; } } } } return nParsAdded; } void LauAbsFitModel::addConParameters() { for ( LauParameterPList::const_iterator iter = fitVars_.begin(); iter != fitVars_.end(); ++iter ) { if ( (*iter)->gaussConstraint() ) { conVars_.push_back( *iter ); std::cout << "INFO in LauAbsFitModel::addConParameters : Added Gaussian constraint to parameter "<< (*iter)->name() << std::endl; } } // Add penalties from the constraints to fit parameters const std::vector& storeCon = this->constraintsStore(); for ( std::vector::const_iterator iter = storeCon.begin(); iter != storeCon.end(); ++iter ) { const std::vector& names = (*iter).conPars_; std::vector params; for ( std::vector::const_iterator iternames = names.begin(); iternames != names.end(); ++iternames ) { for ( LauParameterPList::const_iterator iterfit = fitVars_.begin(); iterfit != fitVars_.end(); ++iterfit ) { if ( (*iternames) == (*iterfit)->name() ){ params.push_back(*iterfit); } } } // If the parameters are not found, skip it if ( params.size() != (*iter).conPars_.size() ) { std::cerr << "WARNING in LauAbsFitModel::addConParameters: Could not find parameters to constrain in the formula... skipping" << std::endl; continue; } LauFormulaPar* formPar = new LauFormulaPar( (*iter).formula_, (*iter).formula_, params ); formPar->addGaussianConstraint( (*iter).mean_, (*iter).width_ ); conVars_.push_back(formPar); std::cout << "INFO in LauAbsFitModel::addConParameters : Added Gaussian constraint to formula\n"; std::cout << " : Formula: " << (*iter).formula_ << std::endl; for ( std::vector::iterator iterparam = params.begin(); iterparam != params.end(); ++iterparam ) { std::cout << " : Parameter: " << (*iterparam)->name() << std::endl; } } } void LauAbsFitModel::updateFitParameters(LauPdfList& pdfList) { for (LauPdfList::iterator pdf_iter = pdfList.begin(); pdf_iter != pdfList.end(); ++pdf_iter) { (*pdf_iter)->updatePulls(); } } void LauAbsFitModel::printFitParameters(const LauPdfList& pdfList, std::ostream& fout) const { LauPrint print; for (LauPdfList::const_iterator pdf_iter = pdfList.begin(); pdf_iter != pdfList.end(); ++pdf_iter) { const LauAbsRValuePList& pars = (*pdf_iter)->getParameters(); for (LauAbsRValuePList::const_iterator pars_iter = pars.begin(); pars_iter != pars.end(); ++pars_iter) { LauParameterPList params = (*pars_iter)->getPars(); for (LauParameterPList::iterator params_iter = params.begin(); params_iter != params.end(); ++params_iter) { if (!(*params_iter)->clone()) { fout << (*params_iter)->name() << " & $"; print.printFormat(fout, (*params_iter)->value()); if ((*params_iter)->fixed() == kTRUE) { fout << "$ (fixed) \\\\"; } else { fout << " \\pm "; print.printFormat(fout, (*params_iter)->error()); fout << "$ \\\\" << std::endl; } } } } } } void LauAbsFitModel::cacheInfo(LauPdfList& pdfList, const LauFitDataTree& theData) { for (LauPdfList::iterator pdf_iter = pdfList.begin(); pdf_iter != pdfList.end(); ++pdf_iter) { (*pdf_iter)->cacheInfo(theData); } } Double_t LauAbsFitModel::prodPdfValue(LauPdfList& pdfList, UInt_t iEvt) { Double_t pdfVal = 1.0; for (LauPdfList::iterator pdf_iter = pdfList.begin(); pdf_iter != pdfList.end(); ++pdf_iter) { (*pdf_iter)->calcLikelihoodInfo(iEvt); pdfVal *= (*pdf_iter)->getLikelihood(); } return pdfVal; } void LauAbsFitModel::printEventInfo(UInt_t iEvt) const { const LauFitData& data = inputFitData_->getData(iEvt); std::cerr << " : Input data values for this event:" << std::endl; for (LauFitData::const_iterator iter = data.begin(); iter != data.end(); ++iter) { std::cerr << " " << iter->first << " = " << iter->second << std::endl; } } void LauAbsFitModel::printVarsInfo() const { std::cerr << " : Current values of fit parameters:" << std::endl; for (UInt_t i(0); inTotParams(); ++i) { std::cerr << " " << (fitVars_[i]->name()).Data() << " = " << fitVars_[i]->value() << std::endl; } } void LauAbsFitModel::prepareInitialParArray( TObjArray& array ) { // Update initial fit parameters if required (e.g. if using random numbers). this->checkInitFitParams(); // Store the total number of parameters and the number of free parameters UInt_t nPars = fitVars_.size(); UInt_t nFreePars = 0; // Send the fit parameters for ( LauParameterPList::iterator iter = fitVars_.begin(); iter != fitVars_.end(); ++iter ) { if ( ! (*iter)->fixed() ) { ++nFreePars; } array.Add( *iter ); } this->startNewFit( nPars, nFreePars ); } void LauAbsFitModel::finaliseExperiment( const LauAbsFitter::FitStatus& fitStat, const TObjArray* parsFromMaster, const TMatrixD* covMat, TObjArray& parsToMaster ) { // Copy the fit status information this->storeFitStatus( fitStat, *covMat ); // Now process the parameters const UInt_t nPars = this->nTotParams(); UInt_t nParsFromMaster = parsFromMaster->GetEntries(); if ( nParsFromMaster != nPars ) { std::cerr << "ERROR in LauAbsFitModel::finaliseExperiment : Unexpected number of parameters received from master" << std::endl; std::cerr << " : Received " << nParsFromMaster << " when expecting " << nPars << std::endl; gSystem->Exit( EXIT_FAILURE ); } for ( UInt_t iPar(0); iPar < nParsFromMaster; ++iPar ) { LauParameter* parameter = dynamic_cast( (*parsFromMaster)[iPar] ); if ( ! parameter ) { std::cerr << "ERROR in LauAbsFitModel::finaliseExperiment : Error reading parameter from master" << std::endl; gSystem->Exit( EXIT_FAILURE ); } if ( parameter->name() != fitVars_[iPar]->name() ) { std::cerr << "ERROR in LauAbsFitModel::finaliseExperiment : Error reading parameter from master" << std::endl; gSystem->Exit( EXIT_FAILURE ); } *(fitVars_[iPar]) = *parameter; } // Write the results into the ntuple this->finaliseFitResults( outputTableName_ ); // Store the per-event likelihood values if ( this->writeSPlotData() ) { this->storePerEvtLlhds(); } // Create a toy MC sample using the fitted parameters so that // the user can compare the fit to the data. if (compareFitData_ == kTRUE && fitStat.status == 3) { this->createFitToyMC(fitToyMCFileName_, fitToyMCTableName_); } // Send the finalised fit parameters for ( LauParameterPList::iterator iter = fitVars_.begin(); iter != fitVars_.end(); ++iter ) { parsToMaster.Add( *iter ); } } UInt_t LauAbsFitModel::readExperimentData() { // retrieve the data and find out how many events have been read const UInt_t exptIndex = this->iExpt(); inputFitData_->readExperimentData( exptIndex ); const UInt_t nEvent = inputFitData_->nEvents(); this->eventsPerExpt( nEvent ); return nEvent; } void LauAbsFitModel::setParametersFromFile(const TString& fileName, const TString& treeName, const Bool_t fix) { fixParamFileName_ = fileName; fixParamTreeName_ = treeName; fixParams_ = fix; } void LauAbsFitModel::setParametersFromMap(const std::map& parameters, const Bool_t fix) { fixParamMap_ = parameters; fixParams_ = fix; } void LauAbsFitModel::setNamedParameters(const TString& fileName, const TString& treeName, const std::set& parameters, const Bool_t fix) { fixParamFileName_ = fileName; fixParamTreeName_ = treeName; fixParamNames_ = parameters; fixParams_ = fix; } void LauAbsFitModel::setParametersFileFallback(const TString& fileName, const TString& treeName, const std::map& parameters, const Bool_t fix) { fixParamFileName_ = fileName; fixParamTreeName_ = treeName; fixParamMap_ = parameters; fixParams_ = fix; } diff --git a/src/LauAbsIncohRes.cc b/src/LauAbsIncohRes.cc index 7f9123f..f7e2559 100644 --- a/src/LauAbsIncohRes.cc +++ b/src/LauAbsIncohRes.cc @@ -1,49 +1,48 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauAbsIncohRes.cc \brief File containing implementation of LauAbsIncohRes class. */ #include "LauAbsIncohRes.hh" #include "LauDaughters.hh" #include "LauResonanceInfo.hh" -ClassImp(LauAbsIncohRes) // Constructor LauAbsIncohRes::LauAbsIncohRes(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters) {} // Destructor LauAbsIncohRes::~LauAbsIncohRes() { } LauComplex LauAbsIncohRes::resAmp(Double_t /*mass*/, Double_t spinTerm) { return LauComplex(spinTerm, 0.0); } diff --git a/src/LauAbsModIndPartWave.cc b/src/LauAbsModIndPartWave.cc index c81314c..3fa1732 100644 --- a/src/LauAbsModIndPartWave.cc +++ b/src/LauAbsModIndPartWave.cc @@ -1,249 +1,248 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauAbsModIndPartWave.cc \brief File containing implementation of LauAbsModIndPartWave class. */ #include #include #include "LauConstants.hh" #include "LauKinematics.hh" #include "LauAbsModIndPartWave.hh" #include "LauResonanceInfo.hh" -ClassImp(LauAbsModIndPartWave) LauAbsModIndPartWave::LauAbsModIndPartWave(LauResonanceInfo* resInfo, Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), nKnots_(0), spline1_(0), spline2_(0), type1_(Lau1DCubicSpline::StandardSpline), type2_(Lau1DCubicSpline::StandardSpline), leftBound1_(Lau1DCubicSpline::NotAKnot), rightBound1_(Lau1DCubicSpline::NotAKnot), leftBound2_(Lau1DCubicSpline::NotAKnot), rightBound2_(Lau1DCubicSpline::NotAKnot), leftGrad1_(0.), rightGrad1_(0.), leftGrad2_(0.), rightGrad2_(0.), secondStage_(kFALSE) { } LauAbsModIndPartWave::~LauAbsModIndPartWave() { delete spline1_; delete spline2_; } void LauAbsModIndPartWave::floatKnotsSecondStage(const Bool_t secondStage) { secondStage_ = secondStage; // if the parameters have not yet been created we can now just return if ( amp1Pars_.size() != nKnots_ ) { return; } // otherwise we need to toggle their second-stage parameter for ( UInt_t i(0); i < nKnots_; ++i ) { amp1Pars_[i]->secondStage(secondStage_); amp2Pars_[i]->secondStage(secondStage_); } } std::set LauAbsModIndPartWave::checkKnots(const std::set& masses) { std::set knots = masses; const std::set::const_iterator first = knots.begin(); const std::set::const_reverse_iterator last = knots.rbegin(); const Double_t lower_limit = this->getMassDaug1() + this->getMassDaug2(); const Double_t upper_limit = this->getMassParent() - this->getMassBachelor(); // check whether we have been given knots at unphysical masses if ( *first < lower_limit ) { std::cerr << "WARNING in LauAbsModIndPartWave::checkKnots : Knot found at mass " << *first << " is below the lower kinematic limit." << std::endl; std::cerr << " : Lower kinematic limit is at mass " << lower_limit << std::endl; std::cerr << " : Aborting definition of knot positions." << std::endl; knots.clear(); return knots; } if ( *last > upper_limit ) { std::cerr << "WARNING in LauAbsModIndPartWave::checkKnots : Knot found at mass " << *last << " is above the upper kinematic limit." << std::endl; std::cerr << " : Upper kinematic limit is at mass " << upper_limit << std::endl; std::cerr << " : Aborting definition of knot positions." << std::endl; knots.clear(); return knots; } // check if we have knots at each extreme - if not, add them in if ( (*first) != lower_limit ) { knots.insert( lower_limit ); } if ( (*last) != upper_limit ) { knots.insert( upper_limit ); } return knots; } void LauAbsModIndPartWave::defineKnots(const std::set& masses) { if ( ! masses_.empty() ) { std::cerr << "WARNING in LauAbsModIndPartWave::defineKnots : Knot positions have already been defined, not making any changes." << std::endl; return; } const std::set knots = this->checkKnots( masses ); nKnots_ = knots.size(); if ( nKnots_ == 0 ) { return; } masses_.reserve(nKnots_); amp1Vals_.reserve(nKnots_); amp2Vals_.reserve(nKnots_); amp1Pars_.reserve(nKnots_); amp2Pars_.reserve(nKnots_); UInt_t counter(0); for ( std::set::const_iterator iter = knots.begin(); iter != knots.end(); ++iter ) { masses_.push_back( *iter ); amp1Vals_.push_back(1.0); amp2Vals_.push_back(1.0); this->createAmpParameters(counter); ++counter; } for ( std::vector::const_iterator iter = masses_.begin(); iter != masses_.end(); ++iter ) { std::cout << "INFO in LauAbsModIndPartWave::defineKnots : Knot added to resonance " << this->getResonanceName() << " at mass " << *iter << std::endl; } } void LauAbsModIndPartWave::initialise() { if ( spline1_ != 0 ) { delete spline1_; spline1_ = 0; } if ( spline2_ != 0 ) { delete spline2_; spline2_ = 0; } for ( UInt_t i(0); i < nKnots_; ++i ) { amp1Vals_[i] = amp1Pars_[i]->unblindValue(); amp2Vals_[i] = amp2Pars_[i]->unblindValue(); } spline1_ = new Lau1DCubicSpline(masses_, amp1Vals_, type1_, leftBound1_, rightBound1_, leftGrad1_, rightGrad1_); spline2_ = new Lau1DCubicSpline(masses_, amp2Vals_, type2_, leftBound2_, rightBound2_, leftGrad2_, rightGrad2_); } LauComplex LauAbsModIndPartWave::resAmp(Double_t mass, Double_t spinTerm) { amp_.zero(); Bool_t paramChanged1(kFALSE), paramChanged2(kFALSE); for ( UInt_t i(0); i < nKnots_; ++i ) { if ( !amp1Pars_[i]->fixed() && amp1Pars_[i]->unblindValue() != amp1Vals_[i] ) { paramChanged1 = kTRUE; amp1Vals_[i] = amp1Pars_[i]->unblindValue(); } if ( !amp2Pars_[i]->fixed() && amp2Pars_[i]->unblindValue() != amp2Vals_[i] ) { paramChanged2 = kTRUE; amp2Vals_[i] = amp2Pars_[i]->unblindValue(); } } if ( spline1_ == 0 || spline2_ == 0) { std::cerr << "ERROR in LauAbsModIndPartWave::resAmp : One of the splines is null" << std::endl; return amp_; } if ( paramChanged1 ) { spline1_->updateYValues(amp1Vals_); } if ( paramChanged2 ) { spline2_->updateYValues(amp2Vals_); } this->evaluateAmplitude( mass ); amp_.rescale( spinTerm ); return amp_; } void LauAbsModIndPartWave::setSplineType(Lau1DCubicSpline::LauSplineType type1, Lau1DCubicSpline::LauSplineType type2) { type1_ = type1; type2_ = type2; } void LauAbsModIndPartWave::setSplineBoundaryConditions(Lau1DCubicSpline::LauSplineBoundaryType leftBound1, Lau1DCubicSpline::LauSplineBoundaryType rightBound1, Lau1DCubicSpline::LauSplineBoundaryType leftBound2, Lau1DCubicSpline::LauSplineBoundaryType rightBound2, Double_t leftGrad1, Double_t rightGrad1, Double_t leftGrad2, Double_t rightGrad2) { leftBound1_ = leftBound1; rightBound1_ = rightBound1; leftBound2_ = leftBound2; rightBound2_ = rightBound2; leftGrad1_ = leftGrad1; rightGrad1_ = rightGrad1; leftGrad2_ = leftGrad2; rightGrad2_ = rightGrad2; } const std::vector& LauAbsModIndPartWave::getFloatingParameters() { this->clearFloatingParameters(); for ( UInt_t i(0); i < nKnots_; ++i ) { if ( !amp1Pars_[i]->fixed() ) { this->addFloatingParameter( amp1Pars_[i] ); } if ( !amp2Pars_[i]->fixed() ) { this->addFloatingParameter( amp2Pars_[i] ); } } return this->getParameters(); } diff --git a/src/LauAbsPdf.cc b/src/LauAbsPdf.cc index e93b858..ed3c8bb 100644 --- a/src/LauAbsPdf.cc +++ b/src/LauAbsPdf.cc @@ -1,577 +1,576 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauAbsPdf.cc \brief File containing implementation of LauAbsPdf class. */ #include #include #include #include #include "TSystem.h" #include "LauAbsPdf.hh" #include "LauRandom.hh" #include "LauIntegrals.hh" #include "LauKinematics.hh" -ClassImp(LauAbsPdf) // Constructor for the abstract PDF class. LauAbsPdf::LauAbsPdf(const TString& theVarName, const std::vector& params, Double_t minAbscissa, Double_t maxAbscissa) : varNames_(), param_(params), norm_(0.0), maxHeight_(0.0), heightUpToDate_(kFALSE), minAbscissas_(), maxAbscissas_(), randomFun_(LauRandom::randomFun()), cachePDF_(kFALSE), unNormPDFVal_(0.0), nNormPoints_(50), integMethod_(GaussLegendre), withinNormCalc_(kFALSE), withinGeneration_(kFALSE), normWeightsDone_(kFALSE) { // Store the variable name varNames_.insert( std::make_pair( 0, theVarName ) ); // Store the min and max values minAbscissas_.push_back( minAbscissa ); maxAbscissas_.push_back( maxAbscissa ); } LauAbsPdf::LauAbsPdf(const std::vector& theVarNames, const std::vector& params, const LauFitData& minAbscissas, const LauFitData& maxAbscissas) : varNames_(), param_(params), norm_(0.0), maxHeight_(0.0), heightUpToDate_(kFALSE), minAbscissas_(), maxAbscissas_(), randomFun_(LauRandom::randomFun()), cachePDF_(kFALSE), unNormPDFVal_(0.0), nNormPoints_(50), integMethod_(GaussLegendre), withinNormCalc_(kFALSE), withinGeneration_(kFALSE), normWeightsDone_(kFALSE) { // Check that we have at least one variable if ( theVarNames.empty() ) { std::cerr << "ERROR in LauAbsPdf::LauAbsPdf : No variables supplied." << std::endl; gSystem->Exit(EXIT_FAILURE); } // Store the variable names for ( UInt_t i(0); i < theVarNames.size(); ++i ) { varNames_.insert( std::make_pair( i, theVarNames[i] ) ); } // Store the min and max abcissas for every variable UInt_t nVars = varNames_.size(); minAbscissas_.resize( nVars ); maxAbscissas_.resize( nVars ); for ( std::map::const_iterator iter = varNames_.begin(); iter != varNames_.end(); ++iter ) { UInt_t varIndex = iter->first; const TString& theVarName = iter->second; LauFitData::const_iterator min_iter = minAbscissas.find( theVarName ); LauFitData::const_iterator max_iter = maxAbscissas.find( theVarName ); if ( min_iter == minAbscissas.end() || max_iter == maxAbscissas.end() ) { std::cerr << "ERROR in LauAbsPdf::LauAbsPdf : Either min or max abscissa not provided for variable \"" << theVarName << "\"." << std::endl; gSystem->Exit(EXIT_FAILURE); } minAbscissas_[ varIndex ] = min_iter->second; maxAbscissas_[ varIndex ] = max_iter->second; } } std::vector LauAbsPdf::varNames() const { std::vector theVarNames; theVarNames.reserve( varNames_.size() ); for ( std::map::const_iterator iter = varNames_.begin(); iter != varNames_.end(); ++iter ) { theVarNames.push_back( iter->second ); } return theVarNames; } UInt_t LauAbsPdf::nFixedParameters() const { LauParamFixed pred; return std::count_if(param_.begin(),param_.end(),pred); } Double_t LauAbsPdf::getMinAbscissa( const TString& theVarName ) const { for ( std::map::const_iterator iter = varNames_.begin(); iter != varNames_.end(); ++iter ) { UInt_t index = iter->first; const TString& name = iter->second; if ( name == theVarName ) { return minAbscissas_[ index ]; } } std::cerr << "ERROR in LauAbsPdf::getMinAbscissa : Variable \"" << theVarName << "\" not found." << std::endl; return 0.0; } Double_t LauAbsPdf::getMaxAbscissa( const TString& theVarName ) const { for ( std::map::const_iterator iter = varNames_.begin(); iter != varNames_.end(); ++iter ) { UInt_t index = iter->first; const TString& name = iter->second; if ( name == theVarName ) { return maxAbscissas_[ index ]; } } std::cerr << "ERROR in LauAbsPdf::getMaxAbscissa : Variable \"" << theVarName << "\" not found." << std::endl; return 0.0; } LauFitData LauAbsPdf::getMinAbscissas() const { LauFitData minAbscissas; for ( std::map::const_iterator iter = varNames_.begin(); iter != varNames_.end(); ++iter ) { UInt_t varIndex = iter->first; const TString& theVarName = iter->second; minAbscissas[ theVarName ] = minAbscissas_[ varIndex ]; } return minAbscissas; } LauFitData LauAbsPdf::getMaxAbscissas() const { LauFitData maxAbscissas; for ( std::map::const_iterator iter = varNames_.begin(); iter != varNames_.end(); ++iter ) { UInt_t varIndex = iter->first; const TString& theVarName = iter->second; maxAbscissas[ theVarName ] = maxAbscissas_[ varIndex ]; } return maxAbscissas; } LauFitData LauAbsPdf::getRanges() const { LauFitData minVals = this->getMinAbscissas(); LauFitData maxVals = this->getMaxAbscissas(); LauFitData range; for ( LauFitData::const_iterator iter = maxVals.begin(); iter != maxVals.end(); ++iter ) { const TString& theVarName = iter->first; Double_t maxVal = iter->second; Double_t minVal = minVals.find(theVarName)->second; range[theVarName] = maxVal - minVal; } return range; } void LauAbsPdf::setMinAbscissa(const TString& theVarName, Double_t minAbscissa) { for ( std::map::const_iterator iter = varNames_.begin(); iter != varNames_.end(); ++iter ) { UInt_t index = iter->first; const TString& name = iter->second; if ( name == theVarName ) { minAbscissas_[ index ] = minAbscissa; return; } } std::cerr << "ERROR in LauAbsPdf::setMinAbscissa : Variable \"" << theVarName << "\" not found." << std::endl; } void LauAbsPdf::setMaxAbscissa(const TString& theVarName, Double_t maxAbscissa) { for ( std::map::const_iterator iter = varNames_.begin(); iter != varNames_.end(); ++iter ) { UInt_t index = iter->first; const TString& name = iter->second; if ( name == theVarName ) { maxAbscissas_[ index ] = maxAbscissa; return; } } std::cerr << "ERROR in LauAbsPdf::setMaxAbscissa : Variable \"" << theVarName << "\" not found." << std::endl; } Bool_t LauAbsPdf::checkRange(const LauAbscissas& abscissas) const { // This method assumes the ordering of the abscissas provided match // those of the min and max vectors // check that the size is correct UInt_t nVars = abscissas.size(); if ( this->isDPDependent() ) { nVars = abscissas.size() - 2; // if we depend on the DP we'll have been provided with the DP co-ordinates as well } if ( nVars != minAbscissas_.size() || nVars != maxAbscissas_.size() ) { std::cerr << "ERROR in LauAbsPdf::checkRange : Unexpected number of absicssas: " << nVars << std::endl; std::cerr << " : " << this->IsA()->GetName() << " expects " << minAbscissas_.size() << std::endl; return kFALSE; } for ( UInt_t i(0); i < nVars; ++i ) { Double_t abscissa = abscissas[i]; Double_t minVal = minAbscissas_[i]; Double_t maxVal = maxAbscissas_[i]; if ( (abscissa < minVal) || (abscissa > maxVal) ) { std::cerr << "ERROR in LauAbsPdf::checkRange : " << abscissa << " outside allowed range: [" << minVal << "," << maxVal << "]" << std::endl; return kFALSE; } } return kTRUE; } void LauAbsPdf::cacheInfo(const LauFitDataTree& inputData) { Bool_t hasBranch(kTRUE); for ( std::map::const_iterator iter = varNames_.begin(); iter != varNames_.end(); ++iter ) { hasBranch &= inputData.haveBranch( iter->second ); if (!hasBranch) { std::cerr << "ERROR in LauAbsPdf::cacheInfo : Input data does not contain variable \"" << iter->second << "\"." << std::endl; return; } } // determine whether we are caching our PDF value Bool_t doCaching( this->nFixedParameters() == this->nParameters() ); this->cachePDF( doCaching ); // clear the vectors and reserve enough space UInt_t nEvents = inputData.nEvents(); abscissas_.clear(); abscissas_.reserve(nEvents); unNormPDFValues_.clear(); unNormPDFValues_.reserve(nEvents); for (UInt_t iEvt = 0; iEvt < nEvents; ++iEvt) { const LauFitData& dataValues = inputData.getData(iEvt); LauAbscissas myData; // add all our variables into the data for ( std::map::const_iterator var_iter = varNames_.begin(); var_iter != varNames_.end(); ++var_iter ) { LauFitData::const_iterator iter = dataValues.find( var_iter->second ); myData.push_back( iter->second ); } // if we're DP dependent then we'll need the DP co-ordinates as well if ( this->isDPDependent() ) { LauFitData::const_iterator iter = dataValues.find( "m13Sq" ); myData.push_back( iter->second ); iter = dataValues.find( "m23Sq" ); myData.push_back( iter->second ); } if (!this->checkRange(myData)) { gSystem->Exit(EXIT_FAILURE); } abscissas_.push_back( myData ); if (this->cachePDF()) { this->calcLikelihoodInfo( myData ); unNormPDFValues_.push_back( this->getUnNormLikelihood() ); } } if (!this->cachePDF()) { // in this case we seem to be doing a fit where the parameters are floating // so need to mark that the PDF height is no longer up to date this->heightUpToDate(kFALSE); } } LauFitData LauAbsPdf::generate(const LauKinematics* kinematics) { this->withinGeneration(kTRUE); // Check that the PDF height is up to date // N.B. this must now called every time (the method will simply // return if there is nothing to do) this->calcPDFHeight( kinematics ); Bool_t gotAbscissa(kFALSE); if (randomFun_ == 0) { std::cerr << "ERROR in LauAbsPdf::generate : Please set the random number generator for this PDF by using the setRandomFun(TRandom*) function." << std::endl; this->withinGeneration(kFALSE); gSystem->Exit(EXIT_FAILURE); } if ( this->isDPDependent() && !kinematics ) { std::cerr << "ERROR in LauAbsPdf::generate : PDF depends on the DP and an invalid kinematics pointer has been provided." << std::endl; this->withinGeneration(kFALSE); gSystem->Exit(EXIT_FAILURE); } // container for holding the generated abscissa(s) LauAbscissas genAbscissa(1); // Generate the value of the abscissa. Double_t genPDFVal(0.0); Double_t PDFheight = this->getMaxHeight()*(1.0+1e-11); while (!gotAbscissa) { if ( this->isDPDependent() ) { genAbscissa.resize(3); genAbscissa[1] = kinematics->getm13Sq(); genAbscissa[2] = kinematics->getm23Sq(); } genAbscissa[0] = randomFun_->Rndm()*this->getRange() + this->getMinAbscissa(); this->calcLikelihoodInfo(genAbscissa); genPDFVal = this->getUnNormLikelihood(); if (randomFun_->Rndm() <= genPDFVal/PDFheight) {gotAbscissa = kTRUE;} if (genPDFVal > PDFheight) { std::cerr << "WARNING in LauAbsPdf::generate : genPDFVal = " << genPDFVal << " is larger than the maximum PDF height " << this->getMaxHeight() << " for the abscissa = " << genAbscissa[0] << "." << std::endl; std::cerr << " : Need to reset height to be larger than " << genPDFVal << " by using the setMaxHeight(Double_t) function and re-run the Monte Carlo generation!" << std::endl; } } LauFitData genData; genData[ this->varName() ] = genAbscissa[0]; this->withinGeneration(kFALSE); return genData; } Double_t LauAbsPdf::getLikelihood() const { if (TMath::Abs(norm_) > 1e-10) { return unNormPDFVal_/norm_; } else { return 0.0; } } Double_t LauAbsPdf::getLikelihood( const TString& theVarName ) const { if ( theVarName != this->varName() ) { std::cerr << "ERROR in LauAbsPdf::getLikelihood : Unrecognised variable name \"" << theVarName << "\", cannot determine likelihood." << std::endl; return 0.0; } return this->getLikelihood(); } void LauAbsPdf::calcLikelihoodInfo(UInt_t iEvt) { if (this->cachePDF() && (unNormPDFValues_.size() == abscissas_.size())) { unNormPDFVal_ = unNormPDFValues_[iEvt]; } else { this->calcLikelihoodInfo( abscissas_[iEvt] ); } } LauAbsRValue* LauAbsPdf::findParameter(const TString& parName) { for ( std::vector::iterator iter = param_.begin(); iter != param_.end(); ++iter ) { // std::vector params = (*iter)->getPars(); // for (std::vector::iterator params_iter = params.begin(); params_iter != params.end(); ++params_iter ) { if ((*iter)->name().Contains(parName)) { return (*iter); } // } } std::cerr << "ERROR in LauAbsPdf::findParameter : Parameter \"" << parName << "\" not found." << std::endl; return 0; } const LauAbsRValue* LauAbsPdf::findParameter(const TString& parName) const { for ( std::vector::const_iterator iter = param_.begin(); iter != param_.end(); ++iter ) { // std::vector params = (*iter)->getPars(); // for (std::vector::iterator params_iter = params.begin(); params_iter != params.end(); ++params_iter ) { if ((*iter)->name().Contains(parName)) { return (*iter); // } } } std::cerr << "ERROR in LauAbsPdf::findParameter : Parameter \"" << parName << "\" not found." << std::endl; return 0; } void LauAbsPdf::updatePulls() { for ( std::vector::iterator iter = param_.begin(); iter != param_.end(); ++iter ) { std::vector params = (*iter)->getPars(); for (std::vector::iterator params_iter = params.begin(); params_iter != params.end(); ++params_iter ) { if (!(*iter)->fixed()) { (*params_iter)->updatePull(); } } } } void LauAbsPdf::addParameters(std::vector& params) { for ( std::vector::iterator iter = params.begin(); iter != params.end(); ++iter ) { param_.push_back(*iter); } } void LauAbsPdf::calcNorm() { this->withinNormCalc(kTRUE); if ( this->nInputVars() > 1 ) { std::cerr << "ERROR in LauAbsPdf::calcNorm : Numeric integration only works for 1D PDFs." << std::endl; gSystem->Exit(EXIT_FAILURE); } IntMethod sumMethod = this->integMethod(); Double_t normFac = (sumMethod == GaussLegendre) ? this->integrGaussLegendre() : this->integTrapezoid(); this->setNorm(normFac); this->withinNormCalc(kFALSE); } Double_t LauAbsPdf::integrGaussLegendre() { if (!this->normWeightsDone()) { this->getNormWeights(); } // Now compute the integral Double_t norm(0.0); for (UInt_t i = 0; i < normWeights_.size(); i++) { this->calcLikelihoodInfo(normAbscissas_[i]); Double_t fun = this->getUnNormLikelihood(); Double_t intFactor = 0.5 * this->getRange(); norm += normWeights_[i]*intFactor*fun; } //std::cout<<"====================================================="<normWeightsDone()) { std::cerr << "WARNING in LauAbsPdf::getNormWeights : Already calculated weights, not doing it again." << std::endl; return; } // Avoid integral if we have no points in x space if (nNormPoints_ == 0) { std::cerr << "ERROR in LauAbsPdf::getNormWeights : Zero points specified, this is daft!" << std::endl; return; } // Calculate the normalisation weights and abscissas Double_t precision(1e-6); Double_t intMean = 0.5*(this->getMaxAbscissa() + this->getMinAbscissa()); Double_t range = this->getMaxAbscissa() - this->getMinAbscissa(); Double_t halfRange = 0.5*range; std::vector abscissas; LauIntegrals funIntegrals(precision); funIntegrals.calcGaussLegendreWeights(nNormPoints_, abscissas, normWeights_); //std::cout<<"====================================================="<(normWeights_.size()); normAbscissas_.resize(nWeights); // Use same number of abscissas for x and y co-ordinates Int_t m = (nWeights + 1)/2; for (Int_t i = 0; i < m; ++i) { Int_t ii = nWeights - 1 - i; // symmetric i index Double_t dx = halfRange*abscissas[i]; Double_t tmpVal = intMean - dx; normAbscissas_[i].push_back( tmpVal ); tmpVal = intMean + dx; normAbscissas_[ii].push_back( tmpVal ); } this->normWeightsDone(kTRUE); } Double_t LauAbsPdf::integTrapezoid() { Double_t abscVal, tnm, sum, del; Int_t it, j; static Double_t norm(0.0); Double_t range = this->getRange(); if (this->nNormPoints()==1){ LauAbscissas abscissa(1); abscissa[0] = this->getMinAbscissa(); this->calcLikelihoodInfo(abscissa); Double_t funAbsMin = this->getUnNormLikelihood(); abscissa[0] = this->getMinAbscissa(); this->calcLikelihoodInfo(abscissa); Double_t funAbsMax = this->getUnNormLikelihood(); norm = 0.5*range*(funAbsMin+funAbsMax); return norm; } else { for (it=1, j=1; j< this->nNormPoints()-1; j++) {it<<=1;} tnm=it; del=range/tnm; abscVal= this->getMinAbscissa()+ 0.5*del; for (sum = 0.0, j=1; jcalcLikelihoodInfo(abscissa); Double_t funVal = this->getUnNormLikelihood(); sum+=funVal; } norm = 0.5*(norm + sum*range/tnm); return norm; } } diff --git a/src/LauAbsResonance.cc b/src/LauAbsResonance.cc index f956be6..0f538dd 100644 --- a/src/LauAbsResonance.cc +++ b/src/LauAbsResonance.cc @@ -1,720 +1,719 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauAbsResonance.cc \brief File containing implementation of LauAbsResonance class. */ #include #include "TSystem.h" #include "LauAbsResonance.hh" #include "LauConstants.hh" #include "LauDaughters.hh" #include "LauKinematics.hh" #include "LauParameter.hh" #include "LauResonanceInfo.hh" -ClassImp(LauAbsResonance) bool LauAbsResonance::isIncoherentModel(LauResonanceModel model) { switch(model) { case BW: case RelBW: case GS: case Flatte: case Sigma: case Kappa: case Dabba: case LASS: case LASS_BW: case LASS_NR: case EFKLLM: case KMatrix: case FlatNR: case NRModel: case BelleNR: case PowerLawNR: case BelleSymNR: case BelleSymNRNoInter: case TaylorNR: case PolNR: case Pole: case PolarFFNR: case PolarFFSymNR: case PolarFFSymNRNoInter: case Rescattering: case Rescattering2: case RescatteringNoInter: case MIPW_MagPhase: case MIPW_RealImag: case RhoOmegaMix_GS: case RhoOmegaMix_RBW: case RhoOmegaMix_GS_1: case RhoOmegaMix_RBW_1: break; case GaussIncoh: return true; } return false; } // Constructor LauAbsResonance::LauAbsResonance(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : resInfo_(resInfo), daughters_(daughters), nameParent_(""), nameDaug1_(""), nameDaug2_(""), nameBachelor_(""), chargeParent_(0), chargeDaug1_(0), chargeDaug2_(0), chargeBachelor_(0), massParent_(0.0), massDaug1_(0.0), massDaug2_(0.0), massBachelor_(0.0), resName_( (resInfo!=0) ? resInfo->getName() : "" ), sanitisedName_( (resInfo!=0) ? resInfo->getSanitisedName() : "" ), resMass_( (resInfo!=0) ? resInfo->getMass() : 0 ), resWidth_( (resInfo!=0) ? resInfo->getWidth() : 0 ), resSpin_( (resInfo!=0) ? resInfo->getSpin() : 0 ), resCharge_( (resInfo!=0) ? resInfo->getCharge() : 0 ), resPairAmpInt_(resPairAmpInt), parBWFactor_(0), resBWFactor_(0), spinType_(Zemach_P), flipHelicity_(kFALSE), ignoreMomenta_(kFALSE), ignoreSpin_(kFALSE), ignoreBarrierScaling_(kFALSE), mass_(0.0), cosHel_(0.0), q_(0.0), p_(0.0), pstar_(0.0), erm_(1.0), covFactor_(1.0) { if ( resInfo == 0 ) { std::cerr << "ERROR in LauAbsResonance constructor : null LauResonanceInfo object provided" << std::endl; gSystem->Exit(EXIT_FAILURE); } if ( daughters_ == 0 ) { std::cerr << "ERROR in LauAbsResonance constructor : null LauDaughters object provided" << std::endl; gSystem->Exit(EXIT_FAILURE); } nameParent_ = this->getNameParent(); nameDaug1_ = this->getNameDaug1(); nameDaug2_ = this->getNameDaug2(); nameBachelor_ = this->getNameBachelor(); massParent_ = this->getMassParent(); massDaug1_ = this->getMassDaug1(); massDaug2_ = this->getMassDaug2(); massBachelor_ = this->getMassBachelor(); chargeParent_ = this->getChargeParent(); chargeDaug1_ = this->getChargeDaug1(); chargeDaug2_ = this->getChargeDaug2(); chargeBachelor_ = this->getChargeBachelor(); // check that the total charge adds up to that of the resonance Int_t totalCharge = chargeDaug1_ + chargeDaug2_; if ( (totalCharge != resCharge_) && (resPairAmpInt_ != 0) ) { std::cerr << "ERROR in LauAbsResonance : Total charge of daughters = " << totalCharge << ". Resonance charge = " << resCharge_ << "." << std::endl; gSystem->Exit(EXIT_FAILURE); } } // Constructor LauAbsResonance::LauAbsResonance(const TString& resName, const Int_t resPairAmpInt, const LauDaughters* daughters) : resInfo_(0), daughters_(daughters), nameParent_(""), nameDaug1_(""), nameDaug2_(""), nameBachelor_(""), chargeParent_(0), chargeDaug1_(0), chargeDaug2_(0), chargeBachelor_(0), massParent_(0.0), massDaug1_(0.0), massDaug2_(0.0), massBachelor_(0.0), resName_(resName), sanitisedName_(resName), resMass_(0), resWidth_(0), resSpin_(0), resCharge_(0), resPairAmpInt_(resPairAmpInt), parBWFactor_(0), resBWFactor_(0), spinType_(Zemach_P), flipHelicity_(kFALSE), ignoreMomenta_(kFALSE), ignoreSpin_(kFALSE), ignoreBarrierScaling_(kFALSE), mass_(0.0), cosHel_(0.0), q_(0.0), p_(0.0), pstar_(0.0), erm_(1.0), covFactor_(1.0) { if ( daughters_ == 0 ) { std::cerr << "ERROR in LauAbsResonance constructor : null LauDaughters object provided" << std::endl; gSystem->Exit(EXIT_FAILURE); } nameParent_ = this->getNameParent(); nameDaug1_ = this->getNameDaug1(); nameDaug2_ = this->getNameDaug2(); nameBachelor_ = this->getNameBachelor(); massParent_ = this->getMassParent(); massDaug1_ = this->getMassDaug1(); massDaug2_ = this->getMassDaug2(); massBachelor_ = this->getMassBachelor(); chargeParent_ = this->getChargeParent(); chargeDaug1_ = this->getChargeDaug1(); chargeDaug2_ = this->getChargeDaug2(); chargeBachelor_ = this->getChargeBachelor(); // Since we haven't been provided with a LauResonanceInfo object we can just // set the change of the resonance to be the sum of the daughter charges resCharge_ = chargeDaug1_ + chargeDaug2_; } // Destructor LauAbsResonance::~LauAbsResonance() { } LauComplex LauAbsResonance::amplitude(const LauKinematics* kinematics) { // Use LauKinematics interface for amplitude // For resonance made from tracks i, j, we need the momenta // of tracks i and k in the i-j rest frame for spin helicity calculations // in the Zemach tensor formalism. // Also need the momentum of track k in the parent rest-frame for // calculation of the Blatt-Weisskopf factors. mass_ = 0.0; cosHel_ = 0.0; q_ = 0.0; p_ = 0.0; pstar_ = 0.0; erm_ = 1.0; covFactor_ = 1.0; if (resPairAmpInt_ == 1) { mass_ = kinematics->getm23(); cosHel_ = kinematics->getc23(); q_ = kinematics->getp2_23(); p_ = kinematics->getp1_23(); pstar_ = kinematics->getp1_Parent(); erm_ = kinematics->getcov23(); } else if (resPairAmpInt_ == 2) { mass_ = kinematics->getm13(); cosHel_ = kinematics->getc13(); q_ = kinematics->getp1_13(); p_ = kinematics->getp2_13(); pstar_ = kinematics->getp2_Parent(); erm_ = kinematics->getcov13(); } else if (resPairAmpInt_ == 3) { mass_ = kinematics->getm12(); cosHel_ = kinematics->getc12(); q_ = kinematics->getp1_12(); p_ = kinematics->getp3_12(); pstar_ = kinematics->getp3_Parent(); erm_ = kinematics->getcov12(); } else { std::cerr << "ERROR in LauAbsResonance::amplitude : Nonsense setup of resPairAmp array." << std::endl; gSystem->Exit(EXIT_FAILURE); } if (this->flipHelicity()) { cosHel_ *= -1.0; } if (this->ignoreMomenta()) { q_ = 1.0; p_ = 1.0; pstar_ = 1.0; erm_ = 1.0; } // Calculate the spin factors Double_t spinTerm(1.0); Double_t pProd(1.0); if (!this->ignoreSpin()) { switch ( this->getSpinType() ) { case Zemach_P: pProd = q_*p_; spinTerm = this->calcZemachSpinFactor( pProd ); break; case Zemach_Pstar: pProd = q_*pstar_; spinTerm = this->calcZemachSpinFactor( pProd ); break; case Covariant: pProd = q_*pstar_; spinTerm = this->calcCovSpinFactor( pProd ); break; case Legendre: spinTerm = this->calcLegendrePoly(); break; } } // Calculate the full amplitude LauComplex resAmplitude = this->resAmp(mass_, spinTerm); return resAmplitude; } void LauAbsResonance::calcCovFactor( const Double_t erm ) { if (resSpin_ == 0) { covFactor_ = 1.0; } else if (resSpin_ == 1) { covFactor_ = erm; } else if (resSpin_ == 2) { covFactor_ = erm*erm + 0.5; } else if (resSpin_ == 3) { covFactor_ = erm*(erm*erm + 1.5); } else if (resSpin_ == 4) { covFactor_ = (8.*erm*erm*erm*erm + 24.*erm*erm + 3.)/35.; } else if (resSpin_ > 4) { std::cerr << "WARNING in LauAbsResonance::calcCovFactor : covariant spin factor cannot (yet) be fully calculated for spin >= 5" << std::endl; std::cerr << " : the function of sqrt(1 + (p/mParent)^2) part will be missing" << std::endl; covFactor_ = 1.0; } } Double_t LauAbsResonance::calcCovSpinFactor( const Double_t pProd ) { if (resSpin_ == 0) { covFactor_ = 1.0; return 1.0; } // Covariant spin factor is (p* q)^L * f_L(erm) * P_L(cosHel) Double_t spinFactor(pProd); for ( Int_t i(1); i < resSpin_; ++i ) { spinFactor *= pProd; } this->calcCovFactor( erm_ ); spinFactor *= covFactor_; spinFactor *= this->calcLegendrePoly(); return spinFactor; } Double_t LauAbsResonance::calcZemachSpinFactor( const Double_t pProd ) const { // Calculate the spin factors // // These are calculated as follows // // -2^j * (q*p)^j * cj * Pj(cosHel) // // where Pj(coshHel) is the jth order Legendre polynomial and // // cj = j! / (2j-1)!! if (resSpin_ == 0) { return 1.0; } Double_t spinFactor(pProd); for ( Int_t i(1); i < resSpin_; ++i ) { spinFactor *= pProd; } spinFactor *= this->calcLegendrePoly(); return spinFactor; } Double_t LauAbsResonance::calcLegendrePoly( const Double_t cosHel ) { cosHel_ = cosHel; return this->calcLegendrePoly(); } Double_t LauAbsResonance::calcLegendrePoly() const { Double_t legPol = 1.0; if (resSpin_ == 1) { // Calculate vector resonance Legendre polynomial legPol = -2.0*cosHel_; } else if (resSpin_ == 2) { // Calculate tensor resonance Legendre polynomial legPol = 4.0*(3.0*cosHel_*cosHel_ - 1.0)/3.0; } else if (resSpin_ == 3) { // Calculate spin 3 resonance Legendre polynomial legPol = -8.0*(5.0*cosHel_*cosHel_*cosHel_ - 3.0*cosHel_)/5.0; } else if (resSpin_ == 4) { // Calculate spin 4 resonance Legendre polynomial legPol = 16.0*(35.0*cosHel_*cosHel_*cosHel_*cosHel_ - 30.0*cosHel_*cosHel_ + 3.0)/35.0; } else if (resSpin_ == 5) { // Calculate spin 5 resonance Legendre polynomial legPol = -32.0*(63.0*cosHel_*cosHel_*cosHel_*cosHel_*cosHel_ - 70.0*cosHel_*cosHel_*cosHel_ + 15.0*cosHel_)/63.0; } else if (resSpin_ > 5) { std::cerr << "WARNING in LauAbsResonance::calcLegendrePoly : Legendre polynomials not (yet) implemented for spin > 5" << std::endl; } return legPol; } void LauAbsResonance::changeResonance(const Double_t newMass, const Double_t newWidth, const Int_t newSpin) { if (newMass > 0.0) { resMass_->valueAndRange(newMass,0.0,3.0*newMass); resMass_->initValue(newMass); resMass_->genValue(newMass); std::cout << "INFO in LauAbsResonance::changeResonance : Setting mass to " << resMass_->value() << std::endl; } if (newWidth > 0.0) { resWidth_->valueAndRange(newWidth,0.0,3.0*newWidth); resWidth_->initValue(newWidth); resWidth_->genValue(newWidth); std::cout << "INFO in LauAbsResonance::changeResonance : Setting width to " << resWidth_->value() << std::endl; } if (newSpin > -1) { resSpin_ = newSpin; std::cout << "INFO in LauAbsResonance::changeResonance : Setting spin to " << resSpin_ << std::endl; } } void LauAbsResonance::changeBWBarrierRadii(const Double_t resRadius, const Double_t parRadius) { if ( resRadius >= 0.0 && resBWFactor_ != 0 ) { LauParameter* resBWRadius = resBWFactor_->getRadiusParameter(); resBWRadius->value(resRadius); resBWRadius->initValue(resRadius); resBWRadius->genValue(resRadius); std::cout << "INFO in LauAbsResonance::changeBWBarrierRadii : Setting resonance factor radius to " << resBWRadius->value() << std::endl; } if ( parRadius >= 0.0 && parBWFactor_ != 0 ) { LauParameter* parBWRadius = parBWFactor_->getRadiusParameter(); parBWRadius->value(parRadius); parBWRadius->initValue(parRadius); parBWRadius->genValue(parRadius); std::cout << "INFO in LauAbsResonance::changeBWBarrierRadii : Setting parent factor radius to " << parBWRadius->value() << std::endl; } } void LauAbsResonance::setResonanceParameter(const TString& name, const Double_t value) { //This function should always be overwritten if needed in classes inheriting from LauAbsResonance. std::cerr << "WARNING in LauAbsResonance::setResonanceParameter : Unable to set parameter \"" << name << "\" to value: " << value << "." << std::endl; } void LauAbsResonance::floatResonanceParameter(const TString& name) { //This function should always be overwritten if needed in classes inheriting from LauAbsResonance. std::cerr << "WARNING in LauAbsResonance::floatResonanceParameter : Unable to release parameter \"" << name << "\"." << std::endl; } LauParameter* LauAbsResonance::getResonanceParameter(const TString& name) { //This function should always be overwritten if needed in classes inheriting from LauAbsResonance. std::cerr << "WARNING in LauAbsResonance::getResonanceParameter : Unable to get parameter \"" << name << "\"." << std::endl; return 0; } void LauAbsResonance::addFloatingParameter( LauParameter* param ) { if ( param == 0 ) { return; } if ( param->clone() ) { resParameters_.push_back( param->parent() ); } else { resParameters_.push_back( param ); } } void LauAbsResonance::fixBarrierRadii(const Bool_t fixResRad, const Bool_t fixParRad) { if ( resBWFactor_ == 0 ) { std::cerr << "WARNING in LauAbsResonance::fixBarrierRadii : resonance barrier factor not present, cannot fix/float it" << std::endl; return; } if ( parBWFactor_ == 0 ) { std::cerr << "WARNING in LauAbsResonance::fixBarrierRadii : parent barrier factor not present, cannot fix/float it" << std::endl; return; } LauParameter* resBWRadius = resBWFactor_->getRadiusParameter(); resBWRadius->fixed(fixResRad); LauParameter* parBWRadius = parBWFactor_->getRadiusParameter(); parBWRadius->fixed(fixParRad); } Bool_t LauAbsResonance::fixResRadius() const { if ( resBWFactor_ == 0 ) { std::cerr << "WARNING in LauAbsResonance::fixResRadius : resonance barrier factor not present" << std::endl; return kTRUE; } LauParameter* bwRadius = resBWFactor_->getRadiusParameter(); return bwRadius->fixed(); } Bool_t LauAbsResonance::fixParRadius() const { if ( parBWFactor_ == 0 ) { std::cerr << "WARNING in LauAbsResonance::fixParRadius : parent barrier factor not present" << std::endl; return kTRUE; } LauParameter* bwRadius = parBWFactor_->getRadiusParameter(); return bwRadius->fixed(); } Double_t LauAbsResonance::getResRadius() const { if ( resBWFactor_ == 0 ) { std::cerr << "WARNING in LauAbsResonance::getResRadius : resonance barrier factor not present" << std::endl; return -1.0; } LauParameter* bwRadius = resBWFactor_->getRadiusParameter(); return bwRadius->unblindValue(); } Double_t LauAbsResonance::getParRadius() const { if ( parBWFactor_ == 0 ) { std::cerr << "WARNING in LauAbsResonance::getParRadius : parent barrier factor not present" << std::endl; return -1.0; } LauParameter* bwRadius = parBWFactor_->getRadiusParameter(); return bwRadius->unblindValue(); } Double_t LauAbsResonance::getMassParent() const { // Get the parent mass Double_t mass(LauConstants::mB); if (daughters_) { mass = daughters_->getMassParent(); } return mass; } Double_t LauAbsResonance::getMassDaug1() const { // Get the daughter mass Double_t mass(LauConstants::mPi); if (daughters_) { if (resPairAmpInt_ == 1) { mass = daughters_->getMassDaug2(); } else if (resPairAmpInt_ == 2) { mass = daughters_->getMassDaug1(); } else if (resPairAmpInt_ == 3) { mass = daughters_->getMassDaug1(); } } return mass; } Double_t LauAbsResonance::getMassDaug2() const { // Get the daughter mass Double_t mass(LauConstants::mPi); if (daughters_) { if (resPairAmpInt_ == 1) { mass = daughters_->getMassDaug3(); } else if (resPairAmpInt_ == 2) { mass = daughters_->getMassDaug3(); } else if (resPairAmpInt_ == 3) { mass = daughters_->getMassDaug2(); } } return mass; } Double_t LauAbsResonance::getMassBachelor() const { // Get the bachelor mass Double_t mass(LauConstants::mPi); if (daughters_) { if (resPairAmpInt_ == 1) { mass = daughters_->getMassDaug1(); } else if (resPairAmpInt_ == 2) { mass = daughters_->getMassDaug2(); } else if (resPairAmpInt_ == 3) { mass = daughters_->getMassDaug3(); } } return mass; } Int_t LauAbsResonance::getChargeParent() const { // Get the parent charge Int_t charge(0); if (daughters_) { charge = daughters_->getChargeParent(); } return charge; } Int_t LauAbsResonance::getChargeDaug1() const { // Get the daughter charge Int_t charge(0); if (daughters_) { if (resPairAmpInt_ == 1) { charge = daughters_->getChargeDaug2(); } else if (resPairAmpInt_ == 2) { charge = daughters_->getChargeDaug1(); } else if (resPairAmpInt_ == 3) { charge = daughters_->getChargeDaug1(); } } return charge; } Int_t LauAbsResonance::getChargeDaug2() const { // Get the daughter charge Int_t charge(0); if (daughters_) { if (resPairAmpInt_ == 1) { charge = daughters_->getChargeDaug3(); } else if (resPairAmpInt_ == 2) { charge = daughters_->getChargeDaug3(); } else if (resPairAmpInt_ == 3) { charge = daughters_->getChargeDaug2(); } } return charge; } Int_t LauAbsResonance::getChargeBachelor() const { // Get the bachelor charge Int_t charge(0); if (daughters_) { if (resPairAmpInt_ == 1) { charge = daughters_->getChargeDaug1(); } else if (resPairAmpInt_ == 2) { charge = daughters_->getChargeDaug2(); } else if (resPairAmpInt_ == 3) { charge = daughters_->getChargeDaug3(); } } return charge; } TString LauAbsResonance::getNameParent() const { // Get the parent name TString name(""); if (daughters_) { name = daughters_->getNameParent(); } return name; } TString LauAbsResonance::getNameDaug1() const { // Get the daughter name TString name(""); if (daughters_) { if (resPairAmpInt_ == 1) { name = daughters_->getNameDaug2(); } else if (resPairAmpInt_ == 2) { name = daughters_->getNameDaug1(); } else if (resPairAmpInt_ == 3) { name = daughters_->getNameDaug1(); } } return name; } TString LauAbsResonance::getNameDaug2() const { // Get the daughter name TString name(""); if (daughters_) { if (resPairAmpInt_ == 1) { name = daughters_->getNameDaug3(); } else if (resPairAmpInt_ == 2) { name = daughters_->getNameDaug3(); } else if (resPairAmpInt_ == 3) { name = daughters_->getNameDaug2(); } } return name; } TString LauAbsResonance::getNameBachelor() const { // Get the bachelor name TString name(""); if (daughters_) { if (resPairAmpInt_ == 1) { name = daughters_->getNameDaug1(); } else if (resPairAmpInt_ == 2) { name = daughters_->getNameDaug2(); } else if (resPairAmpInt_ == 3) { name = daughters_->getNameDaug3(); } } return name; } diff --git a/src/LauArgusPdf.cc b/src/LauArgusPdf.cc index 593b4b0..87b7a9f 100644 --- a/src/LauArgusPdf.cc +++ b/src/LauArgusPdf.cc @@ -1,149 +1,148 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauArgusPdf.cc \brief File containing implementation of LauArgusPdf class. */ #include #include #include "TMath.h" #include "TSystem.h" #include "LauArgusPdf.hh" #include "LauConstants.hh" -ClassImp(LauArgusPdf) LauArgusPdf::LauArgusPdf(const TString& theVarName, const std::vector& params, Double_t minAbscissa, Double_t maxAbscissa) : LauAbsPdf(theVarName, params, minAbscissa, maxAbscissa), xi_(0), m0_(0) { // Constructor for the ARGUS PDF. // // The parameters in params are the shape, xi, and the end-point of the curve. // The last two arguments specify the range in which the PDF is defined, and the PDF // will be normalised w.r.t. these limits. xi_ = this->findParameter("xi"); m0_ = this->findParameter("m0"); if ((this->nParameters() != 2) || (xi_ == 0) || (m0_ == 0)) { std::cerr << "ERROR in LauArgusPdf constructor: LauArgusPdf requires 2 parameters: argus shape parameter, \"xi\", and end-point, \"m0\"." << std::endl; gSystem->Exit(EXIT_FAILURE); } // Cache the normalisation factor. this->calcNorm(); } LauArgusPdf::~LauArgusPdf() { // Destructor } void LauArgusPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Get our abscissa Double_t abscissa = abscissas[0]; // Get the up to date parameter values Double_t xi = xi_->unblindValue(); Double_t m0 = m0_->unblindValue(); // Calculate the value of the ARGUS function for the given value of the abscissa. Double_t x = abscissa/m0; Double_t term = 1.0 - x*x; if (term < 0.0) {term = 0.0;} // In case |x| > 1.0 (which should happen rarely). Double_t value = abscissa*TMath::Sqrt(term)*TMath::Exp(-xi*term); this->setUnNormPDFVal(value); // if the parameters are floating then we // need to recalculate the normalisation if (!this->cachePDF() && !this->withinNormCalc() && !this->withinGeneration()) { this->calcNorm(); } } void LauArgusPdf::calcNorm() { // Calculate the PDF normalisation and cache it // Get the up to date parameter values Double_t xi = xi_->unblindValue(); Double_t m0 = m0_->unblindValue(); // Since the PDF is 0 above m0 by definition need to check whether m0 is within the range, above it or below it Double_t min = (this->getMinAbscissa() < m0) ? this->getMinAbscissa() : m0; Double_t max = (this->getMaxAbscissa() < m0) ? this->getMaxAbscissa() : m0; // Define variables equivalent to "term" in calcLikelihoodInfo above but at the min and max points Double_t termMin = 1.0 - (min/m0)*(min/m0); Double_t termMax = 1.0 - (max/m0)*(max/m0); // Calculate the various terms in the integrals Double_t norm1 = TMath::Sqrt(termMax)*TMath::Exp(-xi*termMax) - TMath::Sqrt(termMin)*TMath::Exp(-xi*termMin); Double_t norm2 = LauConstants::rootPi/(2.0*TMath::Sqrt(xi)) * ( TMath::Erf(TMath::Sqrt(xi*termMax)) - TMath::Erf(TMath::Sqrt(xi*termMin)) ); // Combine them and set the normalisation Double_t norm = m0*m0*(norm1 - norm2)/(2.0*xi); this->setNorm(norm); } void LauArgusPdf::calcPDFHeight( const LauKinematics* /*kinematics*/ ) { if (this->heightUpToDate()) { return; } // Calculate the PDF height of the ARGUS function. // Get the up to date parameter values Double_t xi = xi_->unblindValue(); Double_t m0 = m0_->unblindValue(); // First make sure that the limits are not larger than the end-point. // (Btw, use the logarithmic derivative to derive this formula) Double_t term = xi*xi + 1.0; Double_t x = TMath::Sqrt((TMath::Sqrt(term) - 1.0 + xi)/(2.0*xi)); x = (x*m0 >= this->getMinAbscissa()) ? x*m0 : this->getMinAbscissa(); LauAbscissas abscissa(1); abscissa[0] = x; this->calcLikelihoodInfo(abscissa); Double_t height = this->getUnNormLikelihood(); this->setMaxHeight(height); } diff --git a/src/LauAsymmCalc.cc b/src/LauAsymmCalc.cc index 388ab32..cee5894 100644 --- a/src/LauAsymmCalc.cc +++ b/src/LauAsymmCalc.cc @@ -1,76 +1,75 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauAsymmCalc.cc \brief File containing implementation of LauAsymmCalc class. */ #include "TMath.h" #include "LauAsymmCalc.hh" -ClassImp(LauAsymmCalc) LauAsymmCalc::LauAsymmCalc(Double_t negValue, Double_t posValue) : negValue_(negValue), posValue_(posValue), asymm_(0.0) { asymm_ = calcAsymmetry(); } LauAsymmCalc::LauAsymmCalc(const LauAsymmCalc& rhs) : negValue_(rhs.negValue_), posValue_(rhs.posValue_), asymm_(rhs.asymm_) { } LauAsymmCalc& LauAsymmCalc::operator=(const LauAsymmCalc& rhs) { if ( &rhs != this ) { negValue_ = rhs.negValue_; posValue_ = rhs.posValue_; asymm_ = rhs.asymm_; } return *this; } LauAsymmCalc::~LauAsymmCalc() { } Double_t LauAsymmCalc::calcAsymmetry() { Double_t num = negValue_ - posValue_; Double_t denom = negValue_ + posValue_; Double_t asymm(0.0); if (TMath::Abs(denom) > 1e-10) { asymm = num/denom; } return asymm; } diff --git a/src/LauBelleCPCoeffSet.cc b/src/LauBelleCPCoeffSet.cc index 5fe967f..edfe493 100644 --- a/src/LauBelleCPCoeffSet.cc +++ b/src/LauBelleCPCoeffSet.cc @@ -1,349 +1,348 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauBelleCPCoeffSet.cc \brief File containing implementation of LauBelleCPCoeffSet class. */ #include #include #include #include "TMath.h" #include "TRandom.h" #include "LauComplex.hh" #include "LauConstants.hh" #include "LauBelleCPCoeffSet.hh" #include "LauParameter.hh" #include "LauPrint.hh" -ClassImp(LauBelleCPCoeffSet) LauBelleCPCoeffSet::LauBelleCPCoeffSet(const TString& compName, Double_t a, Double_t delta, Double_t b, Double_t phi, Bool_t aFixed, Bool_t deltaFixed, Bool_t bFixed, Bool_t phiFixed, Bool_t bSecondStage, Bool_t phiSecondStage) : LauAbsCoeffSet(compName), a_(new LauParameter("A", a, minMagnitude_, maxMagnitude_, aFixed)), b_(new LauParameter("B", b, minMagnitude_, maxMagnitude_, bFixed)), delta_(new LauParameter("Delta", delta, minPhase_, maxPhase_, deltaFixed)), phi_(new LauParameter("Phi", phi, minPhase_, maxPhase_, phiFixed)), particleCoeff_(0.0,0.0), antiparticleCoeff_(0.0,0.0), acp_("ACP", (-2.0*b*TMath::Cos(phi))/(1.0+b*b), -1.0, 1.0, bFixed&&phiFixed) { if (bSecondStage && !bFixed) { b_->secondStage(kTRUE); b_->initValue(0.0); } if (phiSecondStage && !phiFixed) { phi_->secondStage(kTRUE); phi_->initValue(0.0); } } LauBelleCPCoeffSet::LauBelleCPCoeffSet(const LauBelleCPCoeffSet& rhs, CloneOption cloneOption, Double_t constFactor) : LauAbsCoeffSet(rhs.name()), a_(0), b_(0), delta_(0), phi_(0), particleCoeff_( rhs.particleCoeff_ ), antiparticleCoeff_( rhs.antiparticleCoeff_ ), acp_( rhs.acp_ ) { if ( cloneOption == All || cloneOption == TieMagnitude ) { a_ = rhs.a_->createClone(constFactor); } else { a_ = new LauParameter("A", rhs.a_->value(), minMagnitude_, maxMagnitude_, rhs.a_->fixed()); if ( rhs.a_->blind() ) { const LauBlind* blinder = rhs.a_->blinder(); a_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TieCPPars ) { b_ = rhs.b_->createClone(constFactor); } else { b_ = new LauParameter("B", rhs.b_->value(), minMagnitude_, maxMagnitude_, rhs.b_->fixed()); if ( rhs.b_->blind() ) { const LauBlind* blinder = rhs.b_->blinder(); b_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TiePhase ) { delta_ = rhs.delta_->createClone(constFactor); } else { delta_ = new LauParameter("Delta", rhs.delta_->value(), minPhase_, maxPhase_, rhs.delta_->fixed()); if ( rhs.delta_->blind() ) { const LauBlind* blinder = rhs.delta_->blinder(); delta_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TieCPPars ) { phi_ = rhs.phi_->createClone(constFactor); } else { phi_ = new LauParameter("Phi", rhs.phi_->value(), minPhase_, maxPhase_, rhs.phi_->fixed()); if ( rhs.phi_->blind() ) { const LauBlind* blinder = rhs.phi_->blinder(); phi_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } } std::vector LauBelleCPCoeffSet::getParameters() { std::vector pars; pars.push_back(a_); pars.push_back(b_); pars.push_back(delta_); pars.push_back(phi_); return pars; } void LauBelleCPCoeffSet::printParValues() const { std::cout<<"INFO in LauBelleCPCoeffSet::printParValues : Component \""<name()<<"\" has "; std::cout<<"a-magnitude = "<value()<<",\t"; std::cout<<"delta = "<value()<<",\t"; std::cout<<"b-magnitude = "<value()<<",\t"; std::cout<<"phi = "<value()<<"."<name(); resName = resName.ReplaceAll("_", "\\_"); stream<value()); stream<<" \\pm "; print.printFormat(stream, a_->error()); stream<<"$ & $"; print.printFormat(stream, delta_->value()); stream<<" \\pm "; print.printFormat(stream, delta_->error()); stream<<"$ & $"; print.printFormat(stream, b_->value()); stream<<" \\pm "; print.printFormat(stream, b_->error()); stream<<"$ & $"; print.printFormat(stream, phi_->value()); stream<<" \\pm "; print.printFormat(stream, phi_->error()); stream<<"$ \\\\"<fixed() == kFALSE) { // Choose an a-magnitude between 0.0 and 2.0 Double_t mag = LauAbsCoeffSet::getRandomiser()->Rndm()*2.0; a_->initValue(mag); a_->value(mag); } if (b_->fixed() == kFALSE && b_->secondStage() == kFALSE) { // Choose a b-magnitude between 0.0 and 0.1 Double_t mag = LauAbsCoeffSet::getRandomiser()->Rndm()*0.1; b_->initValue(mag); b_->value(mag); } if (delta_->fixed() == kFALSE) { // Choose a phase between +- pi Double_t phase = LauAbsCoeffSet::getRandomiser()->Rndm()*LauConstants::twoPi - LauConstants::pi; delta_->initValue(phase); delta_->value(phase); } if (phi_->fixed() == kFALSE && phi_->secondStage() == kFALSE) { // Choose a phase between +- pi Double_t phase = LauAbsCoeffSet::getRandomiser()->Rndm()*LauConstants::twoPi - LauConstants::pi; phi_->initValue(phase); phi_->value(phase); } } void LauBelleCPCoeffSet::finaliseValues() { // retrieve the current values from the parameters Double_t aVal = a_->value(); Double_t bVal = b_->value(); Double_t deltaVal = delta_->value(); Double_t phiVal = phi_->value(); Double_t genDelta = delta_->genValue(); Double_t genPhi = phi_->genValue(); // Check whether we have a negative "a" magnitude. // If so make it positive and add pi to the "delta" phase. if (aVal < 0.0) { aVal *= -1.0; deltaVal += LauConstants::pi; } // Check whether we have a negative "b" magnitude. // If so make it positive and add pi to the "phi" phase. if (bVal < 0.0) { bVal *= -1.0; phiVal += LauConstants::pi; } // Check now whether the phases lies in the right range (-pi to pi). Bool_t deltaWithinRange(kFALSE); Bool_t phiWithinRange(kFALSE); while (deltaWithinRange == kFALSE && phiWithinRange == kFALSE) { if (deltaVal > -LauConstants::pi && deltaVal < LauConstants::pi) { deltaWithinRange = kTRUE; } else { // Not within the specified range if (deltaVal > LauConstants::pi) { deltaVal -= LauConstants::twoPi; } else if (deltaVal < -LauConstants::pi) { deltaVal += LauConstants::twoPi; } } if (phiVal > -LauConstants::pi && phiVal < LauConstants::pi) { phiWithinRange = kTRUE; } else { // Not within the specified range if (phiVal > LauConstants::pi) { phiVal -= LauConstants::twoPi; } else if (phiVal < -LauConstants::pi) { phiVal += LauConstants::twoPi; } } } // A further problem can occur when the generated phase is close to -pi or pi. // The phase can wrap over to the other end of the scale - // this leads to artificially large pulls so we wrap it back. Double_t diff = deltaVal - genDelta; if (diff > LauConstants::pi) { deltaVal -= LauConstants::twoPi; } else if (diff < -LauConstants::pi) { deltaVal += LauConstants::twoPi; } diff = phiVal - genPhi; if (diff > LauConstants::pi) { phiVal -= LauConstants::twoPi; } else if (diff < -LauConstants::pi) { phiVal += LauConstants::twoPi; } // finally store the new values in the parameters // and update the pulls a_->value(aVal); a_->updatePull(); b_->value(bVal); b_->updatePull(); delta_->value(deltaVal); delta_->updatePull(); phi_->value(phiVal); phi_->updatePull(); } const LauComplex& LauBelleCPCoeffSet::particleCoeff() { LauComplex aTerm(a_->unblindValue()*TMath::Cos(delta_->unblindValue()), a_->unblindValue()*TMath::Sin(delta_->unblindValue())); LauComplex bTerm(b_->unblindValue()*TMath::Cos(phi_->unblindValue()), b_->unblindValue()*TMath::Sin(phi_->unblindValue())); particleCoeff_.setRealImagPart(1.0,0.0); particleCoeff_ += bTerm; particleCoeff_ *= aTerm; return particleCoeff_; } const LauComplex& LauBelleCPCoeffSet::antiparticleCoeff() { LauComplex aTerm(a_->unblindValue()*TMath::Cos(delta_->unblindValue()), a_->unblindValue()*TMath::Sin(delta_->unblindValue())); LauComplex bTerm(b_->unblindValue()*TMath::Cos(phi_->unblindValue()), b_->unblindValue()*TMath::Sin(phi_->unblindValue())); antiparticleCoeff_.setRealImagPart(1.0,0.0); antiparticleCoeff_ -= bTerm; antiparticleCoeff_ *= aTerm; return antiparticleCoeff_; } void LauBelleCPCoeffSet::setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, Bool_t init ) { LauComplex sum = coeff + coeffBar; LauComplex diff = coeff - coeffBar; LauComplex ratio = diff / sum; Double_t aVal( 0.5 * sum.abs() ); Double_t deltaVal( sum.arg() ); Double_t bVal( ratio.abs() ); Double_t phiVal( ratio.arg() ); a_->value( aVal ); delta_->value( deltaVal ); b_->value( bVal ); phi_->value( phiVal ); if ( init ) { a_->genValue( aVal ); delta_->genValue( deltaVal ); b_->genValue( bVal ); phi_->genValue( phiVal ); a_->initValue( aVal ); delta_->initValue( deltaVal ); b_->initValue( bVal ); phi_->initValue( phiVal ); } } LauParameter LauBelleCPCoeffSet::acp() { // set the name TString parName(this->baseName()); parName += "_ACP"; acp_.name(parName); // work out the ACP value Double_t value = (-2.0*b_->value()*TMath::Cos(phi_->value()))/(1.0+b_->value()*b_->value()); // is it fixed? Bool_t fixed = b_->fixed() && phi_->fixed(); acp_.fixed(fixed); // we can't work out the error without the covariance matrix Double_t error(0.0); // set the value and error acp_.valueAndErrors(value,error); return acp_; } LauAbsCoeffSet* LauBelleCPCoeffSet::createClone(const TString& newName, CloneOption cloneOption, Double_t constFactor) { LauAbsCoeffSet* clone(0); if ( cloneOption == All || cloneOption == TiePhase || cloneOption == TieMagnitude || cloneOption == TieCPPars ) { clone = new LauBelleCPCoeffSet( *this, cloneOption, constFactor ); clone->name( newName ); } else { std::cerr << "ERROR in LauBelleCPCoeffSet::createClone : Invalid clone option" << std::endl; } return clone; } diff --git a/src/LauBelleNR.cc b/src/LauBelleNR.cc index 4d09f2d..b7f6c98 100644 --- a/src/LauBelleNR.cc +++ b/src/LauBelleNR.cc @@ -1,150 +1,149 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauBelleNR.cc \brief File containing implementation of LauBelleNR class. */ #include #include "TMath.h" #include "LauBelleNR.hh" #include "LauDaughters.hh" #include "LauParameter.hh" #include "LauResonanceInfo.hh" -ClassImp(LauBelleNR) LauBelleNR::LauBelleNR(LauResonanceInfo* resInfo, const LauAbsResonance::LauResonanceModel resType, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), alpha_(0), model_(resType), forceLegendre_(kTRUE) { TString parName = this->getSanitisedName(); parName += "_alpha"; alpha_ = resInfo->getExtraParameter( parName ); if ( alpha_ == 0 ) { alpha_ = new LauParameter( parName, 0.0, 0.0, 10.0, kTRUE ); alpha_->secondStage(kTRUE); resInfo->addExtraParameter( alpha_ ); } } LauBelleNR::~LauBelleNR() { } void LauBelleNR::initialise() { const LauDaughters* daughters = this->getDaughters(); Int_t resPairAmpInt = this->getPairInt(); if ( daughters->gotSymmetricalDP() && resPairAmpInt != 3 ) { std::cerr << "WARNING in LauBelleNR::initialise : Dalitz plot is symmetric - this lineshape is not appropriate." << std::endl; } if ( model_ != LauAbsResonance::BelleNR && model_ != LauAbsResonance::PowerLawNR ) { std::cerr << "WARNING in LauBelleNR::initialise : Unknown model requested, defaulting to exponential." << std::endl; model_ = LauAbsResonance::BelleNR; } // Make the spin term purely the Legendre polynomial of the cos(helicity angle) if ( forceLegendre_ ) { this->setSpinType( LauAbsResonance::Legendre ); } } LauComplex LauBelleNR::resAmp(Double_t mass, Double_t spinTerm) { Double_t magnitude(1.0); Double_t alpha = this->getAlpha(); if ( model_ == LauAbsResonance::BelleNR ) { magnitude = spinTerm * TMath::Exp(-alpha*mass*mass); } else if ( model_ == LauAbsResonance::PowerLawNR ) { magnitude = spinTerm * TMath::Power(mass*mass, -alpha); } LauComplex resAmplitude(magnitude, 0.0); return resAmplitude; } const std::vector& LauBelleNR::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixAlpha() ) { this->addFloatingParameter( alpha_ ); } return this->getParameters(); } void LauBelleNR::setResonanceParameter(const TString& name, const Double_t value) { // Set various parameters for the lineshape if (name == "alpha") { this->setAlpha(value); std::cout << "INFO in LauBelleNR::setResonanceParameter : Setting parameter alpha = " << this->getAlpha() << std::endl; } else { std::cerr << "WARNING in LauBelleNR::setResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } void LauBelleNR::floatResonanceParameter(const TString& name) { if (name == "alpha") { if ( alpha_->fixed() ) { alpha_->fixed( kFALSE ); this->addFloatingParameter( alpha_ ); } else { std::cerr << "WARNING in LauBelleNR::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else { std::cerr << "WARNING in LauBelleNR::fixResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } LauParameter* LauBelleNR::getResonanceParameter(const TString& name) { if (name == "alpha") { return alpha_; } else { std::cerr << "WARNING in LauBelleNR::getResonanceParameter: Parameter name not reconised." << std::endl; return 0; } } void LauBelleNR::setAlpha(const Double_t alpha) { alpha_->value( alpha ); alpha_->genValue( alpha ); alpha_->initValue( alpha ); } diff --git a/src/LauBelleSymNR.cc b/src/LauBelleSymNR.cc index a862bc6..6f26bf9 100644 --- a/src/LauBelleSymNR.cc +++ b/src/LauBelleSymNR.cc @@ -1,187 +1,186 @@ /* Copyright 2013 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauBelleSymNR.cc \brief File containing implementation of LauBelleSymNR class. */ #include #include "TMath.h" #include "LauBelleSymNR.hh" #include "LauDaughters.hh" #include "LauKinematics.hh" #include "LauResonanceInfo.hh" -ClassImp(LauBelleSymNR) LauBelleSymNR::LauBelleSymNR(LauResonanceInfo* resInfo, const LauAbsResonance::LauResonanceModel resType, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), alpha_(0), model_(resType) { TString parName = this->getSanitisedName(); parName += "_alpha"; alpha_ = resInfo->getExtraParameter( parName ); if ( alpha_ == 0 ) { alpha_ = new LauParameter( parName, 0.0, 0.0, 10.0, kTRUE ); alpha_->secondStage(kTRUE); resInfo->addExtraParameter( alpha_ ); } } LauBelleSymNR::~LauBelleSymNR() { } void LauBelleSymNR::initialise() { const LauDaughters* daughters = this->getDaughters(); if ( ! daughters->gotSymmetricalDP() ) { std::cerr << "WARNING in LauBelleSymNR::initialise : Dalitz plot is symmetric - this lineshape is not appropriate." << std::endl; } Int_t resPairAmpInt = this->getPairInt(); if ( resPairAmpInt == 3 ) { std::cerr << "WARNING in LauBelleSymNR::initialise : This lineshape is intended to be on the symmetrised axes of the DP." << std::endl; } if ( (model_ != LauAbsResonance::BelleSymNR) && (model_ != LauAbsResonance::BelleSymNRNoInter) && (model_ != LauAbsResonance::TaylorNR) ) { std::cerr << "WARNING in LauBelleSymNR::initialise : Unknown model requested, defaulting to exponential." << std::endl; model_ = LauAbsResonance::BelleSymNR; } if ( (model_ != LauAbsResonance::BelleSymNRNoInter) && (this->getSpin() != 0) ) { std::cerr << "WARNING in LauBelleSymNR::initialise : Non-zero spin will be ignored for this model - perhaps you should use LauAbsResonance::BelleSymNRNoInter instead" << std::endl; } // NB we do not need to call setSpinType(LauAbsResonance::Legendre) here (as is done in LauBelleNR) since override the amplitude method and explicitly use calcLegendrePoly } LauComplex LauBelleSymNR::amplitude(const LauKinematics* kinematics) { // This function returns the complex dynamical amplitude for a Belle Non-Resonant distribution // Calculate for symmetric DPs, e.g. 3pi or 3K, by using shapeNo = 1 or 2 // Have s<->t symmetry already done in Dynamics flip function. // For Kpipi or similar plots, one can use the separate exponentials // and consider them as two separate components with their own mag and phase. // For this shapeNo = 3 and shapeNo = 4 need to be used to create the two // individual amplitudes (with the same value of alpha). // Calculate Mandelstam variables. // s = m_13^2, t = m_23^2 const Double_t s = kinematics->getm13Sq(); const Double_t t = kinematics->getm23Sq(); Double_t magnitude(1.0); const Double_t alpha = this->getAlpha(); if ( model_ == LauAbsResonance::BelleSymNR ) { magnitude = TMath::Exp(-alpha*s) + TMath::Exp(-alpha*t); } else if ( model_ == LauAbsResonance::BelleSymNRNoInter ) { magnitude = (s <= t) ? TMath::Exp(-alpha*s) : TMath::Exp(-alpha*t); const Double_t cosHel = (s <= t) ? kinematics->getc13() : kinematics->getc23(); magnitude *= this->calcLegendrePoly( cosHel ); } else if ( model_ == LauAbsResonance::TaylorNR ) { const Double_t mParentSq = kinematics->getmParentSq(); magnitude = alpha*(s + t)/mParentSq + 1.0; } LauComplex resAmplitude(magnitude, 0.0); return resAmplitude; } LauComplex LauBelleSymNR::resAmp(Double_t mass, Double_t spinTerm) { std::cerr << "ERROR in LauBelleSymNR : This method should never be called." << std::endl; std::cerr << " : Returning zero amplitude for mass = " << mass << " and spinTerm = " << spinTerm << "." << std::endl; return LauComplex(0.0, 0.0); } const std::vector& LauBelleSymNR::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixAlpha() ) { this->addFloatingParameter( alpha_ ); } return this->getParameters(); } void LauBelleSymNR::setResonanceParameter(const TString& name, const Double_t value) { // Set various parameters for the lineshape if (name == "alpha") { this->setAlpha(value); std::cout << "INFO in LauBelleSymNR::setResonanceParameter : Setting parameter alpha = " << this->getAlpha() << std::endl; } else { std::cerr << "WARNING in LauBelleSymNR::setResonanceParameter : Parameter name not reconised. No parameter changes made." << std::endl; } } void LauBelleSymNR::floatResonanceParameter(const TString& name) { if (name == "alpha") { if ( alpha_->fixed() ) { alpha_->fixed( kFALSE ); this->addFloatingParameter( alpha_ ); } else { std::cerr << "WARNING in LauBelleSymNR::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else { std::cerr << "WARNING in LauBelleSymNR::fixResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } LauParameter* LauBelleSymNR::getResonanceParameter(const TString& name) { if (name == "alpha") { return alpha_; } else { std::cerr << "WARNING in LauBelleSymNR::getResonanceParameter: Parameter name not reconised." << std::endl; return 0; } } void LauBelleSymNR::setAlpha(const Double_t alpha) { alpha_->value( alpha ); alpha_->genValue( alpha ); alpha_->initValue( alpha ); } diff --git a/src/LauBifurcatedGaussPdf.cc b/src/LauBifurcatedGaussPdf.cc index 9d51c99..340e492 100644 --- a/src/LauBifurcatedGaussPdf.cc +++ b/src/LauBifurcatedGaussPdf.cc @@ -1,165 +1,164 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauBifurcatedGaussPdf.cc \brief File containing implementation of LauBifurcatedGaussPdf class. */ #include #include #include "TMath.h" #include "TSystem.h" #include "LauBifurcatedGaussPdf.hh" #include "LauConstants.hh" -ClassImp(LauBifurcatedGaussPdf) LauBifurcatedGaussPdf::LauBifurcatedGaussPdf(const TString& theVarName, const std::vector& params, Double_t minAbscissa, Double_t maxAbscissa) : LauAbsPdf(theVarName, params, minAbscissa, maxAbscissa), mean_(0), sigmaL_(0), sigmaR_(0) { // Constructor for the bifurcated Gaussian PDF. // The bifurcated Gaussian combines the left half of a // Gaussian with resolution sigmaL with the right half // of a Gaussian with resolution sigmaR, both having // a common mean (or more correctly, peak position). // NB the parameters in params are the mean, sigmaL and sigmaR // The last two arguments specify the range in which the PDF is defined, and the PDF // will be normalised w.r.t. these limits. mean_ = this->findParameter("mean"); sigmaL_ = this->findParameter("sigmaL"); sigmaR_ = this->findParameter("sigmaR"); if ((this->nParameters() != 3) || (mean_ == 0) || (sigmaL_ == 0) || (sigmaR_ == 0) ) { std::cerr << "ERROR in LauBifurcatedGaussPdf constructor: LauBifurcatedGaussPdf requires 3 parameters: \"mean\", \"sigmaL\" and \"sigmaR\"." << std::endl; gSystem->Exit(EXIT_FAILURE); } // Cache the normalisation factor this->calcNorm(); } LauBifurcatedGaussPdf::~LauBifurcatedGaussPdf() { // Destructor } void LauBifurcatedGaussPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Get our abscissa Double_t abscissa = abscissas[0]; // Get the up to date parameter values Double_t mean = mean_->unblindValue(); Double_t sigmaL = sigmaL_->unblindValue(); Double_t sigmaR = sigmaR_->unblindValue(); // Evaluate the Birfucated Gaussian PDF value Double_t arg = abscissa - mean; Double_t coef(0.0); Double_t value(0.0); if (arg < 0.0){ if (TMath::Abs(sigmaL) > 1e-30) { coef = -0.5/(sigmaL*sigmaL); } } else { if (TMath::Abs(sigmaR) > 1e-30) { coef = -0.5/(sigmaR*sigmaR); } } value = TMath::Exp(coef*arg*arg); // Calculate the norm Double_t xscaleL = LauConstants::root2*sigmaL; Double_t xscaleR = LauConstants::root2*sigmaR; Double_t integral(0.0); Double_t norm(0.0); Double_t result(0.0); if(this->getMaxAbscissa() < mean){ integral = sigmaL * ( TMath::Erf((this->getMaxAbscissa() - mean)/xscaleL) - TMath::Erf((this->getMinAbscissa() - mean)/xscaleL)); }else if (this->getMinAbscissa() > mean){ integral = sigmaR * (TMath::Erf((this->getMaxAbscissa() - mean)/xscaleR) - TMath::Erf((this->getMinAbscissa() - mean)/xscaleR)); }else{ integral = sigmaR*TMath::Erf((this->getMaxAbscissa() -mean)/xscaleR) - sigmaL*TMath::Erf((this->getMinAbscissa() - mean)/xscaleL); } norm = LauConstants::rootPiBy2*integral; // the result result = value/norm; this->setUnNormPDFVal(result); } void LauBifurcatedGaussPdf::calcNorm() { // Nothing to do here, since it already normalized this->setNorm(1.0); } void LauBifurcatedGaussPdf::calcPDFHeight( const LauKinematics* /*kinematics*/ ) { if (this->heightUpToDate()) { return; } // Get the up to date parameter values Double_t mean = mean_->unblindValue(); LauAbscissas maxPoint(1); maxPoint[0] = mean; // Calculate the PDF height for the Bifurcated Gaussian function. if (mean>this->getMaxAbscissa()) { maxPoint[0] = this->getMaxAbscissa(); } else if (meangetMinAbscissa()) { maxPoint[0] = this->getMinAbscissa(); } this->calcLikelihoodInfo(maxPoint); Double_t height = this->getUnNormLikelihood(); this->setMaxHeight(height); } diff --git a/src/LauBkgndDPModel.cc b/src/LauBkgndDPModel.cc index 4730d4c..6cf2ffa 100644 --- a/src/LauBkgndDPModel.cc +++ b/src/LauBkgndDPModel.cc @@ -1,306 +1,305 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauBkgndDPModel.cc \brief File containing implementation of LauBkgndDPModel class. */ #include #include #include "TRandom.h" #include "TSystem.h" #include "Lau2DHistDPPdf.hh" #include "Lau2DSplineDPPdf.hh" #include "LauBkgndDPModel.hh" #include "LauDaughters.hh" #include "LauFitDataTree.hh" #include "LauKinematics.hh" #include "LauRandom.hh" #include "LauVetoes.hh" -ClassImp(LauBkgndDPModel) LauBkgndDPModel::LauBkgndDPModel(LauDaughters* daughters, LauVetoes* vetoes) : LauAbsBkgndDPModel(daughters, vetoes), symmetricalDP_(kFALSE), squareDP_(kFALSE), bgHistDPPdf_(0), curEvtHistVal_(0.0), maxPdfHeight_(1.0), pdfNorm_(1.0), doneGenWarning_(kFALSE), lowBinWarningIssued_(kFALSE) { if (daughters != 0) { symmetricalDP_ = daughters->gotSymmetricalDP(); } } LauBkgndDPModel::~LauBkgndDPModel() { if (bgHistDPPdf_ != 0) { delete bgHistDPPdf_; bgHistDPPdf_ = 0; } } void LauBkgndDPModel::setBkgndHisto(const TH2* histo, Bool_t useInterpolation, Bool_t fluctuateBins, Bool_t useUpperHalfOnly, Bool_t squareDP) { if ( ! histo ) { std::cerr << "WARNING in LauBkgndDPModel::setBkgndHisto : Supplied background histogram pointer is null, likelihood for this component will be flat in the Dalitz plot" << std::endl; } Bool_t upperHalf = kFALSE; if (symmetricalDP_ == kTRUE && useUpperHalfOnly == kTRUE) {upperHalf = kTRUE;} std::cout<<"INFO in LauBkgndDPModel::setBkgndHisto : Background histogram has upperHalf = "<(upperHalf)<getKinematics(); const LauVetoes* vetoes = this->getVetoes(); bgHistDPPdf_ = new Lau2DHistDPPdf(histo, kinematics, vetoes, useInterpolation, fluctuateBins, upperHalf, squareDP); maxPdfHeight_ = bgHistDPPdf_->getMaxHeight(); pdfNorm_ = bgHistDPPdf_->getHistNorm(); } void LauBkgndDPModel::setBkgndSpline(const TH2* histo, Bool_t fluctuateBins, Bool_t useUpperHalfOnly, Bool_t squareDP) { if ( ! histo ) { std::cerr << "WARNING in LauBkgndDPModel::setBkgndSpline : Supplied background histogram pointer is null, construction of spline will fail" << std::endl; } Bool_t upperHalf = kFALSE; if (symmetricalDP_ == kTRUE && useUpperHalfOnly == kTRUE) {upperHalf = kTRUE;} std::cout<<"INFO in LauBkgndDPModel::setBkgndSpline : Background histogram has upperHalf = "<(upperHalf)<getKinematics(); const LauVetoes* vetoes = this->getVetoes(); bgHistDPPdf_ = new Lau2DSplineDPPdf(histo, kinematics, vetoes, fluctuateBins, upperHalf, squareDP); maxPdfHeight_ = bgHistDPPdf_->getMaxHeight(); pdfNorm_ = bgHistDPPdf_->getHistNorm(); } Double_t LauBkgndDPModel::calcHistValue(Double_t xVal, Double_t yVal) { // Get the likelihood value of the background in the Dalitz plot. // Check that we have a valid histogram PDF if (bgHistDPPdf_ == 0) { std::cerr << "WARNING in LauBkgndDPModel::calcHistValue : We don't have a histogram so assuming the likelihood is flat in the Dalitz plot." << std::endl; this->setBkgndHisto( 0, kFALSE, kFALSE, kFALSE, kFALSE ); } // Find out the un-normalised PDF value Double_t value = bgHistDPPdf_->interpolateXY(xVal, yVal); // Check that the value is greater than zero // If we're using a spline then negative values can be caused by adjacent bins that all contain a value of zero. // The spline requires the value, its first derivatives and the mixed second derivative to be continuous and to match the input histogram // at the bin centres. Derivatives are calculated using a finite difference approximation taking the difference between the neighbouring bins. // If two bins are zero but the third is not then the second bin will have a positive first derivative causing the spline to dip below zero // between the two zero bins to remain smooth. Such dips are unavoidable but are correctly removed here. if ( value < 0.0 ) { if(!lowBinWarningIssued_) { std::cerr << "WARNING in LauBkgndDPModel::calcHistValue : Value " << value << " is less than 0 - setting to 0. You may want to check your histogram!" << std::endl << " : If you are using a spline then this could be caused by adjacent empty bins. Further warnings will be suppressed." << std::endl; lowBinWarningIssued_=kTRUE; } return 0.0; } LauKinematics* kinematics = this->getKinematics(); // For square DP co-ordinates, need to divide by Jacobian if (squareDP_ == kTRUE) { // Make sure that square DP kinematics are correct, then get Jacobian kinematics->updateSqDPKinematics(xVal, yVal); Double_t jacobian = kinematics->calcSqDPJacobian(); value /= jacobian; } return value; } void LauBkgndDPModel::initialise() { } Bool_t LauBkgndDPModel::generate() { // Routine to generate the background, using data provided by an // already defined histogram. LauKinematics* kinematics = this->getKinematics(); Bool_t gotBG(kFALSE); while (gotBG == kFALSE) { if (squareDP_ == kTRUE) { // Generate a point in m', theta' space. By construction, this point // is already within the DP region. Double_t mPrime(0.0), thetaPrime(0.0); kinematics->genFlatSqDP(mPrime, thetaPrime); // If we're in a symmetrical DP then we should only generate events in one half if ( symmetricalDP_ && thetaPrime > 0.5 ) { thetaPrime = 1.0 - thetaPrime; } // Calculate histogram height for DP point and // compare with the maximum height if ( bgHistDPPdf_ != 0 ) { Double_t bgContDP = bgHistDPPdf_->interpolateXY(mPrime, thetaPrime)/maxPdfHeight_; if (LauRandom::randomFun()->Rndm() < bgContDP) { kinematics->updateSqDPKinematics(mPrime, thetaPrime); gotBG = kTRUE; } } else { if ( !doneGenWarning_ ) { std::cerr << "WARNING in LauBkgndDPModel::generate : We don't have a histogram so generating flat in the square DP, which won't be flat in the conventional DP!" << std::endl; std::cerr << "WARNING in LauBkgndDPModel::generate : This should never happen!! What have you done?!" << std::endl; doneGenWarning_ = kTRUE; } kinematics->updateSqDPKinematics(mPrime, thetaPrime); gotBG = kTRUE; } } else { // Generate a point in the Dalitz plot (phase-space). Double_t m13Sq(0.0), m23Sq(0.0); kinematics->genFlatPhaseSpace(m13Sq, m23Sq); // If we're in a symmetrical DP then we should only generate events in one half if ( symmetricalDP_ && m13Sq > m23Sq ) { Double_t tmpSq = m13Sq; m13Sq = m23Sq; m23Sq = tmpSq; } // Calculate histogram height for DP point and // compare with the maximum height if ( bgHistDPPdf_ != 0 ) { Double_t bgContDP = bgHistDPPdf_->interpolateXY(m13Sq, m23Sq)/maxPdfHeight_; if (LauRandom::randomFun()->Rndm() < bgContDP) { kinematics->updateKinematics(m13Sq, m23Sq); gotBG = kTRUE; } } else { if ( !doneGenWarning_ ) { std::cerr << "WARNING in LauBkgndDPModel::generate : We don't have a histogram so generating flat in the DP." << std::endl; doneGenWarning_ = kTRUE; } kinematics->updateKinematics(m13Sq, m23Sq); gotBG = kTRUE; } } } // Implement veto Bool_t vetoOK(kTRUE); const LauVetoes* vetoes = this->getVetoes(); if (vetoes) { vetoOK = vetoes->passVeto(kinematics); } // Call this function recusively until we pass the veto. if (vetoOK == kFALSE) { this->generate(); } return kTRUE; } void LauBkgndDPModel::fillDataTree(const LauFitDataTree& inputFitTree) { // In LauFitDataTree, the first two variables should always be // m13^2 and m23^2. Other variables follow thus: charge. Int_t nBranches = inputFitTree.nBranches(); if (nBranches < 2) { std::cerr<<"ERROR in LauBkgndDPModel::fillDataTree : Expecting at least 2 variables "<<"in input data tree, but there are "<getKinematics(); // clear and resize the data vector bgData_.clear(); bgData_.resize(nEvents); for (UInt_t iEvt = 0; iEvt < nEvents; iEvt++) { const LauFitData& dataValues = inputFitTree.getData(iEvt); LauFitData::const_iterator iter = dataValues.find("m13Sq"); m13Sq = iter->second; iter = dataValues.find("m23Sq"); m23Sq = iter->second; // Update the kinematics. This will also update m' and theta' if squareDP = true kinematics->updateKinematics(m13Sq, m23Sq); if (squareDP_ == kTRUE) { mPrime = kinematics->getmPrime(); thetaPrime = kinematics->getThetaPrime(); curEvtHistVal_ = this->calcHistValue(mPrime, thetaPrime); } else { curEvtHistVal_ = this->calcHistValue(m13Sq, m23Sq); } bgData_[iEvt] = curEvtHistVal_; } } Double_t LauBkgndDPModel::getUnNormValue(UInt_t iEvt) { // Retrieve the likelihood for the given event this->setDataEventNo(iEvt); return curEvtHistVal_; } Double_t LauBkgndDPModel::getLikelihood(UInt_t iEvt) { // Retrieve the likelihood for the given event this->setDataEventNo(iEvt); Double_t llhd = curEvtHistVal_ / this->getPdfNorm(); return llhd; } void LauBkgndDPModel::setDataEventNo(UInt_t iEvt) { // Retrieve the data for event iEvt if (bgData_.size() > iEvt) { curEvtHistVal_ = bgData_[iEvt]; } else { std::cerr<<"ERROR in LauBkgndDPModel::setDataEventNo : Event index too large: "<= "< #include "TMath.h" #include "LauBlattWeisskopfFactor.hh" #include "LauParameter.hh" #include "LauResonanceInfo.hh" -ClassImp(LauBlattWeisskopfFactor) // Constructor LauBlattWeisskopfFactor::LauBlattWeisskopfFactor( const LauResonanceInfo& resInfo, const BarrierType barrierType, const RestFrame restFrame, const BlattWeisskopfCategory category ) : spin_(resInfo.getSpin()), radius_(new LauParameter("NEED_A_GOOD_NAME",resInfo.getBWRadius(),0.0,10.0,kTRUE)), barrierType_(barrierType), restFrame_(restFrame) { TString categoryName = this->setRadiusName( resInfo, category ); std::cout << "INFO in LauBlattWeisskopfFactor constructor : creating radius parameter for category \"" << categoryName << "\", with initial value " << resInfo.getBWRadius() << std::endl; } LauBlattWeisskopfFactor::LauBlattWeisskopfFactor( const LauResonanceInfo& resInfo, const Double_t resRadius, const BarrierType barrierType, const RestFrame restFrame, const BlattWeisskopfCategory category ) : spin_(resInfo.getSpin()), radius_(new LauParameter("NEED_A_GOOD_NAME",resRadius,0.0,10.0,kTRUE)), barrierType_(barrierType), restFrame_(restFrame) { TString categoryName = this->setRadiusName( resInfo, category ); std::cout << "INFO in LauBlattWeisskopfFactor constructor : creating radius parameter for category \"" << categoryName << "\", with initial value " << resRadius << std::endl; } LauBlattWeisskopfFactor::~LauBlattWeisskopfFactor() { } LauBlattWeisskopfFactor::LauBlattWeisskopfFactor( const LauBlattWeisskopfFactor& other, const UInt_t newSpin ) : spin_(newSpin), radius_(other.radius_->createClone()), barrierType_(other.barrierType_), restFrame_(other.restFrame_) { } TString LauBlattWeisskopfFactor::setRadiusName( const LauResonanceInfo& resInfo, const BlattWeisskopfCategory category ) { TString name = "BarrierRadius_"; TString categoryName; switch (category) { case Parent : categoryName = "Parent"; break; case Indep : categoryName = resInfo.getSanitisedName(); break; case Light : categoryName = "Light"; break; case Kstar : categoryName = "Kstar"; break; case Charm : categoryName = "Charm"; break; case StrangeCharm : categoryName = "StrangeCharm"; break; case Charmonium : categoryName = "Charmonium"; break; case Beauty : categoryName = "Beauty"; break; case StrangeBeauty : categoryName = "StrangeBeauty"; break; case CharmBeauty : categoryName = "CharmBeauty"; break; case Custom1 : categoryName = "Custom1"; break; case Custom2 : categoryName = "Custom2"; break; case Custom3 : categoryName = "Custom3"; break; case Custom4 : categoryName = "Custom4"; break; default : categoryName = "Unknown"; break; } name.Append(categoryName); radius_->name(name); return categoryName; } LauBlattWeisskopfFactor* LauBlattWeisskopfFactor::createClone( const UInt_t newSpin ) { LauBlattWeisskopfFactor* clone = new LauBlattWeisskopfFactor( *this, newSpin ); return clone; } Double_t LauBlattWeisskopfFactor::calcFormFactor( const Double_t p ) const { // Calculate the requested form factor for the resonance, given the momentum value Double_t fFactor(1.0); // For scalars the form factor is always unity // TODO: and we currently don't have formulae for spin > 5 if ( (spin_ == 0) || (spin_ > 5) ) { return fFactor; } const Double_t radius = radius_->unblindValue(); const Double_t z = radius*radius*p*p; if ( barrierType_ == BWBarrier ) { if (spin_ == 1) { fFactor = TMath::Sqrt(2.0*z/(z + 1.0)); } else if (spin_ == 2) { fFactor = TMath::Sqrt(13.0*z*z/(z*z + 3.0*z + 9.0)); } else if (spin_ == 3) { fFactor = TMath::Sqrt(277.0*z*z*z/(z*z*z + 6.0*z*z + 45.0*z + 225.0)); } else if (spin_ == 4) { fFactor = TMath::Sqrt(12746.0*z*z*z*z/(z*z*z*z + 10.0*z*z*z + 135.0*z*z + 1575.0*z + 11025.0)); } else if (spin_ == 5) { fFactor = TMath::Sqrt(998881.0*z*z*z*z*z/(z*z*z*z*z + 15.0*z*z*z*z + 315.0*z*z*z + 6300.0*z*z + 99225.0*z + 893025.0)); } } else if ( barrierType_ == BWPrimeBarrier ) { if (spin_ == 1) { fFactor = TMath::Sqrt(1.0/(z + 1.0)); } else if (spin_ == 2) { fFactor = TMath::Sqrt(1.0/(z*z + 3.0*z + 9.0)); } else if (spin_ == 3) { fFactor = TMath::Sqrt(1.0/(z*z*z + 6.0*z*z + 45.0*z + 225.0)); } else if (spin_ == 4) { fFactor = TMath::Sqrt(1.0/(z*z*z*z + 10.0*z*z*z + 135.0*z*z + 1575.0*z + 11025.0)); } else if (spin_ == 5) { fFactor = TMath::Sqrt(1.0/(z*z*z*z*z + 15.0*z*z*z*z + 315.0*z*z*z + 6300.0*z*z + 99225.0*z + 893025.0)); } } else if ( barrierType_ == ExpBarrier ) { if (spin_ == 1) { fFactor = TMath::Exp( -TMath::Sqrt(z) ); } else if (spin_ == 2) { fFactor = TMath::Exp( -z ); } else if (spin_ == 3) { fFactor = TMath::Exp( -TMath::Sqrt(z*z*z) ); } else if (spin_ == 4) { fFactor = TMath::Exp( -z*z ); } else if (spin_ == 5) { fFactor = TMath::Exp( -TMath::Sqrt(z*z*z*z*z) ); } } return fFactor; } diff --git a/src/LauBlind.cc b/src/LauBlind.cc index 087e8dd..ecaa34e 100644 --- a/src/LauBlind.cc +++ b/src/LauBlind.cc @@ -1,71 +1,70 @@ /* Copyright 2015 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauBlind.cc \brief File containing implementation of LauBlind class. */ #include "LauBlind.hh" #include "TMath.h" #include "TRandom3.h" -ClassImp(LauBlind) LauBlind::LauBlind() : blindingString_(""), blindingWidth_(0.0), offset_(0.0) { } LauBlind::LauBlind(const TString& blindingStr, const Double_t width) : blindingString_(blindingStr), blindingWidth_(width), offset_(0.0) { this->calcOffset(); } LauBlind::LauBlind(const LauBlind& rhs) : blindingString_(rhs.blindingString_), blindingWidth_(rhs.blindingWidth_), offset_(rhs.offset_) { } LauBlind::~LauBlind() { } void LauBlind::calcOffset() { //hash the blinding string to obtain a seed TRandom3 r(TMath::Hash(blindingString_)); //offsets are Gaussian distributed with defined width offset_ = blindingWidth_ * r.Gaus(); } diff --git a/src/LauBreitWignerRes.cc b/src/LauBreitWignerRes.cc index 81d1543..892bccc 100644 --- a/src/LauBreitWignerRes.cc +++ b/src/LauBreitWignerRes.cc @@ -1,78 +1,77 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauBreitWignerRes.cc \brief File containing implementation of LauBreitWignerRes class. */ #include "LauBreitWignerRes.hh" -ClassImp(LauBreitWignerRes) LauBreitWignerRes::LauBreitWignerRes(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters) { } LauBreitWignerRes::~LauBreitWignerRes() { } void LauBreitWignerRes::initialise() { } LauComplex LauBreitWignerRes::resAmp(Double_t mass, Double_t spinTerm) { // This function returns the complex dynamical amplitude for a Breit-Wigner resonance, // given the invariant mass and cos(helicity) values. Double_t resMass = this->getMass(); Double_t deltaM = mass - resMass; Double_t resWidthO2 = 0.5 * this->getWidth(); Double_t resWidthO2Sq = resWidthO2*resWidthO2; LauComplex resAmplitude(deltaM, resWidthO2); resAmplitude.rescale(spinTerm/(deltaM*deltaM + resWidthO2Sq)); return resAmplitude; } const std::vector& LauBreitWignerRes::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixMass() ) { this->addFloatingParameter( this->getMassPar() ); } if ( ! this->fixWidth() ) { this->addFloatingParameter( this->getWidthPar() ); } return this->getParameters(); } diff --git a/src/LauCPFitModel.cc b/src/LauCPFitModel.cc index 15c01ca..75b303a 100644 --- a/src/LauCPFitModel.cc +++ b/src/LauCPFitModel.cc @@ -1,3440 +1,3439 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauCPFitModel.cc \brief File containing implementation of LauCPFitModel class. */ #include #include #include #include #include "TVirtualFitter.h" #include "TSystem.h" #include "TMinuit.h" #include "TRandom.h" #include "TFile.h" #include "TTree.h" #include "TBranch.h" #include "TLeaf.h" #include "TMath.h" #include "TH2.h" #include "TGraph2D.h" #include "TGraph.h" #include "TStyle.h" #include "TCanvas.h" #include "LauAbsBkgndDPModel.hh" #include "LauAbsCoeffSet.hh" #include "LauIsobarDynamics.hh" #include "LauAbsPdf.hh" #include "LauAsymmCalc.hh" #include "LauComplex.hh" #include "LauConstants.hh" #include "LauCPFitModel.hh" #include "LauDaughters.hh" #include "LauEffModel.hh" #include "LauEmbeddedData.hh" #include "LauFitNtuple.hh" #include "LauGenNtuple.hh" #include "LauKinematics.hh" #include "LauPrint.hh" #include "LauRandom.hh" #include "LauScfMap.hh" -ClassImp(LauCPFitModel) LauCPFitModel::LauCPFitModel(LauIsobarDynamics* negModel, LauIsobarDynamics* posModel, Bool_t tagged, const TString& tagVarName) : LauAbsFitModel(), negSigModel_(negModel), posSigModel_(posModel), negKinematics_(negModel ? negModel->getKinematics() : 0), posKinematics_(posModel ? posModel->getKinematics() : 0), usingBkgnd_(kFALSE), nSigComp_(0), nSigDPPar_(0), nExtraPdfPar_(0), nNormPar_(0), negMeanEff_("negMeanEff",0.0,0.0,1.0), posMeanEff_("posMeanEff",0.0,0.0,1.0), negDPRate_("negDPRate",0.0,0.0,100.0), posDPRate_("posDPRate",0.0,0.0,100.0), signalEvents_(0), signalAsym_(0), forceAsym_(kFALSE), tagged_(tagged), tagVarName_(tagVarName), curEvtCharge_(0), useSCF_(kFALSE), useSCFHist_(kFALSE), scfFrac_("scfFrac",0.0,0.0,1.0), scfFracHist_(0), scfMap_(0), compareFitData_(kFALSE), negParent_("B-"), posParent_("B+"), negSignalTree_(0), posSignalTree_(0), reuseSignal_(kFALSE), useNegReweighting_(kFALSE), usePosReweighting_(kFALSE), sigDPLike_(0.0), scfDPLike_(0.0), sigExtraLike_(0.0), scfExtraLike_(0.0), sigTotalLike_(0.0), scfTotalLike_(0.0) { const LauDaughters* negDaug = negSigModel_->getDaughters(); if (negDaug != 0) {negParent_ = negDaug->getNameParent();} const LauDaughters* posDaug = posSigModel_->getDaughters(); if (posDaug != 0) {posParent_ = posDaug->getNameParent();} } LauCPFitModel::~LauCPFitModel() { delete negSignalTree_; delete posSignalTree_; for (LauBkgndEmbDataList::iterator iter = negBkgndTree_.begin(); iter != negBkgndTree_.end(); ++iter) { delete (*iter); } for (LauBkgndEmbDataList::iterator iter = posBkgndTree_.begin(); iter != posBkgndTree_.end(); ++iter) { delete (*iter); } delete scfFracHist_; } void LauCPFitModel::setupBkgndVectors() { UInt_t nBkgnds = this->nBkgndClasses(); negBkgndDPModels_.resize( nBkgnds ); posBkgndDPModels_.resize( nBkgnds ); negBkgndPdfs_.resize( nBkgnds ); posBkgndPdfs_.resize( nBkgnds ); bkgndEvents_.resize( nBkgnds ); bkgndAsym_.resize( nBkgnds ); negBkgndTree_.resize( nBkgnds ); posBkgndTree_.resize( nBkgnds ); reuseBkgnd_.resize( nBkgnds ); bkgndDPLike_.resize( nBkgnds ); bkgndExtraLike_.resize( nBkgnds ); bkgndTotalLike_.resize( nBkgnds ); } void LauCPFitModel::setNSigEvents(LauParameter* nSigEvents) { if ( nSigEvents == 0 ) { std::cerr << "ERROR in LauCPFitModel::setNSigEvents : The LauParameter pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } if ( signalEvents_ != 0 ) { std::cerr << "ERROR in LauCPFitModel::setNSigEvents : You are trying to overwrite the signal yield." << std::endl; return; } if ( signalAsym_ != 0 ) { std::cerr << "ERROR in LauCPFitModel::setNSigEvents : You are trying to overwrite the signal asymmetry." << std::endl; return; } signalEvents_ = nSigEvents; TString name = signalEvents_->name(); if ( ! name.Contains("signalEvents") && !( name.BeginsWith("signal") && name.EndsWith("Events") ) ) { signalEvents_->name("signalEvents"); } Double_t value = nSigEvents->value(); signalEvents_->range(-2.0*(TMath::Abs(value)+1.0), 2.0*(TMath::Abs(value)+1.0)); signalAsym_ = new LauParameter("signalAsym",0.0,-1.0,1.0,kTRUE); } void LauCPFitModel::setNSigEvents( LauParameter* nSigEvents, LauParameter* sigAsym, Bool_t forceAsym ) { if ( nSigEvents == 0 ) { std::cerr << "ERROR in LauCPFitModel::setNSigEvents : The event LauParameter pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } if ( sigAsym == 0 ) { std::cerr << "ERROR in LauCPFitModel::setNSigEvents : The asym LauParameter pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } if ( signalEvents_ != 0 ) { std::cerr << "ERROR in LauCPFitModel::setNSigEvents : You are trying to overwrite the signal yield." << std::endl; return; } if ( signalAsym_ != 0 ) { std::cerr << "ERROR in LauCPFitModel::setNSigEvents : You are trying to overwrite the signal asymmetry." << std::endl; return; } signalEvents_ = nSigEvents; signalEvents_->name("signalEvents"); Double_t value = nSigEvents->value(); signalEvents_->range(-2.0*(TMath::Abs(value)+1.0), 2.0*(TMath::Abs(value)+1.0)); signalAsym_ = sigAsym; signalAsym_->name("signalAsym"); signalAsym_->range(-1.0,1.0); forceAsym_ = forceAsym; } void LauCPFitModel::setNBkgndEvents( LauAbsRValue* nBkgndEvents ) { if ( nBkgndEvents == 0 ) { std::cerr << "ERROR in LauCPFitModel::setNBgkndEvents : The background yield LauParameter pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } if ( ! this->validBkgndClass( nBkgndEvents->name() ) ) { std::cerr << "ERROR in LauCPFitModel::setNBkgndEvents : Invalid background class \"" << nBkgndEvents->name() << "\"." << std::endl; std::cerr << " : Background class names must be provided in \"setBkgndClassNames\" before any other background-related actions can be performed." << std::endl; gSystem->Exit(EXIT_FAILURE); } UInt_t bkgndID = this->bkgndClassID( nBkgndEvents->name() ); if ( bkgndEvents_[bkgndID] != 0 ) { std::cerr << "ERROR in LauCPFitModel::setNBkgndEvents : You are trying to overwrite the background yield." << std::endl; return; } if ( bkgndAsym_[bkgndID] != 0 ) { std::cerr << "ERROR in LauCPFitModel::setNBkgndEvents : You are trying to overwrite the background asymmetry." << std::endl; return; } nBkgndEvents->name( nBkgndEvents->name()+"Events" ); if ( nBkgndEvents->isLValue() ) { Double_t value = nBkgndEvents->value(); LauParameter* yield = dynamic_cast( nBkgndEvents ); yield->range(-2.0*(TMath::Abs(value)+1.0), 2.0*(TMath::Abs(value)+1.0)); } bkgndEvents_[bkgndID] = nBkgndEvents; bkgndAsym_[bkgndID] = new LauParameter(nBkgndEvents->name()+"Asym",0.0,-1.0,1.0,kTRUE); } void LauCPFitModel::setNBkgndEvents(LauAbsRValue* nBkgndEvents, LauAbsRValue* bkgndAsym) { if ( nBkgndEvents == 0 ) { std::cerr << "ERROR in LauCPFitModel::setNBkgndEvents : The background yield LauParameter pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } if ( bkgndAsym == 0 ) { std::cerr << "ERROR in LauCPFitModel::setNBkgndEvents : The background asym LauParameter pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } if ( ! this->validBkgndClass( nBkgndEvents->name() ) ) { std::cerr << "ERROR in LauCPFitModel::setNBkgndEvents : Invalid background class \"" << nBkgndEvents->name() << "\"." << std::endl; std::cerr << " : Background class names must be provided in \"setBkgndClassNames\" before any other background-related actions can be performed." << std::endl; gSystem->Exit(EXIT_FAILURE); } UInt_t bkgndID = this->bkgndClassID( nBkgndEvents->name() ); if ( bkgndEvents_[bkgndID] != 0 ) { std::cerr << "ERROR in LauCPFitModel::setNBkgndEvents : You are trying to overwrite the background yield." << std::endl; return; } if ( bkgndAsym_[bkgndID] != 0 ) { std::cerr << "ERROR in LauCPFitModel::setNBkgndEvents : You are trying to overwrite the background asymmetry." << std::endl; return; } nBkgndEvents->name( nBkgndEvents->name()+"Events" ); if ( nBkgndEvents->isLValue() ) { Double_t value = nBkgndEvents->value(); LauParameter* yield = dynamic_cast( nBkgndEvents ); yield->range(-2.0*(TMath::Abs(value)+1.0), 2.0*(TMath::Abs(value)+1.0)); } bkgndEvents_[bkgndID] = nBkgndEvents; bkgndAsym->name( nBkgndEvents->name()+"Asym" ); if ( bkgndAsym->isLValue() ) { LauParameter* asym = dynamic_cast( bkgndAsym ); asym->range(-1.0, 1.0); } bkgndAsym_[bkgndID] = bkgndAsym; } void LauCPFitModel::splitSignalComponent( const TH2* dpHisto, const Bool_t upperHalf, const Bool_t fluctuateBins, LauScfMap* scfMap ) { if ( useSCF_ == kTRUE ) { std::cerr << "ERROR in LauCPFitModel::splitSignalComponent : Have already setup SCF." << std::endl; return; } if ( dpHisto == 0 ) { std::cerr << "ERROR in LauCPFitModel::splitSignalComponent : The histogram pointer is null." << std::endl; return; } const LauDaughters* daughters = negSigModel_->getDaughters(); scfFracHist_ = new LauEffModel( daughters, 0 ); scfFracHist_->setEffHisto( dpHisto, kTRUE, fluctuateBins, 0.0, 0.0, upperHalf, daughters->squareDP() ); scfMap_ = scfMap; useSCF_ = kTRUE; useSCFHist_ = kTRUE; } void LauCPFitModel::splitSignalComponent( const Double_t scfFrac, const Bool_t fixed ) { if ( useSCF_ == kTRUE ) { std::cerr << "ERROR in LauCPFitModel::splitSignalComponent : Have already setup SCF." << std::endl; return; } scfFrac_.range( 0.0, 1.0 ); scfFrac_.value( scfFrac ); scfFrac_.initValue( scfFrac ); scfFrac_.genValue( scfFrac ); scfFrac_.fixed( fixed ); useSCF_ = kTRUE; useSCFHist_ = kFALSE; } void LauCPFitModel::setBkgndDPModels(const TString& bkgndClass, LauAbsBkgndDPModel* negModel, LauAbsBkgndDPModel* posModel) { if ((negModel==0) || (posModel==0)) { std::cerr << "ERROR in LauCPFitModel::setBkgndDPModels : One or both of the model pointers is null." << std::endl; return; } // check that this background name is valid if ( ! this->validBkgndClass( bkgndClass) ) { std::cerr << "ERROR in LauCPFitModel::setBkgndDPModel : Invalid background class \"" << bkgndClass << "\"." << std::endl; std::cerr << " : Background class names must be provided in \"setBkgndClassNames\" before any other background-related actions can be performed." << std::endl; return; } UInt_t bkgndID = this->bkgndClassID( bkgndClass ); negBkgndDPModels_[bkgndID] = negModel; posBkgndDPModels_[bkgndID] = posModel; usingBkgnd_ = kTRUE; } void LauCPFitModel::setSignalPdfs(LauAbsPdf* negPdf, LauAbsPdf* posPdf) { if ( tagged_ ) { if (negPdf==0 || posPdf==0) { std::cerr << "ERROR in LauCPFitModel::setSignalPdfs : One or both of the PDF pointers is null." << std::endl; return; } } else { // if we're doing an untagged analysis we will only use the negative PDFs if ( negPdf==0 ) { std::cerr << "ERROR in LauCPFitModel::setSignalPdfs : The negative PDF pointer is null." << std::endl; return; } if ( posPdf!=0 ) { std::cerr << "WARNING in LauCPFitModel::setSignalPdfs : Doing an untagged fit so will not use the positive PDF." << std::endl; } } negSignalPdfs_.push_back(negPdf); posSignalPdfs_.push_back(posPdf); } void LauCPFitModel::setSCFPdfs(LauAbsPdf* negPdf, LauAbsPdf* posPdf) { if ( tagged_ ) { if (negPdf==0 || posPdf==0) { std::cerr << "ERROR in LauCPFitModel::setSCFPdfs : One or both of the PDF pointers is null." << std::endl; return; } } else { // if we're doing an untagged analysis we will only use the negative PDFs if ( negPdf==0 ) { std::cerr << "ERROR in LauCPFitModel::setSCFPdfs : The negative PDF pointer is null." << std::endl; return; } if ( posPdf!=0 ) { std::cerr << "WARNING in LauCPFitModel::setSCFPdfs : Doing an untagged fit so will not use the positive PDF." << std::endl; } } negScfPdfs_.push_back(negPdf); posScfPdfs_.push_back(posPdf); } void LauCPFitModel::setBkgndPdfs(const TString& bkgndClass, LauAbsPdf* negPdf, LauAbsPdf* posPdf) { if ( tagged_ ) { if (negPdf==0 || posPdf==0) { std::cerr << "ERROR in LauCPFitModel::setBkgndPdfs : One or both of the PDF pointers is null." << std::endl; return; } } else { // if we're doing an untagged analysis we will only use the negative PDFs if ( negPdf==0 ) { std::cerr << "ERROR in LauCPFitModel::setBkgndPdfs : The negative PDF pointer is null." << std::endl; return; } if ( posPdf!=0 ) { std::cerr << "WARNING in LauCPFitModel::setBkgndPdfs : Doing an untagged fit so will not use the positive PDF." << std::endl; } } // check that this background name is valid if ( ! this->validBkgndClass( bkgndClass ) ) { std::cerr << "ERROR in LauCPFitModel::setBkgndPdfs : Invalid background class \"" << bkgndClass << "\"." << std::endl; std::cerr << " : Background class names must be provided in \"setBkgndClassNames\" before any other background-related actions can be performed." << std::endl; return; } UInt_t bkgndID = this->bkgndClassID( bkgndClass ); negBkgndPdfs_[bkgndID].push_back(negPdf); posBkgndPdfs_[bkgndID].push_back(posPdf); usingBkgnd_ = kTRUE; } void LauCPFitModel::setAmpCoeffSet(LauAbsCoeffSet* coeffSet) { // Resize the coeffPars vector if not already done if ( coeffPars_.empty() ) { const UInt_t nNegAmp = negSigModel_->getnTotAmp(); const UInt_t nPosAmp = posSigModel_->getnTotAmp(); if ( nNegAmp != nPosAmp ) { std::cerr << "ERROR in LauCPFitModel::setAmpCoeffSet : Unequal number of signal DP components in the negative and positive models: " << nNegAmp << " != " << nPosAmp << std::endl; gSystem->Exit(EXIT_FAILURE); } coeffPars_.resize( nNegAmp ); for (std::vector::iterator iter = coeffPars_.begin(); iter != coeffPars_.end(); ++iter) { (*iter) = 0; } fitFracAsymm_.resize( nNegAmp ); acp_.resize( nNegAmp ); } // Is there a component called compName in the signal model? TString compName(coeffSet->name()); TString conjName = negSigModel_->getConjResName(compName); const Int_t negIndex = negSigModel_->resonanceIndex(compName); const Int_t posIndex = posSigModel_->resonanceIndex(conjName); if ( negIndex < 0 ) { std::cerr << "ERROR in LauCPFitModel::setAmpCoeffSet : " << negParent_ << " signal DP model doesn't contain component \"" << compName << "\"." << std::endl; return; } if ( posIndex < 0 ) { std::cerr << "ERROR in LauCPFitModel::setAmpCoeffSet : " << posParent_ << " signal DP model doesn't contain component \"" << conjName << "\"." << std::endl; return; } if ( posIndex != negIndex ) { std::cerr << "ERROR in LauCPFitModel::setAmpCoeffSet : " << negParent_ << " signal DP model and " << posParent_ << " signal DP model have different indices for components \"" << compName << "\" and \"" << conjName << "\"." << std::endl; return; } // Do we already have it in our list of names? if ( coeffPars_[negIndex] != 0 && coeffPars_[negIndex]->name() == compName) { std::cerr << "ERROR in LauCPFitModel::setAmpCoeffSet : Have already set coefficients for \"" << compName << "\"." << std::endl; return; } coeffSet->index(negIndex); coeffPars_[negIndex] = coeffSet; TString parName = coeffSet->baseName(); parName += "FitFracAsym"; fitFracAsymm_[negIndex] = LauParameter(parName, 0.0, -1.0, 1.0); acp_[negIndex] = coeffSet->acp(); ++nSigComp_; std::cout << "INFO in LauCPFitModel::setAmpCoeffSet : Added coefficients for component \"" << compName << "\" to the fit model." << std::endl; coeffSet->printParValues(); } void LauCPFitModel::initialise() { // Initialisation if (!this->useDP() && negSignalPdfs_.empty()) { std::cerr << "ERROR in LauCPFitModel::initialise : Signal model doesn't exist for any variable." << std::endl; gSystem->Exit(EXIT_FAILURE); } if ( this->useDP() ) { // Check that we have all the Dalitz-plot models if ((negSigModel_ == 0) || (posSigModel_ == 0)) { std::cerr << "ERROR in LauCPFitModel::initialise : the pointer to one (neg or pos) of the signal DP models is null.\n"; std::cerr << " : Removing the Dalitz Plot from the model." << std::endl; this->useDP(kFALSE); } if ( usingBkgnd_ ) { if ( negBkgndDPModels_.empty() || posBkgndDPModels_.empty() ) { std::cerr << "ERROR in LauCPFitModel::initialise : No background DP models found.\n"; std::cerr << " : Removing the Dalitz plot from the model." << std::endl; this->useDP(kFALSE); } for (LauBkgndDPModelList::const_iterator dpmodel_iter = negBkgndDPModels_.begin(); dpmodel_iter != negBkgndDPModels_.end(); ++dpmodel_iter ) { if ( (*dpmodel_iter) == 0 ) { std::cerr << "ERROR in LauCPFitModel::initialise : The pointer to one of the background DP models is null.\n"; std::cerr << " : Removing the Dalitz Plot from the model." << std::endl; this->useDP(kFALSE); break; } } for (LauBkgndDPModelList::const_iterator dpmodel_iter = posBkgndDPModels_.begin(); dpmodel_iter != posBkgndDPModels_.end(); ++dpmodel_iter ) { if ( (*dpmodel_iter) == 0 ) { std::cerr << "ERROR in LauCPFitModel::initialise : The pointer to one of the background DP models is null.\n"; std::cerr << " : Removing the Dalitz Plot from the model." << std::endl; this->useDP(kFALSE); break; } } } // Need to check that the number of components we have and that the dynamics has matches up const UInt_t nNegAmp = negSigModel_->getnTotAmp(); const UInt_t nPosAmp = posSigModel_->getnTotAmp(); if ( nNegAmp != nPosAmp ) { std::cerr << "ERROR in LauCPFitModel::initialise : Unequal number of signal DP components in the negative and positive models: " << nNegAmp << " != " << nPosAmp << std::endl; gSystem->Exit(EXIT_FAILURE); } if ( nNegAmp != nSigComp_ ) { std::cerr << "ERROR in LauCPFitModel::initialise : Number of signal DP components in the model (" << nNegAmp << ") not equal to number of coefficients supplied (" << nSigComp_ << ")." << std::endl; gSystem->Exit(EXIT_FAILURE); } if ( !fixParamFileName_.IsNull() || !fixParamMap_.empty() ) { // Set coefficients std::vector params; for ( auto itr = coeffPars_.begin(); itr != coeffPars_.end(); ++itr ) { std::vector p = (*itr)->getParameters(); params.insert(params.end(), p.begin(), p.end()); } this->fixParams(params); // Set resonance parameters (if they exist) negSigModel_->collateResonanceParameters(); posSigModel_->collateResonanceParameters(); this->fixParams(negSigModel_->getFloatingParameters()); this->fixParams(posSigModel_->getFloatingParameters()); } // From the initial parameter values calculate the coefficients // so they can be passed to the signal model this->updateCoeffs(); // If all is well, go ahead and initialise them this->initialiseDPModels(); } // Next check that, if a given component is being used we've got the // right number of PDFs for all the variables involved // TODO - should probably check variable names and so on as well UInt_t nsigpdfvars(0); for ( LauPdfList::const_iterator pdf_iter = negSignalPdfs_.begin(); pdf_iter != negSignalPdfs_.end(); ++pdf_iter ) { std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { ++nsigpdfvars; } } } if (useSCF_) { UInt_t nscfpdfvars(0); for ( LauPdfList::const_iterator pdf_iter = negScfPdfs_.begin(); pdf_iter != negScfPdfs_.end(); ++pdf_iter ) { std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { ++nscfpdfvars; } } } if (nscfpdfvars != nsigpdfvars) { std::cerr << "ERROR in LauCPFitModel::initialise : There are " << nsigpdfvars << " TM signal PDF variables but " << nscfpdfvars << " SCF signal PDF variables." << std::endl; gSystem->Exit(EXIT_FAILURE); } } if (usingBkgnd_) { for (LauBkgndPdfsList::const_iterator bgclass_iter = negBkgndPdfs_.begin(); bgclass_iter != negBkgndPdfs_.end(); ++bgclass_iter) { UInt_t nbkgndpdfvars(0); const LauPdfList& pdfList = (*bgclass_iter); for ( LauPdfList::const_iterator pdf_iter = pdfList.begin(); pdf_iter != pdfList.end(); ++pdf_iter ) { std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { ++nbkgndpdfvars; } } } if (nbkgndpdfvars != nsigpdfvars) { std::cerr << "ERROR in LauCPFitModel::initialise : There are " << nsigpdfvars << " signal PDF variables but " << nbkgndpdfvars << " bkgnd PDF variables." << std::endl; gSystem->Exit(EXIT_FAILURE); } } } // Clear the vectors of parameter information so we can start from scratch this->clearFitParVectors(); // Set the fit parameters for signal and background models this->setSignalDPParameters(); // Set the fit parameters for the various extra PDFs this->setExtraPdfParameters(); // Set the initial bg and signal events this->setFitNEvents(); // Check that we have the expected number of fit variables const LauParameterPList& fitVars = this->fitPars(); if (fitVars.size() != (nSigDPPar_ + nExtraPdfPar_ + nNormPar_)) { std::cerr << "ERROR in LauCPFitModel::initialise : Number of fit parameters not of expected size. Exiting" << std::endl; gSystem->Exit(EXIT_FAILURE); } this->setExtraNtupleVars(); } void LauCPFitModel::recalculateNormalisation() { //std::cout << "INFO in LauCPFitModel::recalculateNormalizationInDPModels : Recalc Norm in DP model" << std::endl; negSigModel_->recalculateNormalisation(); posSigModel_->recalculateNormalisation(); negSigModel_->modifyDataTree(); posSigModel_->modifyDataTree(); } void LauCPFitModel::initialiseDPModels() { std::cout << "INFO in LauCPFitModel::initialiseDPModels : Initialising signal DP model" << std::endl; negSigModel_->initialise(negCoeffs_); posSigModel_->initialise(posCoeffs_); if (usingBkgnd_ == kTRUE) { for (LauBkgndDPModelList::iterator iter = negBkgndDPModels_.begin(); iter != negBkgndDPModels_.end(); ++iter) { (*iter)->initialise(); } for (LauBkgndDPModelList::iterator iter = posBkgndDPModels_.begin(); iter != posBkgndDPModels_.end(); ++iter) { (*iter)->initialise(); } } } void LauCPFitModel::setSignalDPParameters() { // Set the fit parameters for the signal model. nSigDPPar_ = 0; if ( ! this->useDP() ) { return; } std::cout << "INFO in LauCPFitModel::setSignalDPParameters : Setting the initial fit parameters for the signal DP model." << std::endl; // Place isobar coefficient parameters in vector of fit variables LauParameterPList& fitVars = this->fitPars(); for (UInt_t i = 0; i < nSigComp_; i++) { LauParameterPList pars = coeffPars_[i]->getParameters(); for (LauParameterPList::iterator iter = pars.begin(); iter != pars.end(); ++iter) { if ( !(*iter)->clone() ) { fitVars.push_back(*iter); ++nSigDPPar_; } } } // Obtain the resonance parameters and place them in the vector of fit variables and in a separate vector // Need to make sure that they are unique because some might appear in both DP models LauParameterPSet& resVars = this->resPars(); resVars.clear(); LauParameterPList& negSigDPPars = negSigModel_->getFloatingParameters(); LauParameterPList& posSigDPPars = posSigModel_->getFloatingParameters(); for ( LauParameterPList::iterator iter = negSigDPPars.begin(); iter != negSigDPPars.end(); ++iter ) { if ( resVars.insert(*iter).second ) { fitVars.push_back(*iter); ++nSigDPPar_; } } for ( LauParameterPList::iterator iter = posSigDPPars.begin(); iter != posSigDPPars.end(); ++iter ) { if ( resVars.insert(*iter).second ) { fitVars.push_back(*iter); ++nSigDPPar_; } } } void LauCPFitModel::setExtraPdfParameters() { // Include all the parameters of the PDF in the fit // NB all of them are passed to the fit, even though some have been fixed through parameter.fixed(kTRUE) // With the new "cloned parameter" scheme only "original" parameters are passed to the fit. // Their clones are updated automatically when the originals are updated. nExtraPdfPar_ = 0; nExtraPdfPar_ += this->addFitParameters(negSignalPdfs_); if ( tagged_ ) { nExtraPdfPar_ += this->addFitParameters(posSignalPdfs_); } if (useSCF_ == kTRUE) { nExtraPdfPar_ += this->addFitParameters(negScfPdfs_); if ( tagged_ ) { nExtraPdfPar_ += this->addFitParameters(posScfPdfs_); } } if (usingBkgnd_ == kTRUE) { for (LauBkgndPdfsList::iterator iter = negBkgndPdfs_.begin(); iter != negBkgndPdfs_.end(); ++iter) { nExtraPdfPar_ += this->addFitParameters(*iter); } if ( tagged_ ) { for (LauBkgndPdfsList::iterator iter = posBkgndPdfs_.begin(); iter != posBkgndPdfs_.end(); ++iter) { nExtraPdfPar_ += this->addFitParameters(*iter); } } } } void LauCPFitModel::setFitNEvents() { if ( signalEvents_ == 0 ) { std::cerr << "ERROR in LauCPFitModel::setFitNEvents : Signal yield not defined." << std::endl; return; } nNormPar_ = 0; // initialise the total number of events to be the sum of all the hypotheses Double_t nTotEvts = signalEvents_->value(); for (LauBkgndYieldList::const_iterator iter = bkgndEvents_.begin(); iter != bkgndEvents_.end(); ++iter) { nTotEvts += (*iter)->value(); if ( (*iter) == 0 ) { std::cerr << "ERROR in LauCPFitModel::setFitNEvents : Background yield not defined." << std::endl; return; } } this->eventsPerExpt(TMath::FloorNint(nTotEvts)); LauParameterPList& fitVars = this->fitPars(); // if doing an extended ML fit add the number of signal events into the fit parameters if (this->doEMLFit()) { std::cout << "INFO in LauCPFitModel::setFitNEvents : Initialising number of events for signal and background components..." << std::endl; // add the signal fraction to the list of fit parameters if(!signalEvents_->fixed()) { fitVars.push_back(signalEvents_); ++nNormPar_; } } else { std::cout << "INFO in LauCPFitModel::setFitNEvents : Initialising number of events for background components (and hence signal)..." << std::endl; } // if not using the DP in the model we need an explicit signal asymmetry parameter if (this->useDP() == kFALSE) { if(!signalAsym_->fixed()) { fitVars.push_back(signalAsym_); ++nNormPar_; } } if (useSCF_ && !useSCFHist_) { if(!scfFrac_.fixed()) { fitVars.push_back(&scfFrac_); ++nNormPar_; } } if (usingBkgnd_ == kTRUE) { for (LauBkgndYieldList::iterator iter = bkgndEvents_.begin(); iter != bkgndEvents_.end(); ++iter) { std::vector parameters = (*iter)->getPars(); for ( LauParameter* parameter : parameters ) { if(!parameter->clone()) { fitVars.push_back(parameter); ++nNormPar_; } } } for (LauBkgndYieldList::iterator iter = bkgndAsym_.begin(); iter != bkgndAsym_.end(); ++iter) { std::vector parameters = (*iter)->getPars(); for ( LauParameter* parameter : parameters ) { if(!parameter->clone()) { fitVars.push_back(parameter); ++nNormPar_; } } } } } void LauCPFitModel::setExtraNtupleVars() { // Set-up other parameters derived from the fit results, e.g. fit fractions. if (this->useDP() != kTRUE) { return; } // First clear the vectors so we start from scratch this->clearExtraVarVectors(); LauParameterList& extraVars = this->extraPars(); // Add the positive and negative fit fractions for each signal component negFitFrac_ = negSigModel_->getFitFractions(); if (negFitFrac_.size() != nSigComp_) { std::cerr << "ERROR in LauCPFitModel::setExtraNtupleVars : Initial Fit Fraction array of unexpected dimension: " << negFitFrac_.size() << std::endl; gSystem->Exit(EXIT_FAILURE); } for (UInt_t i(0); iExit(EXIT_FAILURE); } } posFitFrac_ = posSigModel_->getFitFractions(); if (posFitFrac_.size() != nSigComp_) { std::cerr << "ERROR in LauCPFitModel::setExtraNtupleVars : Initial Fit Fraction array of unexpected dimension: " << posFitFrac_.size() << std::endl; gSystem->Exit(EXIT_FAILURE); } for (UInt_t i(0); iExit(EXIT_FAILURE); } } // Add the positive and negative fit fractions that have not been corrected for the efficiency for each signal component negFitFracEffUnCorr_ = negSigModel_->getFitFractionsEfficiencyUncorrected(); if (negFitFracEffUnCorr_.size() != nSigComp_) { std::cerr << "ERROR in LauCPFitModel::setExtraNtupleVars : Initial Fit Fraction array of unexpected dimension: " << negFitFracEffUnCorr_.size() << std::endl; gSystem->Exit(EXIT_FAILURE); } for (UInt_t i(0); iExit(EXIT_FAILURE); } } posFitFracEffUnCorr_ = posSigModel_->getFitFractionsEfficiencyUncorrected(); if (posFitFracEffUnCorr_.size() != nSigComp_) { std::cerr << "ERROR in LauCPFitModel::setExtraNtupleVars : Initial Fit Fraction array of unexpected dimension: " << posFitFracEffUnCorr_.size() << std::endl; gSystem->Exit(EXIT_FAILURE); } for (UInt_t i(0); iExit(EXIT_FAILURE); } } for (UInt_t i(0); i negExtraPars = negSigModel_->getExtraParameters(); std::vector::iterator negExtraIter; for (negExtraIter = negExtraPars.begin(); negExtraIter != negExtraPars.end(); ++negExtraIter) { LauParameter negExtraParameter = (*negExtraIter); extraVars.push_back(negExtraParameter); } std::vector posExtraPars = posSigModel_->getExtraParameters(); std::vector::iterator posExtraIter; for (posExtraIter = posExtraPars.begin(); posExtraIter != posExtraPars.end(); ++posExtraIter) { LauParameter posExtraParameter = (*posExtraIter); extraVars.push_back(posExtraParameter); } // Now add in the DP efficiency value Double_t initMeanEff = negSigModel_->getMeanEff().initValue(); negMeanEff_.value(initMeanEff); negMeanEff_.genValue(initMeanEff); negMeanEff_.initValue(initMeanEff); extraVars.push_back(negMeanEff_); initMeanEff = posSigModel_->getMeanEff().initValue(); posMeanEff_.value(initMeanEff); posMeanEff_.genValue(initMeanEff); posMeanEff_.initValue(initMeanEff); extraVars.push_back(posMeanEff_); // Also add in the DP rates Double_t initDPRate = negSigModel_->getDPRate().initValue(); negDPRate_.value(initDPRate); negDPRate_.genValue(initDPRate); negDPRate_.initValue(initDPRate); extraVars.push_back(negDPRate_); initDPRate = posSigModel_->getDPRate().initValue(); posDPRate_.value(initDPRate); posDPRate_.genValue(initDPRate); posDPRate_.initValue(initDPRate); extraVars.push_back(posDPRate_); // Calculate the CPC and CPV Fit Fractions, ACPs and FitFrac asymmetries this->calcExtraFractions(kTRUE); this->calcAsymmetries(kTRUE); // Add the CP violating and CP conserving fit fractions for each signal component for (UInt_t i = 0; i < nSigComp_; i++) { for (UInt_t j = i; j < nSigComp_; j++) { extraVars.push_back(CPVFitFrac_[i][j]); } } for (UInt_t i = 0; i < nSigComp_; i++) { for (UInt_t j = i; j < nSigComp_; j++) { extraVars.push_back(CPCFitFrac_[i][j]); } } // Add the Fit Fraction asymmetry for each signal component for (UInt_t i = 0; i < nSigComp_; i++) { extraVars.push_back(fitFracAsymm_[i]); } // Add the calculated CP asymmetry for each signal component for (UInt_t i = 0; i < nSigComp_; i++) { extraVars.push_back(acp_[i]); } } void LauCPFitModel::calcExtraFractions(Bool_t initValues) { // Calculate the CP-conserving and CP-violating fit fractions if (initValues) { // create the structure CPCFitFrac_.clear(); CPVFitFrac_.clear(); CPCFitFrac_.resize(nSigComp_); CPVFitFrac_.resize(nSigComp_); for (UInt_t i(0); iacp(); LauAsymmCalc asymmCalc(negFitFrac_[i][i].value(), posFitFrac_[i][i].value()); Double_t asym = asymmCalc.getAsymmetry(); fitFracAsymm_[i].value(asym); if (initValues) { fitFracAsymm_[i].genValue(asym); fitFracAsymm_[i].initValue(asym); } } } void LauCPFitModel::finaliseFitResults(const TString& tablePrefixName) { // Retrieve parameters from the fit results for calculations and toy generation // and eventually store these in output root ntuples/text files // Now take the fit parameters and update them as necessary // i.e. to make mag > 0.0, phase in the right range. // This function will also calculate any other values, such as the // fit fractions, using any errors provided by fitParErrors as appropriate. // Also obtain the pull values: (measured - generated)/(average error) if (this->useDP() == kTRUE) { for (UInt_t i = 0; i < nSigComp_; ++i) { // Check whether we have "a/b > 0.0", and phases in the right range coeffPars_[i]->finaliseValues(); } } // update the pulls on the event fractions and asymmetries if (this->doEMLFit()) { signalEvents_->updatePull(); } if (this->useDP() == kFALSE) { signalAsym_->updatePull(); } if (useSCF_ && !useSCFHist_) { scfFrac_.updatePull(); } if (usingBkgnd_ == kTRUE) { for (LauBkgndYieldList::iterator iter = bkgndEvents_.begin(); iter != bkgndEvents_.end(); ++iter) { std::vector parameters = (*iter)->getPars(); for ( LauParameter* parameter : parameters ) { parameter->updatePull(); } } for (LauBkgndYieldList::iterator iter = bkgndAsym_.begin(); iter != bkgndAsym_.end(); ++iter) { std::vector parameters = (*iter)->getPars(); for ( LauParameter* parameter : parameters ) { parameter->updatePull(); } } } // Update the pulls on all the extra PDFs' parameters this->updateFitParameters(negSignalPdfs_); this->updateFitParameters(posSignalPdfs_); if (useSCF_ == kTRUE) { this->updateFitParameters(negScfPdfs_); this->updateFitParameters(posScfPdfs_); } if (usingBkgnd_ == kTRUE) { for (LauBkgndPdfsList::iterator iter = negBkgndPdfs_.begin(); iter != negBkgndPdfs_.end(); ++iter) { this->updateFitParameters(*iter); } for (LauBkgndPdfsList::iterator iter = posBkgndPdfs_.begin(); iter != posBkgndPdfs_.end(); ++iter) { this->updateFitParameters(*iter); } } // Fill the fit results to the ntuple // update the coefficients and then calculate the fit fractions and ACP's if (this->useDP() == kTRUE) { this->updateCoeffs(); negSigModel_->updateCoeffs(negCoeffs_); negSigModel_->calcExtraInfo(); posSigModel_->updateCoeffs(posCoeffs_); posSigModel_->calcExtraInfo(); LauParArray negFitFrac = negSigModel_->getFitFractions(); if (negFitFrac.size() != nSigComp_) { std::cerr << "ERROR in LauCPFitModel::finaliseFitResults : Fit Fraction array of unexpected dimension: " << negFitFrac.size() << std::endl; gSystem->Exit(EXIT_FAILURE); } for (UInt_t i(0); iExit(EXIT_FAILURE); } } LauParArray posFitFrac = posSigModel_->getFitFractions(); if (posFitFrac.size() != nSigComp_) { std::cerr << "ERROR in LauCPFitModel::finaliseFitResults : Fit Fraction array of unexpected dimension: " << posFitFrac.size() << std::endl; gSystem->Exit(EXIT_FAILURE); } for (UInt_t i(0); iExit(EXIT_FAILURE); } } LauParArray negFitFracEffUnCorr = negSigModel_->getFitFractionsEfficiencyUncorrected(); if (negFitFracEffUnCorr.size() != nSigComp_) { std::cerr << "ERROR in LauCPFitModel::finaliseFitResults : Fit Fraction array of unexpected dimension: " << negFitFracEffUnCorr.size() << std::endl; gSystem->Exit(EXIT_FAILURE); } for (UInt_t i(0); iExit(EXIT_FAILURE); } } LauParArray posFitFracEffUnCorr = posSigModel_->getFitFractionsEfficiencyUncorrected(); if (posFitFracEffUnCorr.size() != nSigComp_) { std::cerr << "ERROR in LauCPFitModel::finaliseFitResults : Fit Fraction array of unexpected dimension: " << posFitFracEffUnCorr.size() << std::endl; gSystem->Exit(EXIT_FAILURE); } for (UInt_t i(0); iExit(EXIT_FAILURE); } } for (UInt_t i(0); igetMeanEff().value()); posMeanEff_.value(posSigModel_->getMeanEff().value()); negDPRate_.value(negSigModel_->getDPRate().value()); posDPRate_.value(posSigModel_->getDPRate().value()); this->calcExtraFractions(); this->calcAsymmetries(); // Then store the final fit parameters, and any extra parameters for // the signal model (e.g. fit fractions, FF asymmetries, ACPs, mean efficiency and DP rate) this->clearExtraVarVectors(); LauParameterList& extraVars = this->extraPars(); // Add the positive and negative fit fractions for each signal component for (UInt_t i(0); i negExtraPars = negSigModel_->getExtraParameters(); std::vector::iterator negExtraIter; for (negExtraIter = negExtraPars.begin(); negExtraIter != negExtraPars.end(); ++negExtraIter) { LauParameter negExtraParameter = (*negExtraIter); extraVars.push_back(negExtraParameter); } std::vector posExtraPars = posSigModel_->getExtraParameters(); std::vector::iterator posExtraIter; for (posExtraIter = posExtraPars.begin(); posExtraIter != posExtraPars.end(); ++posExtraIter) { LauParameter posExtraParameter = (*posExtraIter); extraVars.push_back(posExtraParameter); } extraVars.push_back(negMeanEff_); extraVars.push_back(posMeanEff_); extraVars.push_back(negDPRate_); extraVars.push_back(posDPRate_); for (UInt_t i = 0; i < nSigComp_; i++) { for (UInt_t j(i); jprintFitFractions(std::cout); this->printAsymmetries(std::cout); } const LauParameterPList& fitVars = this->fitPars(); const LauParameterList& extraVars = this->extraPars(); LauFitNtuple* ntuple = this->fitNtuple(); ntuple->storeParsAndErrors(fitVars, extraVars); // find out the correlation matrix for the parameters ntuple->storeCorrMatrix(this->iExpt(), this->fitStatus(), this->covarianceMatrix()); // Fill the data into ntuple ntuple->updateFitNtuple(); // Print out the partial fit fractions, phases and the // averaged efficiency, reweighted by the dynamics (and anything else) if (this->writeLatexTable()) { TString sigOutFileName(tablePrefixName); sigOutFileName += "_"; sigOutFileName += this->iExpt(); sigOutFileName += "Expt.tex"; this->writeOutTable(sigOutFileName); } } void LauCPFitModel::printFitFractions(std::ostream& output) { // Print out Fit Fractions, total DP rate and mean efficiency // First for the B- events for (UInt_t i = 0; i < nSigComp_; i++) { const TString compName(coeffPars_[i]->name()); output << negParent_ << " FitFraction for component " << i << " (" << compName << ") = " << negFitFrac_[i][i] << std::endl; } output << negParent_ << " overall DP rate (integral of matrix element squared) = " << negDPRate_ << std::endl; output << negParent_ << " average efficiency weighted by whole DP dynamics = " << negMeanEff_ << std::endl; // Then for the positive sample for (UInt_t i = 0; i < nSigComp_; i++) { const TString compName(coeffPars_[i]->name()); const TString conjName(negSigModel_->getConjResName(compName)); output << posParent_ << " FitFraction for component " << i << " (" << conjName << ") = " << posFitFrac_[i][i] << std::endl; } output << posParent_ << " overall DP rate (integral of matrix element squared) = " << posDPRate_ << std::endl; output << posParent_ << " average efficiency weighted by whole DP dynamics = " << posMeanEff_ << std::endl; } void LauCPFitModel::printAsymmetries(std::ostream& output) { for (UInt_t i = 0; i < nSigComp_; i++) { const TString compName(coeffPars_[i]->name()); output << "Fit Fraction asymmetry for component " << i << " (" << compName << ") = " << fitFracAsymm_[i] << std::endl; } for (UInt_t i = 0; i < nSigComp_; i++) { const TString compName(coeffPars_[i]->name()); output << "ACP for component " << i << " (" << compName << ") = " << acp_[i] << std::endl; } } void LauCPFitModel::writeOutTable(const TString& outputFile) { // Write out the results of the fit to a tex-readable table // TODO - need to include the yields in this table std::ofstream fout(outputFile); LauPrint print; std::cout << "INFO in LauCPFitModel::writeOutTable : Writing out results of the fit to the tex file " << outputFile << std::endl; if (this->useDP() == kTRUE) { // print the fit coefficients in one table coeffPars_.front()->printTableHeading(fout); for (UInt_t i = 0; i < nSigComp_; i++) { coeffPars_[i]->printTableRow(fout); } fout << "\\hline" << std::endl; fout << "\\end{tabular}" << std::endl << std::endl; // print the fit fractions and asymmetries in another fout << "\\begin{tabular}{|l|c|c|c|c|}" << std::endl; fout << "\\hline" << std::endl; fout << "Component & " << negParent_ << " Fit Fraction & " << posParent_ << " Fit Fraction & Fit Fraction Asymmetry & ACP \\\\" << std::endl; fout << "\\hline" << std::endl; Double_t negFitFracSum(0.0); Double_t posFitFracSum(0.0); for (UInt_t i = 0; i < nSigComp_; i++) { TString resName = coeffPars_[i]->name(); resName = resName.ReplaceAll("_", "\\_"); Double_t negFitFrac = negFitFrac_[i][i].value(); Double_t posFitFrac = posFitFrac_[i][i].value(); negFitFracSum += negFitFrac; posFitFracSum += posFitFrac; Double_t fitFracAsymm = fitFracAsymm_[i].value(); Double_t acp = acp_[i].value(); Double_t acpErr = acp_[i].error(); fout << resName << " & $"; print.printFormat(fout, negFitFrac); fout << "$ & $"; print.printFormat(fout, posFitFrac); fout << "$ & $"; print.printFormat(fout, fitFracAsymm); fout << "$ & $"; print.printFormat(fout, acp); fout << " \\pm "; print.printFormat(fout, acpErr); fout << "$ \\\\" << std::endl; } fout << "\\hline" << std::endl; // Also print out sum of fit fractions fout << "Fit Fraction Sum & $"; print.printFormat(fout, negFitFracSum); fout << "$ & $"; print.printFormat(fout, posFitFracSum); fout << "$ & & \\\\" << std::endl; fout << "\\hline" << std::endl; fout << "DP rate & $"; print.printFormat(fout, negDPRate_.value()); fout << "$ & $"; print.printFormat(fout, posDPRate_.value()); fout << "$ & & \\\\" << std::endl; fout << "$< \\varepsilon > $ & $"; print.printFormat(fout, negMeanEff_.value()); fout << "$ & $"; print.printFormat(fout, posMeanEff_.value()); fout << "$ & & \\\\" << std::endl; fout << "\\hline" << std::endl; fout << "\\end{tabular}" << std::endl << std::endl; } if (!negSignalPdfs_.empty()) { fout << "\\begin{tabular}{|l|c|}" << std::endl; fout << "\\hline" << std::endl; if (useSCF_ == kTRUE) { fout << "\\Extra TM Signal PDFs' Parameters: & \\\\" << std::endl; } else { fout << "\\Extra Signal PDFs' Parameters: & \\\\" << std::endl; } this->printFitParameters(negSignalPdfs_, fout); if ( tagged_ ) { this->printFitParameters(posSignalPdfs_, fout); } if (useSCF_ == kTRUE && !negScfPdfs_.empty()) { fout << "\\hline" << std::endl; fout << "\\Extra SCF Signal PDFs' Parameters: & \\\\" << std::endl; this->printFitParameters(negScfPdfs_, fout); if ( tagged_ ) { this->printFitParameters(posScfPdfs_, fout); } } if (usingBkgnd_ == kTRUE && !negBkgndPdfs_.empty()) { fout << "\\hline" << std::endl; fout << "\\Extra Background PDFs' Parameters: & \\\\" << std::endl; for (LauBkgndPdfsList::const_iterator iter = negBkgndPdfs_.begin(); iter != negBkgndPdfs_.end(); ++iter) { this->printFitParameters(*iter, fout); } if ( tagged_ ) { for (LauBkgndPdfsList::const_iterator iter = posBkgndPdfs_.begin(); iter != posBkgndPdfs_.end(); ++iter) { this->printFitParameters(*iter, fout); } } } fout << "\\hline \n\\end{tabular}" << std::endl << std::endl; } } void LauCPFitModel::checkInitFitParams() { // Update the number of signal events to be total-sum(background events) this->updateSigEvents(); // Check whether we want to have randomised initial fit parameters for the signal model if (this->useRandomInitFitPars() == kTRUE) { std::cout << "INFO in LauCPFitModel::checkInitFitParams : Setting random parameters for the signal model" << std::endl; this->randomiseInitFitPars(); } } void LauCPFitModel::randomiseInitFitPars() { // Only randomise those parameters that are not fixed! std::cout << "INFO in LauCPFitModel::randomiseInitFitPars : Randomising the initial fit magnitudes and phases of the components..." << std::endl; if ( fixParamFileName_.IsNull() && fixParamMap_.empty() ) { // No params are imported - randomise as normal for (UInt_t i = 0; i < nSigComp_; i++) { coeffPars_[i]->randomiseInitValues(); } } else { // Only randomise those that are not imported (i.e., not found in allImportedFreeParams_) // by temporarily fixing all imported parameters, and then freeing those not set to be fixed when imported, // except those that are previously set to be fixed anyhow. // Convoluted, but beats changing the behaviour of functions that call checkInitFitParams or the coeffSet // itself. for (auto p : allImportedFreeParams_) { p->fixed(kTRUE); } for (UInt_t i = 0; i < nSigComp_; i++) { coeffPars_[i]->randomiseInitValues(); } for (auto p : allImportedFreeParams_) { p->fixed(kFALSE); } } } std::pair LauCPFitModel::eventsToGenerate() { // Determine the number of events to generate for each hypothesis // If we're smearing then smear each one individually LauGenInfo nEvtsGen; // Keep track of whether any yield or asymmetry parameters are blinded Bool_t blind = kFALSE; // Signal Double_t evtWeight(1.0); Double_t nEvts = signalEvents_->genValue(); if ( nEvts < 0.0 ) { evtWeight = -1.0; nEvts = TMath::Abs( nEvts ); } if ( signalEvents_->blind() ) { blind = kTRUE; } Double_t asym(0.0); Double_t sigAsym(0.0); // need to include this as an alternative in case the DP isn't in the model if ( !this->useDP() || forceAsym_ ) { sigAsym = signalAsym_->genValue(); if ( signalAsym_->blind() ) { blind = kTRUE; } } else { Double_t negRate = negSigModel_->getDPNorm(); Double_t posRate = posSigModel_->getDPNorm(); if (negRate+posRate>1e-30) { sigAsym = (negRate-posRate)/(negRate+posRate); } } asym = sigAsym; Int_t nPosEvts = static_cast((nEvts/2.0 * (1.0 - asym)) + 0.5); Int_t nNegEvts = static_cast((nEvts/2.0 * (1.0 + asym)) + 0.5); if (this->doPoissonSmearing()) { nNegEvts = LauRandom::randomFun()->Poisson(nNegEvts); nPosEvts = LauRandom::randomFun()->Poisson(nPosEvts); } nEvtsGen[std::make_pair("signal",-1)] = std::make_pair(nNegEvts,evtWeight); nEvtsGen[std::make_pair("signal",+1)] = std::make_pair(nPosEvts,evtWeight); // backgrounds const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) { const TString& bkgndClass = this->bkgndClassName(bkgndID); const LauAbsRValue* evtsPar = bkgndEvents_[bkgndID]; const LauAbsRValue* asymPar = bkgndAsym_[bkgndID]; if ( evtsPar->blind() || asymPar->blind() ) { blind = kTRUE; } evtWeight = 1.0; nEvts = TMath::FloorNint( evtsPar->genValue() ); if ( nEvts < 0 ) { evtWeight = -1.0; nEvts = TMath::Abs( nEvts ); } asym = asymPar->genValue(); nPosEvts = static_cast((nEvts/2.0 * (1.0 - asym)) + 0.5); nNegEvts = static_cast((nEvts/2.0 * (1.0 + asym)) + 0.5); if (this->doPoissonSmearing()) { nNegEvts = LauRandom::randomFun()->Poisson(nNegEvts); nPosEvts = LauRandom::randomFun()->Poisson(nPosEvts); } nEvtsGen[std::make_pair(bkgndClass,-1)] = std::make_pair(nNegEvts,evtWeight); nEvtsGen[std::make_pair(bkgndClass,+1)] = std::make_pair(nPosEvts,evtWeight); } // Print out the information on what we're generating, but only if none of the parameters are blind (otherwise we risk unblinding them!) if ( !blind ) { std::cout << "INFO in LauCPFitModel::eventsToGenerate : Generating toy MC with:" << std::endl; std::cout << " : Signal asymmetry = " << sigAsym << " and number of signal events = " << signalEvents_->genValue() << std::endl; for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) { const TString& bkgndClass = this->bkgndClassName(bkgndID); const LauAbsRValue* evtsPar = bkgndEvents_[bkgndID]; const LauAbsRValue* asymPar = bkgndAsym_[bkgndID]; std::cout << " : " << bkgndClass << " asymmetry = " << asymPar->genValue() << " and number of " << bkgndClass << " events = " << evtsPar->genValue() << std::endl; } } return std::make_pair( nEvtsGen, blind ); } Bool_t LauCPFitModel::genExpt() { // Routine to generate toy Monte Carlo events according to the various models we have defined. // Determine the number of events to generate for each hypothesis std::pair info = this->eventsToGenerate(); LauGenInfo nEvts = info.first; const Bool_t blind = info.second; Bool_t genOK(kTRUE); Int_t evtNum(0); const UInt_t nBkgnds = this->nBkgndClasses(); std::vector bkgndClassNames(nBkgnds); std::vector bkgndClassNamesGen(nBkgnds); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { TString name( this->bkgndClassName(iBkgnd) ); bkgndClassNames[iBkgnd] = name; bkgndClassNamesGen[iBkgnd] = "gen"+name; } const Bool_t storeSCFTruthInfo = ( useSCF_ || ( this->enableEmbedding() && negSignalTree_ != 0 && negSignalTree_->haveBranch("mcMatch") && posSignalTree_ != 0 && posSignalTree_->haveBranch("mcMatch") ) ); // Loop over the hypotheses and generate the requested number of events for each one for (LauGenInfo::const_iterator iter = nEvts.begin(); iter != nEvts.end(); ++iter) { const TString& type(iter->first.first); curEvtCharge_ = iter->first.second; Double_t evtWeight( iter->second.second ); Int_t nEvtsGen( iter->second.first ); for (Int_t iEvt(0); iEvtsetGenNtupleDoubleBranchValue( "evtWeight", evtWeight ); this->setGenNtupleDoubleBranchValue( "efficiency", 1.0 ); if (type == "signal") { this->setGenNtupleIntegerBranchValue("genSig",1); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { this->setGenNtupleIntegerBranchValue( bkgndClassNamesGen[iBkgnd], 0 ); } genOK = this->generateSignalEvent(); if ( curEvtCharge_ > 0 ){ this->setGenNtupleDoubleBranchValue( "efficiency", posSigModel_->getEvtEff() ); } else { this->setGenNtupleDoubleBranchValue( "efficiency", negSigModel_->getEvtEff() ); } } else { this->setGenNtupleIntegerBranchValue("genSig",0); if ( storeSCFTruthInfo ) { this->setGenNtupleIntegerBranchValue("genTMSig",0); this->setGenNtupleIntegerBranchValue("genSCFSig",0); } UInt_t bkgndID(0); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { Int_t gen(0); if ( bkgndClassNames[iBkgnd] == type ) { gen = 1; bkgndID = iBkgnd; } this->setGenNtupleIntegerBranchValue( bkgndClassNamesGen[iBkgnd], gen ); } genOK = this->generateBkgndEvent(bkgndID); } if (!genOK) { // If there was a problem with the generation then break out and return. // The problem model will have adjusted itself so that all should be OK next time. break; } if (this->useDP() == kTRUE) { this->setDPBranchValues(); } // Store the event charge this->setGenNtupleIntegerBranchValue(tagVarName_,curEvtCharge_); // Store the event number (within this experiment) // and then increment it this->setGenNtupleIntegerBranchValue("iEvtWithinExpt",evtNum); ++evtNum; this->fillGenNtupleBranches(); if ( !blind && (iEvt%500 == 0) ) { std::cout << "INFO in LauCPFitModel::genExpt : Generated event number " << iEvt << " out of " << nEvtsGen << " " << type << " events." << std::endl; } } if (!genOK) { break; } } if (this->useDP() && genOK) { negSigModel_->checkToyMC(kTRUE,kTRUE); posSigModel_->checkToyMC(kTRUE,kTRUE); // Get the fit fractions if they're to be written into the latex table if (this->writeLatexTable()) { LauParArray negFitFrac = negSigModel_->getFitFractions(); if (negFitFrac.size() != nSigComp_) { std::cerr << "ERROR in LauCPFitModel::genExpt : Fit Fraction array of unexpected dimension: " << negFitFrac.size() << std::endl; gSystem->Exit(EXIT_FAILURE); } for (UInt_t i(0); iExit(EXIT_FAILURE); } } LauParArray posFitFrac = posSigModel_->getFitFractions(); if (posFitFrac.size() != nSigComp_) { std::cerr << "ERROR in LauCPFitModel::genExpt : Fit Fraction array of unexpected dimension: " << posFitFrac.size() << std::endl; gSystem->Exit(EXIT_FAILURE); } for (UInt_t i(0); iExit(EXIT_FAILURE); } } for (UInt_t i(0); igetMeanEff().value()); posMeanEff_.value(posSigModel_->getMeanEff().value()); negDPRate_.value(negSigModel_->getDPRate().value()); posDPRate_.value(posSigModel_->getDPRate().value()); } } // If we're reusing embedded events or if the generation is being // reset then clear the lists of used events if (reuseSignal_ || !genOK) { if (negSignalTree_) { negSignalTree_->clearUsedList(); } if (posSignalTree_) { posSignalTree_->clearUsedList(); } } for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) { LauEmbeddedData* data = negBkgndTree_[bkgndID]; if (reuseBkgnd_[bkgndID] || !genOK) { if (data) { data->clearUsedList(); } } } for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) { LauEmbeddedData* data = posBkgndTree_[bkgndID]; if (reuseBkgnd_[bkgndID] || !genOK) { if (data) { data->clearUsedList(); } } } return genOK; } Bool_t LauCPFitModel::generateSignalEvent() { // Generate signal event Bool_t genOK(kTRUE); Bool_t genSCF(kFALSE); LauIsobarDynamics* model(0); LauKinematics* kinematics(0); LauEmbeddedData* embeddedData(0); LauPdfList* sigPdfs(0); LauPdfList* scfPdfs(0); Bool_t doReweighting(kFALSE); if (curEvtCharge_<0) { model = negSigModel_; kinematics = negKinematics_; sigPdfs = &negSignalPdfs_; scfPdfs = &negScfPdfs_; if (this->enableEmbedding()) { embeddedData = negSignalTree_; doReweighting = useNegReweighting_; } } else { model = posSigModel_; kinematics = posKinematics_; if ( tagged_ ) { sigPdfs = &posSignalPdfs_; scfPdfs = &posScfPdfs_; } else { sigPdfs = &negSignalPdfs_; scfPdfs = &negScfPdfs_; } if (this->enableEmbedding()) { embeddedData = posSignalTree_; doReweighting = usePosReweighting_; } } if (this->useDP()) { if (embeddedData) { if (doReweighting) { // Select a (random) event from the generated data. Then store the // reconstructed DP co-ords, together with other pdf information, // as the embedded data. genOK = embeddedData->getReweightedEvent(model); } else { // Just get the information of a (randomly) selected event in the // embedded data embeddedData->getEmbeddedEvent(kinematics); } genSCF = this->storeSignalMCMatch( embeddedData ); } else { genOK = model->generate(); if ( genOK && useSCF_ ) { Double_t frac(0.0); if ( useSCFHist_ ) { frac = scfFracHist_->calcEfficiency( kinematics ); } else { frac = scfFrac_.genValue(); } if ( frac < LauRandom::randomFun()->Rndm() ) { this->setGenNtupleIntegerBranchValue("genTMSig",1); this->setGenNtupleIntegerBranchValue("genSCFSig",0); genSCF = kFALSE; } else { this->setGenNtupleIntegerBranchValue("genTMSig",0); this->setGenNtupleIntegerBranchValue("genSCFSig",1); genSCF = kTRUE; // Optionally smear the DP position // of the SCF event if ( scfMap_ != 0 ) { Double_t xCoord(0.0), yCoord(0.0); if ( kinematics->squareDP() ) { xCoord = kinematics->getmPrime(); yCoord = kinematics->getThetaPrime(); } else { xCoord = kinematics->getm13Sq(); yCoord = kinematics->getm23Sq(); } // Find the bin number where this event is generated Int_t binNo = scfMap_->binNumber( xCoord, yCoord ); // Retrieve the migration histogram TH2* histo = scfMap_->trueHist( binNo ); const LauAbsEffModel * effModel = model->getEffModel(); do { // Get a random point from the histogram histo->GetRandom2( xCoord, yCoord ); // Update the kinematics if ( kinematics->squareDP() ) { kinematics->updateSqDPKinematics( xCoord, yCoord ); } else { kinematics->updateKinematics( xCoord, yCoord ); } } while ( ! effModel->passVeto( kinematics ) ); } } } } } else { if (embeddedData) { embeddedData->getEmbeddedEvent(0); genSCF = this->storeSignalMCMatch( embeddedData ); } else if ( useSCF_ ) { Double_t frac = scfFrac_.genValue(); if ( frac < LauRandom::randomFun()->Rndm() ) { this->setGenNtupleIntegerBranchValue("genTMSig",1); this->setGenNtupleIntegerBranchValue("genSCFSig",0); genSCF = kFALSE; } else { this->setGenNtupleIntegerBranchValue("genTMSig",0); this->setGenNtupleIntegerBranchValue("genSCFSig",1); genSCF = kTRUE; } } } if (genOK) { if ( useSCF_ ) { if ( genSCF ) { this->generateExtraPdfValues(scfPdfs, embeddedData); } else { this->generateExtraPdfValues(sigPdfs, embeddedData); } } else { this->generateExtraPdfValues(sigPdfs, embeddedData); } } // Check for problems with the embedding if (embeddedData && (embeddedData->nEvents() == embeddedData->nUsedEvents())) { std::cerr << "WARNING in LauCPFitModel::generateSignalEvent : Source of embedded signal events used up, clearing the list of used events." << std::endl; embeddedData->clearUsedList(); } return genOK; } Bool_t LauCPFitModel::generateBkgndEvent(UInt_t bkgndID) { // Generate Bkgnd event Bool_t genOK(kTRUE); LauAbsBkgndDPModel* model(0); LauEmbeddedData* embeddedData(0); LauPdfList* extraPdfs(0); LauKinematics* kinematics(0); if (curEvtCharge_<0) { model = negBkgndDPModels_[bkgndID]; if (this->enableEmbedding()) { embeddedData = negBkgndTree_[bkgndID]; } extraPdfs = &negBkgndPdfs_[bkgndID]; kinematics = negKinematics_; } else { model = posBkgndDPModels_[bkgndID]; if (this->enableEmbedding()) { embeddedData = posBkgndTree_[bkgndID]; } if ( tagged_ ) { extraPdfs = &posBkgndPdfs_[bkgndID]; } else { extraPdfs = &negBkgndPdfs_[bkgndID]; } kinematics = posKinematics_; } if (this->useDP()) { if (embeddedData) { embeddedData->getEmbeddedEvent(kinematics); } else { if (model == 0) { const TString& bkgndClass = this->bkgndClassName(bkgndID); std::cerr << "ERROR in LauCPFitModel::generateBkgndEvent : Can't find the DP model for background class \"" << bkgndClass << "\"." << std::endl; gSystem->Exit(EXIT_FAILURE); } genOK = model->generate(); } } else { if (embeddedData) { embeddedData->getEmbeddedEvent(0); } } if (genOK) { this->generateExtraPdfValues(extraPdfs, embeddedData); } // Check for problems with the embedding if (embeddedData && (embeddedData->nEvents() == embeddedData->nUsedEvents())) { const TString& bkgndClass = this->bkgndClassName(bkgndID); std::cerr << "WARNING in LauCPFitModel::generateBkgndEvent : Source of embedded " << bkgndClass << " events used up, clearing the list of used events." << std::endl; embeddedData->clearUsedList(); } return genOK; } void LauCPFitModel::setupGenNtupleBranches() { // Setup the required ntuple branches this->addGenNtupleDoubleBranch("evtWeight"); this->addGenNtupleIntegerBranch("genSig"); this->addGenNtupleDoubleBranch("efficiency"); if ( useSCF_ || ( this->enableEmbedding() && negSignalTree_ != 0 && negSignalTree_->haveBranch("mcMatch") && posSignalTree_ != 0 && posSignalTree_->haveBranch("mcMatch") ) ) { this->addGenNtupleIntegerBranch("genTMSig"); this->addGenNtupleIntegerBranch("genSCFSig"); } const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { TString name( this->bkgndClassName(iBkgnd) ); name.Prepend("gen"); this->addGenNtupleIntegerBranch(name); } this->addGenNtupleIntegerBranch("charge"); if (this->useDP() == kTRUE) { this->addGenNtupleDoubleBranch("m12"); this->addGenNtupleDoubleBranch("m23"); this->addGenNtupleDoubleBranch("m13"); this->addGenNtupleDoubleBranch("m12Sq"); this->addGenNtupleDoubleBranch("m23Sq"); this->addGenNtupleDoubleBranch("m13Sq"); this->addGenNtupleDoubleBranch("cosHel12"); this->addGenNtupleDoubleBranch("cosHel23"); this->addGenNtupleDoubleBranch("cosHel13"); if (negKinematics_->squareDP() && posKinematics_->squareDP()) { this->addGenNtupleDoubleBranch("mPrime"); this->addGenNtupleDoubleBranch("thPrime"); } } for (LauPdfList::const_iterator pdf_iter = negSignalPdfs_.begin(); pdf_iter != negSignalPdfs_.end(); ++pdf_iter) { std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { this->addGenNtupleDoubleBranch( (*var_iter) ); } } } } void LauCPFitModel::setDPBranchValues() { LauKinematics* kinematics(0); if (curEvtCharge_<0) { kinematics = negKinematics_; } else { kinematics = posKinematics_; } // Store all the DP information this->setGenNtupleDoubleBranchValue("m12", kinematics->getm12()); this->setGenNtupleDoubleBranchValue("m23", kinematics->getm23()); this->setGenNtupleDoubleBranchValue("m13", kinematics->getm13()); this->setGenNtupleDoubleBranchValue("m12Sq", kinematics->getm12Sq()); this->setGenNtupleDoubleBranchValue("m23Sq", kinematics->getm23Sq()); this->setGenNtupleDoubleBranchValue("m13Sq", kinematics->getm13Sq()); this->setGenNtupleDoubleBranchValue("cosHel12", kinematics->getc12()); this->setGenNtupleDoubleBranchValue("cosHel23", kinematics->getc23()); this->setGenNtupleDoubleBranchValue("cosHel13", kinematics->getc13()); if (kinematics->squareDP()) { this->setGenNtupleDoubleBranchValue("mPrime", kinematics->getmPrime()); this->setGenNtupleDoubleBranchValue("thPrime", kinematics->getThetaPrime()); } } void LauCPFitModel::generateExtraPdfValues(LauPdfList* extraPdfs, LauEmbeddedData* embeddedData) { LauKinematics* kinematics(0); if (curEvtCharge_<0) { kinematics = negKinematics_; } else { kinematics = posKinematics_; } if (!extraPdfs) { std::cerr << "ERROR in LauCPFitModel::generateExtraPdfValues : Null pointer to PDF list." << std::endl; gSystem->Exit(EXIT_FAILURE); } if (extraPdfs->empty()) { //std::cerr << "WARNING in LauCPFitModel::generateExtraPdfValues : PDF list is empty." << std::endl; return; } // Generate from the extra PDFs for (LauPdfList::iterator pdf_iter = extraPdfs->begin(); pdf_iter != extraPdfs->end(); ++pdf_iter) { LauFitData genValues; if (embeddedData) { genValues = embeddedData->getValues( (*pdf_iter)->varNames() ); } else { genValues = (*pdf_iter)->generate(kinematics); } for ( LauFitData::const_iterator var_iter = genValues.begin(); var_iter != genValues.end(); ++var_iter ) { TString varName = var_iter->first; if ( varName != "m13Sq" && varName != "m23Sq" ) { Double_t value = var_iter->second; this->setGenNtupleDoubleBranchValue(varName,value); } } } } Bool_t LauCPFitModel::storeSignalMCMatch(LauEmbeddedData* embeddedData) { // Default to TM Bool_t genSCF(kFALSE); Int_t match(1); // Check that we have a valid pointer and that embedded data has // the mcMatch branch. If so then get the match value. if ( embeddedData && embeddedData->haveBranch("mcMatch") ) { match = TMath::Nint( embeddedData->getValue("mcMatch") ); } // Set the variables accordingly. if (match) { this->setGenNtupleIntegerBranchValue("genTMSig",1); this->setGenNtupleIntegerBranchValue("genSCFSig",0); genSCF = kFALSE; } else { this->setGenNtupleIntegerBranchValue("genTMSig",0); this->setGenNtupleIntegerBranchValue("genSCFSig",1); genSCF = kTRUE; } return genSCF; } void LauCPFitModel::propagateParUpdates() { // Update the signal parameters and then the total normalisation for the signal likelihood if (this->useDP() == kTRUE) { this->updateCoeffs(); negSigModel_->updateCoeffs(negCoeffs_); posSigModel_->updateCoeffs(posCoeffs_); } // Update the signal fraction from the background fractions if not doing an extended fit if ( !this->doEMLFit() && !signalEvents_->fixed() ) { this->updateSigEvents(); } } void LauCPFitModel::updateSigEvents() { // The background parameters will have been set from Minuit. // We need to update the signal events using these. Double_t nTotEvts = this->eventsPerExpt(); signalEvents_->range(-2.0*nTotEvts,2.0*nTotEvts); for (LauBkgndYieldList::iterator iter = bkgndEvents_.begin(); iter != bkgndEvents_.end(); ++iter) { LauAbsRValue* nBkgndEvents = (*iter); if ( nBkgndEvents->isLValue() ) { LauParameter* yield = dynamic_cast( nBkgndEvents ); yield->range(-2.0*nTotEvts,2.0*nTotEvts); } } if (signalEvents_->fixed()) { return; } // Subtract background events (if any) from signal. Double_t signalEvents = nTotEvts; if (usingBkgnd_ == kTRUE) { for (LauBkgndYieldList::const_iterator iter = bkgndEvents_.begin(); iter != bkgndEvents_.end(); ++iter) { signalEvents -= (*iter)->value(); } } signalEvents_->value(signalEvents); } void LauCPFitModel::cacheInputFitVars() { // Fill the internal data trees of the signal and background models. // Note that we store the events of both charges in both the // negative and the positive models. It's only later, at the stage // when the likelihood is being calculated, that we separate them. LauFitDataTree* inputFitData = this->fitData(); // First the Dalitz plot variables (m_ij^2) if (this->useDP() == kTRUE) { // need to append SCF smearing bins before caching DP amplitudes if ( scfMap_ != 0 ) { this->appendBinCentres( inputFitData ); } negSigModel_->fillDataTree(*inputFitData); posSigModel_->fillDataTree(*inputFitData); if (usingBkgnd_ == kTRUE) { for (LauBkgndDPModelList::iterator iter = negBkgndDPModels_.begin(); iter != negBkgndDPModels_.end(); ++iter) { (*iter)->fillDataTree(*inputFitData); } for (LauBkgndDPModelList::iterator iter = posBkgndDPModels_.begin(); iter != posBkgndDPModels_.end(); ++iter) { (*iter)->fillDataTree(*inputFitData); } } } // ...and then the extra PDFs this->cacheInfo(negSignalPdfs_, *inputFitData); this->cacheInfo(negScfPdfs_, *inputFitData); for (LauBkgndPdfsList::iterator iter = negBkgndPdfs_.begin(); iter != negBkgndPdfs_.end(); ++iter) { this->cacheInfo((*iter), *inputFitData); } if ( tagged_ ) { this->cacheInfo(posSignalPdfs_, *inputFitData); this->cacheInfo(posScfPdfs_, *inputFitData); for (LauBkgndPdfsList::iterator iter = posBkgndPdfs_.begin(); iter != posBkgndPdfs_.end(); ++iter) { this->cacheInfo((*iter), *inputFitData); } } // the SCF fractions and jacobians if ( useSCF_ && useSCFHist_ ) { if ( !inputFitData->haveBranch( "m13Sq" ) || !inputFitData->haveBranch( "m23Sq" ) ) { std::cerr << "ERROR in LauCPFitModel::cacheInputFitVars : Input data does not contain DP branches and so can't cache the SCF fraction." << std::endl; gSystem->Exit(EXIT_FAILURE); } UInt_t nEvents = inputFitData->nEvents(); recoSCFFracs_.clear(); recoSCFFracs_.reserve( nEvents ); if ( negKinematics_->squareDP() ) { recoJacobians_.clear(); recoJacobians_.reserve( nEvents ); } for (UInt_t iEvt = 0; iEvt < nEvents; iEvt++) { const LauFitData& dataValues = inputFitData->getData(iEvt); LauFitData::const_iterator m13_iter = dataValues.find("m13Sq"); LauFitData::const_iterator m23_iter = dataValues.find("m23Sq"); negKinematics_->updateKinematics( m13_iter->second, m23_iter->second ); Double_t scfFrac = scfFracHist_->calcEfficiency( negKinematics_ ); recoSCFFracs_.push_back( scfFrac ); if ( negKinematics_->squareDP() ) { recoJacobians_.push_back( negKinematics_->calcSqDPJacobian() ); } } } // finally cache the event charge evtCharges_.clear(); if ( tagged_ ) { if ( !inputFitData->haveBranch( tagVarName_ ) ) { std::cerr << "ERROR in LauCPFitModel::cacheInputFitVars : Input data does not contain branch \"" << tagVarName_ << "\"." << std::endl; gSystem->Exit(EXIT_FAILURE); } UInt_t nEvents = inputFitData->nEvents(); evtCharges_.reserve( nEvents ); for (UInt_t iEvt = 0; iEvt < nEvents; iEvt++) { const LauFitData& dataValues = inputFitData->getData(iEvt); LauFitData::const_iterator iter = dataValues.find( tagVarName_ ); curEvtCharge_ = static_cast( iter->second ); evtCharges_.push_back( curEvtCharge_ ); } } } void LauCPFitModel::appendBinCentres( LauFitDataTree* inputData ) { // We'll be caching the DP amplitudes and efficiencies of the centres of the true bins. // To do so, we attach some fake points at the end of inputData, the number of the entry // minus the total number of events corresponding to the number of the histogram for that // given true bin in the LauScfMap object. (What this means is that when Laura is provided with // the LauScfMap object by the user, it's the latter who has to make sure that it contains the // right number of histograms and in exactly the right order!) // Get the x and y co-ordinates of the bin centres std::vector binCentresXCoords; std::vector binCentresYCoords; scfMap_->listBinCentres(binCentresXCoords, binCentresYCoords); // The SCF histograms could be in square Dalitz plot histograms. // The dynamics takes normal Dalitz plot coords, so we might have to convert them back. Bool_t sqDP = negKinematics_->squareDP(); UInt_t nBins = binCentresXCoords.size(); fakeSCFFracs_.clear(); fakeSCFFracs_.reserve( nBins ); if ( sqDP ) { fakeJacobians_.clear(); fakeJacobians_.reserve( nBins ); } for (UInt_t iBin = 0; iBin < nBins; ++iBin) { if ( sqDP ) { negKinematics_->updateSqDPKinematics(binCentresXCoords[iBin],binCentresYCoords[iBin]); binCentresXCoords[iBin] = negKinematics_->getm13Sq(); binCentresYCoords[iBin] = negKinematics_->getm23Sq(); fakeJacobians_.push_back( negKinematics_->calcSqDPJacobian() ); } else { negKinematics_->updateKinematics(binCentresXCoords[iBin],binCentresYCoords[iBin]); } fakeSCFFracs_.push_back( scfFracHist_->calcEfficiency( negKinematics_ ) ); } // Set up inputFitVars_ object to hold the fake events inputData->appendFakePoints(binCentresXCoords,binCentresYCoords); } Double_t LauCPFitModel::getTotEvtLikelihood(UInt_t iEvt) { // Find out whether we have B- or B+ if ( tagged_ ) { curEvtCharge_ = evtCharges_[iEvt]; // check that the charge is either +1 or -1 if (TMath::Abs(curEvtCharge_)!=1) { std::cerr << "ERROR in LauCPFitModel::getTotEvtLikelihood : Charge/tag not accepted value: " << curEvtCharge_ << std::endl; if (curEvtCharge_>0) { curEvtCharge_ = +1; } else { curEvtCharge_ = -1; } std::cerr << " : Making it: " << curEvtCharge_ << "." << std::endl; } } // Get the DP likelihood for signal and backgrounds this->getEvtDPLikelihood(iEvt); // Get the combined extra PDFs likelihood for signal and backgrounds this->getEvtExtraLikelihoods(iEvt); // If appropriate, combine the TM and SCF likelihoods Double_t sigLike = sigDPLike_ * sigExtraLike_; if ( useSCF_ ) { Double_t scfFrac(0.0); if (useSCFHist_) { scfFrac = recoSCFFracs_[iEvt]; } else { scfFrac = scfFrac_.unblindValue(); } sigLike *= (1.0 - scfFrac); if ( (scfMap_ != 0) && (this->useDP() == kTRUE) ) { // if we're smearing the SCF DP PDF then the SCF frac // is already included in the SCF DP likelihood sigLike += (scfDPLike_ * scfExtraLike_); } else { sigLike += (scfFrac * scfDPLike_ * scfExtraLike_); } } // Get the correct event fractions depending on the charge // Signal asymmetry is built into the DP model... but when the DP // isn't in the fit we need an explicit parameter Double_t signalEvents = signalEvents_->unblindValue() * 0.5; if (this->useDP() == kFALSE) { signalEvents *= (1.0 - curEvtCharge_ * signalAsym_->unblindValue()); } // Construct the total event likelihood Double_t likelihood(0.0); if (usingBkgnd_) { likelihood = sigLike*signalEvents; const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) { Double_t bkgndEvents = bkgndEvents_[bkgndID]->unblindValue() * 0.5 * (1.0 - curEvtCharge_ * bkgndAsym_[bkgndID]->unblindValue()); likelihood += bkgndEvents*bkgndDPLike_[bkgndID]*bkgndExtraLike_[bkgndID]; } } else { likelihood = sigLike*0.5; } return likelihood; } Double_t LauCPFitModel::getEventSum() const { Double_t eventSum(0.0); eventSum += signalEvents_->unblindValue(); if (usingBkgnd_) { for (LauBkgndYieldList::const_iterator iter = bkgndEvents_.begin(); iter != bkgndEvents_.end(); ++iter) { eventSum += (*iter)->unblindValue(); } } return eventSum; } void LauCPFitModel::getEvtDPLikelihood(UInt_t iEvt) { // Function to return the signal and background likelihoods for the // Dalitz plot for the given event evtNo. if ( ! this->useDP() ) { // There's always going to be a term in the likelihood for the // signal, so we'd better not zero it. sigDPLike_ = 1.0; scfDPLike_ = 1.0; const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) { if (usingBkgnd_ == kTRUE) { bkgndDPLike_[bkgndID] = 1.0; } else { bkgndDPLike_[bkgndID] = 0.0; } } return; } const UInt_t nBkgnds = this->nBkgndClasses(); if ( tagged_ ) { if (curEvtCharge_==+1) { posSigModel_->calcLikelihoodInfo(iEvt); sigDPLike_ = posSigModel_->getEvtIntensity(); for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) { if (usingBkgnd_ == kTRUE) { bkgndDPLike_[bkgndID] = posBkgndDPModels_[bkgndID]->getLikelihood(iEvt); } else { bkgndDPLike_[bkgndID] = 0.0; } } } else { negSigModel_->calcLikelihoodInfo(iEvt); sigDPLike_ = negSigModel_->getEvtIntensity(); for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) { if (usingBkgnd_ == kTRUE) { bkgndDPLike_[bkgndID] = negBkgndDPModels_[bkgndID]->getLikelihood(iEvt); } else { bkgndDPLike_[bkgndID] = 0.0; } } } } else { posSigModel_->calcLikelihoodInfo(iEvt); negSigModel_->calcLikelihoodInfo(iEvt); sigDPLike_ = 0.5 * ( posSigModel_->getEvtIntensity() + negSigModel_->getEvtIntensity() ); for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) { if (usingBkgnd_ == kTRUE) { bkgndDPLike_[bkgndID] = 0.5 * ( posBkgndDPModels_[bkgndID]->getLikelihood(iEvt) + negBkgndDPModels_[bkgndID]->getLikelihood(iEvt) ); } else { bkgndDPLike_[bkgndID] = 0.0; } } } if ( useSCF_ == kTRUE ) { if ( scfMap_ == 0 ) { // we're not smearing the SCF DP position // so the likelihood is the same as the TM scfDPLike_ = sigDPLike_; } else { // calculate the smeared SCF DP likelihood scfDPLike_ = this->getEvtSCFDPLikelihood(iEvt); } } // Calculate the signal normalisation // NB the 2.0 is there so that the 0.5 factor is applied to // signal and background in the same place otherwise you get // normalisation problems when you switch off the DP in the fit Double_t norm = negSigModel_->getDPNorm() + posSigModel_->getDPNorm(); sigDPLike_ *= 2.0/norm; scfDPLike_ *= 2.0/norm; } Double_t LauCPFitModel::getEvtSCFDPLikelihood(UInt_t iEvt) { Double_t scfDPLike(0.0); Double_t recoJacobian(1.0); Double_t xCoord(0.0); Double_t yCoord(0.0); Bool_t squareDP = negKinematics_->squareDP(); if ( squareDP ) { xCoord = negSigModel_->getEvtmPrime(); yCoord = negSigModel_->getEvtthPrime(); recoJacobian = recoJacobians_[iEvt]; } else { xCoord = negSigModel_->getEvtm13Sq(); yCoord = negSigModel_->getEvtm23Sq(); } // Find the bin that our reco event falls in Int_t recoBin = scfMap_->binNumber( xCoord, yCoord ); // Find out which true Bins contribute to the given reco bin const std::vector* trueBins = scfMap_->trueBins(recoBin); const Int_t nDataEvents = this->eventsPerExpt(); // Loop over the true bins for (std::vector::const_iterator iter = trueBins->begin(); iter != trueBins->end(); ++iter) { Int_t trueBin = (*iter); // prob of a true event in the given true bin migrating to the reco bin Double_t pRecoGivenTrue = scfMap_->prob( recoBin, trueBin ); Double_t pTrue(0.0); // We've cached the DP amplitudes and the efficiency for the // true bin centres, just after the data points if ( tagged_ ) { LauIsobarDynamics* sigModel(0); if (curEvtCharge_<0) { sigModel = negSigModel_; } else { sigModel = posSigModel_; } sigModel->calcLikelihoodInfo( nDataEvents + trueBin ); pTrue = sigModel->getEvtIntensity(); } else { posSigModel_->calcLikelihoodInfo( nDataEvents + trueBin ); negSigModel_->calcLikelihoodInfo( nDataEvents + trueBin ); pTrue = 0.5 * ( posSigModel_->getEvtIntensity() + negSigModel_->getEvtIntensity() ); } // Get the cached SCF fraction (and jacobian if we're using the square DP) Double_t scfFraction = fakeSCFFracs_[ trueBin ]; Double_t jacobian(1.0); if ( squareDP ) { jacobian = fakeJacobians_[ trueBin ]; } scfDPLike += pTrue * jacobian * scfFraction * pRecoGivenTrue; } // Divide by the reco jacobian scfDPLike /= recoJacobian; return scfDPLike; } void LauCPFitModel::getEvtExtraLikelihoods(UInt_t iEvt) { // Function to return the signal and background likelihoods for the // extra variables for the given event evtNo. sigExtraLike_ = 1.0; const UInt_t nBkgnds = this->nBkgndClasses(); if ( ! tagged_ || curEvtCharge_ < 0 ) { sigExtraLike_ = this->prodPdfValue( negSignalPdfs_, iEvt ); if (useSCF_) { scfExtraLike_ = this->prodPdfValue( negScfPdfs_, iEvt ); } for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) { if (usingBkgnd_) { bkgndExtraLike_[bkgndID] = this->prodPdfValue( negBkgndPdfs_[bkgndID], iEvt ); } else { bkgndExtraLike_[bkgndID] = 0.0; } } } else { sigExtraLike_ = this->prodPdfValue( posSignalPdfs_, iEvt ); if (useSCF_) { scfExtraLike_ = this->prodPdfValue( posScfPdfs_, iEvt ); } for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) { if (usingBkgnd_) { bkgndExtraLike_[bkgndID] = this->prodPdfValue( posBkgndPdfs_[bkgndID], iEvt ); } else { bkgndExtraLike_[bkgndID] = 0.0; } } } } void LauCPFitModel::updateCoeffs() { negCoeffs_.clear(); posCoeffs_.clear(); negCoeffs_.reserve(nSigComp_); posCoeffs_.reserve(nSigComp_); for (UInt_t i = 0; i < nSigComp_; i++) { negCoeffs_.push_back(coeffPars_[i]->antiparticleCoeff()); posCoeffs_.push_back(coeffPars_[i]->particleCoeff()); } } void LauCPFitModel::setupSPlotNtupleBranches() { // add branches for storing the experiment number and the number of // the event within the current experiment this->addSPlotNtupleIntegerBranch("iExpt"); this->addSPlotNtupleIntegerBranch("iEvtWithinExpt"); // Store the efficiency of the event (for inclusive BF calculations). if (this->storeDPEff()) { this->addSPlotNtupleDoubleBranch("efficiency"); if ( negSigModel_->usingScfModel() && posSigModel_->usingScfModel() ) { this->addSPlotNtupleDoubleBranch("scffraction"); } } // Store the total event likelihood for each species. if (useSCF_) { this->addSPlotNtupleDoubleBranch("sigTMTotalLike"); this->addSPlotNtupleDoubleBranch("sigSCFTotalLike"); this->addSPlotNtupleDoubleBranch("sigSCFFrac"); } else { this->addSPlotNtupleDoubleBranch("sigTotalLike"); } if (usingBkgnd_) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { TString name( this->bkgndClassName(iBkgnd) ); name += "TotalLike"; this->addSPlotNtupleDoubleBranch(name); } } // Store the DP likelihoods if (this->useDP()) { if (useSCF_) { this->addSPlotNtupleDoubleBranch("sigTMDPLike"); this->addSPlotNtupleDoubleBranch("sigSCFDPLike"); } else { this->addSPlotNtupleDoubleBranch("sigDPLike"); } if (usingBkgnd_) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { TString name( this->bkgndClassName(iBkgnd) ); name += "DPLike"; this->addSPlotNtupleDoubleBranch(name); } } } // Store the likelihoods for each extra PDF if (useSCF_) { this->addSPlotNtupleBranches(&negSignalPdfs_, "sigTM"); this->addSPlotNtupleBranches(&negScfPdfs_, "sigSCF"); } else { this->addSPlotNtupleBranches(&negSignalPdfs_, "sig"); } if (usingBkgnd_) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { const TString& bkgndClass = this->bkgndClassName(iBkgnd); const LauPdfList* pdfList = &(negBkgndPdfs_[iBkgnd]); this->addSPlotNtupleBranches(pdfList, bkgndClass); } } } void LauCPFitModel::addSPlotNtupleBranches(const LauPdfList* extraPdfs, const TString& prefix) { if (extraPdfs) { // Loop through each of the PDFs for (LauPdfList::const_iterator pdf_iter = extraPdfs->begin(); pdf_iter != extraPdfs->end(); ++pdf_iter) { // Count the number of input variables that are not // DP variables (used in the case where there is DP // dependence for e.g. MVA) UInt_t nVars(0); std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { ++nVars; } } if ( nVars == 1 ) { // If the PDF only has one variable then // simply add one branch for that variable TString varName = (*pdf_iter)->varName(); TString name(prefix); name += varName; name += "Like"; this->addSPlotNtupleDoubleBranch(name); } else if ( nVars == 2 ) { // If the PDF has two variables then we // need a branch for them both together and // branches for each TString allVars(""); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { allVars += (*var_iter); TString name(prefix); name += (*var_iter); name += "Like"; this->addSPlotNtupleDoubleBranch(name); } TString name(prefix); name += allVars; name += "Like"; this->addSPlotNtupleDoubleBranch(name); } else { std::cerr << "WARNING in LauCPFitModel::addSPlotNtupleBranches : Can't yet deal with 3D PDFs." << std::endl; } } } } Double_t LauCPFitModel::setSPlotNtupleBranchValues(LauPdfList* extraPdfs, const TString& prefix, UInt_t iEvt) { // Store the PDF value for each variable in the list Double_t totalLike(1.0); Double_t extraLike(0.0); if (extraPdfs) { for (LauPdfList::iterator pdf_iter = extraPdfs->begin(); pdf_iter != extraPdfs->end(); ++pdf_iter) { // calculate the likelihood for this event (*pdf_iter)->calcLikelihoodInfo(iEvt); extraLike = (*pdf_iter)->getLikelihood(); totalLike *= extraLike; // Count the number of input variables that are not // DP variables (used in the case where there is DP // dependence for e.g. MVA) UInt_t nVars(0); std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { ++nVars; } } if ( nVars == 1 ) { // If the PDF only has one variable then // simply store the value for that variable TString varName = (*pdf_iter)->varName(); TString name(prefix); name += varName; name += "Like"; this->setSPlotNtupleDoubleBranchValue(name, extraLike); } else if ( nVars == 2 ) { // If the PDF has two variables then we // store the value for them both together // and for each on their own TString allVars(""); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { allVars += (*var_iter); TString name(prefix); name += (*var_iter); name += "Like"; Double_t indivLike = (*pdf_iter)->getLikelihood( (*var_iter) ); this->setSPlotNtupleDoubleBranchValue(name, indivLike); } TString name(prefix); name += allVars; name += "Like"; this->setSPlotNtupleDoubleBranchValue(name, extraLike); } else { std::cerr << "WARNING in LauCPFitModel::setSPlotNtupleBranchValues : Can't yet deal with 3D PDFs." << std::endl; } } } return totalLike; } LauSPlot::NameSet LauCPFitModel::variableNames() const { LauSPlot::NameSet nameSet; if (this->useDP()) { nameSet.insert("DP"); } // Loop through all the signal PDFs for (LauPdfList::const_iterator pdf_iter = negSignalPdfs_.begin(); pdf_iter != negSignalPdfs_.end(); ++pdf_iter) { // Loop over the variables involved in each PDF std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { // If they are not DP coordinates then add them if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { nameSet.insert( (*var_iter) ); } } } return nameSet; } LauSPlot::NumbMap LauCPFitModel::freeSpeciesNames() const { LauSPlot::NumbMap numbMap; if (!signalEvents_->fixed() && this->doEMLFit()) { numbMap["sig"] = signalEvents_->genValue(); } if ( usingBkgnd_ ) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { const TString& bkgndClass = this->bkgndClassName(iBkgnd); const LauAbsRValue* par = bkgndEvents_[iBkgnd]; if (!par->fixed()) { numbMap[bkgndClass] = par->genValue(); if ( ! par->isLValue() ) { std::cerr << "WARNING in LauCPFitModel::freeSpeciesNames : \"" << par->name() << "\" is a LauFormulaPar, which implies it is perhaps not entirely free to float in the fit, so the sWeight calculation may not be reliable" << std::endl; } } } } return numbMap; } LauSPlot::NumbMap LauCPFitModel::fixdSpeciesNames() const { LauSPlot::NumbMap numbMap; if (signalEvents_->fixed() && this->doEMLFit()) { numbMap["sig"] = signalEvents_->genValue(); } if ( usingBkgnd_ ) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { const TString& bkgndClass = this->bkgndClassName(iBkgnd); const LauAbsRValue* par = bkgndEvents_[iBkgnd]; if (par->fixed()) { numbMap[bkgndClass] = par->genValue(); } } } return numbMap; } LauSPlot::TwoDMap LauCPFitModel::twodimPDFs() const { // This makes the assumption that the form of the positive and // negative PDFs are the same, which seems reasonable to me LauSPlot::TwoDMap twodimMap; for (LauPdfList::const_iterator pdf_iter = negSignalPdfs_.begin(); pdf_iter != negSignalPdfs_.end(); ++pdf_iter) { // Count the number of input variables that are not DP variables UInt_t nVars(0); std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { ++nVars; } } if ( nVars == 2 ) { if (useSCF_) { twodimMap.insert( std::make_pair( "sigTM", std::make_pair( varNames[0], varNames[1] ) ) ); } else { twodimMap.insert( std::make_pair( "sig", std::make_pair( varNames[0], varNames[1] ) ) ); } } } if ( useSCF_ ) { for (LauPdfList::const_iterator pdf_iter = negScfPdfs_.begin(); pdf_iter != negScfPdfs_.end(); ++pdf_iter) { // Count the number of input variables that are not DP variables UInt_t nVars(0); std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { ++nVars; } } if ( nVars == 2 ) { twodimMap.insert( std::make_pair( "sigSCF", std::make_pair( varNames[0], varNames[1] ) ) ); } } } if (usingBkgnd_) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { const TString& bkgndClass = this->bkgndClassName(iBkgnd); const LauPdfList& pdfList = negBkgndPdfs_[iBkgnd]; for (LauPdfList::const_iterator pdf_iter = pdfList.begin(); pdf_iter != pdfList.end(); ++pdf_iter) { // Count the number of input variables that are not DP variables UInt_t nVars(0); std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { ++nVars; } } if ( nVars == 2 ) { twodimMap.insert( std::make_pair( bkgndClass, std::make_pair( varNames[0], varNames[1] ) ) ); } } } } return twodimMap; } void LauCPFitModel::storePerEvtLlhds() { std::cout << "INFO in LauCPFitModel::storePerEvtLlhds : Storing per-event likelihood values..." << std::endl; // if we've not been using the DP model then we need to cache all // the info here so that we can get the efficiency from it LauFitDataTree* inputFitData = this->fitData(); if (!this->useDP() && this->storeDPEff()) { negSigModel_->initialise(negCoeffs_); posSigModel_->initialise(posCoeffs_); negSigModel_->fillDataTree(*inputFitData); posSigModel_->fillDataTree(*inputFitData); } UInt_t evtsPerExpt(this->eventsPerExpt()); LauIsobarDynamics* sigModel(0); LauPdfList* sigPdfs(0); LauPdfList* scfPdfs(0); LauBkgndPdfsList* bkgndPdfs(0); for (UInt_t iEvt = 0; iEvt < evtsPerExpt; ++iEvt) { this->setSPlotNtupleIntegerBranchValue("iExpt",this->iExpt()); this->setSPlotNtupleIntegerBranchValue("iEvtWithinExpt",iEvt); // Find out whether we have B- or B+ if ( tagged_ ) { const LauFitData& dataValues = inputFitData->getData(iEvt); LauFitData::const_iterator iter = dataValues.find("charge"); curEvtCharge_ = static_cast(iter->second); if (curEvtCharge_==+1) { sigModel = posSigModel_; sigPdfs = &posSignalPdfs_; scfPdfs = &posScfPdfs_; bkgndPdfs = &posBkgndPdfs_; } else { sigModel = negSigModel_; sigPdfs = &negSignalPdfs_; scfPdfs = &negScfPdfs_; bkgndPdfs = &negBkgndPdfs_; } } else { sigPdfs = &negSignalPdfs_; scfPdfs = &negScfPdfs_; bkgndPdfs = &negBkgndPdfs_; } // the DP information this->getEvtDPLikelihood(iEvt); if (this->storeDPEff()) { if (!this->useDP()) { posSigModel_->calcLikelihoodInfo(iEvt); negSigModel_->calcLikelihoodInfo(iEvt); } if ( tagged_ ) { this->setSPlotNtupleDoubleBranchValue("efficiency",sigModel->getEvtEff()); if ( negSigModel_->usingScfModel() && posSigModel_->usingScfModel() ) { this->setSPlotNtupleDoubleBranchValue("scffraction",sigModel->getEvtScfFraction()); } } else { this->setSPlotNtupleDoubleBranchValue("efficiency",0.5*(posSigModel_->getEvtEff() + negSigModel_->getEvtEff()) ); if ( negSigModel_->usingScfModel() && posSigModel_->usingScfModel() ) { this->setSPlotNtupleDoubleBranchValue("scffraction",0.5*(posSigModel_->getEvtScfFraction() + negSigModel_->getEvtScfFraction())); } } } if (this->useDP()) { sigTotalLike_ = sigDPLike_; if (useSCF_) { scfTotalLike_ = scfDPLike_; this->setSPlotNtupleDoubleBranchValue("sigTMDPLike",sigDPLike_); this->setSPlotNtupleDoubleBranchValue("sigSCFDPLike",scfDPLike_); } else { this->setSPlotNtupleDoubleBranchValue("sigDPLike",sigDPLike_); } if (usingBkgnd_) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { TString name = this->bkgndClassName(iBkgnd); name += "DPLike"; this->setSPlotNtupleDoubleBranchValue(name,bkgndDPLike_[iBkgnd]); } } } else { sigTotalLike_ = 1.0; if (useSCF_) { scfTotalLike_ = 1.0; } if (usingBkgnd_) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { bkgndTotalLike_[iBkgnd] = 1.0; } } } // the signal PDF values if ( useSCF_ ) { sigTotalLike_ *= this->setSPlotNtupleBranchValues(sigPdfs, "sigTM", iEvt); scfTotalLike_ *= this->setSPlotNtupleBranchValues(scfPdfs, "sigSCF", iEvt); } else { sigTotalLike_ *= this->setSPlotNtupleBranchValues(sigPdfs, "sig", iEvt); } // the background PDF values if (usingBkgnd_) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { const TString& bkgndClass = this->bkgndClassName(iBkgnd); LauPdfList& pdfs = (*bkgndPdfs)[iBkgnd]; bkgndTotalLike_[iBkgnd] *= this->setSPlotNtupleBranchValues(&(pdfs), bkgndClass, iEvt); } } // the total likelihoods if (useSCF_) { Double_t scfFrac(0.0); if ( useSCFHist_ ) { scfFrac = recoSCFFracs_[iEvt]; } else { scfFrac = scfFrac_.unblindValue(); } this->setSPlotNtupleDoubleBranchValue("sigSCFFrac",scfFrac); sigTotalLike_ *= ( 1.0 - scfFrac ); if ( scfMap_ == 0 ) { scfTotalLike_ *= scfFrac; } this->setSPlotNtupleDoubleBranchValue("sigTMTotalLike",sigTotalLike_); this->setSPlotNtupleDoubleBranchValue("sigSCFTotalLike",scfTotalLike_); } else { this->setSPlotNtupleDoubleBranchValue("sigTotalLike",sigTotalLike_); } if (usingBkgnd_) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { TString name = this->bkgndClassName(iBkgnd); name += "TotalLike"; this->setSPlotNtupleDoubleBranchValue(name,bkgndTotalLike_[iBkgnd]); } } // fill the tree this->fillSPlotNtupleBranches(); } std::cout << "INFO in LauCPFitModel::storePerEvtLlhds : Finished storing per-event likelihood values." << std::endl; } void LauCPFitModel::embedNegSignal(const TString& fileName, const TString& treeName, Bool_t reuseEventsWithinEnsemble, Bool_t reuseEventsWithinExperiment, Bool_t useReweighting) { if (negSignalTree_) { std::cerr << "ERROR in LauCPFitModel::embedNegSignal : Already embedding signal from a file." << std::endl; return; } negSignalTree_ = new LauEmbeddedData(fileName,treeName,reuseEventsWithinExperiment); Bool_t dataOK = negSignalTree_->findBranches(); if (!dataOK) { delete negSignalTree_; negSignalTree_ = 0; std::cerr << "ERROR in LauCPFitModel::embedNegSignal : Problem creating data tree for embedding." << std::endl; return; } reuseSignal_ = reuseEventsWithinEnsemble; useNegReweighting_ = useReweighting; if (this->enableEmbedding() == kFALSE) {this->enableEmbedding(kTRUE);} } void LauCPFitModel::embedNegBkgnd(const TString& bkgndClass, const TString& fileName, const TString& treeName, Bool_t reuseEventsWithinEnsemble, Bool_t reuseEventsWithinExperiment) { if ( ! this->validBkgndClass( bkgndClass ) ) { std::cerr << "ERROR in LauCPFitModel::embedBkgnd : Invalid background class \"" << bkgndClass << "\"." << std::endl; std::cerr << " : Background class names must be provided in \"setBkgndClassNames\" before any other background-related actions can be performed." << std::endl; return; } UInt_t bkgndID = this->bkgndClassID( bkgndClass ); if (negBkgndTree_[bkgndID]) { std::cerr << "ERROR in LauCPFitModel::embedNegBkgnd : Already embedding background from a file." << std::endl; return; } negBkgndTree_[bkgndID] = new LauEmbeddedData(fileName,treeName,reuseEventsWithinExperiment); Bool_t dataOK = negBkgndTree_[bkgndID]->findBranches(); if (!dataOK) { delete negBkgndTree_[bkgndID]; negBkgndTree_[bkgndID] = 0; std::cerr << "ERROR in LauCPFitModel::embedNegBkgnd : Problem creating data tree for embedding." << std::endl; return; } reuseBkgnd_[bkgndID] = reuseEventsWithinEnsemble; if (this->enableEmbedding() == kFALSE) {this->enableEmbedding(kTRUE);} } void LauCPFitModel::embedPosSignal(const TString& fileName, const TString& treeName, Bool_t reuseEventsWithinEnsemble, Bool_t reuseEventsWithinExperiment, Bool_t useReweighting) { if (posSignalTree_) { std::cerr << "ERROR in LauCPFitModel::embedPosSignal : Already embedding signal from a file." << std::endl; return; } posSignalTree_ = new LauEmbeddedData(fileName,treeName,reuseEventsWithinExperiment); Bool_t dataOK = posSignalTree_->findBranches(); if (!dataOK) { delete posSignalTree_; posSignalTree_ = 0; std::cerr << "ERROR in LauCPFitModel::embedPosSignal : Problem creating data tree for embedding." << std::endl; return; } reuseSignal_ = reuseEventsWithinEnsemble; usePosReweighting_ = useReweighting; if (this->enableEmbedding() == kFALSE) {this->enableEmbedding(kTRUE);} } void LauCPFitModel::embedPosBkgnd(const TString& bkgndClass, const TString& fileName, const TString& treeName, Bool_t reuseEventsWithinEnsemble, Bool_t reuseEventsWithinExperiment) { if ( ! this->validBkgndClass( bkgndClass ) ) { std::cerr << "ERROR in LauCPFitModel::embedBkgnd : Invalid background class \"" << bkgndClass << "\"." << std::endl; std::cerr << " : Background class names must be provided in \"setBkgndClassNames\" before any other background-related actions can be performed." << std::endl; return; } UInt_t bkgndID = this->bkgndClassID( bkgndClass ); if (posBkgndTree_[bkgndID]) { std::cerr << "ERROR in LauCPFitModel::embedPosBkgnd : Already embedding background from a file." << std::endl; return; } posBkgndTree_[bkgndID] = new LauEmbeddedData(fileName,treeName,reuseEventsWithinExperiment); Bool_t dataOK = posBkgndTree_[bkgndID]->findBranches(); if (!dataOK) { delete posBkgndTree_[bkgndID]; posBkgndTree_[bkgndID] = 0; std::cerr << "ERROR in LauCPFitModel::embedPosBkgnd : Problem creating data tree for embedding." << std::endl; return; } reuseBkgnd_[bkgndID] = reuseEventsWithinEnsemble; if (this->enableEmbedding() == kFALSE) {this->enableEmbedding(kTRUE);} } void LauCPFitModel::weightEvents( const TString& dataFileName, const TString& dataTreeName ) { // Routine to provide weights for events that are uniformly distributed // in the DP (or square DP) so as to reproduce the given DP model if ( posKinematics_->squareDP() ) { std::cout << "INFO in LauCPFitModel::weightEvents : will create weights assuming events were generated flat in the square DP" << std::endl; } else { std::cout << "INFO in LauCPFitModel::weightEvents : will create weights assuming events were generated flat in phase space" << std::endl; } // This reads in the given dataFile and creates an input // fit data tree that stores them for all events and experiments. Bool_t dataOK = this->verifyFitData(dataFileName,dataTreeName); if (!dataOK) { std::cerr << "ERROR in LauCPFitModel::weightEvents : Problem caching the data." << std::endl; return; } LauFitDataTree* inputFitData = this->fitData(); if ( ! inputFitData->haveBranch( "m13Sq_MC" ) || ! inputFitData->haveBranch( "m23Sq_MC" ) ) { std::cerr << "WARNING in LauCPFitModel::weightEvents : Cannot find MC truth DP coordinate branches in supplied data, aborting." << std::endl; return; } if ( ! inputFitData->haveBranch( "charge" ) ) { std::cerr << "WARNING in LauCPFitModel::weightEvents : Cannot find branch specifying event charge in supplied data, aborting." << std::endl; return; } // Create the ntuple to hold the DP weights TString weightsFileName( dataFileName ); Ssiz_t index = weightsFileName.Last('.'); weightsFileName.Insert( index, "_DPweights" ); LauGenNtuple * weightsTuple = new LauGenNtuple( weightsFileName, dataTreeName ); weightsTuple->addIntegerBranch("iExpt"); weightsTuple->addIntegerBranch("iEvtWithinExpt"); weightsTuple->addDoubleBranch("dpModelWeight"); UInt_t iExpmt = this->iExpt(); UInt_t nExpmt = this->nExpt(); UInt_t firstExpmt = this->firstExpt(); for (iExpmt = firstExpmt; iExpmt < (firstExpmt+nExpmt); ++iExpmt) { inputFitData->readExperimentData(iExpmt); UInt_t nEvents = inputFitData->nEvents(); if (nEvents < 1) { std::cerr << "WARNING in LauCPFitModel::weightEvents : Zero events in experiment " << iExpmt << ", skipping..." << std::endl; continue; } weightsTuple->setIntegerBranchValue( "iExpt", iExpmt ); // Calculate and store the weights for the events in this experiment for ( UInt_t iEvent(0); iEvent < nEvents; ++iEvent ) { weightsTuple->setIntegerBranchValue( "iEvtWithinExpt", iEvent ); const LauFitData& evtData = inputFitData->getData( iEvent ); Double_t m13Sq_MC = evtData.find("m13Sq_MC")->second; Double_t m23Sq_MC = evtData.find("m23Sq_MC")->second; Int_t charge = evtData.find("charge")->second; Double_t dpModelWeight(0.0); LauKinematics * kinematics; LauIsobarDynamics * dpModel; if (charge > 0) { kinematics = posKinematics_; dpModel = posSigModel_; } else { kinematics = negKinematics_; dpModel = negSigModel_; } if ( kinematics->withinDPLimits( m13Sq_MC, m23Sq_MC ) ) { kinematics->updateKinematics( m13Sq_MC, m23Sq_MC ); dpModelWeight = dpModel->getEventWeight(); if ( kinematics->squareDP() ) { dpModelWeight *= kinematics->calcSqDPJacobian(); } const Double_t norm = (negSigModel_->getDPNorm() + posSigModel_->getDPNorm())/2.0; dpModelWeight /= norm; } weightsTuple->setDoubleBranchValue( "dpModelWeight", dpModelWeight ); weightsTuple->fillBranches(); } } weightsTuple->buildIndex( "iExpt", "iEvtWithinExpt" ); weightsTuple->addFriendTree(dataFileName, dataTreeName); weightsTuple->writeOutGenResults(); delete weightsTuple; } void LauCPFitModel::savePDFPlots(const TString& label) { savePDFPlotsWave(label, 0); savePDFPlotsWave(label, 1); savePDFPlotsWave(label, 2); std::cout << "LauCPFitModel::plot" << std::endl; // ((LauIsobarDynamics*)negSigModel_)->plot(); //Double_t minm13 = negSigModel_->getKinematics()->getm13Min(); Double_t minm13 = 0.0; Double_t maxm13 = negSigModel_->getKinematics()->getm13Max(); //Double_t minm23 = negSigModel_->getKinematics()->getm23Min(); Double_t minm23 = 0.0; Double_t maxm23 = negSigModel_->getKinematics()->getm23Max(); Double_t mins13 = minm13*minm13; Double_t maxs13 = maxm13*maxm13; Double_t mins23 = minm23*minm23; Double_t maxs23 = maxm23*maxm23; Double_t s13, s23, posChPdf, negChPdf; TString xLabel = "s13"; TString yLabel = "s23"; if (negSigModel_->getDaughters()->gotSymmetricalDP()) { xLabel = "sHigh"; yLabel = "sLow";} Int_t n13=200.00, n23=200.00; Double_t delta13, delta23; delta13 = (maxs13 - mins13)/n13; delta23 = (maxs23 - mins23)/n23; UInt_t nAmp = negSigModel_->getnCohAmp(); for (UInt_t resID = 0; resID <= nAmp; ++resID) { TGraph2D *posDt = new TGraph2D(); TGraph2D *negDt = new TGraph2D(); TGraph2D *acpDt = new TGraph2D(); TString resName = "TotalAmp"; if (resID != nAmp){ TString tStrResID = Form("%d", resID); const LauIsobarDynamics* model = negSigModel_; const LauAbsResonance* resonance = model->getResonance(resID); resName = resonance->getResonanceName(); std::cout << "resName = " << resName << std::endl; } resName.ReplaceAll("(", ""); resName.ReplaceAll(")", ""); resName.ReplaceAll("*", "Star"); posDt->SetName(resName+label); posDt->SetTitle(resName+" ("+label+") Positive"); negDt->SetName(resName+label); negDt->SetTitle(resName+" ("+label+") Negative"); acpDt->SetName(resName+label); acpDt->SetTitle(resName+" ("+label+") Asymmetry"); Int_t count=0; for (Int_t i=0; igetKinematics()->withinDPLimits2(s23, s13)) { if (negSigModel_->getDaughters()->gotSymmetricalDP() && (s13>s23) ) continue; negSigModel_->calcLikelihoodInfo(s13, s23); posSigModel_->calcLikelihoodInfo(s13, s23); LauComplex negChAmp = negSigModel_->getEvtDPAmp(); LauComplex posChAmp = posSigModel_->getEvtDPAmp(); if (resID != nAmp){ negChAmp = negSigModel_->getFullAmplitude(resID); posChAmp = posSigModel_->getFullAmplitude(resID); } negChPdf = negChAmp.abs2(); posChPdf = posChAmp.abs2(); negDt->SetPoint(count,s23,s13,negChPdf); // s23=sHigh, s13 = sLow posDt->SetPoint(count,s23,s13,posChPdf); // s23=sHigh, s13 = sLow acpDt->SetPoint(count,s23,s13, negChPdf - posChPdf); // s23=sHigh, s13 = sLow count++; } } } gStyle->SetPalette(1); TCanvas *posC = new TCanvas("c"+resName+label + "Positive",resName+" ("+label+") Positive",0,0,600,400); posDt->GetXaxis()->SetTitle(xLabel); posDt->GetYaxis()->SetTitle(yLabel); posDt->Draw("SURF1"); posDt->GetXaxis()->SetTitle(xLabel); posDt->GetYaxis()->SetTitle(yLabel); posC->SaveAs("plot_2D_"+resName + "_"+label+"Positive.C"); TCanvas *negC = new TCanvas("c"+resName+label + "Negative",resName+" ("+label+") Negative",0,0,600,400); negDt->GetXaxis()->SetTitle(xLabel); negDt->GetYaxis()->SetTitle(yLabel); negDt->Draw("SURF1"); negDt->GetXaxis()->SetTitle(xLabel); negDt->GetYaxis()->SetTitle(yLabel); negC->SaveAs("plot_2D_"+resName + "_"+label+"Negative.C"); TCanvas *acpC = new TCanvas("c"+resName+label + "Asymmetry",resName+" ("+label+") Asymmetry",0,0,600,400); acpDt->GetXaxis()->SetTitle(xLabel); acpDt->GetYaxis()->SetTitle(yLabel); acpDt->Draw("SURF1"); acpDt->GetXaxis()->SetTitle(xLabel); acpDt->GetYaxis()->SetTitle(yLabel); acpC->SaveAs("plot_2D_"+resName + "_"+label+"Asymmetry.C"); } } void LauCPFitModel::savePDFPlotsWave(const TString& label, const Int_t& spin) { std::cout << "label = "<< label << ", spin = "<< spin << std::endl; TString tStrResID = "S_Wave"; if (spin == 1) tStrResID = "P_Wave"; if (spin == 2) tStrResID = "D_Wave"; TString xLabel = "s13"; TString yLabel = "s23"; std::cout << "LauCPFitModel::savePDFPlotsWave: "<< tStrResID << std::endl; Double_t minm13 = 0.0; Double_t maxm13 = negSigModel_->getKinematics()->getm13Max(); Double_t minm23 = 0.0; Double_t maxm23 = negSigModel_->getKinematics()->getm23Max(); Double_t mins13 = minm13*minm13; Double_t maxs13 = maxm13*maxm13; Double_t mins23 = minm23*minm23; Double_t maxs23 = maxm23*maxm23; Double_t s13, s23, posChPdf, negChPdf; TGraph2D *posDt = new TGraph2D(); TGraph2D *negDt = new TGraph2D(); TGraph2D *acpDt = new TGraph2D(); posDt->SetName(tStrResID+label); posDt->SetTitle(tStrResID+" ("+label+") Positive"); negDt->SetName(tStrResID+label); negDt->SetTitle(tStrResID+" ("+label+") Negative"); acpDt->SetName(tStrResID+label); acpDt->SetTitle(tStrResID+" ("+label+") Asymmetry"); Int_t n13=200.00, n23=200.00; Double_t delta13, delta23; delta13 = (maxs13 - mins13)/n13; delta23 = (maxs23 - mins23)/n23; UInt_t nAmp = negSigModel_->getnCohAmp(); Int_t count=0; for (Int_t i=0; igetKinematics()->withinDPLimits2(s23, s13)) { if (negSigModel_->getDaughters()->gotSymmetricalDP() && (s13>s23) ) continue; LauComplex negChAmp(0,0); LauComplex posChAmp(0,0); Bool_t noWaveRes = kTRUE; negSigModel_->calcLikelihoodInfo(s13, s23); for (UInt_t resID = 0; resID < nAmp; ++resID) { const LauIsobarDynamics* model = negSigModel_; const LauAbsResonance* resonance = model->getResonance(resID); Int_t spin_res = resonance->getSpin(); if (spin != spin_res) continue; noWaveRes = kFALSE; negChAmp += negSigModel_->getFullAmplitude(resID); posChAmp += posSigModel_->getFullAmplitude(resID); } if (noWaveRes) return; negChPdf = negChAmp.abs2(); posChPdf = posChAmp.abs2(); negDt->SetPoint(count,s23,s13,negChPdf); // s23=sHigh, s13 = sLow posDt->SetPoint(count,s23,s13,posChPdf); // s23=sHigh, s13 = sLow acpDt->SetPoint(count,s23,s13, negChPdf - posChPdf); // s23=sHigh, s13 = sLow count++; } } } gStyle->SetPalette(1); TCanvas *posC = new TCanvas("c"+tStrResID+label + "Positive",tStrResID+" ("+label+") Positive",0,0,600,400); posDt->GetXaxis()->SetTitle(xLabel); posDt->GetYaxis()->SetTitle(yLabel); posDt->Draw("SURF1"); posDt->GetXaxis()->SetTitle(xLabel); posDt->GetYaxis()->SetTitle(yLabel); posC->SaveAs("plot_2D_"+tStrResID + "_"+label+"Positive.C"); TCanvas *negC = new TCanvas("c"+tStrResID+label + "Negative",tStrResID+" ("+label+") Negative",0,0,600,400); negDt->GetXaxis()->SetTitle(xLabel); negDt->GetYaxis()->SetTitle(yLabel); negDt->Draw("SURF1"); negDt->GetXaxis()->SetTitle(xLabel); negDt->GetYaxis()->SetTitle(yLabel); negC->SaveAs("plot_2D_"+tStrResID + "_"+label+"Negative.C"); TCanvas *acpC = new TCanvas("c"+tStrResID+label + "Asymmetry",tStrResID+" ("+label+") Asymmetry",0,0,600,400); acpDt->GetXaxis()->SetTitle(xLabel); acpDt->GetYaxis()->SetTitle(yLabel); acpDt->Draw("SURF1"); acpDt->GetXaxis()->SetTitle(xLabel); acpDt->GetYaxis()->SetTitle(yLabel); acpC->SaveAs("plot_2D_"+tStrResID + "_"+label+"Asymmetry.C"); } Double_t LauCPFitModel::getParamFromTree( TTree& tree, const TString& name ) { TBranch* branch{tree.FindBranch( name )}; if ( branch ) { TLeaf* leaf{branch->GetLeaf( name )}; if ( leaf ) { tree.GetEntry(0); return leaf->GetValue(); } else { std::cout << "ERROR in LauCPFitModel::getParamFromTree : Leaf name " + name + " not found in parameter file!" << std::endl; } } else { std::cout << "ERROR in LauCPFitModel::getParamFromTree : Branch name " + name + " not found in parameter file!" << std::endl; } return -1.1; } void LauCPFitModel::fixParam( LauParameter* param, const Double_t val, const Bool_t fix) { std::cout << "INFO in LauCPFitModel::fixParam : Setting " << param->name() << " to " << val << std::endl; param->value(val); param->genValue(val); param->initValue(val); if (fix) { param->fixed(kTRUE); } else if (!param->fixed()){ // Add parameter name to list to indicate that this should not be randomised by randomiseInitFitPars // (otherwise only those that are fixed are not randomised). // This is only done to those that are not already fixed (see randomiseInitFitPars). allImportedFreeParams_.insert(param); } } void LauCPFitModel::fixParams( std::vector& params ) { const Bool_t fix{fixParams_}; // TODO: Allow some parameters to be fixed and some to remain floating (but initialised) if ( !fixParamFileName_.IsNull() ) { // Take param values from a file TFile * paramFile = TFile::Open(fixParamFileName_, "READ"); if (!paramFile) { std::cerr << "ERROR in LauCPFitModel::fixParams : File '" + fixParamFileName_ + "' could not be opened for reading!" << std::endl; return; } TTree * paramTree = dynamic_cast(paramFile->Get(fixParamTreeName_)); if (!paramTree) { std::cerr << "ERROR in LauCPFitModel::fixParams : Tree '" + fixParamTreeName_ + "' not found in parameter file!" << std::endl; return; } if ( !fixParamNames_.empty() ) { // Fix params from file, according to vector of names for( auto itr = params.begin(); itr != params.end(); ++itr ) { auto itrName = fixParamNames_.find( (*itr)->name() ); if ( itrName != fixParamNames_.end() ) { this->fixParam(*itr, this->getParamFromTree(*paramTree, *itrName), fix); } } } else { // Fix some (unspecified) parameters from file, prioritising the map (if it exists) for( auto itr = params.begin(); itr != params.end(); ++itr) { const TString& name = (*itr)->name(); if ( ! fixParamMap_.empty() ) { auto nameValItr = fixParamMap_.find(name); if ( nameValItr != fixParamMap_.end() ) { this->fixParam(*itr, nameValItr->second, fix); } } else { this->fixParam(*itr, this->getParamFromTree(*paramTree, name), fix); } } } // Vector of names? } else { // Fix param names fom map, leave others floating for( auto itr = params.begin(); itr != params.end(); ++itr ) { auto nameValItr = this->fixParamMap_.find( (*itr)->name() ); if ( nameValItr != this->fixParamMap_.end() ) { this->fixParam(*itr, nameValItr->second, fix); } } } } diff --git a/src/LauCacheData.cc b/src/LauCacheData.cc index 2801928..4e134dd 100644 --- a/src/LauCacheData.cc +++ b/src/LauCacheData.cc @@ -1,79 +1,78 @@ /* Copyright 2005 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauCacheData.cc \brief File containing implementation of LauCacheData class. */ #include "LauCacheData.hh" -ClassImp(LauCacheData) LauCacheData::LauCacheData() : m13Sq_(0.0), m23Sq_(0.0), mPrime_(0.0), thPrime_(0.0), eff_(0.0), scfFraction_(0.0), jacobian_(0.0) { } LauCacheData::~LauCacheData() { } LauCacheData::LauCacheData(const LauCacheData& rhs) { this->storem13Sq(rhs.retrievem13Sq()); this->storem23Sq(rhs.retrievem23Sq()); this->storemPrime(rhs.retrievemPrime()); this->storethPrime(rhs.retrievethPrime()); this->storeEff(rhs.retrieveEff()); this->storeScfFraction(rhs.retrieveScfFraction()); this->storeJacobian(rhs.retrieveJacobian()); this->storeRealAmp(rhs.retrieveRealAmp()); this->storeImagAmp(rhs.retrieveImagAmp()); this->storeIncohIntensities(rhs.retrieveIncohIntensities()); } LauCacheData& LauCacheData::operator=(const LauCacheData& rhs) { if (&rhs != this) { this->storem13Sq(rhs.retrievem13Sq()); this->storem23Sq(rhs.retrievem23Sq()); this->storemPrime(rhs.retrievemPrime()); this->storethPrime(rhs.retrievethPrime()); this->storeEff(rhs.retrieveEff()); this->storeScfFraction(rhs.retrieveScfFraction()); this->storeJacobian(rhs.retrieveJacobian()); this->storeRealAmp(rhs.retrieveRealAmp()); this->storeImagAmp(rhs.retrieveImagAmp()); this->storeIncohIntensities(rhs.retrieveIncohIntensities()); } return *this; } diff --git a/src/LauCalcChiSq.cc b/src/LauCalcChiSq.cc index 5d7e31c..da5f589 100644 --- a/src/LauCalcChiSq.cc +++ b/src/LauCalcChiSq.cc @@ -1,544 +1,543 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ // Code to produce an adaptive binning scheme and calculate the 2D chi-square between // two datasets (e.g. low-stat data and high-stat toyMC). // To run the code, do "./CalcChiSq chiSqInput.txt", where chiSqInput.txt is // an input control file, and contains the following lines: // Low_stat_file_name Low_stat_histo_name // High_stat_file_name High_stat_histo_name // Min_bin_content N_free_params Low/high stat_histo_ratio // Note that the low and high stat histograms must have the same bin axes // ranges and number of bins. // It works by using the low stat (first) histogram to find a binning scheme such // that the total number of entries in each bin is >= Min_bin_content. The number // of entries in the histogram is divided by the desired minimum bin content to // give a target number of bins. The largest number of bins that can be expressed // as a product of powers of four, nine, 25, 49 and 121 that does not exceed the // target value is chosen. The histogram is the recursively subdivided in 2x2, 3x3, // 5x5, 7x7 or 11x11 bins. For each stage of the subdivision, each bin is first // divided into equally populated bins in x then each of these is further divded // into equally popiulated bins in y. // The (Pearson) chi-squared is then the sum of the chi-squared contributions // of all bins: // (low_stat_number - high_stat_number)^2/(high_stat_number) // The nDof = number of bins - number of free params - 1 #include "LauCalcChiSq.hh" #include "TAxis.h" #include "TFile.h" #include "TMath.h" #include "TSystem.h" #include "TTree.h" #include "TCanvas.h" #include "TColor.h" #include "TStyle.h" #include #include #include #include -ClassImp(LauCalcChiSq) LauCalcChiSq::LauCalcChiSq(const TString& inputFileName) : inputFileName_(inputFileName), fileName1_(""), fileName2_(""), treeName1_(""), treeName2_(""), xName1_(""), xName2_(""), yName1_(""), yName2_(""), minContent_(10.0), histo1_(0), histo2_(0), chiSqHisto_(0), chiSqSignedHisto_(0), xMin_(0.0), xMax_(0.0), yMin_(0.0), yMax_(0.0), nParams_(0), scaleFactor_(1.0), verbose_(kFALSE) { } LauCalcChiSq::~LauCalcChiSq() { } void LauCalcChiSq::run() { std::cout<<"Running chi-squared algorithm"<initialiseHistos(); std::cout<<"Calculating chi-squared"<calculateChiSq(); //make plots this->makePlots(); // Output the various histograms std::cout<<"Writing out histogram output"<SetDirectory(outFile); histo2_->SetDirectory(outFile); pullHisto_->SetDirectory(outFile); chiSqHisto_->SetDirectory(outFile); chiSqSignedHisto_->SetDirectory(outFile); outFile->Write(); outFile->Close(); std::cout<<"Done"<GetBinContent(1); for(Int_t i=1; i<=histo1_->GetNumberOfBins(); ++i) { //keep track of actual minimum if(histo1_->GetBinContent(i)GetBinContent(i); } // Calculate Pearson chi-square for this bin, using the // second histogram for the expected distribution chiSq = 0.; toyVal = histo2_->GetBinContent(i); dataVal = histo1_->GetBinContent(i); diff = dataVal-toyVal; if(toyVal>0) chiSq = (diff*diff)/toyVal; totalChiSq += chiSq; chiSqHisto_->SetBinContent(i, chiSq); if(diff>0) { chiSqSignedHisto_->SetBinContent(i, chiSq); pullHisto_->SetBinContent(i, sqrt(chiSq)); } else { chiSqSignedHisto_->SetBinContent(i, -chiSq); pullHisto_->SetBinContent(i, -sqrt(chiSq)); } } ndof = histo1_->GetNumberOfBins()-nParams_-1; std::cout<<"Total ChiSq/nDof = "<SetPalette(1,0); const Int_t NRGBs = 5; const Int_t NCont = 255; Double_t stops[NRGBs] = { 0.00, 0.34, 0.61, 0.84, 1.00}; Double_t red[NRGBs] = { 0.00, 0.00, 0.87, 1.00, 0.51}; Double_t green[NRGBs] = { 0.00, 0.81, 1.00, 0.20, 0.00}; Double_t blue[NRGBs] = { 0.51, 1.00, 0.12, 0.00, 0.00}; TColor::CreateGradientColorTable(NRGBs, stops, red, green, blue, NCont); gStyle->SetNumberContours(NCont); gStyle->SetOptStat(0000); TCanvas can; can.SetTopMargin(0.05); can.SetRightMargin(0.17); can.SetBottomMargin(0.16); can.SetLeftMargin(0.14); histo1_->SetLabelFont(62,"x"); histo1_->SetLabelFont(62,"y"); histo1_->SetTitleFont(62,"x"); histo1_->SetTitleFont(62,"y"); histo1_->SetTitleSize(0.06,"x"); histo1_->SetTitleSize(0.06,"y"); histo1_->SetLabelSize(0.05,"x"); histo1_->SetLabelSize(0.05,"y"); histo1_->SetXTitle(xName1_); histo1_->SetYTitle(yName1_); histo1_->Draw("colz"); can.SaveAs("data.pdf"); histo2_->SetLabelFont(62,"x"); histo2_->SetLabelFont(62,"y"); histo2_->SetTitleFont(62,"x"); histo2_->SetTitleFont(62,"y"); histo2_->SetTitleSize(0.06,"x"); histo2_->SetTitleSize(0.06,"y"); histo2_->SetLabelSize(0.05,"x"); histo2_->SetLabelSize(0.05,"y"); histo2_->SetXTitle(xName1_); histo2_->SetYTitle(yName1_); histo2_->Draw("colz"); can.SaveAs("toy.pdf"); if(-1.*pullHisto_->GetMinimum() > pullHisto_->GetMaximum()) pullHisto_->SetMaximum(-1.*pullHisto_->GetMinimum()); else pullHisto_->SetMinimum(-1.*pullHisto_->GetMaximum()); pullHisto_->SetLabelFont(62,"x"); pullHisto_->SetLabelFont(62,"y"); pullHisto_->SetTitleFont(62,"x"); pullHisto_->SetTitleFont(62,"y"); pullHisto_->SetTitleSize(0.06,"x"); pullHisto_->SetTitleSize(0.06,"y"); pullHisto_->SetLabelSize(0.05,"x"); pullHisto_->SetLabelSize(0.05,"y"); pullHisto_->SetXTitle(xName1_); pullHisto_->SetYTitle(yName1_); pullHisto_->Draw("colz"); can.SaveAs("pull.pdf"); chiSqHisto_->SetLabelFont(62,"x"); chiSqHisto_->SetLabelFont(62,"y"); chiSqHisto_->SetTitleFont(62,"x"); chiSqHisto_->SetTitleFont(62,"y"); chiSqHisto_->SetTitleSize(0.06,"x"); chiSqHisto_->SetTitleSize(0.06,"y"); chiSqHisto_->SetLabelSize(0.05,"x"); chiSqHisto_->SetLabelSize(0.05,"y"); chiSqHisto_->SetXTitle(xName1_); chiSqHisto_->SetYTitle(yName1_); chiSqHisto_->Draw("colz"); can.SaveAs("chiSq.pdf"); chiSqSignedHisto_->SetLabelFont(62,"x"); chiSqSignedHisto_->SetLabelFont(62,"y"); chiSqSignedHisto_->SetTitleFont(62,"x"); chiSqSignedHisto_->SetTitleFont(62,"y"); chiSqSignedHisto_->SetTitleSize(0.06,"x"); chiSqSignedHisto_->SetTitleSize(0.06,"y"); chiSqSignedHisto_->SetLabelSize(0.05,"x"); chiSqSignedHisto_->SetLabelSize(0.05,"y"); chiSqSignedHisto_->SetXTitle(xName1_); chiSqSignedHisto_->SetYTitle(yName1_); chiSqSignedHisto_->Draw("colz"); can.SaveAs("chiSqSigned.pdf"); } void LauCalcChiSq::initialiseHistos() { // Open the input control file: // Low_stat_file_name Low_stat_tree_name Low_stat_x_axis_name Low_stat_y_axis_name // High_stat_file_name High_stat_tree_name High_stat_x_axis_name High_stat_y_axis_name // Min_bin_content N_free_params Low/high_stat_histo_ratio xMin xMax yMin yMax std::ifstream getData(inputFileName_.Data()); // get the info on the low stat histo getData >> fileName1_ >> treeName1_ >> xName1_ >> yName1_; if (!getData.good()) { std::cerr<<"Error. Could not read first line of the input file "<Exit(EXIT_FAILURE); } // open the file that contains the low stat histogram TFile * file1 = TFile::Open(fileName1_.Data(), "read"); if (file1 == 0) {gSystem->Exit(EXIT_FAILURE);} // retrieve the low stat histogram TTree* tree1 = dynamic_cast(file1->Get(treeName1_.Data())); if (tree1 == 0) { std::cerr<<"Error. Could not find the tree "<Exit(EXIT_FAILURE); } // get the info on the high stat histogram getData >> fileName2_ >> treeName2_ >> xName2_ >> yName2_; if (!getData.good()) { std::cerr<<"Error. Could not read the second line of the input file "<Exit(EXIT_FAILURE); } // if both histograms are in the same file then just retrieve the // high stat histogram from the file we already have open TFile * file2(0); TTree* tree2(0); if ( fileName2_ == fileName1_ ) { tree2 = dynamic_cast(file1->Get(treeName2_.Data())); } // otherwise open the other file and retrieve the high stat histogram from there else { file2 = TFile::Open(fileName2_.Data(), "read"); if (file2 == 0) {gSystem->Exit(EXIT_FAILURE);} tree2 = dynamic_cast(file2->Get(treeName2_.Data())); } if (tree2 == 0) { std::cerr<<"Error. Could not find the tree "<Exit(EXIT_FAILURE); } // get the info on the minimum content, number of parameters and scalefactor Int_t nParameters(0); Float_t minContent(0.0), scaleFactor(1.0), xMin(0.0), xMax(1.0), yMin(0.0), yMax(1.0); getData >> minContent >> nParameters >> scaleFactor >> xMin >> xMax >> yMin >> yMax; if (getData.good()) { minContent_ = minContent; nParams_ = nParameters; scaleFactor_ = scaleFactor; xMin_ = xMin; xMax_ = xMax; yMin_ = yMin; yMax_ = yMax; } // close the text file getData.close(); std::cout<<"Using the files and trees: "<SetBranchAddress(xName1_.Data(),&x); tree1->SetBranchAddress(yName1_.Data(),&y); Int_t nEntries = tree1->GetEntries(); Double_t* xs = new Double_t[nEntries]; Double_t* ys = new Double_t[nEntries]; for ( Int_t i=0; i < nEntries; ++i ) { tree1->GetEntry( i ); xs[i] = x; ys[i] = y; } theHisto_ = new TH2Poly("theHisto_", "", xMin_, xMax_, yMin_, yMax_); //select the number of divisions to get us closest to minContent entries per bin std::vector divisions; this->pickBinning(xs,ys,nEntries,divisions); //perform the adaptive bining based on histo1_ this->getHisto(xMin_, xMax_, yMin_, yMax_, xs, ys, nEntries, divisions); histo1_ = dynamic_cast(theHisto_->Clone("histo1_")); histo2_ = dynamic_cast(theHisto_->Clone("histo2_")); pullHisto_ = dynamic_cast(theHisto_->Clone("pullHisto_")); chiSqHisto_ = dynamic_cast(theHisto_->Clone("chiSqHisto_")); chiSqSignedHisto_ = dynamic_cast(theHisto_->Clone("chiSqSignedHisto_")); delete[] xs; delete[] ys; //fill the two histograms from the trees TString drawString1, drawString2, weightString2; drawString1 += yName1_; drawString1 += ":"; drawString1 += xName1_; drawString1 += ">>histo1_"; drawString2 += yName2_; drawString2 += ":"; drawString2 += xName2_; drawString2 += ">>histo2_"; weightString2 += scaleFactor_; tree1->Draw(drawString1); tree2->Draw(drawString2,weightString2); histo1_->SetDirectory(0); histo2_->SetDirectory(0); pullHisto_->SetDirectory(0); chiSqHisto_->SetDirectory(0); chiSqSignedHisto_->SetDirectory(0); // close the file(s) containing the trees if (file1 != 0) {file1->Close();} delete file1; if (file2 != 0) {file2->Close();} delete file2; } void LauCalcChiSq::pickBinning(const Double_t* xs, const Double_t* ys, const Int_t nEntries, std::vector& divisions) { //first check how many events we have within the histogram limits Int_t nIn(0); for(Int_t i=0; i= xMin_ && ys[i]= yMin_) { ++nIn; } } //aim to have exactly minContent events in each bin Int_t nBinsTarget = nIn / minContent_; std::cout << "Target is " << minContent_ << " entries per bin" << std::endl; std::cout << "Aiming to divide " << nIn << " entries between " << nBinsTarget << " bins" << std::endl; //we will iteratively sub-divide histogram bins into either 4, 9, 25, 49 or 121 //here we figure out how many 4s, 9s, 25s, 49s and 121s to use to best match our target without exceeding it Int_t nDivisions(0), nNines(0), nTwentyFives(0), nFortyNines(0), nEleventyElevens(0), nBins(1); Int_t nDivisionsBest(0), nNinesBest(0), nTwentyFivesBest(0), nFortyNinesBest(0), nEleventyElevensBest(0), nBinsBest(1); do { ++nDivisions; for(nNines=0; nNines<=nDivisions; ++nNines) { for(nTwentyFives=0; nTwentyFives<=nDivisions-nNines; ++nTwentyFives) { for(nFortyNines=0; nFortyNines<=nDivisions-nNines-nTwentyFives; ++nFortyNines) { for(nEleventyElevens=0; nEleventyElevens<=nDivisions-nNines-nTwentyFives-nFortyNines; ++nEleventyElevens) { nBins = TMath::Power(4,nDivisions-nNines-nTwentyFives-nFortyNines-nEleventyElevens) *TMath::Power(9,nNines)*TMath::Power(25,nTwentyFives) *TMath::Power(49,nFortyNines)*TMath::Power(121,nEleventyElevens); if(nBins < nBinsTarget && nBins > nBinsBest) { //keep track of the best number of bins so far nBinsBest = nBins; nDivisionsBest = nDivisions; nNinesBest = nNines; nTwentyFivesBest = nTwentyFives; nFortyNinesBest = nFortyNines; nEleventyElevensBest = nEleventyElevens; } } } } } } while(TMath::Power(4,nDivisions+1) < nBinsTarget);//if 4^n > target then we've gone far enough std::cout << "Using " << nBinsBest << " bins" << std::endl; //fill the vector with the divisions that we want to make for(Int_t i=0; i& divisions, const UInt_t iter) { //If it's the last iteration create the bin and return if(iter == divisions.size()) { Double_t * x_new = new Double_t[5]; Double_t * y_new = new Double_t[5]; x_new[0] = xMin; x_new[1] = xMin; x_new[2] = xMax; x_new[3] = xMax; x_new[4] = xMin; y_new[0] = yMin; y_new[1] = yMax; y_new[2] = yMax; y_new[3] = yMin; y_new[4] = yMin; theHisto_->AddBin(5, x_new, y_new); if(verbose_) std::cout << "Adding bin from (" << xMin << "," << yMin << ") to (" << xMax << "," << yMax << ")" << std::endl; return; } //If not the last iteration then divide the bin Int_t n_divx=divisions[iter]; Int_t n_divy=divisions[iter]; if(verbose_) std::cout << "Dividing bin from (" << xMin << "," << yMin << ") to (" << xMax << "," << yMax << ") into " << n_divx << " by " << n_divy << " subbins" << std::endl; Double_t *xIn = new Double_t[nEntries]; Double_t *yIn = new Double_t[nEntries]; Int_t *xIndex = new Int_t [nEntries+2]; Int_t *yIndex = new Int_t [nEntries+2]; Int_t xCountIn = 0; for(Int_t i = 0; ixMax)||(ys[i]yMax)) continue; xIn[xCountIn] = xs[i]; ++xCountIn; } //find the delimitting x and y values for the sub bins Double_t xLimits[n_divx + 1]; Double_t yLimits[n_divx][n_divy + 1]; //first sort entries in x and divide bin into equally populated bins in x TMath::Sort(xCountIn, xIn, xIndex, false); xLimits[0] = xMin; xLimits[n_divx] = xMax; for (Int_t nDivx = 0; nDivx < n_divx; ++nDivx){ if (nDivx < (n_divx-1)){ xLimits[nDivx+1] = xIn[xIndex[xCountIn*(nDivx+1)/n_divx]]; } //for each bin in x divide into equally populated bins in y yLimits[nDivx][0] = yMin; yLimits[nDivx][n_divy] = yMax; Int_t yCountIn = 0; for(Int_t i = 0; ixMax)||(ys[i]yMax)) continue; if ((xs[i]=xLimits[nDivx+1])||(ys[i]yMax)) continue; yIn[yCountIn] = ys[i]; ++yCountIn; } TMath::Sort(yCountIn, yIn, yIndex, false); for (Int_t nDivy = 1; nDivy < n_divy; ++nDivy){ yLimits[nDivx][nDivy] = yIn[yIndex[yCountIn*nDivy/n_divy]]; } } delete[] xIn; delete[] yIn; delete[] xIndex; delete[] yIndex; //call for each sub bin for (Int_t nDivx = 0; nDivx < n_divx; ++nDivx){ for (Int_t nDivy = 0; nDivy < n_divy; ++nDivy){ this->getHisto(xLimits[nDivx], xLimits[nDivx + 1], yLimits[nDivx][nDivy], yLimits[nDivx][nDivy + 1], xs, ys, nEntries, divisions,iter+1); } } } diff --git a/src/LauCartesianCPCoeffSet.cc b/src/LauCartesianCPCoeffSet.cc index 18ed134..0a1eba1 100644 --- a/src/LauCartesianCPCoeffSet.cc +++ b/src/LauCartesianCPCoeffSet.cc @@ -1,280 +1,279 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauCartesianCPCoeffSet.cc \brief File containing implementation of LauCartesianCPCoeffSet class. */ #include #include #include #include "TMath.h" #include "TRandom.h" #include "LauCartesianCPCoeffSet.hh" #include "LauComplex.hh" #include "LauConstants.hh" #include "LauParameter.hh" #include "LauPrint.hh" -ClassImp(LauCartesianCPCoeffSet) LauCartesianCPCoeffSet::LauCartesianCPCoeffSet(const TString& compName, Double_t x, Double_t y, Double_t deltaX, Double_t deltaY, Bool_t xFixed, Bool_t yFixed, Bool_t deltaXFixed, Bool_t deltaYFixed, Bool_t deltaXSecondStage, Bool_t deltaYSecondStage) : LauAbsCoeffSet(compName), x_(new LauParameter("X", x, minRealImagPart_, maxRealImagPart_, xFixed)), y_(new LauParameter("Y", y, minRealImagPart_, maxRealImagPart_, yFixed)), deltaX_(new LauParameter("DeltaX", deltaX, minDelta_, maxDelta_, deltaXFixed)), deltaY_(new LauParameter("DeltaY", deltaY, minDelta_, maxDelta_, deltaYFixed)), particleCoeff_( x+deltaX, y+deltaY ), antiparticleCoeff_( x-deltaX, y-deltaY ), acp_("ACP", -2.0*(x*deltaX + y*deltaY)/(x*x + deltaX*deltaX + y*y + deltaY*deltaY), -1.0, 1.0, deltaXFixed&&deltaYFixed) { if (deltaXSecondStage && !deltaXFixed) { deltaX_->secondStage(kTRUE); deltaX_->initValue(0.0); } if (deltaYSecondStage && !deltaYFixed) { deltaY_->secondStage(kTRUE); deltaY_->initValue(0.0); } } LauCartesianCPCoeffSet::LauCartesianCPCoeffSet(const LauCartesianCPCoeffSet& rhs, CloneOption cloneOption, Double_t constFactor) : LauAbsCoeffSet(rhs.name()), x_(0), y_(0), deltaX_(0), deltaY_(0), particleCoeff_( rhs.particleCoeff_ ), antiparticleCoeff_( rhs.antiparticleCoeff_ ), acp_( rhs.acp_ ) { if ( cloneOption == All || cloneOption == TieRealPart ) { x_ = rhs.x_->createClone(constFactor); } else { x_ = new LauParameter("X", rhs.x_->value(), minRealImagPart_, maxRealImagPart_, rhs.x_->fixed()); if ( rhs.x_->blind() ) { const LauBlind* blinder = rhs.x_->blinder(); x_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TieImagPart ) { y_ = rhs.y_->createClone(constFactor); } else { y_ = new LauParameter("Y", rhs.y_->value(), minRealImagPart_, maxRealImagPart_, rhs.y_->fixed()); if ( rhs.y_->blind() ) { const LauBlind* blinder = rhs.y_->blinder(); y_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TieCPPars ) { deltaX_ = rhs.deltaX_->createClone(constFactor); deltaY_ = rhs.deltaY_->createClone(constFactor); } else { deltaX_ = new LauParameter("DeltaX", rhs.deltaX_->value(), minDelta_, maxDelta_, rhs.deltaX_->fixed()); deltaY_ = new LauParameter("DeltaY", rhs.deltaY_->value(), minDelta_, maxDelta_, rhs.deltaY_->fixed()); if ( rhs.deltaX_->secondStage() && !rhs.deltaX_->fixed() ) { deltaX_->secondStage(kTRUE); deltaX_->initValue(0.0); } if ( rhs.deltaY_->secondStage() && !rhs.deltaY_->fixed() ) { deltaY_->secondStage(kTRUE); deltaY_->initValue(0.0); } if ( rhs.deltaX_->blind() ) { const LauBlind* blinder = rhs.deltaX_->blinder(); deltaX_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } if ( rhs.deltaY_->blind() ) { const LauBlind* blinder = rhs.deltaY_->blinder(); deltaY_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } } std::vector LauCartesianCPCoeffSet::getParameters() { std::vector pars; pars.push_back(x_); pars.push_back(y_); pars.push_back(deltaX_); pars.push_back(deltaY_); return pars; } void LauCartesianCPCoeffSet::printParValues() const { std::cout<<"INFO in LauCartesianCPCoeffSet::printParValues : Component \""<name()<<"\" has "; std::cout<<"x = "<value()<<",\t"; std::cout<<"y = "<value()<<",\t"; std::cout<<"Delta x = "<value()<<",\t"; std::cout<<"Delta y = "<value()<<"."<name(); resName = resName.ReplaceAll("_", "\\_"); stream<value()); stream<<" \\pm "; print.printFormat(stream, x_->error()); stream<<"$ & $"; print.printFormat(stream, y_->value()); stream<<" \\pm "; print.printFormat(stream, y_->error()); stream<<"$ & $"; print.printFormat(stream, deltaX_->value()); stream<<" \\pm "; print.printFormat(stream, deltaX_->error()); stream<<"$ & $"; print.printFormat(stream, deltaY_->value()); stream<<" \\pm "; print.printFormat(stream, deltaY_->error()); stream<<"$ \\\\"<fixed() == kFALSE) { // Choose a value for "X" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; x_->initValue(value); x_->value(value); } if (y_->fixed() == kFALSE) { // Choose a value for "Y" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; y_->initValue(value); y_->value(value); } if (deltaX_->fixed() == kFALSE && deltaX_->secondStage() == kFALSE) { // Choose a value for "Delta X" between -0.5 and 0.5 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*1.0 - 0.5; deltaX_->initValue(value); deltaX_->value(value); } if (deltaY_->fixed() == kFALSE && deltaY_->secondStage() == kFALSE) { // Choose a value for "Delta Y" between -0.5 and 0.5 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*1.0 - 0.5; deltaY_->initValue(value); deltaY_->value(value); } } void LauCartesianCPCoeffSet::finaliseValues() { // update the pulls x_->updatePull(); y_->updatePull(); deltaX_->updatePull(); deltaY_->updatePull(); } const LauComplex& LauCartesianCPCoeffSet::particleCoeff() { particleCoeff_.setRealImagPart( x_->unblindValue()+deltaX_->unblindValue(), y_->unblindValue()+deltaY_->unblindValue() ); return particleCoeff_; } const LauComplex& LauCartesianCPCoeffSet::antiparticleCoeff() { antiparticleCoeff_.setRealImagPart( x_->unblindValue()-deltaX_->unblindValue(), y_->unblindValue()-deltaY_->unblindValue() ); return antiparticleCoeff_; } void LauCartesianCPCoeffSet::setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, Bool_t init ) { LauComplex average( coeff ); average += coeffBar; average.rescale( 0.5 ); Double_t xVal( average.re() ); Double_t yVal( average.im() ); Double_t deltaXVal( coeff.re() - average.re() ); Double_t deltaYVal( coeff.im() - average.im() ); x_->value( xVal ); y_->value( yVal ); deltaX_->value( deltaXVal ); deltaY_->value( deltaYVal ); if ( init ) { x_->genValue( xVal ); y_->genValue( yVal ); deltaX_->genValue( deltaXVal ); deltaY_->genValue( deltaYVal ); x_->initValue( xVal ); y_->initValue( yVal ); deltaX_->initValue( deltaXVal ); deltaY_->initValue( deltaYVal ); } } LauParameter LauCartesianCPCoeffSet::acp() { // set the name TString parName(this->baseName()); parName += "_ACP"; acp_.name(parName); // work out the ACP value Double_t numer = x_->value()*deltaX_->value() + y_->value()*deltaY_->value(); Double_t denom = x_->value()*x_->value() + deltaX_->value()*deltaX_->value() + y_->value()*y_->value() + deltaY_->value()*deltaY_->value(); Double_t value = -2.0*numer/denom; // is it fixed? Bool_t fixed = deltaX_->fixed() && deltaY_->fixed(); acp_.fixed(fixed); // we can't work out the error without the covariance matrix Double_t error(0.0); // set the value and error acp_.valueAndErrors(value,error); return acp_; } LauAbsCoeffSet* LauCartesianCPCoeffSet::createClone(const TString& newName, CloneOption cloneOption, Double_t constFactor) { LauAbsCoeffSet* clone(0); if ( cloneOption == All || cloneOption == TieRealPart || cloneOption == TieImagPart || cloneOption == TieCPPars ) { clone = new LauCartesianCPCoeffSet( *this, cloneOption, constFactor ); clone->name( newName ); } else { std::cerr << "ERROR in LauCartesianCPCoeffSet::createClone : Invalid clone option" << std::endl; } return clone; } diff --git a/src/LauCartesianGammaCPCoeffSet.cc b/src/LauCartesianGammaCPCoeffSet.cc index b9cca1f..95d692a 100644 --- a/src/LauCartesianGammaCPCoeffSet.cc +++ b/src/LauCartesianGammaCPCoeffSet.cc @@ -1,312 +1,311 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauCartesianGammaCPCoeffSet.cc \brief File containing implementation of LauCartesianGammaCPCoeffSet class. */ #include #include #include #include "TMath.h" #include "TRandom.h" #include "LauCartesianGammaCPCoeffSet.hh" #include "LauComplex.hh" #include "LauConstants.hh" #include "LauParameter.hh" #include "LauPrint.hh" -ClassImp(LauCartesianGammaCPCoeffSet) LauCartesianGammaCPCoeffSet::LauCartesianGammaCPCoeffSet(const TString& compName, const Double_t x, const Double_t y, const Double_t xCP, const Double_t yCP, const Double_t deltaXCP, const Double_t deltaYCP, const Bool_t xFixed, const Bool_t yFixed, const Bool_t xCPFixed, const Bool_t yCPFixed, const Bool_t deltaXCPFixed, const Bool_t deltaYCPFixed, const Bool_t deltaXCPSecondStage, const Bool_t deltaYCPSecondStage) : LauAbsCoeffSet(compName), x_(new LauParameter("X", x, minRealImagPart_, maxRealImagPart_, xFixed)), y_(new LauParameter("Y", y, minRealImagPart_, maxRealImagPart_, yFixed)), xCP_(new LauParameter("XCP", xCP, minRealImagPart_, maxRealImagPart_, xCPFixed)), yCP_(new LauParameter("YCP", yCP, minRealImagPart_, maxRealImagPart_, yCPFixed)), deltaXCP_(new LauParameter("DeltaXCP", deltaXCP, minDelta_, maxDelta_, deltaXCPFixed)), deltaYCP_(new LauParameter("DeltaYCP", deltaYCP, minDelta_, maxDelta_, deltaYCPFixed)), nonCPPart_( x, y), cpPart_( 1+xCP+deltaXCP, yCP+deltaYCP), cpAntiPart_( 1+xCP-deltaXCP, yCP-deltaYCP), particleCoeff_( nonCPPart_ * cpPart_ ), antiparticleCoeff_( nonCPPart_ * cpAntiPart_ ), acp_("ACP", (antiparticleCoeff_.abs2()-particleCoeff_.abs2())/(antiparticleCoeff_.abs2()+particleCoeff_.abs2()), -1.0, 1.0, deltaXCPFixed&&deltaYCPFixed) { if (deltaXCPSecondStage && !deltaXCPFixed) { deltaXCP_->secondStage(kTRUE); deltaXCP_->initValue(0.0); } if (deltaYCPSecondStage && !deltaYCPFixed) { deltaYCP_->secondStage(kTRUE); deltaYCP_->initValue(0.0); } } LauCartesianGammaCPCoeffSet::LauCartesianGammaCPCoeffSet(const LauCartesianGammaCPCoeffSet& rhs, CloneOption cloneOption, Double_t constFactor) : LauAbsCoeffSet(rhs.name()), x_(0), y_(0), xCP_(0), yCP_(0), deltaXCP_(0), deltaYCP_(0), nonCPPart_( rhs.nonCPPart_ ), cpPart_( rhs.cpPart_ ), cpAntiPart_( rhs.cpAntiPart_ ), particleCoeff_( rhs.particleCoeff_ ), antiparticleCoeff_( rhs.antiparticleCoeff_ ), acp_( rhs.acp_ ) { if ( cloneOption == All || cloneOption == TieRealPart ) { x_ = rhs.x_->createClone(constFactor); } else { x_ = new LauParameter("X", rhs.x_->value(), minRealImagPart_, maxRealImagPart_, rhs.x_->fixed()); if ( rhs.x_->blind() ) { const LauBlind* blinder = rhs.x_->blinder(); x_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TieImagPart ) { y_ = rhs.y_->createClone(constFactor); } else { y_ = new LauParameter("Y", rhs.y_->value(), minRealImagPart_, maxRealImagPart_, rhs.y_->fixed()); if ( rhs.y_->blind() ) { const LauBlind* blinder = rhs.y_->blinder(); y_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TieCPPars ) { xCP_ = rhs.xCP_->createClone(constFactor); yCP_ = rhs.yCP_->createClone(constFactor); deltaXCP_ = rhs.deltaXCP_->createClone(constFactor); deltaYCP_ = rhs.deltaYCP_->createClone(constFactor); } else { xCP_ = new LauParameter("XCP", rhs.xCP_->value(), minRealImagPart_, maxRealImagPart_, rhs.xCP_->fixed()); if ( rhs.xCP_->blind() ) { const LauBlind* blinder = rhs.xCP_->blinder(); xCP_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } yCP_ = new LauParameter("YCP", rhs.yCP_->value(), minRealImagPart_, maxRealImagPart_, rhs.yCP_->fixed()); if ( rhs.yCP_->blind() ) { const LauBlind* blinder = rhs.yCP_->blinder(); yCP_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } deltaXCP_ = new LauParameter("DeltaXCP", rhs.deltaXCP_->value(), minDelta_, maxDelta_, rhs.deltaXCP_->fixed()); deltaYCP_ = new LauParameter("DeltaYCP", rhs.deltaYCP_->value(), minDelta_, maxDelta_, rhs.deltaYCP_->fixed()); if ( rhs.deltaXCP_->secondStage() && !rhs.deltaXCP_->fixed() ) { deltaXCP_->secondStage(kTRUE); deltaXCP_->initValue(0.0); } if ( rhs.deltaYCP_->secondStage() && !rhs.deltaYCP_->fixed() ) { deltaYCP_->secondStage(kTRUE); deltaYCP_->initValue(0.0); } if ( rhs.deltaXCP_->blind() ) { const LauBlind* blinder = rhs.deltaXCP_->blinder(); deltaXCP_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } if ( rhs.deltaYCP_->blind() ) { const LauBlind* blinder = rhs.deltaYCP_->blinder(); deltaYCP_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } } std::vector LauCartesianGammaCPCoeffSet::getParameters() { std::vector pars; pars.push_back(x_); pars.push_back(y_); if(!xCP_->fixed()) pars.push_back(xCP_); if(!yCP_->fixed()) pars.push_back(yCP_); if(!deltaXCP_->fixed()) pars.push_back(deltaXCP_); if(!deltaYCP_->fixed()) pars.push_back(deltaYCP_); return pars; } void LauCartesianGammaCPCoeffSet::printParValues() const { std::cout<<"INFO in LauCartesianGammaCPCoeffSet::printParValues : Component \""<name()<<"\" has "; std::cout<<"x = "<value()<<",\t"; std::cout<<"y = "<value()<<",\t"; std::cout<<"xCP = "<value()<<",\t"; std::cout<<"yCP = "<value()<<",\t"; std::cout<<"Delta xCP = "<value()<<",\t"; std::cout<<"Delta yCP = "<value()<<"."<name(); resName = resName.ReplaceAll("_", "\\_"); stream<value()); stream<<" \\pm "; print.printFormat(stream, x_->error()); stream<<"$ & $"; print.printFormat(stream, y_->value()); stream<<" \\pm "; print.printFormat(stream, y_->error()); stream<<"$ & $"; print.printFormat(stream, xCP_->value()); stream<<" \\pm "; print.printFormat(stream, xCP_->error()); stream<<"$ & $"; print.printFormat(stream, yCP_->value()); stream<<" \\pm "; print.printFormat(stream, yCP_->error()); stream<<"$ & $"; print.printFormat(stream, deltaXCP_->value()); stream<<" \\pm "; print.printFormat(stream, deltaXCP_->error()); stream<<"$ & $"; print.printFormat(stream, deltaYCP_->value()); stream<<" \\pm "; print.printFormat(stream, deltaYCP_->error()); stream<<"$ \\\\"<fixed() == kFALSE) { // Choose a value for "X" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; x_->initValue(value); x_->value(value); } if (y_->fixed() == kFALSE) { // Choose a value for "Y" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; y_->initValue(value); y_->value(value); } if (xCP_->fixed() == kFALSE) { // Choose a value for "XCP" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; xCP_->initValue(value); xCP_->value(value); } if (yCP_->fixed() == kFALSE) { // Choose a value for "YCP" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; yCP_->initValue(value); yCP_->value(value); } if (deltaXCP_->fixed() == kFALSE && deltaXCP_->secondStage() == kFALSE) { // Choose a value for "Delta XCP" between -0.5 and 0.5 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*1.0 - 0.5; deltaXCP_->initValue(value); deltaXCP_->value(value); } if (deltaYCP_->fixed() == kFALSE && deltaYCP_->secondStage() == kFALSE) { // Choose a value for "Delta YCP" between -0.5 and 0.5 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*1.0 - 0.5; deltaYCP_->initValue(value); deltaYCP_->value(value); } } void LauCartesianGammaCPCoeffSet::finaliseValues() { // update the pulls x_->updatePull(); y_->updatePull(); xCP_->updatePull(); yCP_->updatePull(); deltaXCP_->updatePull(); deltaYCP_->updatePull(); } const LauComplex& LauCartesianGammaCPCoeffSet::particleCoeff() { nonCPPart_.setRealImagPart( x_->unblindValue(), y_->unblindValue() ); cpPart_.setRealImagPart( 1.0+xCP_->unblindValue()+deltaXCP_->unblindValue(), yCP_->unblindValue()+deltaYCP_->unblindValue() ); particleCoeff_ = nonCPPart_ * cpPart_; return particleCoeff_; } const LauComplex& LauCartesianGammaCPCoeffSet::antiparticleCoeff() { nonCPPart_.setRealImagPart( x_->unblindValue(), y_->unblindValue() ); cpAntiPart_.setRealImagPart( 1.0+xCP_->unblindValue()-deltaXCP_->unblindValue(), yCP_->unblindValue()-deltaYCP_->unblindValue() ); antiparticleCoeff_ = nonCPPart_ * cpAntiPart_; return antiparticleCoeff_; } void LauCartesianGammaCPCoeffSet::setCoeffValues( const LauComplex&, const LauComplex&, Bool_t ) { std::cerr << "ERROR in LauCartesianGammaCPCoeffSet::setCoeffValues : Method not supported by this class - too many parameters" << std::endl; } LauParameter LauCartesianGammaCPCoeffSet::acp() { // set the name TString parName(this->baseName()); parName += "_ACP"; acp_.name(parName); // work out the ACP value const LauComplex nonCPPart( x_->value(), y_->value() ); const LauComplex cpPart( 1.0+xCP_->value()+deltaXCP_->value(), yCP_->value()+deltaYCP_->value() ); const LauComplex cpAntiPart( 1.0+xCP_->value()-deltaXCP_->value(), yCP_->value()-deltaYCP_->value() ); const LauComplex partCoeff = nonCPPart * cpPart; const LauComplex antiCoeff = nonCPPart * cpAntiPart; const Double_t numer = antiCoeff.abs2() - partCoeff.abs2(); const Double_t denom = antiCoeff.abs2() + partCoeff.abs2(); const Double_t value = numer/denom; // is it fixed? const Bool_t fixed = deltaXCP_->fixed() && deltaYCP_->fixed(); acp_.fixed(fixed); // we can't work out the error without the covariance matrix const Double_t error(0.0); // set the value and error acp_.valueAndErrors(value,error); return acp_; } LauAbsCoeffSet* LauCartesianGammaCPCoeffSet::createClone(const TString& newName, CloneOption cloneOption, Double_t constFactor) { LauAbsCoeffSet* clone(0); if ( cloneOption == All || cloneOption == TieRealPart || cloneOption == TieImagPart || cloneOption == TieCPPars ) { clone = new LauCartesianGammaCPCoeffSet( *this, cloneOption, constFactor ); clone->name( newName ); } else { std::cerr << "ERROR in LauCartesianGammaCPCoeffSet::createClone : Invalid clone option" << std::endl; } return clone; } diff --git a/src/LauChebychevPdf.cc b/src/LauChebychevPdf.cc index 11f9e3f..7078357 100644 --- a/src/LauChebychevPdf.cc +++ b/src/LauChebychevPdf.cc @@ -1,177 +1,176 @@ /* Copyright 2009 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauChebychevPdf.cc \brief File containing implementation of LauChebychevPdf class. */ /***************************************************************************** * Class based on RooFit/RooChebychev. * * Original copyright given below. * ***************************************************************************** * Authors: * * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu * * DK, David Kirkby, UC Irvine, dkirkby@uci.edu * * * * Copyright (c) 2000-2005, Regents of the University of California * * and Stanford University. All rights reserved. * * * * Redistribution and use in source and binary forms, * * with or without modification, are permitted according to the terms * * listed in LICENSE (http://roofit.sourceforge.net/license.txt) * *****************************************************************************/ #include #include #include "TMath.h" #include "TSystem.h" #include "LauChebychevPdf.hh" -ClassImp(LauChebychevPdf) LauChebychevPdf::LauChebychevPdf(const TString& theVarName, const std::vector& params, Double_t minAbscissa, Double_t maxAbscissa) : LauAbsPdf(theVarName, params, minAbscissa, maxAbscissa), coeffs_(params.size(),0) { // Constructor for the Chebychev Polynomial PDF. // // The parameters in params are the coefficients of the polynomial // (polynomial can be anything from 0 to 7 orders). // The last two arguments specify the range in which the PDF is defined, and the PDF // will be normalised w.r.t. these limits. if ( (this->nParameters() > 7) ) { std::cerr << "ERROR in LauChebychevPdf constructor: Too many coeffs - can only cope with order <=7 polynomial." << std::endl; gSystem->Exit(EXIT_FAILURE); } for ( UInt_t i(0); i < this->nParameters(); ++i ) { TString name = "c"; name += i+1; coeffs_[i] = this->findParameter( name ); } // Cache the normalisation factor this->calcNorm(); } LauChebychevPdf::~LauChebychevPdf() { // Destructor } //inline static double p0(double ,double a) { return a; } inline static double p1(double t,double a,double b) { return a*t+b; } inline static double p2(double t,double a,double b,double c) { return p1(t,p1(t,a,b),c); } inline static double p3(double t,double a,double b,double c,double d) { return p2(t,p1(t,a,b),c,d); } //inline static double p4(double t,double a,double b,double c,double d,double e) { return p3(t,p1(t,a,b),c,d,e); } void LauChebychevPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Get our abscissa Double_t abscissa = abscissas[0]; Double_t xmin = this->getMinAbscissa(); Double_t xmax = this->getMaxAbscissa(); Double_t x(-1.0+2.0*(abscissa-xmin)/(xmax-xmin)); Double_t x2(x*x); Double_t sum(0) ; switch ( coeffs_.size() ) { case 7: sum += coeffs_[6]->unblindValue()*x*p3(x2,64,-112,56,-7); [[fallthrough]]; case 6: sum += coeffs_[5]->unblindValue()*p3(x2,32,-48,18,-1); [[fallthrough]]; case 5: sum += coeffs_[4]->unblindValue()*x*p2(x2,16,-20,5); [[fallthrough]]; case 4: sum += coeffs_[3]->unblindValue()*p2(x2,8,-8,1); [[fallthrough]]; case 3: sum += coeffs_[2]->unblindValue()*x*p1(x2,4,-3); [[fallthrough]]; case 2: sum += coeffs_[1]->unblindValue()*p1(x2,2,-1); [[fallthrough]]; case 1: sum += coeffs_[0]->unblindValue()*x; [[fallthrough]]; case 0: sum +=1; } this->setUnNormPDFVal( sum ); // if the parameters are floating then we // need to recalculate the normalisation if (!this->cachePDF() && !this->withinNormCalc() && !this->withinGeneration()) { this->calcNorm(); } } void LauChebychevPdf::calcNorm() { Double_t xmin = this->getMinAbscissa(); Double_t xmax = this->getMaxAbscissa(); Double_t norm(0) ; switch( coeffs_.size() ) { case 7: case 6: norm += coeffs_[5]->unblindValue()*(-1 + 18./3. - 48./5. + 32./7.); [[fallthrough]]; case 5: case 4: norm += coeffs_[3]->unblindValue()*( 1 - 8./3. + 8./5.); [[fallthrough]]; case 3: case 2: norm += coeffs_[1]->unblindValue()*(-1 + 2./3.); [[fallthrough]]; case 1: case 0: norm += 1; } norm *= xmax-xmin; this->setNorm(norm); } void LauChebychevPdf::calcPDFHeight(const LauKinematics* /*kinematics*/) { // TODO - this method can hopefully be improved // At present it scans through the range and then increases by a 20% safety factor // Maybe there's a better way? if (this->heightUpToDate()) { return; } // Calculate the PDF height LauAbscissas maxPoint(1); Double_t minAbs = this->getMinAbscissa(); Double_t maxAbs = this->getMaxAbscissa(); Double_t range = maxAbs - minAbs; Double_t maxHeight(0.0); // Just scan through the range for ( Double_t point = minAbs; point <= maxAbs; point += range/1000.0 ) { maxPoint[0] = point; this->calcLikelihoodInfo(maxPoint); Double_t heightAtPoint = this->getUnNormLikelihood(); if ( heightAtPoint > maxHeight ) { maxHeight = heightAtPoint; } } // Mutliply by 120% to be on the safe side maxHeight *= 1.2; this->setMaxHeight(maxHeight); } diff --git a/src/LauCleoCPCoeffSet.cc b/src/LauCleoCPCoeffSet.cc index 976dbf8..d6d3041 100644 --- a/src/LauCleoCPCoeffSet.cc +++ b/src/LauCleoCPCoeffSet.cc @@ -1,342 +1,341 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauCleoCPCoeffSet.cc \brief File containing implementation of LauCleoCPCoeffSet class. */ #include #include #include #include "TMath.h" #include "TRandom.h" #include "LauCleoCPCoeffSet.hh" #include "LauComplex.hh" #include "LauConstants.hh" #include "LauParameter.hh" #include "LauPrint.hh" -ClassImp(LauCleoCPCoeffSet) LauCleoCPCoeffSet::LauCleoCPCoeffSet(const TString& compName, Double_t a, Double_t delta, Double_t b, Double_t phi, Bool_t aFixed, Bool_t deltaFixed, Bool_t bFixed, Bool_t phiFixed, Bool_t bSecondStage, Bool_t phiSecondStage) : LauAbsCoeffSet(compName), a_(new LauParameter("A", a, minMagnitude_, maxMagnitude_, aFixed)), b_(new LauParameter("B", b, minMagnitude_, maxMagnitude_, bFixed)), delta_(new LauParameter("Delta", delta, minPhase_, maxPhase_, deltaFixed)), phi_(new LauParameter("Phi", phi, minPhase_, maxPhase_, phiFixed)), particleCoeff_( (a+b)*TMath::Cos(delta+phi), (a+b)*TMath::Sin(delta+phi) ), antiparticleCoeff_( (a-b)*TMath::Cos(delta-phi), (a-b)*TMath::Sin(delta-phi) ), acp_("ACP", (-2.0*a*b)/(a*a+b*b), -1.0, 1.0, bFixed&&phiFixed) { if (bSecondStage && !bFixed) { b_->secondStage(kTRUE); b_->initValue(0.0); } if (phiSecondStage && !phiFixed) { phi_->secondStage(kTRUE); phi_->initValue(0.0); } } LauCleoCPCoeffSet::LauCleoCPCoeffSet(const LauCleoCPCoeffSet& rhs, CloneOption cloneOption, Double_t constFactor) : LauAbsCoeffSet(rhs.name()), a_(0), b_(0), delta_(0), phi_(0), particleCoeff_( rhs.particleCoeff_ ), antiparticleCoeff_( rhs.antiparticleCoeff_ ), acp_( rhs.acp_ ) { if ( cloneOption == All || cloneOption == TieMagnitude ) { a_ = rhs.a_->createClone(constFactor); } else { a_ = new LauParameter("A", rhs.a_->value(), minMagnitude_, maxMagnitude_, rhs.a_->fixed()); if ( rhs.a_->blind() ) { const LauBlind* blinder = rhs.a_->blinder(); a_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TieCPPars ) { b_ = rhs.b_->createClone(constFactor); } else { b_ = new LauParameter("B", rhs.b_->value(), minMagnitude_, maxMagnitude_, rhs.b_->fixed()); if ( rhs.b_->blind() ) { const LauBlind* blinder = rhs.b_->blinder(); b_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TiePhase ) { delta_ = rhs.delta_->createClone(constFactor); } else { delta_ = new LauParameter("Delta", rhs.delta_->value(), minPhase_, maxPhase_, rhs.delta_->fixed()); if ( rhs.delta_->blind() ) { const LauBlind* blinder = rhs.delta_->blinder(); delta_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TieCPPars ) { phi_ = rhs.phi_->createClone(constFactor); } else { phi_ = new LauParameter("Phi", rhs.phi_->value(), minPhase_, maxPhase_, rhs.phi_->fixed()); if ( rhs.phi_->blind() ) { const LauBlind* blinder = rhs.phi_->blinder(); phi_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } } std::vector LauCleoCPCoeffSet::getParameters() { std::vector pars; pars.push_back(a_); pars.push_back(b_); pars.push_back(delta_); pars.push_back(phi_); return pars; } void LauCleoCPCoeffSet::printParValues() const { std::cout<<"INFO in LauCleoCPCoeffSet::printParValues : Component \""<name()<<"\" has "; std::cout<<"a-magnitude = "<value()<<",\t"; std::cout<<"delta = "<value()<<",\t"; std::cout<<"b-magnitude = "<value()<<",\t"; std::cout<<"phi = "<value()<<"."<name(); resName = resName.ReplaceAll("_", "\\_"); stream<value()); stream<<" \\pm "; print.printFormat(stream, a_->error()); stream<<"$ & $"; print.printFormat(stream, delta_->value()); stream<<" \\pm "; print.printFormat(stream, delta_->error()); stream<<"$ & $"; print.printFormat(stream, b_->value()); stream<<" \\pm "; print.printFormat(stream, b_->error()); stream<<"$ & $"; print.printFormat(stream, phi_->value()); stream<<" \\pm "; print.printFormat(stream, phi_->error()); stream<<"$ \\\\"<fixed() == kFALSE) { // Choose an a-magnitude between 0.0 and 2.0 Double_t mag = LauAbsCoeffSet::getRandomiser()->Rndm()*2.0; a_->initValue(mag); a_->value(mag); } if (b_->fixed() == kFALSE && b_->secondStage() == kFALSE) { // Choose a b-magnitude between 0.0 and 0.1 Double_t mag = LauAbsCoeffSet::getRandomiser()->Rndm()*0.1; b_->initValue(mag); b_->value(mag); } if (delta_->fixed() == kFALSE) { // Choose a phase between +- pi Double_t phase = LauAbsCoeffSet::getRandomiser()->Rndm()*LauConstants::twoPi - LauConstants::pi; delta_->initValue(phase); delta_->value(phase); } if (phi_->fixed() == kFALSE && phi_->secondStage() == kFALSE) { // Choose a phase between +- pi Double_t phase = LauAbsCoeffSet::getRandomiser()->Rndm()*LauConstants::twoPi - LauConstants::pi; phi_->initValue(phase); phi_->value(phase); } } void LauCleoCPCoeffSet::finaliseValues() { // retrieve the current values from the parameters Double_t aVal = a_->value(); Double_t bVal = b_->value(); Double_t deltaVal = delta_->value(); Double_t phiVal = phi_->value(); Double_t genDelta = delta_->genValue(); Double_t genPhi = phi_->genValue(); // Check whether we have a negative "a" magnitude. // If so make it positive and add pi to the "delta" phase. if (aVal < 0.0) { aVal *= -1.0; bVal *= -1.0; deltaVal += LauConstants::pi; } // Check now whether the phases lies in the right range (-pi to pi). Bool_t deltaWithinRange(kFALSE); Bool_t phiWithinRange(kFALSE); while (deltaWithinRange == kFALSE && phiWithinRange == kFALSE) { if (deltaVal > -LauConstants::pi && deltaVal < LauConstants::pi) { deltaWithinRange = kTRUE; } else { // Not within the specified range if (deltaVal > LauConstants::pi) { deltaVal -= LauConstants::twoPi; } else if (deltaVal < -LauConstants::pi) { deltaVal += LauConstants::twoPi; } } if (phiVal > -LauConstants::pi && phiVal < LauConstants::pi) { phiWithinRange = kTRUE; } else { // Not within the specified range if (phiVal > LauConstants::pi) { phiVal -= LauConstants::twoPi; } else if (phiVal < -LauConstants::pi) { phiVal += LauConstants::twoPi; } } } // A further problem can occur when the generated phase is close to -pi or pi. // The phase can wrap over to the other end of the scale - // this leads to artificially large pulls so we wrap it back. Double_t diff = deltaVal - genDelta; if (diff > LauConstants::pi) { deltaVal -= LauConstants::twoPi; } else if (diff < -LauConstants::pi) { deltaVal += LauConstants::twoPi; } diff = phiVal - genPhi; if (diff > LauConstants::pi) { phiVal -= LauConstants::twoPi; } else if (diff < -LauConstants::pi) { phiVal += LauConstants::twoPi; } // finally store the new values in the parameters // and update the pulls a_->value(aVal); a_->updatePull(); b_->value(bVal); b_->updatePull(); delta_->value(deltaVal); delta_->updatePull(); phi_->value(phiVal); phi_->updatePull(); } const LauComplex& LauCleoCPCoeffSet::particleCoeff() { Double_t magnitude = a_->unblindValue() + b_->unblindValue(); Double_t phase = delta_->unblindValue() + phi_->unblindValue(); particleCoeff_.setRealImagPart(magnitude*TMath::Cos(phase), magnitude*TMath::Sin(phase)); return particleCoeff_; } const LauComplex& LauCleoCPCoeffSet::antiparticleCoeff() { Double_t magnitude = a_->unblindValue() - b_->unblindValue(); Double_t phase = delta_->unblindValue() - phi_->unblindValue(); antiparticleCoeff_.setRealImagPart(magnitude*TMath::Cos(phase), magnitude*TMath::Sin(phase)); return antiparticleCoeff_; } void LauCleoCPCoeffSet::setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, Bool_t init ) { Double_t mag = coeff.abs(); Double_t magBar = coeffBar.abs(); Double_t phase = coeff.arg(); Double_t phaseBar = coeffBar.arg(); Double_t aVal( 0.5 * ( mag + magBar ) ); Double_t deltaVal( 0.5 * ( phase + phaseBar ) ); Double_t bVal( 0.5 * ( mag - magBar ) ); Double_t phiVal( 0.5 * ( phase - phaseBar ) ); a_->value( aVal ); delta_->value( deltaVal ); b_->value( bVal ); phi_->value( phiVal ); if ( init ) { a_->genValue( aVal ); delta_->genValue( deltaVal ); b_->genValue( bVal ); phi_->genValue( phiVal ); a_->initValue( aVal ); delta_->initValue( deltaVal ); b_->initValue( bVal ); phi_->initValue( phiVal ); } } LauParameter LauCleoCPCoeffSet::acp() { // set the name TString parName(this->baseName()); parName += "_ACP"; acp_.name(parName); // work out the ACP value Double_t numer = -2.0*a_->value()*b_->value(); Double_t denom = a_->value()*a_->value()+b_->value()*b_->value(); Double_t value = numer/denom; // is it fixed? Bool_t fixed = a_->fixed() && b_->fixed(); acp_.fixed(fixed); // we can't work out the error without the covariance matrix Double_t error(0.0); // set the value and error acp_.valueAndErrors(value,error); return acp_; } LauAbsCoeffSet* LauCleoCPCoeffSet::createClone(const TString& newName, CloneOption cloneOption, Double_t constFactor) { LauAbsCoeffSet* clone(0); if ( cloneOption == All || cloneOption == TiePhase || cloneOption == TieMagnitude || cloneOption == TieCPPars ) { clone = new LauCleoCPCoeffSet( *this, cloneOption, constFactor ); clone->name( newName ); } else { std::cerr << "ERROR in LauCleoCPCoeffSet::createClone : Invalid clone option" << std::endl; } return clone; } diff --git a/src/LauComplex.cc b/src/LauComplex.cc index 7642d6f..c5ecc53 100644 --- a/src/LauComplex.cc +++ b/src/LauComplex.cc @@ -1,70 +1,69 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauComplex.cc \brief File containing implementation of LauComplex class. */ /***************************************************************************** * Class based on RooFit/RooComplex. * * Original copyright given below. * ***************************************************************************** * Authors: * * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu * * DK, David Kirkby, UC Irvine, dkirkby@uci.edu * * * * Copyright (c) 2000-2005, Regents of the University of California * * and Stanford University. All rights reserved. * * * * Redistribution and use in source and binary forms, * * with or without modification, are permitted according to the terms * * listed in LICENSE (http://roofit.sourceforge.net/license.txt) * *****************************************************************************/ #include #include "LauComplex.hh" -ClassImp(LauComplex); void LauComplex::print() const { std::cout << (*this) << std::endl; } std::ostream& operator<<(std::ostream& os, const LauComplex& z) { return os<<"("<>(std::istream& ios, LauComplex& z) { Double_t a(0.0), b(0.0); char temp; ios >> temp >> a >> temp >> b >> temp; z.setRealImagPart( a, b ); return ios; } diff --git a/src/LauCruijffPdf.cc b/src/LauCruijffPdf.cc index 6fa8b41..0517963 100644 --- a/src/LauCruijffPdf.cc +++ b/src/LauCruijffPdf.cc @@ -1,168 +1,167 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauCruijffPdf.cc \brief File containing implementation of LauCruijffPdf class. */ /***************************************************************************** * Class based on RooFit/RooCruijff. * * Original copyright given below. * ***************************************************************************** * Authors: * * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu * * DK, David Kirkby, UC Irvine, dkirkby@uci.edu * * * * Copyright (c) 2000-2005, Regents of the University of California * * and Stanford University. All rights reserved. * * * * Redistribution and use in source and binary forms, * * with or without modification, are permitted according to the terms * * listed in LICENSE (http://roofit.sourceforge.net/license.txt) * *****************************************************************************/ #include #include using std::cout; using std::cerr; using std::endl; using std::vector; #include "TMath.h" #include "TSystem.h" #include "LauCruijffPdf.hh" #include "LauConstants.hh" -ClassImp(LauCruijffPdf) LauCruijffPdf::LauCruijffPdf(const TString& theVarName, const vector& params, Double_t minAbscissa, Double_t maxAbscissa) : LauAbsPdf(theVarName, params, minAbscissa, maxAbscissa), mean_(0), sigmaL_(0), sigmaR_(0), alphaL_(0), alphaR_(0) { // Constructor for the Cruijff PDF. // // The parameters in params are the mean, sigmaR, sigmaL, alphaR // and alphaL. // The last two arguments specify the range in which the PDF is defined, and the PDF // will be normalised w.r.t. these limits. mean_ = this->findParameter("mean"); sigmaR_ = this->findParameter("sigmaR"); sigmaL_ = this->findParameter("sigmaL"); alphaR_ = this->findParameter("alphaR"); alphaL_ = this->findParameter("alphaL"); if ((this->nParameters() != 5) || (mean_ == 0) || (sigmaR_ == 0) || (sigmaL_ == 0) || (alphaL_ == 0) || (alphaR_ == 0)) { cerr<<"ERROR in LauCruijffPdf constructor: LauCruijffPdf requires 5 parameters: \"mean\", \"sigmaL\", \"sigmaR\", \"alphaR\" and \"alphaL\"."<Exit(EXIT_FAILURE); } // Cache the normalisation factor this->calcNorm(); } LauCruijffPdf::~LauCruijffPdf() { // Destructor } void LauCruijffPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Get our abscissa Double_t abscissa = abscissas[0]; // Get the up to date parameter values Double_t mean = mean_->unblindValue(); Double_t sigmaL = sigmaL_->unblindValue(); Double_t sigmaR = sigmaR_->unblindValue(); Double_t alphaL = alphaL_->unblindValue(); Double_t alphaR = alphaR_->unblindValue(); // Evaluate the LauCruijff PDF value Double_t arg = abscissa - mean; Double_t coef(0.0); Double_t value(0.0); if (arg < 0.0){ if (TMath::Abs(sigmaL) > 1e-30) { coef = -1.0/(2.0*sigmaL*sigmaL + alphaL*arg*arg); } } else { if (TMath::Abs(sigmaR) > 1e-30) { coef = -1.0/(2.0*sigmaR*sigmaR+ alphaR*arg*arg); } } value = TMath::Exp(coef*arg*arg); // if the parameters are floating then we // need to recalculate the normalisation if (!this->cachePDF() && !this->withinNormCalc() && !this->withinGeneration()) { this->calcNorm(); } this->setUnNormPDFVal(value); } void LauCruijffPdf::calcPDFHeight( const LauKinematics* /*kinematics*/ ) { if (this->heightUpToDate()) { return; } // Get the up to date parameter values Double_t mean = mean_->unblindValue(); LauAbscissas maxPoint(1); maxPoint[0] = mean; // Calculate the PDF height if (mean < this->getMinAbscissa()) { maxPoint[0] = this->getMinAbscissa(); } else if (mean > this->getMaxAbscissa()) { maxPoint[0] = this->getMaxAbscissa(); } this->calcLikelihoodInfo(maxPoint); Double_t height = this->getUnNormLikelihood(); // Multiply by a small factor to avoid problems from rounding errors height *= (1.0 + 1e-1); this->setMaxHeight(height); } diff --git a/src/LauCrystalBallPdf.cc b/src/LauCrystalBallPdf.cc index 9c7da10..7128bfa 100644 --- a/src/LauCrystalBallPdf.cc +++ b/src/LauCrystalBallPdf.cc @@ -1,230 +1,229 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauCrystalBallPdf.cc \brief File containing implementation of LauCrystalBallPdf class. */ /***************************************************************************** * Class based on RooFit/RooCBShape. * * Original copyright given below. * ***************************************************************************** * Authors: * * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu * * DK, David Kirkby, UC Irvine, dkirkby@uci.edu * * * * Copyright (c) 2000-2005, Regents of the University of California * * and Stanford University. All rights reserved. * * * * Redistribution and use in source and binary forms, * * with or without modification, are permitted according to the terms * * listed in LICENSE (http://roofit.sourceforge.net/license.txt) * *****************************************************************************/ #include #include using std::cout; using std::cerr; using std::endl; using std::vector; #include "TMath.h" #include "TSystem.h" #include "LauConstants.hh" #include "LauCrystalBallPdf.hh" -ClassImp(LauCrystalBallPdf) LauCrystalBallPdf::LauCrystalBallPdf(const TString& theVarName, const vector& params, Double_t minAbscissa, Double_t maxAbscissa) : LauAbsPdf(theVarName, params, minAbscissa, maxAbscissa), mean_(0), sigma_(0), alpha_(0), n_(0) { // Constructor for the Crystal Ball PDF, which is a gaussian and a decaying tail // smoothly matched up. The tail goes as a 1/x^n // // The parameters in params are the mean and the sigma (half the width) of the gaussian, // the distance from the mean in which the gaussian and the tail are matched up (which // can be negative or positive), and the power "n" for the tail. // The last two arguments specify the range in which the PDF is defined, and the PDF // will be normalised w.r.t. these limits. mean_ = this->findParameter("mean"); sigma_ = this->findParameter("sigma"); alpha_ = this->findParameter("alpha"); n_ = this->findParameter("order"); if ((this->nParameters() != 4) || (mean_ == 0) || (sigma_ == 0) || (alpha_ == 0) || (n_ == 0)) { cerr<<"ERROR in LauCrystalBallPdf constructor: LauCrystalBallPdf requires 4 parameters: \"mean\", \"sigma\", \"alpha\" and \"order\"."<Exit(EXIT_FAILURE); } // Cache the normalisation factor this->calcNorm(); } LauCrystalBallPdf::~LauCrystalBallPdf() { // Destructor } void LauCrystalBallPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Get our abscissa Double_t abscissa = abscissas[0]; // Get the up to date parameter values Double_t mean = mean_->unblindValue(); Double_t sigma = sigma_->unblindValue(); Double_t alpha = alpha_->unblindValue(); Double_t n = n_->unblindValue(); Double_t result(0.0); Double_t t = (abscissa - mean)/sigma; if (alpha < 0.0) { t = -t; } Double_t absAlpha = TMath::Abs(alpha); if (t >= -absAlpha) { result = TMath::Exp(-0.5*t*t); } else { Double_t a = TMath::Power(n/absAlpha,n)*TMath::Exp(-0.5*absAlpha*absAlpha); Double_t b = n/absAlpha - absAlpha; result = a/TMath::Power(b - t, n); } this->setUnNormPDFVal(result); // if the parameters are floating then we // need to recalculate the normalisation if (!this->cachePDF() && !this->withinNormCalc() && !this->withinGeneration()) { this->calcNorm(); } } void LauCrystalBallPdf::calcNorm() { // Get the up to date parameter values Double_t mean = mean_->unblindValue(); Double_t sigma = sigma_->unblindValue(); Double_t alpha = alpha_->unblindValue(); Double_t n = n_->unblindValue(); Double_t result = 0.0; Bool_t useLog = kFALSE; if ( TMath::Abs(n-1.0) < 1.0e-05 ) { useLog = kTRUE; } Double_t sig = TMath::Abs(sigma); Double_t tmin = (this->getMinAbscissa() - mean)/sig; Double_t tmax = (this->getMaxAbscissa() - mean)/sig; if (alpha < 0) { Double_t tmp = tmin; tmin = -tmax; tmax = -tmp; } Double_t absAlpha = TMath::Abs(alpha); if ( tmin >= -absAlpha ) { result += sig*LauConstants::rootPiBy2*( this->approxErf( tmax / LauConstants::root2 ) - approxErf( tmin / LauConstants::root2 ) ); } else if ( tmax <= -absAlpha ) { Double_t a = TMath::Power(n/absAlpha, n)*TMath::Exp( -0.5*absAlpha*absAlpha); Double_t b = n/absAlpha - absAlpha; if ( useLog == kTRUE ) { result += a*sig*( TMath::Log(b - tmin) - TMath::Log(b - tmax) ); } else { result += a*sig/(1.0 - n)*( 1.0/(TMath::Power( b - tmin, n - 1.0)) - 1.0/(TMath::Power( b - tmax, n - 1.0)) ); } } else { Double_t a = TMath::Power(n/absAlpha, n)*TMath::Exp( -0.5*absAlpha*absAlpha ); Double_t b = n/absAlpha - absAlpha; Double_t term1 = 0.0; if ( useLog == kTRUE ) term1 = a*sig*( TMath::Log(b - tmin) - TMath::Log(n / absAlpha)); else term1 = a*sig/(1.0 - n)*( 1.0/(TMath::Power( b - tmin, n - 1.0)) - 1.0/(TMath::Power( n/absAlpha, n - 1.0)) ); Double_t term2 = sig*LauConstants::rootPiBy2*( this->approxErf( tmax / LauConstants::root2 ) - this->approxErf( -absAlpha / LauConstants::root2 ) ); result += term1 + term2; } this->setNorm(result); } void LauCrystalBallPdf::calcPDFHeight( const LauKinematics* /*kinematics*/ ) { if (this->heightUpToDate()) { return; } // Get the up to date parameter values Double_t mean = mean_->unblindValue(); // The Crystall Ball function is a Gaussian with an exponentially decaying tail // Therefore, calculate the PDF height for the Gaussian function. LauAbscissas abscissa(1); abscissa[0] = mean; this->calcLikelihoodInfo(abscissa); Double_t height = this->getUnNormLikelihood(); this->setMaxHeight(height); } Double_t LauCrystalBallPdf::approxErf(Double_t arg) const { static const Double_t erflim = 5.0; if ( arg > erflim ) { return 1.0; } if ( arg < -erflim ) { return -1.0; } return TMath::Erf(arg); } diff --git a/src/LauDPDepBifurGaussPdf.cc b/src/LauDPDepBifurGaussPdf.cc index 9974d6b..585a056 100644 --- a/src/LauDPDepBifurGaussPdf.cc +++ b/src/LauDPDepBifurGaussPdf.cc @@ -1,283 +1,282 @@ /* Copyright 2007 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauDPDepBifurGaussPdf.cc \brief File containing implementation of LauDPDepBifurGaussPdf class. */ #include #include using std::cout; using std::cerr; using std::endl; using std::vector; #include "TMath.h" #include "TRandom.h" #include "TSystem.h" #include "Lau1DHistPdf.hh" #include "LauConstants.hh" #include "LauComplex.hh" #include "LauDaughters.hh" #include "LauFitDataTree.hh" #include "LauKinematics.hh" #include "LauDPDepBifurGaussPdf.hh" -ClassImp(LauDPDepBifurGaussPdf) LauDPDepBifurGaussPdf::LauDPDepBifurGaussPdf(const TString& theVarName, const vector& params, Double_t minAbscissa, Double_t maxAbscissa, const LauDaughters* daughters, const vector& meanCoeffs, const vector& sigmaLCoeffs, const vector& sigmaRCoeffs, DPAxis dpAxis) : LauAbsPdf(theVarName, params, minAbscissa, maxAbscissa), kinematics_(daughters ? daughters->getKinematics() : 0), mean_(0), sigmaL_(0), sigmaR_(0), meanVal_(0.0), sigmaLVal_(0.0), sigmaRVal_(0.0), meanCoeffs_(meanCoeffs), sigmaLCoeffs_(sigmaLCoeffs), sigmaRCoeffs_(sigmaRCoeffs), dpAxis_(dpAxis), scaleMethod_(poly) { // Check we have a valid kinematics object if ( ! kinematics_ ) { cerr<<"ERROR in LauDPDepBifurGaussPdf::LauDPDepBifurGaussPdf : Have not been provided with a valid DP kinematics object."<Exit(EXIT_FAILURE); } // The parameters are: // - the mean, the sigmaL and the sigmaR of the Bifurcated Gaussian // // The next two arguments specify the range in which the PDF is defined, // and the PDF will be normalised w.r.t. these limits. // // The final three argument define whether the BF Gaussian parameters should be scaled or not mean_ = this->findParameter("mean"); sigmaL_ = this->findParameter("sigmaL"); sigmaR_ = this->findParameter("sigmaR"); if ((this->nParameters() != 3) || (mean_ == 0) || (sigmaL_ == 0) || (sigmaR_ == 0) ) { cerr<<"ERROR in LauDPDepBifurGaussPdf constructor: LauDPDepBifurGaussPdf requires 3 parameters:" <<" \"mean\", \"sigmaL\" and \"sigmaR\"."<Exit(EXIT_FAILURE); } // Cache the normalisation factor this->calcNorm(); } LauDPDepBifurGaussPdf::~LauDPDepBifurGaussPdf() { // Destructor } void LauDPDepBifurGaussPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissas are within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Get our abscissa Double_t abscissa = abscissas[0]; // Get the up to date parameter values meanVal_ = mean_->unblindValue(); sigmaLVal_ = sigmaL_->unblindValue(); sigmaRVal_ = sigmaR_->unblindValue(); // Find out the DP position Double_t dpPos(0.0); UInt_t nVars = this->nInputVars(); if ( abscissas.size() == nVars+2 ) { Double_t m13Sq = abscissas[nVars]; Double_t m23Sq = abscissas[nVars+1]; if ( dpAxis_ == M12 ) { dpPos = kinematics_->calcThirdMassSq(m13Sq,m23Sq); } else if ( dpAxis_ == M13 ) { dpPos = m13Sq; } else if ( dpAxis_ == M23 ) { dpPos = m23Sq; } else if ( dpAxis_ == MMIN ) { dpPos = TMath::Min( m13Sq, m23Sq ); } else if ( dpAxis_ == MMAX ) { dpPos = TMath::Max( m13Sq, m23Sq ); } else { dpPos = kinematics_->distanceFromDPCentre(m13Sq,m23Sq); } } // Scale the gaussian parameters by the dpPos (if appropriate) ScaleMethod scale = this->scaleMethod(); if ( scale==poly ) { this->scalePars_poly(dpPos); } else if ( scale==polyNegPower ) { this->scalePars_polyNegPower(dpPos); } else { cerr<<"Scaling method unknown! Methods available: and ."<Exit(EXIT_FAILURE); } // Evaluate the Birfucated Gaussian PDF value Double_t arg = abscissa - meanVal_; Double_t coef(0.0); Double_t value(0.0); if (arg < 0.0) { if (TMath::Abs(sigmaLVal_) > 1e-30) { coef = -0.5/(sigmaLVal_*sigmaLVal_); } } else { if (TMath::Abs(sigmaRVal_) > 1e-30) { coef = -0.5/(sigmaRVal_*sigmaRVal_); } } value = TMath::Exp(coef*arg*arg); // Calculate the norm Double_t xscaleL = LauConstants::root2*sigmaLVal_; Double_t xscaleR = LauConstants::root2*sigmaRVal_; Double_t integral(0.0); Double_t norm(0.0); Double_t result(0.0); if ( this->getMaxAbscissa() < meanVal_ ) { integral = sigmaLVal_ * ( TMath::Erf((this->getMaxAbscissa() - meanVal_)/xscaleL) - TMath::Erf((this->getMinAbscissa() - meanVal_)/xscaleL)); } else if ( this->getMinAbscissa() > meanVal_ ) { integral = sigmaRVal_ * (TMath::Erf((this->getMaxAbscissa() - meanVal_)/xscaleR) - TMath::Erf((this->getMinAbscissa() - meanVal_)/xscaleR)); } else { integral = sigmaRVal_*TMath::Erf((this->getMaxAbscissa() -meanVal_)/xscaleR) - sigmaLVal_*TMath::Erf((this->getMinAbscissa() - meanVal_)/xscaleL); } norm = LauConstants::rootPiBy2*integral; // the result result = value/norm; this->setUnNormPDFVal(result); } void LauDPDepBifurGaussPdf::scalePars_poly(Double_t dpPos) { Int_t power = 1; for (vector::const_iterator iter = meanCoeffs_.begin(); iter != meanCoeffs_.end(); ++iter) { Double_t coeff = (*iter); meanVal_ += coeff * TMath::Power(dpPos,power); ++power; } power = 1; for (vector::const_iterator iter = sigmaLCoeffs_.begin(); iter != sigmaLCoeffs_.end(); ++iter) { Double_t coeff = (*iter); sigmaLVal_ += coeff * TMath::Power(dpPos,power); ++power; } power = 1; for (vector::const_iterator iter = sigmaRCoeffs_.begin(); iter != sigmaRCoeffs_.end(); ++iter) { Double_t coeff = (*iter); sigmaRVal_ += coeff * TMath::Power(dpPos,power); ++power; } } void LauDPDepBifurGaussPdf::scalePars_polyNegPower(Double_t dpPos) { Int_t power = -1; for (vector::const_iterator iter = meanCoeffs_.begin(); iter != meanCoeffs_.end(); ++iter) { Double_t coeff = (*iter); meanVal_ += coeff * TMath::Power(dpPos,power); --power; } power = -1; for (vector::const_iterator iter = sigmaLCoeffs_.begin(); iter != sigmaLCoeffs_.end(); ++iter) { Double_t coeff = (*iter); sigmaLVal_ += coeff * TMath::Power(dpPos,power); --power; } power = -1; for (vector::const_iterator iter = sigmaRCoeffs_.begin(); iter != sigmaRCoeffs_.end(); ++iter) { Double_t coeff = (*iter); sigmaRVal_ += coeff * TMath::Power(dpPos,power); --power; } } void LauDPDepBifurGaussPdf::calcNorm() { this->setNorm(1.0); } void LauDPDepBifurGaussPdf::calcPDFHeight( const LauKinematics* kinematics ) { // Get the up to date parameter values meanVal_ = mean_->unblindValue(); sigmaLVal_ = sigmaL_->unblindValue(); sigmaRVal_ = sigmaR_->unblindValue(); // Scale the gaussian parameters by the dpCentreDist (if appropriate) Double_t dpCentreDist = kinematics->distanceFromDPCentre(); ScaleMethod scale = this->scaleMethod(); if ( scale==poly ) { this->scalePars_poly(dpCentreDist); } else if ( scale==polyNegPower ) { this->scalePars_polyNegPower(dpCentreDist); } else { cerr<<"Scaling method unknown! Methods available: and ."<Exit(EXIT_FAILURE); } // Calculate the PDF height for the Bifurcated Gaussian function. LauAbscissas maxPoint(3); maxPoint[0] = meanVal_; maxPoint[1] = kinematics->getm13Sq(); maxPoint[2] = kinematics->getm23Sq(); if ( meanVal_ > this->getMaxAbscissa() ) { maxPoint[0] = this->getMaxAbscissa(); } else if ( meanVal_ < this->getMinAbscissa() ) { maxPoint[0] = this->getMinAbscissa(); } this->calcLikelihoodInfo(maxPoint); Double_t height = this->getUnNormLikelihood(); // Multiply by a small factor to avoid problems from rounding errors height *= 1.001; this->setMaxHeight(height); } diff --git a/src/LauDPDepCruijffPdf.cc b/src/LauDPDepCruijffPdf.cc index dc17d27..41cc2d6 100644 --- a/src/LauDPDepCruijffPdf.cc +++ b/src/LauDPDepCruijffPdf.cc @@ -1,321 +1,320 @@ /* Copyright 2009 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauDPDepCruijffPdf.cc \brief File containing implementation of LauDPDepCruijffPdf class. */ #include #include using std::cout; using std::cerr; using std::endl; #include "TMath.h" #include "TSystem.h" #include "LauConstants.hh" #include "LauDaughters.hh" #include "LauDPDepCruijffPdf.hh" #include "LauKinematics.hh" -ClassImp(LauDPDepCruijffPdf) LauDPDepCruijffPdf::LauDPDepCruijffPdf(const TString& theVarName, const std::vector& params, Double_t minAbscissa, Double_t maxAbscissa, const LauDaughters* daughters, const std::vector& meanCoeffs, const std::vector& sigmaLCoeffs, const std::vector& sigmaRCoeffs, const std::vector& alphaLCoeffs, const std::vector& alphaRCoeffs, DPAxis dpAxis) : LauAbsPdf(theVarName, params, minAbscissa, maxAbscissa), kinematics_(daughters ? daughters->getKinematics() : 0), mean_(0), sigmaL_(0), sigmaR_(0), alphaL_(0), alphaR_(0), meanVal_(0.0), sigmaLVal_(0.0), sigmaRVal_(0.0), alphaLVal_(0.0), alphaRVal_(0.0), meanCoeffs_(meanCoeffs), sigmaLCoeffs_(sigmaLCoeffs), sigmaRCoeffs_(sigmaRCoeffs), alphaLCoeffs_(alphaLCoeffs), alphaRCoeffs_(alphaRCoeffs), dpAxis_(dpAxis) { // Constructor for the Dalitz-plot dependent Cruijff PDF. // Check we have a valid kinematics object if ( ! kinematics_ ) { cerr<<"ERROR in LauDPDepCruijffPdf::LauDPDepCruijffPdf : Have not been provided with a valid DP kinematics object."<Exit(EXIT_FAILURE); } // The parameters in params are the mean, sigmaR, sigmaL, alphaR and alphaL. // The last two arguments specify the range in which the PDF is defined, and the PDF // will be normalised w.r.t. these limits. mean_ = this->findParameter("mean"); sigmaR_ = this->findParameter("sigmaR"); sigmaL_ = this->findParameter("sigmaL"); alphaR_ = this->findParameter("alphaR"); alphaL_ = this->findParameter("alphaL"); if ((this->nParameters() != 5) || (mean_ == 0) || (sigmaR_ == 0) || (sigmaL_ == 0) || (alphaL_ == 0) || (alphaR_ == 0)) { cerr<<"ERROR in LauDPDepCruijffPdf constructor: LauDPDepCruijffPdf requires 5 parameters: \"mean\", \"sigmaL\", \"sigmaR\", \"alphaR\" and \"alphaL\"."<Exit(EXIT_FAILURE); } // Cache the normalisation factor this->calcNorm(); } LauDPDepCruijffPdf::~LauDPDepCruijffPdf() { // Destructor } void LauDPDepCruijffPdf::calcNorm() { this->setNorm(1.0); } void LauDPDepCruijffPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Get our abscissa Double_t abscissa = abscissas[0]; // Get the up to date parameter values meanVal_ = mean_->unblindValue(); sigmaLVal_ = sigmaL_->unblindValue(); sigmaRVal_ = sigmaR_->unblindValue(); alphaLVal_ = alphaL_->unblindValue(); alphaRVal_ = alphaR_->unblindValue(); // Find out the DP position Double_t dpPos(0.0); UInt_t nVars = this->nInputVars(); if ( abscissas.size() == nVars+2 ) { Double_t m13Sq = abscissas[nVars]; Double_t m23Sq = abscissas[nVars+1]; if ( dpAxis_ == M12 ) { dpPos = kinematics_->calcThirdMassSq(m13Sq,m23Sq); } else if ( dpAxis_ == M13 ) { dpPos = m13Sq; } else if ( dpAxis_ == M23 ) { dpPos = m23Sq; } else if ( dpAxis_ == MMIN ) { dpPos = TMath::Min( m13Sq, m23Sq ); } else if ( dpAxis_ == MMAX ) { dpPos = TMath::Max( m13Sq, m23Sq ); } else { dpPos = kinematics_->distanceFromDPCentre(m13Sq,m23Sq); } } // Scale the parameters according to the DP position this->scalePars( dpPos ); // Calculate the PDF value Double_t value = this->currentPDFValue( abscissa ); // Calculate the normalisation IntMethod sumMethod = this->integMethod(); Double_t normFac = (sumMethod == GaussLegendre) ? this->integrGaussLegendre() : this->integTrapezoid(); value /= normFac; this->setUnNormPDFVal(value); } Double_t LauDPDepCruijffPdf::currentPDFValue(Double_t abscissa) const { Double_t arg = abscissa - meanVal_; Double_t coef(0.0); if (arg < 0.0){ if (TMath::Abs(sigmaLVal_) > 1e-30) { coef = -1.0/(2.0*sigmaLVal_*sigmaLVal_ + alphaLVal_*arg*arg); } } else { if (TMath::Abs(sigmaRVal_) > 1e-30) { coef = -1.0/(2.0*sigmaRVal_*sigmaRVal_ + alphaRVal_*arg*arg); } } return TMath::Exp(coef*arg*arg); } Double_t LauDPDepCruijffPdf::integrGaussLegendre() { if (!this->normWeightsDone()) { this->getNormWeights(); } const std::vector& norm_abscissas = this->normAbscissas(); const std::vector& norm_weights = this->normWeights(); // Now compute the integral Double_t norm(0.0); for (UInt_t i = 0; i < norm_weights.size(); i++) { Double_t fun = this->currentPDFValue( norm_abscissas[i][0] ); Double_t intFactor = 0.5 * this->getRange(); norm += norm_weights[i]*intFactor*fun; } return norm; } Double_t LauDPDepCruijffPdf::integTrapezoid() { static Double_t norm(0.0); Double_t range = this->getRange(); if (this->nNormPoints()==1){ Double_t abscissa = this->getMinAbscissa(); Double_t funAbsMin = this->currentPDFValue(abscissa); abscissa = this->getMaxAbscissa(); Double_t funAbsMax = this->currentPDFValue(abscissa); norm = 0.5*range*(funAbsMin+funAbsMax); return norm; } else { Double_t abscVal(0.0), tnm(0.0), sum(0.0), del(0.0); Int_t it(0), j(0); for (it=1, j=1; j< this->nNormPoints()-1; j++) {it<<=1;} tnm=it; del=range/tnm; abscVal= this->getMinAbscissa()+ 0.5*del; for (sum = 0.0, j=1; jcurrentPDFValue(abscVal); sum+=funVal; } norm = 0.5*(norm + sum*range/tnm); return norm; } } void LauDPDepCruijffPdf::scalePars(Double_t dpPos) { Int_t power = 1; for (std::vector::const_iterator iter = meanCoeffs_.begin(); iter != meanCoeffs_.end(); ++iter) { Double_t coeff = (*iter); meanVal_ += coeff * TMath::Power(dpPos,power); ++power; } power = 1; for (std::vector::const_iterator iter = sigmaLCoeffs_.begin(); iter != sigmaLCoeffs_.end(); ++iter) { Double_t coeff = (*iter); sigmaLVal_ += coeff * TMath::Power(dpPos,power); ++power; } power = 1; for (std::vector::const_iterator iter = sigmaRCoeffs_.begin(); iter != sigmaRCoeffs_.end(); ++iter) { Double_t coeff = (*iter); sigmaRVal_ += coeff * TMath::Power(dpPos,power); ++power; } power = 1; for (std::vector::const_iterator iter = alphaLCoeffs_.begin(); iter != alphaLCoeffs_.end(); ++iter) { Double_t coeff = (*iter); alphaLVal_ += coeff * TMath::Power(dpPos,power); ++power; } power = 1; for (std::vector::const_iterator iter = alphaRCoeffs_.begin(); iter != alphaRCoeffs_.end(); ++iter) { Double_t coeff = (*iter); alphaRVal_ += coeff * TMath::Power(dpPos,power); ++power; } } void LauDPDepCruijffPdf::calcPDFHeight( const LauKinematics* kinematics ) { // Get the up to date parameter values meanVal_ = mean_->unblindValue(); sigmaLVal_ = sigmaL_->unblindValue(); sigmaRVal_ = sigmaR_->unblindValue(); alphaLVal_ = alphaL_->unblindValue(); alphaRVal_ = alphaR_->unblindValue(); // Find out the DP position Double_t dpPos(0.0); if ( dpAxis_ == M12 ) { dpPos = kinematics->getm12Sq(); } else if ( dpAxis_ == M13 ) { dpPos = kinematics->getm13Sq(); } else if ( dpAxis_ == M23 ) { dpPos = kinematics->getm23Sq(); } else { dpPos = kinematics->distanceFromDPCentre(); } // Scale the parameters according to the DP position this->scalePars( dpPos ); // Calculate the PDF height LauAbscissas maxPoint(3); maxPoint[0] = meanVal_; maxPoint[1] = kinematics->getm13Sq(); maxPoint[2] = kinematics->getm23Sq(); if (meanVal_ < this->getMinAbscissa()) { maxPoint[0] = this->getMinAbscissa(); } else if (meanVal_ > this->getMaxAbscissa()) { maxPoint[0] = this->getMaxAbscissa(); } this->calcLikelihoodInfo(maxPoint); Double_t height = this->getUnNormLikelihood(); // Multiply by a small factor to avoid problems from rounding errors height *= 1.01; this->setMaxHeight(height); } diff --git a/src/LauDPDepGaussPdf.cc b/src/LauDPDepGaussPdf.cc index e7bebfe..aeecdc7 100644 --- a/src/LauDPDepGaussPdf.cc +++ b/src/LauDPDepGaussPdf.cc @@ -1,217 +1,216 @@ /* Copyright 2009 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauDPDepGaussPdf.cc \brief File containing implementation of LauDPDepGaussPdf class. */ #include #include using std::cout; using std::cerr; using std::endl; #include "TMath.h" #include "TSystem.h" #include "LauConstants.hh" #include "LauDaughters.hh" #include "LauDPDepGaussPdf.hh" #include "LauKinematics.hh" -ClassImp(LauDPDepGaussPdf) LauDPDepGaussPdf::LauDPDepGaussPdf(const TString& theVarName, const std::vector& params, Double_t minAbscissa, Double_t maxAbscissa, const LauDaughters* daughters, const std::vector& meanCoeffs, const std::vector& sigmaCoeffs, DPAxis dpAxis) : LauAbsPdf(theVarName, params, minAbscissa, maxAbscissa), kinematics_(daughters ? daughters->getKinematics() : 0), mean_(0), sigma_(0), meanVal_(0.0), sigmaVal_(0.0), meanCoeffs_(meanCoeffs), sigmaCoeffs_(sigmaCoeffs), dpAxis_(dpAxis) { // Constructor for the Gaussian PDF. // Check we have a valid kinematics object if ( ! kinematics_ ) { cerr<<"ERROR in LauDPDepGaussPdf::LauDPDepGaussPdf : Have not been provided with a valid DP kinematics object."<Exit(EXIT_FAILURE); } // The parameters in params are the mean and the sigma (half the width) of the gaussian. // The last two arguments specify the range in which the PDF is defined, and the PDF // will be normalised w.r.t. these limits. mean_ = this->findParameter("mean"); sigma_ = this->findParameter("sigma"); if ((this->nParameters() != 2) || (mean_ == 0) || (sigma_ == 0)) { cerr<<"ERROR in LauDPDepGaussPdf constructor: LauDPDepGaussPdf requires 2 parameters: \"mean\" and \"sigma\"."<Exit(EXIT_FAILURE); } // Cache the normalisation factor this->calcNorm(); } LauDPDepGaussPdf::~LauDPDepGaussPdf() { // Destructor } void LauDPDepGaussPdf::calcNorm() { this->setNorm(1.0); } void LauDPDepGaussPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Get our abscissa Double_t abscissa = abscissas[0]; // Get the up to date parameter values meanVal_ = mean_->unblindValue(); sigmaVal_ = sigma_->unblindValue(); // Find out the DP position Double_t dpPos(0.0); UInt_t nVars = this->nInputVars(); if ( abscissas.size() == nVars+2 ) { Double_t m13Sq = abscissas[nVars]; Double_t m23Sq = abscissas[nVars+1]; if ( dpAxis_ == M12 ) { dpPos = kinematics_->calcThirdMassSq(m13Sq,m23Sq); } else if ( dpAxis_ == M13 ) { dpPos = m13Sq; } else if ( dpAxis_ == M23 ) { dpPos = m23Sq; } else if ( dpAxis_ == MMIN ) { dpPos = TMath::Min( m13Sq, m23Sq ); } else if ( dpAxis_ == MMAX ) { dpPos = TMath::Max( m13Sq, m23Sq ); } else { dpPos = kinematics_->distanceFromDPCentre(m13Sq,m23Sq); } } // Scale the parameters according to the DP position this->scalePars( dpPos ); // Calculate the value of the Gaussian for the given value of the abscissa. Double_t arg = abscissa - meanVal_; Double_t exponent(0.0); if (TMath::Abs(sigmaVal_) > 1e-10) { exponent = -0.5*arg*arg/(sigmaVal_*sigmaVal_); } Double_t value = TMath::Exp(exponent); Double_t norm(0.0); Double_t scale = LauConstants::root2*sigmaVal_; if (TMath::Abs(sigmaVal_) > 1e-10) { norm = LauConstants::rootPiBy2*sigmaVal_*(TMath::Erf((this->getMaxAbscissa() - meanVal_)/scale) - TMath::Erf((this->getMinAbscissa() - meanVal_)/scale)); } value /= norm; this->setUnNormPDFVal(value); } void LauDPDepGaussPdf::scalePars(Double_t dpPos) { Int_t power = 1; for (std::vector::const_iterator iter = meanCoeffs_.begin(); iter != meanCoeffs_.end(); ++iter) { Double_t coeff = (*iter); meanVal_ += coeff * TMath::Power(dpPos,power); ++power; } power = 1; for (std::vector::const_iterator iter = sigmaCoeffs_.begin(); iter != sigmaCoeffs_.end(); ++iter) { Double_t coeff = (*iter); sigmaVal_ += coeff * TMath::Power(dpPos,power); ++power; } } void LauDPDepGaussPdf::calcPDFHeight(const LauKinematics* kinematics) { // Get the up to date parameter values meanVal_ = mean_->unblindValue(); // Find out the DP position Double_t dpPos(0.0); if ( dpAxis_ == M12 ) { dpPos = kinematics->getm12Sq(); } else if ( dpAxis_ == M13 ) { dpPos = kinematics->getm13Sq(); } else if ( dpAxis_ == M23 ) { dpPos = kinematics->getm23Sq(); } else if ( dpAxis_ == MMIN ) { Double_t m13Sq = kinematics->getm13Sq(); Double_t m23Sq = kinematics->getm23Sq(); dpPos = TMath::Min( m13Sq, m23Sq ); } else if ( dpAxis_ == MMAX ) { Double_t m13Sq = kinematics->getm13Sq(); Double_t m23Sq = kinematics->getm23Sq(); dpPos = TMath::Max( m13Sq, m23Sq ); } else { dpPos = kinematics->distanceFromDPCentre(); } // Scale the parameters according to the DP position this->scalePars( dpPos ); LauAbscissas maxPoint(3); maxPoint[0] = meanVal_; maxPoint[1] = kinematics->getm13Sq(); maxPoint[2] = kinematics->getm23Sq(); // Calculate the PDF height for the Gaussian function. if (meanVal_>this->getMaxAbscissa()) { maxPoint[0] = this->getMaxAbscissa(); } else if (meanVal_getMinAbscissa()) { maxPoint[0] = this->getMinAbscissa(); } this->calcLikelihoodInfo(maxPoint); Double_t height = this->getUnNormLikelihood(); this->setMaxHeight(height); } diff --git a/src/LauDPDepMapPdf.cc b/src/LauDPDepMapPdf.cc index 67c195e..087d45d 100644 --- a/src/LauDPDepMapPdf.cc +++ b/src/LauDPDepMapPdf.cc @@ -1,369 +1,368 @@ /* Copyright 2013 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauDPDepMapPdf.cc \brief File containing implementation of LauDPDepMapPdf class. */ #include #include using std::cout; using std::cerr; using std::endl; #include "TH1.h" #include "TMath.h" #include "TSystem.h" #include "LauConstants.hh" #include "LauDaughters.hh" #include "Lau2DHistDP.hh" #include "LauParameter.hh" #include "LauDPDepMapPdf.hh" -ClassImp(LauDPDepMapPdf) LauDPDepMapPdf::LauDPDepMapPdf(const std::vector& pdfs, const LauDaughters* daughters, const TH2* dpHisto, Bool_t upperHalf) : LauAbsPdf((!pdfs.empty() && pdfs[0]) ? pdfs[0]->varNames() : std::vector(), std::vector(), (!pdfs.empty() && pdfs[0]) ? pdfs[0]->getMinAbscissas() : LauFitData(), (!pdfs.empty() && pdfs[0]) ? pdfs[0]->getMaxAbscissas() : LauFitData()), daughters_( new LauDaughters(*daughters) ), pdfs_(pdfs), dpDependence_( new Lau2DHistDP(dpHisto, daughters, kFALSE, kFALSE, 0, 0, upperHalf, daughters->squareDP()) ), dpAxisDependence_(0), dpAxis_( CentreDist ), indices_(0) { // Constructor for the PDF map. // The index into the PDF collection is read from the DP histogram. // So the first thing we have to do is check the pointers are all valid. for ( std::vector::const_iterator iter = pdfs_.begin(); iter != pdfs_.end(); ++iter){ if (!(*iter)) { cerr<<"ERROR in LauDPDepMapPdf constructor: one of the PDF pointers is null."<Exit(EXIT_FAILURE); } // Next check that the abscissa ranges are the same for each PDF if (pdfs_[0]->getMinAbscissa() != (*iter)->getMinAbscissa()) { cerr<<"ERROR in LauDPDepMapPdf constructor: minimum abscissa values not the same for two PDFs."<Exit(EXIT_FAILURE); } if (pdfs_[0]->getMaxAbscissa() != (*iter)->getMaxAbscissa()) { cerr<<"ERROR in LauDPDepMapPdf constructor: maximum abscissa values not the same for two PDFs."<Exit(EXIT_FAILURE); } // Also check that both PDFs are expecting the same number of input variables if (pdfs_[0]->nInputVars() != (*iter)->nInputVars()) { cerr<<"ERROR in LauDPDepMapPdf constructor: number of input variables not the same for two PDFs."<Exit(EXIT_FAILURE); } // Also check that both PDFs are expecting the same variable name(s) if (pdfs_[0]->varNames() != (*iter)->varNames()) { cerr<<"ERROR in LauDPDepMapPdf constructor: variable name(s) not the same for two PDFs."<Exit(EXIT_FAILURE); } } // Then we need to grab all the parameters and pass them to the base class. // This is so that when we are asked for them they can be put into the fit. for ( std::vector::const_iterator iter = pdfs_.begin(); iter != pdfs_.end(); ++iter){ std::vector& pdfpars = (*iter)->getParameters(); this->addParameters(pdfpars); } // Cache the normalisation factor this->calcNorm(); } LauDPDepMapPdf::LauDPDepMapPdf(const std::vector& pdfs, const LauDaughters* daughters, const TH1* dpAxisHisto, DPAxis dpAxis) : LauAbsPdf((!pdfs.empty() && pdfs[0]) ? pdfs[0]->varNames() : std::vector(), std::vector(), (!pdfs.empty() && pdfs[0]) ? pdfs[0]->getMinAbscissas() : LauFitData(), (!pdfs.empty() && pdfs[0]) ? pdfs[0]->getMaxAbscissas() : LauFitData()), daughters_( new LauDaughters(*daughters) ), pdfs_(pdfs), dpDependence_( 0 ), dpAxisDependence_(dpAxisHisto ? dynamic_cast(dpAxisHisto->Clone()) : 0), dpAxis_( dpAxis ), indices_( 0 ) { // Constructor for the PDFs map. // The index into the PDF collection is read from one of // the DP axes. if ( dpAxisDependence_ ) { dpAxisDependence_->SetDirectory(0); } // So the first thing we have to do is check the pointers are all valid. for ( std::vector::const_iterator iter = pdfs_.begin(); iter != pdfs_.end(); ++iter){ if (!(*iter)) { cerr<<"ERROR in LauDPDepMapPdf constructor: one of the PDF pointers is null."<Exit(EXIT_FAILURE); } // Next check that the abscissa ranges are the same for each PDF if (pdfs_[0]->getMinAbscissa() != (*iter)->getMinAbscissa()) { cerr<<"ERROR in LauDPDepMapPdf constructor: minimum abscissa values not the same for two PDFs."<Exit(EXIT_FAILURE); } if (pdfs_[0]->getMaxAbscissa() != (*iter)->getMaxAbscissa()) { cerr<<"ERROR in LauDPDepMapPdf constructor: maximum abscissa values not the same for two PDFs."<Exit(EXIT_FAILURE); } // Also check that both PDFs are expecting the same number of input variables if (pdfs_[0]->nInputVars() != (*iter)->nInputVars()) { cerr<<"ERROR in LauDPDepMapPdf constructor: number of input variables not the same for two PDFs."<Exit(EXIT_FAILURE); } // Also check that both PDFs are expecting the same variable name(s) if (pdfs_[0]->varNames() != (*iter)->varNames()) { cerr<<"ERROR in LauDPDepMapPdf constructor: variable name(s) not the same for two PDFs."<Exit(EXIT_FAILURE); } } // Then we need to grab all the parameters and pass them to the base class. // This is so that when we are asked for them they can be put into the fit. for ( std::vector::const_iterator iter = pdfs_.begin(); iter != pdfs_.end(); ++iter){ std::vector& pdfpars = (*iter)->getParameters(); this->addParameters(pdfpars); } // Cache the normalisation factor this->calcNorm(); } LauDPDepMapPdf::~LauDPDepMapPdf() { // Destructor delete daughters_; daughters_ = 0; delete dpDependence_; dpDependence_ = 0; delete dpAxisDependence_; dpAxisDependence_ = 0; } UInt_t LauDPDepMapPdf::determineDPRegion( Double_t m13Sq, Double_t m23Sq ) const { UInt_t regionIndex(0); LauKinematics* kinematics = daughters_->getKinematics(); kinematics->updateKinematics( m13Sq, m23Sq ); if ( dpDependence_ ) { if (daughters_->squareDP()){ Double_t mprime = kinematics->getmPrime(); Double_t thprime = kinematics->getThetaPrime(); regionIndex = static_cast( dpDependence_->interpolateXY( mprime, thprime ) ); } else { regionIndex = static_cast( dpDependence_->interpolateXY( m13Sq, m23Sq ) ); } } else if ( dpAxisDependence_ ) { Double_t dpPos(0.0); if ( dpAxis_ == M12 ) { dpPos = kinematics->calcThirdMassSq(m13Sq,m23Sq); } else if ( dpAxis_ == M13 ) { dpPos = m13Sq; } else if ( dpAxis_ == M23 ) { dpPos = m23Sq; } else if ( dpAxis_ == MMIN ) { dpPos = TMath::Min( m13Sq, m23Sq ); } else if ( dpAxis_ == MMAX ) { dpPos = TMath::Max( m13Sq, m23Sq ); } else { dpPos = kinematics->distanceFromDPCentre(m13Sq,m23Sq); } Int_t bin = dpAxisDependence_->FindFixBin( dpPos ); regionIndex = static_cast( dpAxisDependence_->GetBinContent( bin ) ); } else { // This should never happen cerr << "ERROR in LauDPDepMapPdf::determineDPRegion : No means of determining the region!" << endl; gSystem->Exit(EXIT_FAILURE); } return regionIndex; } void LauDPDepMapPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Create a set of absissas that doesn't contain the DP variables UInt_t nVars = this->nInputVars(); LauAbscissas noDPVars( nVars ); for ( UInt_t i(0); i < nVars; ++i ) { noDPVars[i] = abscissas[i]; } // Find which region of the DP we're in // The DP variables will be abscissas[nInputVars] and // abscissas[nInputVars+1] (if present). UInt_t regionIndex(0); if ( abscissas.size() == nVars+2 ) { Double_t m13Sq = abscissas[nVars]; Double_t m23Sq = abscissas[nVars+1]; regionIndex = this->determineDPRegion( m13Sq, m23Sq ); } else { // This should never happen cerr << "ERROR in LauDPDepMapPdf::calcLikelihoodInfo : DP vars not supplied, no means of determining the region!" << endl; gSystem->Exit(EXIT_FAILURE); } // Check that the region index is valid if ( regionIndex >= pdfs_.size() ) { cerr << "ERROR in LauDPDepMapPdf::calcLikelihoodInfo : No PDF supplied for region " << regionIndex << endl; gSystem->Exit(EXIT_FAILURE); } // Evaluate the normalised PDF values LauAbsPdf* pdf = pdfs_[regionIndex]; if ( pdf->isDPDependent() ) { pdf->calcLikelihoodInfo(abscissas); } else { pdf->calcLikelihoodInfo(noDPVars); } Double_t result = pdf->getUnNormLikelihood(); this->setUnNormPDFVal(result); Double_t norm = pdf->getNorm(); this->setNorm(norm); } void LauDPDepMapPdf::calcNorm() { // Nothing to do here, since it is already normalized this->setNorm(1.0); } void LauDPDepMapPdf::calcPDFHeight( const LauKinematics* kinematics ) { // This method gives you the maximum possible height of the PDF. // It combines the maximum heights of the two individual PDFs. // So it would give the true maximum if the two individual maxima coincided. // It is guaranteed to always be >= the true maximum. Double_t m13Sq = kinematics->getm13Sq(); Double_t m23Sq = kinematics->getm23Sq(); // Find which region of the DP we're in UInt_t regionIndex = this->determineDPRegion( m13Sq, m23Sq ); // Check that the region index is valid if ( regionIndex >= pdfs_.size() ) { cerr << "ERROR in LauDPDepMapPdf::calcPDFHeight : No PDF supplied for region " << regionIndex << endl; gSystem->Exit(EXIT_FAILURE); } // Evaluate the normalised PDF values LauAbsPdf* pdf = pdfs_[regionIndex]; // Update the heights of the individual PDFs pdf->calcPDFHeight( kinematics ); // Find the PDF maximum Double_t height = pdf->getMaxHeight(); this->setMaxHeight(height); } // Override the base class methods for cacheInfo and calcLikelihoodInfo(UInt_t iEvt). // For both of these we delegate some functionality to the constituent PDFs. void LauDPDepMapPdf::cacheInfo(const LauFitDataTree& inputData) { // delegate to the sub-PDFs to cache their information for ( std::vector::const_iterator iter = pdfs_.begin(); iter != pdfs_.end(); ++iter){ (*iter)->cacheInfo( inputData ); } // now check that the DP variables are included in the data Bool_t hasBranch = inputData.haveBranch( "m13Sq" ); hasBranch &= inputData.haveBranch( "m23Sq" ); if (!hasBranch) { cerr<<"ERROR in LauDPDepMapPdf::cacheInfo : Input data does not contain Dalitz plot variables m13Sq and/or m23Sq."<nFixedParameters() == this->nParameters() ); this->cachePDF( doCaching ); if ( !doCaching ) { // in this case we seem to be doing a fit where the parameters are floating // so need to mark that the PDF height is no longer up to date this->heightUpToDate(kFALSE); } // clear the vector and reserve enough space UInt_t nEvents = inputData.nEvents(); indices_.clear(); indices_.reserve(nEvents); // loop through the events, determine the fraction and store for (UInt_t iEvt = 0; iEvt < nEvents; ++iEvt) { const LauFitData& dataValues = inputData.getData(iEvt); Double_t m13Sq = dataValues.find("m13Sq")->second; Double_t m23Sq = dataValues.find("m23Sq")->second; UInt_t regionIndex = this->determineDPRegion( m13Sq, m23Sq ); indices_.push_back( regionIndex ); } } void LauDPDepMapPdf::calcLikelihoodInfo(UInt_t iEvt) { // Get the fraction value for this event UInt_t regionIndex = indices_[iEvt]; // Evaluate the normalised PDF value LauAbsPdf* pdf = pdfs_[regionIndex]; pdf->calcLikelihoodInfo(iEvt); Double_t result = pdf->getUnNormLikelihood(); this->setUnNormPDFVal(result); Double_t norm = pdf->getNorm(); this->setNorm(norm); } diff --git a/src/LauDPDepSumPdf.cc b/src/LauDPDepSumPdf.cc index 47f0815..fae9a6e 100644 --- a/src/LauDPDepSumPdf.cc +++ b/src/LauDPDepSumPdf.cc @@ -1,432 +1,431 @@ /* Copyright 2009 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauDPDepSumPdf.cc \brief File containing implementation of LauDPDepSumPdf class. */ #include #include using std::cout; using std::cerr; using std::endl; using std::vector; #include "TMath.h" #include "TSystem.h" #include "LauConstants.hh" #include "LauDaughters.hh" #include "LauEffModel.hh" #include "LauParameter.hh" #include "LauDPDepSumPdf.hh" -ClassImp(LauDPDepSumPdf) LauDPDepSumPdf::LauDPDepSumPdf(LauAbsPdf* pdf1, LauAbsPdf* pdf2, const LauDaughters* daughters, const TH2* dpHisto, Bool_t upperHalf, Bool_t useSpline) : LauAbsPdf(pdf1 ? pdf1->varNames() : vector(), vector(), pdf1 ? pdf1->getMinAbscissas() : LauFitData(), pdf1 ? pdf1->getMaxAbscissas() : LauFitData()), daughters_( new LauDaughters(*daughters) ), pdf1_(pdf1), pdf2_(pdf2), frac_(0), fracVal_(0.5), dpDependence_( new LauEffModel(daughters, 0) ), dpAxis_( CentreDist ) { // Constructor for the sum PDF. // We are defining the sum as: // f x (PDF1/S(PDF1)) + (1-f) x (PDF2/S(PDF2)) // where f is the fraction, x is multiplication, PDFi is the i'th PDF, // and S(PDFi) is the integral of the i'th PDF. // The value of the fraction is read from the DP histogram. if(useSpline) { dpDependence_->setEffSpline( dpHisto, kFALSE, 0.0, 0.0, upperHalf, daughters->squareDP()); } else { dpDependence_->setEffHisto( dpHisto, kTRUE, kFALSE, 0.0, 0.0, upperHalf, daughters->squareDP() ); } // So the first thing we have to do is check the pointers are all valid. if (!pdf1 || !pdf2) { cerr<<"ERROR in LauDPDepSumPdf constructor: one of the 2 PDF pointers is null."<Exit(EXIT_FAILURE); } // Next check that the abscissa ranges are the same for each PDF if (pdf1->getMinAbscissa() != pdf2->getMinAbscissa()) { cerr<<"ERROR in LauDPDepSumPdf constructor: minimum abscissa values not the same for the two PDFs."<Exit(EXIT_FAILURE); } if (pdf1->getMaxAbscissa() != pdf2->getMaxAbscissa()) { cerr<<"ERROR in LauDPDepSumPdf constructor: maximum abscissa values not the same for the two PDFs."<Exit(EXIT_FAILURE); } // Also check that both PDFs are expecting the same number of input variables if (pdf1->nInputVars() != pdf2->nInputVars()) { cerr<<"ERROR in LauDPDepSumPdf constructor: number of input variables not the same for the two PDFs."<Exit(EXIT_FAILURE); } // Also check that both PDFs are expecting the same variable name(s) if (pdf1->varNames() != pdf2->varNames()) { cerr<<"ERROR in LauDPDepSumPdf constructor: variable name(s) not the same for the two PDFs."<Exit(EXIT_FAILURE); } // Then we need to grab all the parameters and pass them to the base class. // This is so that when we are asked for them they can be put into the fit. // The number of parameters is the number in PDF1 + the number in PDF2. UInt_t nPar(pdf1->nParameters()+pdf2->nParameters()); vector params; params.reserve(nPar); vector& pdf1pars = pdf1->getParameters(); vector& pdf2pars = pdf2->getParameters(); for (vector::iterator iter = pdf1pars.begin(); iter != pdf1pars.end(); ++iter) { params.push_back(*iter); } for (vector::iterator iter = pdf2pars.begin(); iter != pdf2pars.end(); ++iter) { params.push_back(*iter); } this->addParameters(params); // Cache the normalisation factor this->calcNorm(); } LauDPDepSumPdf::LauDPDepSumPdf(LauAbsPdf* pdf1, LauAbsPdf* pdf2, LauParameter* frac, const LauDaughters* daughters, const std::vector& fracCoeffs, DPAxis dpAxis) : LauAbsPdf(pdf1 ? pdf1->varNames() : vector(), vector(), pdf1 ? pdf1->getMinAbscissas() : LauFitData(), pdf1 ? pdf1->getMaxAbscissas() : LauFitData()), daughters_( new LauDaughters(*daughters) ), pdf1_(pdf1), pdf2_(pdf2), frac_(frac), fracVal_( frac ? frac->unblindValue() : 0.0 ), dpDependence_( 0 ), fracCoeffs_( fracCoeffs ), dpAxis_( dpAxis ) { // Constructor for the sum PDF. // We are defining the sum as: // f x (PDF1/S(PDF1)) + (1-f) x (PDF2/S(PDF2)) // where f is the fraction, x is multiplication, PDFi is the i'th PDF, // and S(PDFi) is the integral of the i'th PDF. // The value of the fraction has a polynomial dependence on one of // the DP axes. // So the first thing we have to do is check the pointers are all valid. if (!pdf1 || !pdf2) { cerr<<"ERROR in LauDPDepSumPdf constructor: one of the 2 PDF pointers is null."<Exit(EXIT_FAILURE); } if ( !frac ) { cerr<<"ERROR in LauDPDepSumPdf constructor: the fraction parameter pointer is null."<Exit(EXIT_FAILURE); } // Next check that the abscissa ranges are the same for each PDF if (pdf1->getMinAbscissa() != pdf2->getMinAbscissa()) { cerr<<"ERROR in LauDPDepSumPdf constructor: minimum abscissa values not the same for the two PDFs."<Exit(EXIT_FAILURE); } if (pdf1->getMaxAbscissa() != pdf2->getMaxAbscissa()) { cerr<<"ERROR in LauDPDepSumPdf constructor: maximum abscissa values not the same for the two PDFs."<Exit(EXIT_FAILURE); } // Also check that both PDFs are expecting the same number of input variables if (pdf1->nInputVars() != pdf2->nInputVars()) { cerr<<"ERROR in LauDPDepSumPdf constructor: number of input variables not the same for the two PDFs."<Exit(EXIT_FAILURE); } // Also check that both PDFs are expecting the same variable name(s) if (pdf1->varNames() != pdf2->varNames()) { cerr<<"ERROR in LauDPDepSumPdf constructor: variable name(s) not the same for the two PDFs."<Exit(EXIT_FAILURE); } // Then we need to grab all the parameters and pass them to the base class. // This is so that when we are asked for them they can be put into the fit. // The number of parameters is the number in PDF1 + the number in PDF2. UInt_t nPar( pdf1->nParameters() + pdf2->nParameters() + 1 ); vector params; params.reserve(nPar); params.push_back(frac); vector& pdf1pars = pdf1->getParameters(); vector& pdf2pars = pdf2->getParameters(); for (vector::iterator iter = pdf1pars.begin(); iter != pdf1pars.end(); ++iter) { params.push_back(*iter); } for (vector::iterator iter = pdf2pars.begin(); iter != pdf2pars.end(); ++iter) { params.push_back(*iter); } this->addParameters(params); // Now check that we can find the fraction parameter ok frac_ = this->findParameter("frac"); if (frac_ == 0) { cerr<<"ERROR in LauDPDepSumPdf constructor: parameter \"frac\" not found."<Exit(EXIT_FAILURE); } // Cache the normalisation factor this->calcNorm(); } LauDPDepSumPdf::~LauDPDepSumPdf() { // Destructor delete daughters_; daughters_ = 0; delete dpDependence_; dpDependence_ = 0; } void LauDPDepSumPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } LauAbscissas noDPVars(1); noDPVars[0] = abscissas[0]; // Evaluate the normalised PDF values if ( pdf1_->isDPDependent() ) { pdf1_->calcLikelihoodInfo(abscissas); } else { pdf1_->calcLikelihoodInfo(noDPVars); } if ( pdf2_->isDPDependent() ) { pdf2_->calcLikelihoodInfo(abscissas); } else { pdf2_->calcLikelihoodInfo(noDPVars); } Double_t result1 = pdf1_->getLikelihood(); Double_t result2 = pdf2_->getLikelihood(); // Determine the fraction // The DP variables will be abscissas[nInputVars] and // abscissas[nInputVars+1] (if present). UInt_t nVars = this->nInputVars(); if ( abscissas.size() == nVars+2 ) { Double_t m13Sq = abscissas[nVars]; Double_t m23Sq = abscissas[nVars+1]; LauKinematics* kinematics = daughters_->getKinematics(); if ( dpDependence_ ) { kinematics->updateKinematics( m13Sq, m23Sq ); fracVal_ = dpDependence_->calcEfficiency( kinematics ); } else { fracVal_ = frac_->unblindValue(); Double_t dpPos(0.0); if ( dpAxis_ == M12 ) { dpPos = kinematics->calcThirdMassSq(m13Sq,m23Sq); } else if ( dpAxis_ == M13 ) { dpPos = m13Sq; } else if ( dpAxis_ == M23 ) { dpPos = m23Sq; } else if ( dpAxis_ == MMIN ) { dpPos = TMath::Min( m13Sq, m23Sq ); } else if ( dpAxis_ == MMAX ) { dpPos = TMath::Max( m13Sq, m23Sq ); } else { dpPos = kinematics->distanceFromDPCentre(m13Sq,m23Sq); } this->scaleFrac( dpPos ); } } // Add them together Double_t result = fracVal_ * result1 + (1.0-fracVal_) * result2; this->setUnNormPDFVal(result); } void LauDPDepSumPdf::scaleFrac( Double_t dpPos ) { Int_t power = 1; for (std::vector::const_iterator iter = fracCoeffs_.begin(); iter != fracCoeffs_.end(); ++iter) { Double_t coeff = (*iter); fracVal_ += coeff * TMath::Power(dpPos,power); ++power; } } void LauDPDepSumPdf::calcNorm() { // Nothing to do here, since it is already normalized this->setNorm(1.0); } void LauDPDepSumPdf::calcPDFHeight( const LauKinematics* kinematics ) { // This method gives you the maximum possible height of the PDF. // It combines the maximum heights of the two individual PDFs. // So it would give the true maximum if the two individual maxima coincided. // It is guaranteed to always be >= the true maximum. // Update the heights of the individual PDFs pdf1_->calcPDFHeight( kinematics ); pdf2_->calcPDFHeight( kinematics ); // Get the up to date parameter values if ( dpDependence_ ) { fracVal_ = dpDependence_->calcEfficiency( kinematics ); } else { fracVal_ = frac_->unblindValue(); Double_t dpPos(0.0); if ( dpAxis_ == M12 ) { dpPos = kinematics->getm12Sq(); } else if ( dpAxis_ == M13 ) { dpPos = kinematics->getm13Sq(); } else if ( dpAxis_ == M23 ) { dpPos = kinematics->getm23Sq(); } else if ( dpAxis_ == MMIN ) { Double_t m13Sq = kinematics->getm13Sq(); Double_t m23Sq = kinematics->getm23Sq(); dpPos = TMath::Min( m13Sq, m23Sq ); } else if ( dpAxis_ == MMAX ) { Double_t m13Sq = kinematics->getm13Sq(); Double_t m23Sq = kinematics->getm23Sq(); dpPos = TMath::Max( m13Sq, m23Sq ); } else { dpPos = kinematics->distanceFromDPCentre(); } this->scaleFrac( dpPos ); } // Find the (un-normalised) individual PDF maxima Double_t height1 = pdf1_->getMaxHeight(); Double_t height2 = pdf2_->getMaxHeight(); // Get the individual PDF normalisation factors Double_t norm1 = pdf1_->getNorm(); Double_t norm2 = pdf2_->getNorm(); // Calculate the normalised individual PDF maxima height1 /= norm1; height2 /= norm2; // Combine these heights together Double_t height = fracVal_ * height1 + (1-fracVal_) * height2; this->setMaxHeight(height); } // Override the base class methods for cacheInfo and calcLikelihoodInfo(UInt_t iEvt). // For both of these we delegate to the two constituent PDFs. void LauDPDepSumPdf::cacheInfo(const LauFitDataTree& inputData) { // delegate to the two sub-PDFs to cache their information pdf1_->cacheInfo(inputData); pdf2_->cacheInfo(inputData); // now check that the DP variables are included in the data Bool_t hasBranch = inputData.haveBranch( "m13Sq" ); hasBranch &= inputData.haveBranch( "m23Sq" ); if (!hasBranch) { cerr<<"ERROR in LauDPDepSumPdf::cacheInfo : Input data does not contain Dalitz plot variables m13Sq and/or m23Sq."<nFixedParameters() == this->nParameters() ); this->cachePDF( doCaching ); if ( !doCaching ) { // in this case we seem to be doing a fit where the parameters are floating // so need to mark that the PDF height is no longer up to date this->heightUpToDate(kFALSE); } // clear the vector and reserve enough space UInt_t nEvents = inputData.nEvents(); fractions_.clear(); fractions_.reserve(nEvents); // loop through the events, determine the fraction and store for (UInt_t iEvt = 0; iEvt < nEvents; iEvt++) { const LauFitData& dataValues = inputData.getData(iEvt); Double_t m13Sq = dataValues.find("m13Sq")->second; Double_t m23Sq = dataValues.find("m23Sq")->second; LauKinematics* kinematics = daughters_->getKinematics(); if ( dpDependence_ ) { // if we're using the histogram then just // determine the fraction and store kinematics->updateKinematics( m13Sq, m23Sq ); fracVal_ = dpDependence_->calcEfficiency( kinematics ); } else { // if we're scaling the fraction parameter then we // just store the scaling info since the parameter // might be floating fracVal_ = frac_->unblindValue(); Double_t dpPos(0.0); if ( dpAxis_ == M12 ) { dpPos = kinematics->calcThirdMassSq(m13Sq,m23Sq); } else if ( dpAxis_ == M13 ) { dpPos = m13Sq; } else if ( dpAxis_ == M23 ) { dpPos = m23Sq; } else if ( dpAxis_ == MMIN ) { dpPos = TMath::Min( m13Sq, m23Sq ); } else if ( dpAxis_ == MMAX ) { dpPos = TMath::Max( m13Sq, m23Sq ); } else { dpPos = kinematics->distanceFromDPCentre(m13Sq,m23Sq); } this->scaleFrac( dpPos ); fracVal_ -= frac_->unblindValue(); } fractions_.push_back( fracVal_ ); } } void LauDPDepSumPdf::calcLikelihoodInfo(UInt_t iEvt) { // Get the fraction value for this event fracVal_ = fractions_[iEvt]; if ( frac_ ) { // if we're scaling the parameter then need to add the // current value of the parameter fracVal_ += frac_->unblindValue(); } // Evaluate the normalised PDF values pdf1_->calcLikelihoodInfo(iEvt); pdf2_->calcLikelihoodInfo(iEvt); Double_t result1 = pdf1_->getLikelihood(); Double_t result2 = pdf2_->getLikelihood(); // Add them together Double_t result = fracVal_ * result1 + (1-fracVal_) * result2; this->setUnNormPDFVal(result); } diff --git a/src/LauDPPartialIntegralInfo.cc b/src/LauDPPartialIntegralInfo.cc index 0da95b6..35f5427 100644 --- a/src/LauDPPartialIntegralInfo.cc +++ b/src/LauDPPartialIntegralInfo.cc @@ -1,187 +1,186 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauDPPartialIntegralInfo.cc \brief File containing implementation of LauDPPartialIntegralInfo class. */ #include #include "LauDPPartialIntegralInfo.hh" #include "LauIntegrals.hh" #include "LauKinematics.hh" -ClassImp(LauDPPartialIntegralInfo) LauDPPartialIntegralInfo::LauDPPartialIntegralInfo(const Double_t minm13, const Double_t maxm13, const Double_t minm23, const Double_t maxm23, const Double_t m13BinWidth, const Double_t m23BinWidth, const Double_t precision, const UInt_t nAmp, const UInt_t nIncohAmp, const Bool_t squareDP, const LauKinematics* kinematics) : minm13_(minm13), maxm13_(maxm13), minm23_(minm23), maxm23_(maxm23), m13BinWidth_(m13BinWidth), m23BinWidth_(m23BinWidth), nm13Points_(static_cast((maxm13-minm13)/m13BinWidth)), nm23Points_(static_cast((maxm23-minm23)/m23BinWidth)), nAmp_(nAmp), nIncohAmp_(nIncohAmp), squareDP_(squareDP) { const Double_t meanm13 = 0.5*(minm13 + maxm13); const Double_t rangem13 = maxm13 - minm13; const Double_t halfRangem13 = 0.5*rangem13; const Double_t meanm23 = 0.5*(minm23 + maxm23); const Double_t rangem23 = maxm23 - minm23; const Double_t halfRangem23 = 0.5*rangem23; const Double_t intFactor = halfRangem13*halfRangem23; // Raise error if squareDP is true but the kinematics object is not provided if ( squareDP_ && kinematics == 0 ) { std::cerr << "ERROR in LauDPPartialIntegralInfo constructor : Integration in the square DP has been specified but no valid kinematics object has been provided!" << std::endl; return; } // Avoid integral if we have no points in either x or y space if (nm13Points_ == 0 || nm23Points_ == 0) { std::cerr << "ERROR in LauDPPartialIntegralInfo constructor : Range has zero grid points in one or both of the dimensions!" << std::endl; return; } // Print a warning if we have a very large number of points if ( (nm13Points_ * nm23Points_) > 8000000 ) { std::cerr << "WARNING in LauDPPartialIntegralInfo constructor : The integration binning scheme has a very large number of bins, this could cause high memory consumption!" << std::endl; std::cerr << " : In case of problems, consider using LauIsobarDynamics::setNarrowResonanceThreshold and/or LauIsobarDynamics::setIntegralBinningFactor to tune the binning behaviour." << std::endl; } LauIntegrals dpIntegrals(precision); dpIntegrals.calcGaussLegendreWeights(nm13Points_, m13Points_, m13Weights_); dpIntegrals.calcGaussLegendreWeights(nm23Points_, m23Points_, m23Weights_); // Print out total weights for the integration Double_t totm13Weight(0.0), totm23Weight(0.0); for (UInt_t i = 0; i < nm13Points_; ++i) { totm13Weight += m13Weights_[i]; } for (UInt_t i = 0; i < nm23Points_; ++i) { totm23Weight += m23Weights_[i]; } if ( squareDP_ ) { std::cout<<"INFO in LauDPPartialIntegralInfo constructor : nmPrimePoints = "< #include "LauConstants.hh" #include "LauDabbaRes.hh" #include "LauResonanceInfo.hh" -ClassImp(LauDabbaRes) LauDabbaRes::LauDabbaRes(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), mSumSq_(0.0), sAdler_(0.0), b_(0), alpha_(0), beta_(0) { // Default constant factors const Double_t bVal = 24.49; const Double_t alphaVal = 0.1; const Double_t betaVal = 0.1; const TString& parNameBase = this->getSanitisedName(); TString bName(parNameBase); bName += "_b"; b_ = resInfo->getExtraParameter( bName ); if ( b_ == 0 ) { b_ = new LauParameter( bName, bVal, 0.0, 100.0, kTRUE ); b_->secondStage(kTRUE); resInfo->addExtraParameter( b_ ); } TString alphaName(parNameBase); alphaName += "_alpha"; alpha_ = resInfo->getExtraParameter( alphaName ); if ( alpha_ == 0 ) { alpha_ = new LauParameter( alphaName, alphaVal, 0.0, 10.0, kTRUE ); alpha_->secondStage(kTRUE); resInfo->addExtraParameter( alpha_ ); } TString betaName(parNameBase); betaName += "_beta"; beta_ = resInfo->getExtraParameter( betaName ); if ( beta_ == 0 ) { beta_ = new LauParameter( betaName, betaVal, 0.0, 10.0, kTRUE ); beta_->secondStage(kTRUE); resInfo->addExtraParameter( beta_ ); } } LauDabbaRes::~LauDabbaRes() { } void LauDabbaRes::initialise() { // check that we have a D and a pi this->checkDaughterTypes(); // Initialise various constants Double_t massDaug1 = this->getMassDaug1(); Double_t massDaug2 = this->getMassDaug2(); Double_t mSum = massDaug1 + massDaug2; mSumSq_ = mSum*mSum; Double_t massDaug1Sq = massDaug1*massDaug1; Double_t massDaug2Sq = massDaug2*massDaug2; sAdler_ = TMath::Max(massDaug1Sq,massDaug2Sq) - 0.5*TMath::Min(massDaug1Sq,massDaug2Sq); // Adler zero at (mD)^2 - 0.5*(mpi)^2 Int_t resSpin = this->getSpin(); if (resSpin != 0) { std::cerr << "WARNING in LauDabbaRes::initialise : Spin = " << resSpin << " is not zero! It will be ignored anyway!" << std::endl; } } void LauDabbaRes::checkDaughterTypes() const { // Check that the daughter tracks are D and pi. Otherwise issue a warning. Int_t resPairAmpInt = this->getPairInt(); if (resPairAmpInt < 1 || resPairAmpInt > 3) { std::cerr << "WARNING in LauDabbaRes::checkDaughterTypes : resPairAmpInt = " << resPairAmpInt << " is out of the range [1,2,3]." << std::endl; return; } // Check that daughter types agree const TString& nameDaug1 = this->getNameDaug1(); const TString& nameDaug2 = this->getNameDaug2(); if ( !( nameDaug1.Contains("pi", TString::kIgnoreCase) && nameDaug2.Contains("d", TString::kIgnoreCase) ) ) { if ( !( nameDaug2.Contains("pi", TString::kIgnoreCase) && nameDaug1.Contains("d", TString::kIgnoreCase) ) ) { std::cerr << "ERROR in LauDabbaRes::checkDaughterTypes : Dabba model is using daughters \"" << nameDaug1 << "\" and \"" << nameDaug2 << "\" that are not a D meson and a pion." << std::endl; } } } LauComplex LauDabbaRes::resAmp(Double_t mass, Double_t spinTerm) { // This function returns the complex dynamical amplitude for a Dabba distribution // given the invariant mass and cos(helicity) values. // Invariant mass squared combination for the system Double_t s = mass*mass; // Dabba is spin zero - so there are no helicity factors. // Just set it to 1.0 in case anyone decides to use it at a later date. spinTerm = 1.0; // Phase-space factor Double_t rho(0.0); Double_t sDiff = s - mSumSq_; if ( sDiff > 0.0 ) { rho = TMath::Sqrt(1.0 - mSumSq_/s); } const Double_t bVal = this->getBValue(); const Double_t alphaVal = this->getAlphaValue(); const Double_t betaVal = this->getBetaValue(); Double_t realPart = 1.0 - betaVal * sDiff; Double_t imagPart = bVal * TMath::Exp( - alphaVal * sDiff ) * ( s - sAdler_ ) * rho; LauComplex resAmplitude( realPart, imagPart ); Double_t denomFactor = realPart*realPart + imagPart*imagPart; Double_t invDenomFactor = 0.0; if (denomFactor > 1e-10) {invDenomFactor = 1.0/denomFactor;} resAmplitude.rescale(spinTerm*invDenomFactor); return resAmplitude; } const std::vector& LauDabbaRes::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixBValue() ) { this->addFloatingParameter( b_ ); } if ( ! this->fixAlphaValue() ) { this->addFloatingParameter( alpha_ ); } if ( ! this->fixBetaValue() ) { this->addFloatingParameter( beta_ ); } return this->getParameters(); } void LauDabbaRes::setResonanceParameter(const TString& name, const Double_t value) { // Set various parameters for the lineshape if (name == "b") { this->setBValue(value); std::cout << "INFO in LauDabbaRes::setResonanceParameter : Setting parameter b = " << this->getBValue() << std::endl; } else if (name == "alpha") { this->setAlphaValue(value); std::cout << "INFO in LauDabbaRes::setResonanceParameter : Setting parameter alpha = " << this->getAlphaValue() << std::endl; } else if (name == "beta") { this->setBetaValue(value); std::cout << "INFO in LauDabbaRes::setResonanceParameter : Setting parameter beta = " << this->getBetaValue() << std::endl; } else { std::cerr << "WARNING in LauDabbaRes::setResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } void LauDabbaRes::floatResonanceParameter(const TString& name) { if (name == "b") { if ( b_->fixed() ) { b_->fixed( kFALSE ); this->addFloatingParameter( b_ ); } else { std::cerr << "WARNING in LauDabbaRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "alpha") { if ( alpha_->fixed() ) { alpha_->fixed( kFALSE ); this->addFloatingParameter( alpha_ ); } else { std::cerr << "WARNING in LauDabbaRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "beta") { if ( beta_->fixed() ) { beta_->fixed( kFALSE ); this->addFloatingParameter( beta_ ); } else { std::cerr << "WARNING in LauDabbaRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else { std::cerr << "WARNING in LauDabbaRes::fixResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } LauParameter* LauDabbaRes::getResonanceParameter(const TString& name) { if (name == "b") { return b_; } else if (name == "alpha") { return alpha_; } else if (name == "beta") { return beta_; } else { std::cerr << "WARNING in LauDabbaRes::getResonanceParameter: Parameter name not reconised." << std::endl; return 0; } } void LauDabbaRes::setBValue(const Double_t b) { b_->value( b ); b_->genValue( b ); b_->initValue( b ); } void LauDabbaRes::setAlphaValue(const Double_t alpha) { alpha_->value( alpha ); alpha_->genValue( alpha ); alpha_->initValue( alpha ); } void LauDabbaRes::setBetaValue(const Double_t beta) { beta_->value( beta ); beta_->genValue( beta ); beta_->initValue( beta ); } diff --git a/src/LauDatabasePDG.cc b/src/LauDatabasePDG.cc index b925b59..ec03665 100644 --- a/src/LauDatabasePDG.cc +++ b/src/LauDatabasePDG.cc @@ -1,269 +1,268 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauDatabasePDG.cc \brief File containing implementation of LauDatabasePDG class. */ #include using std::cout; using std::cerr; using std::endl; #include "TDatabasePDG.h" #include "LauDatabasePDG.hh" #include "LauParticlePDG.hh" LauDatabasePDG* LauDatabasePDG::theInstance_ = 0; -ClassImp(LauDatabasePDG) // Constructor LauDatabasePDG::LauDatabasePDG() : theDatabase_( new TDatabasePDG() ), particles_(), debug_(kFALSE) { } // Destructor LauDatabasePDG::~LauDatabasePDG() { delete theDatabase_; theDatabase_ = 0; for (LauPDGList::iterator iter = particles_.begin(); iter != particles_.end(); ++iter) { delete iter->second; iter->second = 0; } } // Private static method to access the instance // Will create it and add the missing particles if it doesn't already exist LauDatabasePDG& LauDatabasePDG::get() { if (theInstance_ == 0) { theInstance_ = new LauDatabasePDG(); theInstance_->addMissingParticles(); } return *theInstance_; } // All static methods grab the instance and call the private non-static // methods - this ensures that the database exists and that the missing // particles are added to it. const LauParticlePDG* LauDatabasePDG::particle(Int_t theCode) { return LauDatabasePDG::get().createParticle( theCode ); } const LauParticlePDG* LauDatabasePDG::particle(const TString& theString) { return LauDatabasePDG::get().createParticle( theString ); } Int_t LauDatabasePDG::code(const TString& theString) { return LauDatabasePDG::get().pdgCode( theString ); } TString LauDatabasePDG::string(Int_t theCode) { return LauDatabasePDG::get().pdgName( theCode ); } // The following method adds particles to the ROOT database that are // missing from it's default setup. This should only be called once, // immediately after the creation of the instance. void LauDatabasePDG::addMissingParticles() { TParticlePDG* part(0); TParticlePDG* antipart(0); // format is: // name, title, mass, stable?, width, 3*Q, category, PDG code part = theDatabase_->AddParticle("deuteron", "deuteron", 1.8756134, kTRUE, 0.0, 3, "Nucleus", 1011); antipart = theDatabase_->AddAntiParticle("anti-deuteron", -1011); part->SetAntiParticle(antipart); antipart->SetAntiParticle(part); part = theDatabase_->AddParticle("tritium", "tritium", 2.80925, kTRUE, 0.0, 3, "Nucleus", 1021); antipart = theDatabase_->AddAntiParticle("anti-tritium", -1021); part->SetAntiParticle(antipart); antipart->SetAntiParticle(part); part = theDatabase_->AddParticle("He3", "He3", 2.80923, kTRUE, 0.0, 6, "Nucleus", 1012); antipart = theDatabase_->AddAntiParticle("anti-He3", -1012); part->SetAntiParticle(antipart); antipart->SetAntiParticle(part); part = theDatabase_->AddParticle("alpha", "alpha", 3.727417, kTRUE, 0.0, 3, "Nucleus", 1022); antipart = theDatabase_->AddAntiParticle("anti-alpha", -1022); part->SetAntiParticle(antipart); antipart->SetAntiParticle(part); part = theDatabase_->AddParticle("eta_c(2S)", "eta_c(2S)", 3.628, kTRUE, 0.0195, 0, "Meson", 20441); part = theDatabase_->AddParticle("psi(3770)", "psi(3770)", 3.7699, kTRUE, 0.0236, 0, "Meson", 40443); part = theDatabase_->AddParticle("rho(2S)0", "rho(2S)0", 1.46, kTRUE, 0.31, 0, "Meson", 30113); part = theDatabase_->AddParticle("rho(2S)+", "rho(2S)+", 1.46, kTRUE, 0.31, 3, "Meson", 30213); antipart = theDatabase_->AddAntiParticle("rho(2S)-", -30213); part->SetAntiParticle(antipart); antipart->SetAntiParticle(part); part = theDatabase_->AddParticle("rho(3S)0", "rho(3S)0", 1.46, kTRUE, 0.31, 0, "Meson", 40113); part = theDatabase_->AddParticle("rho(3S)+", "rho(3S)+", 1.46, kTRUE, 0.31, 3, "Meson", 40213); antipart = theDatabase_->AddAntiParticle("rho(3S)-", -40213); part->SetAntiParticle(antipart); antipart->SetAntiParticle(part); part = theDatabase_->AddParticle("Xsu", "Xsu", 1.6, kTRUE, 0.5, 3, "Meson", 30353); antipart = theDatabase_->AddAntiParticle("anti-Xsu", -30353); part->SetAntiParticle(antipart); antipart->SetAntiParticle(part); part = theDatabase_->AddParticle("Xu0", "Xu0", 1., kTRUE, 0., 0, "Special", 41); part = theDatabase_->AddParticle("Xu+", "Xu+", 1., kTRUE, 0., 3, "Special", 42); antipart = theDatabase_->AddAntiParticle("Xu-", -42); part->SetAntiParticle(antipart); antipart->SetAntiParticle(part); part = theDatabase_->AddParticle("Xsd", "Xsd", 1.6, kTRUE, 0.5, 0, "Meson", 30343); antipart = theDatabase_->AddAntiParticle("anti-Xsd", -30343); part->SetAntiParticle(antipart); antipart->SetAntiParticle(part); part = theDatabase_->AddParticle("K'*0", "K'*0", 1.414, kTRUE, 0.232, 0, "Meson", 100313); antipart = theDatabase_->AddAntiParticle("anti-K'*0", -100313); part->SetAntiParticle(antipart); antipart->SetAntiParticle(part); part = theDatabase_->AddParticle("K'*+", "K'*+", 1.414, kTRUE, 0.232, 3, "Meson", 100323); antipart = theDatabase_->AddAntiParticle("K'*-", -100323); part->SetAntiParticle(antipart); antipart->SetAntiParticle(part); part = theDatabase_->AddParticle("K''*0", "K''*0", 1.717, kTRUE, 0.322, 0, "Meson", 30313); antipart = theDatabase_->AddAntiParticle("anti-K''*0", -30313); part->SetAntiParticle(antipart); antipart->SetAntiParticle(part); part = theDatabase_->AddParticle("K''*+", "K''*+", 1.717, kTRUE, 0.322, 3, "Meson", 30323); antipart = theDatabase_->AddAntiParticle("K''*-", -30323); part->SetAntiParticle(antipart); antipart->SetAntiParticle(part); } // These next two methods are the ones that actually build-up our database. const LauParticlePDG* LauDatabasePDG::createParticle(Int_t theCode) { // if we've already created this one simply return it LauPDGList::iterator iter = particles_.find(theCode); if ( iter != particles_.end() ) { return iter->second; } // otherwise we'll have to make it... // first get the particle from the database TParticlePDG* theTParticle = theDatabase_->GetParticle( theCode ); if (theTParticle == 0) { cerr<<"ERROR in LauDatabasePDG::createParticle : Invalid PDG code: "< insertResult = particles_.insert( std::make_pair( theCode, theParticle ) ); if ( ! insertResult.second ) { cerr<<"ERROR in LauDatabasePDG::createParticle : Something went wrong inserting particle "<AntiParticle(); // check if we have a self-conjugate particle if ( theTAntiParticle == 0 || theTAntiParticle == theTParticle ) { // if so then set it to be it's own anti-particle and return theParticle->setAntiParticle( theParticle ); if ( debug_ ) { cout<<"INFO in LauDatabasePDG::createParticle : Created self-conjugate particle "<GetName()<code(); insertResult = particles_.insert( std::make_pair( conjCode, antiParticle ) ); if ( ! insertResult.second ) { cerr<<"ERROR in LauDatabasePDG::createParticle : Something went wrong inserting anti-particle "<setAntiParticle( antiParticle ); antiParticle->setAntiParticle( theParticle ); // and finally return the particle we've created if ( debug_ ) { cout<<"INFO in LauDatabasePDG::createParticle : Created particle "<GetName()<<" and its conjugate "<GetName()<pdgCode(theString); if ( theCode == 0 ) { cerr<<"ERROR in LauDatabasePDG::createParticle : Invalid particle string: "<createParticle(theCode); } // These last two methods have to be independent of our own database since // they are used by the methods that create the particles and so we'd end // up with an infinite loop. Int_t LauDatabasePDG::pdgCode(const TString& theString) { TParticlePDG* theParticle = theDatabase_->GetParticle(theString); if (theParticle == 0) { cerr<<"ERROR in LauDatabasePDG::pdgCode : Invalid particle string: "<PdgCode(); } TString LauDatabasePDG::pdgName(Int_t theCode) { TParticlePDG* theParticle = theDatabase_->GetParticle(theCode); if (theParticle == 0) { cerr<<"ERROR in LauDatabasePDG::pdgName : Invalid particle code: "<GetName(); } diff --git a/src/LauDaughters.cc b/src/LauDaughters.cc index 2914c78..08705c1 100644 --- a/src/LauDaughters.cc +++ b/src/LauDaughters.cc @@ -1,345 +1,344 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauDaughters.cc \brief File containing implementation of LauDaughters class. */ #include #include "TSystem.h" #include "LauDatabasePDG.hh" #include "LauDaughters.hh" #include "LauKinematics.hh" #include "LauParticlePDG.hh" -ClassImp(LauDaughters) LauDaughters::LauDaughters(Int_t codeParent, Int_t code1, Int_t code2, Int_t code3, Bool_t useSquareDP) : kinematics_(0), parent_(0), symmetricalDP_(kFALSE), fullySymmetricDP_(kFALSE), flavourConjugateDP_(kFALSE) { this->createParticleLists(); TString nameParent = LauDatabasePDG::string( codeParent ); TString name1 = LauDatabasePDG::string( code1 ); TString name2 = LauDatabasePDG::string( code2 ); TString name3 = LauDatabasePDG::string( code3 ); this->setParentType(nameParent); this->setDaugType(name1, name2, name3); // Create kinematics object kinematics_ = new LauKinematics(this->getMassDaug1(), this->getMassDaug2(), this->getMassDaug3(), this->getMassParent(), useSquareDP, symmetricalDP_, fullySymmetricDP_); } LauDaughters::LauDaughters(const TString& nameParent, const TString& name1, const TString& name2, const TString& name3, Bool_t useSquareDP) : kinematics_(0), parent_(0), symmetricalDP_(kFALSE), fullySymmetricDP_(kFALSE), flavourConjugateDP_(kFALSE) { this->createParticleLists(); this->setParentType(nameParent); this->setDaugType(name1, name2, name3); // Create kinematics object kinematics_ = new LauKinematics(this->getMassDaug1(), this->getMassDaug2(), this->getMassDaug3(), this->getMassParent(), useSquareDP, symmetricalDP_, fullySymmetricDP_); } LauDaughters::~LauDaughters() { delete kinematics_; kinematics_ = 0; } LauDaughters::LauDaughters( const LauDaughters& rhs ) : kinematics_(0), parent_(0), symmetricalDP_(kFALSE), fullySymmetricDP_(kFALSE), flavourConjugateDP_(kFALSE) { this->createParticleLists(); this->setParentType( rhs.getNameParent() ); this->setDaugType( rhs.getNameDaug1() , rhs.getNameDaug2() , rhs.getNameDaug3() ); // Create kinematics object kinematics_ = new LauKinematics(this->getMassDaug1(), this->getMassDaug2(), this->getMassDaug3(), this->getMassParent(), rhs.squareDP(), rhs.gotSymmetricalDP(), rhs.gotFullySymmetricDP()); } void LauDaughters::createParticleLists() { // Create list of allowed daughters allowedDaughters_.clear(); allowedDaughters_.push_back(LauDatabasePDG::particle("pi+")); allowedDaughters_.push_back(LauDatabasePDG::particle("pi-")); allowedDaughters_.push_back(LauDatabasePDG::particle("pi0")); allowedDaughters_.push_back(LauDatabasePDG::particle("K+")); allowedDaughters_.push_back(LauDatabasePDG::particle("K-")); allowedDaughters_.push_back(LauDatabasePDG::particle("K_S0")); allowedDaughters_.push_back(LauDatabasePDG::particle("eta")); allowedDaughters_.push_back(LauDatabasePDG::particle("eta'")); allowedDaughters_.push_back(LauDatabasePDG::particle("D+")); allowedDaughters_.push_back(LauDatabasePDG::particle("D-")); allowedDaughters_.push_back(LauDatabasePDG::particle("D0")); allowedDaughters_.push_back(LauDatabasePDG::particle("D0_bar")); allowedDaughters_.push_back(LauDatabasePDG::particle("D_s+")); allowedDaughters_.push_back(LauDatabasePDG::particle("D_s-")); // Create list of allowed parents allowedParents_.clear(); allowedParents_.push_back(LauDatabasePDG::particle("B+")); allowedParents_.push_back(LauDatabasePDG::particle("B-")); allowedParents_.push_back(LauDatabasePDG::particle("B0")); allowedParents_.push_back(LauDatabasePDG::particle("B0_bar")); allowedParents_.push_back(LauDatabasePDG::particle("B_s0")); allowedParents_.push_back(LauDatabasePDG::particle("B_s0_bar")); allowedParents_.push_back(LauDatabasePDG::particle("D+")); allowedParents_.push_back(LauDatabasePDG::particle("D-")); allowedParents_.push_back(LauDatabasePDG::particle("D0")); allowedParents_.push_back(LauDatabasePDG::particle("D0_bar")); allowedParents_.push_back(LauDatabasePDG::particle("D_s+")); allowedParents_.push_back(LauDatabasePDG::particle("D_s-")); } void LauDaughters::setParentType(const TString& nameParent) { parent_ = 0; const Int_t codeParent = LauDatabasePDG::code( nameParent ); for ( std::vector::const_iterator iter = allowedParents_.begin(); iter != allowedParents_.end(); ++iter ) { const Int_t code = (*iter)->code(); if ( codeParent == code ) { parent_ = (*iter); std::cout<<"INFO in LauDaughters::setParentType : Setting parent to be "<string()<<" == "<code()<Exit(EXIT_FAILURE); } } void LauDaughters::setDaugType(const TString& name1, const TString& name2, const TString& name3) { const TString names[3] = { name1, name2, name3 }; const Int_t codes[3] = { LauDatabasePDG::code( name1 ), LauDatabasePDG::code( name2 ), LauDatabasePDG::code( name3 ) }; daughters_.clear(); daughters_.resize(3); for ( int i(0); i<3; ++i ) { for ( std::vector::const_iterator iter = allowedDaughters_.begin(); iter != allowedDaughters_.end(); ++iter ) { Int_t code = (*iter)->code(); if ( codes[i] == code ) { daughters_[i] = (*iter); std::cout<<"INFO in LauDaughters::setDaugType : Setting daughter "<string()<<" == "<code()<Exit(EXIT_FAILURE); } } // Initialise the various data members concerning particle masses this->sanityCheck(); // Check whether we have a symmetrical Dalitz plot this->testDPSymmetry(); } void LauDaughters::testDPSymmetry() { // Check to see if we have a symmetrical or flavour-conjugate DP. symmetricalDP_ = kFALSE; fullySymmetricDP_ = kFALSE; flavourConjugateDP_ = kFALSE; if ( daughters_[0]->code() == daughters_[1]->code() && daughters_[0]->code() == daughters_[2]->code() ) { std::cout<<"INFO in LauDaughters::testDPSymmetry : We have a fully symmetric DP. "<code() == daughters_[1]->code() ) { std::cout<<"INFO in LauDaughters::testDPSymmetry : We have a symmetrical DP. "<code() == daughters_[2]->code() ) { std::cerr<<"ERROR in LauDaughters::testDPSymmetry : daughter 1 and daughter 3 are both "<string()<<" but DP can only fold on daughters 1 and 2."<Exit(EXIT_FAILURE); } else if ( daughters_[1]->code() == daughters_[2]->code() ) { std::cerr<<"ERROR in LauDaughters::testDPSymmetry : daughter 2 and daughter 3 are both "<string()<<" but DP can only fold on daughters 1 and 2."<Exit(EXIT_FAILURE); } else if ( daughters_[0]->type() == daughters_[1]->type() && daughters_[2]->charge() == 0 ) { std::cout<<"INFO in LauDaughters::testDPSymmetry : We have a flavour-conjugate DP. "<type() == daughters_[2]->type() && daughters_[1]->charge() == 0 ) { std::cerr<<"WARNING in LauDaughters::testDPSymmetry : it looks like we have a flavour-conjugate DP but the "<string()<<" and "<string()<<" are not positioned as daughters 1 and 2." << std::endl; } else if ( daughters_[1]->type() == daughters_[2]->type() && daughters_[0]->charge() == 0 ) { std::cerr<<"WARNING in LauDaughters::testDPSymmetry : it looks like we have a flavour-conjugate DP but the "<string()<<" and "<string()<<" are not positioned as daughters 1 and 2." << std::endl; } } void LauDaughters::sanityCheck() { // Check masses and charges of daughters Int_t totCharge(0); Double_t totMass(0.0); for ( std::vector::const_iterator iter = daughters_.begin(); iter != daughters_.end(); ++iter ) { totCharge += (*iter)->charge(); totMass += (*iter)->mass(); } if (totCharge != parent_->charge()) { std::cerr<<"ERROR in LauDaughters::sanityCheck : Total charge of daughters ("<charge()<<")."<Exit(EXIT_FAILURE); } if (totMass > parent_->mass()) { std::cerr<<"ERROR in LauDaughters::sanityCheck : Total mass of daughters ("<mass()<<")."<Exit(EXIT_FAILURE); } } Double_t LauDaughters::getMassDaug1() const { return daughters_[0]->mass(); } Double_t LauDaughters::getMassDaug2() const { return daughters_[1]->mass(); } Double_t LauDaughters::getMassDaug3() const { return daughters_[2]->mass(); } Double_t LauDaughters::getMassParent() const { return parent_->mass(); } TString LauDaughters::getNameDaug1() const { return daughters_[0]->string(); } TString LauDaughters::getNameDaug2() const { return daughters_[1]->string(); } TString LauDaughters::getNameDaug3() const { return daughters_[2]->string(); } TString LauDaughters::getNameParent() const { return parent_->string(); } TString LauDaughters::getSanitisedNameDaug1() const { return daughters_[0]->stringAlphaNum(); } TString LauDaughters::getSanitisedNameDaug2() const { return daughters_[1]->stringAlphaNum(); } TString LauDaughters::getSanitisedNameDaug3() const { return daughters_[2]->stringAlphaNum(); } TString LauDaughters::getSanitisedNameParent() const { return parent_->stringAlphaNum(); } Int_t LauDaughters::getTypeDaug1() const { return daughters_[0]->code(); } Int_t LauDaughters::getTypeDaug2() const { return daughters_[1]->code(); } Int_t LauDaughters::getTypeDaug3() const { return daughters_[2]->code(); } Int_t LauDaughters::getTypeParent() const { return parent_->code(); } Int_t LauDaughters::getChargeDaug1() const { return daughters_[0]->charge(); } Int_t LauDaughters::getChargeDaug2() const { return daughters_[1]->charge(); } Int_t LauDaughters::getChargeDaug3() const { return daughters_[2]->charge(); } Int_t LauDaughters::getChargeParent() const { return parent_->charge(); } Int_t LauDaughters::getCharge(Int_t resPairAmpInt) const { Int_t charge = this->getChargeParent(); if ( resPairAmpInt>0 && resPairAmpInt<4 ) { charge -= daughters_[resPairAmpInt-1]->charge(); } return charge; } diff --git a/src/LauEFKLLMRes.cc b/src/LauEFKLLMRes.cc index 1d9a7f8..443c310 100644 --- a/src/LauEFKLLMRes.cc +++ b/src/LauEFKLLMRes.cc @@ -1,175 +1,174 @@ /* Copyright 2015 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauEFKLLMRes.cc \brief File containing implementation of LauEFKLLMRes class. */ #include #include "Lau1DCubicSpline.hh" #include "LauKinematics.hh" #include "LauEFKLLMRes.hh" #include "LauResonanceInfo.hh" #include "LauTextFileParser.hh" -ClassImp(LauEFKLLMRes); Lau1DCubicSpline* LauEFKLLMRes::magSpline_ = 0; Lau1DCubicSpline* LauEFKLLMRes::phaseSpline_ = 0; LauEFKLLMRes::LauEFKLLMRes(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), massFactor_(0) { const Double_t massFactorVal = 0.; const TString& parNameBase = this->getSanitisedName(); TString massFactorName(parNameBase); massFactorName += "_massFactor"; massFactor_ = resInfo->getExtraParameter( massFactorName ); if ( massFactor_ == 0 ) { massFactor_ = new LauParameter( massFactorName, massFactorVal, -10.0, 10.0, kTRUE ); massFactor_->secondStage(kTRUE); resInfo->addExtraParameter( massFactor_ ); } } LauEFKLLMRes::~LauEFKLLMRes() { } void LauEFKLLMRes::initialise() { } void LauEFKLLMRes::setResonanceParameter(const TString& name, const Double_t value) { if(name=="massFactor") { this->setMassFactor(value); std::cout << "INFO in LauEFKLLMRes::setResonanceParameter: Mass factor set to " << value << std::endl; } else { std::cerr << "WARNING in LauEFKLLMRes::setResonanceParameter: Parameter name not reconised." << std::endl; } } void LauEFKLLMRes::floatResonanceParameter(const TString& name) { if(name=="massFactor") { if ( massFactor_->fixed() ) { massFactor_->fixed( kFALSE ); this->addFloatingParameter( massFactor_ ); } else { std::cerr << "WARNING in LauEFKLLMRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else { std::cerr << "WARNING in LauEFKLLMRes::floatResonanceParameter: Parameter name not reconised." << std::endl; } } LauParameter* LauEFKLLMRes::getResonanceParameter(const TString& name) { if(name=="massFactor") { return massFactor_; } else { std::cerr << "WARNING in LauEFKLLMRes::getResonanceParameter: Parameter name not reconised." << std::endl; return 0; } } const std::vector& LauEFKLLMRes::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixMassFactor() ) { this->addFloatingParameter( massFactor_ ); } return this->getParameters(); } LauComplex LauEFKLLMRes::resAmp(Double_t mass, Double_t /*spinTerm*/) { LauComplex amp(0.0, 0.0); if (magSpline_ == 0 || phaseSpline_ == 0) { std::cerr << "ERROR in LauEFKLLMRes::resAmp : One of the splines is null." << std::endl; return amp; } const Double_t massSq = mass*mass; const Double_t mag = magSpline_->evaluate(massSq); const Double_t phase = TMath::DegToRad()*phaseSpline_->evaluate(massSq); LauComplex ff(mag*TMath::Cos(phase), mag*TMath::Sin(phase)); amp = ff.scale(TMath::Power(mass,this->getMassFactor())); return amp; } void LauEFKLLMRes::setupFormFactor(const TString& inputFile) { LauTextFileParser readFile(inputFile); readFile.processFile(); std::vector mSqVals; std::vector magVals; std::vector phaseVals; std::vector line; line=readFile.getNextLine(); while(!line.empty()) { UInt_t length = line.size(); if(length!=3) { std::cerr << "ERROR in LauEFKLLMRes::setupFormFactor : Unexpected number of fields in text file, aborting reading of form-factor information." << std::endl; return; } mSqVals.push_back( atof(line[0].c_str())); magVals.push_back( atof(line[1].c_str())); phaseVals.push_back(atof(line[2].c_str())); line=readFile.getNextLine(); } // Destroy any splines we already had defined but issue a warning just in case if ( magSpline_ != 0 || phaseSpline_ != 0 ) { std::cerr << "WARNING in LauEFKLLMRes::setupFormFactor : Overwriting previous form-factor splines with newly read values." << std::endl; delete magSpline_; delete phaseSpline_; } magSpline_ = new Lau1DCubicSpline(mSqVals, magVals, Lau1DCubicSpline::AkimaSpline); phaseSpline_ = new Lau1DCubicSpline(mSqVals, phaseVals, Lau1DCubicSpline::AkimaSpline); } void LauEFKLLMRes::setMassFactor(const Double_t massFactor) { massFactor_->value( massFactor ); massFactor_->genValue( massFactor ); massFactor_->initValue( massFactor ); } diff --git a/src/LauEffModel.cc b/src/LauEffModel.cc index 8c1913f..f58bc93 100644 --- a/src/LauEffModel.cc +++ b/src/LauEffModel.cc @@ -1,323 +1,322 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauEffModel.cc \brief File containing implementation of LauEffModel class. */ #include #include #include "TSystem.h" #include "Lau2DHistDP.hh" #include "Lau2DSplineDP.hh" #include "LauDaughters.hh" #include "LauEffModel.hh" #include "LauKinematics.hh" #include "LauVetoes.hh" -ClassImp(LauEffModel) LauEffModel::LauEffModel(const LauDaughters* daughters, const LauVetoes* vetoes) : daughters_( daughters ), vetoes_( vetoes ), effHisto_( 0 ), fluctuateEffHisto_( kFALSE ), lowBinWarningIssued_( kFALSE ), highBinWarningIssued_( kFALSE ) { if ( daughters_ == 0 ) { std::cerr << "ERROR in LauEffModel Constructor : invalid pointer to daughters object supplied." << std::endl; gSystem->Exit(EXIT_FAILURE); } } LauEffModel::~LauEffModel() { std::vector::iterator it = effHisto_.begin(); std::vector::iterator end = effHisto_.end(); for( ; it!=end; ++it) { delete *it; *it=0; } effHisto_.clear(); } void LauEffModel::setEffHisto(const TH2* effHisto, Bool_t useInterpolation, Bool_t fluctuateBins, Double_t avEff, Double_t absError, Bool_t useUpperHalfOnly, Bool_t squareDP) { // Set the efficiency across the Dalitz plot using a predetermined 2D histogram // with x = m_13^2, y = m_23^2. Bool_t upperHalf( kFALSE ); if ( daughters_->gotSymmetricalDP() && useUpperHalfOnly == kTRUE) {upperHalf = kTRUE;} std::cout<<"INFO in LauEffModel::setEffHisto : Efficiency histogram has upperHalf = "<(upperHalf)<::iterator it = effHisto_.begin(); std::vector::iterator end = effHisto_.end(); for( ; it!=end; ++it) { delete *it; *it=0; } effHisto_.clear(); // Copy the histogram. effHisto_.push_back(new Lau2DHistDP(effHisto, daughters_, useInterpolation, fluctuateBins, avEff, absError, upperHalf, squareDP)); fluctuateEffHisto_ = fluctuateBins; if (avEff > 0.0 && absError > 0.0) { fluctuateEffHisto_ = kTRUE; } } void LauEffModel::setEffHisto(const TH2* effHisto, const TH2* errorHi, const TH2* errorLo, Bool_t useInterpolation, Bool_t fluctuateBins, Double_t avEff, Double_t absError, Bool_t useUpperHalfOnly, Bool_t squareDP) { // Set the efficiency across the Dalitz plot using a predetermined 2D histogram // with x = m_13^2, y = m_23^2. Bool_t upperHalf( kFALSE ); if ( daughters_->gotSymmetricalDP() && useUpperHalfOnly == kTRUE) {upperHalf = kTRUE;} std::cout<<"INFO in LauEffModel::setEffHisto : Efficiency histogram has upperHalf = "<(upperHalf)<::iterator it = effHisto_.begin(); std::vector::iterator end = effHisto_.end(); for( ; it!=end; ++it) { delete *it; *it=0; } effHisto_.clear(); // Copy the histogram. effHisto_.push_back(new Lau2DHistDP(effHisto, errorHi, errorLo, daughters_, useInterpolation, fluctuateBins, avEff, absError, upperHalf, squareDP)); fluctuateEffHisto_ = fluctuateBins; if (avEff > 0.0 && absError > 0.0) { fluctuateEffHisto_ = kTRUE; } } void LauEffModel::setEffSpline(const TH2* effHisto, Bool_t fluctuateBins, Double_t avEff, Double_t absError, Bool_t useUpperHalfOnly, Bool_t squareDP) { // Set the efficiency across the Dalitz plot using a predetermined 2D histogram // with x = m_13^2, y = m_23^2. Bool_t upperHalf( kFALSE ); if ( daughters_->gotSymmetricalDP() && useUpperHalfOnly == kTRUE) {upperHalf = kTRUE;} std::cout<<"INFO in LauEffModel::setEffSpline : Efficiency histogram has upperHalf = "<(upperHalf)<::iterator it = effHisto_.begin(); std::vector::iterator end = effHisto_.end(); for( ; it!=end; ++it) { delete *it; *it=0; } effHisto_.clear(); // Copy the histogram. effHisto_.push_back(new Lau2DSplineDP(effHisto, daughters_, fluctuateBins, avEff, absError, upperHalf, squareDP)); fluctuateEffHisto_ = fluctuateBins; if (avEff > 0.0 && absError > 0.0) { fluctuateEffHisto_ = kTRUE; } } void LauEffModel::setEffSpline(const TH2* effHisto, const TH2* errorHi, const TH2* errorLo, Bool_t fluctuateBins, Double_t avEff, Double_t absError, Bool_t useUpperHalfOnly, Bool_t squareDP) { // Set the efficiency across the Dalitz plot using a predetermined 2D histogram // with x = m_13^2, y = m_23^2. Bool_t upperHalf( kFALSE ); if ( daughters_->gotSymmetricalDP() && useUpperHalfOnly == kTRUE) {upperHalf = kTRUE;} std::cout<<"INFO in LauEffModel::setEffSpline : Efficiency histogram has upperHalf = "<(upperHalf)<::iterator it = effHisto_.begin(); std::vector::iterator end = effHisto_.end(); for( ; it!=end; ++it) { delete *it; *it=0; } effHisto_.clear(); // Copy the histogram. effHisto_.push_back(new Lau2DSplineDP(effHisto, errorHi, errorLo, daughters_, fluctuateBins, avEff, absError, upperHalf, squareDP)); fluctuateEffHisto_ = fluctuateBins; if (avEff > 0.0 && absError > 0.0) { fluctuateEffHisto_ = kTRUE; } } void LauEffModel::addEffHisto(const TH2* effHisto, Bool_t useInterpolation, Double_t avEff, Double_t absError, Bool_t useUpperHalfOnly, Bool_t squareDP) { // Set the efficiency across the Dalitz plot using a predetermined 2D histogram // with x = m_13^2, y = m_23^2. Bool_t upperHalf( kFALSE ); if ( daughters_->gotSymmetricalDP() && useUpperHalfOnly == kTRUE) {upperHalf = kTRUE;} std::cout<<"INFO in LauEffModel::addEffHisto : Efficiency histogram has upperHalf = "<(upperHalf)<gotSymmetricalDP() && useUpperHalfOnly == kTRUE) {upperHalf = kTRUE;} std::cout<<"INFO in LauEffModel::addEffHisto : Efficiency histogram has upperHalf = "<(upperHalf)<gotSymmetricalDP() && useUpperHalfOnly == kTRUE) {upperHalf = kTRUE;} std::cout<<"INFO in LauEffModel::addEffSpline : Efficiency histogram has upperHalf = "<(upperHalf)<gotSymmetricalDP() && useUpperHalfOnly == kTRUE) {upperHalf = kTRUE;} std::cout<<"INFO in LauEffModel::addEffSpline : Efficiency histogram has upperHalf = "<(upperHalf)<::const_iterator it = effHisto_.begin(); const std::vector::const_iterator end = effHisto_.end(); for( ; it!=end; ++it) { if ( (*it)->usingSquareDP() ) { xVal = kinematics->getmPrime(); yVal = kinematics->getThetaPrime(); } else { xVal = kinematics->getm13Sq(); yVal = kinematics->getm23Sq(); } eff *= (*it)->interpolateXY(xVal, yVal); } return eff; } Double_t LauEffModel::calcEfficiency( const LauKinematics* kinematics ) const { // Routine to calculate the efficiency for the given event/point in // the Dalitz plot. This routine uses the 2D histogram set by the // setEffHisto() function. Double_t eff(1.0); // Check for vetoes Bool_t vetoOK(kTRUE); if ( vetoes_ != 0 ) { vetoOK = vetoes_->passVeto(kinematics); } if (vetoOK == kFALSE) { // We failed the veto. eff = 0.0; } else { // We are using a 2D histogram representation of the efficiency across the Dalitz plot. eff = this->getEffHistValue( kinematics ); } // Check that the efficiency is in the allowed range (0-1) // If we're using a spline then out-of-range efficiencies can be caused by adjacent bins that all contain a value of either zero or one. // The spline requires the efficiency, its first derivatives and the mixed second derivative to be continuous and to match the input histogram // at the bin centres. Derivatives are calculated using a finite difference approximation taking the difference between the neighbouring bins. // If two bins are zero but the third is not then the second bin will have a positive first derivative causing the spline to dip below zero // between the two zero bins to remain smooth. The analogous case with adjacent maximised bins will cause peaks above one. Such dips are // unavoidable but are correctly removed here. if ( eff < 0.0 ) { if(!lowBinWarningIssued_) { std::cerr << "WARNING in LauEffModel::calcEfficiency : Efficiency " << eff << " is less than 0 - setting to 0. You may want to check your histogram!" << std::endl << " : If you are using a spline then this could be caused by adjacent empty bins. Further warnings will be suppressed." << std::endl; lowBinWarningIssued_=kTRUE; } eff = 0.0; } else if ( eff > 1.0 ) { if(!highBinWarningIssued_) { std::cerr << "WARNING in LauEffModel::calcEfficiency : Efficiency " << eff << " is greater than 1 - setting to 1. You may want to check your histogram!" << std::endl << " : If you are using a spline then this could be caused by adjacent full bins. Further warnings will be suppressed." << std::endl; highBinWarningIssued_=kTRUE; } eff = 1.0; } return eff; } Bool_t LauEffModel::passVeto( const LauKinematics* kinematics ) const { Bool_t pass = kTRUE; if ( vetoes_ != 0 ) { pass = vetoes_->passVeto( kinematics ); } return pass; } diff --git a/src/LauEmbeddedData.cc b/src/LauEmbeddedData.cc index 3054b7f..56659a7 100644 --- a/src/LauEmbeddedData.cc +++ b/src/LauEmbeddedData.cc @@ -1,216 +1,215 @@ /* Copyright 2007 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauEmbeddedData.cc \brief File containing implementation of LauEmbeddedData class. */ #include #include using std::cerr; using std::endl; #include "TRandom.h" #include "LauIsobarDynamics.hh" #include "LauEmbeddedData.hh" #include "LauKinematics.hh" #include "LauRandom.hh" -ClassImp(LauEmbeddedData) LauEmbeddedData::LauEmbeddedData(const TString& fileName, const TString& treeName, Bool_t allowReuseOfEvents) : theDataTree_(new LauFitDataTree(fileName,treeName)), reuseEvents_(allowReuseOfEvents) { } LauEmbeddedData::~LauEmbeddedData() { delete theDataTree_; } Bool_t LauEmbeddedData::findBranches() { if ( theDataTree_ == 0 ) { cerr<<"ERROR in LauEmbeddedData::findBranches : Invalid pointer to the data tree object."<findBranches(); if ( ! branchesReadOK ) { cerr<<"ERROR in LauEmbeddedData::findBranches : Problem finding branches."<readAllData(); return kTRUE; } Bool_t LauEmbeddedData::getReweightedEvent(LauIsobarDynamics* dynamics) { if (!theDataTree_) { cerr<<"ERROR in LauEmbeddedData::getReweightedEvent : Invalid pointer to the data tree object."<nEvents(); UInt_t iEvt(0); // First select a random event within the embedded data sample if (this->reuseEvents()) { iEvt = LauRandom::randomFun()->Integer(numEvents); } else { if (this->nUsedEvents() == numEvents) { cerr<<"ERROR in LauEmbeddedData::getReweightedEvent : Have already used all events in the tree."<Integer(numEvents); ok = usedEvents_.insert(iEvt).second; } } // Retrieve the data for the selected event theData_ = theDataTree_->getData(iEvt); LauKinematics* kinematics = dynamics->getKinematics(); if (kinematics != 0) { // Get the true m13Sq, m23Sq variables. Double_t m13Sq_MC = this->getValue("m13Sq_MC"); Double_t m23Sq_MC = this->getValue("m23Sq_MC"); if (kinematics->withinDPLimits(m13Sq_MC,m23Sq_MC)) { // Update the kinematics with the true m13Sq, m23Sq variables kinematics->updateKinematics(m13Sq_MC, m23Sq_MC); // Use this event or not, according to whether the amplitude model selects it. // The LauIsobarDynamics uses an accept/reject method based on the // ratio of the current to maximum ASq value. Other models may use alternative methods, // but they must provide a yes/no answer if the event is accepted. Bool_t gotReweightedEvent = dynamics->gotReweightedEvent(); if (gotReweightedEvent == kTRUE) { // Event is accepted. // Update the kinematics to use the reco variables. Double_t m13Sq = this->getValue("m13Sq"); Double_t m23Sq = this->getValue("m23Sq"); kinematics->updateKinematics(m13Sq, m23Sq); if (LauIsobarDynamics::GenOK != dynamics->checkToyMC(kFALSE,kFALSE)) { return kFALSE; } } else { // Recursively run this function until we get an accepted event return this->getReweightedEvent(dynamics); } } else { cerr<<"WARNING in LauEmbeddedData::getReweightedEvent : Skipping event "<getReweightedEvent(dynamics); } } return kTRUE; } void LauEmbeddedData::getEmbeddedEvent(LauKinematics* kinematics) { if (!theDataTree_) { cerr<<"ERROR in LauEmbeddedData::getEmbeddedEvent : Invalid pointer to the data tree object."<nEvents(); UInt_t iEvt(0); if (this->reuseEvents()) { iEvt = LauRandom::randomFun()->Integer(numEvents); } else { if (this->nUsedEvents() == numEvents) { cerr<<"ERROR in LauEmbeddedData::getEmbeddedEvent : Have already used all events in the tree."<Integer(numEvents); ok = usedEvents_.insert(iEvt).second; } } theData_ = theDataTree_->getData(iEvt); if (kinematics!=0) { Double_t m13Sq = this->getValue("m13Sq"); Double_t m23Sq = this->getValue("m23Sq"); if (kinematics->withinDPLimits(m13Sq,m23Sq)) { kinematics->updateKinematics(m13Sq,m23Sq); } else { cerr<<"WARNING in LauEmbeddedData::getEmbeddedEvent : Skipping event that isn't within the DP boundary."<getEmbeddedEvent(kinematics); } } } Double_t LauEmbeddedData::getValue(const TString& name) const { LauFitData::const_iterator iter = theData_.find(name); if (iter == theData_.end()) { cerr<<"ERROR in LauEmbeddedData::getValue : Could not find branch \""<second; } } LauFitData LauEmbeddedData::getValues(const std::vector& names) const { LauFitData retVal; for ( std::vector::const_iterator iter = names.begin(); iter != names.end(); ++iter ) { const TString& name = (*iter); LauFitData::const_iterator data_iter = theData_.find(name); if ( data_iter == theData_.end() ) { cerr<<"WARNING in LauEmbeddedData::getValues : Could not find branch \""< #include using std::cout; using std::cerr; using std::endl; using std::vector; #include "TMath.h" #include "TSystem.h" #include "LauConstants.hh" #include "LauExponentialPdf.hh" -ClassImp(LauExponentialPdf) LauExponentialPdf::LauExponentialPdf(const TString& theVarName, const vector& params, Double_t minAbscissa, Double_t maxAbscissa) : LauAbsPdf(theVarName, params, minAbscissa, maxAbscissa), slope_(0) { // Constructor for the Exponential PDF. // // The parameter in param is the slope of the exponential ie exp(slope*x). // The last two arguments specify the range in which the PDF is defined, and the PDF // will be normalised w.r.t. these limits. slope_ = this->findParameter("slope"); if ((this->nParameters() != 1) || (slope_ == 0)) { cerr<<"ERROR in LauExponentialPdf constructor: LauExponentialPdf requires 1 parameter: \"slope\"."<Exit(EXIT_FAILURE); } // Cache the normalisation factor this->calcNorm(); } LauExponentialPdf::~LauExponentialPdf() { // Destructor } void LauExponentialPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Get our abscissa Double_t abscissa = abscissas[0]; // Get the up to date parameter values Double_t slope = slope_->unblindValue(); // Calculate the value of the Exponential for the given value of the abscissa. Double_t exponent(0.0); if(slope != 0){ exponent = slope*abscissa; } Double_t value = TMath::Exp(exponent); this->setUnNormPDFVal(value); // if the parameters are floating then we // need to recalculate the normalisation if (!this->cachePDF() && !this->withinNormCalc() && !this->withinGeneration()) { this->calcNorm(); } } void LauExponentialPdf::calcNorm() { // Get the up to date parameter values Double_t slope = slope_->unblindValue(); // Calculate the normalisation of the exponential and cache it. Double_t norm(0.0); if(slope != 0){ norm = (1/slope)*(TMath::Exp(slope*this->getMaxAbscissa()) - TMath::Exp(slope*this->getMinAbscissa())) ; } this->setNorm(norm); } void LauExponentialPdf::calcPDFHeight(const LauKinematics* /*kinematics*/) { if (this->heightUpToDate()) { return; } // Get the up to date parameter values Double_t slope = slope_->unblindValue(); LauAbscissas maxPoint(1); maxPoint[0] = 0; // Calculate the PDF height for the Exponential function. if (slope > 0) { maxPoint[0] = this->getMaxAbscissa(); } else if (slope < 0) { maxPoint[0] = this->getMinAbscissa(); } this->calcLikelihoodInfo(maxPoint); Double_t height = this->getUnNormLikelihood(); this->setMaxHeight(height); } diff --git a/src/LauFitDataTree.cc b/src/LauFitDataTree.cc index 02abec6..efc01ae 100644 --- a/src/LauFitDataTree.cc +++ b/src/LauFitDataTree.cc @@ -1,388 +1,387 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauFitDataTree.cc \brief File containing implementation of LauFitDataTree class. */ #include #include #include #include "TFile.h" #include "TLeaf.h" #include "TString.h" #include "TSystem.h" #include "LauFitDataTree.hh" -ClassImp(LauFitDataTree) LauFitDataTree::LauFitDataTree(const TString& rootFileName, const TString& rootTreeName) : rootFileName_(rootFileName), rootTreeName_(rootTreeName), rootFile_(0), rootTree_(0), eventList_(0) { if (rootFileName_ != "" && rootTreeName_ != "") { this->openFileAndTree(); } } LauFitDataTree::~LauFitDataTree() { if (rootFile_ && rootFile_->IsOpen()) { delete rootTree_; rootTree_ = 0; delete eventList_; eventList_ = 0; } delete rootFile_; rootFile_ = 0; } void LauFitDataTree::openFileAndTree() { // first check whether we've already opened up the file or not if (!rootFile_) { // if not, first check the filename and if all ok create the file if (rootFileName_ == "") { std::cerr << "ERROR in LauFitDataTree::openFileAndTree : Bad filename supplied, not creating file or tree." << std::endl; return; } rootFile_ = TFile::Open(rootFileName_, "read"); if (!rootFile_ || rootFile_->IsZombie() || !rootFile_->IsOpen()) { std::cerr << "ERROR in LauFitDataTree::openFileAndTree : Problem opening file \"" << rootFileName_ << "\" for reading." << std::endl; return; } } // check whether we've already created the tree if (!rootTree_) { // if not change to the file's directory and grab the tree rootFile_->cd(); rootTree_ = dynamic_cast(rootFile_->Get(rootTreeName_)); if (!rootTree_) { std::cerr << "ERROR in LauFitDataTree::openFileAndTree : Problem reading tree \"" << rootTreeName_ << "\" from file." << std::endl; return; } rootTree_->SetDirectory(rootFile_); } } Bool_t LauFitDataTree::findBranches() { if (!rootTree_) { std::cerr << "ERROR in LauFitDataTree::findBranches : Invalid pointer to data tree." << std::endl; return kFALSE; } // this method should only be called once if ( ! leafNames_.empty() ) { std::cerr << "ERROR in LauFitDataTree::findBranches : Branches already found, not running again." << std::endl; return kFALSE; } leafNames_.clear(); eventData_.clear(); eventDataOut_.clear(); leaves_.clear(); treeEvents_.clear(); fakeEvents_.clear(); const UInt_t numBranches(this->nBranches()); eventData_.reserve( numBranches ); TObjArray* pLeaves = rootTree_->GetListOfLeaves(); if (!pLeaves) { std::cerr << "ERROR in LauFitDataTree::findBranches : Problem retrieving leaves from the tree." << std::endl; return kFALSE; } TObjArray& leaves = *pLeaves; const UInt_t numLeaves = static_cast( leaves.GetEntries() ); if ( numBranches != numLeaves ) { std::cerr << "ERROR in LauFitDataTree::findBranches : List of leaves is not the same size as the number of branches - this is strange!" << std::endl; std::cerr << " : There are " << numLeaves << " leaves and " << numBranches << " branches" << std::endl; return kFALSE; } for (UInt_t iLeaf = 0; iLeaf < numBranches; ++iLeaf) { TLeaf * leaf = dynamic_cast(leaves[iLeaf]); // we can't deal with arrays Int_t size = leaf->GetNdata(); if (size != 1) { std::cerr << "ERROR in LauFitDataTree::findBranches : Tree has array branches, can't deal with those." << std::endl; return kFALSE; } // find the name and type of the leaf TString name = leaf->GetName(); // initialise an entry in the maps to hold the value leafNames_[ name ] = iLeaf; leaves_.push_back( leaf ); eventData_.push_back( 0.0 ); eventDataOut_[ name ] = 0.0; } const UInt_t numEvents(this->nTotalEvents()); std::cout << "INFO in LauFitDataTree::findBranches : Finished finding data tree branches." << std::endl; std::cout << " : Tree contains " << numBranches << " branches and a total of " << numEvents << " events." << std::endl; return kTRUE; } void LauFitDataTree::readExperimentData(UInt_t iExpt) { // Check that we have a valid tree to read from if (!rootTree_) { std::cerr << "ERROR in LauFitDataTree::readExperimentData : Invalid pointer to data tree." << std::endl; return; } rootFile_->cd(); // If the event list doesn't exist, create it if (!eventList_) { eventList_ = new TEventList("elist","elist"); eventList_->SetDirectory(rootFile_); } // Reset the event list so it contains no entries eventList_->Reset(); // Check that the tree contains the iExpt branch if (!this->haveBranch("iExpt")) { // If it doesn't, check which experiment we've been asked to read if ( iExpt == 0 ) { // If it's experiment 0, assume that we should read all events in the tree (but print a warning since this is an assumption) std::cerr << "WARNING in LauFitDataTree::readExperimentData : Tree does not contain \"iExpt\" branch, will read all data in the tree" << std::endl; this->readAllData(); return; } else { // Otherwise we can't really do anything, so print an error and return std::cerr << "ERROR in LauFitDataTree::readExperimentData : Tree does not contain \"iExpt\" branch and experiment requested is > 0, will not read anything" << std::endl; return; } } // Fill the event list with the entries for the requested experiment TString listName(eventList_->GetName()); listName.Prepend(">>"); TString selection("iExpt=="); selection += iExpt; std::cout << "INFO in LauFitDataTree::readExperimentData : Setting tree to experiment number " << iExpt << "." << std::endl; rootTree_->Draw(listName,selection); std::cout << " : Found " << this->nEvents() << " events." << std::endl; // Load the data this->loadData(); } UInt_t LauFitDataTree::nBranches() const { if ( rootTree_ ) { return static_cast(rootTree_->GetNbranches()); } else if ( ! fakeEvents_.empty() ) { std::vector::const_iterator fakeIter = fakeEvents_.begin(); return (*fakeIter).size(); } else { return 0; } } void LauFitDataTree::appendFakePoints( const std::vector& xCoords, const std::vector& yCoords) { if ( xCoords.size() != yCoords.size() ) { std::cerr << "ERROR in LauFitDataTree::appendFakePoints : The co-ordinate vectors are not the same size!" << std::endl; gSystem->Exit(EXIT_FAILURE); } // clear the list of fake events and reserve enough space fakeEvents_.clear(); fakeEvents_.reserve(xCoords.size()); // loop over the event data zeroing everything for (LauEventData::iterator iter = eventData_.begin(); iter != eventData_.end(); ++iter) { *iter = 0.0; } // find the vector indices for the DP co-ordinates LauNameIndexMap::const_iterator iter = leafNames_.find( "m13Sq" ); if ( iter == leafNames_.end() ) { std::cerr << "ERROR in LauFitDataTree::appendFakePoints : Can't find entry \"m13Sq\" in event data map." << std::endl; gSystem->Exit(EXIT_FAILURE); } UInt_t m13SqIdx = iter->second; iter = leafNames_.find( "m23Sq" ); if ( iter == leafNames_.end() ) { std::cerr << "ERROR in LauFitDataTree::appendFakePoints : Can't find entry \"m23Sq\" in event data map." << std::endl; gSystem->Exit(EXIT_FAILURE); } UInt_t m23SqIdx = iter->second; // TODO - is this really needed? Comment out for now. /* // and a fake tagCat which we don't care about, but the program // needs a number here for comptibility with conventional events. iter = leafNames_.find( "tagCat" ); if ( iter == leafNames_.end() ) { std::cerr << "ERROR in LauFitDataTree::appendFakePoints : Can't find entry \"tagCat\" in event data map." << std::endl; gSystem->Exit(EXIT_FAILURE); } UInt_t tagCatIdx = iter->second; */ for (UInt_t iEvt = 0; iEvt < xCoords.size() ; ++iEvt) { // set the values eventData_[ m13SqIdx ] = xCoords[iEvt]; eventData_[ m23SqIdx ] = yCoords[iEvt]; //eventData_[ tagCatIdx ] = 0.0; // append to the list of fake events fakeEvents_.push_back(eventData_); } } Bool_t LauFitDataTree::haveBranch(const TString& name) const { LauNameIndexMap::const_iterator iter = leafNames_.find( name ); return (iter != leafNames_.end()); } void LauFitDataTree::disableAllBranches() const { rootTree_->SetBranchStatus("*", 0); } void LauFitDataTree::enableAllBranches() const { rootTree_->SetBranchStatus("*", 1); } void LauFitDataTree::enableBranch(const TString& name) const { if (this->haveBranch(name)) {rootTree_->SetBranchStatus(name, 1);} } void LauFitDataTree::disableBranch(const TString& name) const { if (this->haveBranch(name)) {rootTree_->SetBranchStatus(name, 0);} } void LauFitDataTree::loadData() { // Clear any data from previous expts treeEvents_.clear(); // Reserve enough space in the vector Long64_t nEvts = this->nEvents(); treeEvents_.reserve( nEvts ); const UInt_t nLeaves = this->nBranches(); // Loop through the tree and store the data for ( Long64_t iEvt(0); iEvt < nEvts; ++iEvt ) { // Find which entry from the full tree contains the requested event Long64_t iEntry = eventList_ ? eventList_->GetEntry(iEvt) : iEvt; if (iEntry<0) { // this shouldn't happen, but just in case... std::cerr << "ERROR in LauFitDataTree::loadData : Requested event not found." << std::endl; gSystem->Exit(EXIT_FAILURE); } // Then retrieve that entry from the tree rootTree_->GetEntry(iEntry); // Copy the leaf values into eventData_ for ( UInt_t iLeaf(0); iLeaf < nLeaves; ++iLeaf ) { const TLeaf * leaf = leaves_[ iLeaf ]; Double_t value = leaf->GetValue(); if ( std::isnan( value ) || std::isinf( value ) ) { std::cerr << "ERROR in LauFitDataTree::loadData : Event " << iEvt << " has infinite or NaN entry for variable " << leaf->GetName() << std::endl; gSystem->Exit(EXIT_FAILURE); } eventData_[ iLeaf ] = value; } // Store the event in the vector treeEvents_.push_back( eventData_ ); } } void LauFitDataTree::readAllData() { delete eventList_; eventList_ = 0; this->loadData(); } const LauFitData& LauFitDataTree::getData(UInt_t iEvt) const { // For a given event, within the current experiment, // retrieve the input fit variables const UInt_t numTreeEvents = this->nEvents(); const UInt_t numFakeEvents = this->nFakeEvents(); // Does the requested event come from the tree or from the fake events list? if ( iEvt < numTreeEvents ) { if ( iEvt > treeEvents_.size() ) { // this shouldn't happen, but just in case... std::cerr << "ERROR in LauFitDataTree::getData : Requested event, " << iEvt << ", not found." << std::endl; gSystem->Exit(EXIT_FAILURE); } // Retrieve that event from the vector eventData_ = treeEvents_[iEvt]; } else if ( iEvt < (numTreeEvents + numFakeEvents) ) { // Find the entry from the fake events list contains the requested event UInt_t iEntry = iEvt - numTreeEvents; // Copy the entry into eventData_ eventData_ = fakeEvents_[iEntry]; } else { std::cerr << "ERROR in LauFitDataTree::getData : Requested event " << iEvt << " not found for " << rootTreeName_ << std::endl; gSystem->Exit(EXIT_FAILURE); } for ( LauNameIndexMap::const_iterator iter = leafNames_.begin(); iter != leafNames_.end(); ++iter ) { const TString& name = iter->first; UInt_t index = iter->second; LauFitData::iterator outIter = eventDataOut_.find( name ); if ( outIter == eventDataOut_.end() ) { std::cerr << "ERROR in LauFitDataTree::getData : Something very strange happening." << std::endl; gSystem->Exit(EXIT_FAILURE); } outIter->second = eventData_[ index ]; } return eventDataOut_; } diff --git a/src/LauFitNtuple.cc b/src/LauFitNtuple.cc index 3b8fc6f..e4caa8e 100644 --- a/src/LauFitNtuple.cc +++ b/src/LauFitNtuple.cc @@ -1,342 +1,341 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauFitNtuple.cc \brief File containing implementation of LauFitNtuple class. */ #include #include "TFile.h" #include "TMath.h" #include "TMatrixD.h" #include "TSystem.h" #include "TTree.h" #include "LauAbsFitter.hh" #include "LauFitNtuple.hh" #include "LauFitter.hh" #include "LauParameter.hh" #include "LauParamFixed.hh" -ClassImp(LauFitNtuple) LauFitNtuple::LauFitNtuple(const TString& fileName, Bool_t storeAsymErrors) : rootFileName_(fileName), rootFile_(0), fitResults_(0), definedFitTree_(kFALSE), storeAsymErrors_(storeAsymErrors), fitStatus_({-1,0.0,0.0}), nFitPars_(0), nFreePars_(0), nExtraPars_(0), iExpt_(0) { rootFile_ = TFile::Open(rootFileName_, "recreate"); rootFile_->cd(); fitResults_ = new TTree("fitResults", "fitResults"); fitResults_->SetDirectory(rootFile_); fitVars_.clear(); extraVars_.clear(); } LauFitNtuple::~LauFitNtuple() { if (rootFile_ && rootFile_->IsOpen()) { delete fitResults_; fitResults_ = 0; } delete rootFile_; rootFile_ = 0; } void LauFitNtuple::storeCorrMatrix(const UInt_t iExpt, const LauAbsFitter::FitStatus& fitStatus, const TMatrixD& covMatrix) { // store the minimised NLL value, correlation matrix status and experiment number iExpt_ = iExpt; fitStatus_ = fitStatus; // make the correlation matrix the correct dimensions if (definedFitTree_ == kFALSE) { corrMatrix_.clear(); corrMatrix_.resize(nFitPars_); for (UInt_t i = 0; i < nFitPars_; ++i) {corrMatrix_[i].resize(nFitPars_);} } // under certain circumstances, e.g. if the fit has failed in the first // stage of a two-stage fit, the covariance matrix might not have the // expected dimensions, or it might even be empty Bool_t needsPadding = kFALSE; const UInt_t nElements = covMatrix.GetNoElements(); if ( nElements == 0 ) { // if it's empty we can just make a diagonal matrix std::cerr << "WARNING in LauFitNtuple::storeCorrMatrix : received empty covariance matrix - will store diagonal correlation matrix" << std::endl; for (UInt_t i = 0; i < nFitPars_; ++i) { for (UInt_t j = 0; j < nFitPars_; ++j) { if (i == j) { corrMatrix_[i][j] = 1.0; } else { corrMatrix_[i][j] = 0.0; } } } return; } else if ( nElements != nFreePars_*nFreePars_ ) { UInt_t dimension = covMatrix.GetNrows(); UInt_t nSecondStage = 0; for (UInt_t i = 0; i < nFitPars_; ++i) { if ( fitVars_[i]->secondStage() ) { ++nSecondStage; } } if ( (dimension + nSecondStage) == nFreePars_ ) { needsPadding = kTRUE; std::cerr << "WARNING in LauFitNtuple::storeCorrMatrix : received smaller covariance matrix than expected, likely due to failure of first stage fit - will pad the correlation matrix" << std::endl; std::cerr << " : nFitPars_ = " << nFitPars_ << std::endl; std::cerr << " : nFreePars_ = " << nFreePars_ << std::endl; std::cerr << " : nSecondStage = " << nSecondStage << std::endl; std::cerr << " : covMatrix size = " << dimension << std::endl; } else { std::cerr << "WARNING in LauFitNtuple::storeCorrMatrix : received smaller covariance matrix than expected, for unknown reasons - will store diagonal correlation matrix" << std::endl; std::cerr << " : nFitPars_ = " << nFitPars_ << std::endl; std::cerr << " : nFreePars_ = " << nFreePars_ << std::endl; std::cerr << " : nSecondStage = " << nSecondStage << std::endl; std::cerr << " : covMatrix size = " << dimension << std::endl; for (UInt_t i = 0; i < nFitPars_; ++i) { for (UInt_t j = 0; j < nFitPars_; ++j) { if (i == j) { corrMatrix_[i][j] = 1.0; } else { corrMatrix_[i][j] = 0.0; } } } return; } } // calculate the correlation matrix information from the fitter covariance matrix Bool_t iFixed(kFALSE); Bool_t jFixed(kFALSE); Bool_t iSecondStage(kFALSE); Bool_t jSecondStage(kFALSE); UInt_t iFree(0); UInt_t jFree(0); for (UInt_t i = 0; i < nFitPars_; ++i) { iFixed = fitVars_[i]->fixed(); iSecondStage = fitVars_[i]->secondStage(); // reset the "j" free parameter counter jFree = 0; // NB the supplied covariance matrix is of dimension nFreePars_ x nFreePars_ for (UInt_t j = 0; j < nFitPars_; ++j) { jFixed = fitVars_[j]->fixed(); jSecondStage = fitVars_[j]->secondStage(); if (i == j) { corrMatrix_[i][j] = 1.0; } else if (iFixed == kTRUE || jFixed == kTRUE) { corrMatrix_[i][j] = 0.0; } else if ( needsPadding && ( iSecondStage || jSecondStage ) ) { corrMatrix_[i][j] = 0.0; } else { Double_t r_ij = covMatrix(iFree,jFree); Double_t r_ii = covMatrix(iFree,iFree); Double_t r_jj = covMatrix(jFree,jFree); Double_t denom = r_ii * r_jj; if (denom < 0.0) { r_ij = 0.0; denom = 1.0; } denom = TMath::Sqrt(denom); if (denom < 1e-30) { r_ij = 0.0; denom = 1.0; } corrMatrix_[i][j] = r_ij / denom; } if ( !jFixed && !(needsPadding && jSecondStage) ) { ++jFree; } } if ( !iFixed && !(needsPadding && iSecondStage) ) { ++iFree; } } } void LauFitNtuple::storeParsAndErrors(const std::vector& fitVars, const std::vector& extraVars) { fitVars_ = fitVars; UInt_t nFitPars = fitVars_.size(); // the number of parameters being given to us should be the same as the number from the last fit // OR it's the first time so the "last" number is zero if (nFitPars_ != 0 && nFitPars_ != nFitPars) { std::cerr << "ERROR in LauFitNtuple::storeParsAndErrors : expected total number of parameters (" << nFitPars_ << ") not the same as the number provided (" << nFitPars << ")." << std::endl; gSystem->Exit(EXIT_FAILURE); } LauParamFixed pred; UInt_t nFreePars = nFitPars - std::count_if(fitVars_.begin(),fitVars_.end(),pred); // the number of free parameters being given to us should be the same as the number from the last fit // OR it's the first time so the "last" number is zero // (NB we check whether nFitPars_ is zero for this since it is possible to have zero free parameters, albeit rather daft) if (nFitPars_ != 0 && nFreePars_ != nFreePars) { std::cerr << "ERROR in LauFitNtuple::storeParsAndErrors : expected number of free parameters (" << nFreePars_ << ") not the same as the number provided (" << nFreePars << ")." << std::endl; gSystem->Exit(EXIT_FAILURE); } nFitPars_ = nFitPars; nFreePars_ = nFreePars; extraVars_ = extraVars; nExtraPars_ = extraVars_.size(); } void LauFitNtuple::updateFitNtuple() { // Now create and fill the stored fit results into an ntuple (TTree) if (definedFitTree_ == kFALSE) { std::cout << "INFO in LauFitNtuple::updateFitNtuple : totNoPars = " << nFitPars_ << std::endl; // Add experiment number as a branch fitResults_->Branch("iExpt", &iExpt_, "iExpt/I"); fitResults_->Branch("fitStatus", &fitStatus_.status, "fitStatus/I"); // Add NLL (negative log-likelihood) and EDM values from fit fitResults_->Branch("NLL", &fitStatus_.NLL, "NLL/D"); fitResults_->Branch("EDM", &fitStatus_.EDM, "EDM/D"); for (UInt_t i = 0; i < nFitPars_; i++) { TString parName = fitVars_[i]->name(); TString parNameD(parName); parNameD += "/D"; fitResults_->Branch(parName.Data(), &fitVars_[i]->value_, parNameD.Data()); TString parInitName(parName); parInitName += "_True"; TString parInitNameD(parInitName); parInitNameD += "/D"; fitResults_->Branch(parInitName.Data(), &fitVars_[i]->genValue_, parInitNameD.Data()); if (!fitVars_[i]->fixed()) { TString parErrName(parName); parErrName += "_Error"; TString parErrNameD(parErrName); parErrNameD += "/D"; fitResults_->Branch(parErrName.Data(), &fitVars_[i]->error_, parErrNameD.Data()); if ( storeAsymErrors_ ) { TString parNegErrName(parName); parNegErrName += "_NegError"; TString parNegErrNameD(parNegErrName); parNegErrNameD += "/D"; fitResults_->Branch(parNegErrName.Data(), &fitVars_[i]->negError_, parNegErrNameD.Data()); TString parPosErrName(parName); parPosErrName += "_PosError"; TString parPosErrNameD(parPosErrName); parPosErrNameD += "/D"; fitResults_->Branch(parPosErrName.Data(), &fitVars_[i]->posError_, parPosErrNameD.Data()); } TString parPullName(parName); parPullName += "_Pull"; TString parPullNameD(parPullName); parPullNameD += "/D"; fitResults_->Branch(parPullName.Data(), &fitVars_[i]->pull_, parPullNameD.Data()); } // Now add in the correlation matrix values (only for floating parameters) if (!fitVars_[i]->fixed()) { // First the global correlation coeffs TString parGCCName(parName); parGCCName += "_GCC"; TString parGCCNameD(parGCCName); parGCCNameD += "/D"; fitResults_->Branch(parGCCName.Data(), &fitVars_[i]->gcc_, parGCCNameD.Data()); if ( ! corrMatrix_.empty() ) { // Then the rest for (UInt_t j = 0; j < nFitPars_; j++) { if (!fitVars_[j]->fixed() && i!=j) { TString parName2 = fitVars_[j]->name(); TString corrName("corr__"); corrName += parName; corrName += "__"; corrName += parName2; TString corrNameD(corrName); corrNameD += "/D"; fitResults_->Branch(corrName.Data(), &corrMatrix_[i][j], corrNameD.Data()); } } } } } // Update extra parameter values... for (UInt_t i = 0; i < nExtraPars_; i++) { TString parName = extraVars_[i].name(); TString parNameD(parName); parNameD += "/D"; fitResults_->Branch(parName.Data(), &extraVars_[i].value_, parNameD.Data()); TString parInitName(parName); parInitName += "_True"; TString parInitNameD(parInitName); parInitNameD += "/D"; fitResults_->Branch(parInitName.Data(), &extraVars_[i].genValue_, parInitNameD.Data()); //TString parErrName(parName); parErrName += "_Error"; //TString parErrNameD(parErrName); parErrNameD += "/D"; //fitResults_->Branch(parErrName.Data(), &extraVars_[i].error_, parErrNameD.Data()); // Also find the fit fraction pull and store it //TString pullName(parName); pullName += "_Pull"; //TString pullNameD(pullName); pullNameD += "/D"; //fitResults_->Branch(pullName.Data(), &extraVars_[i].pull_, pullNameD.Data()); } definedFitTree_ = kTRUE; } std::cout << "INFO in LauFitNtuple::updateFitNtuple : Stored fit values for experiment " << iExpt_ << "\n"; std::cout << " : fitStatus = " << fitStatus_.status << std::endl; std::cout << " : NLL = " << fitStatus_.NLL << std::endl; std::cout << " : EDM = " << fitStatus_.EDM << std::endl; fitResults_->Fill(); } void LauFitNtuple::writeOutFitResults() { // Write out the fit ntuple to the appropriate root file rootFile_->cd(); fitResults_->Write("",TObject::kOverwrite); rootFile_->Close(); delete rootFile_; rootFile_ = 0; } diff --git a/src/LauFitObject.cc b/src/LauFitObject.cc index 4c0f3e6..9e872bd 100644 --- a/src/LauFitObject.cc +++ b/src/LauFitObject.cc @@ -1,101 +1,100 @@ /* Copyright 2017 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauFitObject.cc \brief File containing implementation of LauFitObject class. */ #include "LauFitObject.hh" -ClassImp(LauFitObject) LauFitObject::LauFitObject() : TObject(), storeCon_(), twoStageFit_(kFALSE), useAsymmFitErrors_(kFALSE), nParams_(0), nFreeParams_(0), withinAsymErrorCalc_(kFALSE), firstExpt_(0), nExpt_(0), iExpt_(0), evtsPerExpt_(0), fitStatus_({-1,0.0,0.0}), worstLogLike_(std::numeric_limits::max()), covMatrix_(), numberOKFits_(0), numberBadFits_(0) { } void LauFitObject::resetFitCounters() { numberOKFits_ = 0; numberBadFits_ = 0; fitStatus_ = { -1, 0.0, 0.0 }; } void LauFitObject::startNewFit( const UInt_t nPars, const UInt_t nFreePars ) { // Reset the worst likelihood found to its catch-all value worstLogLike_ = std::numeric_limits::max(); // Store the number of fit parameters (total and floating) nParams_ = nPars; nFreeParams_ = nFreePars; } void LauFitObject::storeFitStatus( const LauAbsFitter::FitStatus& status, const TMatrixD& covMatrix ) { fitStatus_ = status; covMatrix_.Clear(); covMatrix_.ResizeTo( covMatrix.GetNrows(), covMatrix.GetNcols() ); covMatrix_.SetMatrixArray( covMatrix.GetMatrixArray() ); // Keep track of how many fits worked or failed // NB values of fitStatus_ indicate the status of the error matrix: // 0= not calculated at all // 1= approximation only, not accurate // 2= full matrix, but forced positive-definite // 3= full accurate covariance matrix if (fitStatus_.status == 3) { ++numberOKFits_; } else { ++numberBadFits_; } } void LauFitObject::addConstraint(const TString& formula, const std::vector& pars, const Double_t mean, const Double_t width) { StoreConstraints newCon; newCon.formula_ = formula; newCon.conPars_ = pars; newCon.mean_ = mean; newCon.width_ = width; storeCon_.push_back(newCon); } diff --git a/src/LauFitter.cc b/src/LauFitter.cc index 7c079b4..ccc5ed2 100644 --- a/src/LauFitter.cc +++ b/src/LauFitter.cc @@ -1,64 +1,63 @@ /* Copyright 2005 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauFitter.cc \brief File containing implementation of LauFitter methods. */ #include #include "LauFitter.hh" #include "LauAbsFitter.hh" #include "LauMinuit.hh" LauAbsFitter* LauFitter::theInstance_ = 0; LauFitter::Type LauFitter::fitterType_ = LauFitter::Minuit; -ClassImp(LauFitter) void LauFitter::setFitterType( Type type ) { if ( theInstance_ != 0 ) { std::cerr << "ERROR in LauFitter::setFitterType : The fitter has already been created, cannot change the type now." << std::endl; return; } fitterType_ = type; } LauAbsFitter* LauFitter::fitter() { // Returns a pointer to a singleton LauAbsFitter object. // Creates the object the first time it is called. if ( theInstance_ == 0 ) { if ( fitterType_ == Minuit ) { theInstance_ = new LauMinuit(); } } return theInstance_; } diff --git a/src/LauFlatNR.cc b/src/LauFlatNR.cc index 41ea817..24d6e33 100644 --- a/src/LauFlatNR.cc +++ b/src/LauFlatNR.cc @@ -1,61 +1,60 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauFlatNR.cc \brief File containing implementation of LauFlatNR class. */ #include #include "LauKinematics.hh" #include "LauFlatNR.hh" -ClassImp(LauFlatNR) LauFlatNR::LauFlatNR(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters) { } LauFlatNR::~LauFlatNR() { } void LauFlatNR::initialise() { } LauComplex LauFlatNR::amplitude(const LauKinematics* /*kinematics*/) { // return the uniform amplitude return LauComplex(1.0, 0.0); } LauComplex LauFlatNR::resAmp(Double_t mass, Double_t spinTerm) { std::cerr << "ERROR in LauFlatNR::resAmp : This method shouldn't get called." << std::endl; std::cerr << " Returning zero amplitude for mass = " << mass << " and spinTerm = " << spinTerm << "." << std::endl; return LauComplex(0.0, 0.0); } diff --git a/src/LauFlatteRes.cc b/src/LauFlatteRes.cc index 80c4e54..0feed54 100644 --- a/src/LauFlatteRes.cc +++ b/src/LauFlatteRes.cc @@ -1,369 +1,368 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauFlatteRes.cc \brief File containing implementation of LauFlatteRes class. */ #include #include "LauConstants.hh" #include "LauFlatteRes.hh" #include "LauResonanceInfo.hh" #include "TSystem.h" -ClassImp(LauFlatteRes) LauFlatteRes::LauFlatteRes(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), g1_(0), g2_(0), mSumSq0_(0.0), mSumSq1_(0.0), mSumSq2_(0.0), mSumSq3_(0.0), useAdlerTerm_(kFALSE), sA_(0.0), absorbM0_(kFALSE) { Double_t resMass(0.0); Double_t g1Val(0.0); Double_t g2Val(0.0); const TString& resName = this->getResonanceName(); if ( resName == "f_0(980)" ) { // Set the mass threshold values mSumSq0_ = (LauConstants::mPi0 + LauConstants::mPi0) * (LauConstants::mPi0 + LauConstants::mPi0); mSumSq1_ = (LauConstants::mPi + LauConstants::mPi) * (LauConstants::mPi + LauConstants::mPi); mSumSq2_ = (LauConstants::mK + LauConstants::mK) * (LauConstants::mK + LauConstants::mK); mSumSq3_ = (LauConstants::mK0 + LauConstants::mK0) * (LauConstants::mK0 + LauConstants::mK0); // Set values of mass and coupling constants from: // Phys. Lett. B 607, 243 (2005) resMass = 0.965; // 0.965 +/- 0.008 +/- 0.006 GeV/c^2 g1Val = 0.165; // 0.165 +/- 0.010 +/- 0.015 GeV^2 g2Val = 4.21*g1Val; // 4.21 +/- 0.25 +/- 0.21 useAdlerTerm_ = kFALSE; sA_ = 0.0; absorbM0_ = kTRUE; } else if ( resName == "K*0_0(1430)" ) { // Set the mass threshold values mSumSq0_ = (LauConstants::mK0 + LauConstants::mPi0) * (LauConstants::mK0 + LauConstants::mPi0); mSumSq1_ = (LauConstants::mK + LauConstants::mPi) * (LauConstants::mK + LauConstants::mPi); mSumSq2_ = (LauConstants::mK0 + LauConstants::mEtaPrime) * (LauConstants::mK0 + LauConstants::mEtaPrime); mSumSq3_ = (LauConstants::mK0 + LauConstants::mEtaPrime) * (LauConstants::mK0 + LauConstants::mEtaPrime); // Set values of mass and coupling constants from: // Phys. Lett. B 572, 1 (2003) resMass = 1.513; // GeV/c^2 g1Val = 0.304; // GeV g2Val = 0.380; // GeV useAdlerTerm_ = kTRUE; sA_ = 0.234; absorbM0_ = kFALSE; } else if ( resName == "K*+_0(1430)" || resName == "K*-_0(1430)" ) { // Set the mass threshold values mSumSq0_ = (LauConstants::mK + LauConstants::mPi0) * (LauConstants::mK + LauConstants::mPi0); mSumSq1_ = (LauConstants::mK0 + LauConstants::mPi) * (LauConstants::mK0 + LauConstants::mPi); mSumSq2_ = (LauConstants::mK + LauConstants::mEtaPrime) * (LauConstants::mK + LauConstants::mEtaPrime); mSumSq3_ = (LauConstants::mK + LauConstants::mEtaPrime) * (LauConstants::mK + LauConstants::mEtaPrime); // Set values of mass and coupling constants from: // Phys. Lett. B 572, 1 (2003) resMass = 1.513; // GeV/c^2 g1Val = 0.304; // GeV g2Val = 0.380; // GeV useAdlerTerm_ = kTRUE; sA_ = 0.234; absorbM0_ = kFALSE; } else if ( resName == "a0_0(980)" ) { // Set the mass threshold values mSumSq0_ = (LauConstants::mEta + LauConstants::mPi0) * (LauConstants::mEta + LauConstants::mPi0); mSumSq1_ = (LauConstants::mEta + LauConstants::mPi0) * (LauConstants::mEta + LauConstants::mPi0); mSumSq2_ = (LauConstants::mK + LauConstants::mK) * (LauConstants::mK + LauConstants::mK); mSumSq3_ = (LauConstants::mK0 + LauConstants::mK0) * (LauConstants::mK0 + LauConstants::mK0); // Set values of mass and coupling constants from: // Phys. Rev. D 57, 3860 (1998) resMass = 0.982; // 0.982 +/- 0.003 GeV/c^2 g1Val = 0.324*0.324; // 0.324 +/- 0.015 GeV (NB this value needs to be squared since the paper uses g_1^2 and g_2^2) g2Val = 1.03*g1Val; // 1.03 +/- 0.14 (NB this is indeed the ratio of what the paper refers to as g_2^2 and g_1^2, so can be used unchanged here) useAdlerTerm_ = kFALSE; sA_ = 0.0; absorbM0_ = kTRUE; } else if ( resName == "a+_0(980)" || resName == "a-_0(980)" ) { // Set the mass threshold values mSumSq0_ = (LauConstants::mEta + LauConstants::mPi) * (LauConstants::mEta + LauConstants::mPi); mSumSq1_ = (LauConstants::mEta + LauConstants::mPi) * (LauConstants::mEta + LauConstants::mPi); mSumSq2_ = (LauConstants::mK + LauConstants::mK0) * (LauConstants::mK + LauConstants::mK0); mSumSq3_ = (LauConstants::mK + LauConstants::mK0) * (LauConstants::mK + LauConstants::mK0); // Set values of mass and coupling constants from: // Phys. Rev. D 57, 3860 (1998) resMass = 0.982; // 0.982 +/- 0.003 GeV/c^2 g1Val = 0.324*0.324; // 0.324 +/- 0.015 GeV (NB this value needs to be squared since the paper uses g_1^2 and g_2^2) g2Val = 1.03*g1Val; // 1.03 +/- 0.14 (NB this is indeed the ratio of what the paper refers to as g_2^2 and g_1^2, so can be used unchanged here) useAdlerTerm_ = kFALSE; sA_ = 0.0; absorbM0_ = kTRUE; } const TString couplingUnits = (absorbM0_) ? "GeV^2" : "GeV"; std::cout << "INFO in LauFlatteRes::LauFlatteRes : Setting default parameters for " << resName << ":\n"; std::cout << " : mass = " << resMass << " GeV/c^2\n"; std::cout << " : g1 = " << g1Val << " " << couplingUnits << "\n"; std::cout << " : g2 = " << g2Val << " " << couplingUnits << "\n"; if ( absorbM0_ ) { std::cout << " : Will absorb m0 into couplings\n"; } else { std::cout << " : Will not absorb m0 into couplings\n"; } if ( useAdlerTerm_ ) { std::cout << " : Will use Adler zero term\n"; std::cout << " : sA = " << sA_ << " GeV^2/c^4\n"; } else { std::cout << " : Will not use Adler zero term\n"; } // Set the mass value LauParameter* massPar = this->getMassPar(); if ( massPar ) { massPar->valueAndRange(resMass,0.0,3.0*resMass); massPar->initValue(resMass); massPar->genValue(resMass); } else { std::cerr << "ERROR in LauFlatteRes::LauFlatteRes : Unable to retrieve mass parameter" << std::endl; } // Create the parameters for the coupling constants const TString& parNameBase = this->getSanitisedName(); TString g1Name(parNameBase); g1Name += "_g1"; g1_ = resInfo->getExtraParameter( g1Name ); if ( g1_ == 0 ) { g1_ = new LauParameter( g1Name, g1Val, 0.0, 10.0, kTRUE ); g1_->secondStage(kTRUE); resInfo->addExtraParameter( g1_ ); } TString g2Name(parNameBase); g2Name += "_g2"; g2_ = resInfo->getExtraParameter( g2Name ); if ( g2_ == 0 ) { g2_ = new LauParameter( g2Name, g2Val, 0.0, 10.0, kTRUE ); g2_->secondStage(kTRUE); resInfo->addExtraParameter( g2_ ); } } LauFlatteRes::~LauFlatteRes() { } void LauFlatteRes::initialise() { const TString& resName = this->getResonanceName(); if ( resName != "f_0(980)" && resName != "K*0_0(1430)" && resName != "K*+_0(1430)" && resName != "K*-_0(1430)" && resName != "a0_0(980)" && resName != "a+_0(980)" && resName != "a-_0(980)" ) { std::cerr << "ERROR in LauFlatteRes::initialise : Unexpected resonance name \"" << resName << "\" for Flatte shape." << std::endl; gSystem->Exit(EXIT_FAILURE); } Int_t resSpin = this->getSpin(); if (resSpin != 0) { std::cerr << "WARNING in LauFlatteRes::amplitude : Resonance spin is " << resSpin << "." << std::endl; std::cerr << " : Flatte amplitude is only defined for scalers, resetting spin to 0." << std::endl; this->changeResonance( -1.0, -1.0, 0 ); } } LauComplex LauFlatteRes::resAmp(Double_t mass, Double_t spinTerm) { // This function returns the complex dynamical amplitude for a Flatte distribution // given the invariant mass and cos(helicity) values. const Double_t resMass = this->getMass(); const Double_t resMassSq = resMass*resMass; const Double_t s = mass*mass; // Invariant mass squared combination for the system const Double_t g1Val = this->getg1Parameter(); const Double_t g2Val = this->getg2Parameter(); Double_t dMSq = resMassSq - s; Double_t rho1(0.0), rho2(0.0); if (s > mSumSq0_) { rho1 = TMath::Sqrt(1.0 - mSumSq0_/s)/3.0; if (s > mSumSq1_) { rho1 += 2.0*TMath::Sqrt(1.0 - mSumSq1_/s)/3.0; if (s > mSumSq2_) { rho2 = 0.5*TMath::Sqrt(1.0 - mSumSq2_/s); if (s > mSumSq3_) { rho2 += 0.5*TMath::Sqrt(1.0 - mSumSq3_/s); } else { // Continue analytically below higher channel thresholds // This contributes to the real part of the amplitude denominator dMSq += g2Val*resMass*0.5*TMath::Sqrt(mSumSq3_/s - 1.0); } } else { // Continue analytically below higher channel thresholds // This contributes to the real part of the amplitude denominator rho2 = 0.0; dMSq += g2Val*resMass*(0.5*TMath::Sqrt(mSumSq2_/s - 1.0) + 0.5*TMath::Sqrt(mSumSq3_/s - 1.0)); } } else { // Continue analytically below higher channel thresholds // This contributes to the real part of the amplitude denominator dMSq += g1Val*resMass*2.0*TMath::Sqrt(mSumSq1_/s - 1.0)/3.0; } } Double_t massFactor = 1.0; if ( ! absorbM0_ ) { massFactor = resMass; } if (useAdlerTerm_) { massFactor *= ( s - sA_ ) / ( resMassSq - sA_ ); } const Double_t width1 = g1Val*rho1*massFactor; const Double_t width2 = g2Val*rho2*massFactor; const Double_t widthTerm = width1 + width2; LauComplex resAmplitude(dMSq, widthTerm); const Double_t denomFactor = dMSq*dMSq + widthTerm*widthTerm; Double_t invDenomFactor = 0.0; if (denomFactor > 1e-10) {invDenomFactor = 1.0/denomFactor;} resAmplitude.rescale(spinTerm*invDenomFactor); return resAmplitude; } const std::vector& LauFlatteRes::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixMass() ) { this->addFloatingParameter( this->getMassPar() ); } // NB the width is given in terms of g1 and g2 so the normal width // parameter should be ignored, hence it is not added to the list if ( ! this->fixg1Parameter() ) { this->addFloatingParameter( g1_ ); } if ( ! this->fixg2Parameter() ) { this->addFloatingParameter( g2_ ); } return this->getParameters(); } void LauFlatteRes::setResonanceParameter(const TString& name, const Double_t value) { if (name == "g1") { this->setg1Parameter(value); std::cout << "INFO in LauFlatteRes::setResonanceParameter : Setting g1 parameter to " << this->getg1Parameter() << std::endl; } else if (name == "g2") { this->setg2Parameter(value); std::cout << "INFO in LauFlatteRes::setResonanceParameter : Setting g2 parameter to " << this->getg2Parameter() << std::endl; } else { std::cerr << "WARNING in LauFlatteRes::setResonanceParameter : Parameter name \"" << name << "\" not recognised." << std::endl; } } void LauFlatteRes::floatResonanceParameter(const TString& name) { if (name == "g1") { if ( g1_->fixed() ) { g1_->fixed( kFALSE ); this->addFloatingParameter( g1_ ); } else { std::cerr << "WARNING in LauFlatteRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "g2") { if ( g2_->fixed() ) { g2_->fixed( kFALSE ); this->addFloatingParameter( g2_ ); } else { std::cerr << "WARNING in LauFlatteRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else { std::cerr << "WARNING in LauFlatteRes::fixResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } LauParameter* LauFlatteRes::getResonanceParameter(const TString& name) { if (name == "g1") { return g1_; } else if (name == "g2") { return g2_; } else { std::cerr << "WARNING in LauFlatteRes::getResonanceParameter: Parameter name not reconised." << std::endl; return 0; } } void LauFlatteRes::setg1Parameter(const Double_t g1) { g1_->value( g1 ); g1_->genValue( g1 ); g1_->initValue( g1 ); } void LauFlatteRes::setg2Parameter(const Double_t g2) { g2_->value( g2 ); g2_->genValue( g2 ); g2_->initValue( g2 ); } diff --git a/src/LauFormulaPar.cc b/src/LauFormulaPar.cc index 04bfdc4..3dfa950 100644 --- a/src/LauFormulaPar.cc +++ b/src/LauFormulaPar.cc @@ -1,208 +1,207 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauFormulaPar.cc \brief File containing implementation of LauFormulaPar class. */ #include #include #include #include #include "TRandom.h" #include "TMessage.h" #include "TSystem.h" #include "LauFormulaPar.hh" #include "LauParameter.hh" #include "LauRandom.hh" -ClassImp(LauFormulaPar) LauFormulaPar::LauFormulaPar(const TString& forName, const TString& formula, const std::vector& params) : name_(forName), formula_(forName,formula), paramVec_(params), dummy_(0), paramArray_(0), gaussConstraint_(kFALSE), constraintMean_(0.0), constraintWidth_(0.0) { // Check length of vector matches number of parameter in the formula Int_t nPars = paramVec_.size(); if (formula_.GetNpar() != nPars){ std::cerr<<"ERROR in LauFormulaPar::evaluate : Number of parameters in the formula is : "<Exit(EXIT_FAILURE); } if (formula_.GetNdim() != 1){ std::cerr<<"ERROR in LauFormulaPar::evaluate : Given formula of dimension: "<Exit(EXIT_FAILURE); } // Dummy array for TFormula dummy_ = new Double_t[1]; // Array of input parameters paramArray_ = new Double_t[nPars]; } LauFormulaPar::~LauFormulaPar() { delete[] dummy_; delete[] paramArray_; } LauFormulaPar::LauFormulaPar(const LauFormulaPar& rhs) : LauAbsRValue(rhs), name_(rhs.name_), formula_(rhs.formula_), paramVec_(rhs.paramVec_), dummy_(0), paramArray_(0), gaussConstraint_(rhs.gaussConstraint_), constraintMean_(rhs.constraintMean_), constraintWidth_(rhs.constraintWidth_) { // Check length of vector matches number of parameter in the formula Int_t nPars = paramVec_.size(); if (formula_.GetNpar() != nPars){ std::cerr<<"ERROR in LauFormulaPar::evaluate : Number of parameters in the formula is : "<Exit(EXIT_FAILURE); } if (formula_.GetNdim() != 1){ std::cerr<<"ERROR in LauFormulaPar::evaluate : Given formula of dimension: "<Exit(EXIT_FAILURE); } // Dummy array for TFormula dummy_ = new Double_t[1]; // Array of input parameters paramArray_ = new Double_t[nPars]; } LauFormulaPar& LauFormulaPar::operator=(const LauFormulaPar& rhs) { if ( &rhs != this ) { name_ = rhs.name_; formula_ = rhs.formula_; Int_t nOldPars = paramVec_.size(); Int_t nNewPars = rhs.paramVec_.size(); paramVec_ = rhs.paramVec_; if ( nOldPars != nNewPars ) { delete [] paramArray_; paramArray_ = new Double_t[nNewPars]; } // NB no need to recreate dummy_ gaussConstraint_ = rhs.gaussConstraint_; constraintMean_ = rhs.constraintMean_; constraintWidth_ = rhs.constraintWidth_; } return *this; } Double_t LauFormulaPar::value() const { //Assign vector values to array Int_t nPars = paramVec_.size(); for(Int_t i=0; ivalue(); } return formula_.EvalPar(dummy_,paramArray_); } Double_t LauFormulaPar::unblindValue() const { //Assign vector values to array Int_t nPars = paramVec_.size(); for(Int_t i=0; iunblindValue(); } return formula_.EvalPar(dummy_,paramArray_); } Double_t LauFormulaPar::genValue() const { //Assign vector values to array Int_t nPars = paramVec_.size(); for(Int_t i=0; igenValue(); } return formula_.EvalPar(dummy_,paramArray_); } Double_t LauFormulaPar::initValue() const { //Assign vector values to array Int_t nPars = paramVec_.size(); for(Int_t i=0; iinitValue(); } return formula_.EvalPar(dummy_,paramArray_); } Bool_t LauFormulaPar::fixed() const { for ( std::vector::const_iterator iter = paramVec_.begin(); iter != paramVec_.end(); ++iter ) { if ( !(*iter)->fixed() ) { return kFALSE; } } return kTRUE; } Bool_t LauFormulaPar::blind() const { for ( std::vector::const_iterator iter = paramVec_.begin(); iter != paramVec_.end(); ++iter ) { if ( (*iter)->blind() ) { return kTRUE; } } return kFALSE; } void LauFormulaPar::addGaussianConstraint(Double_t newGaussMean, Double_t newGaussWidth) { gaussConstraint_ = kTRUE; constraintMean_ = newGaussMean; constraintWidth_ = newGaussWidth; } void LauFormulaPar::removeGaussianConstraint() { gaussConstraint_ = kFALSE; } diff --git a/src/LauGaussIncohRes.cc b/src/LauGaussIncohRes.cc index 12229af..3a2a682 100644 --- a/src/LauGaussIncohRes.cc +++ b/src/LauGaussIncohRes.cc @@ -1,99 +1,98 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauGaussIncohRes.cc \brief File containing implementation of LauGaussIncohRes class. */ #include #include "LauConstants.hh" #include "LauGaussIncohRes.hh" #include "LauKinematics.hh" -ClassImp(LauGaussIncohRes) LauGaussIncohRes::LauGaussIncohRes(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsIncohRes(resInfo, resPairAmpInt, daughters) { } LauGaussIncohRes::~LauGaussIncohRes() { } void LauGaussIncohRes::initialise() { } Double_t LauGaussIncohRes::intensityFactor(const LauKinematics* kinematics) { Int_t pair = this->getPairInt(); Double_t mass(0.); switch(pair) { case 1: mass = kinematics->getm23(); break; case 2: mass = kinematics->getm13(); break; case 3: mass = kinematics->getm12(); break; default: std::cerr << "ERROR in LauGaussIncohRes::intensityFactor : Incorrect daughter pair defined." << std::endl; std::cerr << " Returning zero intensity." << std::endl; return 0.; } Double_t m0 = this->getMass(); Double_t G0 = this->getWidth(); if(G0==0) { std::cerr << "ERROR in LauGaussIncohRes::intensityFactor : Gaussian width cannot be zero." << std::endl; std::cerr << " Returning zero intensity." << std::endl; return 0.; } Double_t exponent = -0.5 * ( mass - m0 ) * (mass - m0 ) / (G0*G0); Double_t intensity = TMath::Exp(exponent); return intensity; } const std::vector& LauGaussIncohRes::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixMass() ) { this->addFloatingParameter( this->getMassPar() ); } if ( ! this->fixWidth() ) { this->addFloatingParameter( this->getWidthPar() ); } return this->getParameters(); } diff --git a/src/LauGaussPdf.cc b/src/LauGaussPdf.cc index 0c519bc..f0237d0 100644 --- a/src/LauGaussPdf.cc +++ b/src/LauGaussPdf.cc @@ -1,146 +1,145 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauGaussPdf.cc \brief File containing implementation of LauGaussPdf class. */ #include #include using std::cout; using std::cerr; using std::endl; using std::vector; #include "TMath.h" #include "TSystem.h" #include "LauConstants.hh" #include "LauGaussPdf.hh" -ClassImp(LauGaussPdf) LauGaussPdf::LauGaussPdf(const TString& theVarName, const vector& params, Double_t minAbscissa, Double_t maxAbscissa) : LauAbsPdf(theVarName, params, minAbscissa, maxAbscissa), mean_(0), sigma_(0) { // Constructor for the Gaussian PDF. // // The parameters in params are the mean and the sigma (half the width) of the gaussian. // The last two arguments specify the range in which the PDF is defined, and the PDF // will be normalised w.r.t. these limits. mean_ = this->findParameter("mean"); sigma_ = this->findParameter("sigma"); if ((this->nParameters() != 2) || (mean_ == 0) || (sigma_ == 0)) { cerr<<"ERROR in LauGaussPdf constructor: LauGaussPdf requires 2 parameters: \"mean\" and \"sigma\"."<Exit(EXIT_FAILURE); } // Cache the normalisation factor this->calcNorm(); } LauGaussPdf::~LauGaussPdf() { // Destructor } void LauGaussPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Get our abscissa Double_t abscissa = abscissas[0]; // Get the up to date parameter values Double_t mean = mean_->unblindValue(); Double_t sigma = sigma_->unblindValue(); // Calculate the value of the Gaussian for the given value of the abscissa. Double_t arg = abscissa - mean; Double_t exponent(0.0); if (TMath::Abs(sigma) > 1e-10) { exponent = -0.5*arg*arg/(sigma*sigma); } Double_t value = TMath::Exp(exponent); this->setUnNormPDFVal(value); // if the parameters are floating then we // need to recalculate the normalisation if (!this->cachePDF() && !this->withinNormCalc() && !this->withinGeneration()) { this->calcNorm(); } } void LauGaussPdf::calcNorm() { // Get the up to date parameter values Double_t mean = mean_->unblindValue(); Double_t sigma = sigma_->unblindValue(); // Calculate the normalisation of the gaussian and cache it. Double_t scale = LauConstants::root2*sigma; Double_t norm(0.0); if (TMath::Abs(sigma) > 1e-10) { norm = LauConstants::rootPiBy2*sigma*(TMath::Erf((this->getMaxAbscissa() - mean)/scale) - TMath::Erf((this->getMinAbscissa() - mean)/scale)); } this->setNorm(norm); } void LauGaussPdf::calcPDFHeight(const LauKinematics* /*kinematics*/) { if (this->heightUpToDate()) { return; } // Get the up to date parameter values Double_t mean = mean_->unblindValue(); LauAbscissas maxPoint(1); maxPoint[0] = mean; // Calculate the PDF height for the Gaussian function. if (mean>this->getMaxAbscissa()) { maxPoint[0] = this->getMaxAbscissa(); } else if (meangetMinAbscissa()) { maxPoint[0] = this->getMinAbscissa(); } this->calcLikelihoodInfo(maxPoint); Double_t height = this->getUnNormLikelihood(); this->setMaxHeight(height); } diff --git a/src/LauGenNtuple.cc b/src/LauGenNtuple.cc index a67c704..8686e05 100644 --- a/src/LauGenNtuple.cc +++ b/src/LauGenNtuple.cc @@ -1,217 +1,216 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauGenNtuple.cc \brief File containing implementation of LauGenNtuple class. */ #include using std::cout; using std::cerr; using std::endl; #include "TFile.h" #include "TTree.h" #include "LauGenNtuple.hh" -ClassImp(LauGenNtuple) LauGenNtuple::LauGenNtuple(const TString& rootFileName, const TString& rootTreeName) : rootFileName_(rootFileName), rootTreeName_(rootTreeName), rootFile_(0), rootTree_(0), definedBranches_(kFALSE) { this->createFileAndTree(); } LauGenNtuple::~LauGenNtuple() { // seems that closing the file deletes the tree // so only delete if the file is still open for some reason if (rootFile_ && rootFile_->IsOpen()) { delete rootTree_; rootTree_ = 0; } delete rootFile_; rootFile_ = 0; } void LauGenNtuple::createFileAndTree() { // first check whether we've already opened up the file or not if (!rootFile_) { // if not, first check the filename and if all ok create the file if (rootFileName_ == "") { cerr<<"ERROR in LauGenNtuple::createFileAndTree : Bad filename supplied, not creating file or tree."<IsZombie() || !rootFile_->IsWritable()) { cerr<<"ERROR in LauGenNtuple::createFileAndTree : Problem opening file \""<cd(); rootTree_ = new TTree(rootTreeName_, rootTreeName_); rootTree_->SetDirectory(rootFile_); this->definedBranches(kFALSE); } } void LauGenNtuple::addIntegerBranch(const TString& name) { if (this->definedBranches()) { cerr<<"ERROR in LauGenNtuple::addIntegerBranch : Already defined branches, can't add further ones."<setIntegerBranchValue(name, 0); } void LauGenNtuple::addDoubleBranch(const TString& name) { if (this->definedBranches()) { cerr<<"ERROR in LauGenNtuple::addDoubleBranch : Already defined branches, can't add further ones."<setDoubleBranchValue(name, 0.0); } void LauGenNtuple::setIntegerBranchValue(const TString& name, Int_t value) { intVars_[name] = value; } void LauGenNtuple::setDoubleBranchValue(const TString& name, Double_t value) { doubleVars_[name] = value; } Int_t LauGenNtuple::getIntegerBranchValue(const TString& name) const { IntVarMap::const_iterator iter = intVars_.find( name ); if ( iter == intVars_.end() ) { cerr<<"ERROR in LauGenNtuple::getIntegerBranchValue : no such branch \""<second; } } Double_t LauGenNtuple::getDoubleBranchValue(const TString& name) const { DoubleVarMap::const_iterator iter = doubleVars_.find( name ); if ( iter == doubleVars_.end() ) { cerr<<"ERROR in LauGenNtuple::getDoubleBranchValue : no such branch \""<second; } } void LauGenNtuple::defineBranches() { if (this->definedBranches()) { cerr<<"ERROR in LauGenNtuple::defineBranches : Already defined branches, not doing it again."<first; Int_t * pointer = &(iter->second); TString thirdPart(name); thirdPart += "/I"; rootTree_->Branch(name, pointer, thirdPart); } for (DoubleVarMap::iterator iter = doubleVars_.begin(); iter != doubleVars_.end(); ++iter) { TString name = iter->first; Double_t * pointer = &(iter->second); TString thirdPart(name); thirdPart += "/D"; rootTree_->Branch(name, pointer, thirdPart); } this->definedBranches(kTRUE); } void LauGenNtuple::fillBranches() { if (!rootTree_) { cerr<<"ERROR in LauGenNtuple::fillBranches : Tree not created, cannot fill branches."<definedBranches()) { this->defineBranches(); } rootTree_->Fill(); } void LauGenNtuple::deleteAndRecreateTree() { if (rootTree_) { delete rootTree_; rootTree_ = 0; } this->createFileAndTree(); } Int_t LauGenNtuple::buildIndex(const TString& majorName, const TString& minorName) { if (!rootTree_) { cerr<<"ERROR in LauGenNtuple::buildIndex : Tree not created, cannot build index."<BuildIndex(majorName, minorName); } void LauGenNtuple::writeOutGenResults() { // Write out the generated ntuple // Check that the file is open if ( rootFile_ == 0 ) { cerr<<"ERROR in LauGenNtuple::writeOutGenResults : File not opened, can't write anything."<GetCurrentFile(); } rootFile_->cd(); rootTree_->Write("",TObject::kOverwrite); rootFile_->Close(); delete rootFile_; rootFile_ = 0; } void LauGenNtuple::addFriendTree(const TString& rootFileName, const TString& rootTreeName) { if (!rootTree_) { cerr<<"ERROR in LauGenNtuple::addFriendTree : Tree not created, cannot add friend."<AddFriend(rootTreeName,rootFileName); } diff --git a/src/LauGounarisSakuraiRes.cc b/src/LauGounarisSakuraiRes.cc index 643d28d..c51d355 100644 --- a/src/LauGounarisSakuraiRes.cc +++ b/src/LauGounarisSakuraiRes.cc @@ -1,284 +1,283 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauGounarisSakuraiRes.cc \brief File containing implementation of LauGounarisSakuraiRes class. */ #include #include "LauConstants.hh" #include "LauGounarisSakuraiRes.hh" -ClassImp(LauGounarisSakuraiRes) LauGounarisSakuraiRes::LauGounarisSakuraiRes(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), q0_(0.0), p0_(0.0), pstar0_(0.0), erm0_(0.0), resMass_(0.0), resMassSq_(0.0), resWidth_(0.0), resRadius_(0.0), parRadius_(0.0), mDaugSum_(0.0), mDaugSumSq_(0.0), mDaugDiff_(0.0), mDaugDiffSq_(0.0), mParentSq_(0.0), mBachSq_(0.0), h0_(0.0), dhdm0_(0.0), d_(0.0), FR0_(1.0), FP0_(1.0) { } LauGounarisSakuraiRes::~LauGounarisSakuraiRes() { } void LauGounarisSakuraiRes::initialise() { // Set-up various constants. This must be called again if the mass/width/spin // of a resonance changes... resMass_ = this->getMass(); resWidth_ = this->getWidth(); resRadius_ = this->getResRadius(); parRadius_ = this->getParRadius(); Double_t massDaug1 = this->getMassDaug1(); Double_t massDaug2 = this->getMassDaug2(); Double_t massBachelor = this->getMassBachelor(); Double_t massParent = this->getMassParent(); // Check that the spin is 1 Int_t resSpin = this->getSpin(); if (resSpin != 1) { std::cerr << "WARNING in LauGounarisSakuraiRes::initialise : Resonance spin is != 1. This lineshape is for the rho(770), setting the spin to 1." << std::endl; this->changeResonance( -1.0, -1.0, 1 ); resSpin = this->getSpin(); } // Create the mass squares, sums, differences etc. resMassSq_ = resMass_*resMass_; mDaugSum_ = massDaug1 + massDaug2; mDaugSumSq_ = mDaugSum_*mDaugSum_; mDaugDiff_ = massDaug1 - massDaug2; mDaugDiffSq_ = mDaugDiff_*mDaugDiff_; mParentSq_ = massParent*massParent; mBachSq_ = massBachelor*massBachelor; // Decay momentum of either daughter in the resonance rest frame // when resonance mass = rest-mass value, m_0 (PDG value) Double_t term1 = resMassSq_ - mDaugSumSq_; Double_t term2 = resMassSq_ - mDaugDiffSq_; Double_t term12 = term1*term2; if (term12 > 0.0) { q0_ = TMath::Sqrt(term12)/(2.0*resMass_); } else { q0_ = 0.0; } // Momentum of the bachelor particle in the resonance rest frame // when resonance mass = rest-mass value, m_0 (PDG value) Double_t eBach = (mParentSq_ - resMassSq_ - mBachSq_)/(2.0*resMass_); Double_t termBach = eBach*eBach - mBachSq_; if ( eBach<0.0 || termBach<0.0 ) { p0_ = 0.0; } else { p0_ = TMath::Sqrt( termBach ); } // Momentum of the bachelor particle in the parent rest frame // when resonance mass = rest-mass value, m_0 (PDG value) Double_t eStarBach = (mParentSq_ + mBachSq_ - resMassSq_)/(2.0*massParent); Double_t termStarBach = eStarBach*eStarBach - mBachSq_; if ( eStarBach<0.0 || termStarBach<0.0 ) { pstar0_ = 0.0; } else { pstar0_ = TMath::Sqrt( termStarBach ); } // Covariant factor when resonance mass = rest-mass value, m_0 (PDF value) erm0_ = (mParentSq_ + resMassSq_ - mBachSq_)/(2.0*massParent*resMass_); this->calcCovFactor( erm0_ ); // Calculate the Blatt-Weisskopf form factor for the case when m = m_0 FR0_ = 1.0; FP0_ = 1.0; if ( resSpin > 0 ) { const LauBlattWeisskopfFactor* resBWFactor = this->getResBWFactor(); const LauBlattWeisskopfFactor* parBWFactor = this->getParBWFactor(); FR0_ = (resBWFactor!=0) ? resBWFactor->calcFormFactor(q0_) : 1.0; switch ( parBWFactor->getRestFrame() ) { case LauBlattWeisskopfFactor::ResonanceFrame: FP0_ = (parBWFactor!=0) ? parBWFactor->calcFormFactor(p0_) : 1.0; break; case LauBlattWeisskopfFactor::ParentFrame: FP0_ = (parBWFactor!=0) ? parBWFactor->calcFormFactor(pstar0_) : 1.0; break; case LauBlattWeisskopfFactor::Covariant: { Double_t covFactor = this->getCovFactor(); if ( resSpin > 2 ) { covFactor = TMath::Power( covFactor, 1.0/resSpin ); } else if ( resSpin == 2 ) { covFactor = TMath::Sqrt( covFactor ); } FP0_ = (parBWFactor!=0) ? parBWFactor->calcFormFactor(pstar0_*covFactor) : 1.0; break; } } } // Calculate the extra things needed by the G-S shape h0_ = 2.0*LauConstants::invPi * q0_/resMass_ * TMath::Log((resMass_ + 2.0*q0_)/(2.0*LauConstants::mPi)); dhdm0_ = h0_ * (1.0/(8.0*q0_*q0_) - 1.0/(2.0*resMassSq_)) + 1.0/(LauConstants::twoPi*resMassSq_); d_ = 3.0*LauConstants::invPi * LauConstants::mPi*LauConstants::mPi/(q0_*q0_) * TMath::Log((resMass_ + 2.0*q0_)/(2.0*LauConstants::mPi)) + resMass_/(LauConstants::twoPi*q0_) - LauConstants::mPi*LauConstants::mPi*resMass_/(LauConstants::pi*q0_*q0_*q0_); } LauComplex LauGounarisSakuraiRes::resAmp(Double_t mass, Double_t spinTerm) { // This function returns the complex dynamical amplitude for a Breit-Wigner resonance, // given the invariant mass and cos(helicity) values. LauComplex resAmplitude(0.0, 0.0); if (mass < 1e-10) { std::cerr << "WARNING in LauGounarisSakuraiRes::amplitude : mass < 1e-10." << std::endl; return LauComplex(0.0, 0.0); } else if (q0_ < 1e-30) { return LauComplex(0.0, 0.0); } // Calculate the width of the resonance (as a function of mass) // First, calculate the various form factors. // NB // q is the momentum of either daughter in the resonance rest-frame, // p is the momentum of the bachelor in the resonance rest-frame, // pstar is the momentum of the bachelor in the parent rest-frame. // These quantities have been calculate in LauAbsResonance::amplitude(...) const Double_t resMass = this->getMass(); const Double_t resWidth = this->getWidth(); const Double_t resRadius = this->getResRadius(); const Double_t parRadius = this->getParRadius(); // If the mass is floating and its value has changed we need to // recalculate everything that assumes that value // Similarly for the BW radii if ( ( (!this->fixMass()) && resMass != resMass_ ) || ( (!this->fixResRadius()) && resRadius != resRadius_ ) || ( (!this->fixParRadius()) && parRadius != parRadius_ ) ) { this->initialise(); } const Int_t resSpin = this->getSpin(); const Double_t q = this->getQ(); const Double_t p = this->getP(); const Double_t pstar = this->getPstar(); Double_t fFactorR(1.0); Double_t fFactorB(1.0); if ( resSpin > 0 ) { const LauBlattWeisskopfFactor* resBWFactor = this->getResBWFactor(); const LauBlattWeisskopfFactor* parBWFactor = this->getParBWFactor(); fFactorR = (resBWFactor!=0) ? resBWFactor->calcFormFactor(q) : 1.0; switch ( parBWFactor->getRestFrame() ) { case LauBlattWeisskopfFactor::ResonanceFrame: fFactorB = (parBWFactor!=0) ? parBWFactor->calcFormFactor(p) : 1.0; break; case LauBlattWeisskopfFactor::ParentFrame: fFactorB = (parBWFactor!=0) ? parBWFactor->calcFormFactor(pstar) : 1.0; break; case LauBlattWeisskopfFactor::Covariant: { Double_t covFactor = this->getCovFactor(); if ( resSpin > 2 ) { covFactor = TMath::Power( covFactor, 1.0/resSpin ); } else if ( resSpin == 2 ) { covFactor = TMath::Sqrt( covFactor ); } fFactorB = (parBWFactor!=0) ? parBWFactor->calcFormFactor(pstar*covFactor) : 1.0; break; } } } const Double_t fFactorRRatio = fFactorR/FR0_; const Double_t fFactorBRatio = fFactorB/FP0_; const Double_t qRatio = q/q0_; const Double_t qTerm = qRatio*qRatio*qRatio; const Double_t totWidth = resWidth*qTerm*(resMass/mass)*fFactorRRatio*fFactorRRatio; const Double_t massSq = mass*mass; const Double_t massSqTerm = resMassSq_ - massSq; const Double_t h = 2.0*LauConstants::invPi * q/mass * TMath::Log((mass + 2.0*q)/(2.0*LauConstants::mPi)); const Double_t f = resWidth * resMassSq_/(q0_*q0_*q0_) * (q*q * (h - h0_) + massSqTerm * q0_*q0_ * dhdm0_); // Compute the complex amplitude resAmplitude = LauComplex(massSqTerm + f, resMass*totWidth); // Scale by the denominator factor, as well as the spin term and Blatt-Weisskopf factors Double_t numerFactor = spinTerm*(1.0 + d_ * resWidth/resMass); if (!this->ignoreBarrierScaling()) { numerFactor *= fFactorRRatio*fFactorBRatio; } const Double_t denomFactor = (massSqTerm + f)*(massSqTerm + f) + resMassSq_*totWidth*totWidth; resAmplitude.rescale(numerFactor/denomFactor); return resAmplitude; } const std::vector& LauGounarisSakuraiRes::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixMass() ) { this->addFloatingParameter( this->getMassPar() ); } if ( ! this->fixWidth() ) { this->addFloatingParameter( this->getWidthPar() ); } if ( ! this->fixResRadius() ) { this->addFloatingParameter( this->getResBWFactor()->getRadiusParameter() ); } if ( ! this->fixParRadius() ) { this->addFloatingParameter( this->getParBWFactor()->getRadiusParameter() ); } return this->getParameters(); } diff --git a/src/LauIntegrals.cc b/src/LauIntegrals.cc index 6e0f685..05aa3f7 100644 --- a/src/LauIntegrals.cc +++ b/src/LauIntegrals.cc @@ -1,178 +1,177 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauIntegrals.cc \brief File containing implementation of LauIntegrals class. */ #include using std::cout; using std::endl; #include "TMath.h" #include "LauConstants.hh" #include "LauIntegrals.hh" -ClassImp(LauIntegrals) LauIntegrals::LauIntegrals(Double_t weightsPrecision) : weightsPrecision_( weightsPrecision ) { } LauIntegrals::~LauIntegrals() { } LauIntegrals::LauIntegrals(const LauIntegrals& rhs) : weightsPrecision_( rhs.weightsPrecision_ ) { } LauIntegrals& LauIntegrals::operator=(const LauIntegrals& rhs) { if ( &rhs != this ) { weightsPrecision_ = rhs.weightsPrecision_; } return *this; } void LauIntegrals::calcGaussLegendreWeights(const Int_t numPoints, std::vector& abscissas, std::vector& weights) { // Calculate the Gauss-Legendre weights that will be used for the // simple Gaussian integration method given the number of points abscissas.clear(); weights.clear(); abscissas.resize(numPoints); weights.resize(numPoints); Int_t m = (numPoints+1)/2; Double_t dnumPoints(numPoints); Double_t dnumPointsPlusHalf = static_cast(numPoints + 0.5); Int_t i(0), j(0); Double_t p1(0.0), p2(0.0), p3(0.0), pp(0.0), z(0.0), zSq(0.0), z1(0.0), di(0.0); for (i = 1; i <= m; i++){ di = static_cast(i); z = TMath::Cos(LauConstants::pi*(di - 0.25)/dnumPointsPlusHalf); zSq = z*z; // Starting with the above approximation for the ith root, we enter the // main loop of refinement by Newton's method do{ p1 = 1.0; p2 = 0.0; // Calculate the Legendre polynomial at z - recurrence relation for (j = 1; j <= numPoints; j++){ p3 = p2; p2 = p1; p1 = (( 2.0*j - 1.0) * z * p2 - (j - 1.0)*p3)/static_cast(j); } // p1 = Legendre polynomial. Compute its derivative, pp. pp = dnumPoints * (z*p1 - p2)/(zSq - 1.0); z1 = z; z = z1 - p1/pp; // Newton's method } while (TMath::Abs(z-z1) > weightsPrecision_); // Scale the root to the desired interval // Remember that the vector entries start with 0, hence i-1 (where first i value is 1) abscissas[i-1] = z; abscissas[numPoints-i] = abscissas[i-1]; // Symmetric abscissa weights[i-1] = 2.0/((1.0 - zSq)*pp*pp); weights[numPoints-i] = weights[i-1]; // Symmetric weight } } void LauIntegrals::calcGaussHermiteWeights(const Int_t numPoints, std::vector& abscissas, std::vector& weights) { // Calculate the Gauss-Hermite weights that will be used for the // simple Gaussian integration method for a function weighted by an exp(-x**2) term // These weights are common to all integration intervals - therefore they // should only be calculated once - when the constructor is called, for example. abscissas.clear(); weights.clear(); abscissas.resize(numPoints); weights.resize(numPoints); Int_t m = (numPoints+1)/2; Double_t dnumPoints(numPoints); Int_t i(0), j(0), its(0); Double_t p1(0.0), p2(0.0), p3(0.0), pp(0.0), z(0.0), z1(0.0); Double_t numPointsTerm(2*numPoints+1); // The roots are symmetric about the origin. Therefore, we only need to find half of them // Loop over the desired roots. for (i = 1; i <= m; i++) { if (i == 1) { // Initial guess for largest root z = TMath::Sqrt(numPointsTerm) - 1.85575*TMath::Power(numPointsTerm, -0.16667); } else if (i == 2) { // Initial guess for second largest root z -= 1.14*TMath::Power(dnumPoints, 0.426)/z; } else if (i == 3) { // Initial guess for third largest root z = 1.86*z - 0.86*abscissas[0]; } else if (i == 4) { // Initial guess for fourth largest root z = 1.91*z - 0.91*abscissas[1]; } else { // Initial guess for other roots z = 2.0*z - abscissas[i-3]; } for (its = 1; its <= 10; its++) { p1 = LauConstants::pim4; p2 = 0.0; for (j = 1; j <= numPoints; j++) { Double_t dj(j); p3 = p2; p2 = p1; p1 = z*TMath::Sqrt(2.0/dj)*p2 - TMath::Sqrt((dj-1.0)/dj)*p3; } // p1 is now the desired Hermite polynomial. Compute its derivative, pp pp = TMath::Sqrt(2.0*dnumPoints)*p2; z1 = z; if (pp > 1e-10) {z = z1 - p1/pp;} if (TMath::Abs(z - z1) < weightsPrecision_) break; } // Scale the root to the desired interval // Remember that the vector entries start with 0, hence i-1 (where first i value is 1) abscissas[i-1] = z; abscissas[numPoints-i] = -z; // Symmetric abscissa weights[i-1] = 2.0/(pp*pp); weights[numPoints-i] = weights[i-1]; // Symmetric weight } } diff --git a/src/LauIsobarDynamics.cc b/src/LauIsobarDynamics.cc index 78a5810..dcf7c76 100644 --- a/src/LauIsobarDynamics.cc +++ b/src/LauIsobarDynamics.cc @@ -1,2681 +1,2680 @@ /* Copyright 2005 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauIsobarDynamics.cc \brief File containing implementation of LauIsobarDynamics class. */ #include #include #include #include #include #include "TFile.h" #include "TRandom.h" #include "TSystem.h" #include "LauAbsEffModel.hh" #include "LauAbsResonance.hh" #include "LauAbsIncohRes.hh" #include "LauBelleNR.hh" #include "LauBelleSymNR.hh" #include "LauCacheData.hh" #include "LauConstants.hh" #include "LauDaughters.hh" #include "LauDPPartialIntegralInfo.hh" #include "LauFitDataTree.hh" #include "LauIsobarDynamics.hh" #include "LauKinematics.hh" #include "LauKMatrixProdPole.hh" #include "LauKMatrixProdSVP.hh" #include "LauKMatrixPropagator.hh" #include "LauKMatrixPropFactory.hh" #include "LauNRAmplitude.hh" #include "LauPrint.hh" #include "LauRandom.hh" #include "LauResonanceInfo.hh" #include "LauResonanceMaker.hh" #include "LauRhoOmegaMix.hh" -ClassImp(LauIsobarDynamics) // for Kpipi: only one scfFraction 2D histogram is needed LauIsobarDynamics::LauIsobarDynamics(LauDaughters* daughters, LauAbsEffModel* effModel, LauAbsEffModel* scfFractionModel) : daughters_(daughters), kinematics_(daughters_ ? daughters_->getKinematics() : 0), effModel_(effModel), nAmp_(0), nIncohAmp_(0), DPNorm_(0.0), DPRate_("DPRate", 0.0, 0.0, 1000.0), meanDPEff_("meanDPEff", 0.0, 0.0, 1.0), currentEvent_(0), symmetricalDP_(kFALSE), fullySymmetricDP_(kFALSE), flavConjDP_(kFALSE), integralsDone_(kFALSE), normalizationSchemeDone_(kFALSE), forceSymmetriseIntegration_(kFALSE), intFileName_("integ.dat"), m13BinWidth_(0.005), m23BinWidth_(0.005), mPrimeBinWidth_(0.001), thPrimeBinWidth_(0.001), narrowWidth_(0.020), binningFactor_(100.0), m13Sq_(0.0), m23Sq_(0.0), mPrime_(0.0), thPrime_(0.0), tagCat_(-1), eff_(1.0), scfFraction_(0.0), jacobian_(0.0), ASq_(0.0), evtLike_(0.0), iterationsMax_(100000), nSigGenLoop_(0), aSqMaxSet_(1.25), aSqMaxVar_(0.0), flipHelicity_(kTRUE), recalcNormalisation_(kFALSE) { if (daughters != 0) { symmetricalDP_ = daughters->gotSymmetricalDP(); fullySymmetricDP_ = daughters->gotFullySymmetricDP(); flavConjDP_ = daughters->gotFlavourConjugateDP(); typDaug_.push_back(daughters->getTypeDaug1()); typDaug_.push_back(daughters->getTypeDaug2()); typDaug_.push_back(daughters->getTypeDaug3()); } if (scfFractionModel != 0) { scfFractionModel_[0] = scfFractionModel; } sigResonances_.clear(); sigIncohResonances_.clear(); kMatrixPropagators_.clear(); kMatrixPropSet_.clear(); extraParameters_.clear(); } // for Kspipi, we need a scfFraction 2D histogram for each tagging category. They are provided by the map. // Also, we need to know the place that the tagging category of the current event occupies in the data structure inputFitTree LauIsobarDynamics::LauIsobarDynamics(LauDaughters* daughters, LauAbsEffModel* effModel, LauTagCatScfFractionModelMap scfFractionModel) : daughters_(daughters), kinematics_(daughters_ ? daughters_->getKinematics() : 0), effModel_(effModel), scfFractionModel_(scfFractionModel), nAmp_(0), nIncohAmp_(0), DPNorm_(0.0), DPRate_("DPRate", 0.0, 0.0, 1000.0), meanDPEff_("meanDPEff", 0.0, 0.0, 1.0), currentEvent_(0), symmetricalDP_(kFALSE), fullySymmetricDP_(kFALSE), flavConjDP_(kFALSE), integralsDone_(kFALSE), normalizationSchemeDone_(kFALSE), forceSymmetriseIntegration_(kFALSE), intFileName_("integ.dat"), m13BinWidth_(0.005), m23BinWidth_(0.005), mPrimeBinWidth_(0.001), thPrimeBinWidth_(0.001), narrowWidth_(0.020), binningFactor_(100.0), m13Sq_(0.0), m23Sq_(0.0), mPrime_(0.0), thPrime_(0.0), tagCat_(-1), eff_(1.0), scfFraction_(0.0), jacobian_(0.0), ASq_(0.0), evtLike_(0.0), iterationsMax_(100000), nSigGenLoop_(0), aSqMaxSet_(1.25), aSqMaxVar_(0.0), flipHelicity_(kTRUE), recalcNormalisation_(kFALSE) { // Constructor for the isobar signal model if (daughters != 0) { symmetricalDP_ = daughters->gotSymmetricalDP(); fullySymmetricDP_ = daughters->gotFullySymmetricDP(); flavConjDP_ = daughters->gotFlavourConjugateDP(); typDaug_.push_back(daughters->getTypeDaug1()); typDaug_.push_back(daughters->getTypeDaug2()); typDaug_.push_back(daughters->getTypeDaug3()); } sigResonances_.clear(); sigIncohResonances_.clear(); kMatrixPropagators_.clear(); kMatrixPropSet_.clear(); extraParameters_.clear(); } LauIsobarDynamics::~LauIsobarDynamics() { extraParameters_.clear(); for ( std::vector::iterator iter = data_.begin(); iter != data_.end(); ++iter ) { delete (*iter); } data_.clear(); for (std::vector::iterator it = dpPartialIntegralInfo_.begin(); it != dpPartialIntegralInfo_.end(); ++it) { delete (*it); } dpPartialIntegralInfo_.clear(); } void LauIsobarDynamics::resetNormVectors() { for (UInt_t i = 0; i < nAmp_; i++) { fSqSum_[i] = 0.0; fSqEffSum_[i] = 0.0; fNorm_[i] = 0.0; ff_[i].zero(); for (UInt_t j = 0; j < nAmp_; j++) { fifjEffSum_[i][j].zero(); fifjSum_[i][j].zero(); } } for (UInt_t i = 0; i < nIncohAmp_; i++) { fSqSum_[i+nAmp_] = 0.0; fSqEffSum_[i+nAmp_] = 0.0; fNorm_[i+nAmp_] = 0.0; incohInten_[i] = 0.0; } } void LauIsobarDynamics::recalculateNormalisation() { if ( recalcNormalisation_ == kFALSE ) { return; } // We need to calculate the normalisation constants for the // Dalitz plot generation/fitting. integralsDone_ = kFALSE; this->resetNormVectors(); this->findIntegralsToBeRecalculated(); this->calcDPNormalisation(); integralsDone_ = kTRUE; } void LauIsobarDynamics::findIntegralsToBeRecalculated() { // Loop through the resonance parameters and see which ones have changed // For those that have changed mark the corresponding resonance(s) as needing to be re-evaluated integralsToBeCalculated_.clear(); const UInt_t nResPars = resonancePars_.size(); for ( UInt_t iPar(0); iPar < nResPars; ++iPar ) { const Double_t newValue = resonancePars_[iPar]->value(); if ( newValue != resonanceParValues_[iPar] ) { resonanceParValues_[iPar] = newValue; const std::vector& indices = resonanceParResIndex_[iPar]; std::vector::const_iterator indexIter = indices.begin(); const std::vector::const_iterator indexEnd = indices.end(); for( ; indexIter != indexEnd; ++indexIter) { integralsToBeCalculated_.insert(*indexIter); } } } } void LauIsobarDynamics::collateResonanceParameters() { // Initialise all resonance models resonancePars_.clear(); resonanceParValues_.clear(); resonanceParResIndex_.clear(); std::set uniqueResPars; UInt_t resIndex(0); for ( std::vector::iterator resIter = sigResonances_.begin(); resIter != sigResonances_.end(); ++resIter ) { (*resIter)->initialise(); // Check if this resonance has floating parameters // Append all unique parameters to our list const std::vector& resPars = (*resIter)->getFloatingParameters(); for ( std::vector::const_iterator parIter = resPars.begin(); parIter != resPars.end(); ++parIter ) { if ( uniqueResPars.insert( *parIter ).second ) { // This parameter has not already been added to // the list of unique ones. Add it, its value // and its associated resonance ID to the // appropriate lists. resonancePars_.push_back( *parIter ); resonanceParValues_.push_back( (*parIter)->value() ); std::vector resIndices( 1, resIndex ); resonanceParResIndex_.push_back( resIndices ); } else { // This parameter has already been added to the // list of unique ones. However, we still need // to indicate that this resonance should be // associated with it. std::vector::const_iterator uniqueParIter = resonancePars_.begin(); std::vector >::iterator indicesIter = resonanceParResIndex_.begin(); while( (*uniqueParIter) != (*parIter) ) { ++uniqueParIter; ++indicesIter; } ( *indicesIter ).push_back( resIndex ); } } ++resIndex; } for ( std::vector::iterator resIter = sigIncohResonances_.begin(); resIter != sigIncohResonances_.end(); ++resIter ) { (*resIter)->initialise(); // Check if this resonance has floating parameters // Append all unique parameters to our list const std::vector& resPars = (*resIter)->getFloatingParameters(); for ( std::vector::const_iterator parIter = resPars.begin(); parIter != resPars.end(); ++parIter ) { if ( uniqueResPars.insert( *parIter ).second ) { // This parameter has not already been added to // the list of unique ones. Add it, its value // and its associated resonance ID to the // appropriate lists. resonancePars_.push_back( *parIter ); resonanceParValues_.push_back( (*parIter)->value() ); std::vector resIndices( 1, resIndex ); resonanceParResIndex_.push_back( resIndices ); } else { // This parameter has already been added to the // list of unique ones. However, we still need // to indicate that this resonance should be // associated with it. std::vector::const_iterator uniqueParIter = resonancePars_.begin(); std::vector >::iterator indicesIter = resonanceParResIndex_.begin(); while( (*uniqueParIter) != (*parIter) ) { ++uniqueParIter; ++indicesIter; } ( *indicesIter ).push_back( resIndex ); } } ++resIndex; } } void LauIsobarDynamics::initialise(const std::vector& coeffs) { // Check whether we have a valid set of integration constants for // the normalisation of the signal likelihood function. this->initialiseVectors(); // Mark the DP integrals as undetermined integralsDone_ = kFALSE; this->collateResonanceParameters(); if ( resonancePars_.empty() ) { recalcNormalisation_ = kFALSE; } else { recalcNormalisation_ = kTRUE; } // Print summary of what we have so far to screen this->initSummary(); if ( nAmp_+nIncohAmp_ == 0 ) { std::cout << "INFO in LauIsobarDynamics::initialise : No contributions to DP model, not performing normalisation integrals." << std::endl; } else { // We need to calculate the normalisation constants for the Dalitz plot generation/fitting. std::cout<<"INFO in LauIsobarDynamics::initialise : Starting special run to generate the integrals for normalising the PDF..."<calcDPNormalisation(); // Write the integrals to a file (mainly for debugging purposes) this->writeIntegralsFile(); } integralsDone_ = kTRUE; std::cout << std::setprecision(10); std::cout<<"INFO in LauIsobarDynamics::initialise : Summary of the integrals:"<getResonanceModel(); getChar << resModelInt << " "; } getChar << std::endl; // Write out the track pairings for each resonance. This is specified // by the resPairAmpInt integer in the addResonance function. for (i = 0; i < nAmp_; i++) { getChar << resPairAmp_[i] << " "; } getChar << std::endl; // Write out the fSqSum = |ff|^2, where ff = resAmp() for (i = 0; i < nAmp_; i++) { getChar << fSqSum_[i] << " "; } getChar << std::endl; // Similar to fSqSum, but with the efficiency term included. for (i = 0; i < nAmp_; i++) { getChar << fSqEffSum_[i] << " "; } getChar << std::endl; // Write out the f_i*f_j_conj*eff values = resAmp_i*resAmp_j_conj*eff. // Note that only the top half of the i*j "matrix" is required, as it // is symmetric w.r.t i, j. for (i = 0; i < nAmp_; i++) { for (j = i; j < nAmp_; j++) { getChar << fifjEffSum_[i][j] << " "; } } getChar << std::endl; // Similar to fifjEffSum, but without the efficiency term included. for (i = 0; i < nAmp_; i++) { for (j = i; j < nAmp_; j++) { getChar << fifjSum_[i][j] << " "; } } getChar << std::endl; // Write out number of incoherent resonances in the Dalitz plot model getChar << nIncohAmp_ << std::endl; // Write out the incoherent resonances for (i = 0; i < nIncohAmp_; i++) { getChar << incohResTypAmp_[i] << " "; } getChar << std::endl; // Write out the incoherent resonance model types (BW, RelBW etc...) for (i = 0; i < nIncohAmp_; i++) { LauAbsResonance* theResonance = sigIncohResonances_[i]; Int_t resModelInt = theResonance->getResonanceModel(); getChar << resModelInt << " "; } getChar << std::endl; // Write out the track pairings for each incoherent resonance. This is specified // by the resPairAmpInt integer in the addIncohResonance function. for (i = 0; i < nIncohAmp_; i++) { getChar << incohResPairAmp_[i] << " "; } getChar << std::endl; // Write out the fSqSum = |ff|^2, where |ff|^2 = incohResAmp() for (i = nAmp_; i < nAmp_+nIncohAmp_; i++) { getChar << fSqSum_[i] << " "; } getChar << std::endl; // Similar to fSqSum, but with the efficiency term included. for (i = nAmp_; i < nAmp_+nIncohAmp_; i++) { getChar << fSqEffSum_[i] << " "; } getChar << std::endl; } LauAbsResonance* LauIsobarDynamics::addResonance(const TString& resName, const Int_t resPairAmpInt, const LauAbsResonance::LauResonanceModel resType, const LauBlattWeisskopfFactor::BlattWeisskopfCategory bwCategory) { // Function to add a resonance in a Dalitz plot. // No check is made w.r.t flavour and charge conservation rules, and so // the user is responsible for checking the internal consistency of // their function statements with these laws. For example, the program // will not prevent the user from asking for a rho resonance in a K-pi // pair or a K* resonance in a pi-pi pair. // However, to assist the user, a summary of the resonant structure requested // by the user is printed before the program runs. It is important to check this // information when you first define your Dalitz plot model before doing // any fitting/generating. // Arguments are: resonance name, integer to specify the resonance track pairing // (1 => m_23, 2 => m_13, 3 => m_12), i.e. the bachelor track number. // The third argument resType specifies whether the resonance is a Breit-Wigner (BW) // Relativistic Breit-Wigner (RelBW) or Flatte distribution (Flatte), for example. if( LauAbsResonance::isIncoherentModel(resType) == true ) { std::cerr<<"ERROR in LauIsobarDynamics::addResonance : Resonance type \""<getCharge(resPairAmpInt) == 0 && daughters_->getChargeParent() == 0 && daughters_->getTypeParent() > 0 ) { if ( ( resPairAmpInt == 1 && TMath::Abs(daughters_->getTypeDaug2()) == TMath::Abs(daughters_->getTypeDaug3()) ) || ( resPairAmpInt == 2 && TMath::Abs(daughters_->getTypeDaug1()) == TMath::Abs(daughters_->getTypeDaug3()) ) || ( resPairAmpInt == 3 && TMath::Abs(daughters_->getTypeDaug1()) == TMath::Abs(daughters_->getTypeDaug2()) ) ) { theResonance->flipHelicity(kTRUE); } } // Set the resonance name and what track is the bachelor TString resonanceName = theResonance->getResonanceName(); resTypAmp_.push_back(resonanceName); // Always force the non-resonant amplitude pair to have resPairAmp = 0 // in case the user chooses the wrong number. if ( resType == LauAbsResonance::FlatNR || resType == LauAbsResonance::NRModel ) { std::cout<<"INFO in LauIsobarDynamics::addResonance : Setting resPairAmp to 0 for "<( resonanceMaker.getResonance(daughters_, resName, resPairAmpInt, resType) ); if (theResonance == 0) { std::cerr<<"ERROR in LauIsobarDynamics::addIncohResonance : Couldn't create the resonance \""<getResonanceName(); incohResTypAmp_.push_back(resonanceName); incohResPairAmp_.push_back(resPairAmpInt); // Increment the number of resonance amplitudes we have so far ++nIncohAmp_; // Finally, add the resonance object to the internal array sigIncohResonances_.push_back(theResonance); std::cout<<"INFO in LauIsobarDynamics::addIncohResonance : Successfully added incoherent resonance. Total number of incoherent resonances so far = "< nChannels) { std::cerr << "ERROR in LauIsobarDynamics::defineKMatrixPropagator. The rowIndex, which is set to " << rowIndex << ", must be between 1 and the number of channels " << nChannels << std::endl; gSystem->Exit(EXIT_FAILURE); } TString propagatorName(propName), parameterFile(paramFileName); LauKMatrixPropagator* thePropagator = LauKMatrixPropFactory::getInstance()->getPropagator(propagatorName, parameterFile, resPairAmpInt, nChannels, nPoles, rowIndex); kMatrixPropagators_[propagatorName] = thePropagator; } void LauIsobarDynamics::addKMatrixProdPole(const TString& poleName, const TString& propName, Int_t poleIndex, Bool_t useProdAdler) { // Add a K-matrix production pole term, using the K-matrix propagator given by the propName. // Here, poleIndex is the integer specifying the pole number. // First, find the K-matrix propagator. KMPropMap::iterator mapIter = kMatrixPropagators_.find(propName); if (mapIter != kMatrixPropagators_.end()) { LauKMatrixPropagator* thePropagator = mapIter->second; // Make sure the pole index is valid Int_t nPoles = thePropagator->getNPoles(); if (poleIndex < 1 || poleIndex > nPoles) { std::cerr<<"ERROR in LauIsobarDynamics::addKMatrixProdPole : The pole index "<getResPairAmpInt(); LauAbsResonance* prodPole = new LauKMatrixProdPole(poleName, poleIndex, resPairAmpInt, thePropagator, daughters_, useProdAdler); resTypAmp_.push_back(poleName); resPairAmp_.push_back(resPairAmpInt); ++nAmp_; sigResonances_.push_back(prodPole); // Also store the propName-poleName pair for calculating total fit fractions later on // (avoiding the need to use dynamic casts to check which resonances are of the K-matrix type) kMatrixPropSet_[poleName] = propName; std::cout<<"INFO in LauIsobarDynamics::addKMatrixProdPole : Successfully added K-matrix production pole term. Total number of resonances so far = "<second; // Make sure the channel index is valid Int_t nChannels = thePropagator->getNChannels(); if (channelIndex < 1 || channelIndex > nChannels) { std::cerr<<"ERROR in LauIsobarDynamics::addKMatrixProdSVP : The channel index "<getResPairAmpInt(); LauAbsResonance* prodSVP = new LauKMatrixProdSVP(SVPName, channelIndex, resPairAmpInt, thePropagator, daughters_, useProdAdler); resTypAmp_.push_back(SVPName); resPairAmp_.push_back(resPairAmpInt); ++nAmp_; sigResonances_.push_back(prodSVP); // Also store the SVPName-propName pair for calculating total fit fractions later on // (avoiding the need to use dynamic casts to check which resonances are of the K-matrix type) kMatrixPropSet_[SVPName] = propName; std::cout<<"INFO in LauIsobarDynamics::addKMatrixProdSVP : Successfully added K-matrix production slowly-varying (SVP) term. Total number of resonances so far = "<::const_iterator iter=sigResonances_.begin(); iter!=sigResonances_.end(); ++iter) { theResonance = (*iter); if (theResonance != 0) { const TString& resString = theResonance->getResonanceName(); if (resString == resName) { return index; } } ++index; } for (std::vector::const_iterator iter=sigIncohResonances_.begin(); iter!=sigIncohResonances_.end(); ++iter) { theResonance = (*iter); if (theResonance != 0) { const TString& resString = theResonance->getResonanceName(); if (resString == resName) { return index; } } ++index; } return -1; } Bool_t LauIsobarDynamics::hasResonance(const TString& resName) const { const Int_t index = this->resonanceIndex(resName); if (index < 0) { return kFALSE; } else { return kTRUE; } } const LauAbsResonance* LauIsobarDynamics::getResonance(const UInt_t resIndex) const { if ( resIndex < this->getnCohAmp() ) { return sigResonances_[resIndex]; } else if ( resIndex < this->getnTotAmp() ) { return sigIncohResonances_[ resIndex - nAmp_ ]; } else { std::cerr<<"ERROR in LauIsobarDynamics::getResonance : Couldn't find resonance with index \""<getnCohAmp() ) { return sigResonances_[resIndex]; } else if ( resIndex < this->getnTotAmp() ) { return sigIncohResonances_[ resIndex - nAmp_ ]; } else { std::cerr<<"ERROR in LauIsobarDynamics::getResonance : Couldn't find resonance with index \""<resonanceIndex( resName ); if ( index < 0 ) { std::cerr<<"ERROR in LauIsobarDynamics::findResonance : Couldn't find resonance with name \""<getResonance( index ); } } const LauAbsResonance* LauIsobarDynamics::findResonance(const TString& resName) const { const Int_t index = this->resonanceIndex( resName ); if ( index < 0 ) { std::cerr<<"ERROR in LauIsobarDynamics::findResonance : Couldn't find resonance with name \""<getResonance( index ); } } void LauIsobarDynamics::removeCharge(TString& string) const { Ssiz_t index = string.Index("+"); if (index != -1) { string.Remove(index,1); } index = string.Index("-"); if (index != -1) { string.Remove(index,1); } } void LauIsobarDynamics::calcDPNormalisation() { if (!normalizationSchemeDone_) { this->calcDPNormalisationScheme(); } for (std::vector::iterator it = dpPartialIntegralInfo_.begin(); it != dpPartialIntegralInfo_.end(); ++it) { this->calcDPPartialIntegral( *it ); } for (UInt_t i = 0; i < nAmp_+nIncohAmp_; ++i) { fNorm_[i] = 0.0; if (fSqSum_[i] > 0.0) {fNorm_[i] = TMath::Sqrt(1.0/(fSqSum_[i]));} } } std::vector< std::pair > LauIsobarDynamics::formGapsFromRegions( const std::vector< std::pair >& regions, const Double_t min, const Double_t max ) const { std::vector< std::pair > gaps(regions.size() + 1, std::make_pair(0., 0.)); // Given some narrow resonance regions, find the regions that correspond to the gaps between them gaps[0].first = min; for (UInt_t i = 0; i < regions.size(); ++i) { gaps[i].second = regions[i].first; gaps[i + 1].first = regions[i].second; } gaps[gaps.size() - 1].second = max; return gaps; } void LauIsobarDynamics::cullNullRegions( std::vector& regions ) const { LauDPPartialIntegralInfo* tmp(0); regions.erase( std::remove(regions.begin(), regions.end(), tmp), regions.end() ); } void LauIsobarDynamics::correctDPOverlap( std::vector< std::pair >& regions, const std::vector& binnings ) const { if (regions.empty()) { return; } // If the regions overlap, ensure that the one with the finest binning takes precedence (i.e., extends its full width) for (UInt_t i = 0; i < regions.size() - 1; ++i) { if ( regions[i + 1].first <= regions[i].second ) { if ((binnings[i] < binnings[i + 1])) { regions[i + 1] = std::make_pair(regions[i].second, regions[i + 1].second); } else { regions[i] = std::make_pair(regions[i].first, regions[i + 1].first); } } } } std::vector LauIsobarDynamics::m13IntegrationRegions( const std::vector< std::pair >& m13Regions, const std::vector< std::pair >& m23Regions, const std::vector& m13Binnings, const Double_t precision, const Double_t defaultBinning ) const { // Create integration regions for all narrow resonances in m13 except for the overlaps with narrow resonances in m23 std::vector integrationRegions; const Double_t m23Min = kinematics_->getm23Min(); const Double_t m23Max = kinematics_->getm23Max(); // Loop over narrow resonances in m13 for (UInt_t m13i = 0; m13i < m13Regions.size(); ++m13i) { const Double_t m13Binning = m13Binnings[m13i]; const Double_t resMin13 = m13Regions[m13i].first; const Double_t resMax13 = m13Regions[m13i].second; // Initialise to the full height of the DP in case there are no narrow resonances in m23 Double_t lastResMax23 = m23Min; // Loop over narrow resonances in m23 for (UInt_t m23i = 0; m23i < m23Regions.size(); m23i++) { const Double_t resMin23 = m23Regions[m23i].first; const Double_t resMax23 = m23Regions[m23i].second; // For the first entry, add the area between m23 threshold and this first entry if (m23i == 0) { integrationRegions.push_back(this->newDPIntegrationRegion(resMin13, resMax13, m23Min, resMin23, m13Binning, defaultBinning, precision, nAmp_, nIncohAmp_)); } // For all entries except the last one, add the area between this and the next entry if (m23i != (m23Regions.size() - 1)) { const Double_t nextResMin23 = m23Regions[m23i + 1].first; integrationRegions.push_back(this->newDPIntegrationRegion(resMin13, resMax13, resMax23, nextResMin23, m13Binning, defaultBinning, precision, nAmp_, nIncohAmp_)); } else { lastResMax23 = resMax23; } } // Add the area between the last entry and the maximum m23 (which could be the whole strip if there are no entries in m23Regions) integrationRegions.push_back(this->newDPIntegrationRegion(resMin13, resMax13, lastResMax23, m23Max, m13Binning, defaultBinning, precision, nAmp_, nIncohAmp_)); } return integrationRegions; } std::vector LauIsobarDynamics::m23IntegrationRegions( const std::vector >& m13Regions, const std::vector >& m23Regions, const std::vector& m13Binnings, const std::vector& m23Binnings, const Double_t precision, const Double_t defaultBinning ) const { // Create integration regions for all narrow resonances in m23 (including the overlap regions with m13 narrow resonances) std::vector integrationRegions; const Double_t m13Min = kinematics_->getm13Min(); const Double_t m13Max = kinematics_->getm13Max(); // Loop over narrow resonances in m23 for (UInt_t m23i = 0; m23i < m23Regions.size(); m23i++) { const Double_t m23Binning = m23Binnings[m23i]; const Double_t resMin23 = m23Regions[m23i].first; const Double_t resMax23 = m23Regions[m23i].second; // Initialise to the full width of the DP in case there are no narrow resonances in m13 Double_t lastResMax13 = m13Min; // Loop over narrow resonances in m13 for (UInt_t m13i = 0; m13i < m13Regions.size(); m13i++){ const Double_t m13Binning = m13Binnings[m23i]; const Double_t resMin13 = m13Regions[m13i].first; const Double_t resMax13 = m13Regions[m13i].second; // Overlap region (only needed in m23) integrationRegions.push_back(this->newDPIntegrationRegion(resMin13, resMax13, resMin23, resMax23, m13Binning, m23Binning, precision, nAmp_, nIncohAmp_)); // For the first entry, add the area between m13 threshold and this first entry if (m13i == 0) { integrationRegions.push_back(this->newDPIntegrationRegion(m13Min, resMin13, resMin23, resMax23, defaultBinning, m23Binning, precision, nAmp_, nIncohAmp_)); } // For all entries except the last one, add the area between this and the next entry if (m13i != m13Regions.size() - 1) { const Double_t nextResMin13 = m23Regions[m13i + 1].first; integrationRegions.push_back(this->newDPIntegrationRegion(resMax13, nextResMin13, resMin23, resMax23, defaultBinning, m23Binning, precision, nAmp_, nIncohAmp_)); } else { lastResMax13 = resMax13; } } // Add the area between the last entry and the maximum m13 (which could be the whole strip if there are no entries in m13Regions) integrationRegions.push_back(this->newDPIntegrationRegion(lastResMax13, m13Max, resMin23, resMax23, defaultBinning, m23Binning, precision, nAmp_, nIncohAmp_)); } return integrationRegions; } LauDPPartialIntegralInfo* LauIsobarDynamics::newDPIntegrationRegion( const Double_t minm13, const Double_t maxm13, const Double_t minm23, const Double_t maxm23, const Double_t m13BinWidth, const Double_t m23BinWidth, const Double_t precision, const UInt_t nAmp, const UInt_t nIncohAmp ) const { const UInt_t nm13Points = static_cast((maxm13-minm13)/m13BinWidth); const UInt_t nm23Points = static_cast((maxm23-minm23)/m23BinWidth); // If we would create a region with no interior points, just return a null pointer if (nm13Points == 0 || nm23Points == 0) { return 0; } return new LauDPPartialIntegralInfo(minm13, maxm13, minm23, maxm23, m13BinWidth, m23BinWidth, precision, nAmp, nIncohAmp); } void LauIsobarDynamics::calcDPNormalisationScheme() { if ( ! dpPartialIntegralInfo_.empty() ) { std::cerr << "ERROR in LauIsobarDynamics::calcDPNormalisationScheme : Scheme already stored!" << std::endl; return; } // The precision for the Gauss-Legendre weights const Double_t precision(1e-6); // Get the rectangle that encloses the DP const Double_t minm13 = kinematics_->getm13Min(); const Double_t maxm13 = kinematics_->getm13Max(); const Double_t minm23 = kinematics_->getm23Min(); const Double_t maxm23 = kinematics_->getm23Max(); const Double_t minm12 = kinematics_->getm12Min(); const Double_t maxm12 = kinematics_->getm12Max(); // Find out whether we have narrow resonances in the DP (defined here as width < 20 MeV). std::vector< std::pair > m13NarrowRes; std::vector< std::pair > m23NarrowRes; std::vector< std::pair > m12NarrowRes; // Rho-omega mixing models implicitly contains omega(782) model, but width is of rho(770) - handle as a special case LauResonanceMaker& resonanceMaker = LauResonanceMaker::get(); LauResonanceInfo* omega_info = resonanceMaker.getResInfo("omega(782)"); const Double_t omegaMass = (omega_info!=0) ? omega_info->getMass()->unblindValue() : 0.78265; const Double_t omegaWidth = (omega_info!=0) ? omega_info->getWidth()->unblindValue() : 0.00849; for ( std::vector::const_iterator iter = sigResonances_.begin(); iter != sigResonances_.end(); ++iter ) { LauAbsResonance::LauResonanceModel model = (*iter)->getResonanceModel(); const TString& name = (*iter)->getResonanceName(); Int_t pair = (*iter)->getPairInt(); Double_t mass = (*iter)->getMass(); Double_t width = (*iter)->getWidth(); if ( model == LauAbsResonance::RhoOmegaMix_GS || model == LauAbsResonance::RhoOmegaMix_GS_1 || model == LauAbsResonance::RhoOmegaMix_RBW || model == LauAbsResonance::RhoOmegaMix_RBW_1 ) { mass = omegaMass; width = omegaWidth; } if ( width > narrowWidth_ || width == 0.0 ) { continue; } std::cout << "INFO in LauIsobarDynamics::calcDPNormalisationScheme : Found narrow resonance: " << name << ", mass = " << mass << ", width = " << width << ", pair int = " << pair << std::endl; if ( pair == 1 ) { if ( mass < minm23 || mass > maxm23 ){ std::cout << std::string(53, ' ') << ": But its pole is outside the kinematically allowed range, so will not consider it narrow for the purposes of integration" << std::endl; } else { m23NarrowRes.push_back( std::make_pair(mass,width) ); if ( fullySymmetricDP_ ) { m13NarrowRes.push_back( std::make_pair(mass,width) ); m12NarrowRes.push_back( std::make_pair(mass,width) ); } else if ( symmetricalDP_ || ( flavConjDP_ && forceSymmetriseIntegration_ ) ) { m13NarrowRes.push_back( std::make_pair(mass,width) ); } } } else if ( pair == 2 ) { if ( mass < minm13 || mass > maxm13 ){ std::cout << std::string(53, ' ') << ": But its pole is outside the kinematically allowed range, so will not consider it narrow for the purposes of integration" << std::endl; } else { m13NarrowRes.push_back( std::make_pair(mass,width) ); if ( fullySymmetricDP_ ) { m23NarrowRes.push_back( std::make_pair(mass,width) ); m12NarrowRes.push_back( std::make_pair(mass,width) ); } else if ( symmetricalDP_ || ( flavConjDP_ && forceSymmetriseIntegration_ ) ) { m23NarrowRes.push_back( std::make_pair(mass,width) ); } } } else if ( pair == 3 ) { if ( mass < minm12 || mass > maxm12 ){ std::cout << std::string(53, ' ') << ": But its pole is outside the kinematically allowed range, so will not consider it narrow for the purposes of integration" << std::endl; } else { m12NarrowRes.push_back( std::make_pair(mass,width) ); if ( fullySymmetricDP_ ) { m13NarrowRes.push_back( std::make_pair(mass,width) ); m12NarrowRes.push_back( std::make_pair(mass,width) ); } } } else { std::cerr << "WARNING in LauIsobarDynamics::calcDPNormalisationScheme : strange pair integer, " << pair << ", for resonance \"" << (*iter)->getResonanceName() << std::endl; } } for ( std::vector::const_iterator iter = sigIncohResonances_.begin(); iter != sigIncohResonances_.end(); ++iter ) { const TString& name = (*iter)->getResonanceName(); Int_t pair = (*iter)->getPairInt(); Double_t mass = (*iter)->getMass(); Double_t width = (*iter)->getWidth(); if ( width > narrowWidth_ || width == 0.0 ) { continue; } std::cout<<"INFO in LauIsobarDynamics::calcDPNormalisationScheme : Found narrow resonance: " << name << ", mass = " << mass << ", width = " << width << ", pair int = " << pair << std::endl; if ( pair == 1 ) { if ( mass < minm23 || mass > maxm23 ){ std::cout << std::string(53, ' ') << ": But its pole is outside the kinematically allowed range, so will not consider it narrow for the purposes of integration" << std::endl; } else { m23NarrowRes.push_back( std::make_pair(mass,width) ); if ( fullySymmetricDP_ ) { m13NarrowRes.push_back( std::make_pair(mass,width) ); m12NarrowRes.push_back( std::make_pair(mass,width) ); } else if ( symmetricalDP_ || ( flavConjDP_ && forceSymmetriseIntegration_ ) ) { m13NarrowRes.push_back( std::make_pair(mass,width) ); } } } else if ( pair == 2 ) { if ( mass < minm13 || mass > maxm13 ){ std::cout << std::string(53, ' ') << ": But its pole is outside the kinematically allowed range, so will not consider it narrow for the purposes of integration" << std::endl; } else { m13NarrowRes.push_back( std::make_pair(mass,width) ); if ( fullySymmetricDP_ ) { m23NarrowRes.push_back( std::make_pair(mass,width) ); m12NarrowRes.push_back( std::make_pair(mass,width) ); } else if ( symmetricalDP_ || ( flavConjDP_ && forceSymmetriseIntegration_ ) ) { m23NarrowRes.push_back( std::make_pair(mass,width) ); } } } else if ( pair == 3 ) { if ( mass < minm12 || mass > maxm12 ){ std::cout << std::string(53, ' ') << ": But its pole is outside the kinematically allowed range, so will not consider it narrow for the purposes of integration" << std::endl; } else { m12NarrowRes.push_back( std::make_pair(mass,width) ); if ( fullySymmetricDP_ ) { m13NarrowRes.push_back( std::make_pair(mass,width) ); m12NarrowRes.push_back( std::make_pair(mass,width) ); } } } else { std::cerr << "WARNING in LauIsobarDynamics::calcDPNormalisationScheme : strange pair integer, " << pair << ", for resonance \"" << (*iter)->getResonanceName() << std::endl; } } // Depending on how many narrow resonances we have and where they are // we adopt different approaches if ( ! m12NarrowRes.empty() ) { // We have at least one narrow resonance in m12 // Switch to using the square DP for the integration // TODO - for the time being just use a single, reasonably fine by default and tunable, grid // - can later consider whether there's a need to split up the mPrime axis into regions around particularly narrow resonances in m12 // - but it seems that this isn't really needed since even the default tune gives a good resolution for most narrow resonances such as phi / chi_c0 std::cout<<"INFO in LauIsobarDynamics::calcDPNormalisationScheme : One or more narrow resonances found in m12, integrating over whole square Dalitz plot with bin widths of "<squareDP() ) { std::cerr << "WARNING in LauIsobarDynamics::calcDPNormalisationScheme : forcing kinematics to calculate the required square DP co-ordinates" << std::endl; kinematics_->squareDP(kTRUE); } dpPartialIntegralInfo_.push_back(new LauDPPartialIntegralInfo(0.0, 1.0, 0.0, 1.0, mPrimeBinWidth_, thPrimeBinWidth_, precision, nAmp_, nIncohAmp_, kTRUE, kinematics_)); } else if (m13NarrowRes.empty() && m23NarrowRes.empty()) { // There are no narrow resonances, so we just do a single grid over the whole DP std::cout << "INFO in LauIsobarDynamics::calcDPNormalisationScheme : No narrow resonances found, integrating over whole Dalitz plot..." << std::endl; dpPartialIntegralInfo_.push_back(new LauDPPartialIntegralInfo(minm13, maxm13, minm23, maxm23, m13BinWidth_, m23BinWidth_, precision, nAmp_, nIncohAmp_)); } else { // Get regions in that correspond to narrow resonances in m13 and m23, and correct for overlaps in each dimension (to use the finest binning) // Sort resonances by ascending mass to calculate regions properly std::sort(m13NarrowRes.begin(), m13NarrowRes.end()); std::sort(m23NarrowRes.begin(), m23NarrowRes.end()); // For each narrow resonance in m13, determine the corresponding window and its binning std::vector > m13Regions; std::vector m13Binnings; for ( std::vector >::const_iterator iter = m13NarrowRes.begin(); iter != m13NarrowRes.end(); ++iter ) { Double_t mass = iter->first; Double_t width = iter->second; Double_t regionBegin = mass - 5.0 * width; Double_t regionEnd = mass + 5.0 * width; Double_t binning = width / binningFactor_; // check if we ought to extend the region to the edge of the phase space (in either direction) if ( regionBegin < (minm13+50.0*m13BinWidth_) ) { std::cout << "INFO in LauIsobarDynamics::calcDPNormalisationScheme : Resonance at m13 = " << mass << " is close to threshold, extending integration region" << std::endl; regionBegin = minm13; } if ( regionEnd > (maxm13-50.0*m13BinWidth_) ) { std::cout << "INFO in LauIsobarDynamics::calcDPNormalisationScheme : Resonance at m13 = " << mass << " is close to upper edge of phase space, extending integration region" << std::endl; regionEnd = maxm13; } m13Regions.push_back(std::make_pair(regionBegin, regionEnd)); m13Binnings.push_back(binning); } // For each narrow resonance in m23, determine the corresponding window and its binning std::vector > m23Regions; std::vector m23Binnings; for ( std::vector >::const_iterator iter = m23NarrowRes.begin(); iter != m23NarrowRes.end(); ++iter ) { Double_t mass = iter->first; Double_t width = iter->second; Double_t regionBegin = mass - 5.0 * width; Double_t regionEnd = mass + 5.0 * width; Double_t binning = width / binningFactor_; // check if we ought to extend the region to the edge of the phase space (in either direction) if ( regionBegin < (minm23+50.0*m23BinWidth_) ) { std::cout << "INFO in LauIsobarDynamics::calcDPNormalisationScheme : Resonance at m23 = " << mass << " is close to threshold, extending integration region" << std::endl; regionBegin = minm23; } if ( regionEnd > (maxm23-50.0*m23BinWidth_) ) { std::cout << "INFO in LauIsobarDynamics::calcDPNormalisationScheme : Resonance at m23 = " << mass << " is close to upper edge of phase space, extending integration region" << std::endl; regionEnd = maxm23; } m23Regions.push_back(std::make_pair(regionBegin, regionEnd)); m23Binnings.push_back(binning); } // Sort out overlaps between regions in the same mass pairing this->correctDPOverlap(m13Regions, m13Binnings); this->correctDPOverlap(m23Regions, m23Binnings); // Get the narrow resonance regions plus any overlap region std::vector fineScheme13 = this->m13IntegrationRegions(m13Regions, m23Regions, m13Binnings, precision, m13BinWidth_); std::vector fineScheme23 = this->m23IntegrationRegions(m13Regions, m23Regions, m13Binnings, m23Binnings, precision, m23BinWidth_); // Get coarse regions by calculating the gaps between the // narrow resonances and using the same functions to create // the integration grid object for each std::vector< std::pair > coarseRegions = this->formGapsFromRegions(m13Regions, minm13, maxm13); std::vector coarseBinning( fineScheme13.size()+1, m13BinWidth_ ); std::vector coarseScheme = this->m13IntegrationRegions(coarseRegions, m23Regions, coarseBinning, precision, m13BinWidth_); dpPartialIntegralInfo_.insert(dpPartialIntegralInfo_.end(), fineScheme13.begin(), fineScheme13.end()); dpPartialIntegralInfo_.insert(dpPartialIntegralInfo_.end(), fineScheme23.begin(), fineScheme23.end()); dpPartialIntegralInfo_.insert(dpPartialIntegralInfo_.end(), coarseScheme.begin(), coarseScheme.end()); // Remove any null pointer entries in the integral list // (that are produced when an integration region with no // interior points is defined) this->cullNullRegions(dpPartialIntegralInfo_); } normalizationSchemeDone_ = kTRUE; } void LauIsobarDynamics::setIntegralBinWidths(const Double_t m13BinWidth, const Double_t m23BinWidth, const Double_t mPrimeBinWidth, const Double_t thPrimeBinWidth) { // Set the bin widths for the m13 vs m23 integration grid m13BinWidth_ = m13BinWidth; m23BinWidth_ = m23BinWidth; // Set the bin widths for the m' vs theta' integration grid mPrimeBinWidth_ = mPrimeBinWidth; thPrimeBinWidth_ = thPrimeBinWidth; } void LauIsobarDynamics::calcDPPartialIntegral(LauDPPartialIntegralInfo* intInfo) { // Calculate the integrals for all parts of the amplitude in the given region of the DP const Bool_t squareDP = intInfo->getSquareDP(); const UInt_t nm13Points = intInfo->getnm13Points(); const UInt_t nm23Points = intInfo->getnm23Points(); //Double_t dpArea(0.0); for (UInt_t i = 0; i < nm13Points; ++i) { const Double_t m13 = intInfo->getM13Value(i); const Double_t m13Sq = m13*m13; for (UInt_t j = 0; j < nm23Points; ++j) { const Double_t m23 = intInfo->getM23Value(j); const Double_t m23Sq = m23*m23; const Double_t weight = intInfo->getWeight(i,j); // Calculate the integral contributions for each resonance. // Only points within the DP area contribute. // This also calculates the total DP area as a check. // NB if squareDP is true, m13 and m23 are actually mPrime and thetaPrime Bool_t withinDP = squareDP ? kinematics_->withinSqDPLimits(m13, m23) : kinematics_->withinDPLimits(m13Sq, m23Sq); if (withinDP == kTRUE) { if ( squareDP ) { // NB m13 and m23 are actually mPrime and thetaPrime kinematics_->updateSqDPKinematics(m13, m23); } else { kinematics_->updateKinematics(m13Sq, m23Sq); } this->calculateAmplitudes(intInfo, i, j); this->addGridPointToIntegrals(weight); // Increment total DP area //dpArea += weight; } } // j weights loop } // i weights loop // Print out DP area to check whether we have a sensible output //std::cout<<" : dpArea = "<::const_iterator intEnd = integralsToBeCalculated_.end(); for (UInt_t iAmp = 0; iAmp < nAmp_; ++iAmp) { if ( integralsToBeCalculated_.find(iAmp) != intEnd ) { // Calculate the dynamics for this resonance ff_[iAmp] = this->resAmp(iAmp); // Store the new value in the integration info object intInfo->storeAmplitude( m13Point, m23Point, iAmp, ff_[iAmp] ); } else { // Retrieve the cached value of the amplitude ff_[iAmp] = intInfo->getAmplitude( m13Point, m23Point, iAmp ); } } for (UInt_t iAmp = 0; iAmp < nIncohAmp_; ++iAmp) { if ( integralsToBeCalculated_.find(iAmp+nAmp_) != intEnd ) { // Calculate the dynamics for this resonance incohInten_[iAmp] = this->incohResAmp(iAmp); // Store the new value in the integration info object intInfo->storeIntensity( m13Point, m23Point, iAmp, incohInten_[iAmp] ); } else { // Retrieve the cached value of the amplitude incohInten_[iAmp] = intInfo->getIntensity( m13Point, m23Point, iAmp ); } } // If symmetric, do as above with flipped kinematics and add to amplitude // (No need to retrive the cache if this was done in the first case) if ( symmetricalDP_ == kTRUE ) { kinematics_->flipAndUpdateKinematics(); for (UInt_t iAmp = 0; iAmp < nAmp_; ++iAmp) { if ( (integralsToBeCalculated_.find(iAmp) != intEnd) && !sigResonances_[iAmp]->preSymmetrised() ) { // Calculate the dynamics for this resonance ff_[iAmp] += this->resAmp(iAmp); // Store the new value in the integration info object intInfo->storeAmplitude( m13Point, m23Point, iAmp, ff_[iAmp] ); } } for (UInt_t iAmp = 0; iAmp < nIncohAmp_; ++iAmp) { if ( (integralsToBeCalculated_.find(iAmp+nAmp_) != intEnd) && !sigResonances_[iAmp]->preSymmetrised() ) { // Calculate the dynamics for this resonance incohInten_[iAmp] += this->incohResAmp(iAmp); // Store the new value in the integration info object intInfo->storeIntensity( m13Point, m23Point, iAmp, incohInten_[iAmp] ); } } kinematics_->flipAndUpdateKinematics(); } if (fullySymmetricDP_ == kTRUE) { // rotate and evaluate kinematics_->rotateAndUpdateKinematics(); for (UInt_t iAmp = 0; iAmp < nAmp_; ++iAmp) { if ( (integralsToBeCalculated_.find(iAmp) != intEnd) && !sigResonances_[iAmp]->preSymmetrised() ) { // Calculate the dynamics for this resonance ff_[iAmp] += this->resAmp(iAmp); // Store the new value in the integration info object intInfo->storeAmplitude( m13Point, m23Point, iAmp, ff_[iAmp] ); } } for (UInt_t iAmp = 0; iAmp < nIncohAmp_; ++iAmp) { if ( (integralsToBeCalculated_.find(iAmp+nAmp_) != intEnd) && !sigResonances_[iAmp]->preSymmetrised() ) { // Calculate the dynamics for this resonance incohInten_[iAmp] += this->incohResAmp(iAmp); // Store the new value in the integration info object intInfo->storeIntensity( m13Point, m23Point, iAmp, incohInten_[iAmp] ); } } // rotate and evaluate kinematics_->rotateAndUpdateKinematics(); for (UInt_t iAmp = 0; iAmp < nAmp_; ++iAmp) { if ( (integralsToBeCalculated_.find(iAmp) != intEnd) && !sigResonances_[iAmp]->preSymmetrised() ) { // Calculate the dynamics for this resonance ff_[iAmp] += this->resAmp(iAmp); // Store the new value in the integration info object intInfo->storeAmplitude( m13Point, m23Point, iAmp, ff_[iAmp] ); } } for (UInt_t iAmp = 0; iAmp < nIncohAmp_; ++iAmp) { if ( (integralsToBeCalculated_.find(iAmp+nAmp_) != intEnd) && !sigResonances_[iAmp]->preSymmetrised() ) { // Calculate the dynamics for this resonance incohInten_[iAmp] += this->incohResAmp(iAmp); // Store the new value in the integration info object intInfo->storeIntensity( m13Point, m23Point, iAmp, incohInten_[iAmp] ); } } // rotate, flip and evaluate kinematics_->rotateAndUpdateKinematics(); kinematics_->flipAndUpdateKinematics(); for (UInt_t iAmp = 0; iAmp < nAmp_; ++iAmp) { if ( (integralsToBeCalculated_.find(iAmp) != intEnd) && !sigResonances_[iAmp]->preSymmetrised() ) { // Calculate the dynamics for this resonance ff_[iAmp] += this->resAmp(iAmp); // Store the new value in the integration info object intInfo->storeAmplitude( m13Point, m23Point, iAmp, ff_[iAmp] ); } } for (UInt_t iAmp = 0; iAmp < nIncohAmp_; ++iAmp) { if ( (integralsToBeCalculated_.find(iAmp+nAmp_) != intEnd) && !sigResonances_[iAmp]->preSymmetrised() ) { // Calculate the dynamics for this resonance incohInten_[iAmp] += this->incohResAmp(iAmp); // Store the new value in the integration info object intInfo->storeIntensity( m13Point, m23Point, iAmp, incohInten_[iAmp] ); } } // rotate and evaluate kinematics_->rotateAndUpdateKinematics(); for (UInt_t iAmp = 0; iAmp < nAmp_; ++iAmp) { if ( (integralsToBeCalculated_.find(iAmp) != intEnd) && !sigResonances_[iAmp]->preSymmetrised() ) { // Calculate the dynamics for this resonance ff_[iAmp] += this->resAmp(iAmp); // Store the new value in the integration info object intInfo->storeAmplitude( m13Point, m23Point, iAmp, ff_[iAmp] ); } } for (UInt_t iAmp = 0; iAmp < nIncohAmp_; ++iAmp) { if ( (integralsToBeCalculated_.find(iAmp+nAmp_) != intEnd) && !sigResonances_[iAmp]->preSymmetrised() ) { // Calculate the dynamics for this resonance incohInten_[iAmp] += this->incohResAmp(iAmp); // Store the new value in the integration info object intInfo->storeIntensity( m13Point, m23Point, iAmp, incohInten_[iAmp] ); } } // rotate and evaluate kinematics_->rotateAndUpdateKinematics(); for (UInt_t iAmp = 0; iAmp < nAmp_; ++iAmp) { if ( (integralsToBeCalculated_.find(iAmp) != intEnd) && !sigResonances_[iAmp]->preSymmetrised() ) { // Calculate the dynamics for this resonance ff_[iAmp] += this->resAmp(iAmp); // Store the new value in the integration info object intInfo->storeAmplitude( m13Point, m23Point, iAmp, ff_[iAmp] ); } } for (UInt_t iAmp = 0; iAmp < nIncohAmp_; ++iAmp) { if ( (integralsToBeCalculated_.find(iAmp+nAmp_) != intEnd) && !sigResonances_[iAmp]->preSymmetrised() ) { // Calculate the dynamics for this resonance incohInten_[iAmp] += this->incohResAmp(iAmp); // Store the new value in the integration info object intInfo->storeIntensity( m13Point, m23Point, iAmp, incohInten_[iAmp] ); } } // rotate and flip to get us back to where we started kinematics_->rotateAndUpdateKinematics(); kinematics_->flipAndUpdateKinematics(); } // If we haven't cached the data, then we need to find out the efficiency. eff_ = this->retrieveEfficiency(); intInfo->storeEfficiency( m13Point, m23Point, eff_ ); } void LauIsobarDynamics::calculateAmplitudes() { std::set::const_iterator iter = integralsToBeCalculated_.begin(); const std::set::const_iterator intEnd = integralsToBeCalculated_.end(); for ( iter = integralsToBeCalculated_.begin(); iter != intEnd; ++iter) { // Calculate the dynamics for this resonance if(*iter < nAmp_) { ff_[*iter] = this->resAmp(*iter); } else { incohInten_[*iter-nAmp_] = this->incohResAmp(*iter-nAmp_); } } if ( symmetricalDP_ == kTRUE ) { kinematics_->flipAndUpdateKinematics(); for ( iter = integralsToBeCalculated_.begin(); iter != intEnd; ++iter) { // Calculate the dynamics for this resonance if(*iter < nAmp_ && !sigResonances_[*iter]->preSymmetrised() ) { ff_[*iter] += this->resAmp(*iter); } else if (*iter >= nAmp_ && !sigResonances_[*iter-nAmp_]->preSymmetrised() ){ incohInten_[*iter-nAmp_] += this->incohResAmp(*iter-nAmp_); } } kinematics_->flipAndUpdateKinematics(); } if ( fullySymmetricDP_ == kTRUE ) { // rotate and evaluate kinematics_->rotateAndUpdateKinematics(); for ( iter = integralsToBeCalculated_.begin(); iter != intEnd; ++iter) { if(*iter < nAmp_ && !sigResonances_[*iter]->preSymmetrised() ) { ff_[*iter] += this->resAmp(*iter); } else if (*iter >= nAmp_ && !sigResonances_[*iter-nAmp_]->preSymmetrised() ){ incohInten_[*iter-nAmp_] += this->incohResAmp(*iter-nAmp_); } } // rotate and evaluate kinematics_->rotateAndUpdateKinematics(); for ( iter = integralsToBeCalculated_.begin(); iter != intEnd; ++iter) { if(*iter < nAmp_ && !sigResonances_[*iter]->preSymmetrised() ) { ff_[*iter] += this->resAmp(*iter); } else if (*iter >= nAmp_ && !sigResonances_[*iter-nAmp_]->preSymmetrised() ){ incohInten_[*iter-nAmp_] += this->incohResAmp(*iter-nAmp_); } } // rotate, flip and evaluate kinematics_->rotateAndUpdateKinematics(); kinematics_->flipAndUpdateKinematics(); for ( iter = integralsToBeCalculated_.begin(); iter != intEnd; ++iter) { if(*iter < nAmp_ && !sigResonances_[*iter]->preSymmetrised() ) { ff_[*iter] += this->resAmp(*iter); } else if (*iter >= nAmp_ && !sigResonances_[*iter-nAmp_]->preSymmetrised() ){ incohInten_[*iter-nAmp_] += this->incohResAmp(*iter-nAmp_); } } // rotate and evaluate kinematics_->rotateAndUpdateKinematics(); for ( iter = integralsToBeCalculated_.begin(); iter != intEnd; ++iter) { if(*iter < nAmp_ && !sigResonances_[*iter]->preSymmetrised() ) { ff_[*iter] += this->resAmp(*iter); } else if (*iter >= nAmp_ && !sigResonances_[*iter-nAmp_]->preSymmetrised() ){ incohInten_[*iter-nAmp_] += this->incohResAmp(*iter-nAmp_); } } // rotate and evaluate kinematics_->rotateAndUpdateKinematics(); for ( iter = integralsToBeCalculated_.begin(); iter != intEnd; ++iter) { if(*iter < nAmp_ && !sigResonances_[*iter]->preSymmetrised() ) { ff_[*iter] += this->resAmp(*iter); } else if (*iter >= nAmp_ && !sigResonances_[*iter-nAmp_]->preSymmetrised() ){ incohInten_[*iter-nAmp_] += this->incohResAmp(*iter-nAmp_); } } // rotate and flip to get us back to where we started kinematics_->rotateAndUpdateKinematics(); kinematics_->flipAndUpdateKinematics(); } // If we haven't cached the data, then we need to find out the efficiency. eff_ = this->retrieveEfficiency(); } void LauIsobarDynamics::calcTotalAmp(const Bool_t useEff) { // Reset the total amplitude to zero totAmp_.zero(); // Loop over all signal amplitudes LauComplex ATerm; for (UInt_t i = 0; i < nAmp_; ++i) { // Get the partial complex amplitude - (mag, phase)*(resonance dynamics) ATerm = Amp_[i]*ff_[i]; // Scale this contribution by its relative normalisation w.r.t. the whole dynamics ATerm.rescale(fNorm_[i]); // Add this partial amplitude to the sum totAmp_ += ATerm; } // Loop over amplitudes // |Sum of partial amplitudes|^2 ASq_ = totAmp_.abs2(); for (UInt_t i = 0; i < nIncohAmp_; ++i) { // Get the partial complex amplitude - (mag, phase) ATerm = Amp_[i+nAmp_]; // Scale this contribution by its relative normalisation w.r.t. the whole dynamics ATerm.rescale(fNorm_[i+nAmp_]); // Add this partial amplitude to the sum ASq_ += ATerm.abs2()*incohInten_[i]; } // Apply the efficiency correction for this event. // Multiply the amplitude squared sum by the DP efficiency if ( useEff ) { ASq_ *= eff_; } } void LauIsobarDynamics::addGridPointToIntegrals(const Double_t weight) { // Combine the Gauss-Legendre weight with the efficiency const Double_t effWeight = eff_*weight; LauComplex fifjEffSumTerm; LauComplex fifjSumTerm; // Calculates the half-matrix of amplitude-squared and interference // terms (dynamical part only) // Add the values at this point on the integration grid to the sums // (one weighted only by the integration weights, one also weighted by // the efficiency) for (UInt_t i = 0; i < nAmp_; ++i) { // Add the dynamical amplitude squared for this resonance. Double_t fSqVal = ff_[i].abs2(); fSqSum_[i] += fSqVal*weight; fSqEffSum_[i] += fSqVal*effWeight; for (UInt_t j = i; j < nAmp_; ++j) { fifjEffSumTerm = fifjSumTerm = ff_[i]*ff_[j].conj(); fifjEffSumTerm.rescale(effWeight); fifjEffSum_[i][j] += fifjEffSumTerm; fifjSumTerm.rescale(weight); fifjSum_[i][j] += fifjSumTerm; } } for (UInt_t i = 0; i < nIncohAmp_; ++i) { // Add the dynamical amplitude squared for this resonance. Double_t fSqVal = incohInten_[i]; fSqSum_[i+nAmp_] += fSqVal*weight; fSqEffSum_[i+nAmp_] += fSqVal*effWeight; } } LauComplex LauIsobarDynamics::resAmp(const UInt_t index) { // Routine to calculate the resonance dynamics (amplitude) // using the appropriate Breit-Wigner/Form Factors. LauComplex amp = LauComplex(0.0, 0.0); if ( index >= nAmp_ ) { std::cerr<<"ERROR in LauIsobarDynamics::resAmp : index = "<= nIncohAmp_ ) { std::cerr<<"ERROR in LauIsobarDynamics::setFFTerm : index = "<= nAmp_) { //Set off-diagonal incoherent terms to zero fitFrac_[i][j].value(0.); fitFracEffUnCorr_[i][j].value(0.); continue; } LauComplex AmpjConj = Amp_[j].conj(); LauComplex AmpTerm = Amp_[i]*AmpjConj; Double_t crossTerm = 2.0*(AmpTerm*fifjSum_[i][j]).re()*fNorm_[i]*fNorm_[j]; fifjTot += crossTerm; Double_t crossEffTerm = 2.0*(AmpTerm*fifjEffSum_[i][j]).re()*fNorm_[i]*fNorm_[j]; fifjEffTot += crossEffTerm; fitFrac_[i][j].value(crossTerm); fitFracEffUnCorr_[i][j].value(crossEffTerm); } } for (i = nAmp_; i < nAmp_+nIncohAmp_; i++) { // Calculate the incoherent terms TString name = "A"; name += i; name += "Sq_FitFrac"; fitFrac_[i][i].name(name); name += "EffUnCorr"; fitFracEffUnCorr_[i][i].name(name); Double_t sumTerm = Amp_[i].abs2()*fSqSum_[i]*fNorm_[i]*fNorm_[i]; fifjTot += sumTerm; Double_t sumEffTerm = Amp_[i].abs2()*fSqEffSum_[i]*fNorm_[i]*fNorm_[i]; fifjEffTot += sumEffTerm; fitFrac_[i][i].value(sumTerm); fitFracEffUnCorr_[i][i].value(sumEffTerm); } for (i = nAmp_; i < nAmp_+nIncohAmp_; i++) { for (j = i+1; j < nAmp_+nIncohAmp_; j++) { //Set off-diagonal incoherent terms to zero TString name = "A"; name += i; name += "A"; name += j; name += "_FitFrac"; fitFrac_[i][j].name(name); name += "EffUnCorr"; fitFracEffUnCorr_[i][j].name(name); fitFrac_[i][j].value(0.); fitFracEffUnCorr_[i][j].value(0.); } } if (TMath::Abs(fifjTot) > 1e-10) { meanDPEff_.value(fifjEffTot/fifjTot); if (init) { meanDPEff_.genValue( meanDPEff_.value() ); meanDPEff_.initValue( meanDPEff_.value() ); } } DPRate_.value(fifjTot); if (init) { DPRate_.genValue( DPRate_.value() ); DPRate_.initValue( DPRate_.value() ); } // Now divide the fitFraction sums by the overall integral for (i = 0; i < nAmp_+nIncohAmp_; i++) { for (j = i; j < nAmp_+nIncohAmp_; j++) { // Get the actual fractions by dividing by the total DP rate Double_t fitFracVal = fitFrac_[i][j].value(); fitFracVal /= fifjTot; fitFrac_[i][j].value( fitFracVal ); Double_t fitFracEffUnCorrVal = fitFracEffUnCorr_[i][j].value(); fitFracEffUnCorrVal /= fifjEffTot; fitFracEffUnCorr_[i][j].value( fitFracEffUnCorrVal ); if (init) { fitFrac_[i][j].genValue( fitFrac_[i][j].value() ); fitFrac_[i][j].initValue( fitFrac_[i][j].value() ); fitFracEffUnCorr_[i][j].genValue( fitFracEffUnCorr_[i][j].value() ); fitFracEffUnCorr_[i][j].initValue( fitFracEffUnCorr_[i][j].value() ); } } } // Work out total fit fraction over all K-matrix components (for each propagator) KMPropMap::iterator mapIter; Int_t propInt(0); for (mapIter = kMatrixPropagators_.begin(); mapIter != kMatrixPropagators_.end(); ++mapIter) { LauKMatrixPropagator* thePropagator = mapIter->second; TString propName = thePropagator->getName(); // Now loop over all resonances and find those which are K-matrix components for this propagator Double_t kMatrixTotFitFrac(0.0); for (i = 0; i < nAmp_; i++) { Bool_t gotKMRes1 = this->gotKMatrixMatch(i, propName); if (gotKMRes1 == kFALSE) {continue;} Double_t fifjSumReal = fifjSum_[i][i].re(); Double_t sumTerm = Amp_[i].abs2()*fifjSumReal*fNorm_[i]*fNorm_[i]; //Double_t fifjEffSumReal = fifjEffSum_[i][i].re(); //Double_t sumEffTerm = Amp_[i].abs2()*fifjEffSumReal*fNorm_[i]*fNorm_[i]; kMatrixTotFitFrac += sumTerm; for (j = i+1; j < nAmp_; j++) { Bool_t gotKMRes2 = this->gotKMatrixMatch(j, propName); if (gotKMRes2 == kFALSE) {continue;} LauComplex AmpjConj = Amp_[j].conj(); LauComplex AmpTerm = Amp_[i]*AmpjConj; Double_t crossTerm = 2.0*(AmpTerm*fifjSum_[i][j]).re()*fNorm_[i]*fNorm_[j]; //Double_t crossEffTerm = 2.0*(AmpTerm*fifjEffSum_[i][j]).re()*fNorm_[i]*fNorm_[j]; kMatrixTotFitFrac += crossTerm; } } kMatrixTotFitFrac /= fifjTot; TString parName("KMatrixTotFF_"); parName += propInt; extraParameters_[propInt].name( parName ); extraParameters_[propInt].value(kMatrixTotFitFrac); if (init) { extraParameters_[propInt].genValue(kMatrixTotFitFrac); extraParameters_[propInt].initValue(kMatrixTotFitFrac); } std::cout<<"INFO in LauIsobarDynamics::calcExtraInfo : Total K-matrix fit fraction for propagator "<calculateRhoOmegaFitFractions_ && !init) { int omegaID = 0; int storeID = 1; // Check which B flavour (and therefore which rho_COPY we are) by whether the FF is non-zero // Only for CP fit though - for a 'simple' fit this is more complicated if (fitFrac_[omegaID][omegaID].value() < 1E-4) { omegaID = 1; storeID = 0; } // Check this is really the correct model LauRhoOmegaMix * rhomega = dynamic_cast(getResonance(omegaID)); if (rhomega != NULL) { // Bail out std::cout << "INFO in LauIsobarDynamics::calcExtraInfo : Calculating omega fit fraction from resonance " << omegaID << std::endl; std::cout << "INFO in LauIsobarDynamics::calcExtraInfo : Storing omega fit fraction in resonance " << storeID << std::endl; // Tell the RhoOmegaMix model only to give us the omega amplitude-squared rhomega->setWhichAmpSq(1); // Recalculate the integrals for the omega fit-fraction integralsDone_ = kFALSE; this->resetNormVectors(); for ( UInt_t k(0); k < nAmp_+nIncohAmp_; ++k ) { integralsToBeCalculated_.insert(k); } this->calcDPNormalisation(); integralsDone_ = kTRUE; Double_t fifjSumRealOmega = fifjSum_[omegaID][omegaID].re(); // Recalculate the integrals for the rho fit-fraction rhomega->setWhichAmpSq(2); integralsDone_ = kFALSE; this->resetNormVectors(); for ( UInt_t k(0); k < nAmp_+nIncohAmp_; ++k ) { integralsToBeCalculated_.insert(k); } this->calcDPNormalisation(); integralsDone_ = kTRUE; Double_t fitFracPartRho = Amp_[omegaID].abs2()*fifjSum_[omegaID][omegaID].re(); // Reset the RhoOmegaMix model and the integrals rhomega->setWhichAmpSq(0); integralsDone_ = kFALSE; this->resetNormVectors(); for ( UInt_t k(0); k < nAmp_+nIncohAmp_; ++k ) { integralsToBeCalculated_.insert(k); } this->calcDPNormalisation(); integralsDone_ = kTRUE; // Store the omega fit-fraction in the rho_COPY location (which is otherwise empty) // Store the rho fit-fraction in the rho location (overwriting the combined FF) Double_t omegaFF = fifjSumRealOmega * fitFrac_[omegaID][omegaID].value(); fitFrac_[storeID][storeID].value(omegaFF); fitFrac_[omegaID][omegaID].value(fitFracPartRho * fNorm_[omegaID] * fNorm_[omegaID] / DPRate_.value()); } else { std::cout << "INFO in LauIsobarDynamics::calcExtraInfo : calculateRhoOmegaFitFractions is set, but the RhoOmegaMix model isn't in the right place. Ignoring this option." << std::endl; } } } Bool_t LauIsobarDynamics::gotKMatrixMatch(UInt_t resAmpInt, const TString& propName) const { Bool_t gotMatch(kFALSE); if (resAmpInt >= nAmp_) {return kFALSE;} const LauAbsResonance* theResonance = sigResonances_[resAmpInt]; if (theResonance == 0) {return kFALSE;} Int_t resModelInt = theResonance->getResonanceModel(); if (resModelInt == LauAbsResonance::KMatrix) { TString resName = theResonance->getResonanceName(); KMStringMap::const_iterator kMPropSetIter = kMatrixPropSet_.find(resName); if (kMPropSetIter != kMatrixPropSet_.end()) { TString kmPropString = kMPropSetIter->second; if (kmPropString == propName) {gotMatch = kTRUE;} } } return gotMatch; } Double_t LauIsobarDynamics::calcSigDPNorm() { // Calculate the normalisation for the log-likelihood function. DPNorm_ = 0.0; for (UInt_t i = 0; i < nAmp_; i++) { // fifjEffSum is the contribution from the term involving the resonance // dynamics (f_i for resonance i) and the efficiency term. Double_t fifjEffSumReal = fifjEffSum_[i][i].re(); // We need to normalise this contribution w.r.t. the complete dynamics in the DP. // Hence we scale by the fNorm_i factor (squared), which is calculated by the // initialise() function, when the normalisation integrals are calculated and cached. // We also include the complex amplitude squared to get the total normalisation // contribution from this resonance. DPNorm_ += Amp_[i].abs2()*fifjEffSumReal*fNorm_[i]*fNorm_[i]; } // We now come to the cross-terms (between resonances i and j) in the normalisation. for (UInt_t i = 0; i < nAmp_; i++) { for (UInt_t j = i+1; j < nAmp_; j++) { LauComplex AmpjConj = Amp_[j].conj(); LauComplex AmpTerm = Amp_[i]*AmpjConj; // Again, fifjEffSum is the contribution from the term involving the resonance // dynamics (f_i*f_j_conjugate) and the efficiency cross term. // Also include the relative normalisation between these two resonances w.r.t. the // total DP dynamical structure (fNorm_i and fNorm_j) and the complex // amplitude squared (mag,phase) part. DPNorm_ += 2.0*(AmpTerm*fifjEffSum_[i][j]).re()*fNorm_[i]*fNorm_[j]; } } for (UInt_t i = 0; i < nIncohAmp_; i++) { DPNorm_ += Amp_[i+nAmp_].abs2()*fSqEffSum_[i+nAmp_]*fNorm_[i+nAmp_]*fNorm_[i+nAmp_]; } return DPNorm_; } Bool_t LauIsobarDynamics::generate() { // Routine to generate a signal event according to the Dalitz plot // model we have defined. // We need to make sure to calculate everything for every resonance integralsToBeCalculated_.clear(); for ( UInt_t i(0); i < nAmp_+nIncohAmp_; ++i ) { integralsToBeCalculated_.insert(i); } nSigGenLoop_ = 0; Bool_t generatedSig(kFALSE); while (generatedSig == kFALSE && nSigGenLoop_ < iterationsMax_) { // Generates uniform DP phase-space distribution Double_t m13Sq(0.0), m23Sq(0.0); kinematics_->genFlatPhaseSpace(m13Sq, m23Sq); // If we're in a symmetrical DP then we should only generate events in one half // TODO - what do we do for fully symmetric? if ( symmetricalDP_ && !fullySymmetricDP_ && m13Sq > m23Sq ) { Double_t tmpSq = m13Sq; m13Sq = m23Sq; m23Sq = tmpSq; } // Calculate the amplitudes and total amplitude for the given DP point this->calcLikelihoodInfo(m13Sq, m23Sq); // Throw the random number and check it against the ratio of ASq and the accept/reject ceiling const Double_t randNo = LauRandom::randomFun()->Rndm(); if (randNo > ASq_/aSqMaxSet_) { ++nSigGenLoop_; } else { generatedSig = kTRUE; nSigGenLoop_ = 0; // Keep a note of the maximum ASq that we've found if (ASq_ > aSqMaxVar_) {aSqMaxVar_ = ASq_;} } } // while loop // Check that all is well with the generation Bool_t sigGenOK(kTRUE); if (GenOK != this->checkToyMC(kTRUE,kFALSE)) { sigGenOK = kFALSE; } return sigGenOK; } LauIsobarDynamics::ToyMCStatus LauIsobarDynamics::checkToyMC(Bool_t printErrorMessages, Bool_t printInfoMessages) { // Check whether we have generated the toy MC OK. ToyMCStatus ok(GenOK); if (nSigGenLoop_ >= iterationsMax_) { // Exceeded maximum allowed iterations - the generation is too inefficient if (printErrorMessages) { std::cerr<<"WARNING in LauIsobarDynamics::checkToyMC : More than "< 1.01 * aSqMaxVar_ ) { if (printErrorMessages) { std::cerr<<" : |A|^2 maximum was set to "< aSqMaxSet_) { // Found a value of ASq higher than the accept/reject ceiling - the generation is biased if (printErrorMessages) { std::cerr<<"WARNING in LauIsobarDynamics::checkToyMC : |A|^2 maximum was set to "< "<= "<retrievem13Sq(); m23Sq_ = currentEvent_->retrievem23Sq(); mPrime_ = currentEvent_->retrievemPrime(); thPrime_ = currentEvent_->retrievethPrime(); tagCat_ = currentEvent_->retrieveTagCat(); eff_ = currentEvent_->retrieveEff(); scfFraction_ = currentEvent_->retrieveScfFraction(); // These two are necessary, even though the dynamics don't actually use scfFraction_ or jacobian_, jacobian_ = currentEvent_->retrieveJacobian(); // since this is at the heart of the caching mechanism. } void LauIsobarDynamics::calcLikelihoodInfo(const UInt_t iEvt) { // Calculate the likelihood and associated info // for the given event using cached information evtLike_ = 0.0; // retrieve the cached dynamics from the tree: // realAmp, imagAmp for each resonance plus efficiency, scf fraction and jacobian this->setDataEventNo(iEvt); // use realAmp and imagAmp to create the resonance amplitudes const std::vector& realAmp = currentEvent_->retrieveRealAmp(); const std::vector& imagAmp = currentEvent_->retrieveImagAmp(); const std::vector& incohInten = currentEvent_->retrieveIncohIntensities(); for (UInt_t i = 0; i < nAmp_; i++) { this->setFFTerm(i, realAmp[i], imagAmp[i]); } for (UInt_t i = 0; i < nIncohAmp_; i++) { this->setIncohIntenTerm(i, incohInten[i]); } // Update the dynamics - calculates totAmp_ and then ASq_ = totAmp_.abs2() * eff_ // All calculated using cached information on the individual amplitudes and efficiency. this->calcTotalAmp(kTRUE); // Calculate the normalised matrix element squared value if (DPNorm_ > 1e-10) { evtLike_ = ASq_/DPNorm_; } } void LauIsobarDynamics::calcLikelihoodInfo(const Double_t m13Sq, const Double_t m23Sq) { this->calcLikelihoodInfo(m13Sq, m23Sq, -1); } void LauIsobarDynamics::calcLikelihoodInfo(const Double_t m13Sq, const Double_t m23Sq, const Int_t tagCat) { // Calculate the likelihood and associated info // for the given point in the Dalitz plot // Also retrieves the SCF fraction in the bin where the event lies (done // here to cache it along with the the rest of the DP quantities, like eff) // The jacobian for the square DP is calculated here for the same reason. evtLike_ = 0.0; // update the kinematics for the specified DP point kinematics_->updateKinematics(m13Sq, m23Sq); // calculate the jacobian and the scfFraction to cache them later scfFraction_ = this->retrieveScfFraction(tagCat); if (kinematics_->squareDP() == kTRUE) { jacobian_ = kinematics_->calcSqDPJacobian(); } // calculate the ff_ terms and retrieves eff_ from the efficiency model this->calculateAmplitudes(); // then calculate totAmp_ and finally ASq_ = totAmp_.abs2() * eff_ this->calcTotalAmp(kTRUE); // Calculate the normalised matrix element squared value if (DPNorm_ > 1e-10) { evtLike_ = ASq_/DPNorm_; } } void LauIsobarDynamics::modifyDataTree() { if ( recalcNormalisation_ == kFALSE ) { return; } const UInt_t nEvents = data_.size(); std::set::const_iterator iter = integralsToBeCalculated_.begin(); const std::set::const_iterator intEnd = integralsToBeCalculated_.end(); for (UInt_t iEvt = 0; iEvt < nEvents; ++iEvt) { currentEvent_ = data_[iEvt]; std::vector& realAmp = currentEvent_->retrieveRealAmp(); std::vector& imagAmp = currentEvent_->retrieveImagAmp(); std::vector& incohInten = currentEvent_->retrieveIncohIntensities(); const Double_t m13Sq = currentEvent_->retrievem13Sq(); const Double_t m23Sq = currentEvent_->retrievem23Sq(); const Int_t tagCat = currentEvent_->retrieveTagCat(); this->calcLikelihoodInfo(m13Sq, m23Sq, tagCat); for ( iter = integralsToBeCalculated_.begin(); iter != intEnd; ++iter) { const UInt_t i = *iter; if(*iter < nAmp_) { realAmp[i] = ff_[i].re(); imagAmp[i] = ff_[i].im(); } else { incohInten[i-nAmp_] = incohInten_[i-nAmp_]; } } } } void LauIsobarDynamics::fillDataTree(const LauFitDataTree& inputFitTree) { // In LauFitDataTree, the first two variables should always be m13^2 and m23^2. // Other variables follow thus: charge/flavour tag prob, etc. // Since this is the first caching, we need to make sure to calculate everything for every resonance integralsToBeCalculated_.clear(); for ( UInt_t i(0); i < nAmp_+nIncohAmp_; ++i ) { integralsToBeCalculated_.insert(i); } UInt_t nBranches = inputFitTree.nBranches(); if (nBranches < 2) { std::cerr<<"ERROR in LauIsobarDynamics::fillDataTree : Expecting at least 2 variables " <<"in input data tree, but there are "<Exit(EXIT_FAILURE); } // Data structure that will cache the variables required to // calculate the signal likelihood for this experiment for ( std::vector::iterator iter = data_.begin(); iter != data_.end(); ++iter ) { delete (*iter); } data_.clear(); Double_t m13Sq(0.0), m23Sq(0.0); Double_t mPrime(0.0), thPrime(0.0); Int_t tagCat(-1); std::vector realAmp(nAmp_), imagAmp(nAmp_); Double_t eff(0.0), scfFraction(0.0), jacobian(0.0); UInt_t nEvents = inputFitTree.nEvents() + inputFitTree.nFakeEvents(); data_.reserve(nEvents); for (UInt_t iEvt = 0; iEvt < nEvents; ++iEvt) { const LauFitData& dataValues = inputFitTree.getData(iEvt); LauFitData::const_iterator iter = dataValues.find("m13Sq"); m13Sq = iter->second; iter = dataValues.find("m23Sq"); m23Sq = iter->second; // is there more than one tagging category? // if so then we need to know the category from the data if (scfFractionModel_.size()>1) { iter = dataValues.find("tagCat"); tagCat = static_cast(iter->second); } // calculates the amplitudes and total amplitude for the given DP point // tagging category not needed by dynamics, but to find out the scfFraction this->calcLikelihoodInfo(m13Sq, m23Sq, tagCat); // extract the real and imaginary parts of the ff_ terms for storage for (UInt_t i = 0; i < nAmp_; i++) { realAmp[i] = ff_[i].re(); imagAmp[i] = ff_[i].im(); } if ( kinematics_->squareDP() ) { mPrime = kinematics_->getmPrime(); thPrime = kinematics_->getThetaPrime(); } eff = this->getEvtEff(); scfFraction = this->getEvtScfFraction(); jacobian = this->getEvtJacobian(); // store the data for each event in the list data_.push_back( new LauCacheData() ); data_[iEvt]->storem13Sq(m13Sq); data_[iEvt]->storem23Sq(m23Sq); data_[iEvt]->storemPrime(mPrime); data_[iEvt]->storethPrime(thPrime); data_[iEvt]->storeTagCat(tagCat); data_[iEvt]->storeEff(eff); data_[iEvt]->storeScfFraction(scfFraction); data_[iEvt]->storeJacobian(jacobian); data_[iEvt]->storeRealAmp(realAmp); data_[iEvt]->storeImagAmp(imagAmp); data_[iEvt]->storeIncohIntensities(incohInten_); } } Bool_t LauIsobarDynamics::gotReweightedEvent() { // Select the event (kinematics_) using an accept/reject method based on the // ratio of the current value of ASq to the maximal value. Bool_t accepted(kFALSE); // calculate the ff_ terms and retrieves eff_ from the efficiency model this->calculateAmplitudes(); // then calculate totAmp_ and finally ASq_ = totAmp_.abs2() (without the efficiency correction!) this->calcTotalAmp(kFALSE); // Compare the ASq value with the maximal value (set by the user) if (LauRandom::randomFun()->Rndm() < ASq_/aSqMaxSet_) { accepted = kTRUE; } if (ASq_ > aSqMaxVar_) {aSqMaxVar_ = ASq_;} return accepted; } Double_t LauIsobarDynamics::getEventWeight() { // calculate the ff_ terms and retrieves eff_ from the efficiency model this->calculateAmplitudes(); // then calculate totAmp_ and finally ASq_ = totAmp_.abs2() (without the efficiency correction!) this->calcTotalAmp(kFALSE); // return the event weight = the value of the squared amplitude return ASq_; } void LauIsobarDynamics::updateCoeffs(const std::vector& coeffs) { // Check that the number of coeffs is correct if (coeffs.size() != this->getnTotAmp()) { std::cerr << "ERROR in LauIsobarDynamics::updateCoeffs : Expected " << this->getnTotAmp() << " but got " << coeffs.size() << std::endl; gSystem->Exit(EXIT_FAILURE); } // Now check if the coeffs have changed Bool_t changed = (Amp_ != coeffs); if (changed) { // Copy the coeffs Amp_ = coeffs; } // TODO should perhaps keep track of whether the resonance parameters have changed here and if none of those and none of the coeffs have changed then we don't need to update the norm // Update the total normalisation for the signal likelihood this->calcSigDPNorm(); } TString LauIsobarDynamics::getConjResName(const TString& resName) const { // Get the name of the charge conjugate resonance TString conjName(resName); Ssiz_t index1 = resName.Index("+"); Ssiz_t index2 = resName.Index("-"); if (index1 != -1) { conjName.Replace(index1, 1, "-"); } else if (index2 != -1) { conjName.Replace(index2, 1, "+"); } return conjName; } Double_t LauIsobarDynamics::retrieveEfficiency() { Double_t eff(1.0); if (effModel_ != 0) { eff = effModel_->calcEfficiency(kinematics_); } return eff; } Double_t LauIsobarDynamics::retrieveScfFraction(Int_t tagCat) { Double_t scfFraction(0.0); // scf model and eff model are exactly the same, functionally // so we use an instance of LauAbsEffModel, and the method // calcEfficiency actually calculates the scf fraction if (tagCat == -1) { if (!scfFractionModel_.empty()) { scfFraction = scfFractionModel_[0]->calcEfficiency(kinematics_); } } else { scfFraction = scfFractionModel_[tagCat]->calcEfficiency(kinematics_); } return scfFraction; } diff --git a/src/LauKMatrixProdPole.cc b/src/LauKMatrixProdPole.cc index 3223f8c..8fecca8 100644 --- a/src/LauKMatrixProdPole.cc +++ b/src/LauKMatrixProdPole.cc @@ -1,108 +1,107 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauKMatrixProdPole.cc \brief File containing implementation of LauKMatrixProdPole class. */ #include "LauKMatrixProdPole.hh" #include "LauKMatrixPropagator.hh" #include -ClassImp(LauKMatrixProdPole) LauKMatrixProdPole::LauKMatrixProdPole(const TString& poleName, Int_t poleIndex, Int_t resPairAmpInt, LauKMatrixPropagator* propagator, const LauDaughters* daughters, Bool_t useProdAdler) : LauAbsResonance(poleName, resPairAmpInt, daughters), thePropagator_(propagator), poleIndex_(poleIndex - 1), // poleIndex goes from 1 to nPoles useProdAdler_(useProdAdler) { if (useProdAdler_) { std::cout<<"Creating K matrix production pole "<updatePropagator(kinematics); // Sum the pole denominator terms over all channels j, multiplying by // the propagator terms. Note that we do not sum over poles, since we // only want one of the production pole terms. Int_t nChannels = thePropagator_->getNChannels(); Int_t jChannel; for (jChannel = 0; jChannel < nChannels; jChannel++) { Double_t gj = thePropagator_->getCouplingConstant(poleIndex_, jChannel); LauComplex prodTerm = thePropagator_->getPropTerm(jChannel); prodTerm.rescale(gj); amp += prodTerm; } Double_t poleDenom = thePropagator_->getPoleDenomTerm(poleIndex_); // Include Adler zero factor if requested Double_t adlerZero(1.0); if (useProdAdler_) {adlerZero = thePropagator_->getAdlerZero();} amp.rescale(poleDenom*adlerZero); return amp; } diff --git a/src/LauKMatrixProdSVP.cc b/src/LauKMatrixProdSVP.cc index 7ad3c35..789ad72 100644 --- a/src/LauKMatrixProdSVP.cc +++ b/src/LauKMatrixProdSVP.cc @@ -1,96 +1,95 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauKMatrixProdSVP.cc \brief File containing implementation of LauKMatrixProdSVP class. */ #include "LauKMatrixProdSVP.hh" #include "LauKMatrixPropagator.hh" #include -ClassImp(LauKMatrixProdSVP) LauKMatrixProdSVP::LauKMatrixProdSVP(const TString& SVPName, Int_t channelIndex, Int_t resPairAmpInt, LauKMatrixPropagator* propagator, const LauDaughters* daughters, Bool_t useProdAdler) : LauAbsResonance(SVPName, resPairAmpInt, daughters), thePropagator_(propagator), channelIndex_(channelIndex - 1), // channelIndex goes from 1 to nChannels. useProdAdler_(useProdAdler) { // Constructor if (useProdAdler_) { std::cout<<"Creating K matrix production SVP "<updatePropagator(kinematics); Double_t SVPTerm = thePropagator_->getProdSVPTerm(); amp = thePropagator_->getPropTerm(channelIndex_); // Include Adler zero factor if requested Double_t adlerZero(1.0); if (useProdAdler_) {adlerZero = thePropagator_->getAdlerZero();} amp.rescale(SVPTerm*adlerZero); return amp; } diff --git a/src/LauKMatrixPropFactory.cc b/src/LauKMatrixPropFactory.cc index be6d06f..6189451 100644 --- a/src/LauKMatrixPropFactory.cc +++ b/src/LauKMatrixPropFactory.cc @@ -1,90 +1,89 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauKMatrixPropFactory.cc \brief File containing implementation of LauKMatrixPropFactory class. */ // Class for storing K-matrix propagator objects // using the factory method. #include "LauKMatrixPropFactory.hh" #include "LauKMatrixPropagator.hh" #include using std::cout; using std::endl; // the singleton instance LauKMatrixPropFactory* LauKMatrixPropFactory::theFactory_ = 0; -ClassImp(LauKMatrixPropFactory) LauKMatrixPropFactory::LauKMatrixPropFactory() { // Constructor map_.clear(); } LauKMatrixPropFactory::~LauKMatrixPropFactory() { // Destructor KMatrixPropMap::iterator iter; for (iter = map_.begin(); iter != map_.end(); ++iter) { LauKMatrixPropagator* thePropagator = iter->second; delete thePropagator; } map_.clear(); } LauKMatrixPropFactory* LauKMatrixPropFactory::getInstance() { if (theFactory_ == 0) { theFactory_ = new LauKMatrixPropFactory(); } return theFactory_; } LauKMatrixPropagator* LauKMatrixPropFactory::getPropagator(const TString& name, const TString& paramFileName, Int_t resPairAmpInt, Int_t nChannels, Int_t nPoles, Int_t rowIndex) { LauKMatrixPropagator* thePropagator(0); KMatrixPropMap::iterator iter = map_.find(name); if ( iter != map_.end() ) { // We have already made this propagator thePropagator = iter->second; } else { // The propagator does not exist. Create it and store it in the map. thePropagator = new LauKMatrixPropagator(name, paramFileName, resPairAmpInt, nChannels, nPoles, rowIndex); map_[name] = thePropagator; } return thePropagator; } diff --git a/src/LauKMatrixPropagator.cc b/src/LauKMatrixPropagator.cc index 80bafff..9403d64 100644 --- a/src/LauKMatrixPropagator.cc +++ b/src/LauKMatrixPropagator.cc @@ -1,1133 +1,1132 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauKMatrixPropagator.cc \brief File containing implementation of LauKMatrixPropagator class. */ #include "LauKMatrixPropagator.hh" #include "LauConstants.hh" #include "LauTextFileParser.hh" #include "TMath.h" #include "TSystem.h" #include #include #include #include using std::cout; using std::endl; using std::cerr; -ClassImp(LauKMatrixPropagator) LauKMatrixPropagator::LauKMatrixPropagator(const TString& name, const TString& paramFile, Int_t resPairAmpInt, Int_t nChannels, Int_t nPoles, Int_t rowIndex) : name_(name), paramFileName_(paramFile), resPairAmpInt_(resPairAmpInt), index_(rowIndex - 1), previousS_(0.0), scattSVP_(0.0), prodSVP_(0.0), nChannels_(nChannels), nPoles_(nPoles), sAConst_(0.0), m2piSq_(4.0*LauConstants::mPiSq), m2KSq_( 4.0*LauConstants::mKSq), m2EtaSq_(4.0*LauConstants::mEtaSq), mEtaEtaPSumSq_((LauConstants::mEta + LauConstants::mEtaPrime)*(LauConstants::mEta + LauConstants::mEtaPrime)), mEtaEtaPDiffSq_((LauConstants::mEta - LauConstants::mEtaPrime)*(LauConstants::mEta - LauConstants::mEtaPrime)), mKpiSumSq_((LauConstants::mK + LauConstants::mPi)*(LauConstants::mK + LauConstants::mPi)), mKpiDiffSq_((LauConstants::mK - LauConstants::mPi)*(LauConstants::mK - LauConstants::mPi)), mKEtaPSumSq_((LauConstants::mK + LauConstants::mEtaPrime)*(LauConstants::mK + LauConstants::mEtaPrime)), mKEtaPDiffSq_((LauConstants::mK - LauConstants::mEtaPrime)*(LauConstants::mK - LauConstants::mEtaPrime)), mK3piDiffSq_((LauConstants::mK - 3.0*LauConstants::mPi)*(LauConstants::mK - 3.0*LauConstants::mPi)), k3piFactor_(TMath::Power((1.44 - mK3piDiffSq_)/1.44, -2.5)), fourPiFactor1_(16.0*LauConstants::mPiSq), fourPiFactor2_(TMath::Sqrt(1.0 - fourPiFactor1_)), adlerZeroFactor_(0.0), parametersSet_(kFALSE), verbose_(kFALSE), scattSymmetry_(kTRUE) { // Constructor // Check that the index is OK if (index_ < 0 || index_ >= nChannels_) { std::cerr << "ERROR in LauKMatrixPropagator constructor. The rowIndex, which is set to " << rowIndex << ", must be between 1 and the number of channels " << nChannels_ << std::endl; gSystem->Exit(EXIT_FAILURE); } this->setParameters(paramFile); } LauKMatrixPropagator::~LauKMatrixPropagator() { // Destructor realProp_.Clear(); negImagProp_.Clear(); ScattKMatrix_.Clear(); ReRhoMatrix_.Clear(); ImRhoMatrix_.Clear(); ReTMatrix_.Clear(); ImTMatrix_.Clear(); IMatrix_.Clear(); zeroMatrix_.Clear(); } LauComplex LauKMatrixPropagator::getPropTerm(Int_t channel) const { // Get the (i,j) = (index_, channel) term of the propagator // matrix. This allows us not to return the full propagator matrix. Double_t realTerm = this->getRealPropTerm(channel); Double_t imagTerm = this->getImagPropTerm(channel); LauComplex propTerm(realTerm, imagTerm); return propTerm; } Double_t LauKMatrixPropagator::getRealPropTerm(Int_t channel) const { // Get the real part of the (i,j) = (index_, channel) term of the propagator // matrix. This allows us not to return the full propagator matrix. if (parametersSet_ == kFALSE) {return 0.0;} Double_t propTerm = realProp_[index_][channel]; return propTerm; } Double_t LauKMatrixPropagator::getImagPropTerm(Int_t channel) const { // Get the imaginary part of the (i,j) = (index_, channel) term of the propagator // matrix. This allows us not to return the full propagator matrix. if (parametersSet_ == kFALSE) {return 0.0;} Double_t imagTerm = -1.0*negImagProp_[index_][channel]; return imagTerm; } void LauKMatrixPropagator::updatePropagator(const LauKinematics* kinematics) { // Calculate the K-matrix propagator for the given s value. // The K-matrix amplitude is given by // T_i = sum_{ij} (I - iK*rho)^-1 * P_j, where P is the production K-matrix. // i = index for the state (e.g. S-wave index = 0). // Here, we only find the (I - iK*rho)^-1 matrix part. if (!kinematics) {return;} // Get the invariant mass squared (s) from the kinematics object. // Use the resPairAmpInt to find which mass-squared combination to use. Double_t s(0.0); if (resPairAmpInt_ == 1) { s = kinematics->getm23Sq(); } else if (resPairAmpInt_ == 2) { s = kinematics->getm13Sq(); } else if (resPairAmpInt_ == 3) { s = kinematics->getm12Sq(); } this->updatePropagator(s); } void LauKMatrixPropagator::updatePropagator(Double_t s) { // Calculate the K-matrix propagator for the given s value. // The K-matrix amplitude is given by // T_i = sum_{ij} (I - iK*rho)^-1 * P_j, where P is the production K-matrix. // i = index for the state (e.g. S-wave index = 0). // Here, we only find the (I - iK*rho)^-1 matrix part. // Check if we have almost the same s value as before. If so, don't re-calculate // the propagator nor any of the pole mass summation terms. if (TMath::Abs(s - previousS_) < 1e-6*s) { //cout<<"Already got propagator for s = "<calcPoleDenomVect(s); this->updateAdlerZeroFactor(s); // Calculate the scattering K-matrix (real and symmetric) this->calcScattKMatrix(s); // Calculate the phase space density matrix, which is diagonal, but can be complex // if the quantity s is below various threshold values (analytic continuation). this->calcRhoMatrix(s); // Calculate K*rho (real and imaginary parts, since rho can be complex) TMatrixD K_realRho(ScattKMatrix_); K_realRho *= ReRhoMatrix_; TMatrixD K_imagRho(ScattKMatrix_); K_imagRho *= ImRhoMatrix_; // A = I + K*Imag(rho), B = -K*Real(Rho) // Calculate C and D matrices such that (A + iB)*(C + iD) = I, // ie. C + iD = (I - i K*rho)^-1, separated into real and imaginary parts. // realProp C = (A + B A^-1 B)^-1, imagProp D = -A^-1 B C TMatrixD A(IMatrix_); A += K_imagRho; TMatrixD B(zeroMatrix_); B -= K_realRho; TMatrixD invA(TMatrixD::kInverted, A); TMatrixD invA_B(invA); invA_B *= B; TMatrixD B_invA_B(B); B_invA_B *= invA_B; TMatrixD invC(A); invC += B_invA_B; // Set the real part of the propagator matrix ("C") realProp_ = TMatrixD(TMatrixD::kInverted, invC); // Set the (negative) imaginary part of the propagator matrix ("-D") TMatrixD BC(B); BC *= realProp_; negImagProp_ = TMatrixD(invA); negImagProp_ *= BC; // Also calculate the production SVP term, since this uses Adler-zero parameters // defined in the parameter file. this->updateProdSVPTerm(s); // Finally, keep track of the value of s we just used. previousS_ = s; } void LauKMatrixPropagator::setParameters(const TString& inputFile) { // Read an input file that specifies the values of the coupling constants g_i for // the given number of poles and their (bare) masses. Also provided are the f_{ab} // slow-varying constants. The input file should also provide the Adler zero // constants s_0, s_A and s_A0. parametersSet_ = kFALSE; cout<<"Initialising K-matrix propagator "<Exit(EXIT_FAILURE); } UInt_t iLine(0); for (iLine = 1; iLine <= nTotLines; iLine++) { // Get the line of strings std::vector theLine = readFile.getLine(iLine); // There should always be at least two strings: a keyword and at least 1 value if (theLine.size() < 2) {continue;} TString keyword(theLine[0].c_str()); keyword.ToLower(); // Use lowercase if (!keyword.CompareTo("channels")) { // Channel indices for phase-space factors this->storeChannels(theLine); } else if (!keyword.CompareTo("pole")) { // Pole terms this->storePole(theLine); } else if (!keyword.CompareTo("scatt")) { // Scattering terms this->storeScattering(theLine); } else { // Usually Adler-zero constants TString parString(theLine[1].c_str()); this->storeParameter(keyword, parString); } } sAConst_ = 0.5*sA_.unblindValue()*LauConstants::mPiSq; // Symmetrise scattering parameters if enabled if (scattSymmetry_ == kTRUE) { for (Int_t iChannel = 0; iChannel < nChannels_; iChannel++) { for (Int_t jChannel = iChannel; jChannel < nChannels_; jChannel++) { LauParameter fPar = fScattering_[iChannel][jChannel]; fScattering_[jChannel][iChannel] = LauParameter(fPar); } } } // All required parameters have been set parametersSet_ = kTRUE; cout<<"Finished initialising K-matrix propagator "< >. // Set their sizes using the number of poles and channels defined in the constructor gCouplings_.clear(); gCouplings_.resize(nPoles_); for (Int_t iPole = 0; iPole < nPoles_; iPole++) { gCouplings_[iPole].resize(nChannels_); } fScattering_.clear(); fScattering_.resize(nChannels_); for (Int_t iChannel = 0; iChannel < nChannels_; iChannel++) { fScattering_[iChannel].resize(nChannels_); } // Clear other vectors phaseSpaceTypes_.clear(); phaseSpaceTypes_.resize(nChannels_); mSqPoles_.clear(); mSqPoles_.resize(nPoles_); } void LauKMatrixPropagator::storeChannels(const std::vector& theLine) { // Get the list of channel indices to specify what phase space factors should be used // e.g. pipi, Kpi, eta eta', 4pi etc.. // Check that the line has nChannels_+1 strings Int_t nTypes = static_cast(theLine.size()) - 1; if (nTypes != nChannels_) { cerr<<"Error in LauKMatrixPropagator::storeChannels. The input file defines " <checkPhaseSpaceType(phaseSpaceInt); if (checkChannel == kTRUE) { cout<<"Adding phase space channel index "<& theLine) { // Store the pole mass and its coupling constants for each channel. // Each line will contain: Pole poleNumber poleMass poleCouplingsPerChannel // Check that the line has nChannels_ + 3 strings Int_t nWords = static_cast(theLine.size()); Int_t nExpect = nChannels_ + 3; if (nWords == nExpect) { Int_t poleIndex = std::atoi(theLine[1].c_str()) - 1; if (poleIndex >= 0 && poleIndex < nPoles_) { Double_t poleMass = std::atof(theLine[2].c_str()); Double_t poleMassSq = poleMass*poleMass; LauParameter mPoleParam(poleMassSq); mSqPoles_[poleIndex] = mPoleParam; cout<<"Added bare pole mass "<& theLine) { // Store the scattering constants (along one of the channel rows). // Each line will contain: Scatt ScattIndex ScattConstantsPerChannel // Check that the line has nChannels_ + 2 strings Int_t nWords = static_cast(theLine.size()); Int_t nExpect = nChannels_ + 2; if (nWords == nExpect) { Int_t scattIndex = std::atoi(theLine[1].c_str()) - 1; if (scattIndex >= 0 && scattIndex < nChannels_) { for (Int_t iChannel = 0; iChannel < nChannels_; iChannel++) { Double_t scattConst = std::atof(theLine[iChannel+2].c_str()); LauParameter scattParam(scattConst); fScattering_[scattIndex][iChannel] = scattParam; cout<<"Added scattering parameter f("<updateScattSVPTerm(s); // Now loop over iChannel, jChannel to calculate Kij = Kji. for (iChannel = 0; iChannel < nChannels_; iChannel++) { // Scattering matrix is real and symmetric. Start j loop from i. for (jChannel = iChannel; jChannel < nChannels_; jChannel++) { Double_t Kij(0.0); // Calculate pole mass summation term for (iPole = 0; iPole < nPoles_; iPole++) { Double_t g_i = this->getCouplingConstant(iPole, iChannel); Double_t g_j = this->getCouplingConstant(iPole, jChannel); Kij += poleDenomVect_[iPole]*g_i*g_j; if (verbose_) {cout<<"1: Kij for i = "<getScatteringConstant(iChannel, jChannel); Kij += fij*scattSVP_; Kij *= adlerZeroFactor_; if (verbose_) {cout<<"2: Kij for i = "< 1.0e-6) {invPoleTerm = 1.0/poleTerm;} poleDenomVect_.push_back(invPoleTerm); } } Double_t LauKMatrixPropagator::getPoleDenomTerm(Int_t poleIndex) const { if (parametersSet_ == kFALSE) {return 0.0;} Double_t poleDenom(0.0); poleDenom = poleDenomVect_[poleIndex]; return poleDenom; } Double_t LauKMatrixPropagator::getCouplingConstant(Int_t poleIndex, Int_t channelIndex) const { if (parametersSet_ == kFALSE) {return 0.0;} if (poleIndex < 0 || poleIndex >= nPoles_) {return 0.0;} if (channelIndex < 0 || channelIndex >= nChannels_) {return 0.0;} Double_t couplingConst = gCouplings_[poleIndex][channelIndex].unblindValue(); return couplingConst; } Double_t LauKMatrixPropagator::getScatteringConstant(Int_t channel1Index, Int_t channel2Index) const { if (parametersSet_ == kFALSE) {return 0.0;} if (channel1Index < 0 || channel1Index >= nChannels_) {return 0.0;} if (channel2Index < 0 || channel2Index >= nChannels_) {return 0.0;} Double_t scatteringConst = fScattering_[channel1Index][channel2Index].unblindValue(); return scatteringConst; } Double_t LauKMatrixPropagator::calcSVPTerm(Double_t s, Double_t s0) const { if (parametersSet_ == kFALSE) {return 0.0;} // Calculate the "slowly-varying part" (SVP) Double_t result(0.0); Double_t deltaS = s - s0; if (TMath::Abs(deltaS) > 1.0e-6) { result = (mSq0_.unblindValue() - s0)/deltaS; } return result; } void LauKMatrixPropagator::updateScattSVPTerm(Double_t s) { // Update the scattering "slowly-varying part" (SVP) Double_t s0Scatt = s0Scatt_.unblindValue(); scattSVP_ = this->calcSVPTerm(s, s0Scatt); } void LauKMatrixPropagator::updateProdSVPTerm(Double_t s) { // Update the production "slowly-varying part" (SVP) Double_t s0Prod = s0Prod_.unblindValue(); prodSVP_ = this->calcSVPTerm(s, s0Prod); } void LauKMatrixPropagator::updateAdlerZeroFactor(Double_t s) { // Calculate the multiplicative factor containing various Adler zero // constants. adlerZeroFactor_ = 0.0; Double_t sA0Val = sA0_.unblindValue(); Double_t deltaS = s - sA0Val; if (TMath::Abs(deltaS) > 1e-6) { adlerZeroFactor_ = (s - sAConst_)*(1.0 - sA0Val)/deltaS; } } void LauKMatrixPropagator::calcRhoMatrix(Double_t s) { // Calculate the real and imaginary part of the phase space density // diagonal matrix for the given invariant mass squared quantity, s. // The matrix can be complex if s is below threshold (so that // the amplitude continues analytically). // Initialise all entries to zero ReRhoMatrix_.Zero(); ImRhoMatrix_.Zero(); LauComplex rho(0.0, 0.0); Int_t phaseSpaceIndex(0); for (Int_t iChannel (0); iChannel < nChannels_; ++iChannel) { phaseSpaceIndex = phaseSpaceTypes_[iChannel]; if (phaseSpaceIndex == LauKMatrixPropagator::PiPi) { rho = this->calcPiPiRho(s); } else if (phaseSpaceIndex == LauKMatrixPropagator::KK) { rho = this->calcKKRho(s); } else if (phaseSpaceIndex == LauKMatrixPropagator::FourPi) { rho = this->calcFourPiRho(s); } else if (phaseSpaceIndex == LauKMatrixPropagator::EtaEta) { rho = this->calcEtaEtaRho(s); } else if (phaseSpaceIndex == LauKMatrixPropagator::EtaEtaP) { rho = this->calcEtaEtaPRho(s); } else if (phaseSpaceIndex == LauKMatrixPropagator::KPi) { rho = this->calcKPiRho(s); } else if (phaseSpaceIndex == LauKMatrixPropagator::KEtaP) { rho = this->calcKEtaPRho(s); } else if (phaseSpaceIndex == LauKMatrixPropagator::KThreePi) { rho = this->calcKThreePiRho(s); } if (verbose_) { cout<<"ReRhoMatrix("< 4pi state). // The normalisation term rho_0 is found by ensuring that the phase space integral // at s = 1 is equal to sqrt(1.0 - 16*mpiSq/s). Note that the exponent for this // factor in hep-ph/0204328 is wrong; it should be 0.5, i.e. sqrt, not n = 1 to 5. // Plotting the value of this double integral as a function of s can then be fitted // to a 6th-order polynomial (for s < 1), which is the result used below LauComplex rho(0.0, 0.0); if (TMath::Abs(s) < 1e-10) {return rho;} if (s <= 1.0) { Double_t rhoTerm = ((1.07885*s + 0.13655)*s - 0.29744)*s - 0.20840; rhoTerm = ((rhoTerm*s + 0.13851)*s - 0.01933)*s + 0.00051; // For some values of s (below 2*mpi), this term is a very small // negative number. Check for this and set the rho term to zero. if (rhoTerm < 0.0) {rhoTerm = 0.0;} rho.setRealPart( rhoTerm ); } else { rho.setRealPart( TMath::Sqrt(1.0 - (fourPiFactor1_/s)) ); } return rho; } LauComplex LauKMatrixPropagator::calcEtaEtaRho(Double_t s) const { // Calculate the eta-eta phase space factor LauComplex rho(0.0, 0.0); if (TMath::Abs(s) < 1e-10) {return rho;} Double_t sqrtTerm = (-m2EtaSq_/s) + 1.0; if (sqrtTerm < 0.0) { rho.setImagPart( TMath::Sqrt(-sqrtTerm) ); } else { rho.setRealPart( TMath::Sqrt(sqrtTerm) ); } return rho; } LauComplex LauKMatrixPropagator::calcEtaEtaPRho(Double_t s) const { // Calculate the eta-eta' phase space factor. Note that the // mass difference term m_eta - m_eta' is not included, // since this corresponds to a "t or u-channel crossing", // which means that we cannot simply analytically continue // this part of the phase space factor below threshold, which // we can do for s-channel contributions. This is actually an // unsolved problem, e.g. see Guo et al 1409.8652, and // Danilkin et al 1409.7708. Anisovich and Sarantsev in // hep-ph/0204328 "solve" this issue by setting the mass // difference term to unity, which is what we do here... LauComplex rho(0.0, 0.0); if (TMath::Abs(s) < 1e-10) {return rho;} Double_t sqrtTerm = (-mEtaEtaPSumSq_/s) + 1.0; if (sqrtTerm < 0.0) { rho.setImagPart( TMath::Sqrt(-sqrtTerm) ); } else { rho.setRealPart( TMath::Sqrt(sqrtTerm) ); } return rho; } LauComplex LauKMatrixPropagator::calcKPiRho(Double_t s) const { // Calculate the K-pi phase space factor LauComplex rho(0.0, 0.0); if (TMath::Abs(s) < 1e-10) {return rho;} Double_t sqrtTerm1 = (-mKpiSumSq_/s) + 1.0; Double_t sqrtTerm2 = (-mKpiDiffSq_/s) + 1.0; Double_t sqrtTerm = sqrtTerm1*sqrtTerm2; if (sqrtTerm < 0.0) { rho.setImagPart( TMath::Sqrt(-sqrtTerm) ); } else { rho.setRealPart( TMath::Sqrt(sqrtTerm) ); } return rho; } LauComplex LauKMatrixPropagator::calcKEtaPRho(Double_t s) const { // Calculate the K-eta' phase space factor LauComplex rho(0.0, 0.0); if (TMath::Abs(s) < 1e-10) {return rho;} Double_t sqrtTerm1 = (-mKEtaPSumSq_/s) + 1.0; Double_t sqrtTerm2 = (-mKEtaPDiffSq_/s) + 1.0; Double_t sqrtTerm = sqrtTerm1*sqrtTerm2; if (sqrtTerm < 0.0) { rho.setImagPart( TMath::Sqrt(-sqrtTerm) ); } else { rho.setRealPart( TMath::Sqrt(sqrtTerm) ); } return rho; } LauComplex LauKMatrixPropagator::calcKThreePiRho(Double_t s) const { // Calculate the Kpipipi + multimeson phase space factor. // Use the simplest definition in hep-ph/9705401 (Eq 14), which is the form // used for the rest of that paper (thankfully, the amplitude does not depend // significantly on the form used for the K3pi phase space factor). LauComplex rho(0.0, 0.0); if (TMath::Abs(s) < 1e-10) {return rho;} if (s < 1.44) { Double_t powerTerm = (-mK3piDiffSq_/s) + 1.0; if (powerTerm < 0.0) { rho.setImagPart( k3piFactor_*TMath::Power(-powerTerm, 2.5) ); } else { rho.setRealPart( k3piFactor_*TMath::Power(powerTerm, 2.5) ); } } else { rho.setRealPart( 1.0 ); } return rho; } Bool_t LauKMatrixPropagator::checkPhaseSpaceType(Int_t phaseSpaceInt) const { Bool_t passed(kFALSE); if (phaseSpaceInt >= 1 && phaseSpaceInt < LauKMatrixPropagator::TotChannels) { passed = kTRUE; } return passed; } LauComplex LauKMatrixPropagator::getTransitionAmp(Double_t s, Int_t channel) { // Get the complex (unitary) transition amplitude T for the given channel LauComplex TAmp(0.0, 0.0); channel -= 1; if (channel < 0 || channel >= nChannels_) {return TAmp;} this->getTMatrix(s); TAmp.setRealPart(ReTMatrix_[index_][channel]); TAmp.setImagPart(ImTMatrix_[index_][channel]); return TAmp; } LauComplex LauKMatrixPropagator::getPhaseSpaceTerm(Double_t s, Int_t channel) { // Get the complex (unitary) transition amplitude T for the given channel LauComplex rho(0.0, 0.0); channel -= 1; if (channel < 0 || channel >= nChannels_) {return rho;} // If s has changed from the previous value, recalculate rho if (TMath::Abs(s - previousS_) > 1e-6*s) { this->calcRhoMatrix(s); } rho.setRealPart(ReRhoMatrix_[channel][channel]); rho.setImagPart(ImRhoMatrix_[channel][channel]); return rho; } void LauKMatrixPropagator::getTMatrix(const LauKinematics* kinematics) { // Find the unitary T matrix, where T = [sqrt(rho)]^{*} T_hat sqrt(rho), // and T_hat = (I - i K rho)^-1 * K is the Lorentz-invariant T matrix, // which has phase-space factors included (rho). This function is not // needed to calculate the K-matrix amplitudes, but allows us // to check the variation of T as a function of s (kinematics) if (!kinematics) {return;} // Get the invariant mass squared (s) from the kinematics object. // Use the resPairAmpInt to find which mass-squared combination to use. Double_t s(0.0); if (resPairAmpInt_ == 1) { s = kinematics->getm23Sq(); } else if (resPairAmpInt_ == 2) { s = kinematics->getm13Sq(); } else if (resPairAmpInt_ == 3) { s = kinematics->getm12Sq(); } this->getTMatrix(s); } void LauKMatrixPropagator::getTMatrix(Double_t s) { // Find the unitary transition T matrix, where // T = [sqrt(rho)]^{*} T_hat sqrt(rho), and // T_hat = (I - i K rho)^-1 * K is the Lorentz-invariant T matrix, // which has phase-space factors included (rho). Note that the first // sqrt of the rho matrix is complex conjugated. // This function is not needed to calculate the K-matrix amplitudes, but // allows us to check the variation of T as a function of s (kinematics) // Initialse the real and imaginary parts of the T matrix to zero ReTMatrix_.Zero(); ImTMatrix_.Zero(); if (parametersSet_ == kFALSE) {return;} // Update K, rho and the propagator (I - i K rho)^-1 this->updatePropagator(s); // Find the real and imaginary T_hat matrices TMatrixD THatReal = realProp_*ScattKMatrix_; TMatrixD THatImag(zeroMatrix_); THatImag -= negImagProp_*ScattKMatrix_; // Find the square-root of the phase space matrix this->getSqrtRhoMatrix(); // Let sqrt(rho) = A + iB and T_hat = C + iD // => T = A(CA-DB) + B(DA+CB) + i[A(DA+CB) + B(DB-CA)] TMatrixD CA(THatReal); CA *= ReSqrtRhoMatrix_; TMatrixD DA(THatImag); DA *= ReSqrtRhoMatrix_; TMatrixD CB(THatReal); CB *= ImSqrtRhoMatrix_; TMatrixD DB(THatImag); DB *= ImSqrtRhoMatrix_; TMatrixD CAmDB(CA); CAmDB -= DB; TMatrixD DApCB(DA); DApCB += CB; TMatrixD DBmCA(DB); DBmCA -= CA; // Find the real and imaginary parts of the transition matrix T ReTMatrix_ = ReSqrtRhoMatrix_*CAmDB + ImSqrtRhoMatrix_*DApCB; ImTMatrix_ = ReSqrtRhoMatrix_*DApCB + ImSqrtRhoMatrix_*DBmCA; } void LauKMatrixPropagator::getSqrtRhoMatrix() { // Find the square root of the (current) phase space matrix so that // we can find T = [sqrt(rho)}^{*} T_hat sqrt(rho), where T_hat is the // Lorentz-invariant T matrix = (I - i K rho)^-1 * K; note that the first // sqrt of rho matrix is complex conjugated // If rho = rho_i + i rho_r = a + i b, then sqrt(rho) = c + i d, where // c = sqrt(0.5*(r+a)) and d = sqrt(0.5(r-a)), where r = sqrt(a^2 + b^2). // Since rho is diagonal, then the square root of rho will also be diagonal, // with its real and imaginary matrix elements equal to c and d, respectively // Initialise the real and imaginary parts of the square root of // the rho matrix to zero ReSqrtRhoMatrix_.Zero(); ImSqrtRhoMatrix_.Zero(); for (Int_t iChannel (0); iChannel < nChannels_; ++iChannel) { Double_t realRho = ReRhoMatrix_[iChannel][iChannel]; Double_t imagRho = ImRhoMatrix_[iChannel][iChannel]; Double_t rhoMag = sqrt(realRho*realRho + imagRho*imagRho); Double_t rhoSum = rhoMag + realRho; Double_t rhoDiff = rhoMag - realRho; Double_t reSqrtRho(0.0), imSqrtRho(0.0); if (rhoSum > 0.0) {reSqrtRho = sqrt(0.5*rhoSum);} if (rhoDiff > 0.0) {imSqrtRho = sqrt(0.5*rhoDiff);} ReSqrtRhoMatrix_[iChannel][iChannel] = reSqrtRho; ImSqrtRhoMatrix_[iChannel][iChannel] = imSqrtRho; } } LauComplex LauKMatrixPropagator::getTHat(Double_t s, Int_t channel) { LauComplex THat(0.0, 0.0); channel -= 1; if (channel < 0 || channel >= nChannels_) {return THat;} this->updatePropagator(s); // Find the real and imaginary T_hat matrices TMatrixD THatReal = realProp_*ScattKMatrix_; TMatrixD THatImag(zeroMatrix_); THatImag -= negImagProp_*ScattKMatrix_; // Return the specific THat component THat.setRealPart(THatReal[index_][channel]); THat.setImagPart(THatImag[index_][channel]); return THat; } diff --git a/src/LauKappaRes.cc b/src/LauKappaRes.cc index ba10e34..24834d2 100644 --- a/src/LauKappaRes.cc +++ b/src/LauKappaRes.cc @@ -1,300 +1,299 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauKappaRes.cc \brief File containing implementation of LauKappaRes class. */ #include #include "LauConstants.hh" #include "LauKappaRes.hh" #include "LauResonanceInfo.hh" -ClassImp(LauKappaRes) LauKappaRes::LauKappaRes(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), mSumSq_((LauConstants::mPi+LauConstants::mK)*(LauConstants::mPi+LauConstants::mK)), sAdler_(LauConstants::mKSq-0.5*LauConstants::mPiSq), b1_(0), b2_(0), a_(0), m0_(0) { // Default constant factors from BES data const Double_t b1Val = 24.49; const Double_t b2Val = 0.0; const Double_t aVal = 2.5; const Double_t m0Val = 3.3; const TString& parNameBase = this->getSanitisedName(); TString b1Name(parNameBase); b1Name += "_b1"; b1_ = resInfo->getExtraParameter( b1Name ); if ( b1_ == 0 ) { b1_ = new LauParameter( b1Name, b1Val, 0.0, 100.0, kTRUE ); b1_->secondStage(kTRUE); resInfo->addExtraParameter( b1_ ); } TString b2Name(parNameBase); b2Name += "_b2"; b2_ = resInfo->getExtraParameter( b2Name ); if ( b2_ == 0 ) { b2_ = new LauParameter( b2Name, b2Val, 0.0, 100.0, kTRUE ); b2_->secondStage(kTRUE); resInfo->addExtraParameter( b2_ ); } TString aName(parNameBase); aName += "_A"; a_ = resInfo->getExtraParameter( aName ); if ( a_ == 0 ) { a_ = new LauParameter( aName, aVal, 0.0, 10.0, kTRUE ); a_->secondStage(kTRUE); resInfo->addExtraParameter( a_ ); } TString m0Name(parNameBase); m0Name += "_m0"; m0_ = resInfo->getExtraParameter( m0Name ); if ( m0_ == 0 ) { m0_ = new LauParameter( m0Name, m0Val, 0.0, 10.0, kTRUE ); m0_->secondStage(kTRUE); resInfo->addExtraParameter( m0_ ); } } LauKappaRes::~LauKappaRes() { } void LauKappaRes::initialise() { this->checkDaughterTypes(); Double_t resSpin = this->getSpin(); if (resSpin != 0) { std::cerr << "WARNING in LauKappaRes::initialise : Resonance spin is " << resSpin << "." << std::endl; std::cerr << " : Kappa amplitude is only for scalers, resetting spin to 0." << std::endl; this->changeResonance( -1.0, -1.0, 0 ); } } void LauKappaRes::checkDaughterTypes() const { // Check that the daughter tracks are K and pi. Otherwise issue a warning. Int_t resPairAmpInt = this->getPairInt(); if (resPairAmpInt < 1 || resPairAmpInt > 3) { std::cerr << "WARNING in LauKappaRes::checkDaughterTypes : resPairAmpInt = " << resPairAmpInt << " is out of the range [1,2,3]." << std::endl; return; } const TString& nameDaug1 = this->getNameDaug1(); const TString& nameDaug2 = this->getNameDaug2(); if ( !( nameDaug1.Contains("pi", TString::kIgnoreCase) && nameDaug2.Contains("k", TString::kIgnoreCase) ) ) { if ( !( nameDaug2.Contains("pi", TString::kIgnoreCase) && nameDaug1.Contains("k", TString::kIgnoreCase) ) ) { std::cerr << "ERROR in LauKappaRes::checkDaughterTypes : Kappa model is using daughters \"" << nameDaug1 << "\" and \"" << nameDaug2 << "\" that are not a kaon and a pion." << std::endl; } } } LauComplex LauKappaRes::resAmp(Double_t mass, Double_t spinTerm) { // This function returns the complex dynamical amplitude for a Kappa distribution // given the invariant mass and cos(helicity) values. // First check that the appropriate daughters are either pi+pi- or K+K- // Check that the daughter tracks are the same type. Otherwise issue a warning // and set the type to be pion for the Kappa distribution. Returns the // integer defined by the enum LauKappaRes::KappaPartType. Double_t s = mass*mass; // Invariant mass squared combination for the system Double_t rho(0.0); // Phase-space factor if (s > mSumSq_) {rho = TMath::Sqrt(1.0 - mSumSq_/s);} const Double_t m0Val = this->getM0Value(); const Double_t m0Sq = m0Val * m0Val; const Double_t aVal = this->getAValue(); const Double_t b1Val = this->getB1Value(); const Double_t b2Val = this->getB2Value(); Double_t f = b2Val*s + b1Val; // f(s) function Double_t numerator = s - sAdler_; Double_t denom = m0Sq - sAdler_; Double_t gamma(0.0); if (TMath::Abs(denom) > 1e-10 && TMath::Abs(aVal) > 1e-10) { // Decay width of the system gamma = rho*(numerator/denom)*f*TMath::Exp(-(s - m0Sq)/aVal); } // Now form the complex amplitude - use relativistic BW form (without barrier factors) // Note that the M factor in the denominator is not the "pole" at ~500 MeV, but is // m0_ = 0.9264, the mass when the phase shift goes through 90 degrees. Double_t dMSq = m0Sq - s; Double_t widthTerm = gamma*m0Val; LauComplex resAmplitude(dMSq, widthTerm); Double_t denomFactor = dMSq*dMSq + widthTerm*widthTerm; Double_t invDenomFactor = 0.0; if (denomFactor > 1e-10) {invDenomFactor = 1.0/denomFactor;} resAmplitude.rescale(spinTerm*invDenomFactor); return resAmplitude; } const std::vector& LauKappaRes::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixB1Value() ) { this->addFloatingParameter( b1_ ); } if ( ! this->fixB2Value() ) { this->addFloatingParameter( b2_ ); } if ( ! this->fixAValue() ) { this->addFloatingParameter( a_ ); } if ( ! this->fixM0Value() ) { this->addFloatingParameter( m0_ ); } return this->getParameters(); } void LauKappaRes::setResonanceParameter(const TString& name, const Double_t value) { // Set various parameters for the lineshape if (name == "b1") { this->setB1Value(value); std::cout << "INFO in LauKappaRes::setResonanceParameter : Setting parameter b1 = " << this->getB1Value() << std::endl; } else if (name == "b2") { this->setB2Value(value); std::cout << "INFO in LauKappaRes::setResonanceParameter : Setting parameter b2 = " << this->getB2Value() << std::endl; } else if (name == "A") { this->setAValue(value); std::cout << "INFO in LauKappaRes::setResonanceParameter : Setting parameter A = " << this->getAValue() << std::endl; } else if (name == "m0") { this->setM0Value(value); std::cout << "INFO in LauKappaRes::setResonanceParameter : Setting parameter m0 = " << this->getM0Value() << std::endl; } else { std::cerr << "WARNING in LauKappaRes::setResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } void LauKappaRes::floatResonanceParameter(const TString& name) { if (name == "b1") { if ( b1_->fixed() ) { b1_->fixed( kFALSE ); this->addFloatingParameter( b1_ ); } else { std::cerr << "WARNING in LauKappaRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "b2") { if ( b2_->fixed() ) { b2_->fixed( kFALSE ); this->addFloatingParameter( b2_ ); } else { std::cerr << "WARNING in LauKappaRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "A") { if ( a_->fixed() ) { a_->fixed( kFALSE ); this->addFloatingParameter( a_ ); } else { std::cerr << "WARNING in LauKappaRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "m0") { if ( m0_->fixed() ) { m0_->fixed( kFALSE ); this->addFloatingParameter( m0_ ); } else { std::cerr << "WARNING in LauKappaRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else { std::cerr << "WARNING in LauKappaRes::fixResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } LauParameter* LauKappaRes::getResonanceParameter(const TString& name) { if (name == "b1") { return b1_; } else if (name == "b2") { return b2_; } else if (name == "A") { return a_; } else if (name == "m0") { return m0_; } else { std::cerr << "WARNING in LauKappaRes::getResonanceParameter: Parameter name not reconised." << std::endl; return 0; } } void LauKappaRes::setB1Value(const Double_t b1) { b1_->value( b1 ); b1_->genValue( b1 ); b1_->initValue( b1 ); } void LauKappaRes::setB2Value(const Double_t b2) { b2_->value( b2 ); b2_->genValue( b2 ); b2_->initValue( b2 ); } void LauKappaRes::setAValue(const Double_t A) { a_->value( A ); a_->genValue( A ); a_->initValue( A ); } void LauKappaRes::setM0Value(const Double_t m0) { m0_->value( m0 ); m0_->genValue( m0 ); m0_->initValue( m0 ); } diff --git a/src/LauKinematics.cc b/src/LauKinematics.cc index eb7d9f4..98499dc 100644 --- a/src/LauKinematics.cc +++ b/src/LauKinematics.cc @@ -1,744 +1,743 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauKinematics.cc \brief File containing implementation of LauKinematics class. */ #include #include "TF2.h" #include "TMath.h" #include "TRandom.h" #include "LauConstants.hh" #include "LauKinematics.hh" #include "LauRandom.hh" -ClassImp(LauKinematics) LauKinematics::LauKinematics(const Double_t m1, const Double_t m2, const Double_t m3, const Double_t mParent, const Bool_t calcSquareDPCoords, const Bool_t symmetricalDP, const Bool_t fullySymmetricDP) : symmetricalDP_(symmetricalDP), fullySymmetricDP_(fullySymmetricDP), m1_(m1), m2_(m2), m3_(m3), mParent_(mParent), m1Sq_(m1*m1), m2Sq_(m2*m2), m3Sq_(m3*m3), mParentSq_(mParent*mParent), mDTot_(m1 + m2 + m3), massInt_(mParent - (m1+m2+m3)), mSqDTot_(m1*m1 + m2*m2 + m3*m3), m12_(0.0), m23_(0.0), m13_(0.0), m12Sq_(0.0), m23Sq_(0.0), m13Sq_(0.0), c12_(0.0), c23_(0.0), c13_(0.0), mPrime_(0.0), thetaPrime_(0.0), qi_(0.0), qk_(0.0), p1_12_(0.0), p3_12_(0.0), p2_23_(0.0), p1_23_(0.0), p1_13_(0.0), p2_13_(0.0), p1_Parent_(0.0), p2_Parent_(0.0), p3_Parent_(0.0), squareDP_(calcSquareDPCoords), warnings_(kTRUE) { // Constructor mass_.clear(); mMin_.clear(); mMax_.clear(); mSqMin_.clear(); mSqMax_.clear(); mSq_.clear(); mSqDiff_.clear(); mDiff_.clear(); mass_.push_back(m1_); mass_.push_back(m2_); mass_.push_back(m3_); mSq_.push_back(m1Sq_); mSq_.push_back(m2Sq_); mSq_.push_back(m3Sq_); // DP max and min kinematic boundary for circumscribed box // (see figure in PDG book). for (Int_t i = 0; i < 3; i++) { mMin_.push_back(mDTot_ - mass_[i]); mMax_.push_back(mParent_ - mass_[i]); mSqMin_.push_back(mMin_[i]*mMin_[i]); mSqMax_.push_back(mMax_[i]*mMax_[i]); mSqDiff_.push_back(mSqMax_[i] - mSqMin_[i]); mDiff_.push_back(mMax_[i] - mMin_[i]); } if (this->squareDP()) { std::cout<<"INFO in LauKinematics::LauKinematics : squareDP = kTRUE"<updateMassSquares(m13Sq, m23Sq); // Now update the helicity cosines this->calcHelicities(); // Also calculate the m', theta' variables if (squareDP_) {this->calcSqDPVars();} } void LauKinematics::updateSqDPKinematics(const Double_t mPrime, const Double_t thetaPrime) { // From square DP co-ordinates, calculate remaining kinematic variables this->updateSqDPMassSquares(mPrime, thetaPrime); // Finally calculate the helicities and track momenta this->calcHelicities(); } void LauKinematics::calcSqDPVars() { // For given m_12 and cos(theta_12) values, calculate m' and theta' for the square Dalitz plot Double_t value = (2.0*(m12_ - mMin_[2])/mDiff_[2]) - 1.0; mPrime_ = LauConstants::invPi*TMath::ACos(value); thetaPrime_ = LauConstants::invPi*TMath::ACos(c12_); // Sometimes events are assigned exactly thetaPrime = 0.0 or 1.0 // which gives problems with efficiency and other histograms if (thetaPrime_ == 0.0) { thetaPrime_ += 1.0e-10; } else if (thetaPrime_ == 1.0) { thetaPrime_ -= 1.0e-10; } } Double_t LauKinematics::calcSqDPJacobian() const { return this->calcSqDPJacobian(mPrime_,thetaPrime_); } Double_t LauKinematics::calcSqDPJacobian(const Double_t mPrime, const Double_t thPrime) const { // Calculate the Jacobian for the transformation // m23^2, m13^2 -> m', theta' (square DP) const Double_t m12 = 0.5*mDiff_[2]*(1.0 + TMath::Cos(LauConstants::pi*mPrime)) + mMin_[2]; const Double_t m12Sq = m12*m12; const Double_t e1Cms12 = (m12Sq - m2Sq_ + m1Sq_)/(2.0*m12); const Double_t e3Cms12 = (mParentSq_ - m12Sq - m3Sq_)/(2.0*m12); const Double_t p1Cms12 = this->pCalc(e1Cms12, m1Sq_); const Double_t p3Cms12 = this->pCalc(e3Cms12, m3Sq_); const Double_t deriv1 = LauConstants::piBy2*mDiff_[2]*TMath::Sin(LauConstants::pi*mPrime); const Double_t deriv2 = LauConstants::pi*TMath::Sin(LauConstants::pi*thPrime); const Double_t jacobian = 4.0*p1Cms12*p3Cms12*m12*deriv1*deriv2; return jacobian; } void LauKinematics::updateMassSquares(const Double_t m13Sq, const Double_t m23Sq) { m13Sq_ = m13Sq; if (m13Sq_ > 0.0) { m13_ = TMath::Sqrt(m13Sq_); } else { m13_ = 0.0; } m23Sq_ = m23Sq; if (m23Sq_ > 0.0) { m23_ = TMath::Sqrt(m23Sq_); } else { m23_ = 0.0; } // Now calculate m12Sq and m12. this->calcm12Sq(); // Calculate momenta of tracks in parent (B, D etc.) rest-frame this->calcParentFrameMomenta(); } void LauKinematics::updateSqDPMassSquares(const Double_t mPrime, const Double_t thetaPrime) { // From square DP co-ordinates, calculate only the mass-squares // First set the square-DP variables mPrime_ = mPrime; thetaPrime_ = thetaPrime; // Next calculate m12 and c12 Double_t m12 = 0.5*mDiff_[2]*(1.0 + TMath::Cos(LauConstants::pi*mPrime)) + mMin_[2]; Double_t c12 = TMath::Cos(LauConstants::pi*thetaPrime); // From these calculate m13Sq and m23Sq this->updateMassSq_m12(m12, c12); // Calculate momenta of tracks in parent (B, D etc.) rest-frame this->calcParentFrameMomenta(); } void LauKinematics::calcm12Sq() { // Calculate m12Sq from m13Sq and m23Sq. m12Sq_ = mParentSq_ + mSqDTot_ - m13Sq_ - m23Sq_; // If m12Sq is too low, return lower limit, // and modify m13Sq accordingly. if (m12Sq_ < mSqMin_[2]) { m12Sq_ = mSqMin_[2] + 1.0e-3; m13Sq_ = mParentSq_ + mSqDTot_ - m12Sq_ - m23Sq_; } if (m12Sq_ > 0.0) { m12_ = TMath::Sqrt(m12Sq_); } else { m12_ = 0.0; } } void LauKinematics::calcParentFrameMomenta() { Double_t e1 = (mParentSq_ + m1Sq_ - m23Sq_) / (2.0*mParent_); Double_t e2 = (mParentSq_ + m2Sq_ - m13Sq_) / (2.0*mParent_); Double_t e3 = (mParentSq_ + m3Sq_ - m12Sq_) / (2.0*mParent_); p1_Parent_ = this->pCalc(e1, m1Sq_); p2_Parent_ = this->pCalc(e2, m2Sq_); p3_Parent_ = this->pCalc(e3, m3Sq_); } void LauKinematics::calcHelicities() { // Calculate helicity angle cosines, given m12Sq, m13Sq and m23Sq. // cij_ is the cosine of the helicity angle in the rest frame of the // system of particles i and j. // It is (but note the caveat below) the angle between tracks i and k // in the ij rest frame with indices permuted cyclically. // However, it is important to note that it is not exactly a cyclic // permutation (there is a special treatment for c23 inside the cFromM // function) for reasons of preserving the symmetry about m13=m23 for // symmetric final states. // The precise definitions are: // theta12 is defined as the angle between 1&3 in the rest frame of 1&2 // theta23 is defined as the angle between 3&1 in the rest frame of 2&3 // theta13 is defined as the angle between 3&2 in the rest frame of 1&3 // // It is a prerequisite that all mij_ and mijSq_ variables be correctly set. Int_t zero(0), one(1), two(2); c12_ = cFromM(m12Sq_, m13Sq_, m12_, zero, one, two); p1_12_ = qi_; p3_12_ = qk_; // i, j = 12 (rest frame), k = 3 c23_ = cFromM(m23Sq_, m12Sq_, m23_, one, two, zero); p2_23_ = qi_; p1_23_ = qk_; // i, j = 23 (rest frame), k = 1 c13_ = cFromM(m13Sq_, m23Sq_, m13_, two, zero, one); p1_13_ = qi_; p2_13_ = qk_; // i, j = 31 (rest frame), k = 2 } Double_t LauKinematics::cFromM(const Double_t mijSq, const Double_t mikSq, const Double_t mij, const Int_t i, const Int_t j, const Int_t k) const { // Routine to calculate the cos(helicity) variables from the masses of the particles. // (See comment in LauKinematics::calcHelicities for futher information.) Double_t EiCmsij = (mijSq - mSq_[j] + mSq_[i])/(2.0*mij); Double_t EkCmsij = (mParentSq_ - mijSq - mSq_[k])/(2.0*mij); if (EiCmsij < mass_[i]) { if (warnings_) { std::cerr<<"WARNING in LauKinematics::cFromM : EiCmsij = "< 1e-6 && EkCmsij < mass_[k]) { if (warnings_) { std::cerr<<"WARNING in LauKinematics::mFromC : EkCmsij = "<pCalc(EiCmsij, mSq_[i]); Double_t qk = this->pCalc(EkCmsij, mSq_[k]); // Find mikSq Double_t massSq = mSq_[i] + mSq_[k] + 2.0*EiCmsij*EkCmsij - 2.0*qi*qk*cosHel; if (massSq < mSqMin_[j]) { if (warnings_) { std::cerr<<"WARNING in LauKinematics::mFromC : mFromC below bound: i, j, k = "<Rndm()*mSqDiff_[1]; m23Sq = mSqMin_[0] + LauRandom::randomFun()->Rndm()*mSqDiff_[0]; } while ( ! this->withinDPLimits( m13Sq, m23Sq ) ); } void LauKinematics::genFlatSqDP(Double_t& mPrime, Double_t& thetaPrime) const { // Generate random event in the square Dalitz plot mPrime = LauRandom::randomFun()->Rndm(); thetaPrime = LauRandom::randomFun()->Rndm(); } Bool_t LauKinematics::withinDPLimits(const Double_t m13Sq, const Double_t m23Sq) const { // Find out whether the point (m13Sq,m23Sq) is within the limits of the // Dalitz plot. The limits are specified by the invariant masses // of the parent (e.g. B) and its three daughters that were // defined in the constructor of this class. Here // m_13Sq = square of invariant mass of daughters 1 and 3 // m_23Sq = square of invariant mass of daughters 2 and 3. Bool_t withinDP = kFALSE; // First check that m13Sq is within its absolute min and max if (!((m13Sq > mSqMin_[1]) && (m13Sq < mSqMax_[1]))) { return kFALSE; } // Now for the given value of m13Sq calculate the local min and max of m23Sq Double_t m13 = TMath::Sqrt(m13Sq); Double_t e3Cms13 = (m13Sq - m1Sq_ + m3Sq_)/(2.0*m13); Double_t p3Cms13 = this->pCalc(e3Cms13, m3Sq_); Double_t e2Cms13 = (mParentSq_ - m13Sq - m2Sq_)/(2.0*m13); Double_t p2Cms13 = this->pCalc(e2Cms13, m2Sq_); Double_t term = 2.0*e2Cms13*e3Cms13 + m2Sq_ + m3Sq_; Double_t m23SqLocMin = term - 2.0*p2Cms13*p3Cms13; Double_t m23SqLocMax = term + 2.0*p2Cms13*p3Cms13; // Check whether the given value of m23Sq satisfies these bounds if (m23Sq > m23SqLocMin && m23Sq < m23SqLocMax) { withinDP = kTRUE; } return withinDP; } Bool_t LauKinematics::withinDPLimits2(const Double_t m13Sq, const Double_t m23Sq) const { // Same as withinDPLimits, but this time testing whether the m13Sq // variable is within the kinematic boundary for the given m23Sq value Bool_t withinDP = kFALSE; // First check that m13Sq is within its absolute min and max if (!((m23Sq > mSqMin_[0]) && (m23Sq < mSqMax_[0]))) { return kFALSE; } // Now for the given value of m13Sq calculate the local min and max of m23Sq Double_t m23 = TMath::Sqrt(m23Sq); Double_t e3Cms23 = (m23Sq - m2Sq_ + m3Sq_)/(2.0*m23); Double_t p3Cms23 = this->pCalc(e3Cms23, m3Sq_); Double_t e1Cms23 = (mParentSq_ - m23Sq - m1Sq_)/(2.0*m23); Double_t p1Cms23 = this->pCalc(e1Cms23, m1Sq_); Double_t term = 2.0*e3Cms23*e1Cms23 + m1Sq_ + m3Sq_; Double_t m13SqLocMin = term - 2.0*p3Cms23*p1Cms23; Double_t m13SqLocMax = term + 2.0*p3Cms23*p1Cms23; // Check whether the given value of m23Sq satisfies these bounds if (m13Sq > m13SqLocMin && m13Sq < m13SqLocMax) { withinDP = kTRUE; } return withinDP; } Bool_t LauKinematics::withinSqDPLimits(const Double_t mPrime, const Double_t thetaPrime) const { // Check whether m' and theta' are between 0 and 1 Bool_t withinDP(kFALSE); if (mPrime > 0.0 && mPrime < 1.0 && thetaPrime > 0.0 && thetaPrime < 1.0) { withinDP = kTRUE; } return withinDP; } Double_t LauKinematics::calcThirdMassSq(const Double_t firstMassSq, const Double_t secondMassSq) const { // Calculate one massSq from the other two return mParentSq_ + mSqDTot_ - firstMassSq - secondMassSq; } Double_t LauKinematics::distanceFromDPCentre() const { return this->distanceFromDPCentre(m13Sq_,m23Sq_); } Double_t LauKinematics::distanceFromDPCentre(const Double_t m13Sq, const Double_t m23Sq) const { // DP centre is defined as the point where m12=m13=m23 // First find the m^2_ij value for the centre Double_t centreMijSq = (mParentSq_ + m1Sq_ + m2Sq_ + m3Sq_)/3.0; // Then find the difference between this and the two provided co-ords Double_t diff13 = m13Sq - centreMijSq; Double_t diff23 = m23Sq - centreMijSq; // Calculate the total distance Double_t distance = TMath::Sqrt(diff13*diff13 + diff23*diff23); return distance; } Double_t LauKinematics::pCalc(const Double_t energy, const Double_t massSq) const { // Routine to calculate the momentum of a particle, given its energy and // invariant mass (squared). Double_t arg = energy*energy - massSq; if (arg < 0.0) { //if (warnings_) { //std::cerr<<"WARNING in LauKinematics::pCalc : arg < 0.0: "<SetParameter(0,mParent); if (orientation == 1323) { f2->SetParameter(1,m1); f2->SetParameter(2,m2); f2->SetParameter(3,m3); } else if (orientation == 2313) { f2->SetParameter(1,m2); f2->SetParameter(2,m1); f2->SetParameter(3,m3); } else if (orientation == 1213) { f2->SetParameter(1,m2); f2->SetParameter(2,m3); f2->SetParameter(3,m1); } else if (orientation == 1312) { f2->SetParameter(1,m3); f2->SetParameter(2,m2); f2->SetParameter(3,m1); } else if (orientation == 1223) { f2->SetParameter(1,m1); f2->SetParameter(2,m3); f2->SetParameter(3,m2); } else if (orientation == 2312) { f2->SetParameter(1,m3); f2->SetParameter(2,m1); f2->SetParameter(3,m2); } // Set up the contour to be drawn when the value of the function == 1.0 Double_t b[]={1.0}; f2->SetContour(1,b); // Set the number of bins for the contour to be sampled over f2->SetNpx(nbins); f2->SetNpy(nbins); // and the line style f2->SetLineWidth(3); f2->SetLineStyle(kSolid); // Draw the contour on top of the histo that should already have been drawn f2->DrawCopy("same"); delete f2; } Double_t dal(Double_t* x, Double_t* par) { Double_t mParent = par[0]; Double_t mi = par[1]; Double_t mj = par[2]; Double_t mk = par[3]; Double_t mikSq=x[0]; Double_t mjkSq=x[1]; Double_t mik = TMath::Sqrt(mikSq); Double_t mjk = TMath::Sqrt(mjkSq); Double_t ejcmsik = (mParent*mParent-mj*mj-mik*mik)/(2.0*mik); Double_t ekcmsik = (mik*mik+mk*mk-mi*mi)/(2.0*mik); if (ekcmsik #include "LauConstants.hh" #include "LauLASSBWRes.hh" #include "LauResonanceInfo.hh" -ClassImp(LauLASSBWRes) LauLASSBWRes::LauLASSBWRes(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), q0_(0.0), mDaugSum_(0.0), mDaugSumSq_(0.0), mDaugDiff_(0.0), mDaugDiffSq_(0.0), resMassSq_(0.0), r_(0), a_(0) { // Default values for LASS parameters const Double_t rVal = 3.32; const Double_t aVal = 2.07; const TString& parNameBase = this->getSanitisedName(); TString rName(parNameBase); rName += "_r"; r_ = resInfo->getExtraParameter( rName ); if ( r_ == 0 ) { r_ = new LauParameter( rName, rVal, 0.0, 10.0, kTRUE ); r_->secondStage(kTRUE); resInfo->addExtraParameter( r_ ); } TString aName(parNameBase); aName += "_a"; a_ = resInfo->getExtraParameter( aName ); if ( a_ == 0 ) { a_ = new LauParameter( aName, aVal, 0.0, 10.0, kTRUE ); a_->secondStage(kTRUE); resInfo->addExtraParameter( a_ ); } } LauLASSBWRes::~LauLASSBWRes() { } void LauLASSBWRes::initialise() { // Create the mass sums and differences Double_t massDaug1 = this->getMassDaug1(); Double_t massDaug2 = this->getMassDaug2(); mDaugSum_ = massDaug1 + massDaug2; mDaugSumSq_ = mDaugSum_*mDaugSum_; mDaugDiff_ = massDaug1 - massDaug2; mDaugDiffSq_ = mDaugDiff_*mDaugDiff_; Int_t resSpin = this->getSpin(); if (resSpin != 0) { std::cerr << "WARNING in LauLASSBWRes::amplitude : Resonance spin is " << resSpin << "." << std::endl; std::cerr << " : LASS amplitude is only for scalers, resetting spin to 0." << std::endl; this->changeResonance( -1.0, -1.0, 0 ); } this->calcQ0(); } void LauLASSBWRes::calcQ0() { // Decay momentum of either daughter in the resonance rest frame // when resonance mass = rest-mass value, m_0 (PDG value) resMass_ = this->getMass(); resMassSq_ = resMass_*resMass_; q0_ = TMath::Sqrt((resMassSq_ - mDaugSumSq_)*(resMassSq_ - mDaugDiffSq_))/(2.0*resMass_); } LauComplex LauLASSBWRes::resAmp(Double_t mass, Double_t /*spinTerm*/) { LauComplex resAmplitude(0.0, 0.0); if (mass < 1e-10) { std::cerr << "WARNING in LauLASSBWRes::amplitude : mass < 1e-10." << std::endl; return LauComplex(0.0, 0.0); } // Calculate the width of the resonance (as a function of mass) // q is the momentum of either daughter in the resonance rest-frame const Double_t q = this->getQ(); const Double_t resMass = this->getMass(); const Double_t resWidth = this->getWidth(); // If the mass is floating and their value have changed // we need to recalculate everything that assumes this value if ( (!this->fixMass()) && resMass != resMass_ ) { this->calcQ0(); } Double_t qRatio = q/q0_; Double_t totWidth = resWidth*qRatio*(resMass/mass); Double_t massSq = mass*mass; Double_t massSqTerm = resMassSq_ - massSq; // Compute the complex amplitude resAmplitude = LauComplex(massSqTerm, resMass*totWidth); // Scale by the denominator factor resAmplitude.rescale((resMassSq_*resWidth/q0_)/(massSqTerm*massSqTerm + resMassSq_*totWidth*totWidth)); // Calculate the phase shift term const Double_t rVal = this->getEffectiveRange(); const Double_t aVal = this->getScatteringLength(); const Double_t tandeltaB = (2.0*aVal*q)/(2.0 + aVal*rVal*q*q); const Double_t tanSq = tandeltaB*tandeltaB; const Double_t cos2PhaseShift = (1.0 - tanSq) / (1.0 + tanSq); const Double_t sin2PhaseShift = 2.0*tandeltaB / (1.0 + tanSq); LauComplex phaseShift(cos2PhaseShift, sin2PhaseShift); // Multiply by the phase shift resAmplitude = resAmplitude * phaseShift; return resAmplitude; } const std::vector& LauLASSBWRes::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixMass() ) { this->addFloatingParameter( this->getMassPar() ); } if ( ! this->fixWidth() ) { this->addFloatingParameter( this->getWidthPar() ); } if ( ! this->fixEffectiveRange() ) { this->addFloatingParameter( r_ ); } if ( ! this->fixScatteringLength() ) { this->addFloatingParameter( a_ ); } return this->getParameters(); } void LauLASSBWRes::setResonanceParameter(const TString& name, const Double_t value) { // Set various parameters for the LASS lineshape dynamics if (name == "a") { this->setScatteringLength(value); std::cout << "INFO in LauLASSBWRes::setResonanceParameter : Setting LASS Scattering Length = " << this->getScatteringLength() << std::endl; } else if (name == "r") { this->setEffectiveRange(value); std::cout << "INFO in LauLASSBWRes::setResonanceParameter : Setting LASS Effective Range = " << this->getEffectiveRange() << std::endl; } else { std::cerr << "WARNING in LauLASSBWRes::setResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } void LauLASSBWRes::floatResonanceParameter(const TString& name) { if (name == "a") { if ( a_->fixed() ) { a_->fixed( kFALSE ); this->addFloatingParameter( a_ ); } else { std::cerr << "WARNING in LauLASSBWRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "r") { if ( r_->fixed() ) { r_->fixed( kFALSE ); this->addFloatingParameter( r_ ); } else { std::cerr << "WARNING in LauLASSBWRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else { std::cerr << "WARNING in LauLASSBWRes::fixResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } LauParameter* LauLASSBWRes::getResonanceParameter(const TString& name) { if (name == "a") { return a_; } else if (name == "r") { return r_; } else { std::cerr << "WARNING in LauLASSBWRes::getResonanceParameter: Parameter name not reconised." << std::endl; return 0; } } void LauLASSBWRes::setEffectiveRange(const Double_t r) { r_->value( r ); r_->genValue( r ); r_->initValue( r ); } void LauLASSBWRes::setScatteringLength(const Double_t a) { a_->value( a ); a_->genValue( a ); a_->initValue( a ); } diff --git a/src/LauLASSNRRes.cc b/src/LauLASSNRRes.cc index 6180e03..2c19a78 100644 --- a/src/LauLASSNRRes.cc +++ b/src/LauLASSNRRes.cc @@ -1,196 +1,195 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauLASSNRRes.cc \brief File containing implementation of LauLASSNRRes class. */ #include #include "LauConstants.hh" #include "LauLASSNRRes.hh" #include "LauResonanceInfo.hh" -ClassImp(LauLASSNRRes) LauLASSNRRes::LauLASSNRRes(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), r_(0), a_(0), cutOff_(0.0) { // Default values for LASS parameters cutOff_ = 1.8; const Double_t rVal = 3.32; const Double_t aVal = 2.07; const TString& parNameBase = this->getSanitisedName(); TString rName(parNameBase); rName += "_r"; r_ = resInfo->getExtraParameter( rName ); if ( r_ == 0 ) { r_ = new LauParameter( rName, rVal, 0.0, 10.0, kTRUE ); r_->secondStage(kTRUE); resInfo->addExtraParameter( r_ ); } TString aName(parNameBase); aName += "_a"; a_ = resInfo->getExtraParameter( aName ); if ( a_ == 0 ) { a_ = new LauParameter( aName, aVal, 0.0, 10.0, kTRUE ); a_->secondStage(kTRUE); resInfo->addExtraParameter( a_ ); } } LauLASSNRRes::~LauLASSNRRes() { } void LauLASSNRRes::initialise() { Int_t resSpin = this->getSpin(); if (resSpin != 0) { std::cerr << "WARNING in LauLASSNRRes::amplitude : Resonance spin is " << resSpin << "." << std::endl; std::cerr << " : LASS amplitude is only for scalers, resetting spin to 0." << std::endl; this->changeResonance( -1.0, -1.0, 0 ); } } LauComplex LauLASSNRRes::resAmp(Double_t mass, Double_t /*spinTerm*/) { LauComplex bkgAmplitude(0.0, 0.0); if (mass < 1e-10) { std::cerr << "WARNING in LauLASSNRRes::amplitude : mass < 1e-10." << std::endl; return LauComplex(0.0, 0.0); } if (mass < cutOff_) { // q is the momentum of either daughter in the resonance rest-frame const Double_t q = this->getQ(); // Calculate the phase shift term const Double_t rVal = this->getEffectiveRange(); const Double_t aVal = this->getScatteringLength(); const Double_t qcotdeltaB = 1.0/aVal + (rVal*q*q)/2.0; // Compute the complex amplitude bkgAmplitude = LauComplex(qcotdeltaB, q); // Scale by the numerator and denominator factors bkgAmplitude.rescale(mass/(qcotdeltaB*qcotdeltaB + q*q)); } return bkgAmplitude; } const std::vector& LauLASSNRRes::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixMass() ) { this->addFloatingParameter( this->getMassPar() ); } if ( ! this->fixWidth() ) { this->addFloatingParameter( this->getWidthPar() ); } if ( ! this->fixEffectiveRange() ) { this->addFloatingParameter( r_ ); } if ( ! this->fixScatteringLength() ) { this->addFloatingParameter( a_ ); } return this->getParameters(); } void LauLASSNRRes::setResonanceParameter(const TString& name, const Double_t value) { // Set various parameters for the LASS lineshape dynamics if (name == "a") { this->setScatteringLength(value); std::cout << "INFO in LauLASSNRRes::setResonanceParameter : Setting LASS Scattering Length = " << this->getScatteringLength() << std::endl; } else if (name == "r") { this->setEffectiveRange(value); std::cout << "INFO in LauLASSNRRes::setResonanceParameter : Setting LASS Effective Range = " << this->getEffectiveRange() << std::endl; } else { std::cerr << "WARNING in LauLASSNRRes::setResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } void LauLASSNRRes::floatResonanceParameter(const TString& name) { if (name == "a") { if ( a_->fixed() ) { a_->fixed( kFALSE ); this->addFloatingParameter( a_ ); } else { std::cerr << "WARNING in LauLASSNRRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "r") { if ( r_->fixed() ) { r_->fixed( kFALSE ); this->addFloatingParameter( r_ ); } else { std::cerr << "WARNING in LauLASSNRRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else { std::cerr << "WARNING in LauLASSNRRes::fixResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } LauParameter* LauLASSNRRes::getResonanceParameter(const TString& name) { if (name == "a") { return a_; } else if (name == "r") { return r_; } else { std::cerr << "WARNING in LauLASSNRRes::getResonanceParameter: Parameter name not reconised." << std::endl; return 0; } } void LauLASSNRRes::setEffectiveRange(const Double_t r) { r_->value( r ); r_->genValue( r ); r_->initValue( r ); } void LauLASSNRRes::setScatteringLength(const Double_t a) { a_->value( a ); a_->genValue( a ); a_->initValue( a ); } diff --git a/src/LauLASSRes.cc b/src/LauLASSRes.cc index 790412d..e63b4a5 100644 --- a/src/LauLASSRes.cc +++ b/src/LauLASSRes.cc @@ -1,275 +1,274 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauLASSRes.cc \brief File containing implementation of LauLASSRes class. */ #include #include "LauConstants.hh" #include "LauLASSRes.hh" #include "LauResonanceInfo.hh" -ClassImp(LauLASSRes) LauLASSRes::LauLASSRes(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), q0_(0.0), mDaugSum_(0.0), mDaugSumSq_(0.0), mDaugDiff_(0.0), mDaugDiffSq_(0.0), resMassSq_(0.0), r_(0), a_(0), cutOff_(0.0) { // Default values for LASS parameters cutOff_ = 1.8; const Double_t rVal = 3.32; const Double_t aVal = 2.07; const TString& parNameBase = this->getSanitisedName(); TString rName(parNameBase); rName += "_r"; r_ = resInfo->getExtraParameter( rName ); if ( r_ == 0 ) { r_ = new LauParameter( rName, rVal, 0.0, 10.0, kTRUE ); r_->secondStage(kTRUE); resInfo->addExtraParameter( r_ ); } TString aName(parNameBase); aName += "_a"; a_ = resInfo->getExtraParameter( aName ); if ( a_ == 0 ) { a_ = new LauParameter( aName, aVal, 0.0, 10.0, kTRUE ); a_->secondStage(kTRUE); resInfo->addExtraParameter( a_ ); } } LauLASSRes::~LauLASSRes() { } void LauLASSRes::initialise() { // Create the mass sums and differences Double_t massDaug1 = this->getMassDaug1(); Double_t massDaug2 = this->getMassDaug2(); mDaugSum_ = massDaug1 + massDaug2; mDaugSumSq_ = mDaugSum_*mDaugSum_; mDaugDiff_ = massDaug1 - massDaug2; mDaugDiffSq_ = mDaugDiff_*mDaugDiff_; Int_t resSpin = this->getSpin(); if (resSpin != 0) { std::cerr << "WARNING in LauLASSRes::amplitude : Resonance spin is " << resSpin << "." << std::endl; std::cerr << " : LASS amplitude is only for scalers, resetting spin to 0." << std::endl; this->changeResonance( -1.0, -1.0, 0 ); } this->calcQ0(); } void LauLASSRes::calcQ0() { // Decay momentum of either daughter in the resonance rest frame // when resonance mass = rest-mass value, m_0 (PDG value) resMass_ = this->getMass(); resMassSq_ = resMass_*resMass_; q0_ = TMath::Sqrt((resMassSq_ - mDaugSumSq_)*(resMassSq_ - mDaugDiffSq_))/(2.0*resMass_); } LauComplex LauLASSRes::resAmp(Double_t mass, Double_t /*spinTerm*/) { LauComplex resAmplitude(0.0, 0.0); LauComplex bkgAmplitude(0.0, 0.0); LauComplex totAmplitude(0.0, 0.0); if (mass < 1e-10) { std::cerr << "WARNING in LauLASSRes::amplitude : mass < 1e-10." << std::endl; return LauComplex(0.0, 0.0); } //--------------------------- // First do the resonant part //--------------------------- // Calculate the width of the resonance (as a function of mass) // q is the momentum of either daughter in the resonance rest-frame const Double_t q = this->getQ(); const Double_t resMass = this->getMass(); const Double_t resWidth = this->getWidth(); // If the mass is floating and their value have changed // we need to recalculate everything that assumes this value if ( (!this->fixMass()) && resMass != resMass_ ) { this->calcQ0(); } Double_t qRatio = q/q0_; Double_t totWidth = resWidth*qRatio*(resMass/mass); Double_t massSq = mass*mass; Double_t massSqTerm = resMassSq_ - massSq; // Compute the complex amplitude resAmplitude = LauComplex(massSqTerm, resMass*totWidth); // Scale by the denominator factor resAmplitude.rescale((resMassSq_*resWidth/q0_)/(massSqTerm*massSqTerm + resMassSq_*totWidth*totWidth)); // Calculate the phase shift term const Double_t rVal = this->getEffectiveRange(); const Double_t aVal = this->getScatteringLength(); const Double_t tandeltaB = (2.0*aVal*q)/(2.0 + aVal*rVal*q*q); const Double_t tanSq = tandeltaB*tandeltaB; const Double_t cos2PhaseShift = (1.0 - tanSq) / (1.0 + tanSq); const Double_t sin2PhaseShift = 2.0*tandeltaB / (1.0 + tanSq); LauComplex phaseShift(cos2PhaseShift, sin2PhaseShift); // Multiply by the phase shift resAmplitude = resAmplitude * phaseShift; //-------------------------------- // Now do the effective range part //-------------------------------- // Form the real and imaginary parts const Double_t qcotdeltaB = 1.0/aVal + (rVal*q*q)/2.0; // Compute the complex amplitude bkgAmplitude = LauComplex(qcotdeltaB, q); // Scale by the numerator and denominator factors bkgAmplitude.rescale(mass/(qcotdeltaB*qcotdeltaB + q*q)); //------------------ // Add them together //------------------ if (mass > cutOff_) { totAmplitude = resAmplitude; } else { totAmplitude = bkgAmplitude + resAmplitude; } return totAmplitude; } const std::vector& LauLASSRes::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixMass() ) { this->addFloatingParameter( this->getMassPar() ); } if ( ! this->fixWidth() ) { this->addFloatingParameter( this->getWidthPar() ); } if ( ! this->fixEffectiveRange() ) { this->addFloatingParameter( r_ ); } if ( ! this->fixScatteringLength() ) { this->addFloatingParameter( a_ ); } return this->getParameters(); } void LauLASSRes::setResonanceParameter(const TString& name, const Double_t value) { // Set various parameters for the LASS lineshape dynamics if (name == "a") { this->setScatteringLength(value); std::cout << "INFO in LauLASSRes::setResonanceParameter : Setting LASS Scattering Length = " << this->getScatteringLength() << std::endl; } else if (name == "r") { this->setEffectiveRange(value); std::cout << "INFO in LauLASSRes::setResonanceParameter : Setting LASS Effective Range = " << this->getEffectiveRange() << std::endl; } else { std::cerr << "WARNING in LauLASSRes::setResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } void LauLASSRes::floatResonanceParameter(const TString& name) { if (name == "a") { if ( a_->fixed() ) { a_->fixed( kFALSE ); this->addFloatingParameter( a_ ); } else { std::cerr << "WARNING in LauLASSRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "r") { if ( r_->fixed() ) { r_->fixed( kFALSE ); this->addFloatingParameter( r_ ); } else { std::cerr << "WARNING in LauLASSRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else { std::cerr << "WARNING in LauLASSRes::fixResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } LauParameter* LauLASSRes::getResonanceParameter(const TString& name) { if (name == "a") { return a_; } else if (name == "r") { return r_; } else { std::cerr << "WARNING in LauLASSRes::getResonanceParameter: Parameter name not reconised." << std::endl; return 0; } } void LauLASSRes::setEffectiveRange(const Double_t r) { r_->value( r ); r_->genValue( r ); r_->initValue( r ); } void LauLASSRes::setScatteringLength(const Double_t a) { a_->value( a ); a_->genValue( a ); a_->initValue( a ); } diff --git a/src/LauLinearPdf.cc b/src/LauLinearPdf.cc index 5ae16bc..c9922d5 100644 --- a/src/LauLinearPdf.cc +++ b/src/LauLinearPdf.cc @@ -1,129 +1,128 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauLinearPdf.cc \brief File containing implementation of LauLinearPdf class. */ #include #include using std::cout; using std::cerr; using std::endl; using std::vector; #include "TMath.h" #include "TSystem.h" #include "LauConstants.hh" #include "LauLinearPdf.hh" -ClassImp(LauLinearPdf) LauLinearPdf::LauLinearPdf(const TString& theVarName, const vector& params, Double_t minAbscissa, Double_t maxAbscissa) : LauAbsPdf(theVarName, params, minAbscissa, maxAbscissa), slope_(0),posflag_(kTRUE) { // Constructor for the linear PDF. // // The parameters in params are the slope and y-intercept of the line. // The last two arguments specify the range in which the PDF is defined, and the PDF // will be normalised w.r.t. these limits. slope_ = this->findParameter("slope"); if ((this->nParameters() != 1) || (slope_ == 0)) { cerr<<"Warning. LauLinearPdf requires 1 parameter: \"slope\"."<Exit(EXIT_FAILURE); } // Cache the normalisation factor. this->calcNorm(); } LauLinearPdf::~LauLinearPdf() { // Destructor } void LauLinearPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Get our abscissa Double_t abscissa = abscissas[0]; // Get the up to date parameter values Double_t slope = slope_->unblindValue(); // Calculate the value of the straight line for the given value of the abscissa. Double_t constVal = 1.0/(this->getMaxAbscissa() - this->getMinAbscissa()); constVal -= slope * (this->getMaxAbscissa() + this->getMinAbscissa()) * 0.5; Double_t value = slope*abscissa + constVal; // Make sure the PDF doesn't go negative if ( value < 0.0 ) { if ( posflag_ ) { std::cerr << "WARNING in LauLinearPdf::calcLikelihoodInfo : The PDF is negative, setting to zero" << std::endl; } value = 0.0; posflag_= kFALSE; } this->setUnNormPDFVal(value); } void LauLinearPdf::calcNorm() { // Nothing to calculate here since the PDF is already normalised to 1 this->setNorm(1.0); } void LauLinearPdf::calcPDFHeight( const LauKinematics* /*kinematics*/ ) { if (this->heightUpToDate()) { return; } // Get the up to date parameter values Double_t slope = slope_->unblindValue(); // Calculate the PDF height for the straight line LauAbscissas maxPoint(1); if (slope>0.0) { maxPoint[0] = this->getMaxAbscissa(); } else { maxPoint[0] = this->getMinAbscissa(); } this->calcLikelihoodInfo(maxPoint); Double_t height = this->getUnNormLikelihood(); this->setMaxHeight(height); } diff --git a/src/LauMagPhaseCPCoeffSet.cc b/src/LauMagPhaseCPCoeffSet.cc index f7c066a..7839357 100644 --- a/src/LauMagPhaseCPCoeffSet.cc +++ b/src/LauMagPhaseCPCoeffSet.cc @@ -1,322 +1,321 @@ /* Copyright 2011 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauMagPhaseCPCoeffSet.cc \brief File containing implementation of LauMagPhaseCPCoeffSet class. */ #include #include #include #include "TMath.h" #include "TRandom.h" #include "LauMagPhaseCPCoeffSet.hh" #include "LauComplex.hh" #include "LauConstants.hh" #include "LauParameter.hh" #include "LauPrint.hh" -ClassImp(LauMagPhaseCPCoeffSet) LauMagPhaseCPCoeffSet::LauMagPhaseCPCoeffSet(const TString& compName, Double_t mag, Double_t phase, Double_t magBar, Double_t phaseBar, Bool_t magFixed, Bool_t phaseFixed,Bool_t magBarFixed, Bool_t phaseBarFixed) : LauAbsCoeffSet(compName), mag_(new LauParameter("Mag", mag, minMagnitude_, maxMagnitude_, magFixed)), phase_(new LauParameter("Phase", phase, minPhase_, maxPhase_, phaseFixed)), magBar_(new LauParameter("MagBar", magBar, minMagnitude_, maxMagnitude_, magBarFixed)), phaseBar_(new LauParameter("PhaseBar", phaseBar, minPhase_, maxPhase_, phaseBarFixed)), particleCoeff_( mag*TMath::Cos(phase), mag*TMath::Sin(phase) ), antiparticleCoeff_( magBar*TMath::Cos(phaseBar), magBar*TMath::Sin(phaseBar) ), acp_("ACP", (magBar*magBar - mag*mag)/(magBar*magBar + mag*mag), -1.0, 1.0) { } LauMagPhaseCPCoeffSet::LauMagPhaseCPCoeffSet(const LauMagPhaseCPCoeffSet& rhs, CloneOption cloneOption, Double_t constFactor) : LauAbsCoeffSet(rhs.name()), mag_(0), phase_(0), magBar_(0), phaseBar_(0), particleCoeff_( rhs.particleCoeff_ ), antiparticleCoeff_( rhs.antiparticleCoeff_ ), acp_( rhs.acp_ ) { if ( cloneOption == All || cloneOption == TieMagnitude ) { mag_ = rhs.mag_->createClone(constFactor); magBar_ = rhs.magBar_->createClone(constFactor); } else { mag_ = new LauParameter("Mag", rhs.mag_->value(), minMagnitude_, maxMagnitude_, rhs.mag_->fixed()); if ( rhs.mag_->blind() ) { const LauBlind* blinder = rhs.mag_->blinder(); mag_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } magBar_ = new LauParameter("MagBar", rhs.magBar_->value(), minMagnitude_, maxMagnitude_, rhs.magBar_->fixed()); if ( rhs.magBar_->blind() ) { const LauBlind* blinder = rhs.magBar_->blinder(); magBar_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TiePhase ) { phase_ = rhs.phase_->createClone(constFactor); phaseBar_ = rhs.phaseBar_->createClone(constFactor); } else { phase_ = new LauParameter("Phase", rhs.phase_->value(), minPhase_, maxPhase_, rhs.phase_->fixed()); if ( rhs.phase_->blind() ) { const LauBlind* blinder = rhs.phase_->blinder(); phase_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } phaseBar_ = new LauParameter("PhaseBar", rhs.phaseBar_->value(), minPhase_, maxPhase_, rhs.phaseBar_->fixed()); if ( rhs.phaseBar_->blind() ) { const LauBlind* blinder = rhs.phaseBar_->blinder(); phaseBar_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } } std::vector LauMagPhaseCPCoeffSet::getParameters() { std::vector pars; pars.push_back(mag_); pars.push_back(phase_); pars.push_back(magBar_); pars.push_back(phaseBar_); return pars; } void LauMagPhaseCPCoeffSet::printParValues() const { std::cout<<"INFO in LauMagPhaseCPCoeffSet::printParValues : Component \""<name()<<"\" has "; std::cout<<"mag = "<value()<<",\t"; std::cout<<"phase = "<value()<<",\t"; std::cout<<"magBar = "<value()<<",\t"; std::cout<<"phaseBar = "<value()<<"."<name(); resName = resName.ReplaceAll("_", "\\_"); stream<value()); stream<<" \\pm "; print.printFormat(stream, mag_->error()); stream<<"$ & $"; print.printFormat(stream, phase_->value()); stream<<" \\pm "; print.printFormat(stream, phase_->error()); stream<<"$ & $"; print.printFormat(stream, magBar_->value()); stream<<" \\pm "; print.printFormat(stream, magBar_->error()); stream<<"$ & $"; print.printFormat(stream, phaseBar_->value()); stream<<" \\pm "; print.printFormat(stream, phaseBar_->error()); stream<<"$ \\\\"<fixed() == kFALSE) { // Choose a value for "magnitude" between 0.0 and 2.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*2.0; mag_->initValue(value); mag_->value(value); } if (phase_->fixed() == kFALSE) { // Choose a phase between +- pi Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*LauConstants::twoPi - LauConstants::pi; phase_->initValue(value); phase_->value(value); } if (magBar_->fixed() == kFALSE) { // Choose a value for "magnitude" between 0.0 and 2.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*2.0; magBar_->initValue(value); magBar_->value(value); } if (phaseBar_->fixed() == kFALSE) { // Choose a phase between +- pi Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*LauConstants::twoPi - LauConstants::pi; phaseBar_->initValue(value); phaseBar_->value(value); } } void LauMagPhaseCPCoeffSet::finaliseValues() { // retrieve the current values from the parameters Double_t mVal= mag_->value(); Double_t pVal= phase_->value(); Double_t mBarVal= magBar_->value(); Double_t pBarVal= phaseBar_->value(); Double_t genPhase = phase_->genValue(); Double_t genPhaseBar = phaseBar_->genValue(); // Check whether we have a negative magnitude. // If so make it positive and add pi to the phase. if (mVal < 0.0) { mVal *= -1.0; pVal += LauConstants::pi; } if (mBarVal < 0.0) { mBarVal *= -1.0; pBarVal += LauConstants::pi; } // Check now whether the phases lies in the right range (-pi to pi). Bool_t pWithinRange(kFALSE); Bool_t pBarWithinRange(kFALSE); while (pWithinRange == kFALSE && pBarWithinRange == kFALSE) { if (pVal > -LauConstants::pi && pVal < LauConstants::pi) { pWithinRange = kTRUE; } else { // Not within the specified range if (pVal > LauConstants::pi) { pVal -= LauConstants::twoPi; } else if (pVal < -LauConstants::pi) { pVal += LauConstants::twoPi; } } if (pBarVal > -LauConstants::pi && pBarVal < LauConstants::pi) { pBarWithinRange = kTRUE; } else { // Not within the specified range if (pBarVal > LauConstants::pi) { pBarVal -= LauConstants::twoPi; } else if (pBarVal < -LauConstants::pi) { pBarVal += LauConstants::twoPi; } } } // A further problem can occur when the generated phase is close to -pi or pi. // The phase can wrap over to the other end of the scale - // this leads to artificially large pulls so we wrap it back. Double_t diff = pVal - genPhase; if (diff > LauConstants::pi) { pVal -= LauConstants::twoPi; } else if (diff < -LauConstants::pi) { pVal += LauConstants::twoPi; } diff = pBarVal - genPhaseBar; if (diff > LauConstants::pi) { pBarVal -= LauConstants::twoPi; } else if (diff < -LauConstants::pi) { pBarVal += LauConstants::twoPi; } // finally store the new values in the parameters // and update the pulls mag_->value(mVal); mag_->updatePull(); phase_->value(pVal); phase_->updatePull(); magBar_->value(mBarVal); magBar_->updatePull(); phaseBar_->value(pBarVal); phaseBar_->updatePull(); } const LauComplex& LauMagPhaseCPCoeffSet::particleCoeff() { particleCoeff_.setRealImagPart( mag_->unblindValue()*TMath::Cos(phase_->unblindValue()), mag_->unblindValue()*TMath::Sin(phase_->unblindValue()) ); return particleCoeff_; } const LauComplex& LauMagPhaseCPCoeffSet::antiparticleCoeff() { antiparticleCoeff_.setRealImagPart( magBar_->unblindValue()*TMath::Cos(phaseBar_->unblindValue()), magBar_->unblindValue()*TMath::Sin(phaseBar_->unblindValue()) ); return antiparticleCoeff_; } void LauMagPhaseCPCoeffSet::setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, Bool_t init ) { Double_t magVal( coeff.abs() ); Double_t phaseVal( coeff.arg() ); Double_t magBarVal( coeffBar.abs() ); Double_t phaseBarVal( coeffBar.arg() ); mag_->value( magVal ); phase_->value( phaseVal ); magBar_->value( magBarVal ); phaseBar_->value( phaseBarVal ); if ( init ) { mag_->genValue( magVal ); phase_->genValue( phaseVal ); magBar_->genValue( magBarVal ); phaseBar_->genValue( phaseBarVal ); mag_->initValue( magVal ); phase_->initValue( phaseVal ); magBar_->initValue( magBarVal ); phaseBar_->initValue( phaseBarVal ); } } LauParameter LauMagPhaseCPCoeffSet::acp() { // set the name TString parName(this->baseName()); parName += "_ACP"; acp_.name(parName); // work out the ACP value Double_t value(-99.0); value = (magBar_->value()*magBar_->value() - mag_->value()*mag_->value())/(magBar_->value()*magBar_->value() + mag_->value()*mag_->value()); // is it fixed? Bool_t fixed = magBar_->fixed() && mag_->fixed(); acp_.fixed(fixed); // we can't work out the error without the covariance matrix Double_t error(0.0); // set the value and error acp_.valueAndErrors(value,error); return acp_; } LauAbsCoeffSet* LauMagPhaseCPCoeffSet::createClone(const TString& newName, CloneOption cloneOption, Double_t constFactor) { LauAbsCoeffSet* clone(0); if ( cloneOption == All || cloneOption == TiePhase || cloneOption == TieMagnitude ) { clone = new LauMagPhaseCPCoeffSet( *this, cloneOption, constFactor ); clone->name( newName ); } else { std::cerr << "ERROR in LauMagPhaseCPCoeffSet::createClone : Invalid clone option" << std::endl; } return clone; } diff --git a/src/LauMagPhaseCoeffSet.cc b/src/LauMagPhaseCoeffSet.cc index b0addb0..4636873 100644 --- a/src/LauMagPhaseCoeffSet.cc +++ b/src/LauMagPhaseCoeffSet.cc @@ -1,224 +1,223 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauMagPhaseCoeffSet.cc \brief File containing implementation of LauMagPhaseCoeffSet class. */ #include #include #include #include "TMath.h" #include "TRandom.h" #include "LauComplex.hh" #include "LauConstants.hh" #include "LauMagPhaseCoeffSet.hh" #include "LauParameter.hh" #include "LauPrint.hh" -ClassImp(LauMagPhaseCoeffSet) LauMagPhaseCoeffSet::LauMagPhaseCoeffSet(const TString& compName, Double_t magnitude, Double_t phase, Bool_t magFixed, Bool_t phaseFixed) : LauAbsCoeffSet(compName), magnitude_(new LauParameter("A",magnitude,minMagnitude_,maxMagnitude_,magFixed)), phase_(new LauParameter("Delta",phase,minPhase_,maxPhase_,phaseFixed)), coeff_(magnitude*TMath::Cos(phase), magnitude*TMath::Sin(phase)) { } LauMagPhaseCoeffSet::LauMagPhaseCoeffSet(const LauMagPhaseCoeffSet& rhs, CloneOption cloneOption, Double_t constFactor) : LauAbsCoeffSet(rhs.name()), magnitude_(0), phase_(0), coeff_( rhs.coeff_ ) { if ( cloneOption == All || cloneOption == TieMagnitude ) { magnitude_ = rhs.magnitude_->createClone(constFactor); } else { magnitude_ = new LauParameter("A", rhs.magnitude_->value(), minMagnitude_, maxMagnitude_, rhs.magnitude_->fixed()); if ( rhs.magnitude_->blind() ) { const LauBlind* blinder = rhs.magnitude_->blinder(); magnitude_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TiePhase ) { phase_ = rhs.phase_->createClone(constFactor); } else { phase_ = new LauParameter("Delta", rhs.phase_->value(), minPhase_, maxPhase_, rhs.phase_->fixed()); if ( rhs.phase_->blind() ) { const LauBlind* blinder = rhs.phase_->blinder(); phase_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } } std::vector LauMagPhaseCoeffSet::getParameters() { std::vector pars; pars.push_back(magnitude_); pars.push_back(phase_); return pars; } void LauMagPhaseCoeffSet::printParValues() const { std::cout<<"INFO in LauMagPhaseCoeffSet::printParValues : Component \""<name()<<"\" has magnitude = "<value()<<" and phase = "<value()<<"."<name(); resName = resName.ReplaceAll("_", "\\_"); stream<value()); stream<<" \\pm "; print.printFormat(stream, magnitude_->error()); stream<<"$ & $"; print.printFormat(stream, phase_->value()); stream<<" \\pm "; print.printFormat(stream, phase_->error()); stream<<"$ \\\\"<fixed() == kFALSE) { // Choose a magnitude between 0.0 and 2.0 Double_t mag = LauAbsCoeffSet::getRandomiser()->Rndm()*2.0; magnitude_->initValue(mag); magnitude_->value(mag); } if (phase_->fixed() == kFALSE) { // Choose a phase between +- pi Double_t phase = LauAbsCoeffSet::getRandomiser()->Rndm()*LauConstants::twoPi - LauConstants::pi; phase_->initValue(phase); phase_->value(phase); } } void LauMagPhaseCoeffSet::finaliseValues() { // retrieve the current values from the parameters Double_t mag = magnitude_->value(); Double_t phase = phase_->value(); Double_t genPhase = phase_->genValue(); // Check whether we have a negative magnitude. // If so make it positive and add pi to the phase. if (mag < 0.0) { mag *= -1.0; phase += LauConstants::pi; } // Check now whether the phase lies in the right range (-pi to pi). Bool_t withinRange(kFALSE); while (withinRange == kFALSE) { if (phase > -LauConstants::pi && phase <= LauConstants::pi) { withinRange = kTRUE; } else { // Not within the specified range if (phase > LauConstants::pi) { phase -= LauConstants::twoPi; } else if (phase <= -LauConstants::pi) { phase += LauConstants::twoPi; } } } // A further problem can occur when the generated phase is close to -pi or pi. // The phase can wrap over to the other end of the scale - // this leads to artificially large pulls so we wrap it back. Double_t diff = phase - genPhase; if (diff > LauConstants::pi) { phase -= LauConstants::twoPi; } else if (diff < -LauConstants::pi) { phase += LauConstants::twoPi; } // finally store the new values in the parameters // and update the pulls magnitude_->value(mag); magnitude_->updatePull(); phase_->value(phase); phase_->updatePull(); } const LauComplex& LauMagPhaseCoeffSet::particleCoeff() { coeff_.setRealImagPart(magnitude_->unblindValue()*TMath::Cos(phase_->unblindValue()), magnitude_->unblindValue()*TMath::Sin(phase_->unblindValue())); return coeff_; } const LauComplex& LauMagPhaseCoeffSet::antiparticleCoeff() { return this->particleCoeff(); } void LauMagPhaseCoeffSet::setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, Bool_t init ) { LauComplex average( coeff ); average += coeffBar; average.rescale( 0.5 ); Double_t magVal( average.abs() ); Double_t phaseVal( average.arg() ); magnitude_->value( magVal ); phase_->value( phaseVal ); if ( init ) { magnitude_->genValue( magVal ); phase_->genValue( phaseVal ); magnitude_->initValue( magVal ); phase_->initValue( phaseVal ); } } LauParameter LauMagPhaseCoeffSet::acp() { TString parName(this->baseName()); parName += "_ACP"; return LauParameter(parName,0.0); } LauAbsCoeffSet* LauMagPhaseCoeffSet::createClone(const TString& newName, CloneOption cloneOption, Double_t constFactor) { LauAbsCoeffSet* clone(0); if ( cloneOption == All || cloneOption == TiePhase || cloneOption == TieMagnitude ) { clone = new LauMagPhaseCoeffSet( *this, cloneOption, constFactor ); clone->name( newName ); } else { std::cerr << "ERROR in LauMagPhaseCoeffSet::createClone : Invalid clone option" << std::endl; } return clone; } diff --git a/src/LauMergeDataFiles.cc b/src/LauMergeDataFiles.cc index 46fa1ae..552ecae 100644 --- a/src/LauMergeDataFiles.cc +++ b/src/LauMergeDataFiles.cc @@ -1,306 +1,305 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ #include "LauMergeDataFiles.hh" #include #include #include "TLeaf.h" #include "TObjArray.h" #include "TSystem.h" -ClassImp(LauMergeDataFiles) LauMergeDataFiles::LauMergeDataFiles(const TString& fileName1, const TString& fileName2, const TString& treeName) : fileName1_(fileName1), fileName2_(fileName2), treeName_(treeName), inputFile1_(0), inputFile2_(0), inputTree1_(0), inputTree2_(0), outputFile_(0), outputTree_(0) { } LauMergeDataFiles::~LauMergeDataFiles() { if (inputFile1_ && inputFile1_->IsOpen()) { inputFile1_->Close(); } delete inputFile1_; if (inputFile2_ && inputFile2_->IsOpen()) { inputFile2_->Close(); } delete inputFile2_; if (outputFile_ && outputFile_->IsOpen()) { outputFile_->Close(); } delete outputFile_; } void LauMergeDataFiles::openInputFiles() { // open the two input ROOT files inputFile1_ = TFile::Open(fileName1_); if (!inputFile1_ || inputFile1_->IsZombie()) { std::cerr<<"Problem opening file: \""<Exit(EXIT_FAILURE); } inputTree1_ = dynamic_cast( inputFile1_->Get(treeName_) ); if (!inputTree1_) { std::cerr<<"Problem getting tree called "<Exit(EXIT_FAILURE); } inputFile2_ = TFile::Open(fileName2_); if (!inputFile2_ || inputFile2_->IsZombie()) { std::cerr<<"Problem opening file: \""<Exit(EXIT_FAILURE); } inputTree2_ = dynamic_cast( inputFile2_->Get(treeName_) ); if (!inputTree2_) { std::cerr<<"Problem getting tree called "<Exit(EXIT_FAILURE); } } void LauMergeDataFiles::setupInputTrees() { TObjArray* leaves1 = inputTree1_->GetListOfLeaves(); TObjArray* leaves2 = inputTree2_->GetListOfLeaves(); Int_t nLeaves1 = leaves1->GetEntries(); Int_t nLeaves2 = leaves2->GetEntries(); if ( nLeaves1 != nLeaves2 ) { std::cerr<<"Different number of leaves in the two input trees, not continuing."<SetBranchAddress("iExpt",&iExpt_); inputTree1_->SetBranchAddress("iEvtWithinExpt",&iEvtWithinExpt_); inputTree2_->SetBranchAddress("iExpt",&iExpt_); inputTree2_->SetBranchAddress("iEvtWithinExpt",&iEvtWithinExpt_); for (Int_t iLeaf(0); iLeaf((*leaves1)[iLeaf]); TString type = leaf->GetTypeName(); TString name = leaf->GetName(); Int_t size = leaf->GetNdata(); if ((name == "iExpt") || (name == "iEvtWithinExpt") || (size != 1)) { continue; } if ( type == "Double_t" ) { std::pair result = doubleVars_.insert(std::make_pair(name,0.0)); LeafDoubleMap::iterator iter = result.first; bool ok = result.second; if (ok) { inputTree1_->SetBranchAddress(name,&(iter->second)); inputTree2_->SetBranchAddress(name,&(iter->second)); } } else if ( type == "Int_t" ) { std::pair result = integerVars_.insert(std::make_pair(name,0)); LeafIntegerMap::iterator iter = result.first; bool ok = result.second; if (ok) { inputTree1_->SetBranchAddress(name,&(iter->second)); inputTree2_->SetBranchAddress(name,&(iter->second)); } } } std::cout<<"Set branch addresses for "<GetName()<<"\"..."<Branch("iExpt",&iExpt_,"iExpt/I"); outputTree_->Branch("iEvtWithinExpt",&iEvtWithinExpt_,"iEvtWithinExpt/I"); for (LeafDoubleMap::iterator iter = doubleVars_.begin(); iter != doubleVars_.end(); ++iter) { TString name = iter->first; Double_t * address = &(iter->second); TString thirdBit = name; thirdBit += "/D"; outputTree_->Branch(name,address,thirdBit); } for (LeafIntegerMap::iterator iter = integerVars_.begin(); iter != integerVars_.end(); ++iter) { TString name = iter->first; Int_t * address = &(iter->second); TString thirdBit = name; thirdBit += "/I"; outputTree_->Branch(name,address,thirdBit); } std::cout<<"Created "<openInputFiles(); this->setupInputTrees(); outputFile_ = TFile::Open(fileName,"recreate"); outputTree_ = new TTree(treeName_,""); this->setupOutputTree(); // loop over the trees and combine the corresponding experiments std::cout<<"Starting to combine the trees..."<findExperiments( inputTree1_, tree1Expts_ ); this->findExperiments( inputTree2_, tree2Expts_ ); // Check that the experiments in the two trees match if ( !this->checkExperimentMaps() ) { return; } // Loop through the experiments for ( ExptsMap::const_iterator iter1 = tree1Expts_.begin(); iter1 != tree1Expts_.end(); ++iter1 ) { // get the map element for tree2 Int_t expt = iter1->first; ExptsMap::const_iterator iter2 = tree2Expts_.find( expt ); // determine the number of entries in tree1 Int_t nEntriesInTree1 = iter1->second.second - iter1->second.first + 1; // read the entries from the trees, filling the output tree this->readExperiment( inputTree1_, iter1, 0 ); this->readExperiment( inputTree2_, iter2, nEntriesInTree1 ); } // Write the output file this->writeFile(); } void LauMergeDataFiles::findExperiments(TTree* tree, ExptsMap& exptsMap) { const Int_t nEntries = tree->GetEntries(); // loop through the tree for ( Int_t iEntry(0); iEntryGetEntry(iEntry); // see if we already have an element in the map for the // current experiment ExptsMap::iterator iter = exptsMap.find(iExpt_); if ( iter == exptsMap.end() ) { // if not, we need to add an element that points to // this entry in the tree as the start entry exptsMap.insert( std::make_pair( iExpt_, std::make_pair( iEntry, -99 ) ) ); // also we need to complete the map element for the // previous experiment with the previous tree entry // as the last entry ExptsMap::iterator previter = exptsMap.find(iExpt_-1); if ( previter != exptsMap.end() ) { previter->second.second = iEntry-1; } } } // need to complete the map element for the final experiment exptsMap[iExpt_].second = nEntries-1; } Bool_t LauMergeDataFiles::checkExperimentMaps() const { // first check that the two maps are the same size UInt_t size1 = tree1Expts_.size(); UInt_t size2 = tree2Expts_.size(); if ( size1 != size2 ) { std::cerr<<"ERROR in LauMergeDataFiles::checkExperimentMaps : Experiment maps are not the same size.\n"; std::cerr<<" : Tree from "<first; ExptsMap::const_iterator iter2 = tree2Expts_.find( expt ); if ( iter2 == tree2Expts_.end() ) { std::cerr<<"ERROR in LauMergeDataFiles::checkExperimentMaps : Cannot find experiment "<second.first; const Int_t lastEntry = expt->second.second; // loop through all the entries for ( Int_t iEntry(firstEntry); iEntry<=lastEntry; ++iEntry ) { // get the entry from the tree tree->GetEntry( iEntry ); // apply the offset to the "event within experiment" variable iEvtWithinExpt_ += offset; // fill the output tree outputTree_->Fill(); } } void LauMergeDataFiles::writeFile() { std::cout<<"Building experiment:event index"<BuildIndex("iExpt","iEvtWithinExpt"); std::cout<<"Writing data to outputfile "<GetName()<SetDirectory(outputFile_); outputFile_->Write(); // clean-up outputFile_->Close(); delete outputFile_; outputFile_ = 0; outputTree_ = 0; inputFile1_->Close(); delete inputFile1_; inputFile1_ = 0; inputTree1_ = 0; inputFile2_->Close(); delete inputFile2_; inputFile2_ = 0; inputTree2_ = 0; doubleVars_.clear(); integerVars_.clear(); tree1Expts_.clear(); tree2Expts_.clear(); } diff --git a/src/LauMinuit.cc b/src/LauMinuit.cc index 03e1ac0..0f2bea3 100644 --- a/src/LauMinuit.cc +++ b/src/LauMinuit.cc @@ -1,282 +1,281 @@ /* Copyright 2013 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauMinuit.cc \brief File containing implementation of LauMinuit methods. */ #include #include #include "TMatrixD.h" #include "TVirtualFitter.h" #include "LauFitObject.hh" #include "LauFitter.hh" #include "LauMinuit.hh" #include "LauParameter.hh" #include "LauParamFixed.hh" // It's necessary to define an external function that specifies the address of the function // that Minuit needs to minimise. Minuit doesn't know about any classes - therefore // use gMinuit->SetFCN(external_function), gMinuit->SetObjectFit(this). // Here, we use TVirtualFitter* fitter instead of gMinuit, defined below. // Then, within the external function, invoke an object from this class (LauAllModel), // and use the member functions to access the parameters/variables. extern void logLikeFun(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag); -ClassImp(LauMinuit) LauMinuit::LauMinuit( Int_t maxPar ) : LauAbsFitter(), minuit_(0), maxPar_(maxPar), nParams_(0), nFreeParams_(0), twoStageFit_(kFALSE), useAsymmFitErrors_(kFALSE), fitStatus_({-1,0.0,0.0}) { TVirtualFitter::SetDefaultFitter( "Minuit" ); minuit_ = TVirtualFitter::Fitter( 0, maxPar_ ); } LauMinuit::~LauMinuit() { } void LauMinuit::initialise( LauFitObject* fitObj, const std::vector& parameters ) { // Check whether we're going to use asymmetric errors if (useAsymmFitErrors_ == kTRUE) { std::cout << "INFO in LauMinuit::fit : We are going to calculate the asymmetric fit errors." << std::endl; std::cout << " : This will, in general, significantly increase the CPU time required for fitting." << std::endl; } else { std::cout << "INFO in LauMinuit::fit : Only parabolic errors will be calculated." << std::endl; } // Store the parameters params_ = parameters; // Hook the external likelihood function to this LauFitter::fitter() and this class. minuit_->SetFCN( logLikeFun ); minuit_->SetObjectFit( fitObj ); // Clear any stored parameters etc... before using minuit_->Clear(); nParams_ = params_.size(); std::cout << "INFO in LauMinuit::initialise : Setting fit parameters" << std::endl; std::cout << " : Total number of parameters = " << nParams_ << std::endl; // Define the default relative error const Double_t defaultError(0.01); // Set-up the parameters for (UInt_t i = 0; i < nParams_; ++i) { TString name = params_[i]->name(); Double_t initVal = params_[i]->initValue(); Double_t initErr = params_[i]->error(); // If we do not have a supplied estimate of the error, we should make a reasonable guess if ( initErr == 0.0 ) { if ( initVal == 0.0 ) { initErr = defaultError; } else if ( TMath::Abs(initErr/initVal) < 1e-6 ) { initErr = TMath::Abs(defaultError * initVal); } } Double_t minVal = params_[i]->minValue(); Double_t maxVal = params_[i]->maxValue(); Bool_t secondStage = params_[i]->secondStage(); if (this->twoStageFit() && secondStage == kTRUE) { params_[i]->fixed(kTRUE); } Bool_t fixVar = params_[i]->fixed(); std::cout << " : Setting parameter " << i << " called " << name << " to have initial value " << initVal << ", error " << initErr << " and range " << minVal << " to " << maxVal << std::endl; minuit_->SetParameter(i, name, initVal, initErr, minVal, maxVal); // Fix parameter if required if (fixVar == kTRUE) { std::cout << " : Fixing parameter " << i << std::endl; minuit_->FixParameter(i); } } LauParamFixed pred; nFreeParams_ = nParams_ - std::count_if(params_.begin(),params_.end(),pred); // Need to set the "SET ERR" command to +0.5 for +/-1 sigma errors // for maximum likelihood fit. Very important command, otherwise all // extracted errors will be too big, and pull distributions will be too narrow! // TODO - The alternative to this is to make FCN = -2log(L) rather than -log(L) Double_t argL[2]; argL[0] = 0.5; fitStatus_.status = minuit_->ExecuteCommand("SET ERR", argL, 1); //argL[0] = 0; //fitStatus_.status = minuit_->ExecuteCommand("SET STRATEGY", argL, 1); } LauFitObject* LauMinuit::getFitObject() { return (minuit_!=0) ? dynamic_cast( minuit_->GetObjectFit() ) : 0; } const LauAbsFitter::FitStatus& LauMinuit::minimise() { Double_t arglist[2]; arglist[0] = 1000*nParams_; // maximum iterations arglist[1] = 0.05; // tolerance -> min EDM = 0.001*tolerance (0.05) fitStatus_.status = minuit_->ExecuteCommand("MIGRAD", arglist, 2); // Dummy variables - need to feed them to the function // used for getting NLL, EDM and error matrix status Double_t errdef; Int_t nvpar, nparx; if (fitStatus_.status != 0) { std::cerr << "ERROR in LauMinuit::minimise : Error in minimising loglike." << std::endl; } else { // Check that the error matrix is ok fitStatus_.status = minuit_->GetStats(fitStatus_.NLL, fitStatus_.EDM, errdef, nvpar, nparx); std::cout << "INFO in LauMinuit::minimise : Error matrix status after MIGRAD is: " << fitStatus_.status << std::endl; // 0= not calculated at all // 1= approximation only, not accurate // 2= full matrix, but forced positive-definite // 3= full accurate covariance matrix // Fit result was OK. Now get the more precise errors. fitStatus_.status = minuit_->ExecuteCommand("HESSE", arglist, 1); if (fitStatus_.status != 0) { std::cerr << "ERROR in LauMinuit::minimise : Error in HESSE routine." << std::endl; } else { // Check that the error matrix is ok fitStatus_.status = minuit_->GetStats(fitStatus_.NLL, fitStatus_.EDM, errdef, nvpar, nparx); std::cout << "INFO in LauMinuit::minimise : Error matrix status after HESSE is: " << fitStatus_.status << std::endl; // 0= not calculated at all // 1= approximation only, not accurate // 2= full matrix, but forced positive-definite // 3= full accurate covariance matrix // Symmetric errors and eror matrix were OK. // Get asymmetric errors if asked for. if (useAsymmFitErrors_ == kTRUE) { LauFitObject* fitObj = this->getFitObject(); fitObj->withinAsymErrorCalc( kTRUE ); fitStatus_.status = minuit_->ExecuteCommand("MINOS", arglist, 1); fitObj->withinAsymErrorCalc( kFALSE ); if (fitStatus_.status != 0) { std::cerr << "ERROR in LauMinuit::minimise : Error in MINOS routine." << std::endl; } } } } // Print results fitStatus_.status = minuit_->GetStats(fitStatus_.NLL, fitStatus_.EDM, errdef, nvpar, nparx); std::cout << "INFO in LauMinuit::minimise : Final error matrix status is: " << fitStatus_.status << std::endl; // 0= not calculated at all // 1= approximation only, not accurate // 2= full matrix, but forced positive-definite // 3= full accurate covariance matrix minuit_->PrintResults(3, fitStatus_.NLL); // Retrieve the covariance matrix from the fitter // For some reason the array returned is as if the matrix is of dimension nParams_ x nParams_ // but only the elements within the sub-matrix nFreeParams_ x nFreeParams_ have values, // the "trailing" elements are zero, so we trim them off. Double_t* covMatrix = minuit_->GetCovarianceMatrix(); covMatrix_.Clear(); covMatrix_.ResizeTo( nParams_, nParams_ ); covMatrix_.SetMatrixArray( covMatrix ); covMatrix_.ResizeTo( nFreeParams_, nFreeParams_ ); return fitStatus_; } void LauMinuit::fixSecondStageParameters() { for (UInt_t i = 0; i < nParams_; ++i) { Bool_t secondStage = params_[i]->secondStage(); if (secondStage == kTRUE) { params_[i]->fixed(kTRUE); minuit_->FixParameter(i); } } LauParamFixed pred; nFreeParams_ = nParams_ - std::count_if(params_.begin(),params_.end(),pred); } void LauMinuit::releaseSecondStageParameters() { for (UInt_t i = 0; i < nParams_; ++i) { Bool_t secondStage = params_[i]->secondStage(); if (secondStage == kTRUE) { params_[i]->fixed(kFALSE); minuit_->ReleaseParameter(i); } } LauParamFixed pred; nFreeParams_ = nParams_ - std::count_if(params_.begin(),params_.end(),pred); } void LauMinuit::updateParameters() { for (UInt_t i = 0; i < nParams_; ++i) { // Get the value and errors from MINUIT Double_t value = minuit_->GetParameter(i); Double_t error(0.0); Double_t negError(0.0); Double_t posError(0.0); Double_t globalcc(0.0); minuit_->GetErrors(i, posError, negError, error, globalcc); params_[i]->valueAndErrors(value, error, negError, posError); params_[i]->globalCorrelationCoeff(globalcc); } } // Definition of the fitting function for Minuit void logLikeFun(Int_t& npar, Double_t* /*first_derivatives*/, Double_t& f, Double_t* par, Int_t /*iflag*/) { // Routine that specifies the negative log-likelihood function for the fit. // Used by the MINUIT minimising code. LauFitObject* theModel = LauFitter::fitter()->getFitObject(); // Set the internal parameters for this model using parameters from Minuit (pars): theModel->setParsFromMinuit( par, npar ); // Set the value of f to be the total negative log-likelihood for the data sample. f = theModel->getTotNegLogLikelihood(); } diff --git a/src/LauModIndPartWaveMagPhase.cc b/src/LauModIndPartWaveMagPhase.cc index c9176eb..0168eae 100644 --- a/src/LauModIndPartWaveMagPhase.cc +++ b/src/LauModIndPartWaveMagPhase.cc @@ -1,141 +1,140 @@ /* Copyright 2015 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauModIndPartWaveMagPhase.cc \brief File containing implementation of LauModIndPartWaveMagPhase class. */ #include #include #include "Lau1DCubicSpline.hh" #include "LauConstants.hh" #include "LauKinematics.hh" #include "LauModIndPartWaveMagPhase.hh" #include "LauResonanceInfo.hh" -ClassImp(LauModIndPartWaveMagPhase) LauModIndPartWaveMagPhase::LauModIndPartWaveMagPhase(LauResonanceInfo* resInfo, Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsModIndPartWave(resInfo, resPairAmpInt, daughters) { } LauModIndPartWaveMagPhase::~LauModIndPartWaveMagPhase() { } void LauModIndPartWaveMagPhase::createAmpParameters(const UInt_t iKnot) { const TString& parNameBase = this->getSanitisedName(); const Bool_t secondStage = this->floatKnotsSecondStage(); std::vector& magnitudePars = this->getAmp1Pars(); std::vector& phasePars = this->getAmp2Pars(); TString magName(parNameBase); magName += "_A"; magName += iKnot; magnitudePars.push_back(this->getResInfo()->getExtraParameter( magName )); if( magnitudePars[iKnot] == 0) { magnitudePars[iKnot] = new LauParameter( magName, 1.0, 0.0, 10.0, kFALSE); magnitudePars[iKnot]->secondStage(secondStage); this->getResInfo()->addExtraParameter(magnitudePars[iKnot]); } TString phaseName(parNameBase); phaseName += "_d"; phaseName += iKnot; phasePars.push_back(this->getResInfo()->getExtraParameter( phaseName )); if( phasePars[iKnot] == 0) { phasePars[iKnot] = new LauParameter( phaseName, 1.0, -6.0*LauConstants::pi, 6.0*LauConstants::pi, kFALSE); phasePars[iKnot]->secondStage(secondStage); this->getResInfo()->addExtraParameter(phasePars[iKnot]); } } void LauModIndPartWaveMagPhase::setKnotAmp(const UInt_t knot, const Double_t magVal, const Double_t phaseVal, const Bool_t fixMagnitude, const Bool_t fixPhase) { const UInt_t nknots = this->nKnots(); if ( knot >= nknots ) { std::cerr << "WARNING in LauModIndPartWaveMagPhase::setKnotAmp : Index " << knot << " does not correspond to an existing knot in resonance " << this->getResonanceName() << std::endl; std::cerr << " : Index must be in range 0 to " << nknots-1 << std::endl; return; } const std::vector& masses = this->getMasses(); std::vector& magnitudes = this->getAmp1Vals(); std::vector& phases = this->getAmp2Vals(); std::vector& magnitudePars = this->getAmp1Pars(); std::vector& phasePars = this->getAmp2Pars(); magnitudes[knot] = magVal; magnitudePars[knot]->value(magVal); magnitudePars[knot]->genValue(magVal); magnitudePars[knot]->initValue(magVal); magnitudePars[knot]->fixed(fixMagnitude); phases[knot] = phaseVal; phasePars[knot]->value(phaseVal); phasePars[knot]->genValue(phaseVal); phasePars[knot]->initValue(phaseVal); phasePars[knot]->fixed(fixPhase); if ( knot == 0 ) { std::cout << "INFO in LauModIndPartWaveMagPhase::setKnotAmp : Knot updated in resonance " << this->getResonanceName() << " at lower kinematic limit (" << masses[knot] << ")" << std::endl; } else if ( knot == nknots-1 ) { std::cout << "INFO in LauModIndPartWaveMagPhase::setKnotAmp : Knot updated in resonance " << this->getResonanceName() << " at upper kinematic limit (" << masses[knot] << ")" << std::endl; } else { std::cout << "INFO in LauModIndPartWaveMagPhase::setKnotAmp : Knot updated in resonance " << this->getResonanceName() << " at mass " << masses[knot] << std::endl; } if ( fixMagnitude ) { std::cout << " : Magnitude fixed to " << magVal << std::endl; } else { std::cout << " : Magnitude set to " << magVal << std::endl; } if ( fixPhase ) { std::cout << " : Phase fixed to " << phaseVal << std::endl; } else { std::cout << " : Phase set to " << phaseVal << std::endl; } } void LauModIndPartWaveMagPhase::evaluateAmplitude(const Double_t mass) { const Lau1DCubicSpline* splineMag = this->getSpline1(); const Lau1DCubicSpline* splinePhase = this->getSpline2(); const Double_t mag = splineMag->evaluate(mass); const Double_t phase = splinePhase->evaluate(mass); this->setAmp(mag*TMath::Cos(phase), mag*TMath::Sin(phase)); } diff --git a/src/LauModIndPartWaveRealImag.cc b/src/LauModIndPartWaveRealImag.cc index 7e63ba0..2d224e8 100644 --- a/src/LauModIndPartWaveRealImag.cc +++ b/src/LauModIndPartWaveRealImag.cc @@ -1,141 +1,140 @@ /* Copyright 2015 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauModIndPartWaveRealImag.cc \brief File containing implementation of LauModIndPartWaveRealImag class. */ #include #include #include "Lau1DCubicSpline.hh" #include "LauConstants.hh" #include "LauKinematics.hh" #include "LauModIndPartWaveRealImag.hh" #include "LauResonanceInfo.hh" -ClassImp(LauModIndPartWaveRealImag) LauModIndPartWaveRealImag::LauModIndPartWaveRealImag(LauResonanceInfo* resInfo, Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsModIndPartWave(resInfo, resPairAmpInt, daughters) { } LauModIndPartWaveRealImag::~LauModIndPartWaveRealImag() { } void LauModIndPartWaveRealImag::createAmpParameters(const UInt_t iKnot) { const TString& parNameBase = this->getSanitisedName(); const Bool_t secondStage = this->floatKnotsSecondStage(); std::vector& rePars = this->getAmp1Pars(); std::vector& imPars = this->getAmp2Pars(); TString reName(parNameBase); reName += "_Re"; reName += iKnot; rePars.push_back(this->getResInfo()->getExtraParameter( reName )); if( rePars[iKnot] == 0) { rePars[iKnot] = new LauParameter( reName, 1.0, -10.0, 10.0, kFALSE); rePars[iKnot]->secondStage(secondStage); this->getResInfo()->addExtraParameter(rePars[iKnot]); } TString imName(parNameBase); imName += "_Im"; imName += iKnot; imPars.push_back(this->getResInfo()->getExtraParameter( imName )); if( imPars[iKnot] == 0) { imPars[iKnot] = new LauParameter( imName, 1.0, -10.0, 10.0, kFALSE); imPars[iKnot]->secondStage(secondStage); this->getResInfo()->addExtraParameter(imPars[iKnot]); } } void LauModIndPartWaveRealImag::setKnotAmp(const UInt_t knot, const Double_t realVal, const Double_t imagVal, const Bool_t fixRealPart, const Bool_t fixImagPart) { const UInt_t nknots = this->nKnots(); if ( knot >= nknots ) { std::cerr << "WARNING in LauModIndPartWaveRealImag::setKnotAmp : Index " << knot << " does not correspond to an existing knot in resonance " << this->getResonanceName() << std::endl; std::cerr << " : Index must be in range 0 to " << nknots-1 << std::endl; return; } const std::vector& masses = this->getMasses(); std::vector& realVals = this->getAmp1Vals(); std::vector& imagVals = this->getAmp2Vals(); std::vector& realPars = this->getAmp1Pars(); std::vector& imagPars = this->getAmp2Pars(); realVals[knot] = realVal; realPars[knot]->value(realVal); realPars[knot]->genValue(realVal); realPars[knot]->initValue(realVal); realPars[knot]->fixed(fixRealPart); imagVals[knot] = imagVal; imagPars[knot]->value(imagVal); imagPars[knot]->genValue(imagVal); imagPars[knot]->initValue(imagVal); imagPars[knot]->fixed(fixImagPart); if ( knot == 0 ) { std::cout << "INFO in LauModIndPartWaveRealImag::setKnotAmp : Knot updated in resonance " << this->getResonanceName() << " at lower kinematic limit (" << masses[knot] << ")" << std::endl; } else if ( knot == nknots-1 ) { std::cout << "INFO in LauModIndPartWaveRealImag::setKnotAmp : Knot updated in resonance " << this->getResonanceName() << " at upper kinematic limit (" << masses[knot] << ")" << std::endl; } else { std::cout << "INFO in LauModIndPartWaveRealImag::setKnotAmp : Knot updated in resonance " << this->getResonanceName() << " at mass " << masses[knot] << std::endl; } if ( fixRealPart ) { std::cout << " : Real part fixed to " << realVal << std::endl; } else { std::cout << " : Real part set to " << realVal << std::endl; } if ( fixImagPart ) { std::cout << " : Imaginary part fixed to " << imagVal << std::endl; } else { std::cout << " : Imaginary part set to " << imagVal << std::endl; } } void LauModIndPartWaveRealImag::evaluateAmplitude(const Double_t mass) { const Lau1DCubicSpline* splineReal = this->getSpline1(); const Lau1DCubicSpline* splineImag = this->getSpline2(); const Double_t re = splineReal->evaluate(mass); const Double_t im = splineImag->evaluate(mass); this->setAmp(re, im); } diff --git a/src/LauNRAmplitude.cc b/src/LauNRAmplitude.cc index e3c2e4f..3e906c8 100644 --- a/src/LauNRAmplitude.cc +++ b/src/LauNRAmplitude.cc @@ -1,284 +1,283 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauNRAmplitude.cc \brief File containing implementation of LauNRAmplitude class. */ #include #include "LauKinematics.hh" #include "LauNRAmplitude.hh" #include "LauResonanceInfo.hh" -ClassImp(LauNRAmplitude) LauNRAmplitude::LauNRAmplitude(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), d_(0), c1_(0), c2_(0), p1_(0), p2_(0) { // Default values for parameters, taken from arXiv:0709.0075v1 [hep-ph] const Double_t dVal(1.3232e-3); const Double_t c1Val(0.65); const Double_t c2Val(0.55); const Double_t p1Val(18.0); const Double_t p2Val(15.0); const TString& parNameBase = this->getSanitisedName(); TString dName(parNameBase); dName += "_d"; d_ = resInfo->getExtraParameter( dName ); if ( d_ == 0 ) { d_ = new LauParameter( dName, dVal, 0.0, 1.0, kTRUE ); d_->secondStage(kTRUE); resInfo->addExtraParameter( d_ ); } TString c1Name(parNameBase); c1Name += "_c1"; c1_ = resInfo->getExtraParameter( c1Name ); if ( c1_ == 0 ) { c1_ = new LauParameter( c1Name, c1Val, 0.0, 2.0, kTRUE ); c1_->secondStage(kTRUE); resInfo->addExtraParameter( c1_ ); } TString c2Name(parNameBase); c2Name += "_c2"; c2_ = resInfo->getExtraParameter( c2Name ); if ( c2_ == 0 ) { c2_ = new LauParameter( c2Name, c2Val, 0.0, 2.0, kTRUE ); c2_->secondStage(kTRUE); resInfo->addExtraParameter( c2_ ); } TString p1Name(parNameBase); p1Name += "_p1"; p1_ = resInfo->getExtraParameter( p1Name ); if ( p1_ == 0 ) { p1_ = new LauParameter( p1Name, p1Val, 0.0, 50.0, kTRUE ); p1_->secondStage(kTRUE); resInfo->addExtraParameter( p1_ ); } TString p2Name(parNameBase); p2Name += "_p2"; p2_ = resInfo->getExtraParameter( p2Name ); if ( p2_ == 0 ) { p2_ = new LauParameter( p2Name, p2Val, 0.0, 50.0, kTRUE ); p2_->secondStage(kTRUE); resInfo->addExtraParameter( p2_ ); } } LauNRAmplitude::~LauNRAmplitude() { } void LauNRAmplitude::initialise() { } LauComplex LauNRAmplitude::amplitude(const LauKinematics* kinematics) { // Get the information from the kinematics object const Double_t m13Sq = kinematics->getm13Sq(); const Double_t m23Sq = kinematics->getm23Sq(); const Double_t m13 = kinematics->getm13(); const Double_t m23 = kinematics->getm23(); // Calculate the magnitude Double_t magnitude = TMath::Sqrt( m13 * m23 * this->f(m23Sq, c1_->unblindValue(), p1_->unblindValue()) * this->f(m13Sq, c2_->unblindValue(), p2_->unblindValue()) * TMath::Exp( -1.0 * d_->unblindValue() * m13Sq*m13Sq * m23Sq*m23Sq ) ); // return the amplitude LauComplex resAmplitude(magnitude, 0.0); return resAmplitude; } LauComplex LauNRAmplitude::resAmp(Double_t mass, Double_t spinTerm) { std::cerr << "ERROR in LauNRAmplitude::resAmp : This method shouldn't get called." << std::endl; std::cerr << " Returning zero amplitude for mass = " << mass << " and spinTerm = " << spinTerm << "." << std::endl; return LauComplex(0.0, 0.0); } Double_t LauNRAmplitude::f(const Double_t s, const Double_t c, const Double_t p) const { return 1.0 / (1.0 + TMath::Exp( c * (s-p) )); } const std::vector& LauNRAmplitude::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixdParameter() ) { this->addFloatingParameter( d_ ); } if ( ! this->fixc1Parameter() ) { this->addFloatingParameter( c1_ ); } if ( ! this->fixc2Parameter() ) { this->addFloatingParameter( c2_ ); } if ( ! this->fixp1Parameter() ) { this->addFloatingParameter( p1_ ); } if ( ! this->fixp2Parameter() ) { this->addFloatingParameter( p2_ ); } return this->getParameters(); } void LauNRAmplitude::setResonanceParameter(const TString& name, const Double_t value) { // Set various parameters for the NRAmplitude lineshape dynamics if (name == "d") { this->setdParameter(value); std::cout << "INFO in LauNRAmplitude::setResonanceParameter : Setting NRAmplitude d = " << this->getdParameter() << std::endl; } else if (name == "c1") { this->setc1Parameter(value); std::cout << "INFO in LauNRAmplitude::setResonanceParameter : Setting NRAmplitude c1 = " << this->getc1Parameter() << std::endl; } else if (name == "c2") { this->setc2Parameter(value); std::cout << "INFO in LauNRAmplitude::setResonanceParameter : Setting NRAmplitude c2 = " << this->getc2Parameter() << std::endl; } else if (name == "p1") { this->setp1Parameter(value); std::cout << "INFO in LauNRAmplitude::setResonanceParameter : Setting NRAmplitude p1 = " << this->getp1Parameter() << std::endl; } else if (name == "p2") { this->setp2Parameter(value); std::cout << "INFO in LauNRAmplitude::setResonanceParameter : Setting NRAmplitude p2 = " << this->getp2Parameter() << std::endl; } else { std::cerr << "WARNING in LauNRAmplitude::setResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } void LauNRAmplitude::floatResonanceParameter(const TString& name) { if (name == "d") { if ( d_->fixed() ) { d_->fixed( kFALSE ); this->addFloatingParameter( d_ ); } else { std::cerr << "WARNING in LauNRAmplitude::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "c1") { if ( c1_->fixed() ) { c1_->fixed( kFALSE ); this->addFloatingParameter( c1_ ); } else { std::cerr << "WARNING in LauNRAmplitude::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "c2") { if ( c2_->fixed() ) { c2_->fixed( kFALSE ); this->addFloatingParameter( c2_ ); } else { std::cerr << "WARNING in LauNRAmplitude::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "p1") { if ( p1_->fixed() ) { p1_->fixed( kFALSE ); this->addFloatingParameter( p1_ ); } else { std::cerr << "WARNING in LauNRAmplitude::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "p2") { if ( p2_->fixed() ) { p2_->fixed( kFALSE ); this->addFloatingParameter( p2_ ); } else { std::cerr << "WARNING in LauNRAmplitude::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else { std::cerr << "WARNING in LauNRAmplitude::fixResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } LauParameter* LauNRAmplitude::getResonanceParameter(const TString& name) { if (name == "d") { return d_; } else if (name == "c1") { return c1_; } else if (name == "c2") { return c2_; } else if (name == "p1") { return p1_; } else if (name == "p2") { return p2_; } else { std::cerr << "WARNING in LauNRAmplitude::getResonanceParameter: Parameter name not reconised." << std::endl; return 0; } } void LauNRAmplitude::setdParameter(const Double_t d) { d_->value( d ); d_->genValue( d ); d_->initValue( d ); } void LauNRAmplitude::setc1Parameter(const Double_t c1) { c1_->value( c1 ); c1_->genValue( c1 ); c1_->initValue( c1 ); } void LauNRAmplitude::setc2Parameter(const Double_t c2) { c2_->value( c2 ); c2_->genValue( c2 ); c2_->initValue( c2 ); } void LauNRAmplitude::setp1Parameter(const Double_t p1) { p1_->value( p1 ); p1_->genValue( p1 ); p1_->initValue( p1 ); } void LauNRAmplitude::setp2Parameter(const Double_t p2) { p2_->value( p2 ); p2_->genValue( p2 ); p2_->initValue( p2 ); } diff --git a/src/LauNovosibirskPdf.cc b/src/LauNovosibirskPdf.cc index 3e363e4..2f304c1 100644 --- a/src/LauNovosibirskPdf.cc +++ b/src/LauNovosibirskPdf.cc @@ -1,152 +1,151 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauNovosibirskPdf.cc \brief File containing implementation of LauNovosibirskPdf class. */ #include using std::cout; using std::cerr; using std::endl; #include "TMath.h" #include "TSystem.h" #include "LauNovosibirskPdf.hh" #include "LauConstants.hh" -ClassImp(LauNovosibirskPdf) LauNovosibirskPdf::LauNovosibirskPdf(const TString& theVarName, const vector& params, Double_t minAbscissa, Double_t maxAbscissa) : LauAbsPdf(theVarName, params, minAbscissa, maxAbscissa), mean_(0), sigma_(0), tail_(0) { // Constructor for the Novosibirsk PDF. // // The parameters in params are the mean, sigma and tail. // The last two arguments specify the range in which the PDF is defined, and the PDF // will be normalised w.r.t. these limits. mean_ = this->findParameter("mean"); sigma_ = this->findParameter("sigma"); tail_ = this->findParameter("tail"); if ((this->nParameters() != 3) || (mean_ == 0) || (sigma_ == 0) || (tail_ == 0)) { cerr<<"ERROR in LauNovosibirskPdf constructor: LauNovosibirskPdf requires 3 parameters: \"mean\", \"sigma\"and \"tail\" "<Exit(EXIT_FAILURE); } // Cache the normalisation factor this->calcNorm(); } LauNovosibirskPdf::~LauNovosibirskPdf() { // Destructor } void LauNovosibirskPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Get our abscissa Double_t abscissa = abscissas[0]; // Get the up to date parameter values Double_t mean = mean_->unblindValue(); Double_t sigma = sigma_->unblindValue(); Double_t tail = tail_->unblindValue(); // Evaluate the Novosibirsk PDF value Double_t qa(0.0), qb(0.0), qx(0.0), qy(0.0); Double_t arg(0.0); Double_t value(0.0); if(TMath::Abs(tail) < 1.e-7) arg = 0.5*((abscissa - mean)/sigma)*((abscissa - mean)/sigma); else { qa = tail*TMath::Sqrt(LauConstants::log4); qb = TMath::SinH(qa)/qa; qx = (abscissa - mean)/sigma*qb; qy = 1.0+ tail*qx; //---- Cutting curve from right side if( qy > 1.E-7) { arg = 0.5*( (log(qy)/tail)*(log(qy)/tail) + tail*tail); }else{ arg = 15.0; } } value = TMath::Exp(-arg); // if the parameters are floating then we // need to recalculate the normalisation if (!this->cachePDF() && !this->withinNormCalc() && !this->withinGeneration()) { this->calcNorm(); } this->setUnNormPDFVal(value); } void LauNovosibirskPdf::calcPDFHeight( const LauKinematics* /*kinematics*/ ) { if (this->heightUpToDate()) { return; } // Get the up to date parameter values Double_t mean = mean_->unblindValue(); LauAbscissas maxPoint(1); maxPoint[0] = mean; // Calculate the PDF height for the Bifurcated Gaussian function. if (mean < this->getMinAbscissa()) { maxPoint[0] = this->getMinAbscissa(); } else if (mean > this->getMaxAbscissa()) { maxPoint[0] = this->getMaxAbscissa(); } this->calcLikelihoodInfo(maxPoint); Double_t height = this->getUnNormLikelihood(); // Multiply by a small factor to avoid problems from rounding errors height *= (1.0 + 1e-1); this->setMaxHeight(height); } diff --git a/src/LauParameter.cc b/src/LauParameter.cc index 70791ca..091b4c8 100644 --- a/src/LauParameter.cc +++ b/src/LauParameter.cc @@ -1,733 +1,732 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauParameter.cc \brief File containing implementation of LauParameter class. */ #include #include using std::cout; using std::cerr; using std::endl; using std::map; #include "TRandom.h" #include "LauParameter.hh" #include "LauRandom.hh" -ClassImp(LauParameter) LauParameter::LauParameter() : name_(""), value_(0.0), error_(0.0), negError_(0.0), posError_(0.0), genValue_(0.0), initValue_(0.0), minValue_(0.0), maxValue_(0.0), fixed_(kTRUE), secondStage_(kFALSE), gaussConstraint_(kFALSE), constraintMean_(0.0), constraintWidth_(0.0), gcc_(0.0), bias_(0.0), pull_(0.0), clone_(kFALSE), parent_(0), blinder_(0) { } LauParameter::LauParameter(const TString& parName) : name_(parName), value_(0.0), error_(0.0), negError_(0.0), posError_(0.0), genValue_(0.0), initValue_(0.0), minValue_(0.0), maxValue_(0.0), fixed_(kTRUE), secondStage_(kFALSE), gaussConstraint_(kFALSE), constraintMean_(0.0), constraintWidth_(0.0), gcc_(0.0), bias_(0.0), pull_(0.0), clone_(kFALSE), parent_(0), blinder_(0) { } LauParameter::LauParameter(Double_t parValue) : name_(""), value_(parValue), error_(0.0), negError_(0.0), posError_(0.0), genValue_(parValue), initValue_(parValue), minValue_(parValue-1e-6), maxValue_(parValue+1e-6), fixed_(kTRUE), secondStage_(kFALSE), gaussConstraint_(kFALSE), constraintMean_(0.0), constraintWidth_(0.0), gcc_(0.0), bias_(0.0), pull_(0.0), clone_(kFALSE), parent_(0), blinder_(0) { } LauParameter::LauParameter(const TString& parName, Double_t parValue) : name_(parName), value_(parValue), error_(0.0), negError_(0.0), posError_(0.0), genValue_(parValue), initValue_(parValue), minValue_(parValue-1e-6), maxValue_(parValue+1e-6), fixed_(kTRUE), secondStage_(kFALSE), gaussConstraint_(kFALSE), constraintMean_(0.0), constraintWidth_(0.0), gcc_(0.0), bias_(0.0), pull_(0.0), clone_(kFALSE), parent_(0), blinder_(0) { } LauParameter::LauParameter(Double_t parValue, Double_t min, Double_t max) : name_(""), value_(parValue), error_(0.0), negError_(0.0), posError_(0.0), genValue_(parValue), initValue_(parValue), minValue_(min), maxValue_(max), fixed_(kTRUE), secondStage_(kFALSE), gaussConstraint_(kFALSE), constraintMean_(0.0), constraintWidth_(0.0), gcc_(0.0), bias_(0.0), pull_(0.0), clone_(kFALSE), parent_(0), blinder_(0) { this->checkRange(); } LauParameter::LauParameter(Double_t parValue, Double_t parError, Double_t min, Double_t max) : name_(""), value_(parValue), error_(parError), negError_(0.0), posError_(0.0), genValue_(parValue), initValue_(parValue), minValue_(min), maxValue_(max), fixed_(kTRUE), secondStage_(kFALSE), gaussConstraint_(kFALSE), constraintMean_(0.0), constraintWidth_(0.0), gcc_(0.0), bias_(0.0), pull_(0.0), clone_(kFALSE), parent_(0), blinder_(0) { this->checkRange(); } LauParameter::LauParameter(Double_t parValue, Double_t min, Double_t max, Bool_t parFixed) : name_(""), value_(parValue), error_(0.0), negError_(0.0), posError_(0.0), genValue_(parValue), initValue_(parValue), minValue_(min), maxValue_(max), fixed_(parFixed), secondStage_(kFALSE), gaussConstraint_(kFALSE), constraintMean_(0.0), constraintWidth_(0.0), gcc_(0.0), bias_(0.0), pull_(0.0), clone_(kFALSE), parent_(0), blinder_(0) { this->checkRange(); } LauParameter::LauParameter(const TString& parName, Double_t parValue, Double_t min, Double_t max) : name_(parName), value_(parValue), error_(0.0), negError_(0.0), posError_(0.0), genValue_(parValue), initValue_(parValue), minValue_(min), maxValue_(max), fixed_(kTRUE), secondStage_(kFALSE), gaussConstraint_(kFALSE), constraintMean_(0.0), constraintWidth_(0.0), gcc_(0.0), bias_(0.0), pull_(0.0), clone_(kFALSE), parent_(0), blinder_(0) { this->checkRange(); } LauParameter::LauParameter(const TString& parName, Double_t parValue, Double_t min, Double_t max, Bool_t parFixed) : name_(parName), value_(parValue), error_(0.0), negError_(0.0), posError_(0.0), genValue_(parValue), initValue_(parValue), minValue_(min), maxValue_(max), fixed_(parFixed), secondStage_(kFALSE), gaussConstraint_(kFALSE), constraintMean_(0.0), constraintWidth_(0.0), gcc_(0.0), bias_(0.0), pull_(0.0), clone_(kFALSE), parent_(0), blinder_(0) { this->checkRange(); } LauParameter::LauParameter(const TString& parName, Double_t parValue, Double_t parError, Double_t min, Double_t max) : name_(parName), value_(parValue), error_(parError), negError_(0.0), posError_(0.0), genValue_(parValue), initValue_(parValue), minValue_(min), maxValue_(max), fixed_(kTRUE), secondStage_(kFALSE), gaussConstraint_(kFALSE), constraintMean_(0.0), constraintWidth_(0.0), gcc_(0.0), bias_(0.0), pull_(0.0), clone_(kFALSE), parent_(0), blinder_(0) { this->checkRange(); } LauParameter::LauParameter(const LauParameter& rhs) : TObject(rhs), LauAbsRValue(rhs), name_(rhs.name_), value_(rhs.value_), error_(rhs.error_), negError_(rhs.negError_), posError_(rhs.posError_), genValue_(rhs.genValue_), initValue_(rhs.initValue_), minValue_(rhs.minValue_), maxValue_(rhs.maxValue_), fixed_(rhs.fixed_), secondStage_(rhs.secondStage_), gaussConstraint_(rhs.gaussConstraint_), constraintMean_(rhs.constraintMean_), constraintWidth_(rhs.constraintWidth_), gcc_(rhs.gcc_), bias_(rhs.bias_), pull_(rhs.pull_), clone_(rhs.clone_), parent_(rhs.parent_), clones_(rhs.clones_), blinder_((rhs.blinder_==0) ? 0 : new LauBlind(*(rhs.blinder_))) { } LauParameter& LauParameter::operator=(const LauParameter& rhs) { if (&rhs != this) { TObject::operator=(rhs); LauAbsRValue::operator=(rhs); name_ = rhs.name_; value_ = rhs.value_; error_ = rhs.error_; negError_ = rhs.negError_; posError_ = rhs.posError_; genValue_ = rhs.genValue_; initValue_ = rhs.initValue_; minValue_ = rhs.minValue_; maxValue_ = rhs.maxValue_; fixed_ = rhs.fixed_; secondStage_ = rhs.secondStage_; gaussConstraint_ = rhs.gaussConstraint_; constraintMean_ = rhs.constraintMean_; constraintWidth_ = rhs.constraintWidth_; gcc_ = rhs.gcc_; bias_ = rhs.bias_; pull_ = rhs.pull_; clone_ = rhs.clone_; parent_ = rhs.parent_; clones_ = rhs.clones_; delete blinder_; blinder_ = (rhs.blinder_==0) ? 0 : new LauBlind(*(rhs.blinder_)); } return *this; } LauParameter::~LauParameter() { delete blinder_; } std::vector LauParameter::getPars() { std::vector list; list.push_back(this); return list; } void LauParameter::value(Double_t newValue) { if (this->clone()) { parent_->value(newValue); } else { this->checkRange(newValue,this->minValue(),this->maxValue()); this->updateClones(kTRUE); } } void LauParameter::error(Double_t newError) { if (this->clone()) { parent_->error(newError); } else { error_ = TMath::Abs(newError); this->updateClones(kFALSE); } } void LauParameter::negError(Double_t newNegError) { if (this->clone()) { parent_->negError(newNegError); } else { negError_ = TMath::Abs(newNegError); this->updateClones(kFALSE); } } void LauParameter::posError(Double_t newPosError) { if (this->clone()) { parent_->posError(newPosError); } else { posError_ = TMath::Abs(newPosError); this->updateClones(kFALSE); } } void LauParameter::errors(Double_t newError, Double_t newNegError, Double_t newPosError) { if (this->clone()) { parent_->errors(newError,newNegError,newPosError); } else { error_ = TMath::Abs(newError); negError_ = TMath::Abs(newNegError); posError_ = TMath::Abs(newPosError); this->updateClones(kFALSE); } } void LauParameter::valueAndErrors(Double_t newValue, Double_t newError, Double_t newNegError, Double_t newPosError) { if (this->clone()) { parent_->valueAndErrors(newValue,newError,newNegError,newPosError); } else { this->checkRange(newValue,this->minValue(),this->maxValue()); error_ = TMath::Abs(newError); negError_ = TMath::Abs(newNegError); posError_ = TMath::Abs(newPosError); this->updateClones(kFALSE); } } void LauParameter::globalCorrelationCoeff(Double_t newGCCValue) { if (this->clone()) { parent_->globalCorrelationCoeff(newGCCValue); } else { gcc_ = newGCCValue; this->updateClones(kFALSE); } } void LauParameter::genValue(Double_t newGenValue) { if (this->clone()) { parent_->genValue(newGenValue); } else { genValue_ = newGenValue; this->updateClones(kFALSE); } } void LauParameter::initValue(Double_t newInitValue) { if (this->clone()) { parent_->initValue(newInitValue); } else { initValue_ = newInitValue; this->updateClones(kFALSE); } } void LauParameter::minValue(Double_t newMinValue) { if (this->clone()) { parent_->minValue(newMinValue); } else { this->checkRange(this->value(),newMinValue,this->maxValue()); this->updateClones(kFALSE); } } void LauParameter::maxValue(Double_t newMaxValue) { if (this->clone()) { parent_->maxValue(newMaxValue); } else { this->checkRange(this->value(),this->minValue(),newMaxValue); this->updateClones(kFALSE); } } void LauParameter::range(Double_t newMinValue, Double_t newMaxValue) { if (this->clone()) { parent_->range(newMinValue,newMaxValue); } else { this->checkRange(this->value(),newMinValue,newMaxValue); this->updateClones(kFALSE); } } void LauParameter::valueAndRange(Double_t newValue, Double_t newMinValue, Double_t newMaxValue) { if (this->clone()) { parent_->valueAndRange(newValue,newMinValue,newMaxValue); } else { this->checkRange(newValue,newMinValue,newMaxValue); this->updateClones(kFALSE); } } void LauParameter::name(const TString& newName) { // no need to update clones here // clones are allowed to have different names name_ = newName; } void LauParameter::fixed(Bool_t parFixed) { if (this->clone()) { parent_->fixed(parFixed); } else { fixed_ = parFixed; this->updateClones(kFALSE); } } void LauParameter::secondStage(Bool_t secondStagePar) { if (this->clone()) { parent_->secondStage(secondStagePar); } else { secondStage_ = secondStagePar; this->updateClones(kFALSE); } } void LauParameter::addGaussianConstraint(Double_t newGaussMean, Double_t newGaussWidth) { if (this->clone()) { parent_->addGaussianConstraint(newGaussMean,newGaussWidth); } else { gaussConstraint_ = kTRUE; constraintMean_ = newGaussMean; constraintWidth_ = newGaussWidth; this->updateClones(kFALSE); } } void LauParameter::removeGaussianConstraint() { if (this->clone()) { parent_->removeGaussianConstraint(); } else { gaussConstraint_ = kFALSE; this->updateClones(kFALSE); } } void LauParameter::blindParameter(const TString& blindingString, const Double_t width) { if (this->clone()) { parent_->blindParameter(blindingString,width); return; } if ( blinder_ != 0 ) { std::cerr << "WARNING in LauParameter::blindParameter : blinding has already been set up for this parameter" << std::endl; return; } blinder_ = new LauBlind(blindingString,width); for (map::iterator iter = clones_.begin(); iter != clones_.end(); ++iter) { LauParameter* clonePar = iter->first; if ( clonePar->blinder_ != 0 ) { std::cerr << "WARNING in LauParameter::blindParameter : blinding has already been set up for a clone of this parameter - it will be replaced!" << std::endl; delete clonePar->blinder_; clonePar->blinder_ = 0; } clonePar->blinder_ = new LauBlind(*blinder_); } } void LauParameter::updatePull() { if (this->clone()) { parent_->updatePull(); return; } // calculate the bias bias_ = value_ - genValue_; // if we have errors calculated then calculate // the pull using the best error available if ((bias_ > 0.0) && (negError_ > 1e-10)) { pull_ = bias_ / negError_; } else if ((bias_ < 0.0) && (posError_ > 1e-10)) { pull_ = bias_ / posError_; } else if (error_ > 1e-10) { pull_ = bias_ / error_; } else { pull_ = 0.0; } this->updateClones(kFALSE); } void LauParameter::checkRange(Double_t val, Double_t minVal, Double_t maxVal) { // first check that min is less than max (or they are the same - this is allowed) if (minVal > maxVal) { cerr<<"ERROR in LauParameter::checkRange : minValue: "< maxValue_) { minValue_ = maxValue_; cerr<<" : Setting both to "< maxVal)) { if (name_ != "") { cerr<<"ERROR in LauParameter::checkRange : value: "<clone()) { LauParameter* clonePar = parent_->createClone(constFactor); clonePar->name(this->name()); return clonePar; } // clone ourselves using the copy-constructor LauParameter* clonePar = new LauParameter(*this); Double_t newValue = clonePar->value() * constFactor; clonePar->value( newValue ); clonePar->wipeClones(); clonePar->clone(this); clones_.insert( std::make_pair( clonePar, constFactor ) ); return clonePar; } LauParameter* LauParameter::createClone(const TString& newName, Double_t constFactor) { // self message to create the clone LauParameter* clonePar = this->createClone(constFactor); // set the new name clonePar->name(newName); // and return return clonePar; } void LauParameter::updateClones(Bool_t justValue) { // if we don't have any clones then there's nothing to do if ( clones_.empty() ) { return; } // we have to set the values directly rather than using member functions because otherwise we'd get into an infinite loop if (justValue) { for (map::iterator iter = clones_.begin(); iter != clones_.end(); ++iter) { LauParameter* clonePar = iter->first; Double_t constFactor = iter->second; clonePar->value_ = constFactor*this->value(); } } else { for (map::iterator iter = clones_.begin(); iter != clones_.end(); ++iter) { LauParameter* clonePar = iter->first; Double_t constFactor = iter->second; clonePar->value_ = constFactor*this->value(); clonePar->error_ = constFactor*this->error(); clonePar->negError_ = constFactor*this->negError(); clonePar->posError_ = constFactor*this->posError(); clonePar->genValue_ = constFactor*this->genValue(); clonePar->initValue_ = constFactor*this->initValue(); clonePar->minValue_ = constFactor*this->minValue(); clonePar->maxValue_ = constFactor*this->maxValue(); clonePar->fixed_ = this->fixed(); clonePar->secondStage_ = this->secondStage(); clonePar->gaussConstraint_ = this->gaussConstraint(); clonePar->constraintMean_ = this->constraintMean(); clonePar->constraintWidth_ = this->constraintWidth(); clonePar->gcc_ = this->globalCorrelationCoeff(); clonePar->bias_ = this->bias(); clonePar->pull_ = this->pull(); } } } void LauParameter::randomiseValue() { this->randomiseValue(this->minValue(), this->maxValue()); } void LauParameter::randomiseValue(Double_t minVal, Double_t maxVal) { // if we're fixed then do nothing if (this->fixed()) { return; } // check supplied values are sensible if (maxVal < minVal) { cerr<<"ERROR in LauParameter::randomiseValue : Supplied maximum value smaller than minimum value."< this->maxValue()) { maxVal = this->maxValue(); } if (minVal < this->minValue()) { minVal = this->minValue(); } // use the zero-seed random number generator to get values that are // uniformly distributed over the given range Double_t randNo = LauRandom::zeroSeedRandom()->Rndm(); Double_t val = randNo*(maxVal - minVal) + minVal; this->initValue(val); } // ostream operator std::ostream& operator << (std::ostream& stream, const LauParameter& par) { stream << par.value(); return stream; } diff --git a/src/LauParametricStepFuncPdf.cc b/src/LauParametricStepFuncPdf.cc index 3c9e1ed..c5cd27f 100644 --- a/src/LauParametricStepFuncPdf.cc +++ b/src/LauParametricStepFuncPdf.cc @@ -1,231 +1,230 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauParametricStepFuncPdf.cc \brief File containing implementation of LauParametricStepFuncPdf class. */ /***************************************************************************** * Class based on RooFit/RooParametricStepFunction. * * Original copyright given below. * ***************************************************************************** * Authors: * * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu * * DK, David Kirkby, UC Irvine, dkirkby@uci.edu * * * * Copyright (c) 2000-2005, Regents of the University of California * * and Stanford University. All rights reserved. * * * * Redistribution and use in source and binary forms, * * with or without modification, are permitted according to the terms * * listed in LICENSE (http://roofit.sourceforge.net/license.txt) * *****************************************************************************/ #include #include using std::cout; using std::cerr; using std::endl; using std::vector; #include "TMath.h" #include "TSystem.h" #include "LauConstants.hh" #include "LauParametricStepFuncPdf.hh" -ClassImp(LauParametricStepFuncPdf) LauParametricStepFuncPdf::LauParametricStepFuncPdf(const TString& theVarName, const vector& params, const vector& limits, NormBin normalisationBin) : LauAbsPdf(theVarName, params, limits.front(), limits.back()), normBin_(normalisationBin), limits_(limits) { // Constructor for the PSF PDF. // // The parameters in params are the bin contents of all but the // normalisation bin, so has N_bins-1 entries. // The last argument specifies the limits of the bins and the range // as a whole, so has N_bins+1 entries. if (this->nParameters() != this->nBins()-1) { cerr<<"ERROR in LauParametricStepFuncPdf constructor: LauParametricStepFuncPdf requires N-1 parameters, where N is the number of bins."<Exit(EXIT_FAILURE); } // Cache the normalisation factor this->calcNorm(); } LauParametricStepFuncPdf::~LauParametricStepFuncPdf() { // Destructor } void LauParametricStepFuncPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Get our abscissa Double_t abscissa = abscissas[0]; // Get the parameters const vector& pars = this->getParameters(); // Calculate value Double_t value(0.0); const UInt_t numBins = this->nBins(); if ( this->normBin() == Last ) { // the last bin is our normalisation bin for ( UInt_t i(1); i<=numBins; ++i ) { if ( abscissa < limits_[i] ) { // in bin i-1 (starting with bin 0) if ( i < numBins ) { // not in last bin value = pars[i-1]->unblindValue(); break; } else { // in last bin Double_t sum(0.0); Double_t binSize(0.0); for ( UInt_t j(1); junblindValue() * binSize ); } binSize = limits_[numBins] - limits_[numBins-1]; value = ( 1.0 - sum ) / binSize; break; } } } } else { // the first bin is our normalisation bin for ( UInt_t i(1); i<=numBins; ++i ) { if ( abscissa < limits_[i] ) { // in bin i-1 (starting with bin 0) if ( i > 1 ) { // not in first bin value = pars[i-2]->unblindValue(); break; } else { // in first bin Double_t sum(0.0); Double_t binSize(0.0); for ( UInt_t j(2); j<=numBins; ++j ) { binSize = limits_[j] - limits_[j-1]; sum += ( pars[j-2]->unblindValue() * binSize ); } binSize = limits_[1] - limits_[0]; value = ( 1.0 - sum ) / binSize; break; } } } } this->setUnNormPDFVal(value); // if the parameters are floating then we // need to recalculate the normalisation if (!this->cachePDF() && !this->withinNormCalc() && !this->withinGeneration()) { this->calcNorm(); } } void LauParametricStepFuncPdf::calcNorm() { this->setNorm(1.0); } void LauParametricStepFuncPdf::calcPDFHeight( const LauKinematics* /*kinematics*/ ) { if (this->heightUpToDate()) { return; } // Get the parameters const vector& pars = this->getParameters(); // Find the PDF height Double_t height(0.0); Double_t value(0.0); const UInt_t numBins = this->nBins(); if ( this->normBin() == Last ) { // the last bin is our normalisation bin // Check through all the parameterised bins for ( UInt_t i(0); iunblindValue(); if ( height < value ) { height = value; } } // Check the last bin Double_t sum(0.0); Double_t binSize(0.0); for ( UInt_t j(1); junblindValue() * binSize ); } binSize = limits_[numBins] - limits_[numBins-1]; value = ( 1.0 - sum ) / binSize; if ( height < value ) { height = value; } } else { // the first bin is our normalisation bin // Check through all the parameterised bins for ( UInt_t i(1); iunblindValue(); if ( height < value ) { height = value; } } // Check the first bin Double_t sum(0.0); Double_t binSize(0.0); for ( UInt_t j(2); j<=numBins; ++j ) { binSize = limits_[j] - limits_[j-1]; sum += ( pars[j-2]->unblindValue() * binSize ); } binSize = limits_[1] - limits_[0]; value = ( 1.0 - sum ) / binSize; if ( height < value ) { height = value; } } this->setMaxHeight(height); } diff --git a/src/LauParticlePDG.cc b/src/LauParticlePDG.cc index c160f8a..18d22f2 100644 --- a/src/LauParticlePDG.cc +++ b/src/LauParticlePDG.cc @@ -1,149 +1,148 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauParticlePDG.cc \brief File containing implementation of LauParticlePDG class. */ #include using std::cerr; using std::endl; #include "TMath.h" #include "TParticlePDG.h" #include "LauConstants.hh" #include "LauDatabasePDG.hh" #include "LauParticlePDG.hh" -ClassImp(LauParticlePDG) LauParticlePDG::LauParticlePDG(const TParticlePDG* particle) : theParticle_(particle), antiParticle_(0), mass_(0.0), kaon_(kFALSE), pion_(kFALSE), ks_(kFALSE), pi0_(kFALSE), D_(kFALSE), B_(kFALSE) { // store the mass and kaon? and pion? if ( TMath::Abs(this->code()) == 211 ) { // charged pion mass_ = LauConstants::mPi; pion_ = kTRUE; } else if ( this->code() == 111 ) { // neutral pion mass_ = LauConstants::mPi0; pion_ = kTRUE; pi0_ = kTRUE; } else if ( TMath::Abs(this->code()) == 321 ) { // charged kaon mass_ = LauConstants::mK; kaon_ = kTRUE; } else if ( this->code() == 130 || this->code() == 310 || TMath::Abs(this->code()) == 311 ) { // neutral kaon mass_ = LauConstants::mK0; kaon_ = kTRUE; if ( this->code() == 310 ) { ks_ = kTRUE; } } else if ( this->code() == 221 ) { // eta mass_ = LauConstants::mEta; } else if ( this->code() == 331 ) { // eta' mass_ = LauConstants::mEtaPrime; } else if ( TMath::Abs(this->code()) == 411 ) { // charged D mass_ = LauConstants::mD; D_ = kTRUE; } else if ( TMath::Abs(this->code()) == 421 ) { // neutral D mass_ = LauConstants::mD0; D_ = kTRUE; } else if ( TMath::Abs(this->code()) == 431) { // charged D_s mass_ = LauConstants::mDs; D_ = kTRUE; } else if ( TMath::Abs(this->code()) == 511 ) { // neutral B mass_ = LauConstants::mB0; B_ = kTRUE; } else if ( TMath::Abs(this->code()) == 521 ) { // charged B mass_ = LauConstants::mB; B_ = kTRUE; } else if ( TMath::Abs(this->code()) == 531 ) { // neutral B_s mass_ = LauConstants::mBs0; B_ = kTRUE; } } LauParticlePDG::~LauParticlePDG() { } Int_t LauParticlePDG::code() const { if (theParticle_ == 0) { cerr<<"ERROR in LauParticlePDG::code : Null pointer."<PdgCode(); } Int_t LauParticlePDG::conjugateCode() const { if (antiParticle_ == 0) { cerr<<"ERROR in LauParticlePDG::conjugateCode : Null pointer."<code(); } Int_t LauParticlePDG::charge() const { if (theParticle_ == 0) { cerr<<"ERROR in LauParticlePDG::charge : Null pointer."<Charge(); Int_t theCharge = static_cast(chargeTimesThree/3.0); return theCharge; } TString LauParticlePDG::string() const { if (theParticle_ == 0) { cerr<<"ERROR in LauParticlePDG::string : Null pointer."<GetName(); } TString LauParticlePDG::stringAlphaNum() const { TString name = this->string(); name.ReplaceAll("*","st"); name.ReplaceAll("_",""); name.ReplaceAll("(",""); name.ReplaceAll(")",""); name.ReplaceAll("+","p"); name.ReplaceAll("-","m"); return name; } diff --git a/src/LauPolNR.cc b/src/LauPolNR.cc index 61b9088..ea4453a 100644 --- a/src/LauPolNR.cc +++ b/src/LauPolNR.cc @@ -1,96 +1,95 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauPolNR.cc \brief File containing implementation of LauPolNR class. */ #include #include "TMath.h" #include "LauPolNR.hh" #include "LauDaughters.hh" -ClassImp(LauPolNR) LauPolNR::LauPolNR(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), omega_(0.0), order_(0) { } LauPolNR::~LauPolNR() { } void LauPolNR::initialise() { const LauDaughters* daughters = this->getDaughters(); Int_t resPairAmpInt = this->getPairInt(); if ( daughters->gotSymmetricalDP() && resPairAmpInt != 3 ) { std::cerr << "WARNING in LauPolNR::initialise : Dalitz plot is symmetric - this lineshape is not appropriate." << std::endl; } // Make the spin term purely the Legendre polynomial of the cos(helicity angle) this->setSpinType( LauAbsResonance::Legendre ); Double_t omega = 0.5*(daughters->getMassParent()+(1.0/3.0)*(daughters->getMassDaug1()+daughters->getMassDaug2()+daughters->getMassDaug3())); this->setOmega( omega ); TString name = this->getResonanceName(); if (name.EndsWith("0",TString::kExact)){ order_ = 0; } else if (name.EndsWith("1",TString::kExact)){ order_ = 1; } else if (name.EndsWith("2",TString::kExact)){ order_ = 2; } else if (name.EndsWith("3",TString::kExact)){ order_ = 3; } else{ std::cerr << "ERROR in LauPolNR::initialise : Resonance order unknown (known orders : 0, 1, 2 and 3)" << std::endl; std::cerr << " : Defaulting to 0." << std::endl; } } LauComplex LauPolNR::resAmp(Double_t mass, Double_t spinTerm) { Double_t magnitude( spinTerm ); Double_t massDiff = mass - omega_; for ( UInt_t i(0); i < order_; ++i ) { magnitude *= massDiff; } LauComplex resAmplitude(magnitude, 0.0); return resAmplitude; } diff --git a/src/LauPolarFormFactorNR.cc b/src/LauPolarFormFactorNR.cc index 682806a..932209f 100644 --- a/src/LauPolarFormFactorNR.cc +++ b/src/LauPolarFormFactorNR.cc @@ -1,148 +1,147 @@ /* Copyright 2018 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauPolarFormFactorNR.cc \brief File containing implementation of LauPolarFormFactorNR class. */ #include #include "TMath.h" #include "LauConstants.hh" #include "LauPolarFormFactorNR.hh" #include "LauDaughters.hh" #include "LauParameter.hh" #include "LauResonanceInfo.hh" -ClassImp(LauPolarFormFactorNR) LauPolarFormFactorNR::LauPolarFormFactorNR(LauResonanceInfo* resInfo, const LauAbsResonance::LauResonanceModel resType, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), lambda_(0), model_(resType) { TString parName = this->getSanitisedName(); parName += "_lambda"; lambda_ = resInfo->getExtraParameter( parName ); if ( lambda_ == 0 ) { lambda_ = new LauParameter( parName, 1.0, 0.0, 10.0, kTRUE ); lambda_->secondStage(kTRUE); resInfo->addExtraParameter( lambda_ ); } } LauPolarFormFactorNR::~LauPolarFormFactorNR() { } void LauPolarFormFactorNR::initialise() { const LauDaughters* daughters = this->getDaughters(); Int_t resPairAmpInt = this->getPairInt(); if ( daughters->gotSymmetricalDP() && resPairAmpInt != 3 ) { std::cerr << "WARNING in LauPolarFormFactorNR::initialise : Dalitz plot is symmetric - this lineshape is not appropriate." << std::endl; } if ( model_ != LauAbsResonance::PolarFFNR) { std::cerr << "WARNING in LauPolarFormFactorNR::initialise : Unknown model requested, defaulting to Polar Form Factor." << std::endl; model_ = LauAbsResonance::PolarFFNR; } } LauComplex LauPolarFormFactorNR::resAmp(Double_t mass, Double_t) { Double_t magnitude(1.0); Double_t lambda = this->getLambda(); magnitude = 1.0/(1.0 + mass*mass /(lambda*lambda)); LauComplex resAmplitude(magnitude, 0.0); return resAmplitude; } const std::vector& LauPolarFormFactorNR::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixLambda() ) { this->addFloatingParameter( lambda_ ); } return this->getParameters(); } void LauPolarFormFactorNR::setResonanceParameter(const TString& name, const Double_t value) { // Set various parameters for the lineshape if (name == "lambda") { this->setLambda(value); std::cout << "INFO in LauPolarFormFactorNR::setResonanceParameter : Setting parameter lambda = " << this->getLambda() << std::endl; } else { std::cerr << "WARNING in LauPolarFormFactorNR::setResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } void LauPolarFormFactorNR::floatResonanceParameter(const TString& name) { if (name == "lambda") { if ( lambda_->fixed() ) { lambda_->fixed( kFALSE ); this->addFloatingParameter( lambda_ ); } else { std::cerr << "WARNING in LauPolarFormFactorNR::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else { std::cerr << "WARNING in LauPolarFormFactorNR::fixResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } LauParameter* LauPolarFormFactorNR::getResonanceParameter(const TString& name) { if (name == "lambda") { return lambda_; } else { std::cerr << "WARNING in LauPolarFormFactorNR::getResonanceParameter: Parameter name not reconised." << std::endl; return 0; } } void LauPolarFormFactorNR::setLambda(const Double_t lambda) { lambda_->value( lambda ); lambda_->genValue( lambda ); lambda_->initValue( lambda ); } diff --git a/src/LauPolarFormFactorSymNR.cc b/src/LauPolarFormFactorSymNR.cc index ea88f7a..0e4dc6e 100644 --- a/src/LauPolarFormFactorSymNR.cc +++ b/src/LauPolarFormFactorSymNR.cc @@ -1,185 +1,184 @@ /* Copyright 2018 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauPolarFormFactorSymNR.cc \brief File containing implementation of LauPolarFormFactorSymNR class. */ #include #include "TMath.h" #include "LauConstants.hh" #include "LauPolarFormFactorSymNR.hh" #include "LauDaughters.hh" #include "LauParameter.hh" #include "LauResonanceInfo.hh" -ClassImp(LauPolarFormFactorSymNR) LauPolarFormFactorSymNR::LauPolarFormFactorSymNR(LauResonanceInfo* resInfo, const LauAbsResonance::LauResonanceModel resType, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), lambda_(0), model_(resType) { TString parName = this->getSanitisedName(); parName += "_lambda"; lambda_ = resInfo->getExtraParameter( parName ); if ( lambda_ == 0 ) { lambda_ = new LauParameter( parName, 1.0, 0.0, 10.0, kTRUE ); lambda_->secondStage(kTRUE); resInfo->addExtraParameter( lambda_ ); } } LauPolarFormFactorSymNR::~LauPolarFormFactorSymNR() { } void LauPolarFormFactorSymNR::initialise() { const LauDaughters* daughters = this->getDaughters(); if ( ! daughters->gotSymmetricalDP() ) { std::cerr << "WARNING in LauPolarFormFactorSymNR::initialise : Dalitz plot is symmetric - this lineshape is not appropriate." << std::endl; } Int_t resPairAmpInt = this->getPairInt(); if ( resPairAmpInt == 3 ) { std::cerr << "WARNING in LauPolarFormFactorSymNR::initialise : This lineshape is intended to be on the symmetrised axes of the DP." << std::endl; } if ( (model_ != LauAbsResonance::PolarFFSymNR) && (model_ != LauAbsResonance::PolarFFSymNRNoInter)) { std::cerr << "WARNING in LauPolarFormFactorSymNR::initialise : Unknown model requested, defaulting to Polar Form Factor." << std::endl; model_ = LauAbsResonance::PolarFFSymNR; } if ( (model_ != LauAbsResonance::PolarFFSymNR) && (this->getSpin() != 0) ) { std::cerr << "WARNING in LauPolarFormFactorSymNR::initialise : Non-zero spin will be ignored for this model - perhaps you should use LauAbsResonance::PolarFFSymNRNoInter instead" << std::endl; } // NB we do not need to call setSpinType(LauAbsResonance::Legendre) here (as is done in LauPolarFormFactorNR) since override the amplitude method and explicitly use calcLegendrePoly } LauComplex LauPolarFormFactorSymNR::resAmp(Double_t mass, Double_t spinTerm) { std::cerr << "ERROR in LauPolarFormFactorSymNR : This method should never be called." << std::endl; std::cerr << " : Returning zero amplitude for mass = " << mass << " and spinTerm = " << spinTerm << "." << std::endl; return LauComplex(0.0, 0.0); } LauComplex LauPolarFormFactorSymNR::amplitude(const LauKinematics* kinematics) { // This function returns the complex dynamical amplitude for a Polar Form Factor Non-Resonant distribution // Calculate for symmetric DPs, e.g. 3pi or 3K, by using shapeNo = 1 or 2 // Have s<->t symmetry already done in Dynamics flip function. // For Kpipi or similar plots, one can use the separate terms // and consider them as two separate components with their own mag and phase. // For this shapeNo = 3 and shapeNo = 4 need to be used to create the two // individual amplitudes (with the same value of lambda). // Calculate Mandelstam variables. // s = m_13^2, t = m_23^2 const Double_t s = kinematics->getm13Sq(); const Double_t t = kinematics->getm23Sq(); Double_t magnitude(1.0); const Double_t lambda = this->getLambda(); if ( model_ == LauAbsResonance::PolarFFSymNR ) { magnitude = 1.0/(1.0 + s /(lambda*lambda)) + 1.0/(1.0 + t /(lambda*lambda)); } else if ( model_ == LauAbsResonance::PolarFFSymNRNoInter ) { magnitude = (s <= t) ? 1.0/(1.0 + s /(lambda*lambda)) : 1.0/(1.0 + t /(lambda*lambda)); } LauComplex resAmplitude(magnitude, 0.0); return resAmplitude; } const std::vector& LauPolarFormFactorSymNR::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixLambda() ) { this->addFloatingParameter( lambda_ ); } return this->getParameters(); } void LauPolarFormFactorSymNR::setResonanceParameter(const TString& name, const Double_t value) { // Set various parameters for the lineshape if (name == "lambda") { this->setLambda(value); std::cout << "INFO in LauPolarFormFactorSymNR::setResonanceParameter : Setting parameter lambda = " << this->getLambda() << std::endl; } else { std::cerr << "WARNING in LauPolarFormFactorSymNR::setResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } void LauPolarFormFactorSymNR::floatResonanceParameter(const TString& name) { if (name == "lambda") { if ( lambda_->fixed() ) { lambda_->fixed( kFALSE ); this->addFloatingParameter( lambda_ ); } else { std::cerr << "WARNING in LauPolarFormFactorSymNR::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else { std::cerr << "WARNING in LauPolarFormFactorSymNR::fixResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } LauParameter* LauPolarFormFactorSymNR::getResonanceParameter(const TString& name) { if (name == "lambda") { return lambda_; } else { std::cerr << "WARNING in LauPolarFormFactorSymNR::getResonanceParameter: Parameter name not reconised." << std::endl; return 0; } } void LauPolarFormFactorSymNR::setLambda(const Double_t lambda) { lambda_->value( lambda ); lambda_->genValue( lambda ); lambda_->initValue( lambda ); } diff --git a/src/LauPolarGammaCPCoeffSet.cc b/src/LauPolarGammaCPCoeffSet.cc index edfd294..19d3e91 100644 --- a/src/LauPolarGammaCPCoeffSet.cc +++ b/src/LauPolarGammaCPCoeffSet.cc @@ -1,768 +1,767 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauPolarGammaCPCoeffSet.cc \brief File containing implementation of LauPolarGammaCPCoeffSet class. */ #include #include #include #include "TMath.h" #include "TRandom.h" #include "LauPolarGammaCPCoeffSet.hh" #include "LauComplex.hh" #include "LauConstants.hh" #include "LauParameter.hh" #include "LauPrint.hh" LauParameter* LauPolarGammaCPCoeffSet::gammaGlobal_ = 0; LauParameter* LauPolarGammaCPCoeffSet::rDGlobal_ = 0; LauParameter* LauPolarGammaCPCoeffSet::deltaDGlobal_ = 0; -ClassImp(LauPolarGammaCPCoeffSet) LauPolarGammaCPCoeffSet::LauPolarGammaCPCoeffSet(const TString& compName, const DecayType decayType, const Double_t x, const Double_t y, const Double_t rB, const Double_t deltaB, const Double_t gamma, const Double_t rD, const Double_t deltaD, const Bool_t xFixed, const Bool_t yFixed, const Bool_t rBFixed, const Bool_t deltaBFixed, const Bool_t gammaFixed, const Bool_t rDFixed, const Bool_t deltaDFixed, const Bool_t rBSecondStage, const Bool_t deltaBSecondStage, const Bool_t gammaSecondStage, const Bool_t rDSecondStage, const Bool_t deltaDSecondStage, const Bool_t useGlobalGamma, const Bool_t useGlobalADSPars) : LauAbsCoeffSet(compName), decayType_(decayType), x_(0), y_(0), rB_(0), deltaB_(0), gamma_(0), rD_(0), deltaD_(0), useGlobalGamma_(useGlobalGamma), useGlobalADSPars_(useGlobalADSPars), nonCPPart_(x,y), cpPart_(0.0,0.0), cpAntiPart_(0.0,0.0), particleCoeff_(0.0,0.0), antiparticleCoeff_(0.0,0.0), acp_("ACP", 0.0, -1.0, 1.0) { // All of the possible D decay types need these two parameters x_ = new LauParameter("X", x, minRealImagPart_, maxRealImagPart_, xFixed); y_ = new LauParameter("Y", y, minRealImagPart_, maxRealImagPart_, yFixed); // if we're using a global gamma, create it if it doesn't already exist then set gamma_ to point to it // otherwise create our individual copy of gamma if (useGlobalGamma_) { if (!gammaGlobal_) { gammaGlobal_ = new LauParameter("gamma", gamma, minPhase_, maxPhase_, gammaFixed); gamma_ = gammaGlobal_; } else { gamma_ = gammaGlobal_->createClone(); } } else { gamma_ = new LauParameter("gamma", gamma, minPhase_, maxPhase_, gammaFixed); } if (gammaSecondStage && !gammaFixed) { gamma_->secondStage(kTRUE); gamma_->initValue(0.0); } // which of the other parameter we need depends on the D-decay type if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == GLW_CPOdd || decayType_ == GLW_CPEven ) { rB_ = new LauParameter("rB", rB, minMagnitude_, maxMagnitude_, rBFixed); deltaB_ = new LauParameter("deltaB", deltaB, minPhase_, maxPhase_, deltaBFixed); if (rBSecondStage && !rBFixed) { rB_->secondStage(kTRUE); rB_->initValue(0.0); } if (deltaBSecondStage && !deltaBFixed) { deltaB_->secondStage(kTRUE); deltaB_->initValue(0.0); } } if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == ADS_Favoured_btouOnly ) { if (useGlobalADSPars_) { if ( !rDGlobal_ ) { rDGlobal_ = new LauParameter("rD", rD, minMagnitude_, maxMagnitude_, rDFixed); deltaDGlobal_ = new LauParameter("deltaD", deltaD, minPhase_, maxPhase_, deltaDFixed); rD_ = rDGlobal_; deltaD_ = deltaDGlobal_; } else { rD_ = rDGlobal_->createClone(); deltaD_ = deltaDGlobal_->createClone(); } } else { rD_ = new LauParameter("rD", rD, minMagnitude_, maxMagnitude_, rDFixed); deltaD_ = new LauParameter("deltaD", deltaD, minPhase_, maxPhase_, deltaDFixed); } if (rDSecondStage && !rDFixed) { rD_->secondStage(kTRUE); rD_->initValue(0.0); } if (deltaDSecondStage && !deltaDFixed) { deltaD_->secondStage(kTRUE); deltaD_->initValue(0.0); } } } LauPolarGammaCPCoeffSet::LauPolarGammaCPCoeffSet(const LauPolarGammaCPCoeffSet& rhs, CloneOption cloneOption, Double_t constFactor) : LauAbsCoeffSet(rhs.name()), decayType_( rhs.decayType_ ), x_(0), y_(0), rB_(0), deltaB_(0), gamma_(0), rD_(0), deltaD_(0), useGlobalGamma_( rhs.useGlobalGamma_ ), useGlobalADSPars_( rhs.useGlobalADSPars_ ), nonCPPart_( rhs.nonCPPart_ ), cpPart_( rhs.cpPart_ ), cpAntiPart_( rhs.cpAntiPart_ ), particleCoeff_( rhs.particleCoeff_ ), antiparticleCoeff_( rhs.antiparticleCoeff_ ), acp_( rhs.acp_ ) { if ( cloneOption == All || cloneOption == TieRealPart ) { x_ = rhs.x_->createClone(constFactor); } else { x_ = new LauParameter("X", rhs.x_->value(), minRealImagPart_, maxRealImagPart_, rhs.x_->fixed()); if ( rhs.x_->blind() ) { const LauBlind* blinder = rhs.x_->blinder(); x_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TieImagPart ) { y_ = rhs.y_->createClone(constFactor); } else { y_ = new LauParameter("Y", rhs.y_->value(), minRealImagPart_, maxRealImagPart_, rhs.y_->fixed()); if ( rhs.y_->blind() ) { const LauBlind* blinder = rhs.y_->blinder(); y_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TieCPPars ) { gamma_ = rhs.gamma_->createClone(constFactor); if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == GLW_CPOdd || decayType_ == GLW_CPEven ) { rB_ = rhs.rB_->createClone(constFactor); deltaB_ = rhs.deltaB_->createClone(constFactor); } if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == ADS_Favoured_btouOnly ) { rD_ = rhs.rD_->createClone(constFactor); deltaD_ = rhs.deltaD_->createClone(constFactor); } } else { if (useGlobalGamma_) { gamma_ = gammaGlobal_->createClone(); } else { gamma_ = new LauParameter("gamma", rhs.gamma_->value(), minPhase_, maxPhase_, rhs.gamma_->fixed()); if ( rhs.gamma_->blind() ) { const LauBlind* blinder = rhs.gamma_->blinder(); gamma_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } if ( rhs.gamma_->secondStage() && !rhs.gamma_->fixed() ) { gamma_->secondStage(kTRUE); gamma_->initValue(0.0); } } if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == GLW_CPOdd || decayType_ == GLW_CPEven ) { rB_ = new LauParameter("rB", rhs.rB_->value(), minMagnitude_, maxMagnitude_, rhs.rB_->fixed()); if ( rhs.rB_->blind() ) { const LauBlind* blinder = rhs.rB_->blinder(); rB_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } deltaB_ = new LauParameter("deltaB", rhs.deltaB_->value(), minPhase_, maxPhase_, rhs.deltaB_->fixed()); if ( rhs.deltaB_->blind() ) { const LauBlind* blinder = rhs.deltaB_->blinder(); deltaB_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } if ( rhs.rB_->secondStage() && !rhs.rB_->fixed() ) { rB_->secondStage(kTRUE); rB_->initValue(0.0); } if ( rhs.deltaB_->secondStage() && !rhs.deltaB_->fixed() ) { deltaB_->secondStage(kTRUE); deltaB_->initValue(0.0); } } if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == ADS_Favoured_btouOnly ) { if ( useGlobalADSPars_ ) { rD_ = rDGlobal_->createClone(); deltaD_ = deltaDGlobal_->createClone(); } else { rD_ = new LauParameter("rD", rhs.rD_->value(), minMagnitude_, maxMagnitude_, rhs.rD_->fixed()); if ( rhs.rD_->blind() ) { const LauBlind* blinder = rhs.rD_->blinder(); rD_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } deltaD_ = new LauParameter("deltaD", rhs.deltaD_->value(), minPhase_, maxPhase_, rhs.deltaD_->fixed()); if ( rhs.deltaD_->blind() ) { const LauBlind* blinder = rhs.deltaD_->blinder(); deltaD_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } if ( rhs.rD_->secondStage() && !rhs.rD_->fixed() ) { rD_->secondStage(kTRUE); rD_->initValue(0.0); } if ( rhs.deltaD_->secondStage() && !rhs.deltaD_->fixed() ) { deltaD_->secondStage(kTRUE); deltaD_->initValue(0.0); } } } } } void LauPolarGammaCPCoeffSet::adjustName(LauParameter* par, const TString& oldBaseName) { if ( ( par == gamma_ && useGlobalGamma_ ) || ( par == rD_ && useGlobalADSPars_ ) || ( par == deltaD_ && useGlobalADSPars_ ) ) { // for global parameters we do not want to adjust their names return; } else { LauAbsCoeffSet::adjustName(par,oldBaseName); } } std::vector LauPolarGammaCPCoeffSet::getParameters() { std::vector pars; pars.push_back(x_); pars.push_back(y_); if ( !gamma_->fixed() ) { pars.push_back(gamma_); } if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == GLW_CPOdd || decayType_ == GLW_CPEven ) { if ( !rB_->fixed() ) { pars.push_back(rB_); } if ( !deltaB_->fixed() ) { pars.push_back(deltaB_); } } if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == ADS_Favoured_btouOnly ) { if ( !rD_->fixed() ) { pars.push_back(rD_); } if ( !deltaD_->fixed() ) { pars.push_back(deltaD_); } } return pars; } void LauPolarGammaCPCoeffSet::printParValues() const { std::cout<<"INFO in LauPolarGammaCPCoeffSet::printParValues : Component \""<name()<<"\" has "; std::cout<<"x = "<value()<<",\t"; std::cout<<"y = "<value()<<",\t"; if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == GLW_CPOdd || decayType_ == GLW_CPEven ) { std::cout<<"rB = "<value()<<",\t"; std::cout<<"deltaB = "<value()<<",\t"; } if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == ADS_Favoured_btouOnly ) { std::cout<<"rD = "<value()<<",\t"; std::cout<<"deltaD = "<value()<<",\t"; } std::cout<<"gamma = "<value()<<"."<name(); resName = resName.ReplaceAll("_", "\\_"); stream<value()); stream<<" \\pm "; print.printFormat(stream, x_->error()); stream<<"$ & $"; print.printFormat(stream, y_->value()); stream<<" \\pm "; print.printFormat(stream, y_->error()); stream<<"$ & $"; if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == GLW_CPOdd || decayType_ == GLW_CPEven ) { print.printFormat(stream, rB_->value()); stream<<" \\pm "; print.printFormat(stream, rB_->error()); stream<<"$ & $"; print.printFormat(stream, deltaB_->value()); stream<<" \\pm "; print.printFormat(stream, deltaB_->error()); stream<<"$ & $"; } if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == ADS_Favoured_btouOnly ) { print.printFormat(stream, rD_->value()); stream<<" \\pm "; print.printFormat(stream, rD_->error()); stream<<"$ & $"; print.printFormat(stream, deltaD_->value()); stream<<" \\pm "; print.printFormat(stream, deltaD_->error()); stream<<"$ & $"; } print.printFormat(stream, gamma_->value()); stream<<" \\pm "; print.printFormat(stream, gamma_->error()); stream<<"$ \\\\"<fixed() == kFALSE) { // Choose a value for "X" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; x_->initValue(value); x_->value(value); } if (y_->fixed() == kFALSE) { // Choose a value for "Y" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; y_->initValue(value); y_->value(value); } if (gamma_->fixed() == kFALSE && gamma_->secondStage() == kFALSE) { // Choose a value for "gamma" between +-pi Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*LauConstants::twoPi - LauConstants::pi; gamma_->initValue(value); gamma_->value(value); } if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == GLW_CPOdd || decayType_ == GLW_CPEven ) { if (rB_->fixed() == kFALSE && rB_->secondStage() == kFALSE) { // Choose a value for "rB" between 0.0 and 2.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*2.0; rB_->initValue(value); rB_->value(value); } if (deltaB_->fixed() == kFALSE && deltaB_->secondStage() == kFALSE) { // Choose a value for "deltaB" between +- pi Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*LauConstants::twoPi - LauConstants::pi; deltaB_->initValue(value); deltaB_->value(value); } } if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == ADS_Favoured_btouOnly ) { if (rD_->fixed() == kFALSE && rD_->secondStage() == kFALSE) { // Choose a value for "rD" between 0.0 and 2.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*2.0; rD_->initValue(value); rD_->value(value); } if (deltaD_->fixed() == kFALSE && deltaD_->secondStage() == kFALSE) { // Choose a value for "deltaD" between +- pi Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*LauConstants::twoPi - LauConstants::pi; deltaD_->initValue(value); deltaD_->value(value); } } } void LauPolarGammaCPCoeffSet::finaliseValues() { // retrieve the current values from the parameters Double_t gammaVal = gamma_->value(); Double_t rBVal = 0.0; Double_t deltaBVal = 0.0; Double_t genDeltaB = 0.0; Double_t rDVal = 0.0; Double_t deltaDVal = 0.0; Double_t genDeltaD = 0.0; if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == GLW_CPOdd || decayType_ == GLW_CPEven ) { rBVal = rB_->value(); deltaBVal = deltaB_->value(); genDeltaB = deltaB_->genValue(); } if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == ADS_Favoured_btouOnly ) { rDVal = rD_->value(); deltaDVal = deltaD_->value(); genDeltaD = deltaD_->genValue(); } // Check whether we have a negative magnitude. // If so make it positive and add pi to the phases. if (rBVal < 0.0) { rBVal *= -1.0; deltaBVal += LauConstants::pi; } if (rDVal < 0.0) { rDVal *= -1.0; deltaDVal += LauConstants::pi; } // Check now whether the phases lie in the right range (-pi to pi). Bool_t deltaBWithinRange(kFALSE); Bool_t deltaDWithinRange(kFALSE); Bool_t gammaWithinRange(kFALSE); while ( deltaBWithinRange == kFALSE ) { if (deltaBVal > -LauConstants::pi && deltaBVal <= LauConstants::pi) { deltaBWithinRange = kTRUE; } else { // Not within the specified range if (deltaBVal > LauConstants::pi) { deltaBVal -= LauConstants::twoPi; } else if (deltaBVal <= -LauConstants::pi) { deltaBVal += LauConstants::twoPi; } } } while ( deltaDWithinRange == kFALSE ) { if (deltaDVal > -LauConstants::pi && deltaDVal <= LauConstants::pi) { deltaDWithinRange = kTRUE; } else { // Not within the specified range if (deltaDVal > LauConstants::pi) { deltaDVal -= LauConstants::twoPi; } else if (deltaDVal <= -LauConstants::pi) { deltaDVal += LauConstants::twoPi; } } } while ( gammaWithinRange == kFALSE ) { if (gammaVal > -LauConstants::pi && gammaVal <= LauConstants::pi) { gammaWithinRange = kTRUE; } else { // Not within the specified range if (gammaVal > LauConstants::pi) { gammaVal -= LauConstants::twoPi; } else if (gammaVal <= -LauConstants::pi) { gammaVal += LauConstants::twoPi; } } } // To resolve the two-fold ambiguity in gamma and deltaB we require gamma to be in the range 0-pi if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == GLW_CPOdd || decayType_ == GLW_CPEven ) { if (gammaVal < 0.0) { if (deltaBVal <= 0.0) { gammaVal += LauConstants::pi; deltaBVal += LauConstants::pi; } else { gammaVal += LauConstants::pi; deltaBVal -= LauConstants::pi; } } } // A further problem can occur when the generated phase is close to -pi or pi. // The phase can wrap over to the other end of the scale - // this leads to artificially large pulls so we wrap it back. Double_t diff = deltaBVal - genDeltaB; if (diff > LauConstants::pi) { deltaBVal -= LauConstants::twoPi; } else if (diff < -LauConstants::pi) { deltaBVal += LauConstants::twoPi; } diff = deltaDVal - genDeltaD; if (diff > LauConstants::pi) { deltaDVal -= LauConstants::twoPi; } else if (diff < -LauConstants::pi) { deltaDVal += LauConstants::twoPi; } // finally store the new values in the parameters // and update the pulls gamma_->value(gammaVal); gamma_->updatePull(); if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == GLW_CPOdd || decayType_ == GLW_CPEven ) { rB_->value(rBVal); rB_->updatePull(); deltaB_->value(deltaBVal); deltaB_->updatePull(); } if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == ADS_Favoured_btouOnly ) { rD_->value(rDVal); rD_->updatePull(); deltaD_->value(deltaDVal); deltaD_->updatePull(); } } const LauComplex& LauPolarGammaCPCoeffSet::particleCoeff() { this->updateAmplitudes(); return particleCoeff_; } const LauComplex& LauPolarGammaCPCoeffSet::antiparticleCoeff() { this->updateAmplitudes(); return antiparticleCoeff_; } void LauPolarGammaCPCoeffSet::updateAmplitudes() { nonCPPart_.setRealImagPart( x_->unblindValue(), y_->unblindValue() ); const Double_t gammaVal = gamma_->unblindValue(); switch ( decayType_ ) { case GLW_CPOdd : { const Double_t rBVal = rB_->unblindValue(); const Double_t deltaBVal = deltaB_->unblindValue(); cpPart_.setRealImagPart( 1.0 - rBVal*TMath::Cos(deltaBVal + gammaVal), -rBVal*TMath::Sin(deltaBVal + gammaVal) ); cpAntiPart_.setRealImagPart( 1.0 - rBVal*TMath::Cos(deltaBVal - gammaVal), -rBVal*TMath::Sin(deltaBVal - gammaVal) ); break; } case GLW_CPEven : { const Double_t rBVal = rB_->unblindValue(); const Double_t deltaBVal = deltaB_->unblindValue(); cpPart_.setRealImagPart( 1.0 + rBVal*TMath::Cos(deltaBVal + gammaVal), rBVal*TMath::Sin(deltaBVal + gammaVal) ); cpAntiPart_.setRealImagPart( 1.0 + rBVal*TMath::Cos(deltaBVal - gammaVal), rBVal*TMath::Sin(deltaBVal - gammaVal) ); break; } case ADS_Favoured : { const Double_t rBVal = rB_->unblindValue(); const Double_t deltaBVal = deltaB_->unblindValue(); const Double_t rDVal = rD_->unblindValue(); const Double_t deltaDVal = deltaD_->unblindValue(); cpPart_.setRealImagPart( 1.0 + rBVal*rDVal*TMath::Cos(deltaBVal - deltaDVal + gammaVal), rBVal*rDVal*TMath::Sin(deltaBVal - deltaDVal + gammaVal) ); cpAntiPart_.setRealImagPart( 1.0 + rBVal*rDVal*TMath::Cos(deltaBVal - deltaDVal - gammaVal), rBVal*rDVal*TMath::Sin(deltaBVal - deltaDVal - gammaVal) ); break; } case ADS_Suppressed : { const Double_t rBVal = rB_->unblindValue(); const Double_t deltaBVal = deltaB_->unblindValue(); const Double_t rDVal = rD_->unblindValue(); const Double_t deltaDVal = deltaD_->unblindValue(); cpPart_.setRealImagPart( rDVal*TMath::Cos(-deltaDVal) + rBVal*TMath::Cos(deltaBVal + gammaVal), rDVal*TMath::Sin(-deltaDVal) + rBVal*TMath::Sin(deltaBVal + gammaVal) ); cpAntiPart_.setRealImagPart( rDVal*TMath::Cos(-deltaDVal) + rBVal*TMath::Cos(deltaBVal - gammaVal), rDVal*TMath::Sin(-deltaDVal) + rBVal*TMath::Sin(deltaBVal - gammaVal) ); break; } case GLW_CPOdd_btouOnly : nonCPPart_.rescale(-1.0); cpPart_.setRealImagPart( 1.0 * TMath::Cos( gammaVal ), 1.0 * TMath::Sin( gammaVal ) ); cpAntiPart_.setRealImagPart( 1.0 * TMath::Cos( -gammaVal ), 1.0 * TMath::Sin( -gammaVal ) ); break; case GLW_CPEven_btouOnly : cpPart_.setRealImagPart( 1.0 * TMath::Cos( gammaVal ), 1.0 * TMath::Sin( gammaVal ) ); cpAntiPart_.setRealImagPart( 1.0 * TMath::Cos( -gammaVal ), 1.0 * TMath::Sin( -gammaVal ) ); break; case ADS_Favoured_btouOnly : { const Double_t rDVal = rD_->unblindValue(); const Double_t deltaDVal = deltaD_->unblindValue(); cpPart_.setRealImagPart( rDVal * TMath::Cos( -deltaDVal + gammaVal ), rDVal * TMath::Sin( -deltaDVal + gammaVal ) ); cpAntiPart_.setRealImagPart( rDVal * TMath::Cos( -deltaDVal - gammaVal ), rDVal * TMath::Sin( -deltaDVal - gammaVal ) ); break; } case ADS_Suppressed_btouOnly : cpPart_.setRealImagPart( 1.0 * TMath::Cos( gammaVal ), 1.0 * TMath::Sin( gammaVal ) ); cpAntiPart_.setRealImagPart( 1.0 * TMath::Cos( -gammaVal ), 1.0 * TMath::Sin( -gammaVal ) ); break; } particleCoeff_ = nonCPPart_ * cpPart_; antiparticleCoeff_ = nonCPPart_ * cpAntiPart_; } void LauPolarGammaCPCoeffSet::setCoeffValues( const LauComplex&, const LauComplex&, Bool_t ) { std::cerr << "ERROR in LauPolarGammaCPCoeffSet::setCoeffValues : Method not supported by this class - too many parameters" << std::endl; } LauParameter LauPolarGammaCPCoeffSet::acp() { // set the name TString parName(this->baseName()); parName += "_ACP"; acp_.name(parName); // work out the ACP value LauComplex nonCPPart( x_->value(), y_->value() ); LauComplex cpPart; LauComplex cpAntiPart; const Double_t gammaVal = gamma_->value(); switch ( decayType_ ) { case GLW_CPOdd : { const Double_t rBVal = rB_->value(); const Double_t deltaBVal = deltaB_->value(); cpPart.setRealImagPart( 1.0 - rBVal*TMath::Cos(deltaBVal + gammaVal), -rBVal*TMath::Sin(deltaBVal + gammaVal) ); cpAntiPart.setRealImagPart( 1.0 - rBVal*TMath::Cos(deltaBVal - gammaVal), -rBVal*TMath::Sin(deltaBVal - gammaVal) ); break; } case GLW_CPEven : { const Double_t rBVal = rB_->value(); const Double_t deltaBVal = deltaB_->value(); cpPart.setRealImagPart( 1.0 + rBVal*TMath::Cos(deltaBVal + gammaVal), rBVal*TMath::Sin(deltaBVal + gammaVal) ); cpAntiPart.setRealImagPart( 1.0 + rBVal*TMath::Cos(deltaBVal - gammaVal), rBVal*TMath::Sin(deltaBVal - gammaVal) ); break; } case ADS_Favoured : { const Double_t rBVal = rB_->value(); const Double_t deltaBVal = deltaB_->value(); const Double_t rDVal = rD_->value(); const Double_t deltaDVal = deltaD_->value(); cpPart.setRealImagPart( 1.0 + rBVal*rDVal*TMath::Cos(deltaBVal - deltaDVal + gammaVal), rBVal*rDVal*TMath::Sin(deltaBVal - deltaDVal + gammaVal) ); cpAntiPart.setRealImagPart( 1.0 + rBVal*rDVal*TMath::Cos(deltaBVal - deltaDVal - gammaVal), rBVal*rDVal*TMath::Sin(deltaBVal - deltaDVal - gammaVal) ); break; } case ADS_Suppressed : { const Double_t rBVal = rB_->value(); const Double_t deltaBVal = deltaB_->value(); const Double_t rDVal = rD_->value(); const Double_t deltaDVal = deltaD_->value(); cpPart.setRealImagPart( rDVal*TMath::Cos(-deltaDVal) + rBVal*TMath::Cos(deltaBVal + gammaVal), rDVal*TMath::Sin(-deltaDVal) + rBVal*TMath::Sin(deltaBVal + gammaVal) ); cpAntiPart.setRealImagPart( rDVal*TMath::Cos(-deltaDVal) + rBVal*TMath::Cos(deltaBVal - gammaVal), rDVal*TMath::Sin(-deltaDVal) + rBVal*TMath::Sin(deltaBVal - gammaVal) ); break; } case GLW_CPOdd_btouOnly : nonCPPart.rescale(-1.0); cpPart.setRealImagPart( 1.0 * TMath::Cos( gammaVal ), 1.0 * TMath::Sin( gammaVal ) ); cpAntiPart.setRealImagPart( 1.0 * TMath::Cos( -gammaVal ), 1.0 * TMath::Sin( -gammaVal ) ); break; case GLW_CPEven_btouOnly : cpPart.setRealImagPart( 1.0 * TMath::Cos( gammaVal ), 1.0 * TMath::Sin( gammaVal ) ); cpAntiPart.setRealImagPart( 1.0 * TMath::Cos( -gammaVal ), 1.0 * TMath::Sin( -gammaVal ) ); break; case ADS_Favoured_btouOnly : { const Double_t rDVal = rD_->value(); const Double_t deltaDVal = deltaD_->value(); cpPart.setRealImagPart( rDVal * TMath::Cos( -deltaDVal + gammaVal ), rDVal * TMath::Sin( -deltaDVal + gammaVal ) ); cpAntiPart.setRealImagPart( rDVal * TMath::Cos( -deltaDVal - gammaVal ), rDVal * TMath::Sin( -deltaDVal - gammaVal ) ); break; } case ADS_Suppressed_btouOnly : cpPart.setRealImagPart( 1.0 * TMath::Cos( gammaVal ), 1.0 * TMath::Sin( gammaVal ) ); cpAntiPart.setRealImagPart( 1.0 * TMath::Cos( -gammaVal ), 1.0 * TMath::Sin( -gammaVal ) ); break; } const LauComplex partCoeff = nonCPPart * cpPart; const LauComplex antiCoeff = nonCPPart * cpAntiPart; const Double_t numer = antiCoeff.abs2() - partCoeff.abs2(); const Double_t denom = antiCoeff.abs2() + partCoeff.abs2(); const Double_t value = numer/denom; // is it fixed? const Bool_t fixed = gamma_->fixed(); acp_.fixed(fixed); // we can't work out the error without the covariance matrix const Double_t error(0.0); // set the value and error acp_.valueAndErrors(value,error); return acp_; } LauAbsCoeffSet* LauPolarGammaCPCoeffSet::createClone(const TString& newName, CloneOption cloneOption, Double_t constFactor) { LauAbsCoeffSet* clone(0); if ( cloneOption == All || cloneOption == TieRealPart || cloneOption == TieImagPart || cloneOption == TieCPPars ) { clone = new LauPolarGammaCPCoeffSet( *this, cloneOption, constFactor ); clone->name( newName ); } else { std::cerr << "ERROR in LauPolarGammaCPCoeffSet::createClone : Invalid clone option" << std::endl; } return clone; } diff --git a/src/LauPoleRes.cc b/src/LauPoleRes.cc index cc90887..8525415 100644 --- a/src/LauPoleRes.cc +++ b/src/LauPoleRes.cc @@ -1,77 +1,76 @@ /* Copyright 2018 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauPoleRes.cc \brief File containing implementation of LauPoleRes class. */ #include "LauPoleRes.hh" -ClassImp(LauPoleRes) LauPoleRes::LauPoleRes(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters) { } LauPoleRes::~LauPoleRes() { } void LauPoleRes::initialise() { } LauComplex LauPoleRes::resAmp(Double_t mass, Double_t spinTerm) { // This function returns the complex dynamical amplitude for a pole. 1/((mpole*mpole)-m*m) // mpole==(m0-iw0)==(rePole-i*imPole), to use the already defined mass and width of the resonance Double_t rePole = this->getMass(); Double_t imPole = this->getWidth(); Double_t reTerm = rePole*rePole -imPole*imPole -mass*mass; Double_t imTerm = 2.0*rePole*imPole; LauComplex resAmplitude(reTerm, imTerm); resAmplitude.rescale(1./(reTerm*reTerm + imTerm*imTerm)); return resAmplitude.scale(spinTerm); } const std::vector& LauPoleRes::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixMass() ) { this->addFloatingParameter( this->getMassPar() ); } if ( ! this->fixWidth() ) { this->addFloatingParameter( this->getWidthPar() ); } return this->getParameters(); } diff --git a/src/LauPrint.cc b/src/LauPrint.cc index 234a942..31f5e15 100644 --- a/src/LauPrint.cc +++ b/src/LauPrint.cc @@ -1,65 +1,64 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauPrint.cc \brief File containing implementation of LauPrint class. */ #include #include "TMath.h" #include "LauPrint.hh" -ClassImp(LauPrint) LauPrint::LauPrint() { } LauPrint::~LauPrint() { } void LauPrint::printFormat(std::ostream& stream, Double_t value) const { // Print double value to a specified level of precision char* string = new char[100]; if (TMath::Abs(value) < 1e-30) { sprintf(string, "%5.3f", 0.0); } else if (TMath::Abs(value) < 0.01) { sprintf(string, "%5.3e", value); } else if (TMath::Abs(value) < 0.1) { sprintf(string, "%5.3f", value); } else { sprintf(string, "%5.3f", value); } stream< #include #include #include "TMath.h" #include "TRandom.h" #include "LauRealImagCPCoeffSet.hh" #include "LauComplex.hh" #include "LauConstants.hh" #include "LauParameter.hh" #include "LauPrint.hh" -ClassImp(LauRealImagCPCoeffSet) LauRealImagCPCoeffSet::LauRealImagCPCoeffSet(const TString& compName, Double_t x, Double_t y, Double_t xbar, Double_t ybar, Bool_t xFixed, Bool_t yFixed, Bool_t xbarFixed, Bool_t ybarFixed) : LauAbsCoeffSet(compName), x_(new LauParameter("X", x, minRealImagPart_, maxRealImagPart_, xFixed)), y_(new LauParameter("Y", y, minRealImagPart_, maxRealImagPart_, yFixed)), xbar_(new LauParameter("Xbar", xbar, minRealImagPart_, maxRealImagPart_, xbarFixed)), ybar_(new LauParameter("Ybar", ybar, minRealImagPart_, maxRealImagPart_, ybarFixed)), particleCoeff_(x,y), antiparticleCoeff_(xbar,ybar), acp_("ACP", 0.0, -1.0, 1.0, kTRUE) { } LauRealImagCPCoeffSet::LauRealImagCPCoeffSet(const LauRealImagCPCoeffSet& rhs, CloneOption cloneOption, Double_t constFactor) : LauAbsCoeffSet(rhs.name()), x_(0), y_(0), xbar_(0), ybar_(0), particleCoeff_( rhs.particleCoeff_ ), antiparticleCoeff_( rhs.antiparticleCoeff_ ), acp_( rhs.acp_ ) { if ( cloneOption == All || cloneOption == TieRealPart ) { x_ = rhs.x_->createClone(constFactor); xbar_ = rhs.xbar_->createClone(constFactor); } else { x_ = new LauParameter("X", rhs.x_->value(), minRealImagPart_, maxRealImagPart_, rhs.x_->fixed()); if ( rhs.x_->blind() ) { const LauBlind* blinder = rhs.x_->blinder(); x_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } xbar_ = new LauParameter("Xbar", rhs.xbar_->value(), minRealImagPart_, maxRealImagPart_, rhs.xbar_->fixed()); if ( rhs.xbar_->blind() ) { const LauBlind* blinder = rhs.xbar_->blinder(); xbar_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TieImagPart ) { y_ = rhs.y_->createClone(constFactor); ybar_ = rhs.ybar_->createClone(constFactor); } else { y_ = new LauParameter("Y", rhs.y_->value(), minRealImagPart_, maxRealImagPart_, rhs.y_->fixed()); if ( rhs.y_->blind() ) { const LauBlind* blinder = rhs.y_->blinder(); y_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } ybar_ = new LauParameter("Ybar", rhs.ybar_->value(), minRealImagPart_, maxRealImagPart_, rhs.ybar_->fixed()); if ( rhs.ybar_->blind() ) { const LauBlind* blinder = rhs.ybar_->blinder(); ybar_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } } std::vector LauRealImagCPCoeffSet::getParameters() { std::vector pars; pars.push_back(x_); pars.push_back(y_); pars.push_back(xbar_); pars.push_back(ybar_); return pars; } void LauRealImagCPCoeffSet::printParValues() const { std::cout << "INFO in LauRealImagCPCoeffSet::printParValues : Component \"" << this->name() << "\" has "; std::cout << "x = " << x_->value() << ",\t"; std::cout << "y = " << y_->value() << ",\t"; std::cout << "xbar = " << xbar_->value() << ",\t"; std::cout << "ybar = " << ybar_->value() << "." << std::endl; } void LauRealImagCPCoeffSet::printTableHeading(std::ostream& stream) const { stream<<"\\begin{tabular}{|l|c|c|c|c|}"<name(); resName = resName.ReplaceAll("_", "\\_"); stream<value()); stream<<" \\pm "; print.printFormat(stream, x_->error()); stream<<"$ & $"; print.printFormat(stream, y_->value()); stream<<" \\pm "; print.printFormat(stream, y_->error()); stream<<"$ & $"; print.printFormat(stream, xbar_->value()); stream<<" \\pm "; print.printFormat(stream, xbar_->error()); stream<<"$ & $"; print.printFormat(stream, ybar_->value()); stream<<" \\pm "; print.printFormat(stream, ybar_->error()); stream<<"$ \\\\"<fixed() == kFALSE) { // Choose a value for "X" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; x_->initValue(value); x_->value(value); } if (y_->fixed() == kFALSE) { // Choose a value for "Y" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; y_->initValue(value); y_->value(value); } if (xbar_->fixed() == kFALSE) { // Choose a value for "Xbar" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; xbar_->initValue(value); xbar_->value(value); } if (ybar_->fixed() == kFALSE) { // Choose a value for "Ybar" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; ybar_->initValue(value); ybar_->value(value); } } void LauRealImagCPCoeffSet::finaliseValues() { // update the pulls x_->updatePull(); y_->updatePull(); xbar_->updatePull(); ybar_->updatePull(); } const LauComplex& LauRealImagCPCoeffSet::particleCoeff() { particleCoeff_.setRealImagPart( x_->unblindValue(), y_->unblindValue() ); return particleCoeff_; } const LauComplex& LauRealImagCPCoeffSet::antiparticleCoeff() { antiparticleCoeff_.setRealImagPart( xbar_->unblindValue(), ybar_->unblindValue() ); return antiparticleCoeff_; } void LauRealImagCPCoeffSet::setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, Bool_t init ) { Double_t xVal( coeff.re() ); Double_t yVal( coeff.im() ); Double_t xBarVal( coeffBar.re() ); Double_t yBarVal( coeffBar.im() ); x_->value( xVal ); y_->value( yVal ); xbar_->value( xBarVal ); ybar_->value( yBarVal ); if ( init ) { x_->genValue( xVal ); y_->genValue( yVal ); xbar_->genValue( xBarVal ); ybar_->genValue( yBarVal ); x_->initValue( xVal ); y_->initValue( yVal ); xbar_->initValue( xBarVal ); ybar_->initValue( yBarVal ); } } LauParameter LauRealImagCPCoeffSet::acp() { // set the name TString parName(this->baseName()); parName += "_ACP"; acp_.name(parName); // work out the ACP value Double_t csq = x_->value()*x_->value() + y_->value()*y_->value(); Double_t cbarsq = xbar_->value()*xbar_->value() + ybar_->value()*ybar_->value(); Double_t numer = cbarsq - csq; Double_t denom = cbarsq + csq; Double_t value = numer/denom; // is it fixed? Bool_t fixed = x_->fixed() && y_->fixed() && xbar_->fixed() && ybar_->fixed(); acp_.fixed(fixed); // we can't work out the error without the covariance matrix Double_t error(0.0); // set the value and error acp_.valueAndErrors(value,error); return acp_; } LauAbsCoeffSet* LauRealImagCPCoeffSet::createClone(const TString& newName, CloneOption cloneOption, Double_t constFactor) { LauAbsCoeffSet* clone(0); if ( cloneOption == All || cloneOption == TieRealPart || cloneOption == TieImagPart ) { clone = new LauRealImagCPCoeffSet( *this, cloneOption, constFactor ); clone->name( newName ); } else { std::cerr << "ERROR in LauRealImagCPCoeffSet::createClone : Invalid clone option" << std::endl; } return clone; } diff --git a/src/LauRealImagCoeffSet.cc b/src/LauRealImagCoeffSet.cc index f107182..c10bbfc 100644 --- a/src/LauRealImagCoeffSet.cc +++ b/src/LauRealImagCoeffSet.cc @@ -1,185 +1,184 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauRealImagCoeffSet.cc \brief File containing implementation of LauRealImagCoeffSet class. */ #include #include #include #include "TMath.h" #include "TRandom.h" #include "LauComplex.hh" #include "LauConstants.hh" #include "LauRealImagCoeffSet.hh" #include "LauParameter.hh" #include "LauPrint.hh" -ClassImp(LauRealImagCoeffSet) LauRealImagCoeffSet::LauRealImagCoeffSet(const TString& compName, Double_t x, Double_t y, Bool_t xFixed, Bool_t yFixed) : LauAbsCoeffSet(compName), x_(new LauParameter("X",x,minRealImagPart_,maxRealImagPart_,xFixed)), y_(new LauParameter("Y",y,minRealImagPart_,maxRealImagPart_,yFixed)), coeff_(x,y) { } LauRealImagCoeffSet::LauRealImagCoeffSet(const LauRealImagCoeffSet& rhs, CloneOption cloneOption, Double_t constFactor) : LauAbsCoeffSet(rhs.name()), x_(0), y_(0), coeff_( rhs.coeff_ ) { if ( cloneOption == All || cloneOption == TieRealPart ) { x_ = rhs.x_->createClone(constFactor); } else { x_ = new LauParameter("X", rhs.x_->value(), minRealImagPart_, maxRealImagPart_, rhs.x_->fixed()); if ( rhs.x_->blind() ) { const LauBlind* blinder = rhs.x_->blinder(); x_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TieImagPart ) { y_ = rhs.y_->createClone(constFactor); } else { y_ = new LauParameter("Y", rhs.y_->value(), minRealImagPart_, maxRealImagPart_, rhs.y_->fixed()); if ( rhs.y_->blind() ) { const LauBlind* blinder = rhs.y_->blinder(); y_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } } std::vector LauRealImagCoeffSet::getParameters() { std::vector pars; pars.push_back(x_); pars.push_back(y_); return pars; } void LauRealImagCoeffSet::printParValues() const { std::cout<<"INFO in LauRealImagCoeffSet::printParValues : Component \""<name()<<"\" has real part = "<value()<<" and imaginary part = "<value()<<"."<name(); resName = resName.ReplaceAll("_", "\\_"); stream<value()); stream<<" \\pm "; print.printFormat(stream, x_->error()); stream<<"$ & $"; print.printFormat(stream, y_->value()); stream<<" \\pm "; print.printFormat(stream, y_->error()); stream<<"$ \\\\"<fixed() == kFALSE) { // Choose a value between -10.0 and 10.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*20.0 - 10.0; x_->initValue(value); x_->value(value); } if (y_->fixed() == kFALSE) { // Choose a value between -10.0 and 10.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*20.0 - 10.0; y_->initValue(value); y_->value(value); } } void LauRealImagCoeffSet::finaliseValues() { x_->updatePull(); y_->updatePull(); } const LauComplex& LauRealImagCoeffSet::particleCoeff() { coeff_.setRealImagPart(x_->unblindValue(), y_->unblindValue()); return coeff_; } const LauComplex& LauRealImagCoeffSet::antiparticleCoeff() { return this->particleCoeff(); } void LauRealImagCoeffSet::setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, Bool_t init ) { LauComplex average( coeff ); average += coeffBar; average.rescale( 0.5 ); Double_t xVal( average.re() ); Double_t yVal( average.im() ); x_->value( xVal ); y_->value( yVal ); if ( init ) { x_->genValue( xVal ); y_->genValue( yVal ); x_->initValue( xVal ); y_->initValue( yVal ); } } LauParameter LauRealImagCoeffSet::acp() { TString parName(this->baseName()); parName += "_ACP"; return LauParameter(parName,0.0); } LauAbsCoeffSet* LauRealImagCoeffSet::createClone(const TString& newName, CloneOption cloneOption, Double_t constFactor) { LauAbsCoeffSet* clone(0); if ( cloneOption == All || cloneOption == TieRealPart || cloneOption == TieImagPart ) { clone = new LauRealImagCoeffSet( *this, cloneOption, constFactor ); clone->name( newName ); } else { std::cerr << "ERROR in LauRealImagCoeffSet::createClone : Invalid clone option" << std::endl; } return clone; } diff --git a/src/LauRealImagGammaCPCoeffSet.cc b/src/LauRealImagGammaCPCoeffSet.cc index 9120410..1345e22 100644 --- a/src/LauRealImagGammaCPCoeffSet.cc +++ b/src/LauRealImagGammaCPCoeffSet.cc @@ -1,296 +1,295 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauRealImagGammaCPCoeffSet.cc \brief File containing implementation of LauRealImagGammaCPCoeffSet class. */ #include #include #include #include "TMath.h" #include "TRandom.h" #include "LauRealImagGammaCPCoeffSet.hh" #include "LauComplex.hh" #include "LauConstants.hh" #include "LauParameter.hh" #include "LauPrint.hh" -ClassImp(LauRealImagGammaCPCoeffSet) LauRealImagGammaCPCoeffSet::LauRealImagGammaCPCoeffSet(const TString& compName, const Double_t x, const Double_t y, const Double_t xCP, const Double_t yCP, const Double_t xbarCP, const Double_t ybarCP, const Bool_t xFixed, const Bool_t yFixed, const Bool_t xCPFixed, const Bool_t yCPFixed, const Bool_t xbarCPFixed, const Bool_t ybarCPFixed) : LauAbsCoeffSet(compName), x_(new LauParameter("X", x, minRealImagPart_, maxRealImagPart_, xFixed)), y_(new LauParameter("Y", y, minRealImagPart_, maxRealImagPart_, yFixed)), xCP_(new LauParameter("XCP", xCP, minRealImagPart_, maxRealImagPart_, xCPFixed)), yCP_(new LauParameter("YCP", yCP, minRealImagPart_, maxRealImagPart_, yCPFixed)), xbarCP_(new LauParameter("XbarCP", xbarCP, minRealImagPart_, maxRealImagPart_, xbarCPFixed)), ybarCP_(new LauParameter("YbarCP", ybarCP, minRealImagPart_, maxRealImagPart_, ybarCPFixed)), nonCPPart_( x, y), cpPart_( 1+xCP, yCP ), cpAntiPart_( 1+xbarCP, ybarCP ), particleCoeff_( nonCPPart_ * cpPart_ ), antiparticleCoeff_( nonCPPart_ * cpAntiPart_ ), acp_("ACP", (antiparticleCoeff_.abs2()-particleCoeff_.abs2())/(antiparticleCoeff_.abs2()+particleCoeff_.abs2()), -1.0, 1.0, xCPFixed&&yCPFixed&&xbarCPFixed&&ybarCPFixed) { } LauRealImagGammaCPCoeffSet::LauRealImagGammaCPCoeffSet(const LauRealImagGammaCPCoeffSet& rhs, CloneOption cloneOption, Double_t constFactor) : LauAbsCoeffSet(rhs.name()), x_(0), y_(0), xCP_(0), yCP_(0), xbarCP_(0), ybarCP_(0), nonCPPart_( rhs.nonCPPart_ ), cpPart_( rhs.cpPart_ ), cpAntiPart_( rhs.cpAntiPart_ ), particleCoeff_( rhs.particleCoeff_ ), antiparticleCoeff_( rhs.antiparticleCoeff_ ), acp_( rhs.acp_ ) { if ( cloneOption == All || cloneOption == TieRealPart ) { x_ = rhs.x_->createClone(constFactor); } else { x_ = new LauParameter("X", rhs.x_->value(), minRealImagPart_, maxRealImagPart_, rhs.x_->fixed()); if ( rhs.x_->blind() ) { const LauBlind* blinder = rhs.x_->blinder(); x_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TieImagPart ) { y_ = rhs.y_->createClone(constFactor); } else { y_ = new LauParameter("Y", rhs.y_->value(), minRealImagPart_, maxRealImagPart_, rhs.y_->fixed()); if ( rhs.y_->blind() ) { const LauBlind* blinder = rhs.y_->blinder(); y_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TieCPPars ) { xCP_ = rhs.xCP_->createClone(constFactor); yCP_ = rhs.yCP_->createClone(constFactor); xbarCP_ = rhs.xbarCP_->createClone(constFactor); ybarCP_ = rhs.ybarCP_->createClone(constFactor); } else { xCP_ = new LauParameter("XCP", rhs.xCP_->value(), minRealImagPart_, maxRealImagPart_, rhs.xCP_->fixed()); if ( rhs.xCP_->blind() ) { const LauBlind* blinder = rhs.xCP_->blinder(); xCP_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } yCP_ = new LauParameter("YCP", rhs.yCP_->value(), minRealImagPart_, maxRealImagPart_, rhs.yCP_->fixed()); if ( rhs.yCP_->blind() ) { const LauBlind* blinder = rhs.yCP_->blinder(); yCP_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } xbarCP_ = new LauParameter("XbarCP", rhs.xbarCP_->value(), minRealImagPart_, maxRealImagPart_, rhs.xbarCP_->fixed()); if ( rhs.xbarCP_->blind() ) { const LauBlind* blinder = rhs.xbarCP_->blinder(); xbarCP_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } ybarCP_ = new LauParameter("YbarCP", rhs.ybarCP_->value(), minRealImagPart_, maxRealImagPart_, rhs.ybarCP_->fixed()); if ( rhs.ybarCP_->blind() ) { const LauBlind* blinder = rhs.ybarCP_->blinder(); ybarCP_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } } std::vector LauRealImagGammaCPCoeffSet::getParameters() { std::vector pars; pars.push_back(x_); pars.push_back(y_); if(!xCP_->fixed()) pars.push_back(xCP_); if(!yCP_->fixed()) pars.push_back(yCP_); if(!xbarCP_->fixed()) pars.push_back(xbarCP_); if(!ybarCP_->fixed()) pars.push_back(ybarCP_); return pars; } void LauRealImagGammaCPCoeffSet::printParValues() const { std::cout << "INFO in LauRealImagGammaCPCoeffSet::printParValues : Component \"" << this->name() << "\" has "; std::cout << "x = " << x_->value() << ",\t"; std::cout << "y = " << y_->value() << ",\t"; std::cout << "xCP = " << xCP_->value() << ",\t"; std::cout << "yCP = " << yCP_->value() << ",\t"; std::cout << "xbarCP = " << xbarCP_->value() << ",\t"; std::cout << "ybarCP = " << ybarCP_->value() << "." << std::endl; } void LauRealImagGammaCPCoeffSet::printTableHeading(std::ostream& stream) const { stream<<"\\begin{tabular}{|l|c|c|c|c|c|c|}"<name(); resName = resName.ReplaceAll("_", "\\_"); stream<value()); stream<<" \\pm "; print.printFormat(stream, x_->error()); stream<<"$ & $"; print.printFormat(stream, y_->value()); stream<<" \\pm "; print.printFormat(stream, y_->error()); stream<<"$ & $"; print.printFormat(stream, xCP_->value()); stream<<" \\pm "; print.printFormat(stream, xCP_->error()); stream<<"$ & $"; print.printFormat(stream, yCP_->value()); stream<<" \\pm "; print.printFormat(stream, yCP_->error()); stream<<"$ & $"; print.printFormat(stream, xbarCP_->value()); stream<<" \\pm "; print.printFormat(stream, xbarCP_->error()); stream<<"$ & $"; print.printFormat(stream, ybarCP_->value()); stream<<" \\pm "; print.printFormat(stream, ybarCP_->error()); stream<<"$ \\\\"<fixed() == kFALSE) { // Choose a value for "X" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; x_->initValue(value); x_->value(value); } if (y_->fixed() == kFALSE) { // Choose a value for "Y" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; y_->initValue(value); y_->value(value); } if (xCP_->fixed() == kFALSE) { // Choose a value for "XCP" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; xCP_->initValue(value); xCP_->value(value); } if (yCP_->fixed() == kFALSE) { // Choose a value for "YCP" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; yCP_->initValue(value); yCP_->value(value); } if (xbarCP_->fixed() == kFALSE) { // Choose a value for "XbarCP" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; xbarCP_->initValue(value); xbarCP_->value(value); } if (ybarCP_->fixed() == kFALSE) { // Choose a value for "YbarCP" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; ybarCP_->initValue(value); ybarCP_->value(value); } } void LauRealImagGammaCPCoeffSet::finaliseValues() { // update the pulls x_->updatePull(); y_->updatePull(); xCP_->updatePull(); yCP_->updatePull(); xbarCP_->updatePull(); ybarCP_->updatePull(); } const LauComplex& LauRealImagGammaCPCoeffSet::particleCoeff() { nonCPPart_.setRealImagPart( x_->unblindValue(), y_->unblindValue() ); cpPart_.setRealImagPart( 1.0+xCP_->unblindValue(), yCP_->unblindValue() ); particleCoeff_ = nonCPPart_ * cpPart_; return particleCoeff_; } const LauComplex& LauRealImagGammaCPCoeffSet::antiparticleCoeff() { nonCPPart_.setRealImagPart( x_->unblindValue(), y_->unblindValue() ); cpAntiPart_.setRealImagPart( 1.0+xbarCP_->unblindValue(), ybarCP_->unblindValue() ); antiparticleCoeff_ = nonCPPart_ * cpAntiPart_; return antiparticleCoeff_; } void LauRealImagGammaCPCoeffSet::setCoeffValues( const LauComplex&, const LauComplex&, Bool_t ) { std::cerr << "ERROR in LauCartesianGammaCPCoeffSet::setCoeffValues : Method not supported by this class - too many parameters" << std::endl; } LauParameter LauRealImagGammaCPCoeffSet::acp() { // set the name TString parName(this->baseName()); parName += "_ACP"; acp_.name(parName); // work out the ACP value const LauComplex nonCPPart( x_->value(), y_->value() ); const LauComplex cpPart( 1.0+xCP_->value(), yCP_->value() ); const LauComplex cpAntiPart( 1.0+xbarCP_->value(), ybarCP_->value() ); const LauComplex partCoeff = nonCPPart * cpPart; const LauComplex antiCoeff = nonCPPart * cpAntiPart; const Double_t numer = antiCoeff.abs2() - partCoeff.abs2(); const Double_t denom = antiCoeff.abs2() + partCoeff.abs2(); const Double_t value = numer/denom; // is it fixed? const Bool_t fixed = xCP_->fixed() && yCP_->fixed() && xbarCP_->fixed() && ybarCP_->fixed(); acp_.fixed(fixed); // we can't work out the error without the covariance matrix const Double_t error(0.0); // set the value and error acp_.valueAndErrors(value,error); return acp_; } LauAbsCoeffSet* LauRealImagGammaCPCoeffSet::createClone(const TString& newName, CloneOption cloneOption, Double_t constFactor) { LauAbsCoeffSet* clone(0); if ( cloneOption == All || cloneOption == TieRealPart || cloneOption == TieImagPart || cloneOption == TieCPPars ) { clone = new LauRealImagGammaCPCoeffSet( *this, cloneOption, constFactor ); clone->name( newName ); } else { std::cerr << "ERROR in LauRealImagGammaCPCoeffSet::createClone : Invalid clone option" << std::endl; } return clone; } diff --git a/src/LauRelBreitWignerRes.cc b/src/LauRelBreitWignerRes.cc index aaf58e4..04c04bc 100644 --- a/src/LauRelBreitWignerRes.cc +++ b/src/LauRelBreitWignerRes.cc @@ -1,296 +1,295 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauRelBreitWignerRes.cc \brief File containing implementation of LauRelBreitWignerRes class. */ #include #include "LauConstants.hh" #include "LauRelBreitWignerRes.hh" -ClassImp(LauRelBreitWignerRes) LauRelBreitWignerRes::LauRelBreitWignerRes(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), q0_(0.0), p0_(0.0), pstar0_(0.0), erm0_(0.0), resMass_(0.0), resMassSq_(0.0), resWidth_(0.0), resRadius_(0.0), parRadius_(0.0), mDaugSum_(0.0), mDaugSumSq_(0.0), mDaugDiff_(0.0), mDaugDiffSq_(0.0), mParentSq_(0.0), mBachSq_(0.0), FR0_(1.0), FP0_(1.0) { } LauRelBreitWignerRes::~LauRelBreitWignerRes() { } void LauRelBreitWignerRes::initialise() { // Set-up various constants. This must be called again if the mass/width/spin // of a resonance changes... resMass_ = this->getMass(); resWidth_ = this->getWidth(); resRadius_ = this->getResRadius(); parRadius_ = this->getParRadius(); Double_t massDaug1 = this->getMassDaug1(); Double_t massDaug2 = this->getMassDaug2(); Double_t massBachelor = this->getMassBachelor(); Double_t massParent = this->getMassParent(); // Create the mass squares, sums, differences etc. resMassSq_ = resMass_*resMass_; mDaugSum_ = massDaug1 + massDaug2; mDaugSumSq_ = mDaugSum_*mDaugSum_; mDaugDiff_ = massDaug1 - massDaug2; mDaugDiffSq_ = mDaugDiff_*mDaugDiff_; mParentSq_ = massParent*massParent; mBachSq_ = massBachelor*massBachelor; // Create an effective resonance pole mass to protect against resonances // that are below threshold Double_t effResMass = resMass_; Double_t effResMassSq = resMassSq_; if (resMassSq_ - mDaugSumSq_ < 0.0 || resMass_ > massParent - massBachelor){ Double_t minMass = mDaugSum_; Double_t maxMass = massParent - massBachelor; Double_t tanhTerm = std::tanh( (resMass_ - ((minMass + maxMass)/2))/(maxMass-minMass)); effResMass = minMass + (maxMass-minMass)*(1+tanhTerm)/2; effResMassSq = effResMass*effResMass; } // Decay momentum of either daughter in the resonance rest frame // when resonance mass = rest-mass value, m_0 (PDG value) Double_t term1 = effResMassSq - mDaugSumSq_; Double_t term2 = effResMassSq - mDaugDiffSq_; Double_t term12 = term1*term2; if (term12 > 0.0) { q0_ = TMath::Sqrt(term12)/(2.0*effResMass); } else { q0_ = 0.0; } // Momentum of the bachelor particle in the resonance rest frame // when resonance mass = rest-mass value, m_0 (PDG value) Double_t eBach = (mParentSq_ - effResMassSq - mBachSq_)/(2.0*effResMass); Double_t termBach = eBach*eBach - mBachSq_; if ( eBach<0.0 || termBach<0.0 ) { p0_ = 0.0; } else { p0_ = TMath::Sqrt( termBach ); } // Momentum of the bachelor particle in the parent rest frame // when resonance mass = rest-mass value, m_0 (PDG value) Double_t eStarBach = (mParentSq_ + mBachSq_ - effResMassSq)/(2.0*massParent); Double_t termStarBach = eStarBach*eStarBach - mBachSq_; if ( eStarBach<0.0 || termStarBach<0.0 ) { pstar0_ = 0.0; } else { pstar0_ = TMath::Sqrt( termStarBach ); } // Covariant factor when resonance mass = rest-mass value, m_0 (PDF value) erm0_ = (mParentSq_ + effResMassSq - mBachSq_)/(2.0*massParent*effResMass); this->calcCovFactor( erm0_ ); // Calculate the Blatt-Weisskopf form factor for the case when m = m_0 FR0_ = 1.0; FP0_ = 1.0; const Int_t resSpin = this->getSpin(); if ( resSpin > 0 ) { const LauBlattWeisskopfFactor* resBWFactor = this->getResBWFactor(); const LauBlattWeisskopfFactor* parBWFactor = this->getParBWFactor(); FR0_ = (resBWFactor!=0) ? resBWFactor->calcFormFactor(q0_) : 1.0; switch ( parBWFactor->getRestFrame() ) { case LauBlattWeisskopfFactor::ResonanceFrame: FP0_ = (parBWFactor!=0) ? parBWFactor->calcFormFactor(p0_) : 1.0; break; case LauBlattWeisskopfFactor::ParentFrame: FP0_ = (parBWFactor!=0) ? parBWFactor->calcFormFactor(pstar0_) : 1.0; break; case LauBlattWeisskopfFactor::Covariant: { Double_t covFactor = this->getCovFactor(); if ( resSpin > 2 ) { covFactor = TMath::Power( covFactor, 1.0/resSpin ); } else if ( resSpin == 2 ) { covFactor = TMath::Sqrt( covFactor ); } FP0_ = (parBWFactor!=0) ? parBWFactor->calcFormFactor(pstar0_*covFactor) : 1.0; break; } } } } LauComplex LauRelBreitWignerRes::resAmp(Double_t mass, Double_t spinTerm) { // This function returns the complex dynamical amplitude for a Breit-Wigner resonance, // given the invariant mass and cos(helicity) values. LauComplex resAmplitude(0.0, 0.0); if (mass < 1e-10) { std::cerr << "WARNING in LauRelBreitWignerRes::amplitude : mass < 1e-10." << std::endl; return LauComplex(0.0, 0.0); } else if (q0_ < 1e-30) { return LauComplex(0.0, 0.0); } // Calculate the width of the resonance (as a function of mass) // First, calculate the various form factors. // NB // q is the momentum of either daughter in the resonance rest-frame, // p is the momentum of the bachelor in the resonance rest-frame, // pstar is the momentum of the bachelor in the parent rest-frame. // These quantities have been calculate in LauAbsResonance::amplitude(...) const Double_t resMass = this->getMass(); const Double_t resWidth = this->getWidth(); const Double_t resRadius = this->getResRadius(); const Double_t parRadius = this->getParRadius(); // If the mass is floating and its value has changed we need to // recalculate everything that assumes that value // Similarly for the BW radii if ( ( (!this->fixMass()) && resMass != resMass_ ) || ( (!this->fixResRadius()) && resRadius != resRadius_ ) || ( (!this->fixParRadius()) && parRadius != parRadius_ ) ) { this->initialise(); } const Int_t resSpin = this->getSpin(); const Double_t q = this->getQ(); const Double_t p = this->getP(); const Double_t pstar = this->getPstar(); // Get barrier scaling factors Double_t fFactorR(1.0); Double_t fFactorB(1.0); if ( resSpin > 0 ) { const LauBlattWeisskopfFactor* resBWFactor = this->getResBWFactor(); const LauBlattWeisskopfFactor* parBWFactor = this->getParBWFactor(); fFactorR = (resBWFactor!=0) ? resBWFactor->calcFormFactor(q) : 1.0; switch ( parBWFactor->getRestFrame() ) { case LauBlattWeisskopfFactor::ResonanceFrame: fFactorB = (parBWFactor!=0) ? parBWFactor->calcFormFactor(p) : 1.0; break; case LauBlattWeisskopfFactor::ParentFrame: fFactorB = (parBWFactor!=0) ? parBWFactor->calcFormFactor(pstar) : 1.0; break; case LauBlattWeisskopfFactor::Covariant: { Double_t covFactor = this->getCovFactor(); if ( resSpin > 2 ) { covFactor = TMath::Power( covFactor, 1.0/resSpin ); } else if ( resSpin == 2 ) { covFactor = TMath::Sqrt( covFactor ); } fFactorB = (parBWFactor!=0) ? parBWFactor->calcFormFactor(pstar*covFactor) : 1.0; break; } } } const Double_t fFactorRRatio = fFactorR/FR0_; const Double_t fFactorBRatio = fFactorB/FP0_; // If ignoreMomenta is set, set the total width simply as the pole width, and do // not include any momentum-dependent barrier factors (set them to unity) Double_t totWidth(resWidth); if (!this->ignoreMomenta()) { const Double_t qRatio = q/q0_; Double_t qTerm(0.0); if (resSpin == 0) { qTerm = qRatio; } else if (resSpin == 1) { qTerm = qRatio*qRatio*qRatio; } else if (resSpin == 2) { qTerm = qRatio*qRatio*qRatio*qRatio*qRatio; } else { qTerm = TMath::Power(qRatio, 2.0*resSpin + 1.0); } totWidth = resWidth*qTerm*(resMass/mass)*fFactorRRatio*fFactorRRatio; } const Double_t massSq = mass*mass; const Double_t massSqTerm = resMassSq_ - massSq; // Compute the complex amplitude resAmplitude = LauComplex(massSqTerm, resMass*totWidth); // Scale by the denominator factor, as well as the spin term Double_t scale = spinTerm/(massSqTerm*massSqTerm + resMassSq_*totWidth*totWidth); // Include Blatt-Weisskopf barrier factors if (!this->ignoreBarrierScaling()) { scale *= fFactorRRatio*fFactorBRatio; } resAmplitude.rescale(scale); return resAmplitude; } const std::vector& LauRelBreitWignerRes::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixMass() ) { this->addFloatingParameter( this->getMassPar() ); } if ( ! this->fixWidth() ) { this->addFloatingParameter( this->getWidthPar() ); } if ( ! this->fixResRadius() ) { this->addFloatingParameter( this->getResBWFactor()->getRadiusParameter() ); } if ( ! this->fixParRadius() ) { this->addFloatingParameter( this->getParBWFactor()->getRadiusParameter() ); } return this->getParameters(); } diff --git a/src/LauRescattering2Res.cc b/src/LauRescattering2Res.cc index 37fd6c5..396a45c 100644 --- a/src/LauRescattering2Res.cc +++ b/src/LauRescattering2Res.cc @@ -1,672 +1,671 @@ /* Copyright 2018 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauRescattering2Res.cc \brief File containing implementation of LauRescattering2Res class. */ #include #include "LauConstants.hh" #include "LauRescattering2Res.hh" #include "LauResonanceInfo.hh" -ClassImp(LauRescattering2Res) LauRescattering2Res::LauRescattering2Res(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), B1_(0),B2_(0),B3_(0), C1_(0),C2_(0),C3_(0),C4_(0),C5_(0), D0_(0),D1_(0),D2_(0),D3_(0), F1_(0),F2_(0),F3_(0),F4_(0) { // Default values for parameters, taken from const Double_t B1Val(23.6); const Double_t B2Val(29.4); const Double_t B3Val(0.6); const Double_t C1Val(34.39); const Double_t C2Val(4.4); const Double_t C3Val(-32.9); const Double_t C4Val(-16.); const Double_t C5Val(7.4); const Double_t D0Val(0.59); const Double_t D1Val(-0.38); const Double_t D2Val(0.12); const Double_t D3Val(-0.09); const Double_t F1Val(-0.043); const Double_t F2Val(-0.008); const Double_t F3Val(-0.28); const Double_t F4Val(0.026); const TString& parNameBase = this->getSanitisedName(); TString B1Name(parNameBase); B1Name += "_B1"; B1_ = resInfo->getExtraParameter( B1Name ); if ( B1_ == 0 ) { B1_ = new LauParameter( B1Name, B1Val, -100.,100., kTRUE ); B1_->secondStage(kTRUE); resInfo->addExtraParameter( B1_ ); } TString B2Name(parNameBase); B2Name += "_B2"; B2_ = resInfo->getExtraParameter( B2Name ); if ( B2_ == 0 ) { B2_ = new LauParameter( B2Name, B2Val, -100.,100., kTRUE ); B2_->secondStage(kTRUE); resInfo->addExtraParameter( B2_ ); } TString B3Name(parNameBase); B3Name += "_B3"; B3_ = resInfo->getExtraParameter( B3Name ); if ( B3_ == 0 ) { B3_ = new LauParameter( B3Name, B3Val, -100.,100., kTRUE ); B3_->secondStage(kTRUE); resInfo->addExtraParameter( B3_ ); } TString C1Name(parNameBase); C1Name += "_C1"; C1_ = resInfo->getExtraParameter( C1Name ); if ( C1_ == 0 ) { C1_ = new LauParameter( C1Name, C1Val, -100.,100., kTRUE ); C1_->secondStage(kTRUE); resInfo->addExtraParameter( C1_ ); } TString C2Name(parNameBase); C2Name += "_C2"; C2_ = resInfo->getExtraParameter( C2Name ); if ( C2_ == 0 ) { C2_ = new LauParameter( C2Name, C2Val, -100.,100., kTRUE ); C2_->secondStage(kTRUE); resInfo->addExtraParameter( C2_ ); } TString C3Name(parNameBase); C3Name += "_C3"; C3_ = resInfo->getExtraParameter( C3Name ); if ( C3_ == 0 ) { C3_ = new LauParameter( C3Name, C3Val, -100.,100., kTRUE ); C3_->secondStage(kTRUE); resInfo->addExtraParameter( C3_ ); } TString C4Name(parNameBase); C4Name += "_C4"; C4_ = resInfo->getExtraParameter( C4Name ); if ( C4_ == 0 ) { C4_ = new LauParameter( C4Name, C4Val, -100.,100., kTRUE ); C4_->secondStage(kTRUE); resInfo->addExtraParameter( C4_ ); } TString C5Name(parNameBase); C5Name += "_C5"; C5_ = resInfo->getExtraParameter( C5Name ); if ( C5_ == 0 ) { C5_ = new LauParameter( C5Name, C5Val, -100.,100., kTRUE ); C5_->secondStage(kTRUE); resInfo->addExtraParameter( C5_ ); } TString D0Name(parNameBase); D0Name += "_D0"; D0_ = resInfo->getExtraParameter( D0Name ); if ( D0_ == 0 ) { D0_ = new LauParameter( D0Name, D0Val, -100.,100., kTRUE ); D0_->secondStage(kTRUE); resInfo->addExtraParameter( D0_ ); } TString D1Name(parNameBase); D1Name += "_D1"; D1_ = resInfo->getExtraParameter( D1Name ); if ( D1_ == 0 ) { D1_ = new LauParameter( D1Name, D1Val, -100.,100., kTRUE ); D1_->secondStage(kTRUE); resInfo->addExtraParameter( D1_ ); } TString D2Name(parNameBase); D2Name += "_D2"; D2_ = resInfo->getExtraParameter( D2Name ); if ( D2_ == 0 ) { D2_ = new LauParameter( D2Name, D2Val,-100.,100., kTRUE ); D2_->secondStage(kTRUE); resInfo->addExtraParameter( D2_ ); } TString D3Name(parNameBase); D3Name += "_D3"; D3_ = resInfo->getExtraParameter( D3Name ); if ( D3_ == 0 ) { D3_ = new LauParameter( D3Name, D3Val, -100.,100., kTRUE ); D3_->secondStage(kTRUE); resInfo->addExtraParameter( D3_ ); } TString F1Name(parNameBase); F1Name += "_F1"; F1_ = resInfo->getExtraParameter( F1Name ); if ( F1_ == 0 ) { F1_ = new LauParameter( F1Name, F1Val, -100.,100., kTRUE ); F1_->secondStage(kTRUE); resInfo->addExtraParameter( F1_ ); } TString F2Name(parNameBase); F2Name += "_F2"; F2_ = resInfo->getExtraParameter( F2Name ); if ( F2_ == 0 ) { F2_ = new LauParameter( F2Name, F2Val, -100.,100., kTRUE ); F2_->secondStage(kTRUE); resInfo->addExtraParameter( F2_ ); } TString F3Name(parNameBase); F3Name += "_F3"; F3_ = resInfo->getExtraParameter( F3Name ); if ( F3_ == 0 ) { F3_ = new LauParameter( F3Name, F3Val, -100.,100., kTRUE ); F3_->secondStage(kTRUE); resInfo->addExtraParameter( F3_ ); } TString F4Name(parNameBase); F4Name += "_F4"; F4_ = resInfo->getExtraParameter( F4Name ); if ( F4_ == 0 ) { F4_ = new LauParameter( F4Name, F4Val, -100.,100., kTRUE ); F4_->secondStage(kTRUE); resInfo->addExtraParameter( F4_ ); } } LauRescattering2Res::~LauRescattering2Res() { delete B1_;delete B2_;delete B3_; delete C1_;delete C2_;delete C3_;delete C4_;delete C5_; delete D0_;delete D1_;delete D2_;delete D3_; delete F1_;delete F2_;delete F3_;delete F4_; } void LauRescattering2Res::initialise() { sqr_tmin[1] = 2.00*LauConstants::mK; sqr_tmin[2] = 1.47; sqr_tmax[1] = 1.47; sqr_tmax[2] = 2.00; B0_ = 226.5*TMath::Pi()/180.0 + B1_->value() - B2_->value() + B3_->value(); C0_ = phi00(sqr_tmax[1]*sqr_tmax[1], 1) + C1_->value() - C2_->value() + C3_->value() - C4_->value() + C5_->value(); F0_ = g00(sqr_tmax[1]*sqr_tmax[1], 1) + F1_->value() - F2_->value() + F3_->value() - F4_->value(); std::cout << "##### B = " << this->B1_->value()<<", "<< this->B2_->value()<<", "<< this->B3_->value()<C2_->value()<<", "<< this->C3_->value()<<", "<< this->C4_->value()<<", "<< this->C5_->value()<D1_->value()<<", "<< this->D2_->value()<<", "<< this->D3_->value()<< std::endl; std::cout << "##### F = " << this->F1_->value()<<", "<< this->F2_->value()<<", "<< this->F3_->value()<<", "<< this->F4_->value()< sqr_tmax[1] && mass < sqr_tmax[2]) i = 2; if (i == 0) { std::cout << " ERROR MASS = " << mass <<" out of limmits mI, mII" << std::endl; return LauComplex(0,0); } Double_t sqr_t = mass; Double_t mag = this->g00(sqr_t, i); Double_t phase = this->phi00(sqr_t, i); return LauComplex(mag*TMath::Cos(phase), mag*TMath::Sin(phase)); } Double_t LauRescattering2Res::pn(const Double_t x_, const Double_t n) const { if (n==0) return 1.0; if (n==1) return x_; return 2*x_*pn(x_,n-1) - pn(x_,n-2); } Double_t LauRescattering2Res::x(const Double_t sqr_t, const Int_t i) const { return 2.0*(sqr_t-sqr_tmin[i])/(sqr_tmax[i]-sqr_tmin[i]) -1.0; } Double_t LauRescattering2Res::phi00(const Double_t sqr_t, const Int_t i) const { Double_t x_t = x(sqr_t, i); if (i==1) return B0_*this->pn(x_t,0)+ B1_->value()*this->pn(x_t,1)+ B2_->value()*this->pn(x_t,2)+ B3_->value()*this->pn(x_t,3); if (i==2) return C0_*this->pn(x_t,0)+ C1_->value()*this->pn(x_t,1)+ C2_->value()*this->pn(x_t,2)+ C3_->value()*this->pn(x_t,3)+ C4_->value()*this->pn(x_t,4)+ C5_->value()*this->pn(x_t,5); return 0; } Double_t LauRescattering2Res::g00(const Double_t sqr_t, const Int_t i) const { Double_t x_t = x(sqr_t, i); if (i==1) return D0_->value()*this->pn(x_t,0)+ D1_->value()*this->pn(x_t,1)+ D2_->value()*this->pn(x_t,2)+ D3_->value()*this->pn(x_t,3); if (i==2) return F0_*this->pn(x_t,0)+ F1_->value()*this->pn(x_t,1)+ F2_->value()*this->pn(x_t,2)+ F3_->value()*this->pn(x_t,3)+ F4_->value()*this->pn(x_t,4); return 0; } // TODO up to here! const std::vector& LauRescattering2Res::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixB1Parameter() ) { this->addFloatingParameter( B1_ ); } if ( ! this->fixB2Parameter() ) { this->addFloatingParameter( B2_ ); } if ( ! this->fixB3Parameter() ) { this->addFloatingParameter( B3_ ); } if ( ! this->fixC1Parameter() ) { this->addFloatingParameter( C1_ ); } if ( ! this->fixC2Parameter() ) { this->addFloatingParameter( C2_ ); } if ( ! this->fixC3Parameter() ) { this->addFloatingParameter( C3_ ); } if ( ! this->fixC4Parameter() ) { this->addFloatingParameter( C4_ ); } if ( ! this->fixC5Parameter() ) { this->addFloatingParameter( C5_ ); } if ( ! this->fixD0Parameter() ) { this->addFloatingParameter( D0_ ); } if ( ! this->fixD1Parameter() ) { this->addFloatingParameter( D1_ ); } if ( ! this->fixD2Parameter() ) { this->addFloatingParameter( D2_ ); } if ( ! this->fixD3Parameter() ) { this->addFloatingParameter( D3_ ); } if ( ! this->fixF1Parameter() ) { this->addFloatingParameter( F1_ ); } if ( ! this->fixF2Parameter() ) { this->addFloatingParameter( F2_ ); } if ( ! this->fixF3Parameter() ) { this->addFloatingParameter( F3_ ); } if ( ! this->fixF4Parameter() ) { this->addFloatingParameter( F4_ ); } return this->getParameters(); } void LauRescattering2Res::setResonanceParameter(const TString& name, const Double_t value) { // Set various parameters for the NRAmplitude lineshape dynamics if (name == "B1") { this->setB1Parameter(value); std::cout << "INFO in LauRescattering2Res::setResonanceParameter : Setting NRAmplitude B1 = " << this->getB1Parameter() << std::endl; } else if (name == "B2") { this->setB2Parameter(value); std::cout << "INFO in LauRescattering2Res::setResonanceParameter : Setting NRAmplitude B2 = " << this->getB2Parameter() << std::endl; } else if (name == "B3") { this->setB3Parameter(value); std::cout << "INFO in LauRescattering2Res::setResonanceParameter : Setting NRAmplitude B3 = " << this->getB3Parameter() << std::endl; } else if (name == "C1") { this->setC1Parameter(value); std::cout << "INFO in LauRescattering2Res::setResonanceParameter : Setting NRAmplitude C1 = " << this->getC1Parameter() << std::endl; } else if (name == "C2") { this->setC2Parameter(value); std::cout << "INFO in LauRescattering2Res::setResonanceParameter : Setting NRAmplitude C2 = " << this->getC2Parameter() << std::endl; } else if (name == "C3") { this->setC3Parameter(value); std::cout << "INFO in LauRescattering2Res::setResonanceParameter : Setting NRAmplitude C3 = " << this->getC3Parameter() << std::endl; } else if (name == "C4") { this->setC4Parameter(value); std::cout << "INFO in LauRescattering2Res::setResonanceParameter : Setting NRAmplitude C4 = " << this->getC4Parameter() << std::endl; } else if (name == "C5") { this->setC5Parameter(value); std::cout << "INFO in LauRescattering2Res::setResonanceParameter : Setting NRAmplitude C5 = " << this->getC5Parameter() << std::endl; } else if (name == "D0") { this->setD0Parameter(value); std::cout << "INFO in LauRescattering2Res::setResonanceParameter : Setting NRAmplitude D0 = " << this->getD0Parameter() << std::endl; } else if (name == "D1") { this->setD1Parameter(value); std::cout << "INFO in LauRescattering2Res::setResonanceParameter : Setting NRAmplitude D1 = " << this->getD1Parameter() << std::endl; } else if (name == "D2") { this->setD2Parameter(value); std::cout << "INFO in LauRescattering2Res::setResonanceParameter : Setting NRAmplitude D2 = " << this->getD2Parameter() << std::endl; } else if (name == "D3") { this->setD3Parameter(value); std::cout << "INFO in LauRescattering2Res::setResonanceParameter : Setting NRAmplitude D3 = " << this->getD3Parameter() << std::endl; } else if (name == "F1") { this->setF1Parameter(value); std::cout << "INFO in LauRescattering2Res::setResonanceParameter : Setting NRAmplitude F1 = " << this->getF1Parameter() << std::endl; } else if (name == "F2") { this->setF2Parameter(value); std::cout << "INFO in LauRescattering2Res::setResonanceParameter : Setting NRAmplitude F2 = " << this->getF2Parameter() << std::endl; } else if (name == "F3") { this->setF3Parameter(value); std::cout << "INFO in LauRescattering2Res::setResonanceParameter : Setting NRAmplitude F3 = " << this->getF3Parameter() << std::endl; } else if (name == "F4") { this->setF4Parameter(value); std::cout << "INFO in LauRescattering2Res::setResonanceParameter : Setting NRAmplitude F4 = " << this->getF4Parameter() << std::endl; } else { std::cerr << "WARNING in LauRescattering2Res::setResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } void LauRescattering2Res::floatResonanceParameter(const TString& name) { if (name == "B1") { if ( B1_->fixed() ) { B1_->fixed( kFALSE ); this->addFloatingParameter( B1_ ); } else { std::cerr << "WARNING in LauRescattering2Res::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "B2") { if ( B2_->fixed() ) { B2_->fixed( kFALSE ); this->addFloatingParameter( B2_ ); } else { std::cerr << "WARNING in LauRescattering2Res::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "B3") { if ( B3_->fixed() ) { B3_->fixed( kFALSE ); this->addFloatingParameter( B3_ ); } else { std::cerr << "WARNING in LauRescattering2Res::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "C1") { if ( C1_->fixed() ) { C1_->fixed( kFALSE ); this->addFloatingParameter( C1_ ); } else { std::cerr << "WARNING in LauRescattering2Res::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "C2") { if ( C2_->fixed() ) { C2_->fixed( kFALSE ); this->addFloatingParameter( C2_ ); } else { std::cerr << "WARNING in LauRescattering2Res::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "C3") { if ( C3_->fixed() ) { C3_->fixed( kFALSE ); this->addFloatingParameter( C3_ ); } else { std::cerr << "WARNING in LauRescattering2Res::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "C4") { if ( C4_->fixed() ) { C4_->fixed( kFALSE ); this->addFloatingParameter( C4_ ); } else { std::cerr << "WARNING in LauRescattering2Res::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "C5") { if ( C5_->fixed() ) { C5_->fixed( kFALSE ); this->addFloatingParameter( C5_ ); } else { std::cerr << "WARNING in LauRescattering2Res::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "D0") { if ( D0_->fixed() ) { D0_->fixed( kFALSE ); this->addFloatingParameter( D0_ ); } else { std::cerr << "WARNING in LauRescattering2Res::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "D1") { if ( D1_->fixed() ) { D1_->fixed( kFALSE ); this->addFloatingParameter( D1_ ); } else { std::cerr << "WARNING in LauRescattering2Res::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "D2") { if ( D2_->fixed() ) { D2_->fixed( kFALSE ); this->addFloatingParameter( D2_ ); } else { std::cerr << "WARNING in LauRescattering2Res::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "D3") { if ( D3_->fixed() ) { D3_->fixed( kFALSE ); this->addFloatingParameter( D3_ ); } else { std::cerr << "WARNING in LauRescattering2Res::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "F1") { if ( F1_->fixed() ) { F1_->fixed( kFALSE ); this->addFloatingParameter( F1_ ); } else { std::cerr << "WARNING in LauRescattering2Res::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "F2") { if ( F2_->fixed() ) { F2_->fixed( kFALSE ); this->addFloatingParameter( F2_ ); } else { std::cerr << "WARNING in LauRescattering2Res::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "F3") { if ( F3_->fixed() ) { F3_->fixed( kFALSE ); this->addFloatingParameter( F3_ ); } else { std::cerr << "WARNING in LauRescattering2Res::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "4F") { if ( F4_->fixed() ) { F4_->fixed( kFALSE ); this->addFloatingParameter( F4_ ); } else { std::cerr << "WARNING in LauRescattering2Res::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else { std::cerr << "WARNING in LauRescattering2Res::fixResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } LauParameter* LauRescattering2Res::getResonanceParameter(const TString& name) { if (name == "B1") { return B1_; } else if (name == "B2") { return B2_; } else if (name == "B3") { return B3_; } else if (name == "C1") { return C1_; } else if (name == "C2") { return C2_; } else if (name == "C3") { return C3_; } else if (name == "C4") { return C4_; } else if (name == "C5") { return C5_; } else if (name == "D0") { return D0_; } else if (name == "D1") { return D1_; } else if (name == "D2") { return D2_; } else if (name == "D3") { return D3_; } else if (name == "F1") { return F1_; } else if (name == "F2") { return F2_; } else if (name == "F3") { return F3_; } else if (name == "F4") { return F4_; } else { std::cerr << "WARNING in LauRescattering2Res::getResonanceParameter: Parameter name not reconised." << std::endl; return 0; } } void LauRescattering2Res::setB1Parameter(const Double_t B1) { B1_->value( B1 ); B1_->genValue( B1 ); B1_->initValue( B1 ); } void LauRescattering2Res::setB2Parameter(const Double_t B2) { B2_->value( B2 ); B2_->genValue( B2 ); B2_->initValue( B2 ); } void LauRescattering2Res::setB3Parameter(const Double_t B3) { B3_->value( B3 ); B3_->genValue( B3 ); B3_->initValue( B3 ); } void LauRescattering2Res::setC1Parameter(const Double_t C1) { C1_->value( C1 ); C1_->genValue( C1 ); C1_->initValue( C1 ); } void LauRescattering2Res::setC2Parameter(const Double_t C2) { C2_->value( C2 ); C2_->genValue( C2 ); C2_->initValue( C2 ); } void LauRescattering2Res::setC3Parameter(const Double_t C3) { C3_->value( C3 ); C3_->genValue( C3 ); C3_->initValue( C3 ); } void LauRescattering2Res::setC4Parameter(const Double_t C4) { C4_->value( C4 ); C4_->genValue( C4 ); C4_->initValue( C4 ); } void LauRescattering2Res::setC5Parameter(const Double_t C5) { C5_->value( C5 ); C5_->genValue( C5 ); C5_->initValue( C5 ); } void LauRescattering2Res::setD0Parameter(const Double_t D0) { D0_->value( D0 ); D0_->genValue( D0 ); D0_->initValue( D0 ); } void LauRescattering2Res::setD1Parameter(const Double_t D1) { D1_->value( D1 ); D1_->genValue( D1 ); D1_->initValue( D1 ); } void LauRescattering2Res::setD2Parameter(const Double_t D2) { D2_->value( D2 ); D2_->genValue( D2 ); D2_->initValue( D2 ); } void LauRescattering2Res::setD3Parameter(const Double_t D3) { D3_->value( D3 ); D3_->genValue( D3 ); D3_->initValue( D3 ); } void LauRescattering2Res::setF1Parameter(const Double_t F1) { F1_->value( F1 ); F1_->genValue( F1 ); F1_->initValue( F1 ); } void LauRescattering2Res::setF2Parameter(const Double_t F2) { F2_->value( F2 ); F2_->genValue( F2 ); F2_->initValue( F2 ); } void LauRescattering2Res::setF3Parameter(const Double_t F3) { F3_->value( F3 ); F3_->genValue( F3 ); F3_->initValue( F3 ); } void LauRescattering2Res::setF4Parameter(const Double_t F4) { F4_->value( F4 ); F4_->genValue( F4 ); F4_->initValue( F4 ); } diff --git a/src/LauRescatteringRes.cc b/src/LauRescatteringRes.cc index f71bec5..bc503ee 100644 --- a/src/LauRescatteringRes.cc +++ b/src/LauRescatteringRes.cc @@ -1,454 +1,453 @@ /* Copyright 2018 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauRescatteringRes.cc \brief File containing implementation of LauRescatteringRes class. */ #include #include "TMath.h" #include "TSystem.h" #include "LauConstants.hh" #include "LauRescatteringRes.hh" #include "LauDaughters.hh" #include "LauParameter.hh" #include "LauResonanceInfo.hh" -ClassImp(LauRescatteringRes) LauRescatteringRes::LauRescatteringRes(LauResonanceInfo* resInfo, const LauAbsResonance::LauResonanceModel resType, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), lambdaPiPi_(0), lambdaKK_(0), Mf_(0), Ms_(0), Mprime_(0), Eps1_(0), Eps2_(0), C0_(0), model_(resType) { TString parNameBase = this->getSanitisedName(); TString lambdaPiPiName(parNameBase); lambdaPiPiName += "_lambdaPiPi"; lambdaPiPi_ = resInfo->getExtraParameter( lambdaPiPiName ); if ( lambdaPiPi_ == 0 ) { lambdaPiPi_ = new LauParameter( lambdaPiPiName, 1.0, 0.0, 10.0, kTRUE ); lambdaPiPi_->secondStage(kTRUE); resInfo->addExtraParameter( lambdaPiPi_ ); } TString lambdaKKName(parNameBase); lambdaKKName += "_lambdaKK"; lambdaKK_ = resInfo->getExtraParameter( lambdaKKName ); if ( lambdaKK_ == 0 ) { lambdaKK_ = new LauParameter( lambdaKKName, 2.8, 0.0, 10.0, kTRUE ); lambdaKK_->secondStage(kTRUE); resInfo->addExtraParameter( lambdaKK_ ); } TString MfName(parNameBase); MfName += "_Mf"; Mf_ = resInfo->getExtraParameter( MfName ); if ( Mf_ == 0 ) { Mf_ = new LauParameter( MfName, 1.32, 0.0, 10.0, kTRUE ); Mf_->secondStage(kTRUE); resInfo->addExtraParameter( Mf_ ); } TString MsName(parNameBase); MsName += "_Ms"; Ms_ = resInfo->getExtraParameter( MsName ); if ( Ms_ == 0 ) { Ms_ = new LauParameter( MsName, 0.92, 0.0, 10.0, kTRUE ); Ms_->secondStage(kTRUE); resInfo->addExtraParameter( Ms_ ); } TString MprimeName(parNameBase); MprimeName += "_Mprime"; Mprime_ = resInfo->getExtraParameter( MprimeName ); if ( Mprime_ == 0 ) { Mprime_ = new LauParameter( MprimeName, 1.5, 0.0, 10.0, kTRUE ); Mprime_->secondStage(kTRUE); resInfo->addExtraParameter( Mprime_ ); } TString Eps1Name(parNameBase); Eps1Name += "_Eps1"; Eps1_ = resInfo->getExtraParameter( Eps1Name ); if ( Eps1_ == 0 ) { Eps1_ = new LauParameter( Eps1Name, 2.4, 0.0, 10.0, kTRUE ); Eps1_->secondStage(kTRUE); resInfo->addExtraParameter( Eps1_ ); } TString Eps2Name(parNameBase); Eps2Name += "_Eps2"; Eps2_ = resInfo->getExtraParameter( Eps2Name ); if ( Eps2_ == 0 ) { Eps2_ = new LauParameter( Eps2Name, -5.5, -10.0, 10.0, kTRUE ); Eps2_->secondStage(kTRUE); resInfo->addExtraParameter( Eps2_ ); } TString C0Name(parNameBase); C0Name += "_C0"; C0_ = resInfo->getExtraParameter( C0Name ); if ( C0_ == 0 ) { C0_ = new LauParameter( C0Name, 1.3, 0.0, 10.0, kTRUE ); C0_->secondStage(kTRUE); resInfo->addExtraParameter( C0_ ); } } LauRescatteringRes::~LauRescatteringRes() { } void LauRescatteringRes::initialise() { const LauDaughters* daughters = this->getDaughters(); Int_t resPairAmpInt = this->getPairInt(); if ( daughters->gotSymmetricalDP() && resPairAmpInt != 3 ) { std::cerr << "WARNING in LauRescatteringRes::initialise : Dalitz plot is symmetric - this lineshape is not appropriate." << std::endl; std::cerr << "WARNING I think that this warning is not appropiate because Laura Simetrize at LauIsobarModel level." << std::endl; } if ( (model_ != LauAbsResonance::Rescattering) && (model_ != LauAbsResonance::RescatteringNoInter)) { std::cerr << "WARNING in LauRescatteringRes::initialise : Unknown model requested, defaulting to exponential." << std::endl; model_ = LauAbsResonance::Rescattering; } if ( (model_ != LauAbsResonance::RescatteringNoInter) && (this->getSpin() != 0) ) { std::cerr << "WARNING in LauRescatteringRes::initialise : Non-zero spin will be ignored for this model - perhaps you should use LauAbsResonance::BelleSymNRNoInter instead" << std::endl; } } LauComplex LauRescatteringRes::amplitude(const LauKinematics* kinematics) { // This function returns the complex dynamical amplitude for a Reescatering distribution o original // pelaez paper parameters Eq 2.15a [Pelaez et Yndúrain: arXiv:hep-ph/0411334v2 Mar 2005] Double_t Mprime = this->getMprime(); Double_t Mf = this->getMf(); Double_t Ms = this->getMs(); Double_t eps1 = this->getEps1(); Double_t eps2 = this->getEps2(); Double_t c0 = this->getC0(); Double_t lambPiPi = this->getLambdaPiPi(); Double_t lambKK = this->getLambdaKK(); Double_t mk = LauConstants::mK; // Calculate Mandelstam variables: s = m_13^2, t = m_23^2, u = m_12^2. Double_t s = 0; Double_t t = 0; Int_t resPairAmpInt = getPairInt(); if (resPairAmpInt == 1) { s = kinematics->getm23Sq(); t = kinematics->getm12Sq(); } else if (resPairAmpInt == 2) { s = kinematics->getm13Sq(); t = kinematics->getm23Sq(); } else if (resPairAmpInt == 3) { s = kinematics->getm12Sq(); t = kinematics->getm13Sq(); } else { std::cerr << "ERROR in LauAbsResonance::amplitude : Nonsense setup of resPairAmp array." << std::endl; gSystem->Exit(EXIT_FAILURE); } // Calculate amplitude for s variable. Double_t mass_s = TMath::Sqrt(s); Double_t k2Square_s = (s - 4.0*mk*mk)/4.0; Double_t k2Abs_s=0; if (k2Square_s > 0) k2Abs_s = TMath::Sqrt(k2Square_s); else k2Abs_s = TMath::Sqrt(-1.0*k2Square_s); Double_t cotdelta0_s = c0*(s - Ms*Ms)*(Mf*Mf - s)*k2Abs_s/(Mf*Mf*mass_s*k2Square_s); // Eq 2.15a Double_t delta0_s = TMath::ATan(1.0/cotdelta0_s); Double_t eta0_s = 1.0 - (eps1*k2Abs_s/mass_s + eps2*k2Square_s/s)*(Mprime*Mprime-s)/s; // Eq 2.15a if ((mass_s < 2.0*mk)||(mass_s > Mprime )) eta0_s = 1; Double_t mag_s = TMath::Sqrt( 1-eta0_s*eta0_s); Double_t tauRe_s = mag_s*TMath::Cos(2.0*delta0_s); Double_t tauIm_s = mag_s*TMath::Sin(2.0*delta0_s); Double_t NR1_s = 1.0/(1.0+s/(lambPiPi*lambPiPi)); Double_t NR2_s = 1.0/(1.0+s/(lambKK*lambKK)); //LauComplex resAmplitude(-tauIm_s*NR1_s*NR2_s - tauIm_t*NR1_t*NR2_t, tauRe_s*NR1_s*NR2_s + tauRe_t*NR1_t*NR2_t ); if ((model_ == LauAbsResonance::RescatteringNoInter)&&(t<=s)) { NR1_s=0.0; NR2_s=0.0; tauRe_s=0.0; tauIm_s=0.0; } LauComplex resAmplitude(-tauIm_s*NR1_s*NR2_s ,tauRe_s*NR1_s*NR2_s); return resAmplitude; } LauComplex LauRescatteringRes::resAmp(Double_t mass, Double_t spinTerm) { std::cerr << "ERROR in LauRescatteringRes : This method should never be called." << std::endl; std::cerr << " : Returning zero amplitude for mass = " << mass << " and spinTerm = " << spinTerm << "." << std::endl; return LauComplex(0.0, 0.0); } const std::vector& LauRescatteringRes::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixLambdaPiPi() ) { this->addFloatingParameter( lambdaPiPi_ ); } if ( ! this->fixLambdaKK() ) { this->addFloatingParameter( lambdaKK_ ); } if ( ! this->fixMf() ) { this->addFloatingParameter( Mf_ ); } if ( ! this->fixMs() ) { this->addFloatingParameter( Ms_ ); } if ( ! this->fixMprime() ) { this->addFloatingParameter( Mprime_ ); } if ( ! this->fixEps1() ) { this->addFloatingParameter( Eps1_ ); } if ( ! this->fixEps2() ) { this->addFloatingParameter( Eps2_ ); } if ( ! this->fixC0() ) { this->addFloatingParameter( C0_ ); } return this->getParameters(); } void LauRescatteringRes::setResonanceParameter(const TString& name, const Double_t value) { // Set various parameters for the lineshape if (name == "lambdaPiPi") { this->setLambdaPiPi(value); std::cout << "INFO in LauRescatteringRes::setResonanceParameter : Setting parameter lambdaPiPi = " << this->getLambdaPiPi() << std::endl; } else if (name == "lambdaKK") { this->setLambdaKK(value); std::cout << "INFO in LauRescatteringRes::setResonanceParameter : Setting parameter lambdaKK = " << this->getLambdaKK() << std::endl; } else if (name == "Mf") { this->setMf(value); std::cout << "INFO in LauRescatteringRes::setResonanceParameter : Setting parameter Mf = " << this->getMf() << std::endl; } else if (name == "Ms") { this->setMs(value); std::cout << "INFO in LauRescatteringRes::setResonanceParameter : Setting parameter Ms = " << this->getMs() << std::endl; } else if (name == "Mprime") { this->setMprime(value); std::cout << "INFO in LauRescatteringRes::setResonanceParameter : Setting parameter Mprime = " << this->getMprime() << std::endl; } else if (name == "Eps1") { this->setEps1(value); std::cout << "INFO in LauRescatteringRes::setResonanceParameter : Setting parameter eps1 = " << this->getEps1() << std::endl; } else if (name == "Eps2") { this->setEps2(value); std::cout << "INFO in LauRescatteringRes::setResonanceParameter : Setting parameter eps2 = " << this->getEps2() << std::endl; } else if (name == "C0") { this->setC0(value); std::cout << "INFO in LauRescatteringRes::setResonanceParameter : Setting parameter eps2 = " << this->getC0() << std::endl; } else { std::cerr << "WARNING in LauRescatteringRes::setResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } void LauRescatteringRes::floatResonanceParameter(const TString& name) { if (name == "lambdaPiPi") { if ( lambdaPiPi_->fixed() ) { lambdaPiPi_->fixed( kFALSE ); this->addFloatingParameter( lambdaPiPi_ ); } else { std::cerr << "WARNING in LauRescatteringRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "lambdaKK") { if ( lambdaKK_->fixed() ) { lambdaKK_->fixed( kFALSE ); this->addFloatingParameter( lambdaKK_ ); } else { std::cerr << "WARNING in LauRescatteringRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "Mf") { if ( Mf_->fixed() ) { Mf_->fixed( kFALSE ); this->addFloatingParameter( Mf_ ); } else { std::cerr << "WARNING in LauRescatteringRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "Ms") { if ( Ms_->fixed() ) { Ms_->fixed( kFALSE ); this->addFloatingParameter( Ms_ ); } else { std::cerr << "WARNING in LauRescatteringRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "Mprime") { if ( Mprime_->fixed() ) { Mprime_->fixed( kFALSE ); this->addFloatingParameter( Mprime_ ); } else { std::cerr << "WARNING in LauRescatteringRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "Eps1") { if ( Eps1_->fixed() ) { Eps1_->fixed( kFALSE ); this->addFloatingParameter( Eps1_ ); } else { std::cerr << "WARNING in LauRescatteringRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "Eps2") { if ( Eps2_->fixed() ) { Eps2_->fixed( kFALSE ); this->addFloatingParameter( Eps2_ ); } else { std::cerr << "WARNING in LauRescatteringRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "C0") { if ( C0_->fixed() ) { C0_->fixed( kFALSE ); this->addFloatingParameter( C0_ ); } else { std::cerr << "WARNING in LauRescatteringRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else { std::cerr << "WARNING in LauRescatteringRes::fixResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } LauParameter* LauRescatteringRes::getResonanceParameter(const TString& name) { if (name == "lambdaPiPi") { return lambdaPiPi_; } else if (name == "lambdaKK") { return lambdaKK_; } if (name == "Mf") { return Mf_; } else if (name == "Ms") { return Ms_; } if (name == "Mprime") { return Mprime_; } if (name == "Eps1") { return Eps1_; } if (name == "Eps2") { return Eps2_; } if (name == "C0") { return C0_; } else { std::cerr << "WARNING in LauRescatteringRes::getResonanceParameter: Parameter name not reconised." << std::endl; return 0; } } void LauRescatteringRes::setLambdaPiPi(const Double_t lambda) { lambdaPiPi_->value( lambda ); lambdaPiPi_->genValue( lambda ); lambdaPiPi_->initValue( lambda ); } void LauRescatteringRes::setLambdaKK(const Double_t lambda) { lambdaKK_->value( lambda ); lambdaKK_->genValue( lambda ); lambdaKK_->initValue( lambda ); } void LauRescatteringRes::setMf(const Double_t Mf) { Mf_->value( Mf ); Mf_->genValue( Mf ); Mf_->initValue( Mf ); } void LauRescatteringRes::setMs(const Double_t Ms) { Ms_->value( Ms ); Ms_->genValue( Ms ); Ms_->initValue( Ms ); } void LauRescatteringRes::setMprime(const Double_t Mprime) { Mprime_->value( Mprime ); Mprime_->genValue( Mprime); Mprime_->initValue( Mprime ); } void LauRescatteringRes::setEps1(const Double_t Eps1) { Eps1_->value( Eps1 ); Eps1_->genValue( Eps1 ); Eps1_->initValue( Eps1 ); } void LauRescatteringRes::setEps2(const Double_t Eps2) { Eps2_->value( Eps2 ); Eps2_->genValue( Eps2 ); Eps2_->initValue( Eps2 ); } void LauRescatteringRes::setC0(const Double_t C0) { C0_->value( C0 ); C0_->genValue( C0 ); C0_->initValue( C0 ); } diff --git a/src/LauResonanceInfo.cc b/src/LauResonanceInfo.cc index fbb9e59..b2b4504 100644 --- a/src/LauResonanceInfo.cc +++ b/src/LauResonanceInfo.cc @@ -1,212 +1,211 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauResonanceInfo.cc \brief File containing implementation of LauResonanceInfo class. */ #include #include "LauParameter.hh" #include "LauResonanceInfo.hh" -ClassImp(LauResonanceInfo) LauResonanceInfo::LauResonanceInfo(const TString& name, const Double_t mass, const Double_t width, const Int_t spin, const Int_t charge, const LauBlattWeisskopfFactor::BlattWeisskopfCategory bwCategory, const Double_t bwRadius) : name_(name), sanitisedName_(""), mass_(0), width_(0), spin_(spin), charge_(charge), bwCategory_(bwCategory), bwRadius_(bwRadius), conjugate_(0), extraPars_() { this->sanitiseName(); mass_ = new LauParameter(sanitisedName_+"_MASS",mass,0.0,3.0*mass,kTRUE); mass_->secondStage(kTRUE); width_ = new LauParameter(sanitisedName_+"_WIDTH",width,0.0,3.0*width,kTRUE); width_->secondStage(kTRUE); } LauResonanceInfo::~LauResonanceInfo() { delete mass_; mass_ = 0; delete width_; width_ = 0; for ( std::set::iterator iter = extraPars_.begin(); iter != extraPars_.end(); ++iter ) { delete (*iter); } extraPars_.clear(); } LauResonanceInfo::LauResonanceInfo( const LauResonanceInfo& other, const TString& newName, const Int_t newCharge ) : name_(newName), sanitisedName_(""), mass_(0), width_(0), spin_(other.spin_), charge_(newCharge), bwCategory_(other.bwCategory_), bwRadius_(other.bwRadius_), conjugate_(0), extraPars_() { this->sanitiseName(); mass_ = other.mass_->createClone( sanitisedName_+"_MASS" ); width_ = other.width_->createClone( sanitisedName_+"_WIDTH" ); for ( std::set::iterator iter = other.extraPars_.begin(); iter != other.extraPars_.end(); ++iter ) { TString parName = (*iter)->name(); parName.Remove(0, parName.Last('_')); parName.Prepend( sanitisedName_ ); LauParameter* par = (*iter)->createClone( parName ); extraPars_.insert( par ); } } LauResonanceInfo* LauResonanceInfo::createChargeConjugate() { Int_t newCharge = -charge_; TString newName( name_ ); Ssiz_t index = newName.Index("+"); if ( index != -1 ) { newName.Replace( index, 1, "-" ); } else { index = newName.Index("-"); if ( index != -1 ) { newName.Replace( index, 1, "+" ); } } LauResonanceInfo* conjugate = new LauResonanceInfo( *this, newName, newCharge ); conjugate->conjugate_ = this; this->conjugate_ = conjugate; return conjugate; } LauResonanceInfo* LauResonanceInfo::createSharedParameterRecord( const TString& name ) { LauResonanceInfo* newinfo = new LauResonanceInfo( *this, name, charge_ ); sharedParRecords_.push_back(newinfo); return newinfo; } LauParameter* LauResonanceInfo::getExtraParameter( const TString& parName ) { LauParameter* par(0); for ( std::set::iterator iter = extraPars_.begin(); iter != extraPars_.end(); ++iter ) { if ( (*iter)->name() == parName ) { par = (*iter); } } return par; } void LauResonanceInfo::addExtraParameter( LauParameter* param, const Bool_t independentPar ) { bool ok = extraPars_.insert( param ).second; if ( !ok ) { std::cerr << "WARNING in LauResonanceInfo::addExtraParameter : parameter already present, not adding again" << std::endl; return; } if ( conjugate_ != 0 ) { conjugate_->addCloneOfExtraParameter( param, independentPar ); } for ( std::vector::iterator iter = sharedParRecords_.begin(); iter != sharedParRecords_.end(); ++iter ) { (*iter)->addCloneOfExtraParameter( param, independentPar ); } } void LauResonanceInfo::addCloneOfExtraParameter( LauParameter* param, const Bool_t copyNotClone ) { TString parName = param->name(); parName.Remove(0, parName.Last('_')); parName.Prepend( sanitisedName_ ); LauParameter* cloneParam(0); if ( copyNotClone ) { cloneParam = new LauParameter( parName, param->unblindValue(), param->minValue(), param->maxValue(), param->fixed() ); cloneParam->secondStage(kTRUE); } else { cloneParam = param->createClone( parName ); } extraPars_.insert( cloneParam ); } std::ostream& operator<<( std::ostream& stream, const LauResonanceInfo& infoRecord ) { stream << infoRecord.getName() << ": "; stream << "mass = " << infoRecord.getMass()->value() << ", "; stream << "width = " << infoRecord.getWidth()->value() << ", "; stream << "spin = " << infoRecord.getSpin() << ", "; Int_t charge = infoRecord.getCharge(); if ( charge < 0 ) { stream << "charge = " << infoRecord.getCharge() << ", "; } else { stream << "charge = " << infoRecord.getCharge() << ", "; } stream << "BW radius = " << infoRecord.getBWRadius(); return stream; } void LauResonanceInfo::sanitiseName() { sanitisedName_ = name_; sanitisedName_ = sanitisedName_.ReplaceAll("+","p"); sanitisedName_ = sanitisedName_.ReplaceAll("-","m"); sanitisedName_ = sanitisedName_.ReplaceAll("*","st"); sanitisedName_ = sanitisedName_.ReplaceAll("(","_"); sanitisedName_ = sanitisedName_.ReplaceAll(")","_"); sanitisedName_ = sanitisedName_.ReplaceAll("[","_"); sanitisedName_ = sanitisedName_.ReplaceAll("]","_"); sanitisedName_ = sanitisedName_.ReplaceAll("<","_"); sanitisedName_ = sanitisedName_.ReplaceAll(">","_"); sanitisedName_ = sanitisedName_.ReplaceAll("{","_"); sanitisedName_ = sanitisedName_.ReplaceAll("}","_"); sanitisedName_ = sanitisedName_.ReplaceAll(" ","_"); sanitisedName_ = sanitisedName_.ReplaceAll("$",""); sanitisedName_ = sanitisedName_.ReplaceAll("%",""); sanitisedName_ = sanitisedName_.ReplaceAll("&",""); sanitisedName_ = sanitisedName_.ReplaceAll("/",""); sanitisedName_ = sanitisedName_.ReplaceAll(":",""); sanitisedName_ = sanitisedName_.ReplaceAll(";",""); sanitisedName_ = sanitisedName_.ReplaceAll("=",""); sanitisedName_ = sanitisedName_.ReplaceAll("\\",""); sanitisedName_ = sanitisedName_.ReplaceAll("^",""); sanitisedName_ = sanitisedName_.ReplaceAll("|",""); sanitisedName_ = sanitisedName_.ReplaceAll(",",""); sanitisedName_ = sanitisedName_.ReplaceAll(".",""); sanitisedName_.Remove(TString::kBoth,'_'); } diff --git a/src/LauResonanceMaker.cc b/src/LauResonanceMaker.cc index bbf5cbd..c5167b7 100644 --- a/src/LauResonanceMaker.cc +++ b/src/LauResonanceMaker.cc @@ -1,996 +1,995 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauResonanceMaker.cc \brief File containing implementation of LauResonanceMaker class. */ #include #include "LauAbsResonance.hh" #include "LauBelleNR.hh" #include "LauBelleSymNR.hh" #include "LauBreitWignerRes.hh" #include "LauDabbaRes.hh" #include "LauDaughters.hh" #include "LauEFKLLMRes.hh" #include "LauFlatteRes.hh" #include "LauFlatNR.hh" #include "LauGaussIncohRes.hh" #include "LauGounarisSakuraiRes.hh" #include "LauKappaRes.hh" #include "LauLASSRes.hh" #include "LauLASSBWRes.hh" #include "LauLASSNRRes.hh" #include "LauModIndPartWaveMagPhase.hh" #include "LauModIndPartWaveRealImag.hh" #include "LauNRAmplitude.hh" #include "LauRescatteringRes.hh" #include "LauRescattering2Res.hh" #include "LauPolNR.hh" #include "LauPoleRes.hh" #include "LauPolarFormFactorNR.hh" #include "LauPolarFormFactorSymNR.hh" #include "LauRelBreitWignerRes.hh" #include "LauResonanceInfo.hh" #include "LauResonanceMaker.hh" #include "LauRhoOmegaMix.hh" #include "LauSigmaRes.hh" -ClassImp(LauResonanceMaker); LauResonanceMaker* LauResonanceMaker::resonanceMaker_ = 0; LauResonanceMaker::LauResonanceMaker() : nResDefMax_(0), bwBarrierType_(LauBlattWeisskopfFactor::BWPrimeBarrier), bwRestFrame_(LauBlattWeisskopfFactor::ResonanceFrame), spinFormalism_(LauAbsResonance::Zemach_P), summaryPrinted_(kFALSE) { this->createResonanceVector(); this->setDefaultBWRadius( LauBlattWeisskopfFactor::Parent, 4.0 ); } LauResonanceMaker::~LauResonanceMaker() { for ( std::vector::iterator iter = bwIndepFactors_.begin(); iter != bwIndepFactors_.end(); ++iter ) { delete *iter; } bwIndepFactors_.clear(); for ( BWFactorCategoryMap::iterator iter = bwFactors_.begin(); iter != bwFactors_.end(); ++iter ) { delete iter->second.bwFactor_; } bwFactors_.clear(); } LauResonanceMaker& LauResonanceMaker::get() { if ( resonanceMaker_ == 0 ) { resonanceMaker_ = new LauResonanceMaker(); } return *resonanceMaker_; } void LauResonanceMaker::createResonanceVector() { // Function to create all possible resonances that this class supports. // Also add in the sigma and kappa - but a special paramterisation is used // instead of the PDG "pole mass and width" values. std::cout << "INFO in LauResonanceMaker::createResonanceVector : Setting up possible resonance states..." << std::endl; LauResonanceInfo* neutral(0); LauResonanceInfo* positve(0); LauResonanceInfo* negatve(0); // Define the resonance names and store them in the array resInfo_.clear(); resInfo_.reserve(100); // rho resonances name, mass, width, spin, charge, default BW category, BW radius parameter (defaults to 4.0) // rho(770) neutral = new LauResonanceInfo("rho0(770)", 0.77526, 0.1478, 1, 0, LauBlattWeisskopfFactor::Light, 5.3); positve = new LauResonanceInfo("rho+(770)", 0.77511, 0.1491, 1, 1, LauBlattWeisskopfFactor::Light, 5.3); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // The following two lines of code are placed here in order to allow the following, rather niche, scenario: // The LauRhoOmegaMix code permits (through the use of the optional independentPar argument of LauResonanceInfo::addExtraParameter) the magnitude and phase of the rho/omega mixing to potentially differ between the decay of the parent particle to rho0 X and the parent antiparticle to rho0 Xbar. // This can be acheived by using the rho0(770) record in one case and the rho0(770)_COPY record in the other. neutral = neutral->createSharedParameterRecord("rho0(770)_COPY"); resInfo_.push_back( neutral ); // rho(1450) neutral = new LauResonanceInfo("rho0(1450)", 1.465, 0.400, 1, 0, LauBlattWeisskopfFactor::Light ); positve = new LauResonanceInfo("rho+(1450)", 1.465, 0.400, 1, 1, LauBlattWeisskopfFactor::Light ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // rho_3(1690) neutral = new LauResonanceInfo("rho0_3(1690)", 1.686, 0.186, 3, 0, LauBlattWeisskopfFactor::Light ); positve = new LauResonanceInfo("rho+_3(1690)", 1.686, 0.186, 3, 1, LauBlattWeisskopfFactor::Light ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // rho(1700) neutral = new LauResonanceInfo("rho0(1700)", 1.720, 0.250, 1, 0, LauBlattWeisskopfFactor::Light ); positve = new LauResonanceInfo("rho+(1700)", 1.720, 0.250, 1, 1, LauBlattWeisskopfFactor::Light ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // rho(1900) neutral = new LauResonanceInfo("rho0(1900)", 1.909, 0.130, 1, 0, LauBlattWeisskopfFactor::Light ); positve = new LauResonanceInfo("rho+(1900)", 1.909, 0.130, 1, 1, LauBlattWeisskopfFactor::Light ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // rho_3(1990) neutral = new LauResonanceInfo("rho0_3(1990)", 1.982, 0.188, 3, 0, LauBlattWeisskopfFactor::Light ); positve = new LauResonanceInfo("rho+_3(1990)", 1.982, 0.188, 3, 1, LauBlattWeisskopfFactor::Light ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // K* resonances name, mass, width, spin, charge, BW category, BW radius parameter (defaults to 4.0) // K*(892) neutral = new LauResonanceInfo("K*0(892)", 0.89581, 0.0474, 1, 0, LauBlattWeisskopfFactor::Kstar, 3.0); positve = new LauResonanceInfo("K*+(892)", 0.89166, 0.0508, 1, 1, LauBlattWeisskopfFactor::Kstar, 3.0); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // K*(1410) neutral = new LauResonanceInfo("K*0(1410)", 1.414, 0.232, 1, 0, LauBlattWeisskopfFactor::Kstar ); positve = new LauResonanceInfo("K*+(1410)", 1.414, 0.232, 1, 1, LauBlattWeisskopfFactor::Kstar ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // K*_0(1430) neutral = new LauResonanceInfo("K*0_0(1430)", 1.425, 0.270, 0, 0, LauBlattWeisskopfFactor::Kstar ); positve = new LauResonanceInfo("K*+_0(1430)", 1.425, 0.270, 0, 1, LauBlattWeisskopfFactor::Kstar ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // LASS nonresonant model neutral = neutral->createSharedParameterRecord("LASSNR0"); positve = positve->createSharedParameterRecord("LASSNR+"); negatve = negatve->createSharedParameterRecord("LASSNR-"); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // K*_2(1430) neutral = new LauResonanceInfo("K*0_2(1430)", 1.4324, 0.109, 2, 0, LauBlattWeisskopfFactor::Kstar ); positve = new LauResonanceInfo("K*+_2(1430)", 1.4256, 0.0985, 2, 1, LauBlattWeisskopfFactor::Kstar ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // K*(1680) neutral = new LauResonanceInfo("K*0(1680)", 1.717, 0.322, 1, 0, LauBlattWeisskopfFactor::Kstar ); positve = new LauResonanceInfo("K*+(1680)", 1.717, 0.322, 1, 1, LauBlattWeisskopfFactor::Kstar ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // K*(1950) neutral = new LauResonanceInfo("K*0_0(1950)", 1.945, 0.201, 0, 0, LauBlattWeisskopfFactor::Kstar ); positve = new LauResonanceInfo("K*+_0(1950)", 1.945, 0.201, 0, 1, LauBlattWeisskopfFactor::Kstar ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // phi resonances name, mass, width, spin, charge, BW category, BW radius parameter (defaults to 4.0) // phi(1020) neutral = new LauResonanceInfo("phi(1020)", 1.019461, 0.004266, 1, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // phi(1680) neutral = new LauResonanceInfo("phi(1680)", 1.680, 0.150, 1, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // f resonances name, mass, width, spin, charge, BW category, BW radius parameter (defaults to 4.0) // f_0(980) neutral = new LauResonanceInfo("f_0(980)", 0.990, 0.070, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // f_2(1270) neutral = new LauResonanceInfo("f_2(1270)", 1.2751, 0.1851, 2, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // f_0(1370) neutral = new LauResonanceInfo("f_0(1370)", 1.370, 0.350, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // f'_0(1300), from Belle's Kspipi paper neutral = new LauResonanceInfo("f'_0(1300)", 1.449, 0.126, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // f_2(1430) neutral = new LauResonanceInfo("f_2(1430)", 1.430, 0.150, 2, 0, LauBlattWeisskopfFactor::Light ); // PDG width in the range 13 - 150 resInfo_.push_back( neutral ); // f_0(1500) neutral = new LauResonanceInfo("f_0(1500)", 1.505, 0.109, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // f'_2(1525) neutral = new LauResonanceInfo("f'_2(1525)", 1.525, 0.073, 2, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // f_2(1565) neutral = new LauResonanceInfo("f_2(1565)", 1.562, 0.134, 2, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // f_2(1640) neutral = new LauResonanceInfo("f_2(1640)", 1.639, 0.099, 2, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // f_0(1710) neutral = new LauResonanceInfo("f_0(1710)", 1.722, 0.135, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // f_2(1810) neutral = new LauResonanceInfo("f_2(1810)", 1.816, 0.197, 2, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // f_2(1910) neutral = new LauResonanceInfo("f_2(1910)", 1.903, 0.196, 2, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // f_2(1950) neutral = new LauResonanceInfo("f_2(1950)", 1.944, 0.472, 2, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // f_2(2010) neutral = new LauResonanceInfo("f_2(2010)", 2.011, 0.202, 2, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // f_0(2020) neutral = new LauResonanceInfo("f_0(2020)", 1.992, 0.442, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // f_4(2050) neutral = new LauResonanceInfo("f_4(2050)", 2.018, 0.237, 4, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // f_0(2100) neutral = new LauResonanceInfo("f_0(2100)", 2.101, 0.224, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // omega resonances name, mass, width, spin, charge, BW category, BW radius parameter (defaults to 4.0) // omega(782) neutral = new LauResonanceInfo("omega(782)", 0.78265, 0.00849, 1, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // a resonances name, mass, width, spin, charge, BW category, BW radius parameter (defaults to 4.0) // a_0(980) neutral = new LauResonanceInfo("a0_0(980)", 0.980, 0.092, 0, 0, LauBlattWeisskopfFactor::Light ); positve = new LauResonanceInfo("a+_0(980)", 0.980, 0.092, 0, 1, LauBlattWeisskopfFactor::Light ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // a_0(1450) neutral = new LauResonanceInfo("a0_0(1450)", 1.474, 0.265, 0, 0, LauBlattWeisskopfFactor::Light ); positve = new LauResonanceInfo("a+_0(1450)", 1.474, 0.265, 0, 1, LauBlattWeisskopfFactor::Light ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // a_2(1320) neutral = new LauResonanceInfo("a0_2(1320)", 1.3190, 0.1050, 2, 0, LauBlattWeisskopfFactor::Light ); positve = new LauResonanceInfo("a+_2(1320)", 1.3190, 0.1050, 2, 1, LauBlattWeisskopfFactor::Light ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // charmonium resonances name, mass, width, spin, charge, BW category, BW radius parameter (defaults to 4.0) // chi_c0 neutral = new LauResonanceInfo("chi_c0", 3.41475, 0.0105, 0, 0, LauBlattWeisskopfFactor::Charmonium ); resInfo_.push_back( neutral ); // chi_c1 neutral = new LauResonanceInfo("chi_c1", 3.51066, 0.00084, 0, 0, LauBlattWeisskopfFactor::Charmonium ); resInfo_.push_back( neutral ); // chi_c2 neutral = new LauResonanceInfo("chi_c2", 3.55620, 0.00193, 2, 0, LauBlattWeisskopfFactor::Charmonium ); resInfo_.push_back( neutral ); // psi(3770) neutral = new LauResonanceInfo("psi(3770)", 3.77313, 0.0272, 1, 0, LauBlattWeisskopfFactor::Charmonium ); resInfo_.push_back( neutral ); // X(3872) neutral = new LauResonanceInfo("X(3872)", 3.87169, 0.0012, 1, 0, LauBlattWeisskopfFactor::Charmonium ); resInfo_.push_back( neutral ); // chi_c2(2P) neutral = new LauResonanceInfo("chi_c2(2P)", 3.9272, 0.024, 2, 0, LauBlattWeisskopfFactor::Charmonium ); resInfo_.push_back( neutral ); // unknown scalars name, mass, width, spin, charge, BW category, BW radius parameter (defaults to 4.0) // sigma neutral = new LauResonanceInfo("sigma0", 0.475, 0.550, 0, 0, LauBlattWeisskopfFactor::Light ); positve = new LauResonanceInfo("sigma+", 0.475, 0.550, 0, 1, LauBlattWeisskopfFactor::Light ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // kappa neutral = new LauResonanceInfo("kappa0", 0.682, 0.547, 0, 0, LauBlattWeisskopfFactor::Kstar ); positve = new LauResonanceInfo("kappa+", 0.682, 0.547, 0, 1, LauBlattWeisskopfFactor::Kstar ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // dabba neutral = new LauResonanceInfo("dabba0", 2.098, 0.520, 0, 0, LauBlattWeisskopfFactor::Charm ); positve = new LauResonanceInfo("dabba+", 2.098, 0.520, 0, 1, LauBlattWeisskopfFactor::Charm ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // excited charm states name, mass, width, spin, charge, BW category, BW radius parameter (defaults to 4.0) // D* neutral = new LauResonanceInfo("D*0", 2.00696, 0.0021, 1, 0, LauBlattWeisskopfFactor::Charm ); positve = new LauResonanceInfo("D*+", 2.01026, 83.4e-6, 1, 1, LauBlattWeisskopfFactor::Charm ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // D*_0 neutral = new LauResonanceInfo("D*0_0", 2.318, 0.267, 0, 0, LauBlattWeisskopfFactor::Charm ); positve = new LauResonanceInfo("D*+_0", 2.403, 0.283, 0, 1, LauBlattWeisskopfFactor::Charm ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // D*_2 //AVERAGE--neutral = new LauResonanceInfo("D*0_2", 2.4618, 0.049, 2, 0 ); neutral = new LauResonanceInfo("D*0_2", 2.4626, 0.049, 2, 0, LauBlattWeisskopfFactor::Charm ); positve = new LauResonanceInfo("D*+_2", 2.4643, 0.037, 2, 1, LauBlattWeisskopfFactor::Charm ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // D1(2420) neutral = new LauResonanceInfo("D0_1(2420)", 2.4214, 0.0274, 1, 0, LauBlattWeisskopfFactor::Charm ); positve = new LauResonanceInfo("D+_1(2420)", 2.4232, 0.025, 1, 1, LauBlattWeisskopfFactor::Charm ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // D(2600) //OLD--neutral = new LauResonanceInfo("D0(2600)", 2.6087, 0.093, 0, 0 ); //OLD--positve = new LauResonanceInfo("D+(2600)", 2.6213, 0.093, 0, 1 ); neutral = new LauResonanceInfo("D0(2600)", 2.612, 0.093, 0, 0, LauBlattWeisskopfFactor::Charm ); positve = new LauResonanceInfo("D+(2600)", 2.612, 0.093, 0, 1, LauBlattWeisskopfFactor::Charm ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // D(2760) //OLD-- neutral = new LauResonanceInfo("D0(2760)", 2.7633, 0.061, 1, 0 ); //OLD-- positve = new LauResonanceInfo("D+(2760)", 2.7697, 0.061, 1, 1 ); neutral = new LauResonanceInfo("D0(2760)", 2.761, 0.063, 1, 0, LauBlattWeisskopfFactor::Charm ); positve = new LauResonanceInfo("D+(2760)", 2.761, 0.063, 1, 1, LauBlattWeisskopfFactor::Charm ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // D(2900) neutral = new LauResonanceInfo("D0(3000)", 3.0, 0.15, 0, 0, LauBlattWeisskopfFactor::Charm ); resInfo_.push_back( neutral ); // D(3400) neutral = new LauResonanceInfo("D0(3400)", 3.4, 0.15, 0, 0, LauBlattWeisskopfFactor::Charm ); resInfo_.push_back( neutral ); // excited strange charm name, mass, width, spin, charge, BW category, BW radius parameter (defaults to 4.0) // Ds* positve = new LauResonanceInfo("Ds*+", 2.1121, 0.0019, 1, 1, LauBlattWeisskopfFactor::StrangeCharm ); negatve = positve->createChargeConjugate(); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // Ds0*(2317) positve = new LauResonanceInfo("Ds*+_0(2317)", 2.3177, 0.0038, 0, 1, LauBlattWeisskopfFactor::StrangeCharm ); negatve = positve->createChargeConjugate(); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // Ds2*(2573) positve = new LauResonanceInfo("Ds*+_2(2573)", 2.5719, 0.017, 2, 1, LauBlattWeisskopfFactor::StrangeCharm ); negatve = positve->createChargeConjugate(); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // Ds1*(2700) positve = new LauResonanceInfo("Ds*+_1(2700)", 2.709, 0.117, 1, 1, LauBlattWeisskopfFactor::StrangeCharm ); negatve = positve->createChargeConjugate(); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // Ds1*(2860) positve = new LauResonanceInfo("Ds*+_1(2860)", 2.862, 0.180, 1, 1, LauBlattWeisskopfFactor::StrangeCharm ); negatve = positve->createChargeConjugate(); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // Ds3*(2860) positve = new LauResonanceInfo("Ds*+_3(2860)", 2.862, 0.058, 3, 1, LauBlattWeisskopfFactor::StrangeCharm ); negatve = positve->createChargeConjugate(); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // excited bottom states name, mass, width, spin, charge, BW category, BW radius parameter (defaults to 4.0) // B* neutral = new LauResonanceInfo("B*0", 5.3252, 0.00, 1, 0, LauBlattWeisskopfFactor::Beauty, 6.0); positve = new LauResonanceInfo("B*+", 5.3252, 0.00, 1, 1, LauBlattWeisskopfFactor::Beauty, 6.0); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // excited strange bottom name, mass, width, spin, charge, BW category, BW radius parameter (defaults to 4.0) // Bs* neutral = new LauResonanceInfo("Bs*0", 5.4154, 0.00, 1, 0, LauBlattWeisskopfFactor::StrangeBeauty, 6.0); resInfo_.push_back( neutral ); // nonresonant models name, mass, width, spin, charge, BW category, BW radius parameter (defaults to 4.0) // Phase-space nonresonant model neutral = new LauResonanceInfo("NonReson", 0.0, 0.0, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // Theory-based nonresonant model neutral = new LauResonanceInfo("NRModel", 0.0, 0.0, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // Belle nonresonant models neutral = new LauResonanceInfo("BelleSymNR", 0.0, 0.0, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); neutral = new LauResonanceInfo("BelleNR", 0.0, 0.0, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); positve = new LauResonanceInfo("BelleNR+", 0.0, 0.0, 0, 1, LauBlattWeisskopfFactor::Light ); negatve = positve->createChargeConjugate(); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); neutral = new LauResonanceInfo("BelleNR_Swave", 0.0, 0.0, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); positve = new LauResonanceInfo("BelleNR_Swave+",0.0, 0.0, 0, 1, LauBlattWeisskopfFactor::Light ); negatve = positve->createChargeConjugate(); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); neutral = new LauResonanceInfo("BelleNR_Pwave", 0.0, 0.0, 1, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); positve = new LauResonanceInfo("BelleNR_Pwave+",0.0, 0.0, 1, 1, LauBlattWeisskopfFactor::Light ); negatve = positve->createChargeConjugate(); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); neutral = new LauResonanceInfo("BelleNR_Dwave", 0.0, 0.0, 2, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); positve = new LauResonanceInfo("BelleNR_Dwave+",0.0, 0.0, 2, 1, LauBlattWeisskopfFactor::Light ); negatve = positve->createChargeConjugate(); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); neutral = new LauResonanceInfo("BelleNR_Fwave", 0.0, 0.0, 3, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); positve = new LauResonanceInfo("BelleNR_Fwave+",0.0, 0.0, 3, 1, LauBlattWeisskopfFactor::Light ); negatve = positve->createChargeConjugate(); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // Taylor expansion nonresonant model neutral = new LauResonanceInfo("NRTaylor", 0.0, 0.0, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // Polynomial nonresonant models neutral = new LauResonanceInfo("PolNR_S0", 0.0, 0.0, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); neutral = new LauResonanceInfo("PolNR_S1", 0.0, 0.0, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); neutral = new LauResonanceInfo("PolNR_S2", 0.0, 0.0, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); neutral = new LauResonanceInfo("PolNR_P0", 0.0, 0.0, 1, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); neutral = new LauResonanceInfo("PolNR_P1", 0.0, 0.0, 1, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); neutral = new LauResonanceInfo("PolNR_P2", 0.0, 0.0, 1, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // Fake resonances for S-Wave splines neutral = new LauResonanceInfo("Spline_S0", 0.0, 0.0, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); neutral = new LauResonanceInfo("Spline_S0_Bar", 0.0, 0.0, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // Polar Form Factor nonresonant model neutral = new LauResonanceInfo("PolarFFSymNR", 0.0, 0.0, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); neutral = new LauResonanceInfo("PolarFFNR", 0.0, 0.0, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // PiPi-KK Inelastic Scattering neutral = new LauResonanceInfo("Rescattering", 0.0, 0.0, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); nResDefMax_ = resInfo_.size(); } void LauResonanceMaker::setBWType(const LauBlattWeisskopfFactor::BarrierType bwType) { // Check whether any BW factors have been created and bail out if so if ( ! bwIndepFactors_.empty() ) { std::cerr << "ERROR in LauResonanceMaker::setBWType : some barrier factors have already been created - cannot change the barrier type now!" << std::endl; return; } for ( BWFactorCategoryMap::const_iterator iter = bwFactors_.begin(); iter != bwFactors_.end(); ++iter ) { if ( iter->second.bwFactor_ != 0 ) { std::cerr << "ERROR in LauResonanceMaker::setBWType : some barrier factors have already been created - cannot change the barrier type now!" << std::endl; return; } } bwBarrierType_ = bwType; } void LauResonanceMaker::setBWBachelorRestFrame(const LauBlattWeisskopfFactor::RestFrame restFrame) { // Check whether any BW factors have been created and bail out if so if ( ! bwIndepFactors_.empty() ) { std::cerr << "ERROR in LauResonanceMaker::setBWBachelorRestFrame : some barrier factors have already been created - cannot change the rest frame now!" << std::endl; return; } for ( BWFactorCategoryMap::const_iterator iter = bwFactors_.begin(); iter != bwFactors_.end(); ++iter ) { if ( iter->second.bwFactor_ != 0 ) { std::cerr << "ERROR in LauResonanceMaker::setBWBachelorRestFrame : some barrier factors have already been created - cannot change the rest frame now!" << std::endl; return; } } bwRestFrame_ = restFrame; } void LauResonanceMaker::setSpinFormalism(const LauAbsResonance::LauSpinType spinType) { if ( summaryPrinted_ ) { std::cerr << "ERROR in LauResonanceMaker::setSpinFormalism : cannot redefine the spin formalism after creating one or more resonances" << std::endl; return; } spinFormalism_ = spinType; } void LauResonanceMaker::setDefaultBWRadius(const LauBlattWeisskopfFactor::BlattWeisskopfCategory bwCategory, const Double_t bwRadius) { if ( bwCategory == LauBlattWeisskopfFactor::Default || bwCategory == LauBlattWeisskopfFactor::Indep ) { std::cerr << "WARNING in LauResonanceMaker::setDefaultBWRadius : cannot set radius values for Default or Indep categories" << std::endl; return; } // Check if we have an information object for this category BWFactorCategoryMap::iterator factor_iter = bwFactors_.find( bwCategory ); if ( factor_iter != bwFactors_.end() ) { // If so, we can set the value in the information object BlattWeisskopfCategoryInfo& categoryInfo = factor_iter->second; categoryInfo.defaultRadius_ = bwRadius; // Then we can check if a LauBlattWeisskopfFactor object has been created for this category LauBlattWeisskopfFactor* bwFactor = categoryInfo.bwFactor_; if ( bwFactor != 0 ) { // If it has then we can also set its radius value directly LauParameter* radius = bwFactor->getRadiusParameter(); radius->value(bwRadius); radius->initValue(bwRadius); radius->genValue(bwRadius); } } else { // If not then we just store the value to be used later BlattWeisskopfCategoryInfo& categoryInfo = bwFactors_[bwCategory]; categoryInfo.bwFactor_ = 0; categoryInfo.defaultRadius_ = bwRadius; categoryInfo.radiusFixed_ = kTRUE; } } void LauResonanceMaker::fixBWRadius(const LauBlattWeisskopfFactor::BlattWeisskopfCategory bwCategory, const Bool_t fixRadius) { if ( bwCategory == LauBlattWeisskopfFactor::Default || bwCategory == LauBlattWeisskopfFactor::Indep ) { std::cerr << "WARNING in LauResonanceMaker::fixBWRadius : cannot fix/float radius values for Default or Indep categories" << std::endl; return; } // Check if we have an information object for this category BWFactorCategoryMap::iterator factor_iter = bwFactors_.find( bwCategory ); if ( factor_iter != bwFactors_.end() ) { // If so, we can set the value in the information object BlattWeisskopfCategoryInfo& categoryInfo = factor_iter->second; categoryInfo.radiusFixed_ = fixRadius; // Then we can check if a LauBlattWeisskopfFactor object has been created for this category LauBlattWeisskopfFactor* bwFactor = categoryInfo.bwFactor_; if ( bwFactor != 0 ) { // If it has then we can also fix/float its radius value directly LauParameter* radius = bwFactor->getRadiusParameter(); radius->fixed(fixRadius); } } else { // If not then we just store the value to be used later BlattWeisskopfCategoryInfo& categoryInfo = bwFactors_[bwCategory]; categoryInfo.bwFactor_ = 0; categoryInfo.defaultRadius_ = -1.0; categoryInfo.radiusFixed_ = fixRadius; } } LauBlattWeisskopfFactor* LauResonanceMaker::getBWFactor( const LauBlattWeisskopfFactor::BlattWeisskopfCategory bwCategory, const LauResonanceInfo* resInfo ) { LauBlattWeisskopfFactor* bwFactor(0); // If this is an independent factor, create it and add it to the list of independent factors, then return it if ( bwCategory == LauBlattWeisskopfFactor::Indep ) { bwFactor = new LauBlattWeisskopfFactor( *resInfo, bwBarrierType_, bwRestFrame_, bwCategory ); bwIndepFactors_.push_back(bwFactor); return bwFactor; } // Otherwise, look up the category in the category information map BWFactorCategoryMap::iterator factor_iter = bwFactors_.find( bwCategory ); if ( factor_iter == bwFactors_.end() ) { // If the category is currently undefined we need to create it bwFactor = new LauBlattWeisskopfFactor( *resInfo, bwBarrierType_, bwRestFrame_, bwCategory ); BlattWeisskopfCategoryInfo& categoryInfo = bwFactors_[bwCategory]; categoryInfo.bwFactor_ = bwFactor; categoryInfo.defaultRadius_ = bwFactor->getRadiusParameter()->value(); categoryInfo.radiusFixed_ = kTRUE; } else { // If it exists, we can check if the factor object has been created BlattWeisskopfCategoryInfo& categoryInfo = factor_iter->second; if ( categoryInfo.bwFactor_ != 0 ) { // If so, simply clone it const UInt_t resSpin = resInfo->getSpin(); bwFactor = categoryInfo.bwFactor_->createClone( resSpin ); } else { // Otherwise we need to create it, using the default value if it has been set if ( categoryInfo.defaultRadius_ >= 0.0 ) { bwFactor = new LauBlattWeisskopfFactor( *resInfo, categoryInfo.defaultRadius_, bwBarrierType_, bwRestFrame_, bwCategory ); } else { bwFactor = new LauBlattWeisskopfFactor( *resInfo, bwBarrierType_, bwRestFrame_, bwCategory ); } categoryInfo.bwFactor_ = bwFactor; // Set whether the radius should be fixed/floated LauParameter* radius = bwFactor->getRadiusParameter(); radius->fixed( categoryInfo.radiusFixed_ ); } } return bwFactor; } LauAbsResonance* LauResonanceMaker::getResonance(const LauDaughters* daughters, const TString& resName, const Int_t resPairAmpInt, const LauAbsResonance::LauResonanceModel resType, const LauBlattWeisskopfFactor::BlattWeisskopfCategory bwCategory) { // Routine to return the appropriate LauAbsResonance object given the resonance // name (resName), which daughter is the bachelor track (resPairAmpInt = 1,2 or 3), // and the resonance type ("BW" = Breit-Wigner, "Flatte" = Flatte distribution). // If this is the first resonance we are making, first print a summary of the formalism if ( ! summaryPrinted_ ) { std::cout << "INFO in LauResonanceMaker::getResonance : Freezing amplitude formalism:" << std::endl; switch ( spinFormalism_ ) { case LauAbsResonance::Zemach_P : std::cout << " : Spin factors use Zemach spin tensors, with bachelor momentum in resonance rest frame" << std::endl; break; case LauAbsResonance::Zemach_Pstar : std::cout << " : Spin factors use Zemach spin tensors, with bachelor momentum in parent rest frame" << std::endl; break; case LauAbsResonance::Covariant : std::cout << " : Spin factors use Covariant spin tensors" << std::endl; break; case LauAbsResonance::Legendre : std::cout << " : Spin factors are just Legendre polynomials" << std::endl; break; } switch ( bwBarrierType_ ) { case LauBlattWeisskopfFactor::BWBarrier : std::cout << " : Blatt-Weisskopf barrier factors are the 'non-primed' form" << std::endl; break; case LauBlattWeisskopfFactor::BWPrimeBarrier : std::cout << " : Blatt-Weisskopf barrier factors are the 'primed' form" << std::endl; break; case LauBlattWeisskopfFactor::ExpBarrier : std::cout << " : Blatt-Weisskopf barrier factors are the exponential form" << std::endl; break; } switch ( bwRestFrame_ ) { case LauBlattWeisskopfFactor::ParentFrame : std::cout << " : Blatt-Weisskopf barrier factors use bachelor momentum in parent rest frame" << std::endl; break; case LauBlattWeisskopfFactor::ResonanceFrame : std::cout << " : Blatt-Weisskopf barrier factors use bachelor momentum in resonance rest frame" << std::endl; break; case LauBlattWeisskopfFactor::Covariant : std::cout << " : Blatt-Weisskopf barrier factors use covariant expression" << std::endl; break; } summaryPrinted_ = kTRUE; } // Loop over all possible resonance states we have defined in // createResonanceVector() until we get a match with the name of the resonance LauResonanceInfo* resInfo(0); for (std::vector::const_iterator iter=resInfo_.begin(); iter!=resInfo_.end(); ++iter) { if (resName == (*iter)->getName()) { // We have recognised the resonance name. std::cout<<"INFO in LauResonanceMaker::getResonance : Creating resonance: "<getBWCategory(); } LauBlattWeisskopfFactor* resBWFactor = this->getBWFactor( resCategory, resInfo ); LauBlattWeisskopfFactor* parBWFactor = this->getBWFactor( parCategory, resInfo ); theResonance->setBarrierRadii( resBWFactor, parBWFactor ); break; } case LauAbsResonance::GS : { // Gounaris-Sakurai function to try and model the rho(770) better std::cout<<" : Using Gounaris-Sakurai lineshape. "<getBWCategory(); } LauBlattWeisskopfFactor* resBWFactor = this->getBWFactor( resCategory, resInfo ); LauBlattWeisskopfFactor* parBWFactor = this->getBWFactor( parCategory, resInfo ); theResonance->setBarrierRadii( resBWFactor, parBWFactor ); break; } case LauAbsResonance::Flatte : // Flatte distribution - coupled channel Breit-Wigner std::cout<<" : Using Flatte lineshape. "<getBWCategory(); } LauBlattWeisskopfFactor* resBWFactor = this->getBWFactor( resCategory, resInfo ); LauBlattWeisskopfFactor* parBWFactor = this->getBWFactor( parCategory, resInfo ); theResonance->setBarrierRadii( resBWFactor, parBWFactor ); break; } // Set the spin formalism choice theResonance->setSpinType( spinFormalism_ ); return theResonance; } Int_t LauResonanceMaker::resTypeInt(const TString& name) const { // Internal function that returns the resonance integer, specified by the // order of the resonance vector defined in createResonanceVector(), // for a given resonance name. Int_t resTypInt(-99); Int_t i(0); for (std::vector::const_iterator iter=resInfo_.begin(); iter!=resInfo_.end(); ++iter) { if (name.BeginsWith((*iter)->getName(), TString::kExact) == kTRUE) { // We have recognised the resonance from those that are available resTypInt = i; return resTypInt; } ++i; } return resTypInt; } void LauResonanceMaker::printAll( std::ostream& stream ) const { for ( std::vector::const_iterator iter = resInfo_.begin(); iter != resInfo_.end(); ++iter ) { stream << (**iter) << std::endl; } } LauResonanceInfo* LauResonanceMaker::getResInfo(const TString& resName) const { LauResonanceInfo* resInfo(0); for (std::vector::const_iterator iter=resInfo_.begin(); iter!=resInfo_.end(); ++iter) { if (resName == (*iter)->getName()) { // We have recognised the resonance name. resInfo = (*iter); // stop looping break; } } return resInfo; } diff --git a/src/LauResultsExtractor.cc b/src/LauResultsExtractor.cc index fb46651..d33c082 100644 --- a/src/LauResultsExtractor.cc +++ b/src/LauResultsExtractor.cc @@ -1,292 +1,291 @@ /* Copyright 2005 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ #include "LauResultsExtractor.hh" #include #include #include #include #include #include "TChain.h" #include "TFile.h" #include "TH1.h" #include "TLeaf.h" #include "TObjArray.h" #include "TSystem.h" -ClassImp(LauResultsExtractor) LauResultsExtractor::LauResultsExtractor(const TString& inputFileName, const TString& outputFileName, const TString& treeName) : inputFileName_(inputFileName), outputFileName_(outputFileName), treeName_(treeName), inputTree_(0), outputFile_(0), outputTree_(0), nEntries_(0) { } LauResultsExtractor::~LauResultsExtractor() { this->clearMaps(); delete inputTree_; inputTree_ = 0; if (outputFile_ && outputFile_->IsOpen()) { delete outputTree_; outputTree_ = 0; } delete outputFile_; outputFile_ = 0; } void LauResultsExtractor::setupInputTree() { TObjArray* leaves = inputTree_->GetListOfLeaves(); Int_t nLeaves = leaves->GetEntries(); std::cout<<"Setting branches for input tree \""<GetName()<<"\" with "<SetBranchAddress("iExpt",&iExpt_); inputTree_->SetBranchAddress("fitStatus",&fitStatus_); inputTree_->SetBranchAddress("NLL",&NLL_); inputTree_->SetBranchAddress("EDM",&EDM_); for (Int_t iLeaf(3); iLeaf((*leaves)[iLeaf]); TString type = leaf->GetTypeName(); TString name = leaf->GetName(); Int_t size = leaf->GetNdata(); if ((type != "Double_t") || (size != 1)) { continue; } std::pair::iterator,bool> result = otherVars_.insert(std::make_pair(name,0.0)); std::map::iterator iter = result.first; bool ok = result.second; if (ok) { inputTree_->SetBranchAddress(name,&(iter->second)); } } std::cout<<"Set branch addresses for "<GetName()<<"\"..."<Branch("iExpt",&iExpt_,"iExpt/I"); tree->Branch("fitStatus",&fitStatus_,"fitStatus/I"); tree->Branch("NLL",&NLL_,"NLL/D"); tree->Branch("EDM",&EDM_,"EDM/D"); for (std::map::iterator iter = otherVars_.begin(); iter != otherVars_.end(); ++iter) { TString name = iter->first; Double_t * address = &(iter->second); TString thirdBit = name; thirdBit += "/D"; tree->Branch(name,address,thirdBit); } std::cout<<"Created "<SetBranchStatus("iExpt",kTRUE); inputTree_->SetBranchStatus("fitStatus",kTRUE); inputTree_->SetBranchStatus("NLL",kTRUE); inputTree_->SetBranchStatus("EDM",kTRUE); for (std::map::iterator iter = otherVars_.begin(); iter != otherVars_.end(); ++iter) { TString name = iter->first; inputTree_->SetBranchStatus(name,status); } } void LauResultsExtractor::clearMaps() { for (std::map::iterator iter = nllHistos_.begin(); iter != nllHistos_.end(); ++iter) { delete (iter->second); } bestNLL_.clear(); worstNLL_.clear(); allNLLs_.clear(); nllHistos_.clear(); } void LauResultsExtractor::process(Int_t numExpts) { // open the text file std::cout << "\n" << "Chaining...\n" << std::endl; std::ifstream textFile(inputFileName_, std::ios::in); if (!textFile.good()) { std::cerr<<"Problem opening file: \""<Exit(EXIT_FAILURE); } if (inputTree_) { delete inputTree_; inputTree_ = 0; } inputTree_ = new TChain(treeName_); // Read the text file and add each valid entry to the chain TString inputFileName = ""; while(inputFileName.ReadLine(textFile) && (!inputFileName.IsNull())) { if (inputFileName.EndsWith(".root") && !inputFileName.BeginsWith("#")) { std::cout << inputFileName << std::endl; inputTree_->Add(inputFileName); } else { std::cout << inputFileName << "\t *** Skipped ***" << std::endl; } } textFile.close(); std::cout << "\n" << "... finished.\n" << std::endl; nEntries_ = inputTree_->GetEntries(); this->setupInputTree(); outputTree_ = new TTree(treeName_,""); this->setupOutputTree(outputTree_); // setup the map: // for each experiment there is a pair object holding // the best NLL and the tree entry for that NLL value // each expt starts out with NLL = 0.0 and entry = -1 std::cout<<"Setting up the map..."<clearMaps(); for (Int_t i(0); i())); allNLLs_[i].reserve(nEntries_); } std::cout<<" done.\n"<setInputTreeBranchStatus(kFALSE); // loop over the tree and store the best entries for each expt std::cout<<"Starting to store best entry info..."<GetEntry(j); if ( (fitStatus_ == 3) && (NLL_ > -DBL_MAX/10.0) ) { allNLLs_[iExpt_].push_back(NLL_); Double_t curBestNLL = bestNLL_[iExpt_].first; Int_t curBestEntry = bestNLL_[iExpt_].second; if ((NLL_ < curBestNLL) || (curBestEntry == -1)) { bestNLL_[iExpt_] = std::make_pair(NLL_,j); } Double_t curWorstNLL = worstNLL_[iExpt_].first; Int_t curWorstEntry = worstNLL_[iExpt_].second; if ((NLL_ > curWorstNLL) || (curWorstEntry == -1)) { worstNLL_[iExpt_] = std::make_pair(NLL_,j); } } } std::cout<<"Finished storing best entry info.\n"<::const_iterator iter = allNLLs_[i].begin(); iter != allNLLs_[i].end(); ++iter) { histo->Fill(*iter); } nllHistos_.insert(std::make_pair(i, histo)); } std::cout<<" done.\n"<setInputTreeBranchStatus(kTRUE); std::ofstream fout("best-fit.txt"); // loop over the experiments, grab the best entry and store it std::cout<<"Starting to retrieve best entries and fill output tree."<GetEntry(bestEntry); outputTree_->Fill(); } if ((numExpts<100) || (i%(numExpts/100)==0)) { std::cout<<"Writing out experiment "<GetCurrentFile()->GetName()); bestFit.Remove(0,3); Int_t index = bestFit.Index("_"); if ( index < 1 ) { index = bestFit.Index("."); } bestFit.Remove(index); fout<<"Experiment "<writeFile(); } void LauResultsExtractor::writeFile() { if (!outputFile_) { outputFile_ = new TFile(outputFileName_,"recreate"); } for (std::map::iterator iter = nllHistos_.begin(); iter != nllHistos_.end(); ++iter) { (iter->second)->SetDirectory(outputFile_); } outputTree_->SetDirectory(outputFile_); outputFile_->Write(); outputFile_->Close(); delete outputFile_; outputFile_ = 0; nllHistos_.clear(); } diff --git a/src/LauRhoOmegaMix.cc b/src/LauRhoOmegaMix.cc index a51691c..ea9f744 100644 --- a/src/LauRhoOmegaMix.cc +++ b/src/LauRhoOmegaMix.cc @@ -1,510 +1,509 @@ /* Copyright 2016 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauRhoOmegaMix.cc \brief File containing implementation of LauRhoOmegaMix class. */ #include #include "LauBlattWeisskopfFactor.hh" #include "LauConstants.hh" #include "LauDaughters.hh" #include "LauParameter.hh" #include "LauRhoOmegaMix.hh" #include "LauResonanceInfo.hh" #include "LauResonanceMaker.hh" -ClassImp(LauRhoOmegaMix) LauRhoOmegaMix::LauRhoOmegaMix(LauResonanceInfo* resInfo, const LauAbsResonance::LauResonanceModel resType, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), model_(resType), rhoMass_(0.0), rhoResRadius_(0.0), rhoParRadius_(0.0), mOmega_(0), mOmega0_(0.0), mOmegaCur_(0.0), wOmega_(0), wOmega0_(0.0), wOmegaCur_(0.0), magB_(0), phiB_(0), delta_(0), useDenom_(kTRUE), doneFirstInit_(kFALSE), rhoRes_(0), omegaRes_(0), whichAmpSq_(0) { // Create the rho and omega lineshapes depending on the resonance type enumeration. // The narrow omega is always a relativistic Breit-Wigner (RBW), but the broader rho // can either be a RBW or a Gounaris-Sakurai lineshape. The" _1" form for the resonance type // specifies that we want to assume the amplitude denominator correction term is set to 1. // In principle, the rho lineshape can be any resonance defined by the resInfo pointer, so we // use that to extract all relevant information about the first resonance. // We do not need the barrier nor spin factor terms for the components separately, since // they will be added after the lineshapes have been combined LauResonanceMaker& resMaker = LauResonanceMaker::get(); LauAbsResonance::LauResonanceModel rhoType = LauAbsResonance::RelBW; if (resType == LauAbsResonance::RhoOmegaMix_GS || resType == LauAbsResonance::RhoOmegaMix_GS_1) { rhoType = LauAbsResonance::GS; } rhoRes_ = resMaker.getResonance(daughters, resInfo->getName(), resPairAmpInt, rhoType, LauBlattWeisskopfFactor::Light); LauResonanceInfo* omegaInfo = resMaker.getResInfo("omega(782)"); omegaRes_ = resMaker.getResonance(daughters, omegaInfo->getName(), resPairAmpInt, LauAbsResonance::RelBW, LauBlattWeisskopfFactor::Light); // Check to see if we want to set the denominator factor to unity if (resType == LauAbsResonance::RhoOmegaMix_RBW_1 || resType == LauAbsResonance::RhoOmegaMix_GS_1) { useDenom_ = kFALSE; } // Initialise various parameters that can be used in the model const TString& parNameBase = this->getSanitisedName(); // Pole mass of the omega (2nd) resonance. Initialise using the resonance maker (PDG) info mOmega0_ = omegaInfo->getMass()->unblindValue(); // Also set the current internal value of the omega mass for initialisation logic mOmegaCur_ = mOmega0_; TString mOmegaName(parNameBase); mOmegaName += "_mOmega"; mOmega_ = resInfo->getExtraParameter(mOmegaName); if (!mOmega_) { mOmega_ = new LauParameter(mOmegaName, mOmega0_, 0.0, 100.0, kTRUE); mOmega_->secondStage(kTRUE); resInfo->addExtraParameter(mOmega_); } // Pole width of the omega (2nd) resonance. Initialise using the resonance maker (PDG) info wOmega0_ = omegaInfo->getWidth()->unblindValue(); // Also set the current internal value of the omega width for initialisation logic wOmegaCur_ = wOmega0_; TString wOmegaName(parNameBase); wOmegaName += "_wOmega"; wOmega_ = resInfo->getExtraParameter(wOmegaName); if (!wOmega_) { wOmega_ = new LauParameter(wOmegaName, wOmega0_, 0.0, 100.0, kTRUE); wOmega_->secondStage(kTRUE); resInfo->addExtraParameter(wOmega_); } // Set the magnitude and phase of the omega amplitude mixing term. // These should be fitted const Double_t magBVal = 1.0; const Double_t phiBVal = 0.0; TString magBName(parNameBase); magBName += "_magB"; magB_ = resInfo->getExtraParameter(magBName); if (!magB_) { magB_ = new LauParameter(magBName, magBVal, 0.0, 100.0, kTRUE); magB_->secondStage(kTRUE); resInfo->addExtraParameter(magB_, kTRUE); // the kTRUE here allows this value to vary between B and Bbar - TODO: maybe make this configurable? } TString phiBName(parNameBase); phiBName += "_phiB"; phiB_ = resInfo->getExtraParameter(phiBName); if (!phiB_) { phiB_ = new LauParameter(phiBName, phiBVal, -10.0, 10.0, kTRUE); phiB_->secondStage(kTRUE); resInfo->addExtraParameter(phiB_, kTRUE); // the kTRUE here allows this value to vary between B and Bbar - TODO: maybe make this configurable? } // Set the delta parameter for the omega amplitude mixing term. This // is usually fixed but should be varied for systematic error checks. // In theory, this parameter can be complex, but we only use its magnitude // in the mixing amplitude, since its usually very small: (2.15 +- 0.35) MeV/c^2 const Double_t deltaVal = 2.15e-3; TString deltaName(parNameBase); deltaName += "_delta"; delta_ = resInfo->getExtraParameter(deltaName); if (!delta_) { delta_ = new LauParameter(deltaName, deltaVal, 0.0, 100.0, kTRUE); delta_->secondStage(kTRUE); resInfo->addExtraParameter(delta_); } } LauRhoOmegaMix::~LauRhoOmegaMix() { } void LauRhoOmegaMix::initialise() { // Initialise the two resonances. This is done within each amplitude() function // call and so floating parameters are checked every time, although secondary // initialisation checks will be "skipped" since the parameters will be unchanged // for the given set of kinematic variables/parameters this->initialiseRho(); this->initialiseOmega(); } void LauRhoOmegaMix::initialiseRho() { // Propagate settings rhoRes_->setSpinType( this->getSpinType() ); rhoRes_->flipHelicity( this->flipHelicity() ); rhoRes_->ignoreMomenta( this->ignoreMomenta() ); rhoRes_->ignoreSpin( this->ignoreSpin() ); rhoRes_->ignoreBarrierScaling( this->ignoreBarrierScaling() ); // Do the initialisation rhoRes_->initialise(); // Keep track of the current pole mass and barrier factor terms so that // we can reinitialise the rho resonance if they change rhoMass_ = rhoRes_->getMass(); rhoResRadius_ = rhoRes_->getResRadius(); rhoParRadius_ = rhoRes_->getParRadius(); } void LauRhoOmegaMix::initialiseOmega() { // Set the pole mass and width of the omega resonance if this has changed // using the parameters mOmega_ and wOmega_ Double_t newOmegaM(-1.0), newOmegaW(-1.0); const Int_t newOmegaSpin(-1); // See if the new pole mass is different from the current value Double_t tmpOmegaM = mOmega_->unblindValue(); if (fabs(tmpOmegaM - mOmegaCur_) > 1e-10) { newOmegaM = tmpOmegaM; } // See if the new pole width is different from the current value Double_t tmpOmegaW = wOmega_->unblindValue(); if (fabs(tmpOmegaW - wOmegaCur_) > 1e-10) { newOmegaW = tmpOmegaW; } // If any parameter is negative, they are unchanged omegaRes_->changeResonance(newOmegaM, newOmegaW, newOmegaSpin); Bool_t changedOmegaM(kFALSE); if (newOmegaM > -1.0) { changedOmegaM = kTRUE; } if (doneFirstInit_ == kFALSE) { // Let the omega resonance pointer know if the mass or width are fixed or floating omegaRes_->fixMass(this->fixmOmegaValue()); omegaRes_->fixWidth(this->fixwOmegaValue()); // We do not need to use the spin terms for the omega lineshape, since we // use those from the rho for the full amplitude later on // (as such we do not need to propagate the flip helicity setting to the omega, just to the rho) omegaRes_->ignoreSpin(kTRUE); // We want to ignore momentum-dependent width effects: just use the constant pole width omegaRes_->ignoreMomenta(kTRUE); // And we also need to ignore barrier scaling omegaRes_->ignoreBarrierScaling(kTRUE); // Initialise the omega resonance pointer omegaRes_->initialise(); doneFirstInit_ = kTRUE; } else { // Reinitialise the omega resonance pointer only if we have changed // its pole mass. It has no barrier factor if (changedOmegaM == kTRUE) { omegaRes_->initialise(); } } // Keep track of the current values of the mass and width of the omega (floating/fixed) mOmegaCur_ = tmpOmegaM; wOmegaCur_ = tmpOmegaW; } LauComplex LauRhoOmegaMix::amplitude(const LauKinematics* kinematics) { // This function overrides and returns the complex dynamical amplitude for the // rho-omega mass mixing amplitude given the kinematics // Check to see if we need to reinitialise the rho resonance pointer const Double_t resMass = rhoRes_->getMass(); const Double_t resRadius = rhoRes_->getResRadius(); const Double_t parRadius = rhoRes_->getParRadius(); if ( ( (!this->fixMass()) && fabs(resMass - rhoMass_) > 1e-10) || ( (!this->fixResRadius()) && fabs(resRadius - rhoResRadius_) > 1e-10 ) || ( (!this->fixParRadius()) && fabs(parRadius - rhoParRadius_) > 1e-10 ) ) { this->initialiseRho(); } // Always check the initialisaton of the omega resonance in case we have varied // its mass/width via the fit parameters this->initialiseOmega(); // First, get the amplitude of the first (rho) resonance. // This will include the full barrier and spin terms const LauComplex rhoAmp = rhoRes_->amplitude(kinematics); // Next, get the amplitude of the second (omega) resonance. This ignores barrier // and spin terms, and uses the pole width only (no momentum dependence) const LauComplex omegaAmp = omegaRes_->amplitude(kinematics); // The Delta parameter, which we assume is purely real. Theoretically, delta can // be complex, but in practice we only use its (usually small) magnitude const Double_t Delta = (resMass + mOmegaCur_)*this->getdeltaValue(); // The B amplitude term const Double_t magBVal = this->getmagBValue()*Delta; const Double_t phiBVal = this->getphiBValue(); const LauComplex BTerm = LauComplex(magBVal*cos(phiBVal), magBVal*sin(phiBVal)); // The mass mixing term const LauComplex unity(1.0, 0.0); const LauComplex mixingTerm = BTerm*omegaAmp + unity; // Now form the full amplitude LauComplex resAmplitude = rhoAmp*mixingTerm; // Add the mixing correction denominator term if required if (useDenom_) { // Here, we need to disable the rho barrier & spin factors, since they are // only needed for the numerator term of the full amplitude. Note that we still // need to use the momentum-dependent width (with its resonance barrier term) // Disable barrier scaling factors for the amplitude (not width) rhoRes_->ignoreBarrierScaling(kTRUE); // Also ignore spin terms for now rhoRes_->ignoreSpin(kTRUE); const LauComplex rhoAmp2 = rhoRes_->amplitude(kinematics); // Reinstate barrier scaling and spin term flags rhoRes_->ignoreBarrierScaling(kFALSE); rhoRes_->ignoreSpin(kFALSE); // Denominator term const LauComplex DeltaSq = LauComplex(Delta*Delta, 0.0); const LauComplex denomTerm = unity - DeltaSq*rhoAmp2*omegaAmp; // Modify the full amplitude resAmplitude = resAmplitude/denomTerm; if (this->whichAmpSq_ == 1) { // For omega fit fraction return LauComplex(sqrt(omegaAmp.abs() * Delta * magBVal), 0.0); } else if (this->whichAmpSq_ == 2) { // For rho fit fraction return rhoAmp; } } return resAmplitude; } LauComplex LauRhoOmegaMix::resAmp(Double_t mass, Double_t spinTerm) { std::cerr << "ERROR in LauRhoOmegaMix : This method should never be called." << std::endl; std::cerr << " : Returning zero amplitude for mass = " << mass << " and spinTerm = " << spinTerm << "." << std::endl; return LauComplex(0.0, 0.0); } const std::vector& LauRhoOmegaMix::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixmOmegaValue() ) { this->addFloatingParameter( mOmega_ ); } if ( ! this->fixwOmegaValue() ) { this->addFloatingParameter( wOmega_ ); } if ( ! this->fixmagBValue() ) { this->addFloatingParameter( magB_ ); } if ( ! this->fixphiBValue() ) { this->addFloatingParameter( phiB_ ); } if ( ! this->fixdeltaValue() ) { this->addFloatingParameter( delta_ ); } if ( ! this->fixMass() ) { this->addFloatingParameter( this->getMassPar() ); } if ( ! this->fixWidth() ) { this->addFloatingParameter( this->getWidthPar() ); } if ( ! this->fixResRadius() ) { this->addFloatingParameter( this->getResBWFactor()->getRadiusParameter() ); } if ( ! this->fixParRadius() ) { this->addFloatingParameter( this->getParBWFactor()->getRadiusParameter() ); } return this->getParameters(); } void LauRhoOmegaMix::setResonanceParameter(const TString& name, const Double_t value) { // Set various parameters for the lineshape if (name == "mOmega") { this->setmOmegaValue(value); std::cout << "INFO in LauRhoOmegaMix::setResonanceParameter : Setting parameter mOmega = " << this->getmOmegaValue() << std::endl; } else if (name == "wOmega") { this->setwOmegaValue(value); std::cout << "INFO in LauRhoOmegaMix::setResonanceParameter : Setting parameter wOmega = " << this->getwOmegaValue() << std::endl; } else if (name == "magB") { this->setmagBValue(value); std::cout << "INFO in LauRhoOmegaMix::setResonanceParameter : Setting parameter magB = " << this->getmagBValue() << std::endl; } else if (name == "phiB") { this->setphiBValue(value); std::cout << "INFO in LauRhoOmegaMix::setResonanceParameter : Setting parameter phiB = " << this->getphiBValue() << std::endl; } else if (name == "delta") { this->setdeltaValue(value); std::cout << "INFO in LauRhoOmegaMix::setResonanceParameter : Setting parameter delta = " << this->getdeltaValue() << std::endl; } else { std::cerr << "WARNING in LauSigmaRes::setResonanceParameter: Parameter name "<fixed() ) { mOmega_->fixed( kFALSE ); this->addFloatingParameter( mOmega_ ); } else { std::cerr << "WARNING in LauRhoOmegaMix::floatResonanceParameter: Parameter "<fixed() ) { wOmega_->fixed( kFALSE ); this->addFloatingParameter( wOmega_ ); } else { std::cerr << "WARNING in LauRhoOmegaMix::floatResonanceParameter: Parameter "<fixed() ) { magB_->fixed( kFALSE ); this->addFloatingParameter( magB_ ); } else { std::cerr << "WARNING in LauRhoOmegaMix::floatResonanceParameter: Parameter "<fixed() ) { phiB_->fixed( kFALSE ); this->addFloatingParameter( phiB_ ); } else { std::cerr << "WARNING in LauRhoOmegaMix::floatResonanceParameter: Parameter "<fixed() ) { delta_->fixed( kFALSE ); this->addFloatingParameter( delta_ ); } else { std::cerr << "WARNING in LauRhoOmegaMix::floatResonanceParameter: Parameter "<value( mOmega ); mOmega_->genValue( mOmega ); mOmega_->initValue( mOmega ); } void LauRhoOmegaMix::setwOmegaValue(const Double_t wOmega) { wOmega_->value( wOmega ); wOmega_->genValue( wOmega ); wOmega_->initValue( wOmega ); } void LauRhoOmegaMix::setmagBValue(const Double_t magB) { magB_->value( magB ); magB_->genValue( magB ); magB_->initValue( magB ); } void LauRhoOmegaMix::setphiBValue(const Double_t phiB) { phiB_->value( phiB ); phiB_->genValue( phiB ); phiB_->initValue( phiB ); } void LauRhoOmegaMix::setdeltaValue(const Double_t delta) { delta_->value( delta ); delta_->genValue( delta ); delta_->initValue( delta ); } diff --git a/src/LauRooFitSlave.cc b/src/LauRooFitSlave.cc index 78e3737..b6e7a73 100644 --- a/src/LauRooFitSlave.cc +++ b/src/LauRooFitSlave.cc @@ -1,393 +1,392 @@ /* Copyright 2017 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauRooFitSlave.cc \brief File containing implementation of LauRooFitSlave class. */ #include #include #include "RooRealVar.h" #include "RooDataSet.h" #include "TFile.h" #include "TString.h" #include "TSystem.h" #include "TTree.h" #include "LauFitNtuple.hh" #include "LauParameter.hh" #include "LauSimFitSlave.hh" #include "LauRooFitSlave.hh" -ClassImp(LauRooFitSlave) LauRooFitSlave::LauRooFitSlave( RooAbsPdf& model, const Bool_t extended, const RooArgSet& vars, const TString& weightVarName ) : LauSimFitSlave(), model_(model), dataVars_(vars), weightVarName_(weightVarName), dataFile_(0), dataTree_(0), exptData_(0), extended_(extended), iExptCat_("iExpt","Expt Number"), nllVar_(0) { } LauRooFitSlave::~LauRooFitSlave() { delete nllVar_; nllVar_ = 0; this->cleanData(); } void LauRooFitSlave::cleanData() { if ( dataFile_ != 0 ) { dataFile_->Close(); delete dataFile_; dataTree_ = 0; dataFile_ = 0; } delete exptData_; exptData_ = 0; } void LauRooFitSlave::initialise() { if ( weightVarName_ != "" ) { Bool_t weightVarFound = kFALSE; RooFIter argset_iter = dataVars_.fwdIterator(); RooAbsArg* param(0); while ( (param = argset_iter.next()) ) { TString name = param->GetName(); if ( name == weightVarName_ ) { weightVarFound = kTRUE; break; } } if ( ! weightVarFound ) { std::cerr << "ERROR in LauRooFitSlave::initialise : The set of data variables does not contain the weighting variable \"" << weightVarName_ << std::endl; std::cerr << " : Weighting will be disabled." << std::endl; weightVarName_ = ""; } } } Bool_t LauRooFitSlave::verifyFitData(const TString& dataFileName, const TString& dataTreeName) { // Clean-up from any previous runs if ( dataFile_ != 0 ) { this->cleanData(); } // Open the data file dataFile_ = TFile::Open( dataFileName ); if ( ! dataFile_ ) { std::cerr << "ERROR in LauRooFitSlave::verifyFitData : Problem opening data file \"" << dataFileName << "\"" << std::endl; return kFALSE; } // Retrieve the tree dataTree_ = dynamic_cast( dataFile_->Get( dataTreeName ) ); if ( ! dataTree_ ) { std::cerr << "ERROR in LauRooFitSlave::verifyFitData : Problem retrieving tree \"" << dataTreeName << "\" from data file \"" << dataFileName << "\"" << std::endl; dataFile_->Close(); delete dataFile_; dataFile_ = 0; return kFALSE; } // Check that the tree contains branches for all the fit variables RooFIter argset_iter = dataVars_.fwdIterator(); RooAbsArg* param(0); Bool_t allOK(kTRUE); while ( (param = argset_iter.next()) ) { TString name = param->GetName(); TBranch* branch = dataTree_->GetBranch( name ); if ( branch == 0 ) { std::cerr << "ERROR in LauRooFitSlave::verifyFitData : The data tree does not contain a branch for fit variable \"" << name << std::endl; allOK = kFALSE; } } if ( ! allOK ) { return kFALSE; } // Check whether the tree has the branch iExpt TBranch* branch = dataTree_->GetBranch("iExpt"); if ( branch == 0 ) { std::cout << "WARNING in LauRooFitSlave::verifyFitData : Cannot find branch \"iExpt\" in the tree, will treat all data as being from a single experiment" << std::endl; } else { // Define the valid values for the iExpt RooCategory iExptCat_.clearTypes(); const UInt_t firstExp = dataTree_->GetMinimum("iExpt"); const UInt_t lastExp = dataTree_->GetMaximum("iExpt"); for ( UInt_t iExp = firstExp; iExp <= lastExp; ++iExp ) { iExptCat_.defineType( TString::Format("expt%d",iExp), iExp ); } } return kTRUE; } void LauRooFitSlave::prepareInitialParArray( TObjArray& array ) { // Check that the NLL variable has been initialised if ( ! nllVar_ ) { std::cerr << "ERROR in LauRooFitSlave::prepareInitialParArray : NLL var not initialised" << std::endl; return; } // If we already prepared the entries in the fitPars_ vector then we only need to add the contents to the array if ( ! fitPars_.empty() ) { for ( std::vector::iterator iter = fitPars_.begin(); iter != fitPars_.end(); ++iter ) { array.Add(*iter); } return; } // Store the set of parameters and the total number of parameters RooArgSet* varSet = nllVar_->getParameters( exptData_ ); UInt_t nFreePars(0); // Loop through the fit parameters RooFIter argset_iter = varSet->fwdIterator(); RooAbsArg* param(0); while ( (param = argset_iter.next()) ) { // Only consider the free parameters if ( ! param->isConstant() ) { // Add the parameter RooRealVar* rrvar = dynamic_cast( param ); if ( rrvar != 0 ) { // Count the number of free parameters ++nFreePars; // Do the conversion and add it to the array LauParameter* lpar = this->convertToLauParameter( rrvar ); fitVars_.push_back( rrvar ); fitPars_.push_back( lpar ); array.Add( lpar ); } else { RooFormulaVar* rfvar = dynamic_cast( param ); if ( rfvar == 0 ) { std::cerr << "ERROR in LauRooFitSlave::prepareInitialParArray : The parameter is neither a RooRealVar nor a RooFormulaVar, don't know what to do" << std::endl; continue; } std::vector< std::pair > lpars = this->convertToLauParameters( rfvar ); for ( std::vector< std::pair >::iterator iter = lpars.begin(); iter != lpars.end(); ++iter ) { RooRealVar* rrv = iter->first; LauParameter* lpar = iter->second; if ( ! rrv->isConstant() ) { continue; } // Count the number of free parameters ++nFreePars; // Add the parameter to the array fitVars_.push_back( rrvar ); fitPars_.push_back( lpar ); array.Add( lpar ); } } } } delete varSet; this->startNewFit( nFreePars, nFreePars ); } LauParameter* LauRooFitSlave::convertToLauParameter( const RooRealVar* rooParameter ) const { return new LauParameter( rooParameter->GetName(), rooParameter->getVal(), rooParameter->getMin(), rooParameter->getMax(), rooParameter->isConstant() ); } std::vector< std::pair > LauRooFitSlave::convertToLauParameters( const RooFormulaVar* rooFormula ) const { // Create the empty vector std::vector< std::pair > lauParameters; Int_t parIndex(0); RooAbsArg* rabsarg(0); RooRealVar* rrvar(0); RooFormulaVar* rfvar(0); // Loop through all the parameters of the formula while ( (rabsarg = rooFormula->getParameter(parIndex)) ) { // First try converting to a RooRealVar rrvar = dynamic_cast( rabsarg ); if ( rrvar ) { // Do the conversion and add it to the array LauParameter* lpar = this->convertToLauParameter( rrvar ); lauParameters.push_back( std::make_pair(rrvar,lpar) ); continue; } // If that didn't work, try converting to a RooFormulaVar rfvar = dynamic_cast( rabsarg ); if ( rfvar ) { // Do the conversion and add these to the array std::vector< std::pair > lpars = this->convertToLauParameters( rfvar ); for ( std::vector< std::pair >::iterator iter = lpars.begin(); iter != lpars.end(); ++iter ) { lauParameters.push_back( *iter ); } continue; } // If neither of those worked we don't know what to do, so print an error message and continue std::cerr << "ERROR in LauRooFitSlave::convertToLauParameters : One of the parameters is not a RooRealVar nor a RooFormulaVar, it is a: " << rabsarg->ClassName() << std::endl; std::cerr << " : Do not know how to process that - it will be skipped." << std::endl; } return lauParameters; } Double_t LauRooFitSlave::getTotNegLogLikelihood() { Double_t nLL = (nllVar_ != 0) ? nllVar_->getVal() : 0.0; return nLL; } void LauRooFitSlave::setParsFromMinuit(Double_t* par, Int_t npar) { // This function sets the internal parameters based on the values // that Minuit is using when trying to minimise the total likelihood function. // MINOS reports different numbers of free parameters depending on the // situation, so disable this check const UInt_t nFreePars = this->nFreeParams(); if ( ! this->withinAsymErrorCalc() ) { if (static_cast(npar) != nFreePars) { std::cerr << "ERROR in LauRooFitSlave::setParsFromMinuit : Unexpected number of free parameters: " << npar << ".\n"; std::cerr << " Expected: " << nFreePars << ".\n" << std::endl; gSystem->Exit(EXIT_FAILURE); } } // Despite npar being the number of free parameters // the par array actually contains all the parameters, // free and floating... // Update all the floating ones with their new values for (UInt_t i(0); ifixed()) { // Set both the RooRealVars and the LauParameters fitPars_[i]->value(par[i]); fitVars_[i]->setVal(par[i]); } } } UInt_t LauRooFitSlave::readExperimentData() { // check that we're being asked to read a valid index const UInt_t exptIndex = this->iExpt(); if ( iExptCat_.numTypes() == 0 && exptIndex != 0 ) { std::cerr << "ERROR in LauRooFitSlave::readExperimentData : Invalid experiment number " << exptIndex << ", data contains only one experiment" << std::endl; return 0; } else if ( ! iExptCat_.isValidIndex( exptIndex ) ) { std::cerr << "ERROR in LauRooFitSlave::readExperimentData : Invalid experiment number " << exptIndex << std::endl; return 0; } // cleanup the data from any previous experiment delete exptData_; // retrieve the data and find out how many events have been read if ( iExptCat_.numTypes() == 0 ) { exptData_ = new RooDataSet( TString::Format("expt%dData",exptIndex), "", dataTree_, dataVars_, "", (weightVarName_ != "") ? weightVarName_.Data() : 0 ); } else { const TString selectionString = TString::Format("iExpt==%d",exptIndex); TTree* exptTree = dataTree_->CopyTree(selectionString); exptData_ = new RooDataSet( TString::Format("expt%dData",exptIndex), "", exptTree, dataVars_, "", (weightVarName_ != "") ? weightVarName_.Data() : 0 ); delete exptTree; } const UInt_t nEvent = exptData_->numEntries(); this->eventsPerExpt( nEvent ); return nEvent; } void LauRooFitSlave::cacheInputFitVars() { // cleanup the old NLL info delete nllVar_; // construct the new NLL variable for this dataset nllVar_ = new RooNLLVar("nllVar", "", model_, *exptData_, extended_); } void LauRooFitSlave::finaliseExperiment( const LauAbsFitter::FitStatus& fitStat, const TObjArray* parsFromMaster, const TMatrixD* covMat, TObjArray& parsToMaster ) { // Copy the fit status information this->storeFitStatus( fitStat, *covMat ); // Now process the parameters const UInt_t nFreePars = this->nFreeParams(); UInt_t nPars = parsFromMaster->GetEntries(); if ( nPars != nFreePars ) { std::cerr << "ERROR in LauRooFitSlave::finaliseExperiment : Unexpected number of parameters received from master" << std::endl; std::cerr << " : Received " << nPars << " when expecting " << nFreePars << std::endl; gSystem->Exit( EXIT_FAILURE ); } for ( UInt_t iPar(0); iPar < nPars; ++iPar ) { LauParameter* parameter = dynamic_cast( (*parsFromMaster)[iPar] ); if ( ! parameter ) { std::cerr << "ERROR in LauRooFitSlave::finaliseExperiment : Error reading parameter from master" << std::endl; gSystem->Exit( EXIT_FAILURE ); } if ( parameter->name() != fitPars_[iPar]->name() ) { std::cerr << "ERROR in LauRooFitSlave::finaliseExperiment : Error reading parameter from master" << std::endl; gSystem->Exit( EXIT_FAILURE ); } *(fitPars_[iPar]) = *parameter; RooRealVar* rrv = fitVars_[iPar]; rrv->setVal( parameter->value() ); rrv->setError( parameter->error() ); rrv->setAsymError( parameter->negError(), parameter->posError() ); } // Update the pulls and add each finalised fit parameter to the list to // send back to the master for ( std::vector::iterator iter = fitPars_.begin(); iter != fitPars_.end(); ++iter ) { (*iter)->updatePull(); parsToMaster.Add( *iter ); } // Write the results into the ntuple std::vector extraVars; LauFitNtuple* ntuple = this->fitNtuple(); ntuple->storeParsAndErrors(fitPars_, extraVars); // find out the correlation matrix for the parameters ntuple->storeCorrMatrix(this->iExpt(), this->fitStatus(), this->covarianceMatrix()); // Fill the data into ntuple ntuple->updateFitNtuple(); } diff --git a/src/LauSPlot.cc b/src/LauSPlot.cc index 993a543..d761cd6 100644 --- a/src/LauSPlot.cc +++ b/src/LauSPlot.cc @@ -1,1303 +1,1302 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauSPlot.cc \brief File containing implementation of LauSPlot class. Class for defining the SPlot technique based on TSplot from ROOT by the following authors: Muriel Pivk, Anna Kreshuk (10/2005). (Original copyright notice below) */ /********************************************************************** * * * Copyright (c) 2005 ROOT Foundation, CERN/PH-SFT * * * **********************************************************************/ #include #include #include using std::cout; using std::cerr; using std::endl; using std::vector; #include "TEventList.h" #include "TFile.h" #include "TLeaf.h" #include "TMath.h" #include "TObjArray.h" #include "TSystem.h" #include "TTree.h" #include "TVirtualFitter.h" #include "LauSPlot.hh" extern void Yields(Int_t &, Double_t *, Double_t &f, Double_t *x, Int_t iflag); -ClassImp(LauSPlot) LauSPlot::LauSPlot(const TString& fileName, const TString& treeName, Int_t firstExpt, Int_t nExpt, const NameSet& variableNames, const NumbMap& freeSpecies, const NumbMap& fixdSpecies, const TwoDMap& twodimPDFs, Bool_t sigSplit, Bool_t scfDPSmeared) : fileName_(fileName), inputTreeName_(treeName), cnTreeName_(""), sweightTreeName_(""), file_(0), inputTree_(0), cnTree_(0), sweightTree_(0), eventList_(0), variableNames_(variableNames), freeSpecies_(freeSpecies), fixdSpecies_(fixdSpecies), origFreeSpecies_(freeSpecies), origFixdSpecies_(fixdSpecies), twodimPDFs_(twodimPDFs), signalSplit_(sigSplit), scfDPSmear_(scfDPSmeared), readInput_(kFALSE), definedCNBranches_(kFALSE), definedSWeightBranches_(kFALSE), firstExpt_(firstExpt), nExpt_(nExpt), iExpt_(0), nEvents_(0), nDiscVars_(variableNames.size()), nFreeSpecies_(freeSpecies.size()), nFixdSpecies_(fixdSpecies.size()), nSpecies_(freeSpecies.size()+fixdSpecies.size()) { this->openInputFileAndTree(); this->readInputInfo(); this->createSWeightTree(); if (nFixdSpecies_>0) { this->createCNTree(); } } LauSPlot::~LauSPlot() { // seems that closing the file deletes the tree // so only delete if the file is still open if (file_ && file_->IsOpen()) { delete inputTree_; inputTree_ = 0; delete sweightTree_; sweightTree_ = 0; delete cnTree_; cnTree_ = 0; } delete file_; file_ = 0; } void LauSPlot::openInputFileAndTree() { // first check whether we've already opened up the file or not if (!file_) { // if not, first check the filename and if all ok create the file if (fileName_ == "") { cerr<<"ERROR in LauSPlot::createFileAndTree : Bad filename supplied, not creating file or tree."<IsZombie() || !file_->IsWritable()) { cerr<<"ERROR in LauSPlot::createFileAndTree : Problem opening file \""<cd(); inputTree_ = dynamic_cast(file_->Get(inputTreeName_)); inputTree_->SetDirectory(file_); } } void LauSPlot::readInputInfo() { // Read the tree and then setup the maps so we know which leaves to // read from the tree to get the various PDF values Bool_t inputOK = this->readInputLeaves(); if (!inputOK) { this->readInput(inputOK); return; } inputOK = this->checkLeaves(); this->readInput(inputOK); return; } Bool_t LauSPlot::readInputLeaves() { // Read all the leaves in the tree and store them in the leaves map if (!inputTree_) { cerr<<"ERROR in LauSPlot::readInputInfo : Invalid pointer to data tree."<(inputTree_->GetNbranches()) : 0; TObjArray* pLeaves = inputTree_->GetListOfLeaves(); if (!pLeaves) { cerr<<"ERROR in LauSPlot::readInputInfo : Problem retrieving leaves from the tree."< leaves.GetSize()) { cerr<<"ERROR in LauSPlot::readInputInfo : List of leaves is smaller than number of branches - this is strange!"<(leaves[iLeaf]); // we can't deal with arrays Int_t size = leaf->GetNdata(); if (size != 1) { cerr<<"ERROR in LauSPlot::readInputInfo : Tree has array branches, can't deal with those."<GetName(); // initialise an entry in the maps to hold the value leaves_[name] = leaf; } return kTRUE; } Bool_t LauSPlot::checkLeaves() const { // Analyse the names of the leaves to check that we have a leaf for // all bits of information we require, i.e. a likelihood value for // each combination of variable and species // If we have 2D PDFs then we have to look for some extra leaves for ( TwoDMap::const_iterator twodim_iter = twodimPDFs_.begin(); twodim_iter != twodimPDFs_.end(); ++twodim_iter ) { const TString& specName = twodim_iter->first; const TString& firstVarName = twodim_iter->second.first; const TString& secondVarName = twodim_iter->second.second; TString expectedName(specName); expectedName += firstVarName; expectedName += secondVarName; expectedName += "Like"; Bool_t found(kFALSE); for (LeafMap::const_iterator leaf_iter = leaves_.begin(); leaf_iter != leaves_.end(); ++leaf_iter) { const TString& leafName = leaf_iter->first; const TLeaf* leaf = leaf_iter->second; if ((leafName == expectedName) && (leaf != 0)) { found = kTRUE; break; } } if (!found) { cerr<<"ERROR in LauSPlot::checkLeaves : Could not find expected leaf \""<Like for (NumbMap::const_iterator fixd_iter = fixdSpecies_.begin(); fixd_iter != fixdSpecies_.end(); ++fixd_iter) { const TString& specName = fixd_iter->first; // if the signal is split we need to do a dedicated search // for sigTM and sigSCF, so skip the signal here if ( specName == "sig" && this->signalSplit() ) { continue; } for (NameSet::const_iterator vars_iter = variableNames_.begin(); vars_iter != variableNames_.end(); ++vars_iter) { const TString& varName = (*vars_iter); TString expectedName(specName); expectedName += varName; expectedName += "Like"; Bool_t found(kFALSE); for (LeafMap::const_iterator leaf_iter = leaves_.begin(); leaf_iter != leaves_.end(); ++leaf_iter) { const TString& leafName = leaf_iter->first; const TLeaf* leaf = leaf_iter->second; if ((leafName == expectedName) && (leaf != 0)) { found = kTRUE; break; } } if (!found) { cerr<<"ERROR in LauSPlot::checkLeaves : Could not find expected leaf \""<first; // if the signal is split we need to do a dedicated search // for sigTM and sigSCF, so skip the signal here if ( specName == "sig" && this->signalSplit() ) { continue; } for (NameSet::const_iterator vars_iter = variableNames_.begin(); vars_iter != variableNames_.end(); ++vars_iter) { const TString& varName = (*vars_iter); TString expectedName(specName); expectedName += varName; expectedName += "Like"; Bool_t found(kFALSE); for (LeafMap::const_iterator leaf_iter = leaves_.begin(); leaf_iter != leaves_.end(); ++leaf_iter) { const TString& leafName = leaf_iter->first; const TLeaf* leaf = leaf_iter->second; if ((leafName == expectedName) && (leaf != 0)) { found = kTRUE; break; } } if (!found) { cerr<<"ERROR in LauSPlot::checkLeaves : Could not find expected leaf \""<signalSplit() ) { // now need to search for the sigTM and sigSCF leaves for (NameSet::const_iterator vars_iter = variableNames_.begin(); vars_iter != variableNames_.end(); ++vars_iter) { const TString& varName = (*vars_iter); TString expectedName("sigTM"); expectedName += varName; expectedName += "Like"; Bool_t found(kFALSE); for (LeafMap::const_iterator leaf_iter = leaves_.begin(); leaf_iter != leaves_.end(); ++leaf_iter) { const TString& leafName = leaf_iter->first; const TLeaf* leaf = leaf_iter->second; if ((leafName == expectedName) && (leaf != 0)) { found = kTRUE; break; } } if (!found) { cerr<<"ERROR in LauSPlot::checkLeaves : Could not find expected leaf \""<first; const TLeaf* leaf = leaf_iter->second; if ((leafName == expectedName) && (leaf != 0)) { found = kTRUE; break; } } if (!found) { cerr<<"ERROR in LauSPlot::checkLeaves : Could not find expected leaf \""<first; const TLeaf* leaf = leaf_iter->second; if ((leafName == expectedName) && (leaf != 0)) { found = kTRUE; break; } } if (!found) { cerr<<"ERROR in LauSPlot::checkLeaves : Could not find expected leaf \""<cd(); cnTree_ = new TTree(cnTreeName_, cnTreeName_); cnTree_->SetDirectory(file_); this->definedCNBranches(kFALSE); } } void LauSPlot::createSWeightTree() { // check whether we've already created the tree if (!sweightTree_) { // if not change to the file's directory and create the tree sweightTreeName_ = inputTreeName_; sweightTreeName_ += "_sWeights"; file_->cd(); sweightTree_ = new TTree(sweightTreeName_, sweightTreeName_); sweightTree_->SetDirectory(file_); this->definedSWeightBranches(kFALSE); } } void LauSPlot::defineCNBranches() { if (this->definedCNBranches()) { cerr<<"ERROR in LauSPlot::defineCNBranches : Already defined branches, not doing it again."<Branch("iExpt", &iExpt_, "iExpt/I"); for (std::map::iterator excl_iter = cN_.begin(); excl_iter != cN_.end(); ++excl_iter) { const TString& exclName = excl_iter->first; NumbMap& species = excl_iter->second; for (NumbMap::iterator spec_iter = species.begin(); spec_iter != species.end(); ++spec_iter) { const TString& specName = spec_iter->first; Double_t * pointer = &(spec_iter->second); TString name(specName); name += "_cN"; if (exclName == "none") { name += "_all"; } else { name += "_no"; name += exclName; } TString thirdPart(name); thirdPart += "/D"; cnTree_->Branch(name, pointer, thirdPart); } } this->definedCNBranches(kTRUE); } void LauSPlot::defineSWeightBranches() { if (this->definedSWeightBranches()) { cerr<<"ERROR in LauSPlot::defineSWeightBranches : Already defined branches, not doing it again."<::iterator excl_iter = sWeightsCurrent_.begin(); excl_iter != sWeightsCurrent_.end(); ++excl_iter) { const TString& exclName = excl_iter->first; NumbMap& species = excl_iter->second; for (NumbMap::iterator spec_iter = species.begin(); spec_iter != species.end(); ++spec_iter) { const TString& specName = spec_iter->first; Double_t * pointer = &(spec_iter->second); TString name(specName); name += "_sWeight"; if (exclName == "none") { name += "_all"; } else { name += "_no"; name += exclName; } TString thirdPart(name); thirdPart += "/D"; sweightTree_->Branch(name, pointer, thirdPart); } } this->definedSWeightBranches(kTRUE); } void LauSPlot::setExperiment(Int_t iExpt) { if (!inputTree_) { cerr<<"ERROR in LauSPlot::setExperiment : Invalid pointer to data tree."<SetDirectory(file_); } // fill the event list with this experiment's events TString listName(eventList_->GetName()); listName.Prepend(">>"); TString selection("iExpt=="); selection += iExpt; cout<<"LauSPlot::setExperiment : Setting tree to experiment number "<Draw(listName,selection); // find how many events there are nEvents_ = eventList_->GetN(); cout<<" Found "<readExpt(); } void LauSPlot::readExpt() { for (Int_t iEvt(0); iEvt < nEvents_; ++iEvt) { // Find which entry from the full tree contains the requested event Long64_t iEntry = eventList_ ? eventList_->GetEntry(iEvt) : iEvt; if (iEntry<0) { // this shouldn't happen, but just in case... cerr<<"ERROR in LauSPlot::readExpt : Problem retrieving event."<Exit(EXIT_FAILURE); } // Then retrieve that entry from the tree inputTree_->GetEntry(iEntry); // If needed retrieve the SCF fraction values if ( this->signalSplit() ) { for (LeafMap::const_iterator leaf_iter = leaves_.begin(); leaf_iter != leaves_.end(); ++leaf_iter) { const TString& leafName = leaf_iter->first; const TLeaf* leaf = leaf_iter->second; if ((leafName == "sigSCFFrac") && (leaf != 0)) { scfFrac_[iEvt] = leaf->GetValue(); break; } } } // Copy the leaf values into discPdf_ for ( TwoDMap::const_iterator twodim_iter = twodimPDFs_.begin(); twodim_iter != twodimPDFs_.end(); ++twodim_iter ) { const TString& specName = twodim_iter->first; const TString& firstVarName = twodim_iter->second.first; const TString& secondVarName = twodim_iter->second.second; TString varName = firstVarName + secondVarName; TString expectedName(specName); expectedName += varName; expectedName += "Like"; for (LeafMap::const_iterator leaf_iter = leaves_.begin(); leaf_iter != leaves_.end(); ++leaf_iter) { const TString& leafName = leaf_iter->first; const TLeaf* leaf = leaf_iter->second; if ((leafName == expectedName) && (leaf != 0)) { discPdf_[iEvt][specName][varName] = leaf->GetValue(); break; } } } Bool_t needSignalSearch(kFALSE); for (NumbMap::const_iterator fixd_iter = fixdSpecies_.begin(); fixd_iter != fixdSpecies_.end(); ++fixd_iter) { const TString& specName = fixd_iter->first; // if the signal is split we need to do a dedicated search // for sigTM and sigSCF, so skip the signal here if ( specName == "sig" && this->signalSplit() ) { needSignalSearch = kTRUE; continue; } for (NameSet::const_iterator vars_iter = variableNames_.begin(); vars_iter != variableNames_.end(); ++vars_iter) { const TString& varName = (*vars_iter); TString expectedName(specName); expectedName += varName; expectedName += "Like"; for (LeafMap::const_iterator leaf_iter = leaves_.begin(); leaf_iter != leaves_.end(); ++leaf_iter) { const TString& leafName = leaf_iter->first; const TLeaf* leaf = leaf_iter->second; if ((leafName == expectedName) && (leaf != 0)) { discPdf_[iEvt][specName][varName] = leaf->GetValue(); break; } } } } for (NumbMap::const_iterator free_iter = freeSpecies_.begin(); free_iter != freeSpecies_.end(); ++free_iter) { const TString& specName = free_iter->first; // if the signal is split we need to do a dedicated search // for sigTM and sigSCF, so skip the signal here if ( specName == "sig" && this->signalSplit() ) { needSignalSearch = kTRUE; continue; } for (NameSet::const_iterator vars_iter = variableNames_.begin(); vars_iter != variableNames_.end(); ++vars_iter) { const TString& varName = (*vars_iter); TString expectedName(specName); expectedName += varName; expectedName += "Like"; for (LeafMap::const_iterator leaf_iter = leaves_.begin(); leaf_iter != leaves_.end(); ++leaf_iter) { const TString& leafName = leaf_iter->first; const TLeaf* leaf = leaf_iter->second; if ((leafName == expectedName) && (leaf != 0)) { discPdf_[iEvt][specName][varName] = leaf->GetValue(); break; } } } } if ( needSignalSearch ) { for (NameSet::const_iterator vars_iter = variableNames_.begin(); vars_iter != variableNames_.end(); ++vars_iter) { const TString& varName = (*vars_iter); TString specName("sigTM"); TString expectedName(specName); expectedName += varName; expectedName += "Like"; for (LeafMap::const_iterator leaf_iter = leaves_.begin(); leaf_iter != leaves_.end(); ++leaf_iter) { const TString& leafName = leaf_iter->first; const TLeaf* leaf = leaf_iter->second; if ((leafName == expectedName) && (leaf != 0)) { discPdf_[iEvt][specName][varName] = leaf->GetValue(); break; } } specName = "sigSCF"; expectedName = specName; expectedName += varName; expectedName += "Like"; for (LeafMap::const_iterator leaf_iter = leaves_.begin(); leaf_iter != leaves_.end(); ++leaf_iter) { const TString& leafName = leaf_iter->first; const TLeaf* leaf = leaf_iter->second; if ((leafName == expectedName) && (leaf != 0)) { discPdf_[iEvt][specName][varName] = leaf->GetValue(); break; } } } } } } void LauSPlot::runCalculations(const TString& option) { // Calculates the sWeights and cN coeffs // The option controls the print level: // "Q" - no print out (default) // "V" - prints the estimated # of events in species // "VV" - as "V" + the MINUIT printing + sums of weights for control if (!this->readInput()) { cerr<<"ERROR in LauSPlot::runCalculations : The input ntuple has not been successfully read, can't calculate anything."<checkFitter(); // Loop over experiments for (iExpt_ = firstExpt_; iExpt_ < (firstExpt_+nExpt_); ++iExpt_) { this->setExperiment(iExpt_); if (nEvents_ < 1) { cerr<<"ERROR in LauSPlot::runCalculations : Zero events in experiment "<calcTotPDFValues(exclName); // Reset the fitter this->initialiseFitter(opt); // Set the parameters to their initial values this->setFitParameters(); // Run the fit this->runFit(); // Get the fitted parameter values back this->retrieveFittedParameters(opt); // Get the covariance matrix Bool_t covMatOK = this->calcCovMatrix(); Double_t * covmat(0); if (!covMatOK) { TVirtualFitter * fitter = TVirtualFitter::GetFitter(); covmat = fitter->GetCovarianceMatrix(); } if (opt.Contains("W")) { this->printCovMatrixElements(covmat); } // calculate the cN and sWeights from the covariance matrix if (nFixdSpecies_ > 0) { this->calcCNCoeffs(exclName, covmat); } this->calcSWeights(exclName, covmat); // print verbose info if required if (opt.Contains("W")) { this->printSumOfWeights(exclName); } } // Finally fill all the branches for this experiment if (nFixdSpecies_ > 0) { this->fillCNBranches(); } this->fillSWeightBranches(); } } void LauSPlot::checkFitter() const { TString minuitName("TFitter"); TVirtualFitter * fitter = TVirtualFitter::GetFitter(); if (fitter) { TString fitterName(fitter->IsA()->GetName()); if (fitterName != minuitName) { delete fitter; fitter = 0; } } fitter = TVirtualFitter::Fitter(0); } void LauSPlot::initialiseFitter(const TString& opt) { TVirtualFitter * fitter = TVirtualFitter::GetFitter(); fitter->Clear(); fitter->SetFCN(Yields); fitter->SetObjectFit(this); // Set the print level Double_t arglist[10]; if (opt.Contains("Q")) { arglist[0]=-1; } if (opt.Contains("V")) { arglist[0]=0; } if (opt.Contains("W")) { arglist[0]=1; } fitter->ExecuteCommand("SET PRINT", arglist, 1); // Need to set the "SET ERR" command to +0.5 for +/-1 sigma errors // for maximum likelihood fit. arglist[0] = 0.5; fitter->ExecuteCommand("SET ERR", arglist, 1); } void LauSPlot::setFitParameters() const { TVirtualFitter * fitter = TVirtualFitter::GetFitter(); // must add the parameters in the same order as they are stored in pdfTot_ Int_t ispecies(0); const NumbMap& species = pdfTot_.front(); for (NumbMap::const_iterator spec_iter = species.begin(); spec_iter != species.end(); ++spec_iter) { const TString& name(spec_iter->first); // starting parameters should be the original values, // not those that came out of the last fit NumbMap::const_iterator free_iter = origFreeSpecies_.find(name); NumbMap::const_iterator fixd_iter = origFixdSpecies_.find(name); Bool_t fixed = fixd_iter != origFixdSpecies_.end(); Double_t value(0.0); if (fixed) { value = fixd_iter->second; } else { value = free_iter->second; } fitter->SetParameter(ispecies, name, value, 1, 0, 0); if (fixed) { fitter->FixParameter(ispecies); } ++ispecies; } } void LauSPlot::runFit() { TVirtualFitter * fitter = TVirtualFitter::GetFitter(); Double_t arglist[10]; arglist[0] = 1000*nFreeSpecies_; // maximum iterations arglist[1] = 0.05; // tolerance : min EDM = 0.001*tolerance // Execute MIGRAD Int_t fitStatus = fitter->ExecuteCommand("MIGRAD", arglist, 2); if (fitStatus != 0) { cerr<<"ERROR in LauSPlot::runFit : Error during MIGRAD minimisation."<ExecuteCommand("HESSE", arglist, 1); if (fitStatus != 0) { cerr<<"ERROR in LauSPlot::runFit : Error during HESSE error calculation."<first<<","<first<<"] = "<first<<","<first<<"] = "<first); NumbMap::iterator free_iter = freeSpecies_.find(name); if (free_iter != freeSpecies_.end()) { free_iter->second = fitter->GetParameter(ispecies); if (!opt.Contains("Q")) { cout<<"Estimated # of events in species "<second<first; Double_t sumweight(0.0); for (Int_t iEvt(0); iEvt < nEvents_; ++iEvt) { const NumbMap& specWeightMap = sWeights_[iEvt].find(exclName)->second; Double_t weight = specWeightMap.find(specName)->second; sumweight += weight; } cout<<"Sum of sWeights for species \""< denominator(nEvents_); for (Int_t iEvt(0); iEvtfirst; Double_t specNumEvents = spec_iter->second; denominator[iEvt] += specNumEvents * pdfTot_[iEvt][specName]; } for (NumbMap::const_iterator spec_iter = fixdSpecies_.begin(); spec_iter != fixdSpecies_.end(); ++spec_iter) { const TString& specName = spec_iter->first; Double_t specNumEvents = spec_iter->second; denominator[iEvt] += specNumEvents * pdfTot_[iEvt][specName]; } // Square to get the final denominator denominator[iEvt] *= denominator[iEvt]; } // Then calculate each element Int_t i(0); for (NumbMap::const_iterator spec_iter_i = freeSpecies_.begin(); spec_iter_i != freeSpecies_.end(); ++spec_iter_i) { const TString& specName_i = spec_iter_i->first; Int_t j(0); for (NumbMap::const_iterator spec_iter_j = freeSpecies_.begin(); spec_iter_j != freeSpecies_.end(); ++spec_iter_j) { const TString& specName_j = spec_iter_j->first; invMatrix(i,j) = 0.0; for (Int_t iEvt(0); iEvtfirst; // if the signal is split we need to do a dedicated search // for sigTM and sigSCF, so skip the signal here if ( specName == "sig" && this->signalSplit() ) { needSignalSearch = kTRUE; continue; } pdfTot_[iEvt][specName] = 1.0; // loop through the 2D histo list NameSet skipList; for ( TwoDMap::const_iterator twodim_iter = twodimPDFs_.begin(); twodim_iter != twodimPDFs_.end(); ++twodim_iter ) { // if the entry doesn't refer to this // species then skip on if ( specName != twodim_iter->first ) { continue; } // retrieve the two variable names const TString& firstVarName = twodim_iter->second.first; const TString& secondVarName = twodim_iter->second.second; if ( firstVarName != exclName && secondVarName != exclName ) { // if neither name is the one being excluded then... // add them both to the skip list skipList.insert( firstVarName ); skipList.insert( secondVarName ); // and multiply the total by the combined PDF value TString varName = firstVarName + secondVarName; pdfTot_[iEvt][specName] *= discPdf_[iEvt][specName][varName]; } } // loop through all the variables for (NameSet::const_iterator var_iter = variableNames_.begin(); var_iter != variableNames_.end(); ++var_iter) { const TString& varName = (*var_iter); // if the variable isn't the one being excluded if (exclName != varName) { // and it's not involved in a 2D PDF if ( skipList.find(varName) == skipList.end() ) { // multiply the total by its PDF value pdfTot_[iEvt][specName] *= discPdf_[iEvt][specName][varName]; } } } } for (NumbMap::const_iterator spec_iter = freeSpecies_.begin(); spec_iter != freeSpecies_.end(); ++spec_iter) { const TString& specName = spec_iter->first; // if the signal is split we need to do a dedicated search // for sigTM and sigSCF, so skip the signal here if ( specName == "sig" && this->signalSplit() ) { needSignalSearch = kTRUE; continue; } pdfTot_[iEvt][specName] = 1.0; // loop through the 2D histo list NameSet skipList; for ( TwoDMap::const_iterator twodim_iter = twodimPDFs_.begin(); twodim_iter != twodimPDFs_.end(); ++twodim_iter ) { // if the entry doesn't refer to this // species then skip on if ( specName != twodim_iter->first ) { continue; } // retrieve the two variable names const TString& firstVarName = twodim_iter->second.first; const TString& secondVarName = twodim_iter->second.second; if ( firstVarName != exclName && secondVarName != exclName ) { // if neither name is the one being excluded then... // add them both to the skip list skipList.insert( firstVarName ); skipList.insert( secondVarName ); // and multiply the total by the combined PDF value TString varName = firstVarName + secondVarName; pdfTot_[iEvt][specName] *= discPdf_[iEvt][specName][varName]; } } // loop through all the variables for (NameSet::const_iterator var_iter = variableNames_.begin(); var_iter != variableNames_.end(); ++var_iter) { const TString& varName = (*var_iter); // if the variable isn't the one being excluded if (exclName != varName) { // and it's not involved in a 2D PDF if ( skipList.find(varName) == skipList.end() ) { // multiply the total by its PDF value pdfTot_[iEvt][specName] *= discPdf_[iEvt][specName][varName]; } } } } if ( needSignalSearch ) { // loop through the 2D histo list TString specName("sigTM"); Double_t tmPDFVal(1.0); NameSet skipList; for ( TwoDMap::const_iterator twodim_iter = twodimPDFs_.begin(); twodim_iter != twodimPDFs_.end(); ++twodim_iter ) { // if the entry doesn't refer to this // species then skip on if ( specName != twodim_iter->first ) { continue; } // retrieve the two variable names const TString& firstVarName = twodim_iter->second.first; const TString& secondVarName = twodim_iter->second.second; if ( firstVarName != exclName && secondVarName != exclName ) { // if neither name is the one being excluded then... // add them both to the skip list skipList.insert( firstVarName ); skipList.insert( secondVarName ); // and multiply the total by the combined PDF value TString varName = firstVarName + secondVarName; tmPDFVal *= discPdf_[iEvt][specName][varName]; } } // loop through all the variables for (NameSet::const_iterator var_iter = variableNames_.begin(); var_iter != variableNames_.end(); ++var_iter) { const TString& varName = (*var_iter); // if the variable isn't the one being excluded if (exclName != varName) { // and it's not involved in a 2D PDF if ( skipList.find(varName) == skipList.end() ) { // multiply the total by its PDF value tmPDFVal *= discPdf_[iEvt][specName][varName]; } } } tmPDFVal *= (1.0 - scfFrac_[iEvt]); // loop through the 2D histo list specName = "sigSCF"; Double_t scfPDFVal(1.0); skipList.clear(); for ( TwoDMap::const_iterator twodim_iter = twodimPDFs_.begin(); twodim_iter != twodimPDFs_.end(); ++twodim_iter ) { // if the entry doesn't refer to this // species then skip on if ( specName != twodim_iter->first ) { continue; } // retrieve the two variable names const TString& firstVarName = twodim_iter->second.first; const TString& secondVarName = twodim_iter->second.second; if ( firstVarName != exclName && secondVarName != exclName ) { // if neither name is the one being excluded then... // add them both to the skip list skipList.insert( firstVarName ); skipList.insert( secondVarName ); // and multiply the total by the combined PDF value TString varName = firstVarName + secondVarName; scfPDFVal *= discPdf_[iEvt][specName][varName]; } } // loop through all the variables for (NameSet::const_iterator var_iter = variableNames_.begin(); var_iter != variableNames_.end(); ++var_iter) { const TString& varName = (*var_iter); // if the variable isn't the one being excluded if (exclName != varName) { // and it's not involved in a 2D PDF if ( skipList.find(varName) == skipList.end() ) { // multiply the total by its PDF value scfPDFVal *= discPdf_[iEvt][specName][varName]; } } } if ( exclName == "DP" || !this->scfDPSmear() ) { scfPDFVal *= scfFrac_[iEvt]; } pdfTot_[iEvt]["sig"] = tmPDFVal + scfPDFVal; } } } void LauSPlot::calcCNCoeffs(const TString& exclName, const Double_t *covmat) { // Computes the cN for the extended sPlots from the covariance matrix if (nFixdSpecies_ <= 0) { return; } Int_t species_n(0); for (NumbMap::const_iterator iter_n = freeSpecies_.begin(); iter_n != freeSpecies_.end(); ++iter_n) { Int_t species_j(0); const TString& specName = iter_n->first; Double_t value = iter_n->second; cN_[exclName][specName] = value; for (NumbMap::const_iterator iter_j = freeSpecies_.begin(); iter_j != freeSpecies_.end(); ++iter_j) { if (covmat) { cN_[exclName][specName] -= covmat[species_n*nSpecies_+species_j]; } else { cN_[exclName][specName] -= covMat_(species_n,species_j); } ++species_j; } ++species_n; } } void LauSPlot::calcSWeights(const TString& exclName, Double_t *covmat) { // Computes the sWeights from the covariance matrix // NB for the extended sPlot the sum in the denominator is still over all species, // while that in the numerator is only over the free species. // Similarly the sWeights can only be calculated for the free species. Double_t numerator(0.0), denominator(0.0); for (Int_t iEvent = 0; iEvent < nEvents_; ++iEvent) { denominator = 0.0; for (NumbMap::const_iterator free_iter = freeSpecies_.begin(); free_iter != freeSpecies_.end(); ++free_iter) { denominator += free_iter->second * pdfTot_[iEvent][free_iter->first]; } for (NumbMap::const_iterator fixd_iter = fixdSpecies_.begin(); fixd_iter != fixdSpecies_.end(); ++fixd_iter) { denominator += fixd_iter->second * pdfTot_[iEvent][fixd_iter->first]; } Int_t species_n(0); for (NumbMap::const_iterator iter_n = freeSpecies_.begin(); iter_n != freeSpecies_.end(); ++iter_n) { numerator = 0.0; Int_t species_j(0); for (NumbMap::const_iterator iter_j = freeSpecies_.begin(); iter_j != freeSpecies_.end(); ++iter_j) { if (covmat) { numerator += covmat[species_n*nSpecies_+species_j] * pdfTot_[iEvent][iter_j->first]; } else { numerator += covMat_(species_n,species_j) * pdfTot_[iEvent][iter_j->first]; } ++species_j; } sWeights_[iEvent][exclName][iter_n->first] = numerator/denominator; ++species_n; } } } void LauSPlot::fillCNBranches() { if (!cnTree_) { cerr<<"ERROR in LauSPlot::fillCNBranches : Tree not created, cannot fill branches."<definedCNBranches()) { this->defineCNBranches(); } cnTree_->Fill(); } void LauSPlot::fillSWeightBranches() { if (!sweightTree_) { cerr<<"ERROR in LauSPlot::fillSWeightBranches : Tree not created, cannot fill branches."<definedSWeightBranches()) { this->copyEventWeights(0); this->defineSWeightBranches(); } for (Int_t iEvent = 0; iEvent < nEvents_; ++iEvent) { this->copyEventWeights(iEvent); sweightTree_->Fill(); } } void LauSPlot::copyEventWeights(Int_t iEvent) { for (std::map::const_iterator excl_iter = sWeights_[iEvent].begin(); excl_iter != sWeights_[iEvent].end(); ++excl_iter) { const TString& exclName = excl_iter->first; const NumbMap& species = excl_iter->second; for (NumbMap::const_iterator spec_iter = species.begin(); spec_iter != species.end(); ++spec_iter) { const TString& specName = spec_iter->first; sWeightsCurrent_[exclName][specName] = spec_iter->second; } } } void LauSPlot::writeOutResults() { // write out the results // remove the transient objects that we don't want (re-)written to the file if (eventList_) { delete eventList_; eventList_ = 0; } if (inputTree_) { delete inputTree_; inputTree_ = 0; } // first add the input tree as a friend of the output tree this->addFriendTree(); // then write everything to the file and clean up file_->cd(); file_->Write(); file_->Close(); delete file_; file_ = 0; } void LauSPlot::addFriendTree() { if (!sweightTree_) { cerr<<"ERROR in LauSPlot::addFriendTree : Tree not created, cannot add friend."<AddFriend(inputTreeName_,fileName_); } void Yields(Int_t &, Double_t *, Double_t &f, Double_t *x, Int_t /*iflag*/) { // FCN-function for Minuit f = 0.0; TVirtualFitter *fitter = TVirtualFitter::GetFitter(); LauSPlot* theModel = dynamic_cast(fitter->GetObjectFit()); const std::vector& pdfTot = theModel->totalPdf(); Double_t ntot(0.0); for (std::vector::const_iterator evt_iter = pdfTot.begin(); evt_iter != pdfTot.end(); ++evt_iter) { // loop over events const LauSPlot::NumbMap& species = (*evt_iter); Int_t ispecies(0); Double_t lik(0.0); ntot = 0.0; for (LauSPlot::NumbMap::const_iterator spec_iter = species.begin(); spec_iter != species.end(); ++spec_iter) { // loop over species lik += x[ispecies] * spec_iter->second; ntot += x[ispecies]; ++ispecies; } if (lik < 0.0) { // make f the worst possible value to force MINUIT // out of this region of parameter space f = -DBL_MAX; break; } else { f += TMath::Log(lik); } } // extended likelihood f = (ntot-f); } diff --git a/src/LauScfMap.cc b/src/LauScfMap.cc index eb1b6f0..6dabe2f 100644 --- a/src/LauScfMap.cc +++ b/src/LauScfMap.cc @@ -1,211 +1,210 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauScfMap.cc \brief File containing implementation of LauScfMap class. */ #include #include #include #include using std::cout; using std::cerr; using std::flush; using std::endl; #include "TAxis.h" #include "TH2.h" #include "TSystem.h" #include "LauScfMap.hh" -ClassImp(LauScfMap) LauScfMap::LauScfMap(): nBinsX_(-1), nBinsY_(-1), numberOfBins_(-1) { } LauScfMap::~LauScfMap() { for (std::vector::iterator iter = histos_.begin(); iter != histos_.end(); ++iter) { delete (*iter); } } void LauScfMap::setHistos(const std::vector& histos) { // Check that we have enough histograms Int_t nBinsX = histos.front()->GetNbinsX(); Int_t nBinsY = histos.front()->GetNbinsY(); Int_t nHist = histos.size(); if (nHist != nBinsX*nBinsY) { cerr<<"ERROR in LauScfMap::setHistos : There should be as many histograms supplied as there are bins in each of them."<::iterator iter = histos_.begin(); iter != histos_.end(); ++iter) { delete (*iter); } histos_.clear(); // Make sure we have enough space for the new histograms histos_.reserve(nHist); // Loop through the supplied vector // Clone each histogram and store it for (std::vector::const_iterator iter = histos.begin(); iter != histos.end(); ++iter) { TH2* histo = dynamic_cast((*iter)->Clone()); if ( histo==0 ) { cerr<<"ERROR in LauScfMap::setHistos : Problem cloning one of the histograms."<Exit(EXIT_FAILURE); } histos_.push_back(histo); } if ( histos_.size() != histos.size() ) { cerr<<"ERROR in LauScfMap::setHistos : Problem cloning the histograms."<Exit(EXIT_FAILURE); } // Now we need to setup the map // First clear it contribs_.clear(); // Fill in the map that links, to each reco bin, a vector with the numbers of the tru bins // that have non-zero contributions in that reco bin // Loop over each histogram bin for (Int_t j(0); jGetBin(i+1,j+1); std::vector& truBins = contribs_[binNo]; truBins.reserve(nHist); for (Int_t k(0); kGetBinContent(binNo); if (content>0.0) { truBins.push_back(k); } } } } } void LauScfMap::listBinCentres( std::vector& xCoords, std::vector& yCoords) const { // Create the list of fake points, located at the centres of the // true bins, that we will add to the data points, so as to cache // the DP amplitudes, scfFractions and jacobians at those points. // that have non-zero contributions in that reco bin const TAxis* xAxis = histos_.front()->GetXaxis(); Double_t xMax = xAxis->GetXmax(); Double_t xMin = xAxis->GetXmin(); Double_t xIncrement = (Double_t)((xMax - xMin)/nBinsX_); const TAxis* yAxis = histos_.front()->GetYaxis(); Double_t yMax = yAxis->GetXmax(); Double_t yMin = yAxis->GetXmin(); Double_t yIncrement = (Double_t)((yMax - yMin)/nBinsY_); // Loop over each histogram bin Double_t yCoord = yMin + yIncrement/2; for (Int_t j(1); j<=nBinsY_; ++j) { Double_t xCoord = xMin + xIncrement/2; for (Int_t i(1); i<=nBinsX_; ++i) { xCoords.push_back(xCoord); yCoords.push_back(yCoord); xCoord += xIncrement; } yCoord += yIncrement; } } Int_t LauScfMap::binNumber(Double_t xCoord, Double_t yCoord) const { const TH2* histo = histos_.front(); if (histo != 0) { return histo->FindFixBin(xCoord,yCoord); } else { cerr<<"ERROR in LauScfMap::recoBin : No valid histograms found."<* LauScfMap::trueBins(Int_t recoBin) const { std::map< Int_t, std::vector >::const_iterator iter = contribs_.find(recoBin); if (iter != contribs_.end()) { return &(iter->second); } else { return 0; } } Double_t LauScfMap::prob(Int_t recoBin, Int_t trueBin) const { const TH2* histo = histos_[trueBin]; if (histo != 0) { return histo->GetBinContent(recoBin); } else { cerr<<"ERROR in LauScfMap::prob : No histogram found for true bin "<GetBinXYZ( trueBin, x, y, z ); Int_t theBin = nBinsX_*(y-1) + (x-1); if ( theBin < 0 || static_cast(theBin) >= histos_.size() ) { cerr<<"ERROR in LauScfMap::trueHist : No histogram found for true bin "<Exit(EXIT_FAILURE); } TH2* histo = histos_[theBin]; if ( histo == 0 ) { cerr<<"ERROR in LauScfMap::trueHist : Null histogram pointer found for true bin "<Exit(EXIT_FAILURE); } return histo; } diff --git a/src/LauSigmaRes.cc b/src/LauSigmaRes.cc index d7f5f30..8f2a852 100644 --- a/src/LauSigmaRes.cc +++ b/src/LauSigmaRes.cc @@ -1,306 +1,305 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauSigmaRes.cc \brief File containing implementation of LauSigmaRes class. */ #include #include "LauConstants.hh" #include "LauSigmaRes.hh" #include "LauResonanceInfo.hh" -ClassImp(LauSigmaRes) LauSigmaRes::LauSigmaRes(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), mPiSq4_(4.0*LauConstants::mPiSq), sAdler_(LauConstants::mPiSq*0.5), b1_(0), b2_(0), a_(0), m0_(0) { // Initialise various constants mPiSq4_ = 4.0*LauConstants::mPiSq; sAdler_ = LauConstants::mPiSq*0.5; // Adler zero at 0.5*(mpi)^2 // constant factors from BES data const Double_t b1Val = 0.5843; const Double_t b2Val = 1.6663; const Double_t aVal = 1.082; const Double_t m0Val = 0.9264; const TString& parNameBase = this->getSanitisedName(); TString b1Name(parNameBase); b1Name += "_b1"; b1_ = resInfo->getExtraParameter( b1Name ); if ( b1_ == 0 ) { b1_ = new LauParameter( b1Name, b1Val, 0.0, 100.0, kTRUE ); b1_->secondStage(kTRUE); resInfo->addExtraParameter( b1_ ); } TString b2Name(parNameBase); b2Name += "_b2"; b2_ = resInfo->getExtraParameter( b2Name ); if ( b2_ == 0 ) { b2_ = new LauParameter( b2Name, b2Val, 0.0, 100.0, kTRUE ); b2_->secondStage(kTRUE); resInfo->addExtraParameter( b2_ ); } TString aName(parNameBase); aName += "_A"; a_ = resInfo->getExtraParameter( aName ); if ( a_ == 0 ) { a_ = new LauParameter( aName, aVal, 0.0, 10.0, kTRUE ); a_->secondStage(kTRUE); resInfo->addExtraParameter( a_ ); } TString m0Name(parNameBase); m0Name += "_m0"; m0_ = resInfo->getExtraParameter( m0Name ); if ( m0_ == 0 ) { m0_ = new LauParameter( m0Name, m0Val, 0.0, 10.0, kTRUE ); m0_->secondStage(kTRUE); resInfo->addExtraParameter( m0_ ); } } LauSigmaRes::~LauSigmaRes() { } void LauSigmaRes::initialise() { this->checkDaughterTypes(); Double_t resSpin = this->getSpin(); if (resSpin != 0) { std::cerr << "WARNING in LauSigmaRes::initialise : Resonance spin is " << resSpin << "." << std::endl; std::cerr << " : Sigma amplitude is only for scalers, resetting spin to 0." << std::endl; this->changeResonance( -1.0, -1.0, 0 ); } } void LauSigmaRes::checkDaughterTypes() const { // Check that the daughter tracks are the same type. Otherwise issue a warning // and set the type to be pion for the Sigma distribution. Int_t resPairAmpInt = this->getPairInt(); if (resPairAmpInt < 1 || resPairAmpInt > 3) { std::cerr << "WARNING in LauSigmaRes::checkDaughterTypes : resPairAmpInt = " << resPairAmpInt << " is out of the range [1,2,3]." << std::endl; return; } const TString& nameDaug1 = this->getNameDaug1(); const TString& nameDaug2 = this->getNameDaug2(); if (!nameDaug1.CompareTo(nameDaug2, TString::kExact)) { // Daughter types agree. Find out if we have pion or kaon system if (!nameDaug1.Contains("pi")) { std::cerr << "ERROR in LauSigmaRes::checkDaughterTypes : Sigma model is using daughters \""< mPiSq4_) {rho = TMath::Sqrt(1.0 - mPiSq4_/s);} const Double_t m0Val = this->getM0Value(); const Double_t m0Sq = m0Val * m0Val; const Double_t aVal = this->getAValue(); const Double_t b1Val = this->getB1Value(); const Double_t b2Val = this->getB2Value(); Double_t f = b2Val*s + b1Val; // f(s) function Double_t numerator = s - sAdler_; Double_t denom = m0Sq - sAdler_; Double_t gamma(0.0); if (TMath::Abs(denom) > 1e-10 && TMath::Abs(aVal) > 1e-10) { // Decay width of the system gamma = rho*(numerator/denom)*f*TMath::Exp(-(s - m0Sq)/aVal); } // Now form the complex amplitude - use relativistic BW form (without barrier factors) // Note that the M factor in the denominator is not the "pole" at ~500 MeV, but is // m0_ = 0.9264, the mass when the phase shift goes through 90 degrees. Double_t dMSq = m0Sq - s; Double_t widthTerm = gamma*m0Val; LauComplex resAmplitude(dMSq, widthTerm); Double_t denomFactor = dMSq*dMSq + widthTerm*widthTerm; Double_t invDenomFactor = 0.0; if (denomFactor > 1e-10) {invDenomFactor = 1.0/denomFactor;} resAmplitude.rescale(spinTerm*invDenomFactor); return resAmplitude; } const std::vector& LauSigmaRes::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixB1Value() ) { this->addFloatingParameter( b1_ ); } if ( ! this->fixB2Value() ) { this->addFloatingParameter( b2_ ); } if ( ! this->fixAValue() ) { this->addFloatingParameter( a_ ); } if ( ! this->fixM0Value() ) { this->addFloatingParameter( m0_ ); } return this->getParameters(); } void LauSigmaRes::setResonanceParameter(const TString& name, const Double_t value) { // Set various parameters for the lineshape if (name == "b1") { this->setB1Value(value); std::cout << "INFO in LauSigmaRes::setResonanceParameter : Setting parameter b1 = " << this->getB1Value() << std::endl; } else if (name == "b2") { this->setB2Value(value); std::cout << "INFO in LauSigmaRes::setResonanceParameter : Setting parameter b2 = " << this->getB2Value() << std::endl; } else if (name == "A") { this->setAValue(value); std::cout << "INFO in LauSigmaRes::setResonanceParameter : Setting parameter A = " << this->getAValue() << std::endl; } else if (name == "m0") { this->setM0Value(value); std::cout << "INFO in LauSigmaRes::setResonanceParameter : Setting parameter m0 = " << this->getM0Value() << std::endl; } else { std::cerr << "WARNING in LauSigmaRes::setResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } void LauSigmaRes::floatResonanceParameter(const TString& name) { if (name == "b1") { if ( b1_->fixed() ) { b1_->fixed( kFALSE ); this->addFloatingParameter( b1_ ); } else { std::cerr << "WARNING in LauSigmaRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "b2") { if ( b2_->fixed() ) { b2_->fixed( kFALSE ); this->addFloatingParameter( b2_ ); } else { std::cerr << "WARNING in LauSigmaRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "A") { if ( a_->fixed() ) { a_->fixed( kFALSE ); this->addFloatingParameter( a_ ); } else { std::cerr << "WARNING in LauSigmaRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "m0") { if ( m0_->fixed() ) { m0_->fixed( kFALSE ); this->addFloatingParameter( m0_ ); } else { std::cerr << "WARNING in LauSigmaRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else { std::cerr << "WARNING in LauSigmaRes::fixResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } LauParameter* LauSigmaRes::getResonanceParameter(const TString& name) { if (name == "b1") { return b1_; } else if (name == "b2") { return b2_; } else if (name == "A") { return a_; } else if (name == "m0") { return m0_; } else { std::cerr << "WARNING in LauSigmaRes::getResonanceParameter: Parameter name not reconised." << std::endl; return 0; } } void LauSigmaRes::setB1Value(const Double_t b1) { b1_->value( b1 ); b1_->genValue( b1 ); b1_->initValue( b1 ); } void LauSigmaRes::setB2Value(const Double_t b2) { b2_->value( b2 ); b2_->genValue( b2 ); b2_->initValue( b2 ); } void LauSigmaRes::setAValue(const Double_t A) { a_->value( A ); a_->genValue( A ); a_->initValue( A ); } void LauSigmaRes::setM0Value(const Double_t m0) { m0_->value( m0 ); m0_->genValue( m0 ); m0_->initValue( m0 ); } diff --git a/src/LauSigmoidPdf.cc b/src/LauSigmoidPdf.cc index 886f474..0619de9 100644 --- a/src/LauSigmoidPdf.cc +++ b/src/LauSigmoidPdf.cc @@ -1,159 +1,158 @@ /* Copyright 2012 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauSigmoidPdf.cc \brief File containing implementation of LauSigmoidPdf class. */ #include #include using std::cout; using std::cerr; using std::endl; using std::vector; #include "TMath.h" #include "TSystem.h" #include "LauConstants.hh" #include "LauSigmoidPdf.hh" -ClassImp(LauSigmoidPdf) LauSigmoidPdf::LauSigmoidPdf(const TString& theVarName, const vector& params, Double_t minAbscissa, Double_t maxAbscissa) : LauAbsPdf(theVarName, params, minAbscissa, maxAbscissa), a_(0), b_(0) { // Constructor for the general form of a Sigmoid PDF. // // The parameters in params "a" and "b" define the steepness of the // slope and shift of the distribution (negative parameter "a" flips // the distribution around the y-axis). // The last two arguments specify the range in which the PDF is // defined, and the PDF will be normalised w.r.t. these limits. a_ = this->findParameter("a"); b_ = this->findParameter("b"); if ((this->nParameters() != 2) || (a_ == 0) || (b_ == 0)) { cerr<<"ERROR in LauSigmoidPdf constructor: LauSigmoidPdf requires 2 parameters: \"a\" and \"b\"."<Exit(EXIT_FAILURE); } // Cache the normalisation factor this->calcNorm(); } LauSigmoidPdf::~LauSigmoidPdf() { // Destructor } LauSigmoidPdf::LauSigmoidPdf(const LauSigmoidPdf& other) : LauAbsPdf(other.varName(), other.getParameters(), other.getMinAbscissa(), other.getMaxAbscissa()) { // Copy constructor this->setRandomFun(other.getRandomFun()); this->calcNorm(); } void LauSigmoidPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Get our abscissa Double_t abscissa = abscissas[0]; // Get the up to date parameter values Double_t a = a_->unblindValue(); Double_t b = b_->unblindValue(); // Calculate the value of the exponent for the given value of the abscissa. Double_t exponent = -a*abscissa + b; Double_t value = 1.0/(1.0+ TMath::Exp(exponent)); this->setUnNormPDFVal(value); // if the parameters are floating then we // need to recalculate the normalisation if (!this->cachePDF() && !this->withinNormCalc() && !this->withinGeneration()) { this->calcNorm(); } } void LauSigmoidPdf::calcNorm() { // Get the up to date parameter values Double_t a = a_->unblindValue(); Double_t b = b_->unblindValue(); // Calculate the normalisation of the sigmoid and cache it. Double_t norm(0.0); if (TMath::Abs(a) > 1e-10) { Double_t expb = TMath::Exp(b); norm = TMath::Log( TMath::Exp(a * this->getMaxAbscissa()) + expb ) - TMath::Log( TMath::Exp(a * this->getMinAbscissa()) + expb ); norm /= a; } this->setNorm(norm); } void LauSigmoidPdf::calcPDFHeight(const LauKinematics* /*kinematics*/) { if (this->heightUpToDate()) { return; } // Get the up to date parameter values Double_t a = a_->unblindValue(); LauAbscissas maxPoint(1); maxPoint[0] = 0; // Calculate the PDF height for the Sigmoid function. if (a > 0.0) { maxPoint[0] = this->getMaxAbscissa(); } else { maxPoint[0] = this->getMinAbscissa(); } this->calcLikelihoodInfo(maxPoint); Double_t height = this->getUnNormLikelihood(); this->setMaxHeight(height); } diff --git a/src/LauSimFitMaster.cc b/src/LauSimFitMaster.cc index 1160f74..d236d7a 100644 --- a/src/LauSimFitMaster.cc +++ b/src/LauSimFitMaster.cc @@ -1,1050 +1,1049 @@ /* Copyright 2013 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauSimFitMaster.cc \brief File containing implementation of LauSimFitMaster class. */ #include #include #include #include "TMath.h" #include "TMatrixD.h" #include "TMessage.h" #include "TMonitor.h" #include "TObjArray.h" #include "TObjString.h" #include "TServerSocket.h" #include "TSocket.h" #include "TSystem.h" #include "LauAbsFitter.hh" #include "LauFitNtuple.hh" #include "LauFitter.hh" #include "LauFormulaPar.hh" #include "LauParameter.hh" #include "LauParamFixed.hh" #include "LauSimFitMaster.hh" -ClassImp(LauSimFitMaster) LauSimFitMaster::LauSimFitMaster( UInt_t numSlaves, UInt_t port ) : nSlaves_(numSlaves), reqPort_(port), socketMonitor_(0), messageFromSlave_(0), fitNtuple_(0) { messagesToSlaves_.resize( nSlaves_ ); for ( UInt_t iSlave(0); iSlave < nSlaves_; ++iSlave ) { messagesToSlaves_[iSlave] = new TMessage(); } } LauSimFitMaster::~LauSimFitMaster() { delete socketMonitor_; socketMonitor_ = 0; // Tell all slaves that they are finished and delete corresponding socket TString msgStr("Finish"); TMessage message( kMESS_STRING ); message.WriteTString(msgStr); for ( std::vector::iterator iter = sSlaves_.begin(); iter != sSlaves_.end(); ++iter ) { (*iter)->Send(message); (*iter)->Close(); delete (*iter); } sSlaves_.clear(); // Remove the components created to apply constraints to fit parameters for (std::vector::iterator iter = conVars_.begin(); iter != conVars_.end(); ++iter){ if ( !(*iter)->isLValue() ){ delete (*iter); (*iter) = 0; } } conVars_.clear(); // Remove all fit parameters for ( std::vector::iterator iter = params_.begin(); iter != params_.end(); ++iter ) { delete *iter; } params_.clear(); for ( std::vector::iterator iter = vectorPar_.begin(); iter != vectorPar_.end(); ++iter ) { delete[] (*iter); } vectorPar_.clear(); delete messageFromSlave_; messageFromSlave_ = 0; for ( std::vector::iterator iter = messagesToSlaves_.begin(); iter != messagesToSlaves_.end(); ++iter ) { delete (*iter); } messagesToSlaves_.clear(); delete fitNtuple_; } void LauSimFitMaster::initSockets() { if ( socketMonitor_ != 0 ) { std::cerr << "ERROR in LauSimFitMaster::initSockets : Sockets already initialised." << std::endl; return; } //initialise socket connection, then accept a connection and return a full-duplex communication socket. socketMonitor_ = new TMonitor(); TServerSocket *ss = new TServerSocket( reqPort_, kFALSE ); UInt_t actual_port = ss->GetLocalPort(); std::cout << "INFO in LauSimFitMaster::initSockets : Waiting for connection with " << nSlaves_ << " workers on port " << actual_port << std::endl; sSlaves_.resize(nSlaves_); for ( UInt_t iSlave(0); iSlaveAccept(); std::cout << " : Added slave " << iSlave << std::endl; } // tell the clients to start std::cout << "INFO in LauSimFitMaster::initSockets : Initialising slaves" << std::endl; for ( UInt_t iSlave(0); iSlaveuseAsymmFitErrors()); sSlaves_[iSlave]->Send(message); socketMonitor_->Add(sSlaves_[iSlave]); } std::cout << " : Now start fit\n" << std::endl; ss->Close(); delete ss; } /* * OLD VERSION THAT JUST GETS THE NAMES - COULD HAVE A SERIES OF EXCHANGES TO GET THE NAMES, INIT VALUES, RANGES, ETC. INSTEAD OF PASSING PARAMETERS * THIS INCREASES THE GENERALITY OF THE CODE, I.E. THERE IS NO NEED FOR THE SLAVES TO KNOW ANY LAURA++ CLASS BUT THIS ONE, BUT MAKES IT RATHER MORE DENSE * FOR THE MOMENT I WILL STICK WITH THE METHOD OF PASSING LAUPARAMETER OBJECTS AROUND AND CONSIDER GOING BACK TO THIS GENERAL METHOD ONCE EVERYTHING IS WORKING * void LauSimFitMaster::getParametersFromSlavesFirstTime() { slaveIndices_.resize( nSlaves_ ); TSocket* sActive(0); for ( UInt_t iSlave(0); iSlaveSend(message); // Wait to receive the response and check that it has come from the slave we just requested from sActive = socketMonitor_->Select(); if ( sActive != sSlaves_[iSlave] ) { std::cerr << "ERROR in LauSimFitMaster::getParametersFromSlavesFirstTime : Received message from a different slave than expected!" << std::endl; gSystem->Exit(1); } // Read the object and extract the parameter names sSlaves_[iSlave]->Recv( messageFromSlave_ ); TObjArray * objarray = dynamic_cast( messageFromSlave_->ReadObject( messageFromSlave_->GetClass() ) ); if ( ! objarray ) { std::cerr << "ERROR in LauSimFitMaster::getParametersFromSlavesFirstTime : Error reading parameter names from slave" << std::endl; gSystem->Exit(1); } Int_t nPars = objarray->GetEntries(); for ( Int_t iPar(0); iPar < nPars; ++iPar ) { TObjString* objstring = dynamic_cast( (*objarray)[iPar] ); if ( ! objstring ) { std::cerr << "ERROR in LauSimFitMaster::getParametersFromSlavesFirstTime : Error reading parameter names from slave" << std::endl; gSystem->Exit(1); } TString parname = objstring->GetString(); std::map< TString, UInt_t >::iterator iter = parIndices_.find( parname ); if ( iter != parIndices_.end() ) { UInt_t index = iter->second; slaveIndices_[iSlave].push_back( index ); } else { UInt_t index = parIndices_.size(); parIndices_.insert( std::make_pair( parname, index ) ); parNames_.insert( std::make_pair( index, parname ) ); slaveIndices_[iSlave].push_back( index ); } } delete objarray; objarray = 0; delete messageFromSlave_; messageFromSlave_ = 0; } UInt_t nPars = parNames_.size(); parValues_.resize( nPars ); } */ void LauSimFitMaster::getParametersFromSlaves() { if ( socketMonitor_ == 0 ) { std::cerr << "ERROR in LauSimFitMaster::getParametersFromSlaves : Sockets not initialised." << std::endl; return; } if ( params_.empty() ) { this->getParametersFromSlavesFirstTime(); // Add variables to Gaussian constrain to a list this->addConParameters(); } else { this->updateParametersFromSlaves(); } } void LauSimFitMaster::updateParametersFromSlaves() { TSocket* sActive(0); // Construct a message, requesting the list of parameter names TString msgStr = "Send Parameters"; TMessage message( kMESS_STRING ); message.WriteTString( msgStr ); for ( UInt_t iSlave(0); iSlaveSend(message); // Wait to receive the response and check that it has come from the slave we just requested from sActive = socketMonitor_->Select(); if ( sActive != sSlaves_[iSlave] ) { std::cerr << "ERROR in LauSimFitMaster::updateParametersFromSlaves : Received message from a different slave than expected!" << std::endl; gSystem->Exit(1); } // Read the object and extract the parameter names sSlaves_[iSlave]->Recv( messageFromSlave_ ); TObjArray * objarray = dynamic_cast( messageFromSlave_->ReadObject( messageFromSlave_->GetClass() ) ); if ( ! objarray ) { std::cerr << "ERROR in LauSimFitMaster::updateParametersFromSlaves : Error reading parameter names from slave" << std::endl; gSystem->Exit(1); } // We want to auto-delete the supplied parameters since we only copy their values in this case objarray->SetOwner(kTRUE); const UInt_t nPars = objarray->GetEntries(); if ( nPars != slaveIndices_[iSlave].size() ) { std::cerr << "ERROR in LauSimFitMaster::updateParametersFromSlaves : Unexpected number of parameters received from slave" << std::endl; gSystem->Exit(1); } for ( UInt_t iPar(0); iPar < nPars; ++iPar ) { LauParameter* parameter = dynamic_cast( (*objarray)[iPar] ); if ( ! parameter ) { std::cerr << "ERROR in LauSimFitMaster::updateParametersFromSlaves : Error reading parameter from slave" << std::endl; gSystem->Exit(1); } TString parname = parameter->name(); Double_t parvalue = parameter->initValue(); std::map< TString, UInt_t >::iterator iter = parIndices_.find( parname ); if ( iter == parIndices_.end() ) { std::cerr << "ERROR in LauSimFitMaster::updateParametersFromSlaves : Unexpected parameter name received from slave" << std::endl; gSystem->Exit(1); } const UInt_t index = iter->second; if ( slaveIndices_[iSlave][iPar] != index ) { std::cerr << "ERROR in LauSimFitMaster::updateParametersFromSlaves : Unexpected parameter received from slave" << std::endl; gSystem->Exit(1); } params_[index]->initValue( parvalue ); parValues_[index] = parvalue; vectorPar_[iSlave][iPar] = parvalue; this->checkParameter( parameter, index ); } delete objarray; objarray = 0; delete messageFromSlave_; messageFromSlave_ = 0; } } void LauSimFitMaster::getParametersFromSlavesFirstTime() { slaveIndices_.resize( nSlaves_ ); slaveFreeIndices_.resize( nSlaves_ ); vectorPar_.resize( nSlaves_ ); vectorRes_.resize( nSlaves_ ); TSocket* sActive(0); // Construct a message, requesting the list of parameter names TString msgStr = "Send Parameters"; TMessage message( kMESS_STRING ); message.WriteTString( msgStr ); for ( UInt_t iSlave(0); iSlaveSend(message); // Wait to receive the response and check that it has come from the slave we just requested from sActive = socketMonitor_->Select(); if ( sActive != sSlaves_[iSlave] ) { std::cerr << "ERROR in LauSimFitMaster::getParametersFromSlavesFirstTime : Received message from a different slave than expected!" << std::endl; gSystem->Exit(1); } // Read the object and extract the parameter names sSlaves_[iSlave]->Recv( messageFromSlave_ ); TObjArray * objarray = dynamic_cast( messageFromSlave_->ReadObject( messageFromSlave_->GetClass() ) ); if ( ! objarray ) { std::cerr << "ERROR in LauSimFitMaster::getParametersFromSlavesFirstTime : Error reading parameters from slave" << std::endl; gSystem->Exit(1); } const UInt_t nPars = objarray->GetEntries(); vectorPar_[iSlave] = new Double_t[nPars]; for ( UInt_t iPar(0); iPar < nPars; ++iPar ) { LauParameter* parameter = dynamic_cast( (*objarray)[iPar] ); if ( ! parameter ) { std::cerr << "ERROR in LauSimFitMaster::getParametersFromSlavesFirstTime : Error reading parameter from slave" << std::endl; gSystem->Exit(1); } TString parname = parameter->name(); Double_t parvalue = parameter->initValue(); Bool_t parfixed = parameter->fixed(); std::map< TString, UInt_t >::iterator iter = parIndices_.find( parname ); if ( iter != parIndices_.end() ) { UInt_t index = iter->second; slaveIndices_[iSlave].push_back( index ); if ( ! parfixed ) { slaveFreeIndices_[iSlave].push_back( index ); } this->checkParameter( parameter, index ); } else { UInt_t index = parIndices_.size(); parIndices_.insert( std::make_pair( parname, index ) ); parNames_.insert( std::make_pair( index, parname ) ); slaveIndices_[iSlave].push_back( index ); if ( ! parfixed ) { slaveFreeIndices_[iSlave].push_back( index ); } params_.push_back( parameter ); parValues_.push_back( parvalue ); } vectorPar_[iSlave][iPar] = parvalue; } delete objarray; objarray = 0; delete messageFromSlave_; messageFromSlave_ = 0; } } void LauSimFitMaster::printParInfo() const { for ( UInt_t iSlave(0); iSlave& indices = slaveIndices_[iSlave]; std::cout << "INFO in LauSimFitMaster::printParInfo : Slave " << iSlave << " has the following parameters:\n"; for ( std::vector::const_iterator iter = indices.begin(); iter != indices.end(); ++iter ) { const TString& parName = parNames_.find(*iter)->second; Double_t parValue = parValues_[*iter]; const LauParameter* par = params_[*iter]; if ( par->name() != parName || par->initValue() != parValue ) { std::cerr << "ERROR in LauSimFitMaster::printParInfo : Discrepancy in parameter name and value records, this is very strange!!" << std::endl; } std::cout << " : " << parName << " = " << parValue << " and has index " << *iter << "\n"; } std::cout << std::endl; } std::cout << "INFO in LauSimFitMaster::printParInfo : " << "There are " << params_.size() << " parameters in total" << std::endl; } void LauSimFitMaster::checkParameter( const LauParameter* param, UInt_t index ) const { const LauParameter* storedPar = params_[index]; TString parName = storedPar->name(); if ( param->name() != parName ) { std::cerr << "ERROR in LauSimFitMaster::checkParameter : Parameter name is different!! This shouldn't happen!!" << std::endl; } if ( param->initValue() != storedPar->initValue() ) { std::cerr << "WARNING in LauSimFitMaster::checkParameter : Initial value for parameter " << parName << " is different, will use the value first set: " << storedPar->initValue() << std::endl; } if ( param->minValue() != storedPar->minValue() ) { std::cerr << "WARNING in LauSimFitMaster::checkParameter : Minimum allowed value for parameter " << parName << " is different, will use the value first set: " << storedPar->minValue() << std::endl; } if ( param->maxValue() != storedPar->maxValue() ) { std::cerr << "WARNING in LauSimFitMaster::checkParameter : Maximum allowed value for parameter " << parName << " is different, will use the value first set: " << storedPar->maxValue() << std::endl; } if ( param->fixed() != storedPar->fixed() ) { std::cerr << "WARNING in LauSimFitMaster::checkParameter : Fixed/floating property of parameter " << parName << " is different, will use the value first set: " << (storedPar->fixed() ? "fixed" : "floating") << std::endl; } if ( param->secondStage() != storedPar->secondStage() ) { std::cerr << "WARNING in LauSimFitMaster::checkParameter : Second stage property of parameter " << parName << " is different, will use the value first set: " << (storedPar->secondStage() ? "true" : "false") << std::endl; } } void LauSimFitMaster::initialise() { this->initSockets(); } void LauSimFitMaster::runSimFit( const TString& fitNtupleFileName, const UInt_t nExp, const UInt_t firstExp, const Bool_t useAsymmErrors, const Bool_t doTwoStageFit ) { // Routine to perform the total fit. // First, initialise this->useAsymmFitErrors(useAsymmErrors); this->twoStageFit(doTwoStageFit); this->initialise(); std::cout << "INFO in LauSimFitMaster::runSimFit : First experiment = " << firstExp << std::endl; std::cout << "INFO in LauSimFitMaster::runSimFit : Number of experiments = " << nExp << std::endl; // Start the cumulative timer cumulTimer_.Start(); this->resetFitCounters(); // Create and setup the fit results ntuple std::cout << "INFO in LauSimFitMaster::runSimFit : Creating fit ntuple." << std::endl; if (fitNtuple_ != 0) {delete fitNtuple_; fitNtuple_ = 0;} fitNtuple_ = new LauFitNtuple(fitNtupleFileName, useAsymmErrors); // Loop over the number of experiments for (UInt_t iExp = firstExp; iExp < (firstExp+nExp); ++iExp) { // Start the timer to see how long each fit takes timer_.Start(); this->setCurrentExperiment( iExp ); // Instruct the slaves to read the data for this experiment Bool_t readOK = this->readData(); if ( ! readOK ) { std::cerr << "ERROR in LauSimFitMaster::runSimFit : One or more slaves reported problems with reading data for experiment " << iExp << ", skipping..." << std::endl; timer_.Stop(); continue; } // Instruct the slaves to perform the caching this->cacheInputData(); // Do the fit this->fitExpt(); // Stop the timer and see how long the program took so far timer_.Stop(); timer_.Print(); // Instruct the slaves to finalise the results this->finalise(); } // Print out total timing info. std::cout << "INFO in LauSimFitMaster::runSimFit : Cumulative timing:" << std::endl; cumulTimer_.Stop(); cumulTimer_.Print(); // Print out stats on OK fits. const UInt_t nOKFits = this->numberOKFits(); const UInt_t nBadFits = this->numberBadFits(); std::cout << "INFO in LauSimFitMaster::runSimFit : Number of OK Fits = " << nOKFits << std::endl; std::cout << "INFO in LauSimFitMaster::runSimFit : Number of Failed Fits = " << nBadFits << std::endl; Double_t fitEff(0.0); if (nExp != 0) {fitEff = nOKFits/(1.0*nExp);} std::cout << "INFO in LauSimFitMaster::runSimFit : Fit efficiency = " << fitEff*100.0 << "%." << std::endl; // Instruct the slaves to write out any fit results (ntuples etc...). this->writeOutResults(); } void LauSimFitMaster::withinAsymErrorCalc(const Bool_t inAsymErrCalc) { this->LauFitObject::withinAsymErrorCalc(inAsymErrCalc); if ( socketMonitor_ == 0 ) { std::cerr << "ERROR in LauSimFitMaster::withinAsymErrorCalc : Sockets not initialised." << std::endl; return; } // Construct a message, informing the slaves whether or not we are now within the asymmetric error calculation TString msgStr("Asym Error Calc"); const Bool_t asymErrorCalc( this->withinAsymErrorCalc() ); TMessage message( kMESS_STRING ); message.WriteTString( msgStr ); message.WriteBool( asymErrorCalc ); // Send the message to the slaves for ( UInt_t iSlave(0); iSlaveSend(message); } TSocket* sActive(0); UInt_t responsesReceived(0); while ( responsesReceived != nSlaves_ ) { // Get the next queued response sActive = socketMonitor_->Select(); // Extract from the message the ID of the slave and the number of events read Bool_t response(kTRUE); UInt_t iSlave(0); sActive->Recv( messageFromSlave_ ); messageFromSlave_->ReadUInt( iSlave ); messageFromSlave_->ReadBool( response ); if ( response != asymErrorCalc ) { std::cerr << "WARNING in LauSimFitMaster::withinAsymErrorCalc : Problem informing slave " << iSlave << std::endl; } ++responsesReceived; } } Bool_t LauSimFitMaster::readData() { if ( socketMonitor_ == 0 ) { std::cerr << "ERROR in LauSimFitMaster::readData : Sockets not initialised." << std::endl; return kFALSE; } // Construct a message, requesting to read the data for the given experiment TString msgStr("Read Expt"); const UInt_t iExp( this->iExpt() ); TMessage message( kMESS_STRING ); message.WriteTString( msgStr ); message.WriteUInt( iExp ); // Send the message to the slaves for ( UInt_t iSlave(0); iSlaveSend(message); } TSocket* sActive(0); UInt_t responsesReceived(0); Bool_t ok(kTRUE); while ( responsesReceived != nSlaves_ ) { // Get the next queued response sActive = socketMonitor_->Select(); // Extract from the message the ID of the slave and the number of events read sActive->Recv( messageFromSlave_ ); UInt_t iSlave(0); UInt_t nEvents(0); messageFromSlave_->ReadUInt( iSlave ); messageFromSlave_->ReadUInt( nEvents ); if ( nEvents <= 0 ) { std::cerr << "ERROR in LauSimFitMaster::readData : Slave " << iSlave << " reports no events found for experiment " << iExp << std::endl; ok = kFALSE; } else { std::cerr << "INFO in LauSimFitMaster::readData : Slave " << iSlave << " reports " << nEvents << " events found for experiment " << iExp << std::endl; } ++responsesReceived; } return ok; } Bool_t LauSimFitMaster::cacheInputData() { if ( socketMonitor_ == 0 ) { std::cerr << "ERROR in LauSimFitMaster::cacheInputData : Sockets not initialised." << std::endl; return kFALSE; } // Construct a message, requesting it to read the data for the given experiment TString msgStr("Cache"); TMessage message( kMESS_STRING ); message.WriteTString( msgStr ); for ( UInt_t iSlave(0); iSlaveSend(message); } TSocket* sActive(0); UInt_t responsesReceived(0); Bool_t allOK(kTRUE); while ( responsesReceived != nSlaves_ ) { // Get the next queued response sActive = socketMonitor_->Select(); // Extract from the message the ID of the slave and the success/failure flag sActive->Recv( messageFromSlave_ ); UInt_t iSlave(0); Bool_t ok(kTRUE); messageFromSlave_->ReadUInt( iSlave ); messageFromSlave_->ReadBool( ok ); if ( ! ok ) { std::cerr << "ERROR in LauSimFitMaster::cacheInputData : Slave " << iSlave << " reports an error performing caching" << std::endl; allOK = kFALSE; } ++responsesReceived; } return allOK; } void LauSimFitMaster::checkInitFitParams() { this->getParametersFromSlaves(); this->printParInfo(); } void LauSimFitMaster::fitExpt() { // Routine to perform the actual fit for the given experiment // Instruct the slaves to update initial fit parameters if required (e.g. if using random numbers). this->checkInitFitParams(); // Initialise the fitter LauFitter::fitter()->useAsymmFitErrors( this->useAsymmFitErrors() ); LauFitter::fitter()->twoStageFit( this->twoStageFit() ); LauFitter::fitter()->initialise( this, params_ ); this->startNewFit( LauFitter::fitter()->nParameters(), LauFitter::fitter()->nFreeParameters() ); // Now ready for minimisation step std::cout << "\nINFO in LauSimFitMaster::fitExpt : Start minimisation...\n"; LauAbsFitter::FitStatus fitResult = LauFitter::fitter()->minimise(); // If we're doing a two stage fit we can now release (i.e. float) // the 2nd stage parameters and re-fit if (this->twoStageFit()) { if ( fitResult.status != 3 ) { std::cerr << "ERROR in LauSimFitMaster:fitExpt : Not running second stage fit since first stage failed." << std::endl; LauFitter::fitter()->releaseSecondStageParameters(); } else { LauFitter::fitter()->releaseSecondStageParameters(); this->startNewFit( LauFitter::fitter()->nParameters(), LauFitter::fitter()->nFreeParameters() ); fitResult = LauFitter::fitter()->minimise(); } } const TMatrixD& covMat = LauFitter::fitter()->covarianceMatrix(); this->storeFitStatus( fitResult, covMat ); // Store the final fit results and errors into protected internal vectors that // all sub-classes can use within their own finalFitResults implementation // used below (e.g. putting them into an ntuple in a root file) LauFitter::fitter()->updateParameters(); } void LauSimFitMaster::setParsFromMinuit(Double_t* par, Int_t npar) { // This function sets the internal parameters based on the values // that Minuit is using when trying to minimise the total likelihood function. // MINOS reports different numbers of free parameters depending on the // situation, so disable this check if ( ! this->withinAsymErrorCalc() ) { const UInt_t nFreePars = this->nFreeParams(); if (static_cast(npar) != nFreePars) { std::cerr << "ERROR in LauSimFitMaster::setParsFromMinuit : Unexpected number of free parameters: " << npar << ".\n"; std::cerr << " Expected: " << nFreePars << ".\n" << std::endl; gSystem->Exit(EXIT_FAILURE); } } // Despite npar being the number of free parameters // the par array actually contains all the parameters, // free and floating... // Update all the parameters with their new values. // Change the value in the array to be sent out to the slaves and the // parameters themselves (so that constraints are correctly calculated) for (UInt_t i(0); inTotParams(); ++i) { if (!params_[i]->fixed()) { parValues_[i] = par[i]; params_[i]->value(par[i]); } } } Double_t LauSimFitMaster::getTotNegLogLikelihood() { if ( socketMonitor_ == 0 ) { std::cerr << "ERROR in LauSimFitMaster::getTotNegLogLikelihood : Sockets not initialised." << std::endl; return 0.0; } // Send current values of the parameters to the slaves. for ( UInt_t iSlave(0); iSlave& indices = slaveIndices_[iSlave]; std::vector& freeIndices = slaveFreeIndices_[iSlave]; UInt_t nPars = indices.size(); UInt_t nFreePars = freeIndices.size(); for ( UInt_t iPar(0); iPar < nPars; ++iPar ) { vectorPar_[iSlave][iPar] = parValues_[ indices[iPar] ]; } TMessage* message = messagesToSlaves_[iSlave]; message->Reset( kMESS_ANY ); message->WriteUInt( nPars ); message->WriteUInt( nFreePars ); message->WriteFastArray( vectorPar_[iSlave], nPars ); sSlaves_[iSlave]->Send(*message); } Double_t negLogLike(0.0); TSocket *sActive(0); UInt_t responsesReceived(0); Bool_t allOK(kTRUE); while ( responsesReceived != nSlaves_ ) { sActive = socketMonitor_->Select(); sActive->Recv(messageFromSlave_); messageFromSlave_->ReadDouble( vectorRes_[responsesReceived] ); Double_t& nLL = vectorRes_[responsesReceived]; if ( nLL == 0.0 || TMath::IsNaN(nLL) || !TMath::Finite(nLL) ) { allOK = kFALSE; } negLogLike += vectorRes_[responsesReceived]; ++responsesReceived; } // Calculate any penalty terms from Gaussian constrained variables if ( ! conVars_.empty() ){ negLogLike += this->getLogLikelihoodPenalty(); } const Double_t worstNegLogLike = -1.0*this->worstLogLike(); if ( ! allOK ) { std::cerr << "WARNING in LauSimFitMaster::getTotNegLogLikelihood : Strange NLL value returned by one or more slaves\n"; std::cerr << " : Returning worst NLL found so far to force MINUIT out of this region." << std::endl; negLogLike = worstNegLogLike; } else if ( negLogLike > worstNegLogLike ) { this->worstLogLike( -negLogLike ); } return negLogLike; } Double_t LauSimFitMaster::getLogLikelihoodPenalty() { Double_t penalty(0.0); for ( std::vector::const_iterator iter = conVars_.begin(); iter != conVars_.end(); ++iter ) { Double_t val = (*iter)->unblindValue(); Double_t mean = (*iter)->constraintMean(); Double_t width = (*iter)->constraintWidth(); Double_t term = ( val - mean )*( val - mean ); penalty += term/( 2*width*width ); } return penalty; } void LauSimFitMaster::addConParameters() { // Add penalties from the constraints to fit parameters // First, constraints on the fit parameters themselves for ( std::vector::const_iterator iter = params_.begin(); iter != params_.end(); ++iter ) { if ( (*iter)->gaussConstraint() ) { conVars_.push_back( *iter ); std::cout << "INFO in LauSimFitMaster::addConParameters : Added Gaussian constraint to parameter "<< (*iter)->name() << std::endl; } } // Second, constraints on arbitrary combinations const std::vector& storeCon = this->constraintsStore(); for ( std::vector::const_iterator iter = storeCon.begin(); iter != storeCon.end(); ++iter ) { const std::vector& names = (*iter).conPars_; std::vector params; for ( std::vector::const_iterator iternames = names.begin(); iternames != names.end(); ++iternames ) { for ( std::vector::const_iterator iterfit = params_.begin(); iterfit != params_.end(); ++iterfit ) { if ( (*iternames) == (*iterfit)->name() ){ params.push_back(*iterfit); } } } // If the parameters are not found, skip it if ( params.size() != (*iter).conPars_.size() ) { std::cerr << "WARNING in LauSimFitMaster::addConParameters: Could not find parameters to constrain in the formula... skipping" << std::endl; continue; } LauFormulaPar* formPar = new LauFormulaPar( (*iter).formula_, (*iter).formula_, params ); formPar->addGaussianConstraint( (*iter).mean_, (*iter).width_ ); conVars_.push_back(formPar); std::cout << "INFO in LauSimFitMaster::addConParameters : Added Gaussian constraint to formula\n"; std::cout << " : Formula: " << (*iter).formula_ << std::endl; for ( std::vector::iterator iterparam = params.begin(); iterparam != params.end(); ++iterparam ) { std::cout << " : Parameter: " << (*iterparam)->name() << std::endl; } } } Bool_t LauSimFitMaster::finalise() { if ( socketMonitor_ == 0 ) { std::cerr << "ERROR in LauSimFitMaster::finalise : Sockets not initialised." << std::endl; return kFALSE; } // Prepare the covariance matrices const TMatrixD& covMatrix = this->covarianceMatrix(); covMatrices_.resize( nSlaves_ ); LauParamFixed pred; std::map freeParIndices; UInt_t counter(0); for ( UInt_t iPar(0); iPar < this->nTotParams(); ++iPar ) { const LauParameter* par = params_[iPar]; if ( ! pred(par) ) { freeParIndices.insert( std::make_pair(iPar,counter) ); ++counter; } } for ( UInt_t iSlave(0); iSlave freeIndices; freeIndices.reserve( nPar ); for ( UInt_t iPar(0); iPar < nPar; ++iPar ) { UInt_t index = slaveIndices_[iSlave][iPar]; std::map::iterator freeIter = freeParIndices.find(index); if ( freeIter == freeParIndices.end() ) { continue; } UInt_t freeIndex = freeIter->second; freeIndices.push_back( freeIndex ); } const UInt_t nFreePars = freeIndices.size(); TMatrixD& covMat = covMatrices_[iSlave]; covMat.ResizeTo( nFreePars, nFreePars ); for ( UInt_t iPar(0); iPar < nFreePars; ++iPar ) { for ( UInt_t jPar(0); jPar < nFreePars; ++jPar ) { UInt_t i = freeIndices[iPar]; UInt_t j = freeIndices[jPar]; covMat( iPar, jPar ) = covMatrix( i, j ); } } } // The array to hold the parameters TObjArray array; // Send messages to all slaves containing the final parameters and fit status, NLL for ( UInt_t iSlave(0); iSlave& indices = slaveIndices_[iSlave]; UInt_t nPars = indices.size(); for ( UInt_t iPar(0); iPar < nPars; ++iPar ) { array.Add( params_[ indices[iPar] ] ); } const Int_t status = this->statusCode(); const Double_t NLL = this->nll(); const Double_t EDM = this->edm(); TMatrixD& covMat = covMatrices_[iSlave]; TMessage* message = messagesToSlaves_[iSlave]; message->Reset( kMESS_OBJECT ); message->WriteInt( status ); message->WriteDouble( NLL ); message->WriteDouble( EDM ); message->WriteObject( &array ); message->WriteObject( &covMat ); sSlaves_[iSlave]->Send(*message); } TSocket *sActive(0); UInt_t responsesReceived(0); Bool_t allOK(kTRUE); while ( responsesReceived != nSlaves_ ) { // Get the next queued response sActive = socketMonitor_->Select(); // Extract from the message the ID of the slave and the number of events read sActive->Recv( messageFromSlave_ ); UInt_t iSlave(0); Bool_t ok(kTRUE); messageFromSlave_->ReadUInt( iSlave ); messageFromSlave_->ReadBool( ok ); if ( ok ) { TObjArray * objarray = dynamic_cast( messageFromSlave_->ReadObject( messageFromSlave_->GetClass() ) ); if ( ! objarray ) { std::cerr << "ERROR in LauSimFitMaster::finalise : Error reading finalised parameters from slave" << std::endl; allOK = kFALSE; } else { // We want to auto-delete the supplied parameters since we only copy their values in this case objarray->SetOwner(kTRUE); const UInt_t nPars = objarray->GetEntries(); if ( nPars != slaveIndices_[iSlave].size() ) { std::cerr << "ERROR in LauSimFitMaster::finalise : Unexpected number of finalised parameters received from slave" << std::endl; allOK = kFALSE; } else { for ( UInt_t iPar(0); iPar < nPars; ++iPar ) { LauParameter* parameter = dynamic_cast( (*objarray)[iPar] ); if ( ! parameter ) { std::cerr << "ERROR in LauSimFitMaster::finalise : Error reading parameter from slave" << std::endl; allOK = kFALSE; continue; } TString parname = parameter->name(); std::map< TString, UInt_t >::iterator iter = parIndices_.find( parname ); if ( iter == parIndices_.end() ) { std::cerr << "ERROR in LauSimFitMaster::finalise : Unexpected parameter name received from slave" << std::endl; allOK = kFALSE; continue; } const UInt_t index = iter->second; if ( slaveIndices_[iSlave][iPar] != index ) { std::cerr << "ERROR in LauSimFitMaster::finalise : Unexpected parameter received from slave" << std::endl; allOK = kFALSE; continue; } Double_t parvalue = parameter->value(); params_[index]->value( parvalue ); parValues_[index] = parvalue; vectorPar_[iSlave][iPar] = parvalue; } } delete objarray; } } else { std::cerr << "ERROR in LauSimFitMaster::finalise : Slave " << iSlave << " reports an error performing finalisation" << std::endl; allOK = kFALSE; } ++responsesReceived; } // Fill our ntuple as well if ( fitNtuple_ != 0 ) { for ( std::vector::iterator iter = params_.begin(); iter != params_.end(); ++iter ) { if (!(*iter)->fixed()) { (*iter)->updatePull(); } } std::vector extraVars; fitNtuple_->storeParsAndErrors( params_, extraVars ); fitNtuple_->storeCorrMatrix(this->iExpt(), this->fitStatus(), this->covarianceMatrix()); fitNtuple_->updateFitNtuple(); } return allOK; } Bool_t LauSimFitMaster::writeOutResults() { if ( socketMonitor_ == 0 ) { std::cerr << "ERROR in LauSimFitMaster::writeOutResults : Sockets not initialised." << std::endl; return kFALSE; } // Construct a message, requesting to write out the fit results TString msgStr("Write Results"); TMessage message( kMESS_STRING ); message.WriteTString( msgStr ); // Send the message to the slaves for ( UInt_t iSlave(0); iSlaveSend(message); } TSocket *sActive(0); UInt_t responsesReceived(0); Bool_t allOK(kTRUE); while ( responsesReceived != nSlaves_ ) { // Get the next queued response sActive = socketMonitor_->Select(); // Extract from the message the ID of the slave and the number of events read sActive->Recv( messageFromSlave_ ); UInt_t iSlave(0); Bool_t ok(kTRUE); messageFromSlave_->ReadUInt( iSlave ); messageFromSlave_->ReadBool( ok ); if ( ! ok ) { std::cerr << "ERROR in LauSimFitMaster::writeOutResults : Slave " << iSlave << " reports an error performing finalisation" << std::endl; allOK = kFALSE; } ++responsesReceived; } // Write out our ntuple as well if (fitNtuple_ != 0) { fitNtuple_->writeOutFitResults(); } return allOK; } diff --git a/src/LauSimFitSlave.cc b/src/LauSimFitSlave.cc index b1b7f90..307e9c1 100644 --- a/src/LauSimFitSlave.cc +++ b/src/LauSimFitSlave.cc @@ -1,310 +1,309 @@ /* Copyright 2015 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauSimFitSlave.cc \brief File containing implementation of LauSimFitSlave class. */ #include #include #include "TMatrixD.h" #include "TMessage.h" #include "TObjArray.h" #include "TObjString.h" #include "TSocket.h" #include "TSystem.h" #include "LauSimFitSlave.hh" #include "LauFitNtuple.hh" -ClassImp(LauSimFitSlave) LauSimFitSlave::LauSimFitSlave() : sMaster_(0), messageFromMaster_(0), slaveId_(0), nSlaves_(0), parValues_(0), fitNtuple_(0) { } LauSimFitSlave::~LauSimFitSlave() { delete sMaster_; delete messageFromMaster_; delete[] parValues_; delete fitNtuple_; } void LauSimFitSlave::runSlave(const TString& dataFileName, const TString& dataTreeName, const TString& histFileName, const TString& tableFileName, const TString& addressMaster, const UInt_t portMaster) { // Establish the connection to the master process this->connectToMaster( addressMaster, portMaster ); // Initialise the fit model this->initialise(); // NB call to addConParameters() is intentionally not included here cf. // LauAbsFitModel::run() since this has to be dealt with by the master // to avoid multiple inclusions of each penalty term // Print a warning if constraints on combinations of parameters have been specified const std::vector& storeCon = this->constraintsStore(); if ( ! storeCon.empty() ) { std::cerr << "WARNING in LauSimFitSlave::runSlave : Constraints have been added but these will be ignored - they should have been added to the master process" << std::endl; } // Setup saving of fit results to ntuple/LaTeX table etc. this->setupResultsOutputs( histFileName, tableFileName ); // This reads in the given dataFile and creates an input // fit data tree that stores them for all events and experiments. Bool_t dataOK = this->verifyFitData(dataFileName,dataTreeName); if (!dataOK) { std::cerr << "ERROR in LauSimFitSlave::runSlave : Problem caching the fit data." << std::endl; return; } // Now process the various requests from the master this->processMasterRequests(); std::cout << "INFO in LauSimFitSlave::runSlave : Fit slave " << this->slaveId() << " has finished successfully" << std::endl; } void LauSimFitSlave::setupResultsOutputs( const TString& histFileName, const TString& /*tableFileName*/ ) { // Create and setup the fit results ntuple std::cout << "INFO in LauSimFitSlave::setupResultsOutputs : Creating fit ntuple." << std::endl; if (fitNtuple_ != 0) {delete fitNtuple_; fitNtuple_ = 0;} fitNtuple_ = new LauFitNtuple(histFileName, this->useAsymmFitErrors()); } void LauSimFitSlave::connectToMaster( const TString& addressMaster, const UInt_t portMaster ) { if ( sMaster_ != 0 ) { std::cerr << "ERROR in LauSimFitSlave::connectToMaster : master socket already present" << std::endl; return; } // Open connection to master sMaster_ = new TSocket(addressMaster, portMaster); sMaster_->Recv( messageFromMaster_ ); messageFromMaster_->ReadUInt( slaveId_ ); messageFromMaster_->ReadUInt( nSlaves_ ); Bool_t useAsymErrs(kFALSE); messageFromMaster_->ReadBool( useAsymErrs ); this->useAsymmFitErrors(useAsymErrs); delete messageFromMaster_; messageFromMaster_ = 0; std::cout << "INFO in LauSimFitSlave::connectToMaster : Established connection to master on port " << portMaster << std::endl; std::cout << " : We are slave " << slaveId_ << " of " << nSlaves_ << std::endl; if ( useAsymErrs ) { std::cout << " : The fit will determine asymmetric errors" << std::endl; } } void LauSimFitSlave::processMasterRequests() { // Listen for requests from the master and act accordingly TMessage messageToMaster(kMESS_ANY); while ( kTRUE ) { sMaster_->Recv( messageFromMaster_ ); if ( messageFromMaster_->What() == kMESS_STRING ) { TString msgStr; messageFromMaster_->ReadTString( msgStr ); std::cout << "INFO in LauSimFitSlave::processMasterRequests : Received message from master: " << msgStr << std::endl; if ( msgStr == "Send Parameters" ) { // Send the fit parameters TObjArray array; this->prepareInitialParArray( array ); // Create array to efficiently exchange parameter values with master if ( parValues_ != 0 ) { delete[] parValues_; parValues_ = 0; } UInt_t nPar = array.GetEntries(); parValues_ = new Double_t[nPar]; messageToMaster.Reset( kMESS_OBJECT ); messageToMaster.WriteObject( &array ); sMaster_->Send( messageToMaster ); } else if ( msgStr == "Read Expt" ) { // Read the data for this experiment UInt_t iExp(0); messageFromMaster_->ReadUInt( iExp ); this->setCurrentExperiment( iExp ); UInt_t nEvents = this->readExperimentData(); if ( nEvents < 1 ) { std::cerr << "WARNING in LauSimFitSlave::processMasterRequests : Zero events in experiment " << iExp << ", the master should skip this experiment..." << std::endl; } messageToMaster.Reset( kMESS_ANY ); messageToMaster.WriteUInt( slaveId_ ); messageToMaster.WriteUInt( nEvents ); sMaster_->Send( messageToMaster ); } else if ( msgStr == "Cache" ) { // Perform the caching this->cacheInputFitVars(); messageToMaster.Reset( kMESS_ANY ); messageToMaster.WriteUInt( slaveId_ ); messageToMaster.WriteBool( kTRUE ); sMaster_->Send( messageToMaster ); } else if ( msgStr == "Asym Error Calc" ) { Bool_t asymErrorCalc(kFALSE); messageFromMaster_->ReadBool( asymErrorCalc ); this->withinAsymErrorCalc( asymErrorCalc ); messageToMaster.Reset( kMESS_ANY ); messageToMaster.WriteUInt( slaveId_ ); messageToMaster.WriteBool( asymErrorCalc ); sMaster_->Send( messageToMaster ); } else if ( msgStr == "Write Results" ) { this->writeOutAllFitResults(); messageToMaster.Reset( kMESS_ANY ); messageToMaster.WriteUInt( slaveId_ ); messageToMaster.WriteBool( kTRUE ); sMaster_->Send( messageToMaster ); } else if ( msgStr == "Finish" ) { std::cout << "INFO in LauSimFitSlave::processMasterRequests : Message from master to finish" << std::endl; break; } else { std::cerr << "ERROR in LauSimFitSlave::processMasterRequests : Unexpected message from master" << std::endl; gSystem->Exit( EXIT_FAILURE ); } } else if ( messageFromMaster_->What() == kMESS_OBJECT ) { std::cout << "INFO in LauSimFitSlave::processMasterRequests : Received message from master: Finalise" << std::endl; Int_t status(0); Double_t NLL(0.0); Double_t EDM(0.0); messageFromMaster_->ReadInt( status ); messageFromMaster_->ReadDouble( NLL ); messageFromMaster_->ReadDouble( EDM ); TObjArray * objarray = dynamic_cast( messageFromMaster_->ReadObject( messageFromMaster_->GetClass() ) ); if ( ! objarray ) { std::cerr << "ERROR in LauSimFitSlave::processMasterRequests : Error reading parameters from master" << std::endl; gSystem->Exit( EXIT_FAILURE ); } TMatrixD * covMat = dynamic_cast( messageFromMaster_->ReadObject( messageFromMaster_->GetClass() ) ); if ( ! covMat ) { std::cerr << "ERROR in LauSimFitSlave::processMasterRequests : Error reading covariance matrix from master" << std::endl; gSystem->Exit( EXIT_FAILURE ); } TObjArray array; LauAbsFitter::FitStatus fitStat { status, NLL, EDM }; this->finaliseExperiment( fitStat, objarray, covMat, array ); delete objarray; objarray = 0; delete covMat; covMat = 0; // Send the finalised parameters back to the master messageToMaster.Reset( kMESS_ANY ); messageToMaster.WriteUInt( slaveId_ ); messageToMaster.WriteBool( kTRUE ); messageToMaster.WriteObject( &array ); sMaster_->Send( messageToMaster ); } else if ( messageFromMaster_->What() == kMESS_ANY ) { UInt_t nPars(0); UInt_t nFreePars(0); messageFromMaster_->ReadUInt( nPars ); messageFromMaster_->ReadUInt( nFreePars ); if ( nPars != this->nTotParams() ) { std::cerr << "ERROR in LauSimFitSlave::processMasterRequests : Unexpected number of parameters received from master" << std::endl; std::cerr << " : Received " << nPars << " when expecting " << this->nTotParams() << std::endl; gSystem->Exit( EXIT_FAILURE ); } messageFromMaster_->ReadFastArray( parValues_, nPars ); this->setParsFromMinuit( parValues_, nFreePars ); Double_t negLogLike = this->getTotNegLogLikelihood(); messageToMaster.Reset( kMESS_ANY ); messageToMaster.WriteDouble( negLogLike ); sMaster_->Send( messageToMaster ); } else { std::cerr << "ERROR in LauSimFitSlave::processMasterRequests : Unexpected message type" << std::endl; gSystem->Exit( EXIT_FAILURE ); } delete messageFromMaster_; messageFromMaster_ = 0; } } void LauSimFitSlave::writeOutAllFitResults() { // Write out histograms at end if (fitNtuple_ != 0) { fitNtuple_->writeOutFitResults(); } } diff --git a/src/LauSimpleFitModel.cc b/src/LauSimpleFitModel.cc index 30a002e..8b67929 100644 --- a/src/LauSimpleFitModel.cc +++ b/src/LauSimpleFitModel.cc @@ -1,2348 +1,2347 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauSimpleFitModel.cc \brief File containing implementation of LauSimpleFitModel class. */ #include #include #include #include #include "TFile.h" #include "TH2.h" #include "TMinuit.h" #include "TRandom.h" #include "TSystem.h" #include "TVirtualFitter.h" #include "LauAbsBkgndDPModel.hh" #include "LauAbsCoeffSet.hh" #include "LauIsobarDynamics.hh" #include "LauAbsPdf.hh" #include "LauComplex.hh" #include "LauConstants.hh" #include "LauDaughters.hh" #include "LauEmbeddedData.hh" #include "LauEffModel.hh" #include "LauFitNtuple.hh" #include "LauGenNtuple.hh" #include "LauKinematics.hh" #include "LauPrint.hh" #include "LauRandom.hh" #include "LauScfMap.hh" #include "LauSimpleFitModel.hh" #include "TGraph2D.h" #include "TGraph.h" #include "TStyle.h" #include "TCanvas.h" -ClassImp(LauSimpleFitModel) LauSimpleFitModel::LauSimpleFitModel(LauIsobarDynamics* sigModel) : LauAbsFitModel(), sigDPModel_(sigModel), kinematics_(sigModel ? sigModel->getKinematics() : 0), usingBkgnd_(kFALSE), nSigComp_(0), nSigDPPar_(0), nExtraPdfPar_(0), nNormPar_(0), meanEff_("meanEff",0.0,0.0,1.0), dpRate_("dpRate",0.0,0.0,100.0), //signalEvents_("signalEvents",1.0,0.0,1.0), signalEvents_(0), useSCF_(kFALSE), useSCFHist_(kFALSE), scfFrac_("scfFrac",0.0,0.0,1.0), scfFracHist_(0), scfMap_(0), compareFitData_(kFALSE), signalTree_(0), reuseSignal_(kFALSE), useReweighting_(kFALSE), sigDPLike_(0.0), scfDPLike_(0.0), sigExtraLike_(0.0), scfExtraLike_(0.0), sigTotalLike_(0.0), scfTotalLike_(0.0) { } LauSimpleFitModel::~LauSimpleFitModel() { delete signalTree_; for (LauBkgndEmbDataList::iterator iter = bkgndTree_.begin(); iter != bkgndTree_.end(); ++iter) { delete (*iter); } delete scfFracHist_; } void LauSimpleFitModel::setupBkgndVectors() { UInt_t nBkgnds = this->nBkgndClasses(); bkgndDPModels_.resize( nBkgnds ); bkgndPdfs_.resize( nBkgnds ); bkgndEvents_.resize( nBkgnds ); bkgndTree_.resize( nBkgnds ); reuseBkgnd_.resize( nBkgnds ); bkgndDPLike_.resize( nBkgnds ); bkgndExtraLike_.resize( nBkgnds ); bkgndTotalLike_.resize( nBkgnds ); } void LauSimpleFitModel::setNSigEvents(LauParameter* nSigEvents) { if ( nSigEvents == 0 ) { std::cerr << "ERROR in LauSimpleFitModel::setNSigEvents : The signal yield LauParameter pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } if ( signalEvents_ != 0 ) { std::cerr << "ERROR in LauSimpleFitModel::setNSigEvents : You are trying to overwrite the signal yield." << std::endl; return; } signalEvents_ = nSigEvents; TString name = signalEvents_->name(); if ( ! name.Contains("signalEvents") && !( name.BeginsWith("signal") && name.EndsWith("Events") ) ) { signalEvents_->name("signalEvents"); } Double_t value = nSigEvents->value(); signalEvents_->range(-2.0*(TMath::Abs(value)+1.0), 2.0*(TMath::Abs(value)+1.0)); } void LauSimpleFitModel::setNBkgndEvents(LauAbsRValue* nBkgndEvents) { if ( nBkgndEvents == 0 ) { std::cerr << "ERROR in LauSimpleFitModel::setNBkgndEvents : The background yield LauParameter pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } if ( ! this->validBkgndClass( nBkgndEvents->name() ) ) { std::cerr << "ERROR in LauSimpleFitModel::setNBkgndEvents : Invalid background class \"" << nBkgndEvents->name() << "\"." << std::endl; std::cerr << " : Background class names must be provided in \"setBkgndClassNames\" before any other background-related actions can be performed." << std::endl; gSystem->Exit(EXIT_FAILURE); } UInt_t bkgndID = this->bkgndClassID( nBkgndEvents->name() ); if ( bkgndEvents_[bkgndID] != 0 ) { std::cerr << "ERROR in LauSimpleFitModel::setNBkgndEvents : You are trying to overwrite the background yield." << std::endl; return; } nBkgndEvents->name( nBkgndEvents->name()+"Events" ); if ( nBkgndEvents->isLValue() ) { Double_t value = nBkgndEvents->value(); LauParameter* yield = dynamic_cast( nBkgndEvents ); yield->range(-2.0*(TMath::Abs(value)+1.0), 2.0*(TMath::Abs(value)+1.0)); } bkgndEvents_[bkgndID] = nBkgndEvents; } void LauSimpleFitModel::splitSignalComponent( const TH2* dpHisto, const Bool_t upperHalf, const Bool_t fluctuateBins, LauScfMap* scfMap ) { if ( useSCF_ == kTRUE ) { std::cerr << "ERROR in LauSimpleFitModel::splitSignalComponent : Have already setup SCF." << std::endl; return; } if ( dpHisto == 0 ) { std::cerr << "ERROR in LauSimpleFitModel::splitSignalComponent : The histogram pointer is null." << std::endl; return; } const LauDaughters* daughters = sigDPModel_->getDaughters(); scfFracHist_ = new LauEffModel( daughters, 0 ); scfFracHist_->setEffHisto( dpHisto, kTRUE, fluctuateBins, 0.0, 0.0, upperHalf, daughters->squareDP() ); scfMap_ = scfMap; useSCF_ = kTRUE; useSCFHist_ = kTRUE; } void LauSimpleFitModel::splitSignalComponent( const Double_t scfFrac, const Bool_t fixed ) { if ( useSCF_ == kTRUE ) { std::cerr << "ERROR in LauSimpleFitModel::splitSignalComponent : Have already setup SCF." << std::endl; return; } scfFrac_.range( 0.0, 1.0 ); scfFrac_.value( scfFrac ); scfFrac_.initValue( scfFrac ); scfFrac_.genValue( scfFrac ); scfFrac_.fixed( fixed ); useSCF_ = kTRUE; useSCFHist_ = kFALSE; } void LauSimpleFitModel::setBkgndDPModel(const TString& bkgndClass, LauAbsBkgndDPModel* bkgndDPModel) { if (bkgndDPModel == 0) { std::cerr << "ERROR in LauSimpleFitModel::setBkgndDPModel : The model pointer is null." << std::endl; return; } // check that this background name is valid if ( ! this->validBkgndClass( bkgndClass ) ) { std::cerr << "ERROR in LauSimpleFitModel::setBkgndDPModel : Invalid background class \"" << bkgndClass << "\"." << std::endl; std::cerr << " : Background class names must be provided in \"setBkgndClassNames\" before any other background-related actions can be performed." << std::endl; return; } UInt_t bkgndID = this->bkgndClassID( bkgndClass ); bkgndDPModels_[bkgndID] = bkgndDPModel; usingBkgnd_ = kTRUE; } void LauSimpleFitModel::setSignalPdf(LauAbsPdf* pdf) { if (pdf==0) { std::cerr << "ERROR in LauSimpleFitModel::setSignalPdf : The PDF pointer is null." << std::endl; return; } signalPdfs_.push_back(pdf); } void LauSimpleFitModel::setSCFPdf(LauAbsPdf* pdf) { if (pdf==0) { std::cerr << "ERROR in LauSimpleFitModel::setSCFPdf : The PDF pointer is null." << std::endl; return; } scfPdfs_.push_back(pdf); } void LauSimpleFitModel::setBkgndPdf(const TString& bkgndClass, LauAbsPdf* pdf) { if (pdf == 0) { std::cerr << "ERROR in LauSimpleFitModel::setBkgndPdf : The PDF pointer is null." << std::endl; return; } // check that this background name is valid if ( ! this->validBkgndClass( bkgndClass ) ) { std::cerr << "ERROR in LauSimpleFitModel::setBkgndPdf : Invalid background class \"" << bkgndClass << "\"." << std::endl; std::cerr << " : Background class names must be provided in \"setBkgndClassNames\" before any other background-related actions can be performed." << std::endl; return; } UInt_t bkgndID = this->bkgndClassID( bkgndClass ); bkgndPdfs_[bkgndID].push_back(pdf); usingBkgnd_ = kTRUE; } void LauSimpleFitModel::setAmpCoeffSet(LauAbsCoeffSet* coeffSet) { // Resize the coeffPars vector if not already done if ( coeffPars_.empty() ) { coeffPars_.resize( sigDPModel_->getnTotAmp() ); for (std::vector::iterator iter = coeffPars_.begin(); iter != coeffPars_.end(); ++iter) { (*iter) = 0; } } // Is there a component called compName in the signal model? TString compName(coeffSet->name()); const Int_t index = sigDPModel_->resonanceIndex(compName); if ( index < 0 ) { std::cerr << "ERROR in LauSimpleFitModel::setAmpCoeffSet : Signal DP model doesn't contain component \"" << compName << "\"." << std::endl; return; } // Do we already have it in our list of names? if ( coeffPars_[index] != 0 && coeffPars_[index]->name() == compName) { std::cerr << "ERROR in LauSimpleFitModel::setAmpCoeffSet : Have already set coefficients for \"" << compName << "\"." << std::endl; return; } coeffSet->index(index); coeffPars_[index] = coeffSet; ++nSigComp_; std::cout << "INFO in LauSimpleFitModel::setAmpCoeffSet : Added coefficients for component A"<< index << ": \"" << compName << "\" to the fit model." << std::endl; coeffSet->printParValues(); } void LauSimpleFitModel::initialise() { // Initialisation if (!this->useDP() && signalPdfs_.empty()) { std::cerr << "ERROR in LauSimpleFitModel::initialise : Signal model doesn't exist for any variable." << std::endl; gSystem->Exit(EXIT_FAILURE); } if (this->useDP()) { // Check that we have all the Dalitz-plot models if ( sigDPModel_ == 0 ) { std::cerr << "ERROR in LauSimpleFitModel::initialise : The pointer to the signal DP model is null.\n"; std::cerr << " : Removing the Dalitz Plot from the model." << std::endl; this->useDP(kFALSE); } if ( usingBkgnd_ ) { for (LauBkgndDPModelList::const_iterator dpmodel_iter = bkgndDPModels_.begin(); dpmodel_iter != bkgndDPModels_.end(); ++dpmodel_iter ) { if ( (*dpmodel_iter) == 0 ) { std::cerr << "ERROR in LauSimpleFitModel::initialise : The pointer to one of the background DP models is null.\n"; std::cerr << " : Removing the Dalitz Plot from the model." << std::endl; this->useDP(kFALSE); break; } } } // Need to check that the number of components we have and that the dynamics has matches up UInt_t nAmp = sigDPModel_->getnTotAmp(); if (nAmp != nSigComp_) { std::cerr << "ERROR in LauSimpleFitModel::initialise : Number of signal DP components with magnitude and phase set not right." << std::endl; gSystem->Exit(EXIT_FAILURE); } // From the initial parameter values calculate the coefficients // so they can be passed to the signal model this->updateCoeffs(); // If all is well, go ahead and initialise them this->initialiseDPModels(); } // Next check that, if a given component is being used we've got the // right number of PDFs for all the variables involved // TODO - should probably check variable names and so on as well UInt_t nsigpdfvars(0); for ( LauPdfList::const_iterator pdf_iter = signalPdfs_.begin(); pdf_iter != signalPdfs_.end(); ++pdf_iter ) { std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { ++nsigpdfvars; } } } if (useSCF_) { UInt_t nscfpdfvars(0); for ( LauPdfList::const_iterator pdf_iter = scfPdfs_.begin(); pdf_iter != scfPdfs_.end(); ++pdf_iter ) { std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { ++nscfpdfvars; } } } if (nscfpdfvars != nsigpdfvars) { std::cerr << "ERROR in LauSimpleFitModel::initialise : There are " << nsigpdfvars << " TM signal PDF variables but " << nscfpdfvars << " SCF signal PDF variables." << std::endl; gSystem->Exit(EXIT_FAILURE); } } if (usingBkgnd_) { for (LauBkgndPdfsList::const_iterator bgclass_iter = bkgndPdfs_.begin(); bgclass_iter != bkgndPdfs_.end(); ++bgclass_iter) { UInt_t nbkgndpdfvars(0); const LauPdfList& pdfList = (*bgclass_iter); for ( LauPdfList::const_iterator pdf_iter = pdfList.begin(); pdf_iter != pdfList.end(); ++pdf_iter ) { std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { ++nbkgndpdfvars; } } } if (nbkgndpdfvars != nsigpdfvars) { std::cerr << "ERROR in LauSimpleFitModel::initialise : There are " << nsigpdfvars << " signal PDF variables but " << nbkgndpdfvars << " bkgnd PDF variables." << std::endl; gSystem->Exit(EXIT_FAILURE); } } } // Clear the vectors of parameter information so we can start from scratch this->clearFitParVectors(); // Set the fit parameters for signal and background models this->setSignalDPParameters(); // Set the fit parameters for the various extra PDFs this->setExtraPdfParameters(); // Set the initial bg and signal events this->setFitNEvents(); // Check that we have the expected number of fit variables const LauParameterPList& fitVars = this->fitPars(); if (fitVars.size() != (nSigDPPar_ + nExtraPdfPar_ + nNormPar_)) { std::cerr << "ERROR in LauSimpleFitModel::initialise : Number of fit parameters not of expected size." << std::endl; gSystem->Exit(EXIT_FAILURE); } this->setExtraNtupleVars(); } void LauSimpleFitModel::initialiseDPModels() { std::cout << "INFO in LauSimpleFitModel::initialiseDPModels : Initialising DP models" << std::endl; sigDPModel_->initialise(coeffs_); if (usingBkgnd_ == kTRUE) { for (LauBkgndDPModelList::iterator iter = bkgndDPModels_.begin(); iter != bkgndDPModels_.end(); ++iter) { (*iter)->initialise(); } } } void LauSimpleFitModel::recalculateNormalisation() { //std::cout << "INFO in LauSimpleFitModel::recalculateNormalizationInDPModels : Recalc Norm in DP model" << std::endl; sigDPModel_->recalculateNormalisation(); sigDPModel_->modifyDataTree(); } void LauSimpleFitModel::setSignalDPParameters() { // Set the fit parameters for the signal model. nSigDPPar_ = 0; if ( ! this->useDP() ) { return; } std::cout << "INFO in LauSimpleFitModel::setSignalDPParameters : Setting the initial fit parameters for the signal DP model." << std::endl; // Place isobar coefficient parameters in vector of fit variables LauParameterPList& fitVars = this->fitPars(); for (UInt_t i = 0; i < nSigComp_; i++) { LauParameterPList pars = coeffPars_[i]->getParameters(); for (LauParameterPList::iterator iter = pars.begin(); iter != pars.end(); ++iter) { if ( !(*iter)->clone() ) { fitVars.push_back(*iter); ++nSigDPPar_; } } } // Obtain the resonance parameters and place them in the vector of fit variables and in a separate vector LauParameterPSet& resVars = this->resPars(); resVars.clear(); LauParameterPList& sigDPPars = sigDPModel_->getFloatingParameters(); for ( LauParameterPList::iterator iter = sigDPPars.begin(); iter != sigDPPars.end(); ++iter ) { if ( resVars.insert(*iter).second ) { fitVars.push_back(*iter); ++nSigDPPar_; } } } void LauSimpleFitModel::setExtraPdfParameters() { // Include all the parameters of the various PDFs in the fit // NB all of them are passed to the fit, even though some have been fixed through parameter.fixed(kTRUE) // With the new "cloned parameter" scheme only "original" parameters are passed to the fit. // Their clones are updated automatically when the originals are updated. nExtraPdfPar_ = 0; nExtraPdfPar_ += this->addFitParameters(signalPdfs_); if (useSCF_ == kTRUE) { nExtraPdfPar_ += this->addFitParameters(scfPdfs_); } if (usingBkgnd_ == kTRUE) { for (LauBkgndPdfsList::iterator iter = bkgndPdfs_.begin(); iter != bkgndPdfs_.end(); ++iter) { nExtraPdfPar_ += this->addFitParameters(*iter); } } } void LauSimpleFitModel::setFitNEvents() { if ( signalEvents_ == 0 ) { std::cerr << "ERROR in LauSimpleFitModel::setFitNEvents : Signal yield not defined." << std::endl; return; } nNormPar_ = 0; // initialise the total number of events to be the sum of all the hypotheses Double_t nTotEvts = signalEvents_->value(); for (LauBkgndYieldList::const_iterator iter = bkgndEvents_.begin(); iter != bkgndEvents_.end(); ++iter) { nTotEvts += (*iter)->value(); if ( (*iter) == 0 ) { std::cerr << "ERROR in LauSimpleFitModel::setFitNEvents : Background yield not defined." << std::endl; return; } } this->eventsPerExpt(TMath::FloorNint(nTotEvts)); LauParameterPList& fitVars = this->fitPars(); // if doing an extended ML fit add the number of signal events into the fit parameters if (this->doEMLFit()) { std::cout << "INFO in LauSimpleFitModel::setFitNEvents : Initialising number of events for signal and background components..." << std::endl; // add the signal events to the list of fit parameters fitVars.push_back(signalEvents_); ++nNormPar_; } else { std::cout << "INFO in LauSimpleFitModel::setFitNEvents : Initialising number of events for background components (and hence signal)..." << std::endl; } if (useSCF_ && !useSCFHist_) { fitVars.push_back(&scfFrac_); ++nNormPar_; } if (usingBkgnd_ == kTRUE) { for (LauBkgndYieldList::iterator iter = bkgndEvents_.begin(); iter != bkgndEvents_.end(); ++iter) { std::vector parameters = (*iter)->getPars(); for ( LauParameter* parameter : parameters ) { if ( ! parameter->clone() ) { fitVars.push_back(parameter); ++nNormPar_; } } } } } void LauSimpleFitModel::setExtraNtupleVars() { // Set-up other parameters derived from the fit results, e.g. fit fractions. if (this->useDP() != kTRUE) { return; } // First clear the vectors so we start from scratch this->clearExtraVarVectors(); LauParameterList& extraVars = this->extraPars(); // Add a fit fraction for each signal component fitFrac_ = sigDPModel_->getFitFractions(); if (fitFrac_.size() != nSigComp_) { std::cerr << "ERROR in LauSimpleFitModel::setExtraNtupleVars : Initial Fit Fraction array of unexpected dimension: " << fitFrac_.size() << std::endl; gSystem->Exit(EXIT_FAILURE); } for (UInt_t i(0); iExit(EXIT_FAILURE); } } // Add the fit fraction that has not been corrected for the efficiency for each signal component fitFracEffUnCorr_ = sigDPModel_->getFitFractionsEfficiencyUncorrected(); if (fitFracEffUnCorr_.size() != nSigComp_) { std::cerr << "ERROR in LauSimpleFitModel::setExtraNtupleVars : Initial Fit Fraction array of unexpected dimension: " << fitFracEffUnCorr_.size() << std::endl; gSystem->Exit(EXIT_FAILURE); } for (UInt_t i(0); iExit(EXIT_FAILURE); } } for (UInt_t i = 0; i < nSigComp_; i++) { for (UInt_t j = i; j < nSigComp_; j++) { extraVars.push_back(fitFrac_[i][j]); extraVars.push_back(fitFracEffUnCorr_[i][j]); } } // Store any extra parameters/quantities from the DP model (e.g. K-matrix total fit fractions) std::vector extraParams = sigDPModel_->getExtraParameters(); std::vector::iterator extraIter; for (extraIter = extraParams.begin(); extraIter != extraParams.end(); ++extraIter) { LauParameter extraParameter = (*extraIter); extraVars.push_back(extraParameter); } // Now add in the DP efficiency value Double_t initMeanEff = sigDPModel_->getMeanEff().initValue(); meanEff_.value(initMeanEff); meanEff_.initValue(initMeanEff); meanEff_.genValue(initMeanEff); extraVars.push_back(meanEff_); // Also add in the DP rate Double_t initDPRate = sigDPModel_->getDPRate().initValue(); dpRate_.value(initDPRate); dpRate_.initValue(initDPRate); dpRate_.genValue(initDPRate); extraVars.push_back(dpRate_); } void LauSimpleFitModel::finaliseFitResults(const TString& tablePrefixName) { // Retrieve parameters from the fit results for calculations and toy generation // and eventually store these in output root ntuples/text files // Now take the fit parameters and update them as necessary // e.g. to make mag > 0.0 and phase in the right range. // This function will also calculate any other values, such as the // fit fractions, using any errors provided by fitParErrors as appropriate. // Also obtain the pull values: (measured - generated)/(average error) if (this->useDP() == kTRUE) { for (UInt_t i = 0; i < nSigComp_; i++) { // Check whether we have mag > 0.0, and phase in the right range coeffPars_[i]->finaliseValues(); } } // update the pulls on the events if (this->doEMLFit()) { signalEvents_->updatePull(); } if (useSCF_ && !useSCFHist_) { scfFrac_.updatePull(); } if (usingBkgnd_ == kTRUE) { for (LauBkgndYieldList::iterator iter = bkgndEvents_.begin(); iter != bkgndEvents_.end(); ++iter) { std::vector parameters = (*iter)->getPars(); for ( LauParameter* parameter : parameters ) { parameter->updatePull(); } } } // Update the pulls on all the extra PDFs' parameters this->updateFitParameters(signalPdfs_); if (useSCF_ == kTRUE) { this->updateFitParameters(scfPdfs_); } if (usingBkgnd_ == kTRUE) { for (LauBkgndPdfsList::iterator iter = bkgndPdfs_.begin(); iter != bkgndPdfs_.end(); ++iter) { this->updateFitParameters(*iter); } } // Fill the fit results to the ntuple for current experiment // update the coefficients and then calculate the fit fractions if (this->useDP() == kTRUE) { this->updateCoeffs(); sigDPModel_->updateCoeffs(coeffs_); sigDPModel_->calcExtraInfo(); LauParArray fitFrac = sigDPModel_->getFitFractions(); if (fitFrac.size() != nSigComp_) { std::cerr << "ERROR in LauSimpleFitModel::finaliseFitResults : Fit Fraction array of unexpected dimension: " << fitFrac.size() << std::endl; gSystem->Exit(EXIT_FAILURE); } for (UInt_t i(0); iExit(EXIT_FAILURE); } } LauParArray fitFracEffUnCorr = sigDPModel_->getFitFractionsEfficiencyUncorrected(); if (fitFracEffUnCorr.size() != nSigComp_) { std::cerr << "ERROR in LauSimpleFitModel::finaliseFitResults : Fit Fraction array of unexpected dimension: " << fitFracEffUnCorr.size() << std::endl; gSystem->Exit(EXIT_FAILURE); } for (UInt_t i(0); iExit(EXIT_FAILURE); } } for (UInt_t i(0); igetMeanEff().value()); dpRate_.value(sigDPModel_->getDPRate().value()); this->clearExtraVarVectors(); LauParameterList& extraVars = this->extraPars(); // Then store the final fit parameters, and any extra parameters for // the signal model (e.g. fit fractions) for (UInt_t i(0); i extraParams = sigDPModel_->getExtraParameters(); std::vector::iterator extraIter; for (extraIter = extraParams.begin(); extraIter != extraParams.end(); ++extraIter) { LauParameter extraParameter = (*extraIter); extraVars.push_back(extraParameter); } // Now add in the DP efficiency value extraVars.push_back(meanEff_); // Also add in the DP rate extraVars.push_back(dpRate_); this->printFitFractions(std::cout); } const LauParameterPList& fitVars = this->fitPars(); const LauParameterList& extraVars = this->extraPars(); LauFitNtuple* ntuple = this->fitNtuple(); ntuple->storeParsAndErrors(fitVars, extraVars); // find out the correlation matrix for the parameters ntuple->storeCorrMatrix(this->iExpt(), this->fitStatus(), this->covarianceMatrix()); // Fill the data into ntuple ntuple->updateFitNtuple(); // Print out the partial fit fractions, phases and the // averaged efficiency, reweighted by the dynamics (and anything else) if (this->writeLatexTable()) { TString sigOutFileName(tablePrefixName); sigOutFileName += "_"; sigOutFileName += this->iExpt(); sigOutFileName += "Expt.tex"; this->writeOutTable(sigOutFileName); } } void LauSimpleFitModel::printFitFractions(std::ostream& output) { // Print out Fit Fractions, total DP rate and mean efficiency for (UInt_t i = 0; i < nSigComp_; i++) { output << "FitFraction for component " << i << " (" << coeffPars_[i]->name() << ") = " << fitFrac_[i][i] << std::endl; } output << "Overall DP rate (integral of matrix element squared) = " << dpRate_ << std::endl; output << "Average efficiency weighted by whole DP dynamics = " << meanEff_ << std::endl; } void LauSimpleFitModel::writeOutTable(const TString& outputFile) { // Write out the results of the fit to a tex-readable table // TODO - need to include the yields in this table std::ofstream fout(outputFile); LauPrint print; std::cout << "INFO in LauSimpleFitModel::writeOutTable : Writing out results of the fit to the tex file " << outputFile << std::endl; if (this->useDP() == kTRUE) { // print the fit coefficients in one table coeffPars_.front()->printTableHeading(fout); for (UInt_t i = 0; i < nSigComp_; i++) { coeffPars_[i]->printTableRow(fout); } fout << "\\hline" << std::endl; fout << "\\end{tabular}" << std::endl << std::endl; // print the fit fractions in another fout << "\\begin{tabular}{|l|c|}" << std::endl; fout << "\\hline" << std::endl; fout << "Component & FitFraction \\\\" << std::endl; fout << "\\hline" << std::endl; Double_t fitFracSum(0.0); for (UInt_t i = 0; i < nSigComp_; i++) { TString resName = coeffPars_[i]->name(); resName = resName.ReplaceAll("_", "\\_"); fout << resName << " & $"; Double_t fitFrac = fitFrac_[i][i].value(); fitFracSum += fitFrac; print.printFormat(fout, fitFrac); fout << "$ \\\\" << std::endl; } fout << "\\hline" << std::endl; // Also print out sum of fit fractions fout << "Fit Fraction Sum & $"; print.printFormat(fout, fitFracSum); fout << "$ \\\\" << std::endl; fout << "\\hline" << std::endl; fout << "DP rate & $"; print.printFormat(fout, dpRate_.value()); fout << "$ \\\\" << std::endl; fout << "\\hline" << std::endl; fout << "$< \\varepsilon >$ & $"; print.printFormat(fout, meanEff_.value()); fout << "$ \\\\" << std::endl; fout << "\\hline" << std::endl; fout << "\\end{tabular}" << std::endl << std::endl; } if (!signalPdfs_.empty()) { fout << "\\begin{tabular}{|l|c|}" << std::endl; fout << "\\hline" << std::endl; if (useSCF_ == kTRUE) { fout << "\\Extra TM Signal PDFs' Parameters: & \\\\" << std::endl; } else { fout << "\\Extra Signal PDFs' Parameters: & \\\\" << std::endl; } this->printFitParameters(signalPdfs_, fout); if (useSCF_ == kTRUE && !scfPdfs_.empty()) { fout << "\\hline" << std::endl; fout << "\\Extra SCF Signal PDFs' Parameters: & \\\\" << std::endl; this->printFitParameters(scfPdfs_, fout); } if (usingBkgnd_ == kTRUE && !bkgndPdfs_.empty()) { fout << "\\hline" << std::endl; fout << "\\Extra Background PDFs' Parameters: & \\\\" << std::endl; for (LauBkgndPdfsList::const_iterator iter = bkgndPdfs_.begin(); iter != bkgndPdfs_.end(); ++iter) { this->printFitParameters(*iter, fout); } } fout << "\\hline \n\\end{tabular}" << std::endl << std::endl; } } void LauSimpleFitModel::checkInitFitParams() { // Update the number of signal events to be total-sum(background events) this->updateSigEvents(); // Check whether we want to have randomised initial fit parameters for the signal model if (this->useRandomInitFitPars() == kTRUE) { std::cout << "INFO in LauSimpleFitModel::checkInitFitParams : Setting random parameters for the signal DP model" << std::endl; this->randomiseInitFitPars(); } } void LauSimpleFitModel::randomiseInitFitPars() { // Only randomise those parameters that are not fixed! std::cout << "INFO in LauSimpleFitModel::randomiseInitFitPars : Randomising the initial fit magnitudes and phases of the resonances..." << std::endl; for (UInt_t i = 0; i < nSigComp_; i++) { coeffPars_[i]->randomiseInitValues(); } } std::pair LauSimpleFitModel::eventsToGenerate() { // Determine the number of events to generate for each hypothesis // If we're smearing then smear each one individually LauGenInfo nEvtsGen; // Keep track of whether any yield or asymmetry parameters are blinded Bool_t blind = kFALSE; // Signal Double_t evtWeight(1.0); Int_t nEvts = TMath::FloorNint(signalEvents_->genValue()); if ( nEvts < 0 ) { evtWeight = -1.0; nEvts = TMath::Abs( nEvts ); } if (this->doPoissonSmearing()) { nEvts = LauRandom::randomFun()->Poisson(nEvts); } nEvtsGen["signal"] = std::make_pair( nEvts, evtWeight ); if ( signalEvents_->blind() ) { blind = kTRUE; } // Backgrounds const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) { const TString& bkgndClass = this->bkgndClassName(bkgndID); const LauAbsRValue* evtsPar = bkgndEvents_[bkgndID]; evtWeight = 1.0; nEvts = TMath::FloorNint( evtsPar->genValue() ); if ( nEvts < 0 ) { evtWeight = -1.0; nEvts = TMath::Abs( nEvts ); } if (this->doPoissonSmearing()) { nEvts = LauRandom::randomFun()->Poisson(nEvts); } nEvtsGen[bkgndClass] = std::make_pair( nEvts, evtWeight ); if ( evtsPar->blind() ) { blind = kTRUE; } } return std::make_pair( nEvtsGen, blind ); } Bool_t LauSimpleFitModel::genExpt() { // Routine to generate toy Monte Carlo events according to the various models we have defined. // Determine the number of events to generate for each hypothesis std::pair info = this->eventsToGenerate(); LauGenInfo nEvts = info.first; const Bool_t blind = info.second; Bool_t genOK(kTRUE); Int_t evtNum(0); const UInt_t nBkgnds = this->nBkgndClasses(); std::vector bkgndClassNames(nBkgnds); std::vector bkgndClassNamesGen(nBkgnds); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { TString name( this->bkgndClassName(iBkgnd) ); bkgndClassNames[iBkgnd] = name; bkgndClassNamesGen[iBkgnd] = "gen"+name; } const Bool_t storeSCFTruthInfo = ( useSCF_ || ( this->enableEmbedding() && signalTree_ != 0 && signalTree_->haveBranch("mcMatch") ) ); // Loop over the hypotheses and generate the requested number of events for each one for (LauGenInfo::const_iterator iter = nEvts.begin(); iter != nEvts.end(); ++iter) { const TString& type(iter->first); Int_t nEvtsGen( iter->second.first ); Double_t evtWeight( iter->second.second ); for (Int_t iEvt(0); iEvtsetGenNtupleDoubleBranchValue( "evtWeight", evtWeight ); // Add efficiency information this->setGenNtupleDoubleBranchValue( "efficiency", 1 ); if (type == "signal") { this->setGenNtupleIntegerBranchValue("genSig",1); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { this->setGenNtupleIntegerBranchValue( bkgndClassNamesGen[iBkgnd], 0 ); } genOK = this->generateSignalEvent(); this->setGenNtupleDoubleBranchValue( "efficiency", sigDPModel_->getEvtEff() ); } else { this->setGenNtupleIntegerBranchValue("genSig",0); if ( storeSCFTruthInfo ) { this->setGenNtupleIntegerBranchValue("genTMSig",0); this->setGenNtupleIntegerBranchValue("genSCFSig",0); } UInt_t bkgndID(0); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { Int_t gen(0); if ( bkgndClassNames[iBkgnd] == type ) { gen = 1; bkgndID = iBkgnd; } this->setGenNtupleIntegerBranchValue( bkgndClassNamesGen[iBkgnd], gen ); } genOK = this->generateBkgndEvent(bkgndID); } if (!genOK) { // If there was a problem with the generation then break out and return. // The problem model will have adjusted itself so that all should be OK next time. break; } if (this->useDP() == kTRUE) { this->setDPBranchValues(); } // Store the event number (within this experiment) this->setGenNtupleIntegerBranchValue("iEvtWithinExpt",evtNum); // and then increment it ++evtNum; this->fillGenNtupleBranches(); if ( !blind && (iEvt%500 == 0) ) { std::cout << "INFO in LauSimpleFitModel::genExpt : Generated event number " << iEvt << " out of " << nEvtsGen << " " << type << " events." << std::endl; } } if (!genOK) { break; } } if (this->useDP() && genOK) { sigDPModel_->checkToyMC(kTRUE,kTRUE); // Get the fit fractions if they're to be written into the latex table if (this->writeLatexTable()) { LauParArray fitFrac = sigDPModel_->getFitFractions(); if (fitFrac.size() != nSigComp_) { std::cerr << "ERROR in LauSimpleFitModel::genExpt : Fit Fraction array of unexpected dimension: " << fitFrac.size() << std::endl; gSystem->Exit(EXIT_FAILURE); } for (UInt_t i(0); iExit(EXIT_FAILURE); } } for (UInt_t i(0); igetMeanEff().value()); dpRate_.value(sigDPModel_->getDPRate().value()); } } // If we're reusing embedded events or if the generation is being // reset then clear the lists of used events if (reuseSignal_ || !genOK) { if (signalTree_) { signalTree_->clearUsedList(); } } for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) { LauEmbeddedData* data = bkgndTree_[bkgndID]; if (reuseBkgnd_[bkgndID] || !genOK) { if (data) { data->clearUsedList(); } } } return genOK; } Bool_t LauSimpleFitModel::generateSignalEvent() { // Generate signal event Bool_t genOK(kTRUE); Bool_t genSCF(kFALSE); if (this->useDP()) { if (this->enableEmbedding() && signalTree_) { if (useReweighting_) { // Select a (random) event from the generated data. Then store the // reconstructed DP co-ords, together with other pdf information, // as the embedded data. genOK = signalTree_->getReweightedEvent(sigDPModel_); } else { signalTree_->getEmbeddedEvent(kinematics_); } if (signalTree_->haveBranch("mcMatch")) { Int_t match = static_cast(signalTree_->getValue("mcMatch")); if (match) { this->setGenNtupleIntegerBranchValue("genTMSig",1); this->setGenNtupleIntegerBranchValue("genSCFSig",0); genSCF = kFALSE; } else { this->setGenNtupleIntegerBranchValue("genTMSig",0); this->setGenNtupleIntegerBranchValue("genSCFSig",1); genSCF = kTRUE; } } } else { genOK = sigDPModel_->generate(); if ( genOK && useSCF_ ) { Double_t frac(0.0); if ( useSCFHist_ ) { frac = scfFracHist_->calcEfficiency( kinematics_ ); } else { frac = scfFrac_.genValue(); } if ( frac < LauRandom::randomFun()->Rndm() ) { this->setGenNtupleIntegerBranchValue("genTMSig",1); this->setGenNtupleIntegerBranchValue("genSCFSig",0); genSCF = kFALSE; } else { this->setGenNtupleIntegerBranchValue("genTMSig",0); this->setGenNtupleIntegerBranchValue("genSCFSig",1); genSCF = kTRUE; // Optionally smear the DP position // of the SCF event if ( scfMap_ != 0 ) { Double_t xCoord(0.0), yCoord(0.0); if ( kinematics_->squareDP() ) { xCoord = kinematics_->getmPrime(); yCoord = kinematics_->getThetaPrime(); } else { xCoord = kinematics_->getm13Sq(); yCoord = kinematics_->getm23Sq(); } // Find the bin number where this event is generated Int_t binNo = scfMap_->binNumber( xCoord, yCoord ); // Retrieve the migration histogram TH2* histo = scfMap_->trueHist( binNo ); const LauAbsEffModel * effModel = sigDPModel_->getEffModel(); do { // Get a random point from the histogram histo->GetRandom2( xCoord, yCoord ); // Update the kinematics if ( kinematics_->squareDP() ) { kinematics_->updateSqDPKinematics( xCoord, yCoord ); } else { kinematics_->updateKinematics( xCoord, yCoord ); } } while ( ! effModel->passVeto( kinematics_ ) ); } } } } } else { if (this->enableEmbedding() && signalTree_) { signalTree_->getEmbeddedEvent(0); if (signalTree_->haveBranch("mcMatch")) { Int_t match = static_cast(signalTree_->getValue("mcMatch")); if (match) { this->setGenNtupleIntegerBranchValue("genTMSig",1); this->setGenNtupleIntegerBranchValue("genSCFSig",0); genSCF = kFALSE; } else { this->setGenNtupleIntegerBranchValue("genTMSig",0); this->setGenNtupleIntegerBranchValue("genSCFSig",1); genSCF = kTRUE; } } } else if ( useSCF_ ) { Double_t frac = scfFrac_.genValue(); if ( frac < LauRandom::randomFun()->Rndm() ) { this->setGenNtupleIntegerBranchValue("genTMSig",1); this->setGenNtupleIntegerBranchValue("genSCFSig",0); genSCF = kFALSE; } else { this->setGenNtupleIntegerBranchValue("genTMSig",0); this->setGenNtupleIntegerBranchValue("genSCFSig",1); genSCF = kTRUE; } } } if (genOK) { if ( useSCF_ ) { if ( genSCF ) { this->generateExtraPdfValues(&scfPdfs_, signalTree_); } else { this->generateExtraPdfValues(&signalPdfs_, signalTree_); } } else { this->generateExtraPdfValues(&signalPdfs_, signalTree_); } } // Check for problems with the embedding if (this->enableEmbedding() && signalTree_ && (signalTree_->nEvents() == signalTree_->nUsedEvents())) { std::cerr << "WARNING in LauSimpleFitModel::generateSignalEvent : Source of embedded signal events used up, clearing the list of used events." << std::endl; signalTree_->clearUsedList(); } return genOK; } Bool_t LauSimpleFitModel::generateBkgndEvent(UInt_t bkgndID) { // Generate background event Bool_t genOK(kTRUE); LauAbsBkgndDPModel* model = bkgndDPModels_[bkgndID]; LauEmbeddedData* embeddedData(0); if (this->enableEmbedding()) { embeddedData = bkgndTree_[bkgndID]; } LauPdfList* extraPdfs = &bkgndPdfs_[bkgndID]; if (this->useDP()) { if (embeddedData) { embeddedData->getEmbeddedEvent(kinematics_); } else { if (model == 0) { std::cerr << "ERROR in LauSimpleFitModel::generateBkgndEvent : Can't find the DP model for background class \"" << this->bkgndClassName(bkgndID) << "\"." << std::endl; gSystem->Exit(EXIT_FAILURE); } genOK = model->generate(); } } else { if (embeddedData) { embeddedData->getEmbeddedEvent(0); } } if (genOK) { this->generateExtraPdfValues(extraPdfs, embeddedData); } // Check for problems with the embedding if (embeddedData && (embeddedData->nEvents() == embeddedData->nUsedEvents())) { std::cerr << "WARNING in LauSimpleFitModel::generateBkgndEvent : Source of embedded " << this->bkgndClassName(bkgndID) << " events used up, clearing the list of used events." << std::endl; embeddedData->clearUsedList(); } return genOK; } void LauSimpleFitModel::setupGenNtupleBranches() { // Setup the required ntuple branches this->addGenNtupleDoubleBranch("evtWeight"); this->addGenNtupleIntegerBranch("genSig"); this->addGenNtupleDoubleBranch("efficiency"); if ( useSCF_ || ( this->enableEmbedding() && signalTree_ != 0 && signalTree_->haveBranch("mcMatch") ) ) { this->addGenNtupleIntegerBranch("genTMSig"); this->addGenNtupleIntegerBranch("genSCFSig"); } const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { TString name( this->bkgndClassName(iBkgnd) ); name.Prepend("gen"); this->addGenNtupleIntegerBranch(name); } if (this->useDP() == kTRUE) { this->addGenNtupleDoubleBranch("m12"); this->addGenNtupleDoubleBranch("m23"); this->addGenNtupleDoubleBranch("m13"); this->addGenNtupleDoubleBranch("m12Sq"); this->addGenNtupleDoubleBranch("m23Sq"); this->addGenNtupleDoubleBranch("m13Sq"); this->addGenNtupleDoubleBranch("cosHel12"); this->addGenNtupleDoubleBranch("cosHel23"); this->addGenNtupleDoubleBranch("cosHel13"); if (kinematics_->squareDP()) { this->addGenNtupleDoubleBranch("mPrime"); this->addGenNtupleDoubleBranch("thPrime"); } } for (LauPdfList::const_iterator pdf_iter = signalPdfs_.begin(); pdf_iter != signalPdfs_.end(); ++pdf_iter) { std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { this->addGenNtupleDoubleBranch( (*var_iter) ); } } } } void LauSimpleFitModel::setDPBranchValues() { // Store all the DP information this->setGenNtupleDoubleBranchValue("m12", kinematics_->getm12()); this->setGenNtupleDoubleBranchValue("m23", kinematics_->getm23()); this->setGenNtupleDoubleBranchValue("m13", kinematics_->getm13()); this->setGenNtupleDoubleBranchValue("m12Sq", kinematics_->getm12Sq()); this->setGenNtupleDoubleBranchValue("m23Sq", kinematics_->getm23Sq()); this->setGenNtupleDoubleBranchValue("m13Sq", kinematics_->getm13Sq()); this->setGenNtupleDoubleBranchValue("cosHel12", kinematics_->getc12()); this->setGenNtupleDoubleBranchValue("cosHel23", kinematics_->getc23()); this->setGenNtupleDoubleBranchValue("cosHel13", kinematics_->getc13()); if (kinematics_->squareDP()) { this->setGenNtupleDoubleBranchValue("mPrime", kinematics_->getmPrime()); this->setGenNtupleDoubleBranchValue("thPrime", kinematics_->getThetaPrime()); } } void LauSimpleFitModel::generateExtraPdfValues(LauPdfList* extraPdfs, LauEmbeddedData* embeddedData) { // Generate from the extra PDFs if (extraPdfs) { for (LauPdfList::iterator pdf_iter = extraPdfs->begin(); pdf_iter != extraPdfs->end(); ++pdf_iter) { LauFitData genValues; if (embeddedData) { genValues = embeddedData->getValues( (*pdf_iter)->varNames() ); } else { genValues = (*pdf_iter)->generate(kinematics_); } for ( LauFitData::const_iterator var_iter = genValues.begin(); var_iter != genValues.end(); ++var_iter ) { TString varName = var_iter->first; if ( varName != "m13Sq" && varName != "m23Sq" ) { Double_t value = var_iter->second; this->setGenNtupleDoubleBranchValue(varName,value); } } } } } void LauSimpleFitModel::propagateParUpdates() { // Update the total normalisation for the signal likelihood if (this->useDP() == kTRUE) { this->updateCoeffs(); sigDPModel_->updateCoeffs(coeffs_); } // Update the signal events from the background events if not doing an extended fit if ( !this->doEMLFit() && !signalEvents_->fixed() ) { this->updateSigEvents(); } } void LauSimpleFitModel::updateSigEvents() { // The background parameters will have been set from Minuit. // We need to update the signal events using these. Double_t nTotEvts = this->eventsPerExpt(); signalEvents_->range(-2.0*nTotEvts,2.0*nTotEvts); for (LauBkgndYieldList::iterator iter = bkgndEvents_.begin(); iter != bkgndEvents_.end(); ++iter) { LauAbsRValue* nBkgndEvents = (*iter); if ( nBkgndEvents->isLValue() ) { LauParameter* yield = dynamic_cast( nBkgndEvents ); yield->range(-2.0*nTotEvts,2.0*nTotEvts); } } if ( signalEvents_->fixed() ) { return; } // Subtract background events (if any) from signal. Double_t signalEvents = nTotEvts; if ( usingBkgnd_ == kTRUE ) { for (LauBkgndYieldList::const_iterator iter = bkgndEvents_.begin(); iter != bkgndEvents_.end(); ++iter) { signalEvents -= (*iter)->value(); } } signalEvents_->value(signalEvents); } void LauSimpleFitModel::cacheInputFitVars() { // Fill the internal data trees of the signal and backgrond models. LauFitDataTree* inputFitData = this->fitData(); // First the Dalitz plot variables (m_ij^2) if (this->useDP() == kTRUE) { // need to append SCF smearing bins before caching DP amplitudes if ( scfMap_ != 0 ) { this->appendBinCentres( inputFitData ); } sigDPModel_->fillDataTree(*inputFitData); if (usingBkgnd_ == kTRUE) { for (LauBkgndDPModelList::iterator iter = bkgndDPModels_.begin(); iter != bkgndDPModels_.end(); ++iter) { (*iter)->fillDataTree(*inputFitData); } } } // ...and then the extra PDFs this->cacheInfo(signalPdfs_, *inputFitData); this->cacheInfo(scfPdfs_, *inputFitData); for (LauBkgndPdfsList::iterator iter = bkgndPdfs_.begin(); iter != bkgndPdfs_.end(); ++iter) { this->cacheInfo((*iter), *inputFitData); } // and finally the SCF fractions and jacobians if ( useSCF_ && useSCFHist_ ) { if ( !inputFitData->haveBranch( "m13Sq" ) || !inputFitData->haveBranch( "m23Sq" ) ) { std::cerr << "ERROR in LauSimpleFitModel::cacheInputFitVars : Input data does not contain DP branches and so can't cache the SCF fraction." << std::endl; gSystem->Exit(EXIT_FAILURE); } UInt_t nEvents = inputFitData->nEvents(); recoSCFFracs_.clear(); recoSCFFracs_.reserve( nEvents ); if ( kinematics_->squareDP() ) { recoJacobians_.clear(); recoJacobians_.reserve( nEvents ); } for (UInt_t iEvt = 0; iEvt < nEvents; iEvt++) { const LauFitData& dataValues = inputFitData->getData(iEvt); LauFitData::const_iterator m13_iter = dataValues.find("m13Sq"); LauFitData::const_iterator m23_iter = dataValues.find("m23Sq"); kinematics_->updateKinematics( m13_iter->second, m23_iter->second ); Double_t scfFrac = scfFracHist_->calcEfficiency( kinematics_ ); recoSCFFracs_.push_back( scfFrac ); if ( kinematics_->squareDP() ) { recoJacobians_.push_back( kinematics_->calcSqDPJacobian() ); } } } } void LauSimpleFitModel::appendBinCentres( LauFitDataTree* inputData ) { // We'll be caching the DP amplitudes and efficiencies of the centres of the true bins. // To do so, we attach some fake points at the end of inputData, the number of the entry // minus the total number of events corresponding to the number of the histogram for that // given true bin in the LauScfMap object. (What this means is that when Laura is provided with // the LauScfMap object by the user, it's the latter who has to make sure that it contains the // right number of histograms and in exactly the right order!) // Get the x and y co-ordinates of the bin centres std::vector binCentresXCoords; std::vector binCentresYCoords; scfMap_->listBinCentres(binCentresXCoords, binCentresYCoords); // The SCF histograms could be in square Dalitz plot histograms. // The dynamics takes normal Dalitz plot coords, so we might have to convert them back. Bool_t sqDP = kinematics_->squareDP(); UInt_t nBins = binCentresXCoords.size(); fakeSCFFracs_.clear(); fakeSCFFracs_.reserve( nBins ); if ( sqDP ) { fakeJacobians_.clear(); fakeJacobians_.reserve( nBins ); } for (UInt_t iBin = 0; iBin < nBins; ++iBin) { if ( sqDP ) { kinematics_->updateSqDPKinematics(binCentresXCoords[iBin],binCentresYCoords[iBin]); binCentresXCoords[iBin] = kinematics_->getm13Sq(); binCentresYCoords[iBin] = kinematics_->getm23Sq(); fakeJacobians_.push_back( kinematics_->calcSqDPJacobian() ); } else { kinematics_->updateKinematics(binCentresXCoords[iBin],binCentresYCoords[iBin]); } fakeSCFFracs_.push_back( scfFracHist_->calcEfficiency( kinematics_ ) ); } // Set up inputFitVars_ object to hold the fake events inputData->appendFakePoints(binCentresXCoords,binCentresYCoords); } Double_t LauSimpleFitModel::getTotEvtLikelihood(UInt_t iEvt) { // Get the DP likelihood for signal and backgrounds this->getEvtDPLikelihood(iEvt); // Get the combined extra PDFs likelihood for signal and backgrounds this->getEvtExtraLikelihoods(iEvt); // If appropriate, combine the TM and SCF likelihoods Double_t sigLike = sigDPLike_ * sigExtraLike_; if ( useSCF_ ) { Double_t scfFrac(0.0); if (useSCFHist_) { scfFrac = recoSCFFracs_[iEvt]; } else { scfFrac = scfFrac_.unblindValue(); } sigLike *= (1.0 - scfFrac); if ( (scfMap_ != 0) && (this->useDP() == kTRUE) ) { // if we're smearing the SCF DP PDF then the SCF frac // is already included in the SCF DP likelihood sigLike += (scfDPLike_ * scfExtraLike_); } else { sigLike += (scfFrac * scfDPLike_ * scfExtraLike_); } } // Construct the total event likelihood Double_t likelihood = signalEvents_->unblindValue() * sigLike; const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) { likelihood += (bkgndEvents_[bkgndID]->unblindValue() * bkgndDPLike_[bkgndID] * bkgndExtraLike_[bkgndID]); } return likelihood; } Double_t LauSimpleFitModel::getEventSum() const { Double_t eventSum(0.0); eventSum += signalEvents_->unblindValue(); for (LauBkgndYieldList::const_iterator iter = bkgndEvents_.begin(); iter != bkgndEvents_.end(); ++iter) { eventSum += (*iter)->unblindValue(); } return eventSum; } void LauSimpleFitModel::getEvtDPLikelihood(UInt_t iEvt) { // Function to return the signal and background likelihoods for the // Dalitz plot for the given event evtNo. if (this->useDP() == kTRUE) { sigDPModel_->calcLikelihoodInfo(iEvt); sigDPLike_ = sigDPModel_->getEvtLikelihood(); if ( useSCF_ == kTRUE ) { if ( scfMap_ == 0 ) { // we're not smearing the SCF DP position // so the likelihood is the same as the TM scfDPLike_ = sigDPLike_; } else { // calculate the smeared SCF DP likelihood scfDPLike_ = this->getEvtSCFDPLikelihood(iEvt); } } const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) { if (usingBkgnd_ == kTRUE) { bkgndDPLike_[bkgndID] = bkgndDPModels_[bkgndID]->getLikelihood(iEvt); } else { bkgndDPLike_[bkgndID] = 0.0; } } } else { // There's always going to be a term in the likelihood for the // signal, so we'd better not zero it. sigDPLike_ = 1.0; scfDPLike_ = 1.0; const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) { if (usingBkgnd_ == kTRUE) { bkgndDPLike_[bkgndID] = 1.0; } else { bkgndDPLike_[bkgndID] = 0.0; } } } } Double_t LauSimpleFitModel::getEvtSCFDPLikelihood(UInt_t iEvt) { Double_t scfDPLike(0.0); Double_t recoJacobian(1.0); Double_t xCoord(0.0); Double_t yCoord(0.0); Bool_t squareDP = kinematics_->squareDP(); if ( squareDP ) { xCoord = sigDPModel_->getEvtmPrime(); yCoord = sigDPModel_->getEvtthPrime(); recoJacobian = recoJacobians_[iEvt]; } else { xCoord = sigDPModel_->getEvtm13Sq(); yCoord = sigDPModel_->getEvtm23Sq(); } // Find the bin that our reco event falls in Int_t recoBin = scfMap_->binNumber( xCoord, yCoord ); // Find out which true Bins contribute to the given reco bin const std::vector* trueBins = scfMap_->trueBins(recoBin); Int_t nDataEvents = this->eventsPerExpt(); // Loop over the true bins for (std::vector::const_iterator iter = trueBins->begin(); iter != trueBins->end(); ++iter) { Int_t trueBin = (*iter); // prob of a true event in the given true bin migrating to the reco bin Double_t pRecoGivenTrue = scfMap_->prob( recoBin, trueBin ); // We've cached the DP amplitudes and the efficiency for the // true bin centres, just after the data points sigDPModel_->calcLikelihoodInfo( nDataEvents + trueBin ); Double_t pTrue = sigDPModel_->getEvtLikelihood(); // Get the cached SCF fraction (and jacobian if we're using the square DP) Double_t scfFraction = fakeSCFFracs_[ trueBin ]; Double_t jacobian(1.0); if ( squareDP ) { jacobian = fakeJacobians_[ trueBin ]; } scfDPLike += pTrue * jacobian * scfFraction * pRecoGivenTrue; } // Divide by the reco jacobian scfDPLike /= recoJacobian; return scfDPLike; } void LauSimpleFitModel::getEvtExtraLikelihoods(UInt_t iEvt) { // Function to return the signal and background likelihoods for the // extra variables for the given event evtNo. sigExtraLike_ = 1.0; for (LauPdfList::iterator iter = signalPdfs_.begin(); iter != signalPdfs_.end(); ++iter) { (*iter)->calcLikelihoodInfo(iEvt); sigExtraLike_ *= (*iter)->getLikelihood(); } if (useSCF_) { scfExtraLike_ = 1.0; for (LauPdfList::iterator iter = scfPdfs_.begin(); iter != scfPdfs_.end(); ++iter) { (*iter)->calcLikelihoodInfo(iEvt); scfExtraLike_ *= (*iter)->getLikelihood(); } } const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) { if (usingBkgnd_) { bkgndExtraLike_[bkgndID] = 1.0; LauPdfList& pdfList = bkgndPdfs_[bkgndID]; for (LauPdfList::iterator pdf_iter = pdfList.begin(); pdf_iter != pdfList.end(); ++pdf_iter) { (*pdf_iter)->calcLikelihoodInfo(iEvt); bkgndExtraLike_[bkgndID] *= (*pdf_iter)->getLikelihood(); } } else { bkgndExtraLike_[bkgndID] = 0.0; } } } void LauSimpleFitModel::updateCoeffs() { coeffs_.clear(); coeffs_.reserve(nSigComp_); for (UInt_t i = 0; i < nSigComp_; i++) { coeffs_.push_back(coeffPars_[i]->particleCoeff()); } } void LauSimpleFitModel::setupSPlotNtupleBranches() { // add branches for storing the experiment number and the number of // the event within the current experiment this->addSPlotNtupleIntegerBranch("iExpt"); this->addSPlotNtupleIntegerBranch("iEvtWithinExpt"); // Store the efficiency of the event (for inclusive BF calculations). if (this->storeDPEff()) { this->addSPlotNtupleDoubleBranch("efficiency"); if ( sigDPModel_->usingScfModel() ) { this->addSPlotNtupleDoubleBranch("scffraction"); } } // Store the total event likelihood for each species. if (useSCF_) { this->addSPlotNtupleDoubleBranch("sigTMTotalLike"); this->addSPlotNtupleDoubleBranch("sigSCFTotalLike"); this->addSPlotNtupleDoubleBranch("sigSCFFrac"); } else { this->addSPlotNtupleDoubleBranch("sigTotalLike"); } if (usingBkgnd_) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { TString name( this->bkgndClassName(iBkgnd) ); name += "TotalLike"; this->addSPlotNtupleDoubleBranch(name); } } // Store the DP likelihoods if (this->useDP()) { if (useSCF_) { this->addSPlotNtupleDoubleBranch("sigTMDPLike"); this->addSPlotNtupleDoubleBranch("sigSCFDPLike"); } else { this->addSPlotNtupleDoubleBranch("sigDPLike"); } if (usingBkgnd_) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { TString name( this->bkgndClassName(iBkgnd) ); name += "DPLike"; this->addSPlotNtupleDoubleBranch(name); } } } // Store the likelihoods for each extra PDF if (useSCF_) { this->addSPlotNtupleBranches(&signalPdfs_, "sigTM"); this->addSPlotNtupleBranches(&scfPdfs_, "sigSCF"); } else { this->addSPlotNtupleBranches(&signalPdfs_, "sig"); } if (usingBkgnd_) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { const TString& bkgndClass = this->bkgndClassName(iBkgnd); const LauPdfList* pdfList = &(bkgndPdfs_[iBkgnd]); this->addSPlotNtupleBranches(pdfList, bkgndClass); } } } void LauSimpleFitModel::addSPlotNtupleBranches(const LauPdfList* extraPdfs, const TString& prefix) { if (extraPdfs) { // Loop through each of the PDFs for (LauPdfList::const_iterator pdf_iter = extraPdfs->begin(); pdf_iter != extraPdfs->end(); ++pdf_iter) { // Count the number of input variables that are not // DP variables (used in the case where there is DP // dependence for e.g. MVA) UInt_t nVars(0); std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { ++nVars; } } if ( nVars == 1 ) { // If the PDF only has one variable then // simply add one branch for that variable TString varName = (*pdf_iter)->varName(); TString name(prefix); name += varName; name += "Like"; this->addSPlotNtupleDoubleBranch(name); } else if ( nVars == 2 ) { // If the PDF has two variables then we // need a branch for them both together and // branches for each TString allVars(""); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { allVars += (*var_iter); TString name(prefix); name += (*var_iter); name += "Like"; this->addSPlotNtupleDoubleBranch(name); } TString name(prefix); name += allVars; name += "Like"; this->addSPlotNtupleDoubleBranch(name); } else { std::cerr << "WARNING in LauSimpleFitModel::addSPlotNtupleBranches : Can't yet deal with 3D PDFs." << std::endl; } } } } Double_t LauSimpleFitModel::setSPlotNtupleBranchValues(LauPdfList* extraPdfs, const TString& prefix, UInt_t iEvt) { // Store the PDF value for each variable in the list Double_t totalLike(1.0); Double_t extraLike(0.0); if (extraPdfs) { for (LauPdfList::iterator pdf_iter = extraPdfs->begin(); pdf_iter != extraPdfs->end(); ++pdf_iter) { // calculate the likelihood for this event (*pdf_iter)->calcLikelihoodInfo(iEvt); extraLike = (*pdf_iter)->getLikelihood(); totalLike *= extraLike; // Count the number of input variables that are not // DP variables (used in the case where there is DP // dependence for e.g. MVA) UInt_t nVars(0); std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { ++nVars; } } if ( nVars == 1 ) { // If the PDF only has one variable then // simply store the value for that variable TString varName = (*pdf_iter)->varName(); TString name(prefix); name += varName; name += "Like"; this->setSPlotNtupleDoubleBranchValue(name, extraLike); } else if ( nVars == 2 ) { // If the PDF has two variables then we // store the value for them both together // and for each on their own TString allVars(""); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { allVars += (*var_iter); TString name(prefix); name += (*var_iter); name += "Like"; Double_t indivLike = (*pdf_iter)->getLikelihood( (*var_iter) ); this->setSPlotNtupleDoubleBranchValue(name, indivLike); } TString name(prefix); name += allVars; name += "Like"; this->setSPlotNtupleDoubleBranchValue(name, extraLike); } else { std::cerr << "WARNING in LauSimpleFitModel::setSPlotNtupleBranchValues : Can't yet deal with 3D PDFs." << std::endl; } } } return totalLike; } LauSPlot::NameSet LauSimpleFitModel::variableNames() const { LauSPlot::NameSet nameSet; if (this->useDP()) { nameSet.insert("DP"); } // Loop through all the signal PDFs for (LauPdfList::const_iterator pdf_iter = signalPdfs_.begin(); pdf_iter != signalPdfs_.end(); ++pdf_iter) { // Loop over the variables involved in each PDF std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { // If they are not DP coordinates then add them if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { nameSet.insert( (*var_iter) ); } } } return nameSet; } LauSPlot::NumbMap LauSimpleFitModel::freeSpeciesNames() const { LauSPlot::NumbMap numbMap; if (!signalEvents_->fixed() && this->doEMLFit()) { numbMap["sig"] = signalEvents_->genValue(); } if ( usingBkgnd_ ) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { const TString& bkgndClass = this->bkgndClassName(iBkgnd); const LauAbsRValue* par = bkgndEvents_[iBkgnd]; if (!par->fixed()) { numbMap[bkgndClass] = par->genValue(); if ( ! par->isLValue() ) { std::cerr << "WARNING in LauSimpleFitModel::freeSpeciesNames : \"" << par->name() << "\" is a LauFormulaPar, which implies it is perhaps not entirely free to float in the fit, so the sWeight calculation may not be reliable" << std::endl; } } } } return numbMap; } LauSPlot::NumbMap LauSimpleFitModel::fixdSpeciesNames() const { LauSPlot::NumbMap numbMap; if (signalEvents_->fixed() && this->doEMLFit()) { numbMap["sig"] = signalEvents_->genValue(); } if ( usingBkgnd_ ) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { const TString& bkgndClass = this->bkgndClassName(iBkgnd); const LauAbsRValue* par = bkgndEvents_[iBkgnd]; if (par->fixed()) { numbMap[bkgndClass] = par->genValue(); } } } return numbMap; } LauSPlot::TwoDMap LauSimpleFitModel::twodimPDFs() const { LauSPlot::TwoDMap twodimMap; for (LauPdfList::const_iterator pdf_iter = signalPdfs_.begin(); pdf_iter != signalPdfs_.end(); ++pdf_iter) { // Count the number of input variables that are not DP variables UInt_t nVars(0); std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { ++nVars; } } if ( nVars == 2 ) { if (useSCF_) { twodimMap.insert( std::make_pair( "sigTM", std::make_pair( varNames[0], varNames[1] ) ) ); } else { twodimMap.insert( std::make_pair( "sig", std::make_pair( varNames[0], varNames[1] ) ) ); } } } if ( useSCF_ ) { for (LauPdfList::const_iterator pdf_iter = scfPdfs_.begin(); pdf_iter != scfPdfs_.end(); ++pdf_iter) { // Count the number of input variables that are not DP variables UInt_t nVars(0); std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { ++nVars; } } if ( nVars == 2 ) { twodimMap.insert( std::make_pair( "sigSCF", std::make_pair( varNames[0], varNames[1] ) ) ); } } } if (usingBkgnd_) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { const TString& bkgndClass = this->bkgndClassName(iBkgnd); const LauPdfList& pdfList = bkgndPdfs_[iBkgnd]; for (LauPdfList::const_iterator pdf_iter = pdfList.begin(); pdf_iter != pdfList.end(); ++pdf_iter) { // Count the number of input variables that are not DP variables UInt_t nVars(0); std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { ++nVars; } } if ( nVars == 2 ) { twodimMap.insert( std::make_pair( bkgndClass, std::make_pair( varNames[0], varNames[1] ) ) ); } } } } return twodimMap; } void LauSimpleFitModel::storePerEvtLlhds() { std::cout << "INFO in LauSimpleFitModel::storePerEvtLlhds : Storing per-event likelihood values..." << std::endl; // if we've not been using the DP model then we need to cache all // the info here so that we can get the efficiency from it LauFitDataTree* inputFitData = this->fitData(); if (!this->useDP() && this->storeDPEff()) { sigDPModel_->initialise(coeffs_); sigDPModel_->fillDataTree(*inputFitData); } UInt_t evtsPerExpt(this->eventsPerExpt()); for (UInt_t iEvt = 0; iEvt < evtsPerExpt; ++iEvt) { this->setSPlotNtupleIntegerBranchValue("iExpt",this->iExpt()); this->setSPlotNtupleIntegerBranchValue("iEvtWithinExpt",iEvt); // the DP information this->getEvtDPLikelihood(iEvt); if (this->storeDPEff()) { if (!this->useDP()) { sigDPModel_->calcLikelihoodInfo(iEvt); } this->setSPlotNtupleDoubleBranchValue("efficiency",sigDPModel_->getEvtEff()); if ( sigDPModel_->usingScfModel() ) { this->setSPlotNtupleDoubleBranchValue("scffraction",sigDPModel_->getEvtScfFraction()); } } if (this->useDP()) { sigTotalLike_ = sigDPLike_; if (useSCF_) { scfTotalLike_ = scfDPLike_; this->setSPlotNtupleDoubleBranchValue("sigTMDPLike",sigDPLike_); this->setSPlotNtupleDoubleBranchValue("sigSCFDPLike",scfDPLike_); } else { this->setSPlotNtupleDoubleBranchValue("sigDPLike",sigDPLike_); } if (usingBkgnd_) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { TString name = this->bkgndClassName(iBkgnd); name += "DPLike"; this->setSPlotNtupleDoubleBranchValue(name,bkgndDPLike_[iBkgnd]); } } } else { sigTotalLike_ = 1.0; if (useSCF_) { scfTotalLike_ = 1.0; } if (usingBkgnd_) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { bkgndTotalLike_[iBkgnd] = 1.0; } } } // the signal PDF values if ( useSCF_ ) { sigTotalLike_ *= this->setSPlotNtupleBranchValues(&signalPdfs_, "sigTM", iEvt); scfTotalLike_ *= this->setSPlotNtupleBranchValues(&scfPdfs_, "sigSCF", iEvt); } else { sigTotalLike_ *= this->setSPlotNtupleBranchValues(&signalPdfs_, "sig", iEvt); } // the background PDF values if (usingBkgnd_) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { const TString& bkgndClass = this->bkgndClassName(iBkgnd); LauPdfList& pdfs = bkgndPdfs_[iBkgnd]; bkgndTotalLike_[iBkgnd] *= this->setSPlotNtupleBranchValues(&(pdfs), bkgndClass, iEvt); } } // the total likelihoods if (useSCF_) { Double_t scfFrac(0.0); if ( useSCFHist_ ) { scfFrac = recoSCFFracs_[iEvt]; } else { scfFrac = scfFrac_.unblindValue(); } this->setSPlotNtupleDoubleBranchValue("sigSCFFrac",scfFrac); sigTotalLike_ *= ( 1.0 - scfFrac ); if ( scfMap_ == 0 ) { scfTotalLike_ *= scfFrac; } this->setSPlotNtupleDoubleBranchValue("sigTMTotalLike",sigTotalLike_); this->setSPlotNtupleDoubleBranchValue("sigSCFTotalLike",scfTotalLike_); } else { this->setSPlotNtupleDoubleBranchValue("sigTotalLike",sigTotalLike_); } if (usingBkgnd_) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { TString name = this->bkgndClassName(iBkgnd); name += "TotalLike"; this->setSPlotNtupleDoubleBranchValue(name,bkgndTotalLike_[iBkgnd]); } } // fill the tree this->fillSPlotNtupleBranches(); } std::cout << "INFO in LauSimpleFitModel::storePerEvtLlhds : Finished storing per-event likelihood values." << std::endl; } void LauSimpleFitModel::embedSignal(const TString& fileName, const TString& treeName, Bool_t reuseEventsWithinEnsemble, Bool_t reuseEventsWithinExperiment, Bool_t useReweighting) { if (signalTree_) { std::cerr << "ERROR in LauSimpleFitModel::embedSignal : Already embedding signal from a file." << std::endl; return; } signalTree_ = new LauEmbeddedData(fileName,treeName,reuseEventsWithinExperiment); Bool_t dataOK = signalTree_->findBranches(); if (!dataOK) { delete signalTree_; signalTree_ = 0; std::cerr << "ERROR in LauSimpleFitModel::embedSignal : Problem creating data tree for embedding." << std::endl; return; } reuseSignal_ = reuseEventsWithinEnsemble; useReweighting_ = useReweighting; if (this->enableEmbedding() == kFALSE) { this->enableEmbedding(kTRUE); } } void LauSimpleFitModel::embedBkgnd(const TString& bkgndClass, const TString& fileName, const TString& treeName, Bool_t reuseEventsWithinEnsemble, Bool_t reuseEventsWithinExperiment) { if ( ! this->validBkgndClass( bkgndClass ) ) { std::cerr << "ERROR in LauSimpleFitModel::embedBkgnd : Invalid background class \"" << bkgndClass << "\"." << std::endl; std::cerr << " : Background class names must be provided in \"setBkgndClassNames\" before any other background-related actions can be performed." << std::endl; return; } UInt_t bkgndID = this->bkgndClassID( bkgndClass ); if (bkgndTree_[bkgndID]) { std::cerr << "ERROR in LauSimpleFitModel::embedBkgnd : Already embedding background from a file." << std::endl; return; } bkgndTree_[bkgndID] = new LauEmbeddedData(fileName,treeName,reuseEventsWithinExperiment); Bool_t dataOK = bkgndTree_[bkgndID]->findBranches(); if (!dataOK) { delete bkgndTree_[bkgndID]; bkgndTree_[bkgndID] = 0; std::cerr << "ERROR in LauSimpleFitModel::embedBkgnd : Problem creating data tree for embedding." << std::endl; return; } reuseBkgnd_[bkgndID] = reuseEventsWithinEnsemble; if (this->enableEmbedding() == kFALSE) { this->enableEmbedding(kTRUE); } } void LauSimpleFitModel::weightEvents( const TString& dataFileName, const TString& dataTreeName ) { // Routine to provide weights for events that are uniformly distributed // in the DP (or square DP) so as to reproduce the given DP model if ( kinematics_->squareDP() ) { std::cout << "INFO in LauSimpleFitModel::weightEvents : will create weights assuming events were generated flat in the square DP" << std::endl; } else { std::cout << "INFO in LauSimpleFitModel::weightEvents : will create weights assuming events were generated flat in phase space" << std::endl; } // This reads in the given dataFile and creates an input // fit data tree that stores them for all events and experiments. Bool_t dataOK = this->verifyFitData(dataFileName,dataTreeName); if (!dataOK) { std::cerr << "ERROR in LauSimpleFitModel::weightEvents : Problem caching the data." << std::endl; return; } LauFitDataTree* inputFitData = this->fitData(); if ( ! inputFitData->haveBranch( "m13Sq_MC" ) || ! inputFitData->haveBranch( "m23Sq_MC" ) ) { std::cerr << "WARNING in LauSimpleFitModel::weightEvents : Cannot find MC truth DP coordinate branches in supplied data, aborting." << std::endl; return; } // Create the ntuple to hold the DP weights TString weightsFileName( dataFileName ); Ssiz_t index = weightsFileName.Last('.'); weightsFileName.Insert( index, "_DPweights" ); LauGenNtuple * weightsTuple = new LauGenNtuple( weightsFileName, dataTreeName ); weightsTuple->addIntegerBranch("iExpt"); weightsTuple->addIntegerBranch("iEvtWithinExpt"); weightsTuple->addDoubleBranch("dpModelWeight"); UInt_t nExpmt = this->nExpt(); UInt_t firstExpmt = this->firstExpt(); for (UInt_t iExpmt = firstExpmt; iExpmt < (firstExpmt+nExpmt); ++iExpmt) { inputFitData->readExperimentData(iExpmt); UInt_t nEvents = inputFitData->nEvents(); if (nEvents < 1) { std::cerr << "WARNING in LauSimpleFitModel::weightEvents : Zero events in experiment " << iExpmt << ", skipping..." << std::endl; continue; } weightsTuple->setIntegerBranchValue( "iExpt", iExpmt ); // Calculate and store the weights for the events in this experiment for ( UInt_t iEvent(0); iEvent < nEvents; ++iEvent ) { weightsTuple->setIntegerBranchValue( "iEvtWithinExpt", iEvent ); const LauFitData& evtData = inputFitData->getData( iEvent ); Double_t m13Sq_MC = evtData.find("m13Sq_MC")->second; Double_t m23Sq_MC = evtData.find("m23Sq_MC")->second; Double_t dpModelWeight(0.0); if ( kinematics_->withinDPLimits( m13Sq_MC, m23Sq_MC ) ) { kinematics_->updateKinematics( m13Sq_MC, m23Sq_MC ); dpModelWeight = sigDPModel_->getEventWeight(); if ( kinematics_->squareDP() ) { dpModelWeight *= kinematics_->calcSqDPJacobian(); } dpModelWeight /= sigDPModel_->getDPNorm(); } weightsTuple->setDoubleBranchValue( "dpModelWeight", dpModelWeight ); weightsTuple->fillBranches(); } } weightsTuple->buildIndex( "iExpt", "iEvtWithinExpt" ); weightsTuple->addFriendTree(dataFileName, dataTreeName); weightsTuple->writeOutGenResults(); delete weightsTuple; } void LauSimpleFitModel::savePDFPlots(const TString& label) { savePDFPlotsWave(label, 0); savePDFPlotsWave(label, 1); savePDFPlotsWave(label, 2); std::cout << "LauCPFitModel::plot" << std::endl; // ((LauIsobarDynamics*)sigDPModel_)->plot(); //Double_t minm13 = sigDPModel_->getKinematics()->getm13Min(); Double_t minm13 = 0.0; Double_t maxm13 = sigDPModel_->getKinematics()->getm13Max(); //Double_t minm23 = sigDPModel_->getKinematics()->getm23Min(); Double_t minm23 = 0.0; Double_t maxm23 = sigDPModel_->getKinematics()->getm23Max(); Double_t mins13 = minm13*minm13; Double_t maxs13 = maxm13*maxm13; Double_t mins23 = minm23*minm23; Double_t maxs23 = maxm23*maxm23; Double_t s13, s23, chPdf; Int_t n13=200.00, n23=200.00; Double_t delta13, delta23; delta13 = (maxs13 - mins13)/n13; delta23 = (maxs23 - mins23)/n23; UInt_t nAmp = sigDPModel_->getnCohAmp(); for (UInt_t resID = 0; resID <= nAmp; ++resID) { TGraph2D *dt = new TGraph2D(); TString resName = "TotalAmp"; if (resID != nAmp){ TString tStrResID = Form("%d", resID); const LauIsobarDynamics* model = sigDPModel_; const LauAbsResonance* resonance = model->getResonance(resID); resName = resonance->getResonanceName(); std::cout << "resName = " << resName << std::endl; } resName.ReplaceAll("(", ""); resName.ReplaceAll(")", ""); resName.ReplaceAll("*", "Star"); TCanvas *c = new TCanvas("c"+resName+label,resName+" ("+label+")",0,0,600,400); dt->SetName(resName+label); dt->SetTitle(resName+" ("+label+")"); Int_t count=0; for (Int_t i=0; igetKinematics()->withinDPLimits2(s23, s13)) { //if (s13 > 4) continue; sigDPModel_->calcLikelihoodInfo(s13, s23); LauComplex chAmp = sigDPModel_->getEvtDPAmp(); if (resID != nAmp){ chAmp = sigDPModel_->getFullAmplitude(resID); } chPdf = chAmp.abs2(); //if ((z > 0.04)||(z < -0.03)) continue; //z = TMath::Log(z); if (sigDPModel_->getDaughters()->gotSymmetricalDP()){ Double_t sLow = s13; Double_t sHigh = s23; if (sLow>sHigh) { continue; //sLow = s23; //sHigh = s13; } //if (sLow > 3.5) continue; //if (i<10) std::cout << "SymmetricalDP" << std::endl; //if (z>0.02) z = 0.02; //if (z<-0.02) z = -0.02; dt->SetPoint(count,sHigh,sLow,chPdf); count++; } else { dt->SetPoint(count,s13,s23,chPdf); count++; } } } } gStyle->SetPalette(1); dt->GetXaxis()->SetTitle("m_{K#pi}(low)"); dt->GetYaxis()->SetTitle("m_{K#pi}(high)"); dt->Draw("SURF1"); dt->GetXaxis()->SetTitle("m_{K#pi}(low)"); dt->GetYaxis()->SetTitle("m_{K#pi}(high)"); c->SaveAs("plot_2D_"+resName + "_"+label+".C"); } } void LauSimpleFitModel::savePDFPlotsWave(const TString& label, const Int_t& spin) { std::cout << "label = "<< label << ", spin = "<< spin << std::endl; TString tStrResID = "S_Wave"; if (spin == 1) tStrResID = "P_Wave"; if (spin == 2) tStrResID = "D_Wave"; std::cout << "LauSimpleFitModel::savePDFPlotsWave: "<< tStrResID << std::endl; TCanvas *c = new TCanvas("c"+tStrResID+label,tStrResID+" ("+label+")",0,0,600,400); Double_t minm13 = 0.0; Double_t maxm13 = sigDPModel_->getKinematics()->getm13Max(); Double_t minm23 = 0.0; Double_t maxm23 = sigDPModel_->getKinematics()->getm23Max(); Double_t mins13 = minm13*minm13; Double_t maxs13 = maxm13*maxm13; Double_t mins23 = minm23*minm23; Double_t maxs23 = maxm23*maxm23; Double_t s13, s23, chPdf; TGraph2D *dt = new TGraph2D(); dt->SetName(tStrResID+label); dt->SetTitle(tStrResID+" ("+label+")"); Int_t n13=200.00, n23=200.00; Double_t delta13, delta23; delta13 = (maxs13 - mins13)/n13; delta23 = (maxs23 - mins23)/n23; UInt_t nAmp = sigDPModel_->getnCohAmp(); Int_t count=0; for (Int_t i=0; igetKinematics()->withinDPLimits2(s23, s13)) { //if (s13 > 4) continue; LauComplex chAmp(0,0); Bool_t noWaveRes = kTRUE; sigDPModel_->calcLikelihoodInfo(s13, s23); for (UInt_t resID = 0; resID < nAmp; ++resID) { const LauIsobarDynamics* model = sigDPModel_; const LauAbsResonance* resonance = model->getResonance(resID); Int_t spin_res = resonance->getSpin(); if (spin != spin_res) continue; noWaveRes = kFALSE; chAmp += sigDPModel_->getFullAmplitude(resID); } if (noWaveRes) return; chPdf = chAmp.abs2(); if (sigDPModel_->getDaughters()->gotSymmetricalDP()){ Double_t sLow = s13; Double_t sHigh = s23; if (sLow>sHigh) { continue; //sLow = s23; //sHigh = s13; } dt->SetPoint(count,sHigh,sLow,chPdf); count++; } else { dt->SetPoint(count,s13,s23,chPdf); count++; } } } } gStyle->SetPalette(1); dt->GetXaxis()->SetTitle("pipi"); dt->GetYaxis()->SetTitle("pipi"); dt->Draw("SURF1"); dt->GetXaxis()->SetTitle("pipi"); dt->GetYaxis()->SetTitle("pipi"); c->SaveAs("plot_2D_"+tStrResID+"_"+label+".C"); } diff --git a/src/LauSumPdf.cc b/src/LauSumPdf.cc index 4687d5f..0b93e83 100644 --- a/src/LauSumPdf.cc +++ b/src/LauSumPdf.cc @@ -1,211 +1,210 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauSumPdf.cc \brief File containing implementation of LauSumPdf class. */ #include #include #include "TMath.h" #include "TSystem.h" #include "LauConstants.hh" #include "LauParameter.hh" #include "LauSumPdf.hh" -ClassImp(LauSumPdf) LauSumPdf::LauSumPdf(LauAbsPdf* pdf1, LauAbsPdf* pdf2, LauParameter* frac) : LauAbsPdf(pdf1 ? pdf1->varNames() : std::vector(), std::vector(), pdf1 ? pdf1->getMinAbscissas() : LauFitData(), pdf1 ? pdf1->getMaxAbscissas() : LauFitData()), pdf1_(pdf1), pdf2_(pdf2), frac_(frac) { // Constructor for the sum PDF. // We are defining the sum as: // f x (PDF1/S(PDF1)) + (1-f) x (PDF2/S(PDF2)) // where f is the fraction, x is multiplication, PDFi is the i'th PDF, // and S(PDFi) is the integral of the i'th PDF. // // The last two arguments specify the range in which the PDF is defined, and the PDF // will be normalised w.r.t. these limits. // So the first thing we have to do is check the pointers are all valid. if (!frac || !pdf1 || !pdf2) { std::cerr << "ERROR in LauSumPdf constructor : one of the 3 pointers is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } // Next check that the abscissa ranges are the same for each PDF if (pdf1->getMinAbscissa() != pdf2->getMinAbscissa()) { std::cerr << "ERROR in LauSumPdf constructor : minimum abscissa values not the same for the two PDFs." << std::endl; gSystem->Exit(EXIT_FAILURE); } if (pdf1->getMaxAbscissa() != pdf2->getMaxAbscissa()) { std::cerr << "ERROR in LauSumPdf constructor : maximum abscissa values not the same for the two PDFs." << std::endl; gSystem->Exit(EXIT_FAILURE); } // Also check that both PDFs are expecting the same number of input variables if (pdf1->nInputVars() != pdf2->nInputVars()) { std::cerr << "ERROR in LauSumPdf constructor : number of input variables not the same for the two PDFs." << std::endl; gSystem->Exit(EXIT_FAILURE); } // Also check that both PDFs are expecting the same variable name if (pdf1->varNames() != pdf2->varNames()) { std::cerr << "ERROR in LauSumPdf constructor : variable name not the same for the two PDFs." << std::endl; gSystem->Exit(EXIT_FAILURE); } // Then we need to grab all the parameters and pass them to the base class. // This is so that when we are asked for them they can be put into the fit. // The number of parameters is the number in PDF1 + the number in PDF2 + 1 for the fraction. UInt_t nPar(pdf1->nParameters()+pdf2->nParameters()+1); std::vector params; params.reserve(nPar); std::vector& pdf1pars = pdf1->getParameters(); std::vector& pdf2pars = pdf2->getParameters(); params.push_back(frac); for (std::vector::iterator iter = pdf1pars.begin(); iter != pdf1pars.end(); ++iter) { params.push_back(*iter); } for (std::vector::iterator iter = pdf2pars.begin(); iter != pdf2pars.end(); ++iter) { params.push_back(*iter); } this->addParameters(params); // Now check that we can find the fraction parameter ok frac_ = this->findParameter("frac"); if (frac_ == 0) { std::cerr << "ERROR in LauSumPdf constructor : parameter \"frac\" not found." << std::endl; gSystem->Exit(EXIT_FAILURE); } // Cache the normalisation factor this->calcNorm(); } LauSumPdf::~LauSumPdf() { // Destructor } void LauSumPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Get the up to date parameter values Double_t frac = frac_->unblindValue(); // Evaluate the normalised PDF values pdf1_->calcLikelihoodInfo(abscissas); pdf2_->calcLikelihoodInfo(abscissas); Double_t result1 = pdf1_->getLikelihood(); Double_t result2 = pdf2_->getLikelihood(); // Add them together Double_t result = frac * result1 + (1.0-frac) * result2; this->setUnNormPDFVal(result); } void LauSumPdf::calcNorm() { // Nothing to do here, since it is already normalized this->setNorm(1.0); } void LauSumPdf::calcPDFHeight( const LauKinematics* kinematics ) { if ( this->heightUpToDate() && ! this->isDPDependent() ) { return; } // This method gives you the maximum possible height of the PDF. // It combines the maximum heights of the two individual PDFs. // So it would give the true maximum if the two individual maxima coincided. // It is guaranteed to always be >= the true maximum. // Update the heights of the individual PDFs pdf1_->calcPDFHeight( kinematics ); pdf2_->calcPDFHeight( kinematics ); // Get the up to date parameter values Double_t frac = frac_->unblindValue(); // Find the (un-normalised) individual PDF maxima Double_t height1 = pdf1_->getMaxHeight(); Double_t height2 = pdf2_->getMaxHeight(); // Get the individual PDF normalisation factors Double_t norm1 = pdf1_->getNorm(); Double_t norm2 = pdf2_->getNorm(); // Calculate the normalised individual PDF maxima height1 /= norm1; height2 /= norm2; // Combine these heights together Double_t height = frac * height1 + (1-frac) * height2; this->setMaxHeight(height); } // Override the base class methods for cacheInfo and calcLikelihoodInfo(UInt_t iEvt). // For both of these we delegate to the two constituent PDFs. void LauSumPdf::cacheInfo(const LauFitDataTree& inputData) { pdf1_->cacheInfo(inputData); pdf2_->cacheInfo(inputData); // determine whether we are caching our PDF value Bool_t doCaching ( this->nFixedParameters() == this->nParameters() ); this->cachePDF( doCaching ); // Set whether the height is up-to-date only if it is true for both of the sub-PDFs Bool_t hutd = pdf1_->heightUpToDate() && pdf2_->heightUpToDate(); this->heightUpToDate(hutd); } void LauSumPdf::calcLikelihoodInfo(UInt_t iEvt) { // Get the up to date parameter values Double_t frac = frac_->unblindValue(); // Evaluate the normalised PDF values pdf1_->calcLikelihoodInfo(iEvt); pdf2_->calcLikelihoodInfo(iEvt); Double_t result1 = pdf1_->getLikelihood(); Double_t result2 = pdf2_->getLikelihood(); // Add them together Double_t result = frac * result1 + (1.0-frac) * result2; this->setUnNormPDFVal(result); } diff --git a/src/LauVetoes.cc b/src/LauVetoes.cc index 6dc7af4..5c9aabf 100644 --- a/src/LauVetoes.cc +++ b/src/LauVetoes.cc @@ -1,215 +1,214 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauVetoes.cc \brief File containing implementation of LauVetoes class. */ #include #include "LauKinematics.hh" #include "LauVetoes.hh" -ClassImp(LauVetoes) LauVetoes::LauVetoes() : nVetoes_(0) { } LauVetoes::~LauVetoes() { } LauVetoes::LauVetoes(const LauVetoes& other) : nVetoes_(other.nVetoes_), vetoPair_(other.vetoPair_), vetoMinMass_(other.vetoMinMass_), vetoMaxMass_(other.vetoMaxMass_) { } LauVetoes& LauVetoes::operator=(const LauVetoes& other) { if ( &other != this ) { nVetoes_ = other.nVetoes_; vetoPair_ = other.vetoPair_; vetoMinMass_ = other.vetoMinMass_; vetoMaxMass_ = other.vetoMaxMass_; } return *this; } void LauVetoes::addMassVeto(const Int_t resPairAmpInt, const Double_t minMass, const Double_t maxMass) { const Double_t minMassSq = minMass*minMass; const Double_t maxMassSq = maxMass*maxMass; this->addMassSqVeto(resPairAmpInt, minMassSq, maxMassSq); } void LauVetoes::addMassSqVeto(const Int_t resPairAmpInt, const Double_t minMassSq, const Double_t maxMassSq) { // Routine to add a veto in the Dalitz plot. The function takes as input the // bachelor track number (1, 2 or 3) and the mass-squared range of the veto. if (resPairAmpInt == 1) { // The bachelor track is the first track std::cout << "INFO in LauVetoes::addMassSqVeto : Adding the veto for resPairAmpInt = 1, with " << minMassSq << " < m^2_23 < " << maxMassSq << std::endl; } else if (resPairAmpInt == 2) { // The bachelor track is the second track std::cout << "INFO in LauVetoes::addMassSqVeto : Adding the veto for resPairAmpInt = 2, with " << minMassSq << " < m^2_13 < " << maxMassSq << std::endl; } else if (resPairAmpInt == 3) { // The bachelor track is the third track std::cout << "INFO in LauVetoes::addMassSqVeto : Adding the veto for resPairAmpInt = 3, with " << minMassSq << " < m^2_12 < " << maxMassSq << std::endl; } else if (resPairAmpInt == 4) { // Special case for symmetric DPs - the veto will be applied on the minimum of m13Sq and m23Sq std::cout << "INFO in LauVetoes::addMassSqVeto : Adding the veto for resPairAmpInt = 4, with " << minMassSq << " < m^2_min < " << maxMassSq << std::endl; } else if (resPairAmpInt == 5) { // Special case for symmetric DPs - the veto will be applied on the maximum of m13Sq and m23Sq std::cout << "INFO in LauVetoes::addMassSqVeto : Adding the veto for resPairAmpInt = 5, with " << minMassSq << " < m^2_max < " << maxMassSq << std::endl; } else { std::cerr << "ERROR in LauVetoes::addMassSqVeto : Invalid resPairAmpInt. Please use 1, 2 or 3 to specify bachelor daughter track (or 4 or 5 to specify a veto on mMinSq or mMaxSq in a symmetric DP). Veto is not added." << std::endl; return; } // Set the veto limits vetoPair_.push_back(resPairAmpInt); vetoMinMass_.push_back(minMassSq); vetoMaxMass_.push_back(maxMassSq); // Keep track of how many vetoes we have ++nVetoes_; } Bool_t LauVetoes::passVeto(const LauKinematics* kinematics) const { // Routine to ask whether the given Dalitz plot point passes any specified vetoes. if (kinematics == 0) { std::cerr << "ERROR in LauVetoes::passVeto : LauKinematics object is null." << std::endl; return kFALSE; } const Double_t m12Sq = kinematics->getm12Sq(); const Double_t m23Sq = kinematics->getm23Sq(); const Double_t m13Sq = kinematics->getm13Sq(); const Bool_t symmetricDP = kinematics->gotSymmetricalDP(); const Bool_t fullySymmetricDP = kinematics->gotFullySymmetricDP(); return this->passVeto(m12Sq, m23Sq, m13Sq, symmetricDP, fullySymmetricDP); } Bool_t LauVetoes::passVeto(const Double_t m12Sq, const Double_t m23Sq, const Double_t m13Sq, const Bool_t symmetricDP, const Bool_t fullySymmetricDP) const { // Routine to ask whether the given Dalitz plot point passes any specified vetoes. // Loop over the number of possible vetoes for ( UInt_t i(0); i < nVetoes_; ++i) { if (vetoPair_[i] == 1) { // Veto m23 combination if (m23Sq > vetoMinMass_[i] && m23Sq < vetoMaxMass_[i]) { return kFALSE; } // If the DP is symmetric we need to test m13 combination as well if ( symmetricDP || fullySymmetricDP ) { if (m13Sq > vetoMinMass_[i] && m13Sq < vetoMaxMass_[i]) { return kFALSE; } } // If it's fully symmetric we need to check all 3 combinations if ( fullySymmetricDP ) { if (m12Sq > vetoMinMass_[i] && m12Sq < vetoMaxMass_[i]) { return kFALSE; } } } else if (vetoPair_[i] == 2) { // Veto m13 combination if (m13Sq > vetoMinMass_[i] && m13Sq < vetoMaxMass_[i]) { return kFALSE; } // If the DP is symmetric we need to test m23 combination as well if ( symmetricDP || fullySymmetricDP ) { if (m23Sq > vetoMinMass_[i] && m23Sq < vetoMaxMass_[i]) { return kFALSE; } } // If it's fully symmetric we need to check all 3 combinations if ( fullySymmetricDP ) { if (m12Sq > vetoMinMass_[i] && m12Sq < vetoMaxMass_[i]) { return kFALSE; } } } else if (vetoPair_[i] == 3) { // Veto m12 combination if (m12Sq > vetoMinMass_[i] && m12Sq < vetoMaxMass_[i]) { return kFALSE; } // If it's fully symmetric we need to check all 3 combinations if ( fullySymmetricDP ) { if (m13Sq > vetoMinMass_[i] && m13Sq < vetoMaxMass_[i]) { return kFALSE; } if (m23Sq > vetoMinMass_[i] && m23Sq < vetoMaxMass_[i]) { return kFALSE; } } } else if (vetoPair_[i] == 4) { if (!symmetricDP) { std::cerr << "WARNING in LauVetoes::passVeto : resPairAmpInt of 4 is only valid for symmetric DPs, will ignore this veto" << std::endl; continue; } // Veto mMin combination const Double_t mMinSq = TMath::Min( m13Sq, m23Sq ); if (mMinSq > vetoMinMass_[i] && mMinSq < vetoMaxMass_[i]) { return kFALSE; } } else if (vetoPair_[i] == 5) { if (!symmetricDP) { std::cerr << "WARNING in LauVetoes::passVeto : resPairAmpInt of 5 is only valid for symmetric DPs, will ignore this veto" << std::endl; continue; } // Veto mMax combination const Double_t mMaxSq = TMath::Max( m13Sq, m23Sq ); if (mMaxSq > vetoMinMass_[i] && mMaxSq < vetoMaxMass_[i]) { return kFALSE; } } } return kTRUE; } diff --git a/src/LauWeightedSumEffModel.cc b/src/LauWeightedSumEffModel.cc index 0fb5a28..99a6d21 100644 --- a/src/LauWeightedSumEffModel.cc +++ b/src/LauWeightedSumEffModel.cc @@ -1,123 +1,122 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauWeightedSumEffModel.cc \brief File containing implementation of LauWeightedSumEffModel class. */ #include #include #include "TSystem.h" #include "Lau2DHistDP.hh" #include "Lau2DSplineDP.hh" #include "LauDaughters.hh" #include "LauWeightedSumEffModel.hh" #include "LauKinematics.hh" #include "LauVetoes.hh" -ClassImp(LauWeightedSumEffModel) LauWeightedSumEffModel::LauWeightedSumEffModel(const LauDaughters* daughters) : daughters_( daughters ), effModel_( 0 ), fluctuateEffHisto_( kFALSE ), lowBinWarningIssued_( kFALSE ), highBinWarningIssued_( kFALSE ) { if ( daughters_ == 0 ) { std::cerr << "ERROR in LauWeightedSumEffModel Constructor : invalid pointer to daughters object supplied." << std::endl; gSystem->Exit(EXIT_FAILURE); } } void LauWeightedSumEffModel::addEffModel(const LauAbsEffModel* effModel, Double_t coeff) { const LauDaughters* otherDaughters = effModel->getDaughters(); if( otherDaughters->getTypeDaug1()!=daughters_->getTypeDaug1() || otherDaughters->getTypeDaug2()!=daughters_->getTypeDaug2() || otherDaughters->getTypeDaug3()!=daughters_->getTypeDaug3() || otherDaughters->getTypeParent()!=daughters_->getTypeParent() ) { std::cerr << "ERROR in LauWeightedSumEffModel::addEffModel : daughters of provided efficiency model do not match those expected." << std::endl; gSystem->Exit(EXIT_FAILURE); } effModel_.push_back(effModel); coeff_.push_back(coeff); if ( effModel->fluctuateEffHisto() ) { fluctuateEffHisto_ = kTRUE; } } Double_t LauWeightedSumEffModel::calcEfficiency( const LauKinematics* kinematics ) const { // Routine to calculate the efficiency for the given event/point in // the Dalitz plot. This routine uses the models set by the // addEffModel() function. Double_t eff(0.0); std::vector::const_iterator it = effModel_.begin(); std::vector::const_iterator end = effModel_.end(); std::vector::const_iterator coeffIt = coeff_.begin(); for( ; it!=end; ++it) { eff += (*coeffIt)*(*it)->calcEfficiency( kinematics ); ++coeffIt; } // Check that the efficiency is in the allowed range (0-1) // Out of range efficiencies could be caused by incorrect coefficients. if ( eff < 0.0 ) { if(!lowBinWarningIssued_) { std::cerr << "WARNING in LauWeightedSumEffModel::calcEfficiency : Efficiency " << eff << " is less than 0 - setting to 0. You may want to check your coefficients!" << std::endl << " : Further warnings will be suppressed." << std::endl; lowBinWarningIssued_=kTRUE; } eff = 0.0; } else if ( eff > 1.0 ) { if(!highBinWarningIssued_) { std::cerr << "WARNING in LauWeightedSumEffModel::calcEfficiency : Efficiency " << eff << " is greater than 1 - setting to 1. You may want to check your coefficients!" << std::endl << " : Further warnings will be suppressed." << std::endl; highBinWarningIssued_=kTRUE; } eff = 1.0; } return eff; } Bool_t LauWeightedSumEffModel::passVeto( const LauKinematics* kinematics ) const { std::vector::const_iterator it = effModel_.begin(); std::vector::const_iterator end = effModel_.end(); for( ; it!=end; ++it) { if(!(*it)->passVeto( kinematics )) return kFALSE; } return kTRUE; }