Page MenuHomeHEPForge

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/examples/Makefile b/examples/Makefile
index a15afa8..46d8eed 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -1,117 +1,116 @@
# --- External configuration ----------------------------------
# first check that ROOTSYS is defined
ifndef ROOTSYS
ROOTSYS := $(shell root-config --prefix)
ROOTBINDIR := $(shell root-config --bindir)
ifeq ($(ROOTSYS), )
$(error running of root-config failed or reported null value)
endif
else
ROOTBINDIR := $(ROOTSYS)/bin
endif
ROOTCONFIG := $(ROOTBINDIR)/root-config
ARCH := $(shell $(ROOTCONFIG) --arch)
PLATFORM := $(shell $(ROOTCONFIG) --platform)
INCLUDES =
WORKDIR = tmp
ifeq ($(findstring linux, $(ARCH)),linux)
# This set here should work for Linux.
CXX = g++
LD = g++
-CXXFLAGS = -g -O2 -Wall -Wextra -Wshadow -Woverloaded-virtual -fPIC
+CXXFLAGS = -g -O2 -Wall -Wextra -Wshadow -Woverloaded-virtual -Werror -fPIC
MFLAGS = -MM
LDFLAGS = -g
SOFLAGS = -shared
endif
ifeq ($(ARCH),macosx64)
# For Mac OS X you may need to put -m64 in CXXFLAGS and SOFLAGS.
CXX = g++
LD = g++
-CXXFLAGS = -g -O3 -Wall -Wextra -Wshadow -Woverloaded-virtual -fPIC -m64
+CXXFLAGS = -g -O3 -Wall -Wextra -Wshadow -Woverloaded-virtual -Werror -fPIC -m64
MFLAGS = -MM
LDFLAGS = -g
SOFLAGS = -m64 -dynamiclib -single_module -undefined dynamic_lookup
endif
# --- Internal configuration ----------------------------------
INCDIR=../inc
DEPDIR=$(WORKDIR)/dependencies
OBJDIR=$(WORKDIR)/objects
-SHLIBFILE=$(PWD)/$(WORKDIR)/libLauraUtils.so
+LAURALIBDIR=$(shell pwd | xargs dirname)/lib
+LAURALIB = $(LAURALIBDIR)/libLaura++.so
+UTILSLIB = $(PWD)/$(WORKDIR)/libLauraUtils.so
ROOTLIBS = $(shell root-config --libs)
-NLIBS = $(ROOTLIBS)
-NLIBS += -lEG
-NLIBS += -lMinuit
-NLIBS += -lTreePlayer
-NLIBS += ${PWD}/../lib/libLaura++.so
-LIBS = $(filter-out -lNew, $(NLIBS))
+ROOTLIBS += -lEG
+ROOTLIBS += -lMinuit
+ROOTLIBS += -lTreePlayer
INCLUDES += -I$(INCDIR) -I$(shell $(ROOTBINDIR)/root-config --incdir)
CXXFLAGS += $(INCLUDES)
default: bin
# List of all source files
CCLIST:=$(wildcard *.cc)
# List of all source files that contain main functions
BINCCLIST:=$(shell egrep -l "^[[:space:]]*int[[:space:]]*main\>" $(CCLIST))
# List of all source files to be compiled into the library
LIBCCLIST:=$(filter-out $(BINCCLIST), $(CCLIST))
# List of all object files to build
OLIST:=$(patsubst %.cc,%.o,$(addprefix $(OBJDIR)/,$(notdir $(CCLIST))))
# List of all object files to be combined into library
LIBOLIST:=$(patsubst %.cc,%.o,$(addprefix $(OBJDIR)/,$(notdir $(LIBCCLIST))))
# List of all dependency files to make
DLIST:=$(patsubst %.cc,%.d,$(addprefix $(DEPDIR)/,$(notdir $(CCLIST))))
# List of all binary files to make
BINLIST:=$(patsubst %.cc,%,$(notdir $(BINCCLIST)))
# Implicit rule making all dependency Makefiles included at the end of this makefile
$(DEPDIR)/%.d: %.cc
@echo "Making $@"
@mkdir -p $(DEPDIR)
@set -e; $(CXX) $(MFLAGS) $(CXXFLAGS) $< \
| sed 's#\($(notdir $*)\)\.o[ :]*#$(OBJDIR)/\1.o $@ : #g' > $@; \
[ -s $@ ] || rm -f $@
# Implicit rule to compile all sources
$(OBJDIR)/%.o : %.cc
@echo "Compiling $<"
@mkdir -p $(OBJDIR)
@$(CXX) $(CXXFLAGS) -c $< -o $@
# Rule to combine objects into a shared library
-$(SHLIBFILE): $(LIBOLIST)
- @echo "Making $(SHLIBFILE)"
- @rm -f $(SHLIBFILE)
- @$(CXX) $(LIBOLIST) $(SOFLAGS) -o $(SHLIBFILE)
+$(UTILSLIB): $(LIBOLIST)
+ @echo "Making $(UTILSLIB)"
+ @rm -f $(UTILSLIB)
+ @$(CXX) $(LIBOLIST) $(SOFLAGS) -o $(UTILSLIB)
# Rule to compile all binaries
-% : $(OBJDIR)/%.o $(SHLIBFILE)
+% : $(OBJDIR)/%.o $(UTILSLIB)
@echo "Linking $@"
- @$(CXX) $(LDFLAGS) $< -o $@ $(LIBS) $(SHLIBFILE)
+ @$(CXX) $(LDFLAGS) $< -o $@ $(LAURALIB) $(UTILSLIB) $(ROOTLIBS)
bin: $(BINLIST)
clean:
rm -f $(BINLIST)
- rm -f $(SHLIBFILE)
+ rm -f $(UTILSLIB)
rm -rf $(WORKDIR)
.PHONY : bin default clean
-include $(DLIST)
diff --git a/inc/LauAbsDPDynamics.hh b/inc/LauAbsDPDynamics.hh
index 8d0b8cd..81e3395 100644
--- a/inc/LauAbsDPDynamics.hh
+++ b/inc/LauAbsDPDynamics.hh
@@ -1,411 +1,397 @@
-// Copyright University of Warwick 2005 - 2013.
+// Copyright University of Warwick 2005 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauAbsDPDynamics.hh
\brief File containing declaration of LauAbsDPDynamics class.
*/
/*! \class LauAbsDPDynamics
\brief Class for defining the abstract interface for signal Dalitz plot dynamics.
*/
#ifndef LAU_ABS_DP_DYNAMICS
#define LAU_ABS_DP_DYNAMICS
#include <vector>
#include <map>
#include "TString.h"
#include "LauCacheData.hh"
#include "LauParameter.hh"
class LauAbsResonance;
class LauComplex;
class LauDaughters;
class LauEffModel;
class LauFitDataTree;
class LauKinematics;
-class LauResonanceMaker;
class LauAbsDPDynamics {
public:
//! The type used for containing multiple self cross feed fraction models for different categories (e.g. tagging categories)
typedef std::map<Int_t,LauEffModel*> LauTagCatScfFractionModelMap;
//! Constructor
/*!
\param [in] daughters the daughters of the decay
\param [in] effModel the model to describe the efficiency across the Dalitz plot
\param [in] scfFractionModel the model to describe the fraction of poorly constructed events (the self cross feed fraction) across the Dalitz plot
*/
LauAbsDPDynamics(LauDaughters* daughters, LauEffModel* effModel, LauEffModel* scfFractionModel = 0);
//! Constructor
/*!
\param [in] daughters the daughters of the decay
\param [in] effModel the model to describe efficiency across the Dalitz plot
\param [in] scfFractionModel the models to describe the fraction of poorly constructed events (the self cross feed fraction) across the Dalitz plot for various tagging categories
*/
LauAbsDPDynamics(LauDaughters* daughters, LauEffModel* effModel, const LauTagCatScfFractionModelMap& scfFractionModel);
//! Destructor
virtual ~LauAbsDPDynamics();
//! The possible statuses for toy MC generation
enum ToyMCStatus {
GenOK, /*!< Generation completed OK */
MaxIterError, /*!< Maximum allowed number of iterations completed without success (ASqMax is too high) */
ASqMaxError /*!< An amplitude squared value was returned that was larger than the maximum expected (ASqMax is too low) */
};
//! Add a resonance to the Dalitz plot
/*!
\param [in] resName the name of the resonant particle
\param [in] resPairAmpInt the index of the daughter not produced by the resonance (the bachelor)
\param [in] resType the type of the resonance. Allowed types are: flatte, relbw, dabba, kappa, sigma, lass-bw, lass-nr, lass, gs, nrmodel, bellesymnr and bellenr
+ \param [in] fixMass fix or release the mass to be fitted
+ \param [in] fixWidth fix or release the width to be fitted
\param [in] newMass set a custom mass for the resonance
\param [in] newWidth set a custom width for the resonance
\param [in] newSpin set a custom spin for the resonance
*/
- virtual void addResonance(const TString& resName, Int_t resPairAmpInt, const TString& resType,
+ virtual void addResonance(const TString& resName, Int_t resPairAmpInt, const TString& resType, Bool_t fixMass, Bool_t fixWidth,
Double_t newMass, Double_t newWidth, Int_t newSpin) = 0;
//! Initialise the Dalitz plot dynamics
/*!
\param [in] coeffs the complex coefficients for the resonances
*/
virtual void initialise(const std::vector<LauComplex>& coeffs) = 0;
+ //! Recalculate the normalisation
+ virtual void recalculateNormalisation() = 0;
+
//! Obtain the efficiency of the current event from the model
/*!
\return the efficiency
*/
virtual Double_t retrieveEfficiency();
//! Obtain the self cross feed fraction of the current event from the model
/*!
\param [in] tagCat the tagging category of the current event
\return the self cross feed fraction
*/
virtual Double_t retrieveScfFraction(Int_t tagCat);
//! Obtain data from a fit tree
/*!
\param [in] inputFitTree the tree
*/
virtual void fillDataTree(const LauFitDataTree& inputFitTree) = 0;
//! Load the data for a given event
/*!
\param [in] iEvt the number of the event
*/
virtual void setDataEventNo(UInt_t iEvt);
//! Check whether this model includes a named resonance
/*!
\param [in] resName the resonance
\return true if the resonance is present, false otherwise
*/
virtual Bool_t hasResonance(const TString& resName) const;
//! Retrieve the name of the charge conjugate of a named resonance
/*!
\param [in] resName the resonance
\return the name of the charge conjugate
*/
virtual TString getConjResName(const TString& resName) const;
//! Update the complex coefficients for the resonances
/*!
\param [in] coeffs the new set of coefficients
*/
virtual void updateCoeffs(const std::vector<LauComplex>& coeffs);
//! Generate a toy MC signal event
/*!
\return true if the event is successfully generated, false otherwise
*/
virtual Bool_t generate() = 0;
//! Check the status of the toy MC generation
/*!
\param [in] printErrorMessages whether error messages should be printed
\param [in] printInfoMessages whether info messages should be printed
\return the status of the toy MC generation
*/
virtual ToyMCStatus checkToyMC(Bool_t printErrorMessages = kTRUE, Bool_t printInfoMessages = kFALSE) = 0;
//! Calculate the likelihood (and all associated information) given values of the Dalitz plot coordinates
/*!
\param [in] m13Sq the invariant mass squared of the first and third daughters
\param [in] m23Sq the invariant mass squared of the second and third daughters
*/
virtual void calcLikelihoodInfo(Double_t m13Sq, Double_t m23Sq) = 0;
//! Calculate the likelihood (and all associated information) for the given event number
/*!
\param [in] iEvt the event number
*/
virtual void calcLikelihoodInfo(UInt_t iEvt) = 0;
//! Retrieve the likelihood for the current event
/*!
\return the likelihood for the current event
*/
virtual Double_t getEvtLikelihood() const = 0;
//! Retrieve the invariant mass squared of the first and third daughters in the current event
/*!
\return the invariant mass squared of the first and third daughters in the current event
*/
virtual Double_t getEvtm13Sq() const = 0;
//! Retrieve the invariant mass squared of the second and third daughters in the current event
/*!
\return the invariant mass squared of the second and third daughters in the current event
*/
virtual Double_t getEvtm23Sq() const = 0;
//! Retrieve the square Dalitz plot coordinate, m', for the current event
/*!
\return the square Dalitz plot coordinate, m', for the current event
*/
virtual Double_t getEvtmPrime() const = 0;
//! Retrieve the square Dalitz plot coordinate, theta', for the current event
/*!
\return the square Dalitz plot coordinate, theta', for the current event
*/
virtual Double_t getEvtthPrime() const = 0;
//! Retrieve the efficiency for the current event
/*!
\return the efficiency for the current event
*/
virtual Double_t getEvtEff() const = 0;
//! Retrieve the Jacobian, for the transformation into square DP coordinates, for the current event
/*!
\return the Jacobian for the current event
*/
virtual Double_t getEvtJacobian() const = 0; //Not sure whether this should be here or only in LauIsobarDynamics.
//! Retrieve the fraction of events that are poorly reconstructed (the self cross feed fraction) in the Dalitz plot bin of the current event
/*!
\return the self cross feed fraction for the current event
*/
virtual Double_t getEvtScfFraction() const = 0;
//! Retrieve the total amplitude of all amplitude components at the current point in the Dalitz plot
/*!
\return the total amplitude
*/
virtual const LauComplex& getEvtDPAmp() const = 0;
//! Retrieve the amplitude of the given amplitude component at the current point in the Dalitz plot
/*!
\param [in] resID the index of the amplitude component within the model
\return the amplitude of the given amplitude component
*/
virtual LauComplex getDynamicAmp(Int_t resID) const = 0;
//! Calculate the fit fractions, mean efficiency and total DP rate
/*!
\param [in] init whether the calculated values should be used to generate toys and as the initial values when fitting
*/
virtual void calcExtraInfo(Bool_t init = kFALSE) = 0;
// Use this method to select events in the DP for embedded-reweighting.
//! Calculates whether an event with the current kinematics should be accepted in order to produce a distribution of events that matches the model e.g. when reweighting embedded data
/*!
\return true if the event has been accepted, false otherwise
*/
virtual Bool_t gotReweightedEvent() = 0;
//! Calculate the acceptance rate, for events with the current kinematics, when generating events according to the model
/*!
\return the weight for the current kinematics
*/
virtual Double_t getEventWeight() = 0;
//! Retrieve the mean efficiency across the Dalitz plot
/*!
\return the mean efficiency across the Dalitz plot
*/
inline LauParameter getMeanEff() const {return meanDPEff_;}
//! Retrieve the overall Dalitz plot rate
/*!
\return the overall Dalitz plot rate
*/
inline LauParameter getDPRate() const {return DPRate_;}
//! Retrieve the fit fractions for the amplitude components
/*!
\return the fit fractions
*/
inline const LauParArray& getFitFractions() const {return fitFrac_;}
- //! Retrieve the number of defined resonances in the resonance maker
- /*!
- \return the number of defined resonances
- */
- inline UInt_t getnDefinedResonances() const {return nResDefMax_;}
-
//! Retrieve the number of amplitude components
/*!
\return the number of amplitude components
*/
inline UInt_t getnAmp() const {return nAmp_;}
//! Retrieve the normalisation factor for the log-likelihood function
/*!
\return the normalisation factor
*/
inline Double_t getDPNorm() const {return DPNorm_;}
//! Retrieve the number of cached events
/*!
\return the number of cached events
*/
inline UInt_t nData() const {return data_.size();}
//! Retrieve the cached data
/*!
\return the cached data
*/
inline const std::vector<LauCacheData*>& getCacheData() const {return data_;}
//! Retrieve the daughters
/*!
\return the daughters
*/
inline LauDaughters* getDaughters() {return daughters_;}
- //! Retrieve the resonance maker object
- /*!
- \return the resonance maker
- */
- inline LauResonanceMaker* getResonanceMaker() {return resonanceMaker_;}
-
//! Retrieve the Dalitz plot kinematics
/*!
\return the Dalitz plot kinematics
*/
inline LauKinematics* getKinematics() {return kinematics_;}
//! Retrieve the model for the efficiency across the Dalitz plot
/*!
\return the efficiency model
*/
inline LauEffModel* getEffModel() {return effModel_;}
//! Retrieve the model for the fraction of events that are poorly reconstructed (the self cross feed fraction) in each Dalitz plot bin for the first (or only) tagging category
/*!
\return the self cross feed fraction model
*/
inline LauEffModel* getScfFractionModel() {return scfFractionModel_[0];}
//! Retrieve the model for the fraction of events that are poorly reconstructed (the self cross feed fraction) in each Dalitz plot bin for all tagging categories
/*!
\return the self cross feed fraction models
*/
inline std::map <Int_t,LauEffModel*> getScfFractionModels() {return scfFractionModel_;}
//! Check whether a self cross feed fraction model is being used
/*!
\return true if a self cross feed fraction model is being used, false otherwise
*/
inline Bool_t usingScfModel() { return ! scfFractionModel_.empty(); }
//! Retrieve any extra parameters/quantities (e.g. K-matrix total fit fractions)
/*!
\return any extra parameters
*/
std::vector<LauParameter> getExtraParameters() {return extraParameters_;}
protected:
//! Calculate the normalisation factor for the log-likelihood function
/*!
\return the normalisation factor
*/
virtual Double_t calcSigDPNorm() = 0;
//! Retrieve the named resonance
/*!
\param [in] name the name of the resonance to retrieve
\return the named resonance
*/
virtual LauAbsResonance* findResonance(const TString& name) = 0;
//! Retrieve the named resonance
/*!
\param [in] name the name of the resonance to retrieve
\return the named resonance
*/
virtual const LauAbsResonance* findResonance(const TString& name) const = 0;
//! The daughters of the decay
LauDaughters* daughters_;
- //! Object to create resonances
- LauResonanceMaker* resonanceMaker_;
-
//! The kinematics of the decay
LauKinematics* kinematics_;
//! The efficiency model across the Dalitz plot
LauEffModel* effModel_;
//! The self cross feed fraction models across the Dalitz plot
/*!
These model the fraction of signal events that are poorly reconstructed (the self cross feed fraction) as a function of Dalitz plot position.
If the self cross feed is depependent on the tagging category then seperate models can be defined.
*/
LauTagCatScfFractionModelMap scfFractionModel_;
//! The number of amplitude components
UInt_t nAmp_;
- //! The number of resonances defined in the resonance maker
- UInt_t nResDefMax_;
-
//! The complex coefficients for the amplitude components
std::vector<LauComplex> Amp_;
//! The normalisation factor for the log-likelihood function
Double_t DPNorm_;
//! The fit fractions for the amplitude components
LauParArray fitFrac_;
//! The overall Dalitz plot rate
LauParameter DPRate_;
//! The mean efficiency across the Dalitz plot
LauParameter meanDPEff_;
//! The cached data for all events
std::vector<LauCacheData*> data_;
//! The cached data for the current event
LauCacheData* currentEvent_;
//! any extra parameters/quantities (e.g. K-matrix total fit fractions)
std::vector<LauParameter> extraParameters_;
private:
ClassDef(LauAbsDPDynamics,0)
};
#endif
diff --git a/inc/LauAbsFitModel.hh b/inc/LauAbsFitModel.hh
index 367c48c..c6ea055 100644
--- a/inc/LauAbsFitModel.hh
+++ b/inc/LauAbsFitModel.hh
@@ -1,817 +1,821 @@
-// Copyright University of Warwick 2004 - 2013.
+// Copyright University of Warwick 2004 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauAbsFitModel.hh
\brief File containing declaration of LauAbsFitModel class.
*/
/*! \class LauAbsFitModel
\brief Abstract interface to the fitting and toy MC model
Abstract interface to the fitting and toy MC model
Any class inheriting from this must implement the following functions:
- cacheInputFitVars()
- checkInitFitParams()
- finaliseFitResults()
- fixdSpeciesNames()
- freeSpeciesNames()
- genExpt()
- getEventSum()
- getTotEvtLikelihood()
- initialise()
- initialiseDPModels()
- propagateParUpdates()
+ - recalculateNormalisation()
- scfDPSmear()
- setNBkgndEvents()
- setNSigEvents()
- setupBkgndVectors()
- setupGenNtupleBranches()
- setupSPlotNtupleBranches()
- splitSignal()
- storePerEvtLlhds()
- twodimPDFs()
- updateCoeffs()
- variableNames()
- weightEvents()
- writeOutTable()
*/
#ifndef LAU_ABS_FIT_MODEL
#define LAU_ABS_FIT_MODEL
#include "TMatrixD.h"
#include "TString.h"
#include "TStopwatch.h"
#include "TVectorDfwd.h"
#include <vector>
#include <iosfwd>
#include "LauFitObject.hh"
// LauSPlot included to get LauSPlot::NameSet typedef
#include "LauSPlot.hh"
class TMessage;
class TMonitor;
class TSocket;
class TTree;
class LauAbsCoeffSet;
class LauAbsPdf;
class LauComplex;
class LauFitDataTree;
class LauFitNtuple;
class LauGenNtuple;
class LauParameter;
class LauAbsFitModel : public LauFitObject {
public:
//! Constructor
LauAbsFitModel();
//! Destructor
virtual ~LauAbsFitModel();
//! Is the Dalitz plot term in the likelihood
Bool_t useDP() const { return usingDP_; }
//! Switch on/off the Dalitz plot term in the Likelihood (allows fits to other quantities, e.g. B mass)
/*!
\param [in] usingDP the boolean flag
*/
void useDP(Bool_t usingDP) { usingDP_ = usingDP; }
//! Return the flag to store the status of using an sFit or not
Bool_t doSFit() const { return doSFit_; }
//! Do an sFit (use sWeights to isolate signal decays rather than using background histograms)
/*!
\param [in] sWeightBranchName name of the branch of the tree containing the sWeights
\param [in] scaleFactor scaling factor to get the uncertainties correct
*/
void doSFit( const TString& sWeightBranchName, Double_t scaleFactor = 1.0 );
//! Determine whether an extended maximum likelihood fit it being performed
Bool_t doEMLFit() const {return emlFit_;}
//! Choice to perform an extended maximum likelihood fit
/*!
\param [in] emlFit boolean specifying whether or not to perform the EML
*/
void doEMLFit(Bool_t emlFit) {emlFit_ = emlFit;}
//! Determine whether the two-stage fit is enabled
virtual Bool_t twoStageFit() const {return twoStageFit_;}
//! Turn on or off the two stage fit
/*!
The two-stage fit allows certain parameters to be fixed
in one stage and floated in another stage of the fit.
Can be used, for example, in a CP fit where the
CP-parameters are fixed to zero in the first stage
(while the CP-average parameters are determined), then
floated in the second.
\param [in] doTwoStageFit boolean specifying whether or not the two-stage fit should be enabled
*/
virtual void twoStageFit(Bool_t doTwoStageFit) {twoStageFit_ = doTwoStageFit;}
//! Determine whether calculation of asymmetric errors is enabled
Bool_t useAsymmFitErrors() const {return useAsymmFitErrors_;}
//! Turn on or off the computation of asymmetric errors (e.g. MINOS routine in Minuit)
/*!
\param [in] useAsymmErrors boolean specifying whether or not the computation of asymmetric errors is enabled
*/
void useAsymmFitErrors(Bool_t useAsymmErrors) {useAsymmFitErrors_ = useAsymmErrors;}
//! Determine whether Poisson smearing is enabled for the toy MC generation
Bool_t doPoissonSmearing() const {return poissonSmear_;}
//! Turn Poisson smearing (for the toy MC generation) on or off
/*!
\param [in] poissonSmear boolean specifying whether or not to do Poisson smearing
*/
void doPoissonSmearing(Bool_t poissonSmear) {poissonSmear_ = poissonSmear;}
//! Determine whether embedding of events is enabled in the generation
Bool_t enableEmbedding() const {return enableEmbedding_;}
//! Turn on or off embedding of events in the generation
/*!
\param [in] enable boolean specifying whether to embed events
*/
void enableEmbedding(Bool_t enable) {enableEmbedding_ = enable;}
//! Mark that the fit is calculating asymmetric errors
/*!
This is called by the fitter interface to mark when
entering and exiting the asymmetric error calculation
\param [in] inAsymErrCalc boolean marking that the fit is calculating the asymmetric errors
*/
virtual void withinAsymErrorCalc(Bool_t inAsymErrCalc) {withinAsymErrorCalc_ = inAsymErrCalc;}
//! Determine whether writing out of the latex table is enabled
Bool_t writeLatexTable() const {return writeLatexTable_;}
//! Turn on or off the writing out of the latex table
/*!
\param [in] writeTable boolean specifying whether or not the latex table should be written out
*/
void writeLatexTable(Bool_t writeTable) {writeLatexTable_ = writeTable;}
//! Set up the sPlot ntuple
/*!
\param [in] fileName the sPlot file name
\param [in] treeName the sPlot tree name
\param [in] storeDPEfficiency whether or not to store the efficiency information too
\param [in] verbosity define the level of output
*/
void writeSPlotData(const TString& fileName, const TString& treeName, Bool_t storeDPEfficiency, const TString& verbosity = "q");
//! Determine whether the sPlot data is to be written out
Bool_t writeSPlotData() const {return writeSPlotData_;}
//! Determine whether the efficiency information should be stored in the sPlot ntuple
Bool_t storeDPEff() const {return storeDPEff_;}
//! Determine whether the initial values of the fit parameters, in particular the isobar coefficient parameters, are to be randomised
Bool_t useRandomInitFitPars() const {return randomFit_;}
//! Randomise the initial values of the fit parameters, in particular the isobar coefficient parameters
void useRandomInitFitPars(Bool_t boolean) {randomFit_ = boolean;}
//! Set the number of experiments and the first experiment
/*!
\param [in] nExperiments the number of experiments
\param [in] firstExperiment the number of the first experiment
*/
void setNExpts(UInt_t nExperiments, UInt_t firstExperiment = 0) {
nExpt_ = nExperiments;
firstExpt_ = firstExperiment;
}
//! Obtain the total number of events in the current experiment
UInt_t eventsPerExpt() const {return evtsPerExpt_;}
//! Obtain the number of experiments
UInt_t nExpt() const {return nExpt_;}
//! Obtain the number of the first experiment
UInt_t firstExpt() const {return firstExpt_;}
//! Obtain the number of the current experiment
UInt_t iExpt() const {return iExpt_;}
//! Setup the background class names
/*!
\param [in] names a vector of all the background names
*/
virtual void setBkgndClassNames( const std::vector<TString>& names );
//! Returns the number of background classes
inline UInt_t nBkgndClasses() const {return bkgndClassNames_.size();}
//! Set the number of signal events
/*!
\param [in] nSigEvents contains the signal yield and option to fix it
*/
virtual void setNSigEvents(LauParameter* nSigEvents) = 0;
//! Set the number of background events
/*!
The name of the parameter must be that of the corresponding background category (so that it can be correctly assigned)
\param [in] nBkgndEvents contains the name, yield and option to fix the yield of the background
*/
virtual void setNBkgndEvents(LauParameter* nBkgndEvents) = 0;
//! Set the DP amplitude coefficients
/*!
\param [in] coeffSet the set of coefficients
*/
virtual void setAmpCoeffSet(LauAbsCoeffSet* coeffSet) = 0;
//! Specify that a toy MC sample should be created for a successful fit to an experiment
/*!
Generation uses the fitted parameters so that the user can compare the fit to the data
\param [in] toyMCScale the scale factor to get the number of events to generate
\param [in] mcFileName the file name where the toy sample will be stored
\param [in] tableFileName name of the output tex file
\param [in] poissonSmearing turn smearing on or off
*/
void compareFitData(UInt_t toyMCScale = 10, const TString& mcFileName = "fitToyMC.root",
const TString& tableFileName = "fitToyMCTable.tex", Bool_t poissonSmearing = kTRUE);
//! Reweighting - allows e.g. MC events to be weighted by the DP model
/*!
\param [in] dataFileName the name of the data file
\param [in] dataTreeName the name of the tree containing the data
*/
virtual void weightEvents( const TString& dataFileName, const TString& dataTreeName ) = 0;
//! Start the toy generation / fitting
/*!
\param [in] applicationCode specifies what to do, perform a fit ("fit") or generate toy MC ("gen")
\param [in] dataFileName the name of the input data file
\param [in] dataTreeName the name of the tree containing the data
\param [in] histFileName the file name for the output histograms
\param [in] tableFileName the file name for the latex output file
*/
void run(const TString& applicationCode, const TString& dataFileName, const TString& dataTreeName,
const TString& histFileName, const TString& tableFileName = "");
//! Start the slave process for simultaneous fitting
/*!
\param [in] dataFileName the name of the input data file
\param [in] dataTreeName the name of the tree containing the data
\param [in] histFileName the file name for the output histograms
\param [in] tableFileName the file name for the latex output file
\param [in] addressMaster the hostname of the machine running the master process
\param [in] portMaster the port number on which the master process is listening
*/
void runSlave(const TString& dataFileName, const TString& dataTreeName,
const TString& histFileName, const TString& tableFileName = "",
const TString& addressMaster = "localhost", const UInt_t portMaster = 9090);
//! This function sets the parameter values from Minuit
/*!
This function has to be public since it is called from the global FCN.
It should not be called otherwise!
\param [in] par an array storing the various parameter values
\param [in] npar the number of free parameters
*/
virtual void setParsFromMinuit(Double_t* par, Int_t npar);
//! Calculates the total negative log-likelihood
/*!
This function has to be public since it is called from the global FCN.
It should not be called otherwise!
*/
Double_t getTotNegLogLikelihood();
protected:
// Some typedefs
//! List of Pdfs
typedef std::vector<LauAbsPdf*> LauPdfList;
//! List of parameter pointers
typedef std::vector<LauParameter*> LauParameterPList;
//! List of parameters
typedef std::vector<LauParameter> LauParameterList;
//! A type to store background classes
typedef std::map<UInt_t,TString> LauBkgndClassMap;
//! Initialise socket connections for the slaves
void initSockets();
//! Clear the vectors containing fit parameters
void clearFitParVectors();
//! Clear the vectors containing extra ntuple variables
void clearExtraVarVectors();
//! Generate toy MC
/*!
\param [in] dataFileName the name of the file where the generated events are stored
\param [in] dataTreeName the name of the tree used to store the variables
\param [in] histFileName the name of the histogram output file (currently not used)
\param [in] tableFileNameBase the name the latex output file
*/
virtual void generate(const TString& dataFileName, const TString& dataTreeName, const TString& histFileName, const TString& tableFileNameBase);
//! The method that actually generates the toy MC events for the given experiment
/*!
\return the success/failure flag of the generation procedure
*/
virtual Bool_t genExpt() = 0;
//! Perform the total fit
/*!
\param [in] dataFileName the name of the data file
\param [in] dataTreeName the name of the tree containing the data
\param [in] histFileName the name of the histogram output file
\param [in] tableFileNameBase the name the of latex output file
*/
void fit(const TString& dataFileName, const TString& dataTreeName, const TString& histFileName, const TString& tableFileNameBase);
//! Slaves required when performing a simultaneous fit
/*!
\param [in] dataFileName the name of the data file
\param [in] dataTreeName the name of the tree containing the data
\param [in] histFileName the name of the histogram output file
\param [in] tableFileNameBase the name the of latex output file
*/
void fitSlave(const TString& dataFileName, const TString& dataTreeName, const TString& histFileName, const TString& tableFileNameBase);
//! Routine to perform the actual fit for a given experiment
void fitExpt();
//! Routine to perform the minimisation
/*!
\return the success/failure flag of the fit
*/
Bool_t runMinimisation();
//! Create a toy MC sample from the fitted parameters
/*!
\param [in] mcFileName the file name where the toy sample will be stored
\param [in] tableFileName name of the output tex file
*/
void createFitToyMC(const TString& mcFileName, const TString& tableFileName);
//! Store variables from the input file into the internal data storage
/*!
\param [in] dataFileName the name of the input file
\param [in] dataTreeName the name of the input tree
*/
Bool_t cacheFitData(const TString& dataFileName, const TString& dataTreeName);
//! Cache the input data values to calculate the likelihood during the fit
virtual void cacheInputFitVars() = 0;
//! Cache the value of the sWeights to be used in the sFit
virtual void cacheInputSWeights();
//! 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
*/
virtual void initialise() = 0;
+ //! Recalculate normalisation the signal DP model(s)
+ virtual void recalculateNormalisation() = 0;
+
//! Initialise the DP models
virtual void initialiseDPModels() = 0;
/*!
For each amp in the fit this function takes its
particular parameters and from them calculates the
single complex number that is its coefficient.
The vector of these coeffs can then be passed to the
signal dynamics.
*/
virtual void updateCoeffs() = 0;
//! This function (specific to each model) calculates anything that depends on the fit parameter values
virtual void propagateParUpdates() = 0;
//! Calculate the sum of the log-likelihood over the specified events
/*!
\param [in] iStart the event number of the first event to be considered
\param [in] iEnd the event number of the final event to be considered
*/
Double_t getLogLikelihood( UInt_t iStart, UInt_t iEnd );
//! Calculate the penalty terms to the log likelihood from Gaussian constraints
Double_t getLogLikelihoodPenalty();
//! Calculates the likelihood for a given event
/*!
\param [in] iEvt the event number
*/
virtual Double_t getTotEvtLikelihood(UInt_t iEvt) = 0;
//! Returns the sum of the expected events over all hypotheses; used in the EML fit scenario
virtual Double_t getEventSum() const = 0;
//! Prints the values of all the fit variables for the specified event - useful for diagnostics
/*!
\param [in] iEvt the event number
*/
virtual void printEventInfo(UInt_t iEvt) const;
//! Same as printEventInfo, but printing out the values of the variables in the fit
virtual void printVarsInfo() const;
//! Update initial fit parameters if required
virtual void checkInitFitParams() = 0;
//! Write the results of the fit into the ntuple
/*!
\param [in] tableFileName the structure containing the results of the fit
*/
virtual void finaliseFitResults(const TString& tableFileName) = 0;
//! Write the latex table
/*!
\param [in] outputFile the name of the output file
*/
virtual void writeOutTable(const TString& outputFile) = 0;
//! Store the per-event likelihood values
virtual void storePerEvtLlhds() = 0;
//! Write out any fit results
virtual void writeOutAllFitResults();
//! Calculate the sPlot data
virtual void calculateSPlotData();
//! Make sure all parameters hold their genValue as the current value
void setGenValues();
//! Method to set up the storage for background-related quantities called by setBkgndClassNames
virtual void setupBkgndVectors() = 0;
//! Check if the given background class is in the list
/*!
\param [in] className the name of the class to check
\return true or false
*/
Bool_t validBkgndClass( const TString& className ) const;
//! The number assigned to a background class
/*!
\param [in] className the name of the class to check
\return the background class ID number
*/
UInt_t bkgndClassID( const TString& className ) const;
//! Get the name of a background class from the number
/*!
\param [in] classID the ID number of the background class
\return the class name
*/
const TString& bkgndClassName( UInt_t classID ) const;
//! Set the number of events in the current experiment
void eventsPerExpt(UInt_t nEvents) {evtsPerExpt_ = nEvents;}
//! Setup the generation ntuple branches
virtual void setupGenNtupleBranches() = 0;
//! Add a branch to the gen tree for storing an integer
/*!
\param [in] name the name of the branch
*/
virtual void addGenNtupleIntegerBranch(const TString& name);
//! Add a branch to the gen tree for storing a double
/*!
\param [in] name the name of the branch
*/
virtual void addGenNtupleDoubleBranch(const TString& name);
//! Set the value of an integer branch in the gen tree
/*!
\param [in] name the name of the branch
\param [in] value the value to be stored
*/
virtual void setGenNtupleIntegerBranchValue(const TString& name, Int_t value);
//! Set the value of a double branch in the gen tree
/*!
\param [in] name the name of the branch
\param [in] value the value to be stored
*/
virtual void setGenNtupleDoubleBranchValue(const TString& name, Double_t value);
//! Get the value of an integer branch in the gen tree
/*!
\param [in] name the name of the branch
\return the value of the parameter
*/
virtual Int_t getGenNtupleIntegerBranchValue(const TString& name) const;
//! Get the value of a double branch in the gen tree
/*!
\param [in] name the name of the branch
\return the value of the parameter
*/
virtual Double_t getGenNtupleDoubleBranchValue(const TString& name) const;
//! Fill the gen tuple branches
virtual void fillGenNtupleBranches();
//! Setup the branches of the sPlot tuple
virtual void setupSPlotNtupleBranches() = 0;
//! Add a branch to the sPlot tree for storing an integer
/*!
\param [in] name the name of the branch
*/
virtual void addSPlotNtupleIntegerBranch(const TString& name);
//! Add a branch to the sPlot tree for storing a double
/*!
\param [in] name the name of the branch
*/
virtual void addSPlotNtupleDoubleBranch(const TString& name);
//! Set the value of an integer branch in the sPlot tree
/*!
\param [in] name the name of the branch
\param [in] value the value to be stored
*/
virtual void setSPlotNtupleIntegerBranchValue(const TString& name, Int_t value);
//! Set the value of a double branch in the sPlot tree
/*!
\param [in] name the name of the branch
\param [in] value the value to be stored
*/
virtual void setSPlotNtupleDoubleBranchValue(const TString& name, Double_t value);
//! Fill the sPlot tuple
virtual void fillSPlotNtupleBranches();
//! Returns the names of all variables in the fit
virtual LauSPlot::NameSet variableNames() const = 0;
//! Returns the names and yields of species that are free in the fit
virtual LauSPlot::NumbMap freeSpeciesNames() const = 0;
//! Returns the names and yields of species that are fixed in the fit
virtual LauSPlot::NumbMap fixdSpeciesNames() const = 0;
//! Returns the species and variables for all 2D PDFs in the fit
virtual LauSPlot::TwoDMap twodimPDFs() const = 0;
//! Check if the signal is split into well-reconstructed and mis-reconstructed types
virtual Bool_t splitSignal() const = 0;
//! Check if the mis-reconstructed signal is to be smeared in the DP
virtual Bool_t scfDPSmear() const = 0;
//! Add parameters of the PDFs in the list to the list of all fit parameters
/*!
\param [in] pdfList a list of Pdfs
\return the number of parameters added
*/
UInt_t addFitParameters(LauPdfList& pdfList);
//! Add parameters to the list of Gaussian constrained parameters
void addConParameters();
//! Print the fit parameters for all PDFs in the list
/*!
\param [in] pdfList a list of Pdfs
\param [in] fout the output stream to write to
*/
void printFitParameters(const LauPdfList& pdfList, std::ostream& fout) const;
//! Update the fit parameters for all PDFs in the list
/*!
\param [in] pdfList a list of Pdfs
*/
void updateFitParameters(LauPdfList& pdfList);
//! Have all PDFs in the list cache the data
/*!
\param [in] pdfList the list of pdfs
\param [in] theData the data from the fit
*/
void cacheInfo(LauPdfList& pdfList, const LauFitDataTree& theData);
//! Calculate the product of the per-event likelihoods of the PDFs in the list
/*!
\param [in] pdfList the list of pdfs
\param [in] iEvt the event number
*/
Double_t prodPdfValue(LauPdfList& pdfList, UInt_t iEvt);
//! Do any of the PDFs have a dependence on the DP?
/*!
\return the flag to indicated if there is a DP dependence
*/
Bool_t pdfsDependOnDP() const {return pdfsDependOnDP_;}
//! Do any of the PDFs have a dependence on the DP?
/*!
\param [in] dependOnDP the flag to indicated if there is a DP dependence
*/
void pdfsDependOnDP(Bool_t dependOnDP) { pdfsDependOnDP_ = dependOnDP; }
//! Access the fit variables
const LauParameterPList& fitPars() const {return fitVars_;}
LauParameterPList& fitPars() {return fitVars_;}
//! Access the extra variables
const LauParameterList& extraPars() const {return extraVars_;}
LauParameterList& extraPars() {return extraVars_;}
//! Access the Gaussian constrained variables
const LauParameterPList& conPars() const {return conVars_;}
LauParameterPList& conPars() {return conVars_;}
//! Access the fit ntuple
const LauFitNtuple* fitNtuple() const {return fitNtuple_;}
LauFitNtuple* fitNtuple() {return fitNtuple_;}
//! Access the gen ntuple
const LauGenNtuple* genNtuple() const {return genNtuple_;}
LauGenNtuple* genNtuple() {return genNtuple_;}
//! Access the sPlot ntuple
const LauGenNtuple* sPlotNtuple() const {return sPlotNtuple_;}
LauGenNtuple* sPlotNtuple() {return sPlotNtuple_;}
//! Access the data store
const LauFitDataTree* fitData() const {return inputFitData_;}
LauFitDataTree* fitData() {return inputFitData_;}
//! Access the current NLL value
Double_t nll() const {return NLL_;}
//! Access the fit status information
Int_t fitStatus() const {return fitStatus_;}
//! Access the fit covariance matrix
const TMatrixD& covarianceMatrix() const {return covMatrix_;}
private:
// Various control booleans
//! Option to perform a two stage fit
Bool_t twoStageFit_;
//! Option to use asymmetric errors
Bool_t useAsymmFitErrors_;
//! Option to make toy from 1st successful experiment
Bool_t compareFitData_;
//! Option to output a Latex format table
Bool_t writeLatexTable_;
//! Option to write sPlot data
Bool_t writeSPlotData_;
//! Option to store DP efficiencies in the sPlot ntuple
Bool_t storeDPEff_;
//! Option to randomise the initial values of the fit parameters
Bool_t randomFit_;
//! Option to perform an extended ML fit
Bool_t emlFit_;
//! Option to perform Poisson smearing
Bool_t poissonSmear_;
//! Option to enable embedding
Bool_t enableEmbedding_;
//! Option to include the DP as part of the fit
Bool_t usingDP_;
//! Option to state if pdfs depend on DP position
Bool_t pdfsDependOnDP_;
// Info on number of experiments and number of events
//! The number of the first experiment to consider
UInt_t firstExpt_;
//! The number of experiments to consider
UInt_t nExpt_;
//! The number of events per experiment
UInt_t evtsPerExpt_;
//! The number of the current experiment
UInt_t iExpt_;
//! Internal vectors of fit parameters
LauParameterPList fitVars_;
//! Extra variables that aren't in the fit but are stored in the ntuple
LauParameterList extraVars_;
//! Internal vectors of Gaussian parameters
LauParameterPList conVars_;
// Input data and output ntuple
//! The input data
LauFitDataTree* inputFitData_;
//! The fit ntuple
LauFitNtuple* fitNtuple_;
//! The generated ntuple
LauGenNtuple* genNtuple_;
//! The sPlot ntuple
LauGenNtuple* sPlotNtuple_;
// Fit bookeeping variables
//! The status of the fit
Int_t fitStatus_;
//! The negative log-likelihood
Double_t NLL_;
//! The fit covariance matrix
TMatrixD covMatrix_;
//! The number of good fits
UInt_t numberOKFits_;
//! The number of bad fits
UInt_t numberBadFits_;
//! The number of fit parameters
UInt_t nParams_;
//! The number of free fit parameters
UInt_t nFreeParams_;
//! The worst LL value found so far
Double_t worstLogLike_;
//! Flag to indicate if the asymmetric error calculation (e.g. MINOS) is currently running
Bool_t withinAsymErrorCalc_;
// Background class names
//! The background class names
LauBkgndClassMap bkgndClassNames_;
//! An empty string
const TString nullString_;
// sFit related variables
//! Option to perfom the sFit
Bool_t doSFit_;
//! The name of the sWeight branch
TString sWeightBranchName_;
//! The vector of sWeights
std::vector<Double_t> sWeights_;
//! The sWeight scaling factor
Double_t sWeightScaleFactor_;
// Fit timers
//! The fit timer
TStopwatch timer_;
//! The total fit timer
TStopwatch cumulTimer_;
// Comparison toy MC related variables
//! The output file name for Toy MC
TString fitToyMCFileName_;
//! The output table name for Toy MC
TString fitToyMCTableName_;
//! The scaling factor (toy vs data statistics)
UInt_t fitToyMCScale_;
//! Option to perform Poisson smearing
Bool_t fitToyMCPoissonSmear_;
// sPlot related variables
//! The name of the sPlot file
TString sPlotFileName_;
//! The name of the sPlot tree
TString sPlotTreeName_;
//! Control the verbosity of the sFit
TString sPlotVerbosity_;
// Parallel fitting variables
//! A socket to enable parallel setup
TSocket* sMaster_;
//! Message from master to the slaves
TMessage* messageFromMaster_;
//! Slave id number
UInt_t slaveId_;
//! The total number of slaves
UInt_t nSlaves_;
//! Parameter values array (for reading from the master)
Double_t* parValues_;
ClassDef(LauAbsFitModel,0) // Abstract interface to fit/toyMC model
};
#endif
diff --git a/inc/LauAbsResonance.hh b/inc/LauAbsResonance.hh
index 42c2ff1..59bae47 100644
--- a/inc/LauAbsResonance.hh
+++ b/inc/LauAbsResonance.hh
@@ -1,274 +1,310 @@
-// Copyright University of Warwick 2004 - 2013.
+// Copyright University of Warwick 2004 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauAbsResonance.hh
\brief File containing declaration of LauAbsResonance class.
*/
/*! \class LauAbsResonance
\brief Abstract class for defining type for resonance amplitude models (Breit-Wigner, Flatte etc.)
Abstract Class for defining the type for all classes used to model
resonances in the Dalitz plot, such as Breit-Wigner functions.
In addition, some common functionality is implemented, including data such
as the mass and width of the desired state.
*/
#ifndef LAU_ABS_RESONANCE
#define LAU_ABS_RESONANCE
#include "TString.h"
#include "LauComplex.hh"
+#include "LauParameter.hh"
class LauDaughters;
class LauKinematics;
class LauAbsResonance {
public:
//! Define the allowed resonance types
enum LauResonanceModel {
BW, /*!< simple Breit-Wigner */
RelBW, /*!< relativistic Breit-Wigner */
GS, /*!< a modified Breit-Wigner from Gounaris-Sakurai */
Flatte, /*!< Flatte or coupled-channel Breit-Wigner */
Sigma, /*!< special shape for the sigma or f_0(600) */
Kappa, /*!< special shape for the kappa, a low-mass Kpi scalar */
Dabba, /*!< special shape for the dabba, a low-mass Dpi scalar */
LASS, /*!< the LASS amplitude to describe the Kpi S-wave */
LASS_BW, /*!< the resonant part of the LASS amplitude */
LASS_NR, /*!< the nonresonant part of the LASS amplitude */
KMatrix, /*!< S-wave description using K-matrix and P-vector */
FlatNR, /*!< a uniform nonresonant amplitude */
NRModel, /*!< a theoretical model nonresonant amplitude */
BelleNR, /*!< an empirical exponential nonresonant amplitude */
PolNR /*!< an empirical polynomial nonresonant amplitude */
};
//! Define the allowed types of barrier factors
enum BarrierType {
BWBarrier, /*!< Blatt-Weisskopf barrier factor (for use when momentum terms not used in angular term) */
BWPrimeBarrier, /*!< Blatt-Weisskopf barrier factor (for use when momentum terms are used in angular term) - the default */
ExpBarrier /*!< expoential barrier factor (mostly used for virtual contributions) */
};
//! Constructor
/*!
\param [in] resName the name of the resonance
\param [in] resMass the mass of the resonance
\param [in] resWidth the width of the resonance
\param [in] resSpin the spin of the resonance
\param [in] resCharge the charge of the resonance
\param [in] resPairAmpInt the number of the daughter not produced by the resonance
\param [in] daughters the daughter particles
*/
- LauAbsResonance(const TString& resName, Double_t resMass, Double_t resWidth,
+ LauAbsResonance(const TString& resName, LauParameter* resMass, LauParameter* resWidth,
Int_t resSpin, Int_t resCharge, Int_t resPairAmpInt,
const LauDaughters* daughters);
//! Destructor
virtual ~LauAbsResonance();
//! Initialise the model
virtual void initialise() = 0;
//! Calculate the complex amplitude
/*!
\param [in] kinematics the kinematic variables of the current event
\return the complex amplitude
*/
virtual LauComplex amplitude(const LauKinematics* kinematics);
//! Get the resonance model type
/*!
\return the resonance model type
*/
virtual LauResonanceModel getResonanceModel() const = 0;
//! Get the name of the resonance
/*!
\return the resonance name
*/
const TString& getResonanceName() const {return resName_;}
//! Get the integer to identify which DP axis the resonance belongs to
/*!
\return the DP axis identification number, the ID of the bachelor
*/
Int_t getPairInt() const {return resPairAmpInt_;}
//! Get the spin of the resonance
/*!
\return the resonance spin
*/
Int_t getSpin() const {return resSpin_;}
//! Get the charge of the resonance
/*!
\return the resonance charge
*/
Int_t getCharge() const {return resCharge_;}
//! Get the mass of the resonance
/*!
\return the resonance mass
*/
- Double_t getMass() const {return resMass_;}
+ Double_t getMass() const {return (resMass_!=0) ? resMass_->value() : -1.0;}
//! Get the width of the resonance
/*!
\return the resonance width
*/
- Double_t getWidth() const {return resWidth_;}
+ Double_t getWidth() const {return (resWidth_!=0) ? resWidth_->value() : -1.0;}
+
+ //! Retrieve the resonance parameters, e.g. so that they can be loaded into a fit
+ /*!
+ \return parameters of the resonance
+ */
+ const std::vector<LauParameter*>& getParameters() const {return resParameters_;}
//! Get the helicity flip flag
/*!
\return the flip helicity flag
*/
Bool_t flipHelicity() const {return flipHelicity_;}
//! Set the helicity flip flag
/*!
\param [in] boolean the helicity flip status
*/
void flipHelicity(Bool_t boolean) {flipHelicity_ = boolean;}
//! Get the ignore momenta flag
/*!
\return the ignore momenta flag
*/
Bool_t ignoreMomenta() const {return ignoreMomenta_;}
//! Set the ignore p_ and q_ flag
/*!
\param [in] boolean the ignore momenta status
*/
void ignoreMomenta(Bool_t boolean) {ignoreMomenta_ = boolean;}
//! Allow the mass, width and spin of the resonance to be changed
/*!
\param [in] newMass new value of the resonance mass
\param [in] newWidth new value of the resonance width
\param [in] newSpin new value of the resonance spin
*/
void changeResonance(Double_t newMass, Double_t newWidth, Int_t newSpin);
//! Set the updated parameters from changeResonance
/*!
\param [in] value the updated parameter value
\param [in] name the updated parameter name
*/
virtual void setResonanceParameter(Double_t value, const TString& name);
+ //! Fix or release the resonance mass
+ /*!
+ \param [in] parFixed new status of mass
+ */
+ void fixMass(Bool_t parFixed) { if (resMass_!=0) { resMass_->fixed(parFixed); } }
+
+ //! Fix or release the resonance width
+ /*!
+ \param [in] parFixed new status of width
+ */
+ void fixWidth(Bool_t parFixed) { if (resWidth_!=0) { resWidth_->fixed(parFixed); } }
+
+ //! Get the status of resonance mass (fixed or released)
+ /*!
+ \return the status of resonance mass (fixed or released)
+ */
+ Bool_t fixMass() const { return (resMass_!=0) ? resMass_->fixed() : kTRUE; }
+
+ //! Get the status of resonance width (fixed or released)
+ /*!
+ \return the status of resonance width (fixed or released)
+ */
+ Bool_t fixWidth() const { return (resWidth_!=0) ? resWidth_->fixed() : kTRUE; }
+
protected:
//! Get the name of the parent particle
TString getNameParent() const;
//! Get the name of the first daughter of the resonance
TString getNameDaug1() const;
//! Get the name of the second daughter of the resonance
TString getNameDaug2() const;
//! Get the name of the daughter that does not originate form the resonance
TString getNameBachelor() const;
//! Get the parent particle mass
Double_t getMassParent() const;
//! Get the mass of daughter 1
Double_t getMassDaug1() const;
//! Get the mass of daughter 2
Double_t getMassDaug2() const;
//! Get the mass of the bachelor daughter
Double_t getMassBachelor() const;
//! Get the Charge of the parent particle
Int_t getChargeParent() const;
//! Get the charge of daughter 1
Int_t getChargeDaug1() const;
//! Get the charge of daughter 2
Int_t getChargeDaug2() const;
//! Get the charge of the bachelor daughter
Int_t getChargeBachelor() const;
//! Get the current value of the daughter momentum in the resonance rest frame
Double_t getQ() const {return q_;}
//! Get the current value of the bachelor momentum in the resonance rest frame
Double_t getP() const {return p_;}
//! Get the current value of the bachelor momentum in the parent rest frame
Double_t getPstar() const {return pstar_;}
//! Access the daughters object
const LauDaughters* getDaughters() const {return daughters_;}
//! Complex resonant amplitude
/*!
\param [in] mass appropriate invariant mass for the resonance
\param [in] spinTerm Zemach spin term
*/
virtual LauComplex resAmp(Double_t mass, Double_t spinTerm) = 0;
private:
//! Information on the particles
const LauDaughters* daughters_;
//! Parent name
TString nameParent_;
//! Daughter 1 name
TString nameDaug1_;
//! Daughter 2 name
TString nameDaug2_;
//! Bachelor name
TString nameBachelor_;
//! Parent charge
Int_t chargeParent_;
//! Daughter 1 charge
Int_t chargeDaug1_;
//! Daughter 2 charge
Int_t chargeDaug2_;
//! Bachelor charge
Int_t chargeBachelor_;
//! Parent mass
Double_t massParent_;
//! Daughter 1 mass
Double_t massDaug1_;
//! Daughter 2 mass
Double_t massDaug2_;
// Bachelor mass
Double_t massBachelor_;
//! Resonance name
TString resName_;
+
//! Resonance mass
- Double_t resMass_;
+ LauParameter* resMass_;
//! Resonance width
- Double_t resWidth_;
+ LauParameter* resWidth_;
+
+ //! All parameters of the resonance
+ std::vector<LauParameter*> resParameters_;
+
//! Resonance spin
Int_t resSpin_;
//! Resonance charge
Int_t resCharge_;
//! DP axis identifier
Int_t resPairAmpInt_;
//! Boolean to flip helicity
Bool_t flipHelicity_;
- //! Boolean to ignore q_ and p_ in spinTerm
- Bool_t ignoreMomenta_;
+ //! Boolean to ignore q_ and p_ in spinTerm
+ Bool_t ignoreMomenta_;
//! Daughter momentum in resonance rest frame
Double_t q_;
//! Bachelor momentum in resonance rest frame
Double_t p_;
//! Bachelor momentum in parent rest frame
Double_t pstar_;
ClassDef(LauAbsResonance,0) // Abstract resonance class
};
#endif
diff --git a/inc/LauBelleNR.hh b/inc/LauBelleNR.hh
index e74e8ed..d9909e3 100644
--- a/inc/LauBelleNR.hh
+++ b/inc/LauBelleNR.hh
@@ -1,89 +1,89 @@
-// Copyright University of Warwick 2004 - 2013.
+// Copyright University of Warwick 2004 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauBelleNR.hh
\brief File containing declaration of LauBelleNR class.
*/
/*! \class LauBelleNR
\brief Class for defining the Belle nonresonant model.
Defines the nonresonant model from the Belle collaboration.
arXiv:hep-ex/0412066
*/
#ifndef LAU_BELLE_NR
#define LAU_BELLE_NR
#include "TString.h"
#include "LauComplex.hh"
#include "LauAbsResonance.hh"
class LauKinematics;
class LauBelleNR : public LauAbsResonance {
public:
//! Constructor
/*!
\param [in] resName the name of the resonance
\param [in] resMass the mass of the resonance
\param [in] resWidth the width of the resonance
\param [in] resSpin the spin of the resonance
\param [in] resCharge the charge of the resonance
\param [in] resPairAmpInt the number of the daughter not produced by the resonance
\param [in] daughters the daughter particles
*/
- LauBelleNR(const TString& resName, Double_t resMass, Double_t resWidth,
+ LauBelleNR(const TString& resName, LauParameter* resMass, LauParameter* resWidth,
Int_t resSpin, Int_t resCharge, Int_t resPairAmpInt,
const LauDaughters* daughters);
//! Destructor
virtual ~LauBelleNR();
//! Initialise the model
virtual void initialise();
//! Get the resonance model type
/*!
\return the resonance model type
*/
virtual LauAbsResonance::LauResonanceModel getResonanceModel() const {return LauAbsResonance::BelleNR;}
//! Set the parameter alpha, the effective range
/*!
\param [in] alpha the new effective range parameter value
*/
virtual void setAlpha(Double_t alpha) {alpha_ = alpha;}
//! Get the effective range parameter
/*!
\return the effective range parameter
*/
virtual Double_t getAlpha() const {return alpha_;}
protected:
//! Complex resonant amplitude
/*!
\param [in] mass appropriate invariant mass for the resonance
\param [in] spinTerm Zemach spin term
*/
virtual LauComplex resAmp(Double_t mass, Double_t spinTerm);
private:
//! The range parameter
Double_t alpha_;
ClassDef(LauBelleNR,0) // Belle Non-resonant model
};
#endif
diff --git a/inc/LauBelleSymNR.hh b/inc/LauBelleSymNR.hh
index cc8902b..abf9dd9 100644
--- a/inc/LauBelleSymNR.hh
+++ b/inc/LauBelleSymNR.hh
@@ -1,107 +1,107 @@
-// Copyright University of Warwick 2004 - 2013.
+// Copyright University of Warwick 2004 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauBelleSymNR.hh
\brief File containing declaration of LauBelleSymNR class.
*/
/*! \class LauBelleSymNR
\brief Class for defining the symmetric Belle Non Resonant model
Defines the Non Resonant model from the Belle collaboration for the case
of a symmetrical DP
*/
#ifndef LAU_BELLE_SYM_NR
#define LAU_BELLE_SYM_NR
#include "TString.h"
#include "LauComplex.hh"
#include "LauAbsResonance.hh"
class LauKinematics;
class LauBelleSymNR : public LauAbsResonance {
public:
//! Constructor
/*!
\param [in] resName the name of the resonance
\param [in] resMass the mass of the resonance
\param [in] resWidth the width of the resonance
\param [in] resSpin the spin of the resonance
\param [in] resCharge the charge of the resonance
\param [in] resPairAmpInt the number of the daughter not produced by the resonance
\param [in] daughters the daughter particles
*/
- LauBelleSymNR(const TString& resName, Double_t resMass, Double_t resWidth,
+ LauBelleSymNR(const TString& resName, LauParameter* resMass, LauParameter* resWidth,
Int_t resSpin, Int_t resCharge, Int_t resPairAmpInt,
const LauDaughters* daughters);
//! Destructor
virtual ~LauBelleSymNR();
//! Dummy initialisation
virtual void initialise() {return;}
//! Initialise
/*!
\param [in] symmetricalDP flags whether the DP is symmetrical or not
\param [in] alpha effective range parameter
\param [in] shape name of model choice
*/
void initialise(Bool_t symmetricalDP, Double_t alpha, const TString& shape);
//! Get the complex dynamical amplitude
/*!
\param [in] kinematics the kinematic variables of the current event
\return the complex amplitude
*/
virtual LauComplex amplitude(const LauKinematics* kinematics);
//! Get the resonance model type
/*!
\return the resonance model type
*/
virtual LauAbsResonance::LauResonanceModel getResonanceModel() const {return LauAbsResonance::BelleNR;}
//! Set the parameter alpha, the effective range
/*!
\param [in] alpha the new effective range parameter
*/
virtual void setAlpha(Double_t alpha) {alpha_ = alpha;}
//! Get the effective range parameter
/*!
\return the effective range parameter
*/
virtual Double_t getAlpha() {return alpha_;}
protected:
//! This is not called, amplitude is used directly instead
virtual LauComplex resAmp(Double_t mass, Double_t spinTerm);
private:
//! Define the range parameter
Double_t alpha_;
//! Tracks if initialise has been called
Bool_t initialised_;
//! Int to set the correct model type
Int_t shapeNo_;
ClassDef(LauBelleSymNR,0) // Belle Non-resonant model
};
#endif
diff --git a/inc/LauBreitWignerRes.hh b/inc/LauBreitWignerRes.hh
index 16de889..d30b1ae 100644
--- a/inc/LauBreitWignerRes.hh
+++ b/inc/LauBreitWignerRes.hh
@@ -1,73 +1,73 @@
-// Copyright University of Warwick 2004 - 2013.
+// Copyright University of Warwick 2004 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauBreitWignerRes.hh
\brief File containing declaration of LauBreitWignerRes class.
*/
/*! \class LauBreitWignerRes
\brief Class for defining the simple Breit-Wigner resonance model
Class for defining the simple Breit-Wigner resonance model.
This is a non-relativistic Breit-Wigner, with no mass-dependent width or form factors.
*/
#ifndef LAU_BREIT_WIGNER_RES
#define LAU_BREIT_WIGNER_RES
#include "TString.h"
#include "LauComplex.hh"
#include "LauAbsResonance.hh"
class LauBreitWignerRes : public LauAbsResonance {
public:
//! Constructor
/*!
\param [in] resName the name of the resonance
\param [in] resMass the mass of the resonance
\param [in] resWidth the width of the resonance
\param [in] resSpin the spin of the resonance
\param [in] resCharge the charge of the resonance
\param [in] resPairAmpInt the number of the daughter not produced by the resonance
\param [in] daughters the daughter particles
*/
- LauBreitWignerRes(TString resName, Double_t resMass, Double_t resWidth,
+ LauBreitWignerRes(TString resName, LauParameter* resMass, LauParameter* resWidth,
Int_t resSpin, Int_t resCharge, Int_t resPairAmpInt,
const LauDaughters* daughters);
//! Destructor
virtual ~LauBreitWignerRes();
//! Initialise the model
virtual void initialise();
//! Get the resonance model type
/*!
\return the resonance model type
*/
virtual LauAbsResonance::LauResonanceModel getResonanceModel() const {return LauAbsResonance::BW;}
protected:
//! Complex resonant amplitude
/*!
\param [in] mass appropriate invariant mass for the resonance
\param [in] spinTerm Zemach spin term
*/
virtual LauComplex resAmp(Double_t mass, Double_t spinTerm);
private:
ClassDef(LauBreitWignerRes,0) // Breit-Wigner resonance model
};
#endif
diff --git a/inc/LauCPFitModel.hh b/inc/LauCPFitModel.hh
index 17497b3..cc617bd 100644
--- a/inc/LauCPFitModel.hh
+++ b/inc/LauCPFitModel.hh
@@ -1,637 +1,640 @@
-// Copyright University of Warwick 2004 - 2013.
+// Copyright University of Warwick 2004 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauCPFitModel.hh
\brief File containing declaration of LauCPFitModel class.
*/
/*! \class LauCPFitModel
\brief Class for defining a CP fit model.
LauCPFitModel is a class that allows the user to define a three-body Dalitz
plot according to the isobar model, i.e. defining a set of resonances that
have complex amplitudes that can interfere with each other.
It extends the LauSimpleFitModel in that it allows simultaneous fitting of
two parent flavours simultaneously. By default, it assumes perfect tagging
of those flavours but it can also be used in an untagged scenario.
*/
#ifndef LAU_CP_FIT_MODEL
#define LAU_CP_FIT_MODEL
#include <vector>
#include "TString.h"
#include "LauAbsFitModel.hh"
#include "LauParameter.hh"
class TH2;
class LauAbsBkgndDPModel;
class LauAbsCoeffSet;
class LauAbsDPDynamics;
class LauAbsPdf;
class LauEffModel;
class LauEmbeddedData;
class LauKinematics;
class LauScfMap;
class LauCPFitModel : public LauAbsFitModel {
public:
//! Constructor
/*!
\param [in] negModel DP model for the B- sample
\param [in] posModel DP model for the B+ sample
\param [in] tagged is the analysis tagged or untagged?
\param [in] tagVarName store the event charge
*/
LauCPFitModel(LauAbsDPDynamics* negModel, LauAbsDPDynamics* posModel, Bool_t tagged = kTRUE, const TString& tagVarName = "charge");
//! Destructor
virtual ~LauCPFitModel();
//! Set the signal event yield
/*!
\param [in] nSigEvents contains the signal yield and option to fix it
*/
virtual void setNSigEvents(LauParameter* nSigEvents);
//! Set the signal event yield if there is an asymmetry
/*!
\param [in] nSigEvents contains the signal yield and option to fix it
\param [in] sigAsym contains the signal asymmetry fraction and option to fix it
\param [in] forceAsym the option to force there to be an asymmetry
*/
virtual void setNSigEvents(LauParameter* nSigEvents, LauParameter* sigAsym, Bool_t forceAsym = kFALSE);
//! Set the background event yield(s)
/*!
The name of the parameter must be that of the corresponding background category (so that it can be correctly assigned)
\param [in] nBkgndEvents contains the name, yield and option to fix the yield of the background
*/
virtual void setNBkgndEvents(LauParameter* nBkgndEvents);
//! Set the background event yield(s)
/*!
The names of the parameters must be that of the corresponding background category (so that they can be correctly assigned)
\param [in] nBkgndEvents contains the name, yield and option to fix the yield of the background
\param [in] bkgndAsym contains the background asymmetry fraction and option to fix it
*/
virtual void setNBkgndEvents(LauParameter* nBkgndEvents, LauParameter* bkgndAsym);
//! Set the background DP models
/*!
\param [in] bkgndClass the name of the background class
\param [in] negModel the DP model of the B- background
\param [in] posModel the DP model of the B+ background
*/
void setBkgndDPModels(const TString& bkgndClass, LauAbsBkgndDPModel* negModel, LauAbsBkgndDPModel* posModel);
//! Split the signal component into well-reconstructed and mis-reconstructed parts
/*!
The nomenclature used here is TM (truth-matched) and SCF (self cross feed)
In this option, the SCF fraction is DP-dependent
Can also optionally provide a smearing matrix to smear the SCF DP PDF
\param [in] dpHisto the DP histogram of the SCF fraction value
\param [in] upperHalf whether this histogram is only in the upper half of a symmetric DP
\param [in] scfMap the (optional) smearing matrix
*/
void splitSignalComponent( const TH2* dpHisto, Bool_t upperHalf = kFALSE, LauScfMap* scfMap = 0 );
//! Split the signal component into well reconstructed and mis-reconstructed parts
/*!
The nomenclature used here is TM (truth-matched) and SCF (self cross feed)
In this option, the SCF fraction is a single global number
\param [in] scfFrac the SCF fraction value
\param [in] fixed whether the SCF fraction is fixed or floated in the fit
*/
void splitSignalComponent( Double_t scfFrac, Bool_t fixed );
//! Determine whether we are splitting the signal into TM and SCF parts
Bool_t useSCF() const { return useSCF_; }
//! Determine whether the SCF fraction is DP-dependent
Bool_t useSCFHist() const { return useSCFHist_; }
//! Determine if we are smearing the SCF DP PDF
Bool_t smearSCFDP() const { return (scfMap_ != 0); }
// Set the DeltaE and mES models, i.e. give us the PDFs
//! Set the signal PDFs
/*!
\param [in] negPdf the PDF to be added to the B- signal model
\param [in] posPdf the PDF to be added to the B+ signal model
*/
void setSignalPdfs(LauAbsPdf* negPdf, LauAbsPdf* posPdf);
//! Set the SCF PDF for a given variable
/*!
\param [in] negPdf the PDF to be added to the B- signal model
\param [in] posPdf the PDF to be added to the B+ signal model
*/
void setSCFPdfs(LauAbsPdf* negPdf, LauAbsPdf* posPdf);
//! Set the background PDFs
/*!
\param [in] bkgndClass the name of the background class
\param [in] negPdf the PDF to be added to the B- background model
\param [in] posPdf the PDF to be added to the B+ background model
*/
void setBkgndPdfs(const TString& bkgndClass, LauAbsPdf* negPdf, LauAbsPdf* posPdf);
//! Embed full simulation events for the B- signal, rather than generating toy from the PDFs
/*!
\param [in] fileName the name of the file containing SP events
\param [in] treeName the name of the tree
\param [in] reuseEventsWithinEnsemble
\param [in] reuseEventsWithinExperiment
\param [in] useReweighting
*/
void embedNegSignal(const TString& fileName, const TString& treeName,
Bool_t reuseEventsWithinEnsemble, Bool_t reuseEventsWithinExperiment = kFALSE,
Bool_t useReweighting = kFALSE);
//! Embed full simulation events for the given background class, rather than generating toy from the PDFs
/*!
\param [in] bgClass the name of the background class
\param [in] fileName the name of the file containing SP events
\param [in] treeName the name of the tree
\param [in] reuseEventsWithinEnsemble
\param [in] reuseEventsWithinExperiment
*/
void embedNegBkgnd(const TString& bgClass, const TString& fileName, const TString& treeName,
Bool_t reuseEventsWithinEnsemble, Bool_t reuseEventsWithinExperiment = kFALSE);
//! Embed full simulation events for the B+ signal, rather than generating toy from the PDFs
/*!
\param [in] fileName the name of the file containing SP events
\param [in] treeName the name of the tree
\param [in] reuseEventsWithinEnsemble
\param [in] reuseEventsWithinExperiment
\param [in] useReweighting
*/
void embedPosSignal(const TString& fileName, const TString& treeName,
Bool_t reuseEventsWithinEnsemble, Bool_t reuseEventsWithinExperiment = kFALSE,
Bool_t useReweighting = kFALSE);
//! Embed full simulation events for the given background class, rather than generating toy from the PDFs
/*!
\param [in] bgClass the name of the background class
\param [in] fileName the name of the file containing SP events
\param [in] treeName the name of the tree
\param [in] reuseEventsWithinEnsemble
\param [in] reuseEventsWithinExperiment
*/
void embedPosBkgnd(const TString& bgClass, const TString& fileName, const TString& treeName,
Bool_t reuseEventsWithinEnsemble, Bool_t reuseEventsWithinExperiment = kFALSE);
//! Set the DP amplitude coefficients
/*!
\param [in] coeffSet the set of coefficients
*/
virtual void setAmpCoeffSet(LauAbsCoeffSet* coeffSet);
//! Weight events based on the DP model
/*!
\param [in] dataFileName the name of the data file
\param [in] dataTreeName the name of the data tree
*/
virtual void weightEvents( const TString& dataFileName, const TString& dataTreeName );
protected:
//! Define a map to be used to store a category name and numbers
typedef std::map< std::pair<TString,Int_t>, std::pair<Int_t,Double_t> > LauGenInfo;
//! Typedef for a vector of background DP models
typedef std::vector<LauAbsBkgndDPModel*> LauBkgndDPModelList;
//! Typedef for a vector of background PDFs
typedef std::vector<LauPdfList> LauBkgndPdfsList;
//! Typedef for a vector of background yields
typedef std::vector<LauParameter*> LauBkgndYieldList;
//! Typedef for a vector of embedded data objects
typedef std::vector<LauEmbeddedData*> LauBkgndEmbDataList;
//! Typedef for a vector of booleans to flag if events are reused
typedef std::vector<Bool_t> LauBkgndReuseEventsList;
//! Initialise the fit
virtual void initialise();
//! Initialise the signal DP models
virtual void initialiseDPModels();
+ //! Recalculate Normalization the signal DP models
+ virtual void recalculateNormalisation();
+
//! Update the coefficients
virtual void updateCoeffs();
//! Toy MC generation and fitting overloaded functions
virtual Bool_t genExpt();
//! Calculate things that depend on the fit parameters
//! after they have been updated by Minuit
virtual void propagateParUpdates();
//! Read in the input fit data variables, e.g. m13Sq and m23Sq
virtual void cacheInputFitVars();
//! Check the initial fit parameters
virtual void checkInitFitParams();
//! Get the fit results and store them
/*!
\param [in] tablePrefixName prefix for the name of the output file
*/
virtual void finaliseFitResults(const TString& tablePrefixName);
//! Print the fit fractions, total DP rate and mean efficiency
/*!
\param [out] output the output to be printed
*/
virtual void printFitFractions(std::ostream& output);
//! Print the asymmetries
/*!
\param [out] output the output to be printed
*/
virtual void printAsymmetries(std::ostream& output);
//! Write the fit results in latex table format
/*!
\param [in] outputFile the name of the output file
*/
virtual void writeOutTable(const TString& outputFile);
//! Store the per event likelihood values
virtual void storePerEvtLlhds();
// Methods to do with calculating the likelihood functions
// and manipulating the fitting parameters.
//! Get the total likelihood for each event
/*!
\param [in] iEvt the event number
*/
virtual Double_t getTotEvtLikelihood(UInt_t iEvt);
//! Calculate the signal and background likelihoods for the DP for a given event
/*!
\param [in] iEvt the event number
*/
virtual void getEvtDPLikelihood(UInt_t iEvt);
//! Calculate the SCF likelihood for the DP for a given event
/*!
\param [in] iEvt the event number
*/
virtual Double_t getEvtSCFDPLikelihood(UInt_t iEvt);
//! Determine the signal and background likelihood for the extra variables for a given event
/*!
\param [in] iEvt the event number
*/
virtual void getEvtExtraLikelihoods(UInt_t iEvt);
//! Get the total number of events
/*!
\return the total number of events
*/
virtual Double_t getEventSum() const;
//! Set the fit parameters for the DP model
void setSignalDPParameters();
//! Set the fit parameters for the extra PDFs
void setExtraPdfParameters();
//! Set the initial yields
void setFitNEvents();
//! Set-up other parameters that are derived from the fit results, e.g. fit fractions
void setExtraNtupleVars();
//! Randomise the initial fit parameters
void randomiseInitFitPars();
//! Calculate the CP-conserving and CP-violating fit fractions
/*!
\param [in] initValues is this before or after the fit
*/
void calcExtraFractions(Bool_t initValues = kFALSE);
//! Calculate the CP asymmetries
/*!
\param [in] initValues is this before or after the fit
*/
void calcAsymmetries(Bool_t initValues = kFALSE);
//! Define the length of the background vectors
virtual void setupBkgndVectors();
//! Determine the number of events to generate for each hypothesis
LauGenInfo eventsToGenerate();
//! Generate signal event
Bool_t generateSignalEvent();
//! Generate background event
/*!
\param [in] bgID ID number of the background class
*/
Bool_t generateBkgndEvent(UInt_t bgID);
//! Setup the required ntuple branches
void setupGenNtupleBranches();
//! Store all of the DP information
void setDPBranchValues();
//! Generate from the extra PDFs
/*!
\param [in] extraPdfs the list of extra PDFs
\param [in] embeddedData the embedded data sample
*/
void generateExtraPdfValues(LauPdfList* extraPdfs, LauEmbeddedData* embeddedData);
//! Store the MC truth info on the TM/SCF nature of the embedded signal event
/*!
\param [in] embeddedData the full simulation information
*/
Bool_t storeSignalMCMatch(LauEmbeddedData* embeddedData);
//! Add sPlot branches for the extra PDFs
/*!
\param [in] extraPdfs the list of extra PDFs
\param [in] prefix the list of prefixes for the branch names
*/
void addSPlotNtupleBranches(const LauPdfList* extraPdfs, const TString& prefix);
//! Set the branches for the sPlot ntuple with extra PDFs
/*!
\param [in] extraPdfs the list of extra PDFs
\param [in] prefix the list of prefixes for the branch names
\param [in] iEvt the event number
*/
Double_t setSPlotNtupleBranchValues(LauPdfList* extraPdfs, const TString& prefix, UInt_t iEvt);
//! Update the signal events after Minuit sets background parameters
void updateSigEvents();
//! Add branches to store experiment number and the event number within the experiment
virtual void setupSPlotNtupleBranches();
//! Returns the names of all variables in the fit
virtual LauSPlot::NameSet variableNames() const;
//! Returns the names and yields of species that are free in the fit
virtual LauSPlot::NumbMap freeSpeciesNames() const;
//! Returns the names and yields of species that are fixed in the fit
virtual LauSPlot::NumbMap fixdSpeciesNames() const;
//! Returns the species and variables for all 2D PDFs in the fit
virtual LauSPlot::TwoDMap twodimPDFs() const;
//! Check if the signal is split into well-reconstructed and mis-reconstructed types
virtual Bool_t splitSignal() const {return this->useSCF();}
//! Check if the mis-reconstructed signal is to be smeared in the DP
virtual Bool_t scfDPSmear() const {return (scfMap_ != 0);}
//! 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!)
/*!
\param [in] inputData the fit data
*/
void appendBinCentres( LauFitDataTree* inputData );
private:
//! The B- signal Dalitz plot model
LauAbsDPDynamics *negSigModel_;
//! The B+ signal Dalitz plot model
LauAbsDPDynamics *posSigModel_;
//! The B- background Dalitz plot models
LauBkgndDPModelList negBkgndDPModels_;
//! The B+ background Dalitz plot models
LauBkgndDPModelList posBkgndDPModels_;
//! The B- Dalitz plot kinematics object
LauKinematics *negKinematics_;
//! The B+ Dalitz plot kinematics object
LauKinematics *posKinematics_;
//! The B- signal PDFs
LauPdfList negSignalPdfs_;
//! The B+ signal PDFs
LauPdfList posSignalPdfs_;
//! The B- SCF PDFs
LauPdfList negScfPdfs_;
//! The B+ SCF PDFs
LauPdfList posScfPdfs_;
//! The B- background PDFs
LauBkgndPdfsList negBkgndPdfs_;
//! The B+ background PDFs
LauBkgndPdfsList posBkgndPdfs_;
//! Background boolean
Bool_t usingBkgnd_;
//! Number of signal components
UInt_t nSigComp_;
//! Number of signal DP parameters
UInt_t nSigDPPar_;
//! Number of extra PDF parameters
UInt_t nExtraPdfPar_;
//! Number of parameters
UInt_t nNormPar_;
//! Magnitudes and Phases
std::vector<LauAbsCoeffSet*> coeffPars_;
//! The B- fit fractions
LauParArray negFitFrac_;
//! The B+ fit fractions
LauParArray posFitFrac_;
//! The CP violating fit fraction
LauParArray CPVFitFrac_;
//! The CP conserving fit fraction
LauParArray CPCFitFrac_;
//! The fit fraction asymmetries
std::vector<LauParameter> fitFracAsymm_;
//! A_CP parameter
std::vector<LauParameter> acp_;
//! The mean efficiency for B- model
LauParameter negMeanEff_;
//! The mean efficiency for B+ model
LauParameter posMeanEff_;
//! The average DP rate for B-
LauParameter negDPRate_;
//! The average DP rate for B+
LauParameter posDPRate_;
//! Signal yield
LauParameter* signalEvents_;
//! Signal asymmetry
LauParameter* signalAsym_;
//! Option to force an asymmetry
Bool_t forceAsym_;
//! Background yield(s)
LauBkgndYieldList bkgndEvents_;
//! Background asymmetries(s)
LauBkgndYieldList bkgndAsym_;
//! IS the analysis tagged?
const Bool_t tagged_;
//! Event charge
const TString tagVarName_;
//! Current event charge
Int_t curEvtCharge_;
//! Vector to store event charges
std::vector<Int_t> evtCharges_;
//! Is the signal split into TM and SCF
Bool_t useSCF_;
//! Is the SCF fraction DP-dependent
Bool_t useSCFHist_;
//! The (global) SCF fraction parameter
LauParameter scfFrac_;
//! The histogram giving the DP-dependence of the SCF fraction
LauEffModel* scfFracHist_;
//! The smearing matrix for the SCF DP PDF
LauScfMap* scfMap_;
//! The cached values of the SCF fraction for each event
std::vector<Double_t> recoSCFFracs_;
//! The cached values of the SCF fraction for each bin centre
std::vector<Double_t> fakeSCFFracs_;
//! The cached values of the sqDP jacobians for each event
std::vector<Double_t> recoJacobians_;
//! The cached values of the sqDP jacobians for each true bin
std::vector<Double_t> fakeJacobians_;
//! Run choice variables
Bool_t compareFitData_;
//! Name of the parent particle
TString negParent_;
//! Name of the parent particle
TString posParent_;
//! The complex coefficients for B-
std::vector<LauComplex> negCoeffs_;
//! The complex coefficients for B+
std::vector<LauComplex> posCoeffs_;
// Embedding SP events
//! The B- signal event tree
LauEmbeddedData *negSignalTree_;
//! The B+ signal event tree
LauEmbeddedData *posSignalTree_;
//! The B- background event tree
LauBkgndEmbDataList negBkgndTree_;
//! The B+ background event tree
LauBkgndEmbDataList posBkgndTree_;
//! Boolean to reuse signal events
Bool_t reuseSignal_;
//! Boolean to use reweighting for B-
Bool_t useNegReweighting_;
//! Boolean to use reweighting for B+
Bool_t usePosReweighting_;
//! Vector of booleans to reuse background events
LauBkgndReuseEventsList reuseBkgnd_;
// Likelihood values
//! Signal DP likelihood value
Double_t sigDPLike_;
//! SCF DP likelihood value
Double_t scfDPLike_;
//! Background DP likelihood value(s)
std::vector<Double_t> bkgndDPLike_;
//! Signal likelihood from extra PDFs
Double_t sigExtraLike_;
//! SCF likelihood from extra PDFs
Double_t scfExtraLike_;
//! Background likelihood value(s) from extra PDFs
std::vector<Double_t> bkgndExtraLike_;
//! Total signal likelihood
Double_t sigTotalLike_;
//! Total SCF likelihood
Double_t scfTotalLike_;
//! Total background likelihood(s)
std::vector<Double_t> bkgndTotalLike_;
ClassDef(LauCPFitModel,0) // CP fit/ToyMC model
};
#endif
diff --git a/inc/LauDabbaRes.hh b/inc/LauDabbaRes.hh
index 56466db..86bcd86 100644
--- a/inc/LauDabbaRes.hh
+++ b/inc/LauDabbaRes.hh
@@ -1,95 +1,95 @@
-// Copyright University of Warwick 2010 - 2013.
+// Copyright University of Warwick 2010 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauDabbaRes.hh
\brief File containing declaration of LauDabbaRes class.
*/
/*! \class LauDabbaRes
\brief Class for defining the Dabba resonance model
Class for defining the Dabba resonance model
Formulae and data values from arXiv:0901.2217 - author D.V.Bugg
*/
#ifndef LAU_DABBA_RES
#define LAU_DABBA_RES
#include "TString.h"
#include "LauAbsResonance.hh"
#include "LauComplex.hh"
class LauDabbaRes : public LauAbsResonance {
public:
//! Constructor
/*!
\param [in] resName the name of the resonance
\param [in] resMass the mass of the resonance
\param [in] resWidth the width of the resonance
\param [in] resSpin the spin of the resonance
\param [in] resCharge the charge of the resonance
\param [in] resPairAmpInt the number of the daughter not produced by the resonance
\param [in] daughters the daughter particles
*/
- LauDabbaRes(TString resName, Double_t resMass, Double_t resWidth,
+ LauDabbaRes(TString resName, LauParameter* resMass, LauParameter* resWidth,
Int_t resSpin, Int_t resCharge, Int_t resPairAmpInt,
const LauDaughters* daughters);
//! Destructor
virtual ~LauDabbaRes();
//! Initialise the model
virtual void initialise();
//! Get the resonance model type
/*!
\return the resonance model type
*/
virtual LauAbsResonance::LauResonanceModel getResonanceModel() const {return LauAbsResonance::Dabba;}
//! Set the parameter values
/*!
\param [in] b constant factor
\param [in] alpha constant factor
\param [in] beta constant factor
*/
void setConstants(Double_t b, Double_t alpha, Double_t beta);
protected:
//! Complex resonant amplitude
/*!
\param [in] mass appropriate invariant mass for the resonance
\param [in] spinTerm Zemach spin term
*/
virtual LauComplex resAmp(Double_t mass, Double_t spinTerm);
//! Check that the daughter particles are D and pi
void checkDaughterTypes() const;
private:
//! Defined as mD + mPi all squared
Double_t mSumSq_;
//! Defined as mD*mD - 0.5*mPi*mPi
Double_t sAdler_;
//! Constant factor
Double_t b_;
//! Constant factor
Double_t alpha_;
//! Constant factor
Double_t beta_;
ClassDef(LauDabbaRes,0) // Dabba resonance model
};
#endif
diff --git a/inc/LauFlatNR.hh b/inc/LauFlatNR.hh
index 860de54..93a8b7e 100644
--- a/inc/LauFlatNR.hh
+++ b/inc/LauFlatNR.hh
@@ -1,75 +1,75 @@
-// Copyright University of Warwick 2004 - 2013.
+// Copyright University of Warwick 2004 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauFlatNR.hh
\brief File containing declaration of LauFlatNR class.
*/
/*! \class LauFlatNR
\brief Class for defining a uniform nonresonant amplitude
*/
#ifndef LAU_FLAT_NR
#define LAU_FLAT_NR
#include "TString.h"
#include "LauAbsResonance.hh"
#include "LauComplex.hh"
class LauKinematics;
class LauFlatNR : public LauAbsResonance {
public:
//! Constructor
/*!
\param [in] resName the name of the resonance
\param [in] resMass the mass of the resonance
\param [in] resWidth the width of the resonance
\param [in] resSpin the spin of the resonance
\param [in] resCharge the charge of the resonance
\param [in] resPairAmpInt the number of the daughter not produced by the resonance
\param [in] daughters the daughter particles
*/
- LauFlatNR(TString resName, Double_t resMass, Double_t resWidth,
+ LauFlatNR(TString resName, LauParameter* resMass, LauParameter* resWidth,
Int_t resSpin, Int_t resCharge, Int_t resPairAmpInt,
const LauDaughters* daughters);
//! Destructor
virtual ~LauFlatNR();
//! Initialise the model
virtual void initialise();
//! Complex resonant amplitude
/*!
/param [in] kinematics kinematic parameters of the parent and daughter particles
/return the complex amplitude
*/
virtual LauComplex amplitude(const LauKinematics* kinematics);
//! Get the resonance model type
/*!
\return the resonance model type
*/
virtual LauAbsResonance::LauResonanceModel getResonanceModel() const {return LauAbsResonance::FlatNR;}
protected:
//! This is not meant to be called
virtual LauComplex resAmp(Double_t mass, Double_t spinTerm);
private:
ClassDef(LauFlatNR,0) // Uniform non-resonant model
};
#endif
diff --git a/inc/LauFlatteRes.hh b/inc/LauFlatteRes.hh
index 4c0b681..d3abdda 100644
--- a/inc/LauFlatteRes.hh
+++ b/inc/LauFlatteRes.hh
@@ -1,129 +1,129 @@
-// Copyright University of Warwick 2004 - 2013.
+// Copyright University of Warwick 2004 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauFlatteRes.hh
\brief File containing declaration of LauFlatteRes class.
*/
/*! \class LauFlatteRes
\brief Class for defining the Flatte resonance model
Class for defining the Flatte resonance model.
For use with the f_0(980) resonance.
*/
#ifndef LAU_FLATTE_RES
#define LAU_FLATTE_RES
#include "TString.h"
#include "LauComplex.hh"
#include "LauAbsResonance.hh"
class LauFlatteRes : public LauAbsResonance {
public:
//! Constructor
/*!
\param [in] resName the name of the resonance
\param [in] resMass the mass of the resonance
\param [in] resWidth the width of the resonance
\param [in] resSpin the spin of the resonance
\param [in] resCharge the charge of the resonance
\param [in] resPairAmpInt the number of the daughter not produced by the resonance
\param [in] daughters the daughter particles
*/
- LauFlatteRes(TString resName, Double_t resMass, Double_t resWidth,
+ LauFlatteRes(TString resName, LauParameter* resMass, LauParameter* resWidth,
Int_t resSpin, Int_t resCharge, Int_t resPairAmpInt,
const LauDaughters* daughters);
//! Destructor
virtual ~LauFlatteRes();
//! Initialise the model
virtual void initialise();
//! Get the resonance model type
/*!
\return the resonance model type
*/
virtual LauAbsResonance::LauResonanceModel getResonanceModel() const {return LauAbsResonance::Flatte;}
//! Get the g1 parameter
/*!
\return constant factor g1
*/
Double_t getg1Parameter() {return g1_;}
//! Get the g2 parameter
/*!
\return constant factor g2
*/
Double_t getg2Parameter() {return g2_;}
//! Set the constant g factors
/*!
\param [in] g1 gPiPi factor
\param [in] g2 gKK factor
*/
void setGFactors(Double_t g1, Double_t g2);
//! Set the g1 parameter
/*!
\param [in] g1 constant factor
*/
void setg1Parameter(Double_t g1) {g1_ = g1;}
//! Set the g2 parameter
/*!
\param [in] g2 constant factor
*/
void setg2Parameter(Double_t g2) {g2_ = g2;}
//! Set resonance parameter
/*!
\param [in] value value of the parameter to be set
\param [in] name name of the parameter to be set
*/
virtual void setResonanceParameter(Double_t value, const TString& name);
protected:
//! Complex resonant amplitude
/*!
\param [in] mass appropriate invariant mass for the resonance
\param [in] spinTerm Zemach spin term
*/
virtual LauComplex resAmp(Double_t mass, Double_t spinTerm);
private:
//! Define allowed types
enum FlattePartType {FlattePi, FlatteK};
//! Square of the resonance mass
Double_t resMassSq_;
//! Constant factor (default value from BES data)
Double_t g1_;
//! Constant factor (default value from BES data)
Double_t g2_;
//! Defined as (mPi0+mPi0)*(mPi0+mPi0)
Double_t mSumSq0_;
//! Defined as (mPi+mPi)*(mPi+mPi)
Double_t mSumSq1_;
//! Defined as (mK+mK)*(mK+mK)
Double_t mSumSq2_;
//! Defined as (mK0+mK0)*(mK0+mK0)
Double_t mSumSq3_;
ClassDef(LauFlatteRes,0) // Flatte resonance model
};
#endif
diff --git a/inc/LauGounarisSakuraiRes.hh b/inc/LauGounarisSakuraiRes.hh
index 53eb574..05251e0 100644
--- a/inc/LauGounarisSakuraiRes.hh
+++ b/inc/LauGounarisSakuraiRes.hh
@@ -1,130 +1,130 @@
-// Copyright University of Warwick 2006 - 2013.
+// Copyright University of Warwick 2006 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauGounarisSakuraiRes.hh
\brief File containing declaration of LauGounarisSakuraiRes class.
*/
/*! \class LauGounarisSakuraiRes
\brief Class for defininf the Gounaris-Sakurai resonance model
Class for defining the relativistic Gounaris-Sakurai resonance model, which
includes the use of Blatt-Weisskopf barrier factors.
*/
#ifndef LAU_GOUNARIS_SAKURAI_RES
#define LAU_GOUNARIS_SAKURAI_RES
#include "TString.h"
#include "LauComplex.hh"
#include "LauAbsResonance.hh"
class LauGounarisSakuraiRes : public LauAbsResonance {
public:
//! Constructor
/*!
\param [in] resName the name of the resonance
\param [in] resMass the mass of the resonance
\param [in] resWidth the width of the resonance
\param [in] resSpin the spin of the resonance
\param [in] resCharge the charge of the resonance
\param [in] resPairAmpInt the number of the daughter not produced by the resonance
\param [in] daughters the daughter particles
*/
- LauGounarisSakuraiRes(TString resName, Double_t resMass, Double_t resWidth,
+ LauGounarisSakuraiRes(TString resName, LauParameter* resMass, LauParameter* resWidth,
Int_t resSpin, Int_t resCharge, Int_t resPairAmpInt,
const LauDaughters* daughters);
//! Destructor
virtual ~LauGounarisSakuraiRes();
//! Initialise the model
virtual void initialise();
//! Get the resonance model type
/*!
\return the resonance model type
*/
virtual LauAbsResonance::LauResonanceModel getResonanceModel() const {return LauAbsResonance::GS;}
//! Set the form factor model and parameters
/*!
\param [in] resRadius the radius of the barrier for the resonance decay
\param [in] parRadius the radius of the barrier for the parent decay
\param [in] type the form-factor model
*/
void setBarrierRadii(Double_t resRadius, Double_t parRadius, LauAbsResonance::BarrierType type);
protected:
//! Complex resonant amplitude
/*!
\param [in] mass appropriate invariant mass for the resonance
\param [in] spinTerm Zemach spin term
*/
virtual LauComplex resAmp(Double_t mass, Double_t spinTerm);
//! Calculate the form factor for the resonance
/*!
\param [in] z particle momentum multipled by the barrier radius
\return value of the form factor
*/
Double_t calcFFactor(Double_t z);
private:
//! Momentum of the daughters in the resonance rest frame (at pole mass)
Double_t q0_;
//! Momentum of the bachelor in the resonance rest frame (at pole mass)
Double_t p0_;
//! Momentum of the bachelor in the parent rest frame (at pole mass)
Double_t pstar0_;
//! Square of the resonance mass
Double_t resMassSq_;
//! Sum of the two daughter masses
Double_t mDaugSum_;
//! Square of the sum of the two daughter masses
Double_t mDaugSumSq_;
//! Difference between the two daughter masses
Double_t mDaugDiff_;
//! Square of the difference of the two daughter masses
Double_t mDaugDiffSq_;
//! Square of the parent mass
Double_t mParentSq_;
//! Square of the bachelor mass
Double_t mBachSq_;
//! Extra parameter required by GS shape
Double_t h0_;
//! Extra parameter required by GS shape
Double_t dhdm0_;
//! Extra parameter required by GS shape
Double_t d_;
//! Radius of the barrier for resonance decay
Double_t resR_;
//! Radius of the barrier for parent decay
Double_t parR_;
//! Square of the radius of the barrier for resonance decay
Double_t resRSq_;
//! Square of the radius of the barrier for parent decay
Double_t parRSq_;
//! Value of the form factor for resonance decay (at pole mass)
Double_t FR0_;
//! Value of the form factor for parent decay (at pole mass)
Double_t FB0_;
//! Model to be used for the form factor
LauAbsResonance::BarrierType barrierType_;
ClassDef(LauGounarisSakuraiRes,0) // Gounaris-Sakurai resonance model
};
#endif
diff --git a/inc/LauIsobarDynamics.hh b/inc/LauIsobarDynamics.hh
index ccb3926..a5f886e 100644
--- a/inc/LauIsobarDynamics.hh
+++ b/inc/LauIsobarDynamics.hh
@@ -1,763 +1,772 @@
-// Copyright University of Warwick 2005 - 2013.
+// Copyright University of Warwick 2005 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauIsobarDynamics.hh
\brief File containing declaration of LauIsobarDynamics class.
*/
/*! \class LauIsobarDynamics
\brief Class for defining signal dynamics using the isobar model.
*/
#ifndef LAU_ISOBAR_DYNAMICS
#define LAU_ISOBAR_DYNAMICS
#include <vector>
#include "TString.h"
#include "LauAbsDPDynamics.hh"
#include "LauAbsResonance.hh"
#include "LauComplex.hh"
class LauDaughters;
class LauEffModel;
class LauFitDataTree;
class LauKMatrixPropagator;
class LauIsobarDynamics : public LauAbsDPDynamics {
public:
//! Constructor
/*!
\param [in] daughters the daughters of the decay
\param [in] effModel the model to describe the efficiency across the Dalitz plot
\param [in] scfFractionModel the model to describe the fraction of poorly constructed events (the self cross feed fraction) across the Dalitz plot
*/
LauIsobarDynamics(LauDaughters* daughters, LauEffModel* effModel, LauEffModel* scfFractionModel = 0);
//! Constructor
/*!
\param [in] daughters the daughters of the decay
\param [in] effModel the model to describe the efficiency across the Dalitz plot
\param [in] scfFractionModel the models to describe the fraction of poorly constructed events (the self cross feed fraction) across the Dalitz plot for various tagging categories
*/
LauIsobarDynamics(LauDaughters* daughters, LauEffModel* effModel, LauTagCatScfFractionModelMap scfFractionModel);
//! Destructor
virtual ~LauIsobarDynamics();
//! Initialise the Dalitz plot dynamics
/*!
\param [in] coeffs the complex coefficients for the resonances
*/
virtual void initialise(const std::vector<LauComplex>& coeffs);
+ //! recalculate Normalization
+ virtual void recalculateNormalisation();
+
//! Set the name of the file to which to save the results of the integrals
/*!
\param [in] fileName the name of the file
*/
inline void setIntFileName(const TString& fileName) {intFileName_ = fileName;}
// Integration
//! Set the widths of the bins to use when integrating across the Dalitz plot
/*!
\param [in] m13BinWidth the bin width to use when integrating over m13
\param [in] m23BinWidth the bin width to use when integrating over m23
*/
virtual void setIntegralBinWidths(Double_t m13BinWidth, Double_t m23BinWidth);
//! Add a resonance to the Dalitz plot
/*!
\param [in] resName the name of the resonant particle
\param [in] resPairAmpInt the index of the daughter not produced by the resonance
\param [in] resType the type of the resonance. Allowed types are: flatte, relbw, dabba, kappa, sigma, lass-bw, lass-nr, lass, gs, nrmodel, bellesymnr and bellenr
+ \param [in] fixMass fix or release the mass to be fited
+ \param [in] fixWidth fix or release the width to be fited
\param [in] newMass set a custom mass for the resonance
\param [in] newWidth set a custom width for the resonance
\param [in] newSpin set a custom spin for the resonance
*/
virtual void addResonance(const TString& resName, Int_t resPairAmpInt, const TString& resType,
- Double_t newMass = -1.0, Double_t newWidth = -1.0, Int_t newSpin = -1);
+ Bool_t fixMass = kTRUE, Bool_t fixWidth = kTRUE,
+ Double_t newMass = -1.0, Double_t newWidth = -1.0, Int_t newSpin = -1);
//! Define a new K-matrix Propagator
/*!
\param [in] propName the name of the propagator
\param [in] paramFileName the file that defines the propagator
\param [in] resPairAmpInt the index of the bachelor
\param [in] nChannels the number of channels
\param [in] nPoles the number of poles
\param [in] rowIndex the index of the row to be used when summing over all amplitude channels: S-wave corresponds to rowIndex = 1.
*/
virtual void defineKMatrixPropagator(const TString& propName, const TString& paramFileName,
Int_t resPairAmpInt, Int_t nChannels, Int_t nPoles, Int_t rowIndex = 1);
//! Add a K-matrix production pole term to the model
/*!
\param [in] poleName the name of the pole
\param [in] propName the name of the propagator to use
\param [in] poleIndex the index of the pole within the propagator
*/
virtual void addKMatrixProdPole(const TString& poleName, const TString& propName, Int_t poleIndex);
//! Add a K-matrix slowly-varying part (SVP) term to the model
/*!
\param [in] SVPName the name of the term
\param [in] propName the name of the propagator to use
\param [in] channelIndex the index of the channel within the propagator
*/
virtual void addKMatrixProdSVP(const TString& SVPName, const TString& propName, Int_t channelIndex);
//! Change the properties of a resonance particle within this model
/*!
Note that parameters set to -1 are ignored.
\param [in] resName the name of the resonance to modify
\param [in] newMass the new mass for this resonance
\param [in] newWidth the new width for this resonance
\param [in] newSpin the new spin for this resonance
*/
virtual void changeResonance(const TString& resName, Double_t newMass = -1.0, Double_t newWidth = -1.0, Int_t newSpin = -1);
//! Generate a toy MC signal event
/*!
\return kTRUE if the event is successfully generated, kFALSE otherwise
*/
virtual Bool_t generate();
//! Check the status of the toy MC generation
/*!
\param [in] printErrorMessages whether error messages should be printed
\param [in] printInfoMessages whether info messages should be printed
\return the status of the toy MC generation
*/
virtual ToyMCStatus checkToyMC(Bool_t printErrorMessages = kTRUE, Bool_t printInfoMessages = kFALSE);
//! Retrieve the maximum number of iterations allowed when generating an event
/*!
\return the maximum number of iterations allowed
*/
inline Int_t maxGenIterations() const {return iterationsMax_;}
//! Calculate the likelihood (and all associated information) for the given event number
/*!
\param [in] iEvt the event number
*/
virtual void calcLikelihoodInfo(UInt_t iEvt);
//! Calculate the likelihood (and all associated information) given values of the Dalitz plot coordinates
/*!
\param [in] m13Sq the invariant mass squared of the first and third daughters
\param [in] m23Sq the invariant mass squared of the second and third daughters
*/
virtual void calcLikelihoodInfo(Double_t m13Sq, Double_t m23Sq);
//! Calculate the likelihood (and all associated information) given values of the Dalitz plot coordinates and the tagging category
/*!
Also obtain the self cross feed fraction to cache with the rest of the Dalitz plot quantities.
\param [in] m13Sq the invariant mass squared of the first and third daughters
\param [in] m23Sq the invariant mass squared of the second and third daughters
\param [in] tagCat the tagging category
*/
virtual void calcLikelihoodInfo(Double_t m13Sq, Double_t m23Sq, Int_t tagCat);
//! Retrieve the total amplitude for the current event
/*!
\return the total amplitude
*/
virtual const LauComplex& getEvtDPAmp() const {return totAmp_;}
//! Retrieve the invariant mass squared of the first and third daughters in the current event
/*!
\return the invariant mass squared of the first and third daughters in the current event
*/
virtual Double_t getEvtm13Sq() const {return m13Sq_;}
//! Retrieve the invariant mass squared of the second and third daughters in the current event
/*!
\return the invariant mass squared of the second and third daughters in the current event
*/
virtual Double_t getEvtm23Sq() const {return m23Sq_;}
//! Retrieve the square Dalitz plot coordinate, m', for the current event
/*!
\return the square Dalitz plot coordinate, m', for the current event
*/
virtual Double_t getEvtmPrime() const {return mPrime_;}
//! Retrieve the square Dalitz plot coordinate, theta', for the current event
/*!
\return the square Dalitz plot coordinate, theta', for the current event
*/
virtual Double_t getEvtthPrime() const {return thPrime_;}
//! Retrieve the efficiency for the current event
/*!
\return the efficiency for the current event
*/
virtual Double_t getEvtEff() const {return eff_;}
//! Retrieve the fraction of events that are poorly reconstructed (the self cross feed fraction) for the current event
/*!
\return the self cross feed fraction for the current event
*/
virtual Double_t getEvtScfFraction() const {return scfFraction_;}
//! Retrieve the Jacobian, for the transformation into square DP coordinates, for the current event
/*!
\return the Jacobian for the current event
*/
virtual Double_t getEvtJacobian() const {return jacobian_;}
//! Retrieve the likelihood for the current event
/*!
evtLike_ = totAmp_.abs2()*eff_/DPNorm_
\return the likelihood for the current event
*/
virtual Double_t getEvtLikelihood() const {return evtLike_;}
//! Calculate the fit fractions, mean efficiency and total DP rate
/*!
\param [in] init whether the calculated values should be stored as the initial/generated values or the fitted values
*/
virtual void calcExtraInfo(Bool_t init = kFALSE);
//! Calculates whether an event with the current kinematics should be accepted in order to produce a distribution of events that matches the model e.g. when reweighting embedded data
/*!
Uses the accept/reject method.
\return kTRUE if the event has been accepted, kFALSE otherwise
*/
virtual Bool_t gotReweightedEvent();
//! Calculate the acceptance rate, for events with the current kinematics, when generating events according to the model
/*!
\return the weight for the current kinematics
*/
virtual Double_t getEventWeight();
//! Set the maximum value of A squared to be used in the accept/reject
/*!
\param [in] value the new value
*/
inline void setASqMaxValue(Double_t value) {aSqMaxSet_ = value;}
//! Retrieve the maximum value of A squared to be used in the accept/reject
/*!
\return the maximum value of A squared
*/
inline Double_t getASqMaxSetValue() const { return aSqMaxSet_; }
//! Retrieve the maximum of A squared that has been found while generating
/*!
\return the maximum of A squared that has been found
*/
inline Double_t getASqMaxVarValue() const { return aSqMaxVar_; }
//! Retrieve the normalised dynamic part of the amplitude of the given amplitude component at the current point in the Dalitz plot
/*!
\param [in] resID the index of the amplitude component within the model
\return the amplitude of the given amplitude component
*/
virtual LauComplex getDynamicAmp(Int_t resID) const {return ff_[resID].scale(fNorm_[resID]);}
//! Retrieve the event-by-event running totals of amplitude cross terms for all pairs of amplitude components
/*!
\return the event-by-event running totals of amplitude cross terms
*/
inline const std::vector< std::vector<LauComplex> >& getFiFjSum() const {return fifjSum_;}
//! Retrieve the event-by-event running totals of efficiency corrected amplitude cross terms for all pairs of amplitude components
/*!
\return the event-by-event running totals of amplitude cross terms with efficiency corrections applied
*/
inline const std::vector< std::vector<LauComplex> >& getFiFjEffSum() const {return fifjEffSum_;}
//! Retrieve the normalisation factors for the dynamic parts of the amplitudes for all of the amplitude components
/*!
\return the normalisation factors
*/
inline const std::vector<Double_t>& getFNorm() const {return fNorm_;}
//! Fill the internal data structure that caches the resonance dynamics
/*!
\param [in] fitDataTree the data source
*/
virtual void fillDataTree(const LauFitDataTree& fitDataTree);
//! Load the data for a given event
/*!
\param [in] iEvt the number of the event
*/
virtual void setDataEventNo(UInt_t iEvt);
//! Set the alpha parameter for new Belle non-resonant components
/*!
\param [in] alpha the alpha parameter value
*/
inline void setBelleNRAlpha(Double_t alpha) {BelleNRAlpha_ = alpha;}
//! Retreive the alpha parameter for new Belle non-resonant components
/*!
\return the alpha parameter
*/
inline Double_t getBelleNRAlpha() const {return BelleNRAlpha_;}
//! Set the parameters for new LASS components
/*!
\param [in] a the scattering length
\param [in] r the effective range
\param [in] R the resonance magnitude
\param [in] phiR the resonance phase
\param [in] B the background magnitude
\param [in] phiB the background phase
\param [in] cutOff the cutoff value
*/
inline void setLASSParameters(Double_t a, Double_t r, Double_t R = 1.0, Double_t phiR = 0.0, Double_t B = 1.0, Double_t phiB = 0.0, Double_t cutOff = 1.8)
{
this->setLASSScatteringLength(a);
this->setLASSEffectiveRange(r);
this->setLASSResonanceMag(R);
this->setLASSResonancePhase(phiR);
this->setLASSBackgroundMag(B);
this->setLASSBackgroundPhase(phiB);
this->setLASSCutOff(cutOff);
}
//! Set the scattering length for new LASS components
/*!
\param [in] a the scattering length
*/
inline void setLASSScatteringLength(Double_t a) {LASSScatteringLength_ = a; changeLASSScatteringLength_ = kTRUE;}
//! Set the effective range for new LASS components
/*!
\param [in] r the effective range
*/
inline void setLASSEffectiveRange(Double_t r) {LASSEffectiveRange_ = r; changeLASSEffectiveRange_ = kTRUE;}
//! Set the resonance magnitude for new LASS components
/*!
\param [in] R the resonance magnitude
*/
inline void setLASSResonanceMag(Double_t R) {LASSResonanceMag_ = R; changeLASSResonanceMag_ = kTRUE;}
//! Set the resonance phase for new LASS components
/*!
\param [in] phiR the resonance phase
*/
inline void setLASSResonancePhase(Double_t phiR) {LASSResonancePhase_ = phiR; changeLASSResonancePhase_ = kTRUE;}
//! Set the background magnitude for new LASS components
/*!
\param [in] B the background magnitude
*/
inline void setLASSBackgroundMag(Double_t B) {LASSBackgroundMag_ = B; changeLASSBackgroundMag_ = kTRUE;}
//! Set the background phase for new LASS components
/*!
\param [in] phiB the background phase
*/
inline void setLASSBackgroundPhase(Double_t phiB) {LASSBackgroundPhase_ = phiB; changeLASSBackgroundPhase_ = kTRUE;}
//! Set the cutoff value for new LASS components
/*!
\param [in] cutOff the cutoff value
*/
inline void setLASSCutOff(Double_t cutOff) {LASSCutOff_ = cutOff; changeLASSCutOff_ = kTRUE;}
//! Retrieve the scattering length for new LASS components
/*!
\return the scattering length
*/
inline Double_t getLASSScatteringLength() const {return LASSScatteringLength_;}
//! Retrieve the effective range for new LASS components
/*!
\return the effective range
*/
inline Double_t getLASSEffectiveRange() const {return LASSEffectiveRange_;}
//! Retrieve the resonance magnitude for new LASS components
/*!
\return the resonance magnitude
*/
inline Double_t getLASSResonanceMag() const {return LASSResonanceMag_;}
//! Retrieve the resonance phase for new LASS components
/*!
\return the resonance phase
*/
inline Double_t getLASSResonancePhase() const {return LASSResonancePhase_;}
//! Retrieve the background magnitude for new LASS components
/*!
\return the background magnitude
*/
inline Double_t getLASSBackgroundMag() const {return LASSBackgroundMag_;}
//! Retrieve the background phase for new LASS components
/*!
\return the background phase
*/
inline Double_t getLASSBackgroundPhase() const {return LASSBackgroundPhase_;}
//! Retrieve the cutoff value for new LASS components
/*!
\return the cutoff value
*/
inline Double_t getLASSCutOff() const {return LASSCutOff_;}
//! Set the parameters for new Flatte components
/*!
\param [in] g1 the coupling constant for channel 1
\param [in] g2 the coupling constant for channel 2
*/
inline void setFlatteParameters(Double_t g1, Double_t g2) {this->setFlatteg1(g1); this->setFlatteg2(g2);}
//! Set the g1 parameter for new Flatte components
/*!
\param [in] g1 the coupling constant for channel 1
*/
inline void setFlatteg1(Double_t g1) {FlatteParameterg1_ = g1; changeFlatteParameterg1_ = kTRUE;}
//! Set the g2 parameter for new Flatte components
/*!
\param [in] g2 the coupling constant for channel 2
*/
inline void setFlatteg2(Double_t g2) {FlatteParameterg2_ = g2; changeFlatteParameterg2_ = kTRUE;}
//! Retrieve the g1 parameter for new Flatte components
/*!
\return the constant parameter g1
*/
inline Double_t getFlatteg1() const {return FlatteParameterg1_;}
//! Retrieve the g2 parameter for new Flatte components
/*!
\return the constant parameter g2
*/
inline Double_t getFlatteg2() const {return FlatteParameterg2_;}
//! Set the parameters for the barrier factors for new resonances
/*!
\param [in] resRadius the radius due to the resonance
\param [in] parRadius the radius due to the parent
\param [in] type the type of the barrier factor
*/
inline void setBarrierRadii( Double_t resRadius, Double_t parRadius = 4.0,
LauAbsResonance::BarrierType type = LauAbsResonance::BWPrimeBarrier )
{
this->setResBarrierRadius(resRadius);
this->setParBarrierRadius(parRadius);
this->setBarrierType(type);
}
//! Set the radius of the barrier factor due to the resonance to use for new amplitude components
/*!
\param [in] radius the barrier radius
*/
inline void setResBarrierRadius(Double_t radius) {resBarrierRadius_ = radius;}
//! Set the radius of the barrier factor due to the parent to use for new amplitude components
/*!
\param [in] radius the barrier radius
*/
inline void setParBarrierRadius(Double_t radius) {parBarrierRadius_ = radius;}
//! Set the type of barrier factor to use for new amplitude components
/*!
\param [in] type the type of barrier factor. Allowed types are: BWBarrier, BWPrimeBarrier and ExpBarrier.
*/
inline void setBarrierType( LauAbsResonance::BarrierType type ) {barrierType_ = type;}
//! Retrieve the radius of the barrier factor due to the resonance to use for new amplitude components
/*!
\return the barrier radius
*/
inline Double_t getResBarrierRadius() const {return resBarrierRadius_;}
//! Retrieve the radius of the barrier factor due to the parent to use for new amplitude components
/*!
\return the barrier radius
*/
inline Double_t getParBarrierRadius() const {return parBarrierRadius_;}
//! Set the helicity flip flag for new amplitude components
/*!
\param [in] boolean the helicity flip flag
*/
inline void flipHelicityForCPEigenstates(Bool_t boolean) {flipHelicity_ = boolean;}
protected:
//! Print a summary of the model to be used
virtual void initSummary();
//! Initialise the internal storage for this model
virtual void initialiseVectors();
//! Calculate the Dalitz plot normalisation integrals across the whole Dalitz plot
virtual void calcDPNormalisation();
//! Calculate the Dalitz plot normalisation integrals over a given range
/*!
\param [in] minm13 the minimum value of m13 in the integration range
\param [in] maxm13 the maximum value of m13 in the integration range
\param [in] minm23 the minimum value of m23 in the integration range
\param [in] maxm23 the maximum value of m23 in the integration range
\param [in] m13BinWidth the bin width in m13
\param [in] m23BinWidth the bin width in m23
*/
virtual void calcDPPartialIntegral(Double_t minm13, Double_t maxm13, Double_t minm23,
Double_t maxm23, Double_t m13BinWidth, Double_t m23BinWidth);
//! Write the results of the integrals (and related information) to a file
virtual void writeIntegralsFile();
//! Set the dynamic part of the amplitude for a given amplitude component at the current point in the Dalitz plot
/*!
\param [in] index the index of the amplitude component
\param [in] realPart the real part of the amplitude
\param [in] imagPart the imaginary part of the amplitude
*/
virtual void setFFTerm(UInt_t index, Double_t realPart, Double_t imagPart);
//! Calculate the total Dalitz plot amplitude at the current point in the Dalitz plot
/*!
\param [in] cacheResData whether the amplitudes have already been cached
\param [in] weight the weight to apply (used when calculating the integrals)
\param [in] useEff whether to apply efficiency corrections
*/
virtual void dynamics(Bool_t cacheResData = kTRUE, Double_t weight = 1.0, Bool_t useEff = kTRUE);
//! Set the maximum of A squared that has been found
/*!
\param [in] value the new value
*/
inline void setASqMaxVarValue(Double_t value) {aSqMaxVar_ = value;}
//! Calculate the normalisation factor for the log-likelihood function
/*!
\return the normalisation factor
*/
virtual Double_t calcSigDPNorm();
//! Calculate the dynamic part of the amplitude for a given component at the current point in the Dalitz plot
/*!
\param [in] index the index of the amplitude component within the model
*/
virtual LauComplex resAmp(Int_t index);
//! Retrieve the named resonance
/*!
\param [in] name the name of the resonance to retrieve
\return the named resonance
*/
virtual LauAbsResonance* findResonance(const TString& name);
//! Retrieve the named resonance
/*!
\param [in] name the name of the resonance to retrieve
\return the named resonance
*/
virtual const LauAbsResonance* findResonance(const TString& name) const;
//! Remove the charge from the given particle name
/*!
\param [in,out] string the particle name
*/
virtual void removeCharge(TString& string) const;
//! Check whether a resonance is a K-matrix component of a given propagator
/*!
\param [in] resAmpInt the index of the resonance within the model
\param [in] propName the name of the K-matrix propagator
\return true if the resonance is a component of the given propagator, otherwise return false
*/
Bool_t gotKMatrixMatch(UInt_t resAmpInt, const TString& propName) const;
private:
//! The type used for containing the K-matrix propagators
typedef std::map<TString, LauKMatrixPropagator*> KMPropMap;
//! The type used for mapping K-matrix components to their propagators
typedef std::map<TString, TString> KMStringMap;
//! The resonances in the model
std::vector<LauAbsResonance*> sigResonances_;
//! The K-matrix propagators
KMPropMap kMatrixPropagators_;
//! The names of the M-matrix components in the model mapped to their propagators
KMStringMap kMatrixPropSet_;
//! The resonance types of all of the amplitude components
std::vector<TString> resTypAmp_;
//! The index within the resonance maker for each amplitude component
std::vector<Int_t> resIntAmp_;
//! The index of the daughter not produced by the resonance for each amplitude component
std::vector<Int_t> resPairAmp_;
//! The PDG codes of the daughters
std::vector<Int_t> typDaug_;
//! Whether the Dalitz plot is symmetrical
Bool_t symmetricalDP_;
//! Whether the integrals have been performed
Bool_t integralsDone_;
//! The name of the file to save integrals to
TString intFileName_;
//! The bin width to use when integrating over m13
Double_t m13BinWidth_;
//! The bin width to use when integrating over m23
Double_t m23BinWidth_;
//! The invariant mass squared of the first and third daughters
Double_t m13Sq_;
//! The invariant mass squared of the second and third daughters
Double_t m23Sq_;
//! The square Dalitz plot coordinate, m'
Double_t mPrime_;
//! The square Dalitz plot coordinate theta'
Double_t thPrime_;
//! The efficiency at the current point in the Dalitz plot
Double_t eff_;
//!The fraction of events that are poorly reconstructed (the self cross feed fraction) at the current point in the Dalitz plot
Double_t scfFraction_;
//! The Jacobian, for the transformation into square DP coordinates at the current point in the Dalitz plot
Double_t jacobian_;
//! The value of A squared for the current event
Double_t ASq_;
//! The normalised likelihood for the current event
Double_t evtLike_;
//! The total amplitude for the current event
LauComplex totAmp_;
//! The event-by-event running total of efficiency corrected amplitude cross terms for each pair of amplitude components
/*!
Calculated as the sum of ff_[i]*ff_[j]*efficiency for all events
*/
std::vector< std::vector<LauComplex> > fifjEffSum_;
//! The event-by-event running total of the amplitude cross terms for each pair of amplitude components
/*!
Calculated as the sum of ff_[i]*ff_[j] for all events
*/
std::vector< std::vector<LauComplex> > fifjSum_;
//! The dynamic part of the amplitude for each amplitude component at the current point in the Dalitz plot
std::vector<LauComplex> ff_;
//! The event-by-event running total of the dynamical amplitude squared for each amplitude component
std::vector<Double_t> fSqSum_;
//! The normalisation factors for the dynamic parts of the amplitude for each amplitude component
std::vector<Double_t> fNorm_;
//! The maximum allowed number of attempts when generating an event
Int_t iterationsMax_;
//! The number of unsucessful attempts to generate an event so far
Int_t nSigGenLoop_;
//! The maximum allowed value of A squared
Double_t aSqMaxSet_;
//! The maximum value of A squared that has been seen so far while generating
Double_t aSqMaxVar_;
//! The alpha parameter for new Belle non-resonant components
Double_t BelleNRAlpha_;
//! The scattering length for new LASS components
Double_t LASSScatteringLength_;
//! The effective range for new LASS components
Double_t LASSEffectiveRange_;
//! The resonance magnitude for new LASS components
Double_t LASSResonanceMag_;
//! The resonance phase for new LASS components
Double_t LASSResonancePhase_;
//! The background magnitude for new LASS components
Double_t LASSBackgroundMag_;
//! The background phase for new LASS components
Double_t LASSBackgroundPhase_;
//! The cutoff value for new LASS components
Double_t LASSCutOff_;
//! Whether the default value of the LASS scattering length has been changed
Bool_t changeLASSScatteringLength_;
//! Whether the default value of the LASS effective range has been changed
Bool_t changeLASSEffectiveRange_;
//! Whether the default value of the LASS resonance magnitude has been changed
Bool_t changeLASSResonanceMag_;
//! Whether the default value of the LASS resonance phase has been changed
Bool_t changeLASSResonancePhase_;
//! Whether the default value of the LASS background magnitude has been changed
Bool_t changeLASSBackgroundMag_;
//! Whether the default value of the LASS background phase has been changed
Bool_t changeLASSBackgroundPhase_;
//! Whether the default value of the LASS cutoff has been changed
Bool_t changeLASSCutOff_;
//! The constant parameter g1 for new Flatte components
Double_t FlatteParameterg1_;
//! The constant parameter g2 for new Flatte components
Double_t FlatteParameterg2_;
//! Whether the default value of the Flatte parameter g1 has been changed
Bool_t changeFlatteParameterg1_;
//! Whether the default value of the Flatte parameter g2 has been changed
Bool_t changeFlatteParameterg2_;
//! The radius of the resonance barrier factor for new amplitude components
Double_t resBarrierRadius_;
//! The radius of the parent barrier factor for new amplitude components
Double_t parBarrierRadius_;
//! The type of the barrier factor for new amplitude components
LauAbsResonance::BarrierType barrierType_;
//! The helicity flip flag for new amplitude components
Bool_t flipHelicity_;
+ //! Flag to recalculate the normalisation
+ Bool_t recalcNormalisation_;
+
ClassDef(LauIsobarDynamics,0)
};
#endif
diff --git a/inc/LauKappaRes.hh b/inc/LauKappaRes.hh
index b164702..5ff093c 100644
--- a/inc/LauKappaRes.hh
+++ b/inc/LauKappaRes.hh
@@ -1,105 +1,105 @@
-// Copyright University of Warwick 2004 - 2013.
+// Copyright University of Warwick 2004 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauKappaRes.hh
\brief File containing declaration of LauKappaRes class.
*/
/*! \class LauKappaRes
\brief Class for defining the Kappa resonance model
Class for defining the Kappa resonance model.
Formulae and data values from
Phys.Lett.B 572, 1 (2003) - author D.V.Bugg
*/
#ifndef LAU_KAPPA_RES
#define LAU_KAPPA_RES
#include "TString.h"
#include "LauComplex.hh"
#include "LauAbsResonance.hh"
class LauKappaRes : public LauAbsResonance {
public:
//! Constructor
/*!
\param [in] resName the name of the resonance
\param [in] resMass the mass of the resonance
\param [in] resWidth the width of the resonance
\param [in] resSpin the spin of the resonance
\param [in] resCharge the charge of the resonance
\param [in] resPairAmpInt the number of the daughter not produced by the resonance
\param [in] daughters the daughter particles
*/
- LauKappaRes(TString resName, Double_t resMass, Double_t resWidth,
+ LauKappaRes(TString resName, LauParameter* resMass, LauParameter* resWidth,
Int_t resSpin, Int_t resCharge, Int_t resPairAmpInt,
const LauDaughters* daughters);
//! Destructor
virtual ~LauKappaRes();
//! Initialise the model
virtual void initialise();
//! Get the resonance model type
/*!
\return the resonance model type
*/
virtual LauAbsResonance::LauResonanceModel getResonanceModel() const {return LauAbsResonance::Kappa;}
//! Set the parameter values
/*!
\param [in] b1 factor from BES data
\param [in] b2 factor from BES data
\param [in] A factor from BES data
\param [in] m0 factor from BES data
*/
void setConstants(Double_t b1, Double_t b2, Double_t A, Double_t m0);
protected:
//! Complex resonant amplitude
/*!
\param [in] mass appropriate invariant mass for the resonance
\param [in] spinTerm Zemach spin term
*/
virtual LauComplex resAmp(Double_t mass, Double_t spinTerm);
//! Check that Kappa daughters are K and pi
void checkDaughterTypes() const;
private:
//! Define m mSum as mK + mPi
Double_t mSum_;
//! Square of mSum
Double_t mSumSq_;
//! Defined as mK*mK - 0.5*mPi*mPi
Double_t sAdler_;
//! Factor from BES data
Double_t b1_;
//! Factor from BES data
Double_t b2_;
//! Factor from BES data
Double_t A_;
//! Factor from BES data
Double_t m0_;
//! Square of m0
Double_t m0Sq_;
//! Defined as m0Sq - sAdler
Double_t denom_;
ClassDef(LauKappaRes,0) // Kappa resonance model
};
#endif
diff --git a/inc/LauLASSBWRes.hh b/inc/LauLASSBWRes.hh
index 644fcc8..e062c44 100644
--- a/inc/LauLASSBWRes.hh
+++ b/inc/LauLASSBWRes.hh
@@ -1,178 +1,178 @@
-// Copyright University of Warwick 2008 - 2013.
+// Copyright University of Warwick 2008 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauLASSBWRes.hh
\brief File containing declaration of LauLASSBWRes class.
*/
/*! \class LauLASSBWRes
\brief Class for defining the resonant part of the LASS model.
Class for defining the LASS resonance model, which includes a resonant
part, plus an effective range term. This class is the resonant part only.
*/
#ifndef LAU_LASS_BW_RES
#define LAU_LASS_BW_RES
#include "TString.h"
#include "LauComplex.hh"
#include "LauAbsResonance.hh"
class LauLASSBWRes : public LauAbsResonance {
public:
//! Constructor
/*!
\param [in] resName the name of the resonance
\param [in] resMass the mass of the resonance
\param [in] resWidth the width of the resonance
\param [in] resSpin the spin of the resonance
\param [in] resCharge the charge of the resonance
\param [in] resPairAmpInt the number of the daughter not produced by the resonance
\param [in] daughters the daughter particles
*/
- LauLASSBWRes(TString resName, Double_t resMass, Double_t resWidth,
+ LauLASSBWRes(TString resName, LauParameter* resMass, LauParameter* resWidth,
Int_t resSpin, Int_t resCharge, Int_t resPairAmpInt,
const LauDaughters* daughters);
// Destructor
virtual ~LauLASSBWRes();
//! Initialise the model
virtual void initialise();
//! Get the resonance model type
/*!
\return the resonance model type
*/
virtual LauAbsResonance::LauResonanceModel getResonanceModel() const {return LauAbsResonance::LASS_BW;}
//! Get the effective range parameter
/*!
\return the effective range parameter
*/
virtual Double_t getEffectiveRange() {return r_;}
//! Get the scattering length range parameter
/*!
\return the scattering length parameter
*/
virtual Double_t getScatteringLength() {return a_;}
//! Get the background magnitude
/*!
\return the background magnitude
*/
virtual Double_t getBackgroundMag() {return B_;}
//! Get the resonance magnitude
/*!
\return the resonance magnitude
*/
virtual Double_t getResonanceMag() {return R_;}
//! Get the background phase
/*!
\return the backgorund phase
*/
virtual Double_t getBackgroundPhase() {return phiB_;}
//! Get the resonance phase
/*!
\return the resonance phase
*/
virtual Double_t getResonancePhase() {return phiR_;}
//! Get the cut off parameter
/*!
\return the cut off parameter
*/
virtual Double_t getCutOff() {return cutOff_;}
//! Set the effective range parameter
/*!
\param [in] r the effective range parameter
*/
virtual void setEffectiveRange(Double_t r) {r_ = r;}
//! Set the scattering length parameter
/*!
\param [in] a the scattering length parameter
*/
virtual void setScatteringLength(Double_t a) {a_ = a;}
//! Set the background magnitude
/*!
\param [in] B the background magnitude
*/
virtual void setBackgroundMag(Double_t B) {B_ = B;}
//! Set the resonance magnitude
/*!
\param [in] R the resonance magnitude
*/
virtual void setResonanceMag(Double_t R) {R_ = R;}
//! Set the background phase
/*!
\param [in] phiB the background phase
*/
virtual void setBackgroundPhase(Double_t phiB) {phiB_ = phiB;}
//! Set the resonance phase
/*!
\param [in] phiR the resonance phase
*/
virtual void setResonancePhase(Double_t phiR) {phiR_ = phiR;}
//! Set the cut off parameter
/*!
\param [in] cutOff the cut off parameter
*/
virtual void setCutOff(Double_t cutOff) {cutOff_ = cutOff;}
//! Set value of the various parameters
/*!
\param [in] value value of the parameter
\param [in] name nam eof the parameter
*/
virtual void setResonanceParameter(Double_t value, const TString& name);
protected:
//! Complex resonant amplitude
/*!
\param [in] mass appropriate invariant mass for the resonance
\param [in] spinTerm Zemach spin term
*/
virtual LauComplex resAmp(Double_t mass, Double_t spinTerm);
private:
//! Decay momentum of either daughter in the resonance rest frame
Double_t q0_;
//! Sum of the daughter masses
Double_t mDaugSum_;
//! Square of mDaugSum
Double_t mDaugSumSq_;
//! Difference between the daughter masses
Double_t mDaugDiff_;
//! Square of mDaugDiff
Double_t mDaugDiffSq_;
//! Square of the resonance mass
Double_t resMassSq_;
//! LASS effective range parameter
Double_t r_;
//! LASS scattering length parameter
Double_t a_;
//! LASS background magnitude
Double_t B_;
//! LASS resonance magnitude
Double_t R_;
//! LASS background phase
Double_t phiB_;
//! LASS resonance phase
Double_t phiR_;
//! LASS cut off parameter
Double_t cutOff_;
ClassDef(LauLASSBWRes,0) // LASS resonance model
};
#endif
diff --git a/inc/LauLASSNRRes.hh b/inc/LauLASSNRRes.hh
index daeea3f..6c1ee39 100644
--- a/inc/LauLASSNRRes.hh
+++ b/inc/LauLASSNRRes.hh
@@ -1,178 +1,178 @@
-// Copyright University of Warwick 2008 - 2013.
+// Copyright University of Warwick 2008 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauLASSNRRes.hh
\brief File containing declaration of LauLASSNRRes class.
*/
/*! \class LauLASSNRRes
\brief Class for defining the non resonant part of the LASS model
Class for defining the LASS resonance model, which includes a resonant
part, plus an effective range term. This class is the nonresonant part only.
*/
#ifndef LAU_LASS_NR_RES
#define LAU_LASS_NR_RES
#include "TString.h"
#include "LauComplex.hh"
#include "LauAbsResonance.hh"
class LauLASSNRRes : public LauAbsResonance {
public:
//! Constructor
/*!
\param [in] resName the name of the resonance
\param [in] resMass the mass of the resonance
\param [in] resWidth the width of the resonance
\param [in] resSpin the spin of the resonance
\param [in] resCharge the charge of the resonance
\param [in] resPairAmpInt the number of the daughter not produced by the resonance
\param [in] daughters the daughter particles
*/
- LauLASSNRRes(TString resName, Double_t resMass, Double_t resWidth,
+ LauLASSNRRes(TString resName, LauParameter* resMass, LauParameter* resWidth,
Int_t resSpin, Int_t resCharge, Int_t resPairAmpInt,
const LauDaughters* daughters);
//! Destructor
virtual ~LauLASSNRRes();
//! Initialise the model
virtual void initialise();
//! Get the resonance model type
/*!
\return the resonance model type
*/
virtual LauAbsResonance::LauResonanceModel getResonanceModel() const {return LauAbsResonance::LASS_NR;}
//! Get the effective range parameter
/*!
\return the effective range parameter
*/
virtual Double_t getEffectiveRange() {return r_;}
//! Get the scattering length range parameter
/*!
\return the scattering length parameter
*/
virtual Double_t getScatteringLength() {return a_;}
//! Get the background magnitude
/*!
\return the background magnitude
*/
virtual Double_t getBackgroundMag() {return B_;}
//! Get the resonance magnitude
/*!
\return the resonance magnitude
*/
virtual Double_t getResonanceMag() {return R_;}
//! Get the background phase
/*!
\return the backgorund phase
*/
virtual Double_t getBackgroundPhase() {return phiB_;}
//! Get the resonance phase
/*!
\return the resonance phase
*/
virtual Double_t getResonancePhase() {return phiR_;}
//! Get the cut off parameter
/*!
\return the cut off parameter
*/
virtual Double_t getCutOff() {return cutOff_;}
//! Set the effective range parameter
/*!
\param [in] r the effective range parameter
*/
virtual void setEffectiveRange(Double_t r) {r_ = r;}
//! Set the scattering length parameter
/*!
\param [in] a the scattering length parameter
*/
virtual void setScatteringLength(Double_t a) {a_ = a;}
//! Set the background magnitude
/*!
\param [in] B the background magnitude
*/
virtual void setBackgroundMag(Double_t B) {B_ = B;}
//! Set the resonance magnitude
/*!
\param [in] R the resonance magnitude
*/
virtual void setResonanceMag(Double_t R) {R_ = R;}
//! Set the background phase
/*!
\param [in] phiB the background phase
*/
virtual void setBackgroundPhase(Double_t phiB) {phiB_ = phiB;}
//! Set the resonance phase
/*!
\param [in] phiR the resonance phase
*/
virtual void setResonancePhase(Double_t phiR) {phiR_ = phiR;}
//! Set the cut off parameter
/*!
\param [in] cutOff the cut off parameter
*/
virtual void setCutOff(Double_t cutOff) {cutOff_ = cutOff;}
//! Set value of the various parameters
/*!
\param [in] value value of the parameter
\param [in] name name of the parameter
*/
virtual void setResonanceParameter(Double_t value, const TString& name);
protected:
//! Complex resonant amplitude
/*!
\param [in] mass appropriate invariant mass for the resonance
\param [in] spinTerm Zemach spin term
*/
virtual LauComplex resAmp(Double_t mass, Double_t spinTerm);
private:
//! Decay momentum of either daughter in the resonance rest frame
Double_t q0_;
//! Sum of the daughter masses
Double_t mDaugSum_;
//! Square of mDaugSum
Double_t mDaugSumSq_;
//! Difference between the daughter masses
Double_t mDaugDiff_;
//! Square of mDaugDiff
Double_t mDaugDiffSq_;
//! Square of the resonance mass
Double_t resMassSq_;
//! LASS effective range parameter
Double_t r_;
//! LASS scattering length parameter
Double_t a_;
//! LASS background magnitude
Double_t B_;
//! LASS resonance magnitude
Double_t R_;
//! LASS background phase
Double_t phiB_;
//! LASS resonance phase
Double_t phiR_;
//! LASS cut off parameter
Double_t cutOff_;
ClassDef(LauLASSNRRes,0) // LASS nonresonant model
};
#endif
diff --git a/inc/LauLASSRes.hh b/inc/LauLASSRes.hh
index c95a8e2..06d3681 100644
--- a/inc/LauLASSRes.hh
+++ b/inc/LauLASSRes.hh
@@ -1,179 +1,179 @@
-// Copyright University of Warwick 2004 - 2013.
+// Copyright University of Warwick 2004 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauLASSRes.hh
\brief File containing declaration of LauLASSRes class.
*/
/*! \class LauLASSRes
\brief Class for defining the LASS resonance model.
Class for defining the LASS resonance model, which includes a resonant
part, plus an effective range term. This class is the coherent sum of the two.
*/
#ifndef LAU_LASS_RES
#define LAU_LASS_RES
#include "TString.h"
#include "LauComplex.hh"
#include "LauAbsResonance.hh"
class LauLASSRes : public LauAbsResonance {
public:
//! Constructor
/*!
\param [in] resName the name of the resonance
\param [in] resMass the mass of the resonance
\param [in] resWidth the width of the resonance
\param [in] resSpin the spin of the resonance
\param [in] resCharge the charge of the resonance
\param [in] resPairAmpInt the number of the daughter not produced by the resonance
\param [in] daughters the daughter particles
*/
- LauLASSRes(TString resName, Double_t resMass, Double_t resWidth,
+ LauLASSRes(TString resName, LauParameter* resMass, LauParameter* resWidth,
Int_t resSpin, Int_t resCharge, Int_t resPairAmpInt,
const LauDaughters* daughters);
//! Destructor
virtual ~LauLASSRes();
//! Initialise the model
virtual void initialise();
//! Get the resonance model type
/*!
\return the resonance model type
*/
virtual LauAbsResonance::LauResonanceModel getResonanceModel() const {return LauAbsResonance::LASS;}
//! Get the effective range parameter
/*!
\return the effective range parameter
*/
virtual Double_t getEffectiveRange() {return r_;}
//! Get the scattering length range parameter
/*!
\return the scattering length parameter
*/
virtual Double_t getScatteringLength() {return a_;}
//! Get the background magnitude
/*!
\return the background magnitude
*/
virtual Double_t getBackgroundMag() {return B_;}
//! Get the resonance magnitude
/*!
\return the resonance magnitude
*/
virtual Double_t getResonanceMag() {return R_;}
//! Get the background phase
/*!
\return the backgorund phase
*/
virtual Double_t getBackgroundPhase() {return phiB_;}
//! Get the resonance phase
/*!
\return the resonance phase
*/
virtual Double_t getResonancePhase() {return phiR_;}
//! Get the cut off parameter
/*!
\return the cut off parameter
*/
virtual Double_t getCutOff() {return cutOff_;}
//! Set the effective range parameter
/*!
\param [in] r the effective range parameter
*/
virtual void setEffectiveRange(Double_t r) {r_ = r;}
//! Set the scattering length parameter
/*!
\param [in] a the scattering length parameter
*/
virtual void setScatteringLength(Double_t a) {a_ = a;}
//! Set the background magnitude
/*!
\param [in] B the background magnitude
*/
virtual void setBackgroundMag(Double_t B) {B_ = B;}
//! Set the resonance magnitude
/*!
\param [in] R the resonance magnitude
*/
virtual void setResonanceMag(Double_t R) {R_ = R;}
//! Set the background phase
/*!
\param [in] phiB the background phase
*/
virtual void setBackgroundPhase(Double_t phiB) {phiB_ = phiB;}
//! Set the resonance phase
/*!
\param [in] phiR the resonance phase
*/
virtual void setResonancePhase(Double_t phiR) {phiR_ = phiR;}
//! Set the cut off parameter
/*!
\param [in] cutOff the cut off parameter
*/
virtual void setCutOff(Double_t cutOff) {cutOff_ = cutOff;}
//! Set value of the various parameters
/*!
\param [in] value value of the parameter
\param [in] name name of the parameter
*/
virtual void setResonanceParameter(Double_t value, const TString& name);
protected:
//! Complex resonant amplitude
/*!
\param [in] mass appropriate invariant mass for the resonance
\param [in] spinTerm Zemach spin term
*/
virtual LauComplex resAmp(Double_t mass, Double_t spinTerm);
private:
//! Decay momentum of either daughter in the resonance rest frame
Double_t q0_;
//! Sum of the daughter masses
Double_t mDaugSum_;
//! Square of mDaugSum
Double_t mDaugSumSq_;
//! Difference between the daughter masses
Double_t mDaugDiff_;
//! Square of mDaugDiff
Double_t mDaugDiffSq_;
//! Square of the resonance mass
Double_t resMassSq_;
//! LASS effective range parameter
Double_t r_;
//! LASS scattering length parameter
Double_t a_;
//! LASS background magnitude
Double_t B_;
//! LASS resonance magnitude
Double_t R_;
//! LASS background phase
Double_t phiB_;
//! LASS resonance phase
Double_t phiR_;
//! LASS cut off parameter
Double_t cutOff_;
ClassDef(LauLASSRes,0) // LASS resonance model
};
#endif
diff --git a/inc/LauNRAmplitude.hh b/inc/LauNRAmplitude.hh
index b382ee3..ffc4766 100644
--- a/inc/LauNRAmplitude.hh
+++ b/inc/LauNRAmplitude.hh
@@ -1,97 +1,97 @@
-// Copyright University of Warwick 2004 - 2013.
+// Copyright University of Warwick 2004 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauNRAmplitude.hh
\brief File containing declaration of LauNRAmplitude class.
*/
/*! \class LauNRAmplitude
\brief Class for defining the NR amplitude model.
Class for defining the NR amplitude model.
Formulae and data values from arXiv:0709.0075v1 [hep-ph].
*/
#ifndef LAU_NR_AMPLITUDE
#define LAU_NR_AMPLITUDE
#include "TString.h"
#include "LauAbsResonance.hh"
#include "LauComplex.hh"
class LauKinematics;
class LauNRAmplitude : public LauAbsResonance {
public:
//! Constructor
/*!
\param [in] resName the name of the resonance
\param [in] resMass the mass of the resonance
\param [in] resWidth the width of the resonance
\param [in] resSpin the spin of the resonance
\param [in] resCharge the charge of the resonance
\param [in] resPairAmpInt the number of the daughter not produced by the resonance
\param [in] daughters the daughter particles
*/
- LauNRAmplitude(TString resName, Double_t resMass, Double_t resWidth,
+ LauNRAmplitude(TString resName, LauParameter* resMass, LauParameter* resWidth,
Int_t resSpin, Int_t resCharge, Int_t resPairAmpInt,
const LauDaughters* daughters);
//! Destructor
virtual ~LauNRAmplitude();
//! Initialise the model
virtual void initialise();
//! Complex resonant amplitude
/*!
/param [in] kinematics kinematic parameters of the parent and daughter particles
/return the complex amplitude
*/
virtual LauComplex amplitude(const LauKinematics* kinematics);
//! Get the resonance model type
/*!
\return the resonance model type
*/
virtual LauAbsResonance::LauResonanceModel getResonanceModel() const {return LauAbsResonance::NRModel;}
protected:
//! This is not meant to be called
virtual LauComplex resAmp(Double_t mass, Double_t spinTerm);
//! Evaluate the expression 1.0 / (1.0 + TMath::Exp( c * (s-p) ))
/*!
\param [in] s invariant mass squared
\param [in] c parameter from arXiv:0709.0075v1 [hep-ph]
\param [in] p parameter from arXiv:0709.0075v1 [hep-ph]
\return the value of the expression 1.0 / (1.0 + TMath::Exp( c * (s-p) ))
*/
virtual Double_t f(Double_t s, Double_t c, Double_t p) const;
private:
//! Parameter from arXiv:0709.0075v1 [hep-ph]
Double_t d_;
//! Parameter from arXiv:0709.0075v1 [hep-ph]
Double_t c1_;
//! Parameter from arXiv:0709.0075v1 [hep-ph]
Double_t c2_;
//! Parameter from arXiv:0709.0075v1 [hep-ph]
Double_t p1_;
//! Parameter from arXiv:0709.0075v1 [hep-ph]
Double_t p2_;
ClassDef(LauNRAmplitude,0) // Non-resonant amplitude model
};
#endif
diff --git a/inc/LauPolNR.hh b/inc/LauPolNR.hh
index 9759dfb..0ff5a49 100644
--- a/inc/LauPolNR.hh
+++ b/inc/LauPolNR.hh
@@ -1,92 +1,92 @@
-// Copyright University of Warwick 2004 - 2013.
+// Copyright University of Warwick 2004 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauPolNR.hh
\brief File containing declaration of LauPolNR class.
*/
/*! \class LauPolNR
\brief Class for defining the terms of Babar nonresonant model.
Defines the nonresonant model from the Babar collaboration.
arXiv:1201.5897
*/
#ifndef LAU_POL_NR
#define LAU_POL_NR
#include "TString.h"
#include "LauComplex.hh"
#include "LauAbsResonance.hh"
class LauKinematics;
class LauPolNR : public LauAbsResonance {
public:
//! Constructor
/*!
\param [in] resName the name of the resonance
\param [in] resMass the mass of the resonance
\param [in] resWidth the width of the resonance
\param [in] resSpin the spin of the resonance
\param [in] resCharge the charge of the resonance
\param [in] resPairAmpInt the number of the daughter not produced by the resonance
\param [in] daughters the daughter particles
*/
- LauPolNR(const TString& resName, Double_t resMass, Double_t resWidth,
+ LauPolNR(const TString& resName, LauParameter* resMass, LauParameter* resWidth,
Int_t resSpin, Int_t resCharge, Int_t resPairAmpInt,
const LauDaughters* daughters);
//! Destructor
virtual ~LauPolNR();
//! Initialise the model
virtual void initialise();
//! Get the resonance model type
/*!
\return the resonance model type
*/
virtual LauAbsResonance::LauResonanceModel getResonanceModel() const {return LauAbsResonance::PolNR;}
//! Set the parameter omega, the offset parameter
/*!
\param [in] omega the new offset parameter
*/
virtual void setOmega(Double_t omega) {omega_ = omega;}
//! Get the offset parameter
/*!
\return the offset parameter
*/
virtual Double_t getOmega() const {return omega_;}
protected:
//! Complex resonant amplitude
/*!
\param [in] mass appropriate invariant mass for the resonance
\param [in] spinTerm Zemach spin term
*/
virtual LauComplex resAmp(Double_t mass, Double_t spinTerm);
private:
//! The offset parameter
Double_t omega_;
//! The order in the mass
UInt_t order_;
ClassDef(LauPolNR,0) // Polynomial Non-resonant model
};
#endif
diff --git a/inc/LauRelBreitWignerRes.hh b/inc/LauRelBreitWignerRes.hh
index a3f5149..f85ad4b 100644
--- a/inc/LauRelBreitWignerRes.hh
+++ b/inc/LauRelBreitWignerRes.hh
@@ -1,125 +1,129 @@
-// Copyright University of Warwick 2004 - 2013.
+// Copyright University of Warwick 2004 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauRelBreitWignerRes.hh
\brief File containing declaration of LauRelBreitWignerRes class.
*/
/*! \class LauRelBreitWignerRes
\brief Class for defining the relativistic Breit-Wigner resonance model
Class for defining the relativistic Breit-Wigner resonance model, which
includes the use of Blatt-Weisskopf barrier factors.
*/
#ifndef LAU_REL_BREIT_WIGNER_RES
#define LAU_REL_BREIT_WIGNER_RES
#include "TString.h"
#include "LauAbsResonance.hh"
#include "LauComplex.hh"
class LauRelBreitWignerRes : public LauAbsResonance {
public:
//! Constructor
/*!
\param [in] resName the name of the resonance
\param [in] resMass the mass of the resonance
\param [in] resWidth the width of the resonance
\param [in] resSpin the spin of the resonance
\param [in] resCharge the charge of the resonance
\param [in] resPairAmpInt the number of the daughter not produced by the resonance
\param [in] daughters the daughter particles
*/
- LauRelBreitWignerRes(TString resName, Double_t resMass, Double_t resWidth,
+ LauRelBreitWignerRes(TString resName, LauParameter* resMass, LauParameter* resWidth,
Int_t resSpin, Int_t resCharge, Int_t resPairAmpInt,
const LauDaughters* daughters);
//! Destructor
virtual ~LauRelBreitWignerRes();
//! Initialise the model
virtual void initialise();
//! Get the resonance model type
/*!
\return the resonance model type
*/
virtual LauAbsResonance::LauResonanceModel getResonanceModel() const {return LauAbsResonance::RelBW;}
//! Set the form factor model and parameters
/*!
\param [in] resRadius the radius of the barrier for the resonance decay
\param [in] parRadius the radius of the barrier for the parent decay
\param [in] type the form-factor model
*/
void setBarrierRadii(Double_t resRadius, Double_t parRadius, LauAbsResonance::BarrierType type);
protected:
//! Complex resonant amplitude
/*!
\param [in] mass appropriate invariant mass for the resonance
\param [in] spinTerm Zemach spin term
*/
virtual LauComplex resAmp(Double_t mass, Double_t spinTerm);
//! Calculate the form factor for the resonance
/*!
\param [in] z particle momentum multipled by the barrier radius
\return value of the form factor
*/
Double_t calcFFactor(Double_t z);
private:
//! Momentum of the daughters in the resonance rest frame (at pole mass)
Double_t q0_;
//! Momentum of the bachelor in the resonance rest frame (at pole mass)
Double_t p0_;
//! Momentum of the bachelor in the parent rest frame (at pole mass)
Double_t pstar0_;
+ //! The resonance mass
+ Double_t resMass_;
//! Square of the resonance mass
Double_t resMassSq_;
+ //! The resonance width
+ Double_t resWidth_;
//! Sum of the two daughter masses
Double_t mDaugSum_;
//! Square of the sum of the two daughter masses
Double_t mDaugSumSq_;
//! Difference of the two daughter masses
Double_t mDaugDiff_;
//! Square of the difference of the two daughter masses
Double_t mDaugDiffSq_;
//! Square of the parent mass
Double_t mParentSq_;
//! Square of the bachelor mass
Double_t mBachSq_;
//! Radius of the barrier for resonance decay
Double_t resR_;
//! Radius of the barrier for parent decay
Double_t parR_;
//! Square of the radius of the barrier for resonance decay
Double_t resRSq_;
//! Square of the radius of the barrier for parent decay
Double_t parRSq_;
//! Value of the form factor for resonance decay (at pole mass)
Double_t FR0_;
//! Value of the form factor for parent decay (at pole mass)
Double_t FB0_;
//! Model to be used for the form factor
LauAbsResonance::BarrierType barrierType_;
ClassDef(LauRelBreitWignerRes,0) // Relativistic Breit-Wigner resonance model
};
#endif
diff --git a/inc/LauResonanceInfo.hh b/inc/LauResonanceInfo.hh
index 9f1c022..14915b0 100644
--- a/inc/LauResonanceInfo.hh
+++ b/inc/LauResonanceInfo.hh
@@ -1,103 +1,124 @@
-// Copyright University of Warwick 2006 - 2013.
+// Copyright University of Warwick 2006 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauResonanceInfo.hh
\brief File containing declaration of LauResonanceInfo class.
*/
/*! \class LauResonanceInfo
\brief Class for defining the properties of a resonant particle.
*/
#ifndef LAU_RESONANCE_INFO
#define LAU_RESONANCE_INFO
+#include <iosfwd>
+
#include "TString.h"
+class LauParameter;
+
class LauResonanceInfo {
public:
//! Constructor
/*!
\param [in] name the name of the resonant particle
\param [in] mass the mass of the resonant particle
\param [in] width the width of the resonant particle
\param [in] spin the spin of the resonant particle
\param [in] charge the charge of the resonant particle
\param [in] range the range of the resonant particle
*/
LauResonanceInfo(const TString& name, Double_t mass, Double_t width, Int_t spin, Int_t charge, Double_t range = 4.0);
//! Destructor
- virtual ~LauResonanceInfo(){}
+ virtual ~LauResonanceInfo();
//! Retrieve the name of the resonant particle
/*!
\return the name of the resonant particle
*/
TString getName() const {return name_;}
//! Retrieve the mass of the resonant particle
/*!
\return the mass of the resonant particle
*/
- Double_t getMass() const {return mass_;}
+ LauParameter* getMass() const {return mass_;}
//! Retrieve the width of the resonant particle
/*!
\return the width of the resonant particle
*/
- Double_t getWidth() const {return width_;}
+ LauParameter* getWidth() const {return width_;}
//! Retrieve the spin of the resonant particle
/*!
\return the spin of the resonant particle
*/
Int_t getSpin() const {return spin_;}
//! Retrieve the charge of the resonant particle
/*!
\return the charge of the resonant particle
*/
Int_t getCharge() const {return charge_;}
//! Retrieve the range of the resonant particle
/*!
\return the range of the resonant particle
*/
Double_t getRange() const {return range_;}
+ //! Create the charge conjugate particle info record
+ /*!
+ The mass and width parameters are cloned
+ */
+ LauResonanceInfo* createChargeConjugate() const;
+
protected:
private:
+ //! Copy constructor
+ LauResonanceInfo( const LauResonanceInfo& other );
+
+ //! Copy constructor (with new name and charge)
+ LauResonanceInfo( const LauResonanceInfo& other, const TString& newName, const Int_t newCharge );
+
+ //! Copy assignment operator (not implemented)
+ LauResonanceInfo& operator=( const LauResonanceInfo& other );
+
//! The name of the resonant particle
TString name_;
//! The mass of the resonant particle
- Double_t mass_;
+ LauParameter* mass_;
//! The width of the resonant particle
- Double_t width_;
+ LauParameter* width_;
//! The spin of the resonant particle
Int_t spin_;
//! The charge of the resonant particle
Int_t charge_;
//! The range of the resonant particle
Double_t range_;
ClassDef(LauResonanceInfo, 0) // Specify each allowed resonance
};
+ostream& operator<<( ostream& stream, const LauResonanceInfo& infoRecord );
+
#endif
diff --git a/inc/LauResonanceMaker.hh b/inc/LauResonanceMaker.hh
index db6e569..f80c5b3 100644
--- a/inc/LauResonanceMaker.hh
+++ b/inc/LauResonanceMaker.hh
@@ -1,85 +1,105 @@
-// Copyright University of Warwick 2004 - 2013.
+// Copyright University of Warwick 2004 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauResonanceMaker.hh
\brief File containing declaration of LauResonanceMaker class.
*/
/*! \class LauResonanceMaker
- \brief Class for creating resonances.
+ \brief Singleton factory class for creating resonances.
- Class for creating resonances. All known resonances are stored within this class.
+ Singleton factory class for creating resonances. Information records for all known resonances are stored within this class.
*/
#ifndef LAU_RESONANCE_MAKER
#define LAU_RESONANCE_MAKER
-#include "LauResonanceInfo.hh"
+#include <iosfwd>
+#include <vector>
+
#include "TString.h"
-#include <vector>
+#include "LauAbsResonance.hh"
-class LauAbsResonance;
class LauDaughters;
+class LauResonanceInfo;
class LauResonanceMaker {
public:
- //! Constructor
- /*!
- \param [in] daughters the three daughters of the decay
- */
- LauResonanceMaker(const LauDaughters* daughters);
-
- //! Destructor
- virtual ~LauResonanceMaker();
+ //! Get the factory instance
+ static LauResonanceMaker& get();
//! Create a resonance
/*!
+ \param [in] daughters defines the Dalitz plot in which the resonance should be created
\param [in] resName the name of the resonant particle
\param [in] resPairAmpInt the index of the daughter not produced by the resonance
\param [in] resType the type of the resonance.
- Allowed types are: flatte, relbw, dabba, kappa, sigma, lass-bw, lass-nr, lass, gs, nrmodel, bellesymnr and bellenr.
\return the resonance
*/
- LauAbsResonance* getResonance(const TString& resName, Int_t resPairAmpInt, const TString& resType);
+ LauAbsResonance* getResonance(const LauDaughters* daughters, const TString& resName, Int_t resPairAmpInt, const TString& resType);
//! Retrieve the integer index for the specified resonance
/*!
\param [in] name the name of the resonant particle
\return the index
*/
Int_t resTypeInt(const TString& name) const;
//! Retrieve the number of defined resonances
/*!
\return the number of defined resonances
*/
UInt_t getNResDefMax() const {return nResDefMax_;}
+ //! Retrieve the List of floating parameters
+ /*!
+ \return the List of floating parameters
+ */
+ std::vector<LauParameter*> getFloatingParameters();
+
+ //! Print the information records, one per line, to the requested stream
+ /*!
+ \param [in,out] stream the stream to which to print the info
+ */
+ void printAll( ostream& stream ) const;
+
protected:
//! Create the list of known resonances
void createResonanceVector();
private:
+ //! Constructor
+ LauResonanceMaker();
+
+ //! Destructor
+ virtual ~LauResonanceMaker();
+
+ //! Copy constructor (not inplemented)
+ LauResonanceMaker( const LauResonanceMaker& other );
+
+ //! Copy assignment (not implemented)
+ LauResonanceMaker& operator=( const LauResonanceMaker& other );
+
+ //! The singleton instance
+ static LauResonanceMaker* resonanceMaker_;
+
//! The number of known resonances
UInt_t nResDefMax_;
- //! The daughters
- const LauDaughters* daughters_;
-
//! The known resonances
- std::vector<LauResonanceInfo> resInfo_;
+ std::vector<LauResonanceInfo*> resInfo_;
ClassDef(LauResonanceMaker,0) // Kinematic routines
};
#endif
diff --git a/inc/LauSigmaRes.hh b/inc/LauSigmaRes.hh
index d0ca78f..a755ce4 100644
--- a/inc/LauSigmaRes.hh
+++ b/inc/LauSigmaRes.hh
@@ -1,102 +1,102 @@
-// Copyright University of Warwick 2004 - 2013.
+// Copyright University of Warwick 2004 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauSigmaRes.hh
\brief File containing declaration of LauSigmaRes class.
*/
/*! \class LauSigmaRes
\brief Class for defining the Sigma resonance model
Class for defining the Sigma resonance model. Formulae and data values from
Phys.Lett.B 572, 1 (2003) - author D.V.Bugg
*/
#ifndef LAU_SIGMA_RES
#define LAU_SIGMA_RES
#include "TString.h"
#include "LauAbsResonance.hh"
#include "LauComplex.hh"
class LauSigmaRes : public LauAbsResonance {
public:
//! Constructor
/*!
\param [in] resName the name of the resonance
\param [in] resMass the mass of the resonance
\param [in] resWidth the width of the resonance
\param [in] resSpin the spin of the resonance
\param [in] resCharge the charge of the resonance
\param [in] resPairAmpInt the number of the daughter not produced by the resonance
\param [in] daughters the daughter particles
*/
- LauSigmaRes(TString resName, Double_t resMass, Double_t resWidth,
+ LauSigmaRes(TString resName, LauParameter* resMass, LauParameter* resWidth,
Int_t resSpin, Int_t resCharge, Int_t resPairAmpInt,
const LauDaughters* daughters);
//! Destructor
virtual ~LauSigmaRes();
//! Initialise the model
virtual void initialise();
//! Get the resonance model type
/*!
\return the resonance model type
*/
virtual LauAbsResonance::LauResonanceModel getResonanceModel() const {return LauAbsResonance::Sigma;}
//! Set the parameter values
/*!
\param [in] b1 factor from BES data
\param [in] b2 factor from BES data
\param [in] A factor from BES data
\param [in] m0 factor from BES data
*/
void setConstants(Double_t b1, Double_t b2, Double_t A, Double_t m0);
protected:
//! Complex resonant ampltiude
/*!
\param [in] mass appropriate invariant mass for the resonance
\param [in] spinTerm Zemach spin term
*/
virtual LauComplex resAmp(Double_t mass, Double_t spinTerm);
//! Check that both daughters are the same type of particle
void checkDaughterTypes() const;
private:
//! Defined as 4*mPi*mPi
Double_t mPiSq4_;
//! Defined as 0.5*mPi*mPi
Double_t sAdler_;
//! Factor from BES data
Double_t b1_;
//! Factor from BES data
Double_t b2_;
//! Factor from BES data
Double_t A_;
//! Factor from BES data
Double_t m0_;
//! Defined as m0 squared
Double_t m0Sq_;
//! Defined as m0Sq - sAdler
Double_t denom_;
ClassDef(LauSigmaRes,0) // Sigma resonance model
};
#endif
diff --git a/inc/LauSimpleFitModel.hh b/inc/LauSimpleFitModel.hh
index c1932ef..e45a4ad 100644
--- a/inc/LauSimpleFitModel.hh
+++ b/inc/LauSimpleFitModel.hh
@@ -1,482 +1,485 @@
-// Copyright University of Warwick 2004 - 2013.
+// Copyright University of Warwick 2004 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauSimpleFitModel.hh
\brief File containing declaration of LauSimpleFitModel class.
*/
/*! \class LauSimpleFitModel
\brief Define a Dalitz plot according to the isobar model.
A class that allows the user to define a three-body B meson
Dalitz plot according to the isobar model, i.e. defining a set of resonances
that have complex amplitudes that can interfere with each other.
*/
#ifndef LAU_SIMPLE_FIT_MODEL
#define LAU_SIMPLE_FIT_MODEL
#include <vector>
#include "TString.h"
#include "LauAbsFitModel.hh"
#include "LauParameter.hh"
class TH2;
class LauAbsBkgndDPModel;
class LauAbsCoeffSet;
class LauAbsDPDynamics;
class LauAbsPdf;
class LauEffModel;
class LauEmbeddedData;
class LauKinematics;
class LauScfMap;
class LauSimpleFitModel : public LauAbsFitModel {
public:
//! Constructor
/*!
\param [in] sigDPModel the signal DP model
*/
explicit LauSimpleFitModel(LauAbsDPDynamics* sigDPModel);
//! Destructor
virtual ~LauSimpleFitModel();
//! Set the signal event yield
/*!
\param [in] nSigEvents contains the signal yield and boolean to fix it or not
*/
virtual void setNSigEvents(LauParameter* nSigEvents);
//! Set the background event yield(s)
/*!
The name of the parameter must be that of the corresponding background category (so that it can be correctly assigned)
\param [in] nBkgndEvents contains the name, yield and option to fix the background yield
*/
virtual void setNBkgndEvents(LauParameter* nBkgndEvents);
//! Set the background DP models
/*!
\param [in] bkgndClass the name of the background class
\param [in] bkgndModel the DP model of the background
*/
void setBkgndDPModel(const TString& bkgndClass, LauAbsBkgndDPModel* bkgndModel);
//! Split the signal component into well-reconstructed and mis-reconstructed parts
/*!
The nomenclature used here is TM (truth-matched) and SCF (self cross feed)
In this option, the SCF fraction is DP-dependent
Can also optionally provide a smearing matrix to smear the SCF DP PDF
\param [in] dpHisto the DP histogram of the SCF fraction value
\param [in] upperHalf whether this histogram is only in the upper half of a symmetric DP
\param [in] scfMap the (optional) smearing matrix
*/
void splitSignalComponent( const TH2* dpHisto, Bool_t upperHalf = kFALSE, LauScfMap* scfMap = 0 );
//! Split the signal component into well reconstructed and mis-reconstructed parts
/*!
The nomenclature used here is TM (truth-matched) and SCF (self cross feed)
In this option, the SCF fraction is a single global number
\param [in] scfFrac the SCF fraction value
\param [in] fixed whether the SCF fraction is fixed or floated in the fit
*/
void splitSignalComponent( Double_t scfFrac, Bool_t fixed );
//! Determine whether we are splitting the signal into TM and SCF parts
Bool_t useSCF() const { return useSCF_; }
//! Determine whether the SCF fraction is DP-dependent
Bool_t useSCFHist() const { return useSCFHist_; }
//! Determine if we are smearing the SCF DP PDF
Bool_t smearSCFDP() const { return (scfMap_ != 0); }
//! Set the signal PDF for a given variable
/*!
\param [in] pdf the PDF to be added to the signal model
*/
void setSignalPdf(LauAbsPdf* pdf);
//! Set the SCF PDF for a given variable
/*!
\param [in] pdf the PDF to be added to the SCF model
*/
void setSCFPdf(LauAbsPdf* pdf);
//! Set the background PDF
/*!
\param [in] bkgndClass the name of the background class
\param [in] pdf the PDF to be added to the background model
*/
void setBkgndPdf(const TString& bkgndClass, LauAbsPdf* pdf);
//! Embed full simulation events for the signal, rather than generating toy from the PDFs
/*!
\param [in] fileName the name of the file containing SP events
\param [in] treeName the name of the tree
\param [in] reuseEventsWithinEnsemble
\param [in] reuseEventsWithinExperiment
\param [in] useReweighting
*/
void embedSignal(const TString& fileName, const TString& treeName,
Bool_t reuseEventsWithinEnsemble, Bool_t reuseEventsWithinExperiment = kFALSE,
Bool_t useReweighting = kFALSE);
//! Embed full simulation events for the given background class, rather than generating toy from the PDFs
/*!
\param [in] bkgndClass the name of the background class
\param [in] fileName the name of the file containing SP events
\param [in] treeName the name of the tree
\param [in] reuseEventsWithinEnsemble
\param [in] reuseEventsWithinExperiment
*/
void embedBkgnd(const TString& bkgndClass, const TString& fileName, const TString& treeName,
Bool_t reuseEventsWithinEnsemble, Bool_t reuseEventsWithinExperiment = kFALSE);
//! Set the DP amplitude coefficients
/*!
\param [in] coeffSet the set of coefficients
*/
virtual void setAmpCoeffSet(LauAbsCoeffSet* coeffSet);
//! Weight events based on the DP model
/*!
\param [in] dataFileName the name of the data file
\param [in] dataTreeName the name of the data tree
*/
virtual void weightEvents( const TString& dataFileName, const TString& dataTreeName );
protected:
//! Define a map to be used to store a category name and numbers
typedef std::map< TString, std::pair<Int_t,Double_t> > LauGenInfo;
//! Typedef for a vector of background DP models
typedef std::vector<LauAbsBkgndDPModel*> LauBkgndDPModelList;
//! Typedef for a vector of background PDFs
typedef std::vector<LauPdfList> LauBkgndPdfsList;
//! Typedef for a vector of background yields
typedef std::vector<LauParameter*> LauBkgndYieldList;
//! Typedef for a vector of embedded data objects
typedef std::vector<LauEmbeddedData*> LauBkgndEmbDataList;
//! Typedef for a vector of booleans to flag if events are reused
typedef std::vector<Bool_t> LauBkgndReuseEventsList;
//! Initialise the fit
virtual void initialise();
//! Initialise the signal DP model
virtual void initialiseDPModels();
+ //! Recalculate Normalization the signal DP models
+ virtual void recalculateNormalisation();
+
//! Update the coefficients
virtual void updateCoeffs();
//! Toy MC generation and fitting overloaded functions
virtual Bool_t genExpt();
//! Calculate things that depend on the fit parameters
//! after they have been updated by Minuit
virtual void propagateParUpdates();
//! Read in the input fit data variables, e.g. m13Sq and m23Sq
virtual void cacheInputFitVars();
//! Check the initial fit parameters
virtual void checkInitFitParams();
//! Get the fit results and store them
/*!
\param [in] tablePrefixName prefix for the name of the output file
*/
virtual void finaliseFitResults(const TString& tablePrefixName);
//! Print the fit fractions, total DP rate and mean efficiency
/*!
\param [out] output the output to be printed
*/
virtual void printFitFractions(std::ostream& output);
//! Write the fit results in latex table format
/*!
\param [in] outputFile the name of the output file
*/
virtual void writeOutTable(const TString& outputFile);
//! Store the per event likelihood values
virtual void storePerEvtLlhds();
// Methods to do with calculating the likelihood functions
// and manipulating the fitting parameters.
//! Get the total likelihood for each event
/*!
\param [in] iEvt the event number
*/
virtual Double_t getTotEvtLikelihood(UInt_t iEvt);
//! Calculate the signal and background likelihoods for the DP for a given event
/*!
\param [in] iEvt the event number
*/
virtual void getEvtDPLikelihood(UInt_t iEvt);
//! Calculate the SCF likelihood for the DP for a given event
/*!
\param [in] iEvt the event number
*/
virtual Double_t getEvtSCFDPLikelihood(UInt_t iEvt);
//! Determine the signal and background likelihood for the extra variables for a given event
/*!
\param [in] iEvt the event number
*/
virtual void getEvtExtraLikelihoods(UInt_t iEvt);
//! Get the total number of events
/*!
\return the total number of events
*/
virtual Double_t getEventSum() const;
//! Set the fit parameters for the DP model
void setSignalDPParameters();
//! Set the fit parameters for the extra PDFs
void setExtraPdfParameters();
//! Set the initial yields
void setFitNEvents();
//! Set-up other parameters that are derived from the fit results, e.g. fit fractions
void setExtraNtupleVars();
//! Randomise the initial fit parameters
void randomiseInitFitPars();
//! Define the length of the background vectors
virtual void setupBkgndVectors();
//! Determine the number of events to generate for each hypothesis
LauGenInfo eventsToGenerate();
//! Generate signal event
Bool_t generateSignalEvent();
//! Generate background event
/*!
\param [in] bkgndID ID number of the background class
*/
Bool_t generateBkgndEvent(UInt_t bkgndID);
//! Setup the required ntuple branches
void setupGenNtupleBranches();
//! Store all of the DP information
void setDPBranchValues();
//! Generate from the extra PDFs
/*!
\param [in] extraPdfs the list of extra PDFs
\param [in] embeddedData the embedded data sample
*/
void generateExtraPdfValues(LauPdfList* extraPdfs, LauEmbeddedData* embeddedData);
//! Add sPlot branches for the extra PDFs
/*!
\param [in] extraPdfs the list of extra PDFs
\param [in] prefix the list of prefixes for the branch names
*/
void addSPlotNtupleBranches(const LauPdfList* extraPdfs, const TString& prefix);
//! Set the branches for the sPlot ntuple with extra PDFs
/*!
\param [in] extraPdfs the list of extra PDFs
\param [in] prefix the list of prefixes for the branch names
\param [in] iEvt the event number
*/
Double_t setSPlotNtupleBranchValues(LauPdfList* extraPdfs, const TString& prefix, UInt_t iEvt);
//! Update the signal events after Minuit sets background parameters
void updateSigEvents();
//! Add branches to store experiment number and the event number within the experiment
virtual void setupSPlotNtupleBranches();
//! Returns the names of all variables in the fit
virtual LauSPlot::NameSet variableNames() const;
//! Returns the names and yields of species that are free in the fit
virtual LauSPlot::NumbMap freeSpeciesNames() const;
//! Returns the names and yields of species that are fixed in the fit
virtual LauSPlot::NumbMap fixdSpeciesNames() const;
//! Returns the species and variables for all 2D PDFs in the fit
virtual LauSPlot::TwoDMap twodimPDFs() const;
//! Check if the signal is split into well-reconstructed and mis-reconstructed types
virtual Bool_t splitSignal() const {return this->useSCF();}
//! Check if the mis-reconstructed signal is to be smeared in the DP
virtual Bool_t scfDPSmear() const {return (scfMap_ != 0);}
//! 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!)
/*!
\param [in] inputData the fit data
*/
void appendBinCentres( LauFitDataTree* inputData );
private:
//! The signal Dalitz plot model
LauAbsDPDynamics* sigDPModel_;
//! The background Dalitz Plot model
LauBkgndDPModelList bkgndDPModels_;
//! The Dalitz plot kinematics object
LauKinematics *kinematics_;
//! The signal PDFs
LauPdfList signalPdfs_;
//! The SCF PDFs
LauPdfList scfPdfs_;
//! The background PDFs
LauBkgndPdfsList bkgndPdfs_;
//! Background boolean
Bool_t usingBkgnd_;
//! Number of signal components
UInt_t nSigComp_;
//! Number of signal DP parameters
UInt_t nSigDPPar_;
//! Number of extra PDF parameters
UInt_t nExtraPdfPar_;
//! Number of parameters
UInt_t nNormPar_;
//! Magnitudes and Phases
std::vector<LauAbsCoeffSet*> coeffPars_;
//! Fit fractions
LauParArray fitFrac_;
//! The mean efficiency
LauParameter meanEff_;
//! The average DP rate
LauParameter dpRate_;
//! Signal yield
LauParameter* signalEvents_;
//! Background yield(s)
LauBkgndYieldList bkgndEvents_;
//! Is the signal split into TM and SCF
Bool_t useSCF_;
//! Is the SCF fraction DP-dependent
Bool_t useSCFHist_;
//! The (global) SCF fraction parameter
LauParameter scfFrac_;
//! The histogram giving the DP-dependence of the SCF fraction
LauEffModel* scfFracHist_;
//! The smearing matrix for the SCF DP PDF
LauScfMap* scfMap_;
//! The cached values of the SCF fraction for each event
std::vector<Double_t> recoSCFFracs_;
//! The cached values of the SCF fraction for each bin centre
std::vector<Double_t> fakeSCFFracs_;
//! The cached values of the sqDP jacobians for each event
std::vector<Double_t> recoJacobians_;
//! The cached values of the sqDP jacobians for each true bin
std::vector<Double_t> fakeJacobians_;
//! Run choice variables
Bool_t compareFitData_;
//! The complex coefficients
std::vector<LauComplex> coeffs_;
// Embedding SP events
//! The signal event tree
LauEmbeddedData* signalTree_;
//! The background event tree
LauBkgndEmbDataList bkgndTree_;
//! Boolean to reuse signal events
Bool_t reuseSignal_;
//! Boolean to use reweighting
Bool_t useReweighting_;
//! Vector of booleans to reuse background events
LauBkgndReuseEventsList reuseBkgnd_;
//! Signal likelihood value
Double_t sigDPLike_;
//! SCF likelihood value
Double_t scfDPLike_;
//! Background likelihood value(s)
std::vector<Double_t> bkgndDPLike_;
//! Signal likelihood from extra PDFs
Double_t sigExtraLike_;
//! SCF likelihood from extra PDFs
Double_t scfExtraLike_;
//! Background likelihood value(s) from extra PDFs
std::vector<Double_t> bkgndExtraLike_;
//! Total signal likelihood
Double_t sigTotalLike_;
//! Total SCF likelihood
Double_t scfTotalLike_;
//! Total background likelihood(s)
std::vector<Double_t> bkgndTotalLike_;
ClassDef(LauSimpleFitModel,0) // Total fit/ToyMC model
};
#endif
diff --git a/src/LauAbsDPDynamics.cc b/src/LauAbsDPDynamics.cc
index b11057f..78b3bc6 100644
--- a/src/LauAbsDPDynamics.cc
+++ b/src/LauAbsDPDynamics.cc
@@ -1,159 +1,153 @@
-// Copyright University of Warwick 2005 - 2013.
+// Copyright University of Warwick 2005 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauAbsDPDynamics.cc
\brief File containing implementation of LauAbsDPDynamics class.
*/
#include <iostream>
using std::cout;
using std::cerr;
using std::endl;
#include "TSystem.h"
#include "LauAbsDPDynamics.hh"
#include "LauComplex.hh"
#include "LauDaughters.hh"
#include "LauEffModel.hh"
#include "LauKinematics.hh"
-#include "LauResonanceMaker.hh"
ClassImp(LauAbsDPDynamics)
LauAbsDPDynamics::LauAbsDPDynamics(LauDaughters* daughters, LauEffModel* effModel, LauEffModel* scfFractionModel) :
daughters_(daughters),
- resonanceMaker_(new LauResonanceMaker(daughters)),
kinematics_(daughters_ ? daughters_->getKinematics() : 0),
effModel_(effModel),
nAmp_(0),
- nResDefMax_(resonanceMaker_ ? resonanceMaker_->getNResDefMax() : 0),
DPNorm_(0.0),
DPRate_("DPRate", 0.0, 0.0, 1000.0),
meanDPEff_("meanDPEff", 0.0, 0.0, 1.0),
currentEvent_(0)
{
if (scfFractionModel != 0) {
scfFractionModel_[0] = scfFractionModel;
}
extraParameters_.clear();
}
LauAbsDPDynamics::LauAbsDPDynamics(LauDaughters* daughters, LauEffModel* effModel, const LauTagCatScfFractionModelMap& scfFractionModel) :
daughters_(daughters),
- resonanceMaker_(new LauResonanceMaker(daughters)),
kinematics_(daughters_ ? daughters_->getKinematics() : 0),
effModel_(effModel),
scfFractionModel_(scfFractionModel),
nAmp_(0),
- nResDefMax_(resonanceMaker_ ? resonanceMaker_->getNResDefMax() : 0),
DPNorm_(0.0),
DPRate_("DPRate", 0.0, 0.0, 1000.0),
meanDPEff_("meanDPEff", 0.0, 0.0, 1.0),
currentEvent_(0)
{
extraParameters_.clear();
}
LauAbsDPDynamics::~LauAbsDPDynamics()
{
- if (resonanceMaker_ != 0) {
- delete resonanceMaker_; resonanceMaker_ = 0;
- }
extraParameters_.clear();
for ( std::vector<LauCacheData*>::iterator iter = data_.begin(); iter != data_.end(); ++iter ) {
delete (*iter);
}
}
void LauAbsDPDynamics::setDataEventNo(UInt_t iEvt)
{
// Retrieve the data for event iEvt
if (data_.size() > iEvt) {
currentEvent_ = data_[iEvt];
} else {
cerr<<"ERROR in LauAbsDPDynamics::setDataEventNo : Event index too large: "<<iEvt<<" >= "<<data_.size()<<"."<<endl;
}
}
void LauAbsDPDynamics::updateCoeffs(const std::vector<LauComplex>& coeffs)
{
// Check that the number of coeffs is correct
if (coeffs.size() != this->getnAmp()) {
cerr << "ERROR in LauAbsDPDynamics::updateCoeffs : Expected " << this->getnAmp() << " but got " << coeffs.size() << endl;
gSystem->Exit(EXIT_FAILURE);
}
// Now check if the coeffs have changed
Bool_t changed = (Amp_ != coeffs);
if (changed) {
// Copy the coeffs
Amp_ = coeffs;
-
- // Update the total normalisation for the signal likelihood
- this->calcSigDPNorm();
}
+
+ // 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();
}
Bool_t LauAbsDPDynamics::hasResonance(const TString& resName) const
{
const LauAbsResonance* theRes = this->findResonance(resName);
if (theRes != 0) {
return kTRUE;
} else {
return kFALSE;
}
}
TString LauAbsDPDynamics::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 LauAbsDPDynamics::retrieveEfficiency()
{
Double_t eff(1.0);
if (effModel_ != 0) {
eff = effModel_->calcEfficiency(kinematics_);
}
return eff;
}
Double_t LauAbsDPDynamics::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 LauEffModel, 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/LauAbsFitModel.cc b/src/LauAbsFitModel.cc
index 6167ebc..b25937c 100644
--- a/src/LauAbsFitModel.cc
+++ b/src/LauAbsFitModel.cc
@@ -1,1168 +1,1186 @@
-// Copyright University of Warwick 2004 - 2013.
+// Copyright University of Warwick 2004 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauAbsFitModel.cc
\brief File containing implementation of LauAbsFitModel class.
*/
#include <iostream>
#include <limits>
#include <vector>
#include "TMessage.h"
#include "TMonitor.h"
#include "TServerSocket.h"
#include "TSocket.h"
#include "TSystem.h"
#include "TVectorD.h"
#include "TVirtualFitter.h"
#include "LauAbsFitModel.hh"
#include "LauAbsFitter.hh"
#include "LauAbsPdf.hh"
#include "LauComplex.hh"
#include "LauFitter.hh"
#include "LauFitDataTree.hh"
#include "LauFitNtuple.hh"
#include "LauGenNtuple.hh"
#include "LauParameter.hh"
#include "LauParamFixed.hh"
#include "LauPrint.hh"
#include "LauSPlot.hh"
ClassImp(LauAbsFitModel)
LauAbsFitModel::LauAbsFitModel() :
twoStageFit_(kFALSE),
useAsymmFitErrors_(kFALSE),
compareFitData_(kFALSE),
writeLatexTable_(kFALSE),
writeSPlotData_(kFALSE),
storeDPEff_(kFALSE),
randomFit_(kFALSE),
emlFit_(kFALSE),
poissonSmear_(kFALSE),
enableEmbedding_(kFALSE),
usingDP_(kTRUE),
pdfsDependOnDP_(kFALSE),
firstExpt_(0),
nExpt_(0),
evtsPerExpt_(0),
iExpt_(0),
inputFitData_(0),
fitNtuple_(0),
genNtuple_(0),
sPlotNtuple_(0),
fitStatus_(0),
NLL_(0),
numberOKFits_(0),
numberBadFits_(0),
nParams_(0),
nFreeParams_(0),
worstLogLike_(std::numeric_limits<Double_t>::max()),
withinAsymErrorCalc_(kFALSE),
nullString_(""),
doSFit_(kFALSE),
sWeightBranchName_(""),
sWeightScaleFactor_(1.0),
fitToyMCFileName_("fitToyMC.root"),
fitToyMCTableName_("fitToyMCTable"),
fitToyMCScale_(10),
fitToyMCPoissonSmear_(kFALSE),
sPlotFileName_(""),
sPlotTreeName_(""),
sPlotVerbosity_(""),
sMaster_(0),
messageFromMaster_(0),
slaveId_(-1),
nSlaves_(0),
parValues_(0)
{
}
LauAbsFitModel::~LauAbsFitModel()
{
delete inputFitData_; inputFitData_ = 0;
delete fitNtuple_; fitNtuple_ = 0;
delete genNtuple_; genNtuple_ = 0;
delete sPlotNtuple_; sPlotNtuple_ = 0;
delete sMaster_; sMaster_ = 0;
delete[] parValues_; parValues_ = 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("reweight")) {
this->weightEvents(dataFileNameCopy, dataTreeNameCopy);
}
}
void LauAbsFitModel::runSlave(const TString& dataFileName, const TString& dataTreeName,
const TString& histFileName, const TString& tableFileName,
const TString& addressMaster, const UInt_t portMaster)
{
if ( sMaster_ != 0 ) {
std::cerr << "ERROR in LauAbsFitModel::runSlave : 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_ );
delete messageFromMaster_;
messageFromMaster_ = 0;
std::cout << "INFO in LauAbsFitModel::runSlave : Established connection to master on port " << portMaster << std::endl;
std::cout << " : We are slave " << slaveId_ << " of " << nSlaves_ << std::endl;
// 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();
nParams_ = fitVars_.size();
parValues_ = new Double_t[nParams_];
for ( UInt_t iPar(0); iPar < nParams_; ++iPar ) {
parValues_[iPar] = fitVars_[iPar]->initValue();
}
TString dataFileNameCopy(dataFileName);
TString dataTreeNameCopy(dataTreeName);
TString histFileNameCopy(histFileName);
TString tableFileNameCopy(tableFileName);
if (dataFileNameCopy == "") {dataFileNameCopy = "data.root";}
if (dataTreeNameCopy == "") {dataTreeNameCopy = "genResults";}
if (histFileNameCopy == "") {histFileNameCopy = "parInfo.root";}
if (tableFileNameCopy == "") {tableFileNameCopy = "fitResults";}
this->fitSlave(dataFileNameCopy, dataTreeNameCopy, histFileNameCopy, tableFileNameCopy);
std::cout << "INFO in LauAbsFitModel::runSlave : Fit slave " << slaveId_ << " has finished successfully" << std::endl;
}
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<TString>& 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;
fitVars_.clear();
conVars_.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();
Bool_t genOK(kTRUE);
do {
// Loop over the number of experiments
for (iExpt_ = firstExpt_; iExpt_ < (firstExpt_+nExpt_); ++iExpt_) {
// Start the timer to see how long each experiment takes to generate
timer_.Start();
// Store the experiment number in the ntuple
this->setGenNtupleIntegerBranchValue("iExpt",iExpt_);
// Do the generation for this experiment
std::cout << "INFO in LauAbsFitModel::generate : Generating experiment number " << iExpt_ << 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 << "ERROR in LauAbsFitModel::generate : Problem in toy MC generation. Starting again with updated parameters..." << std::endl;
break;
}
if (this->writeLatexTable()) {
TString tableFileName(tableFileNameBase);
tableFileName += "_";
tableFileName += iExpt_;
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.
std::cout << "INFO in LauAbsFitModel::fit : First experiment = " << firstExpt_ << std::endl;
std::cout << "INFO in LauAbsFitModel::fit : Number of experiments = " << nExpt_ << std::endl;
// Start the cumulative timer
cumulTimer_.Start();
numberOKFits_ = 0, numberBadFits_ = 0;
fitStatus_ = -1;
// Create and setup the fit results ntuple
std::cout << "INFO in LauAbsFitModel::fit : Creating fit ntuple." << std::endl;
if (fitNtuple_ != 0) {delete fitNtuple_; fitNtuple_ = 0;}
fitNtuple_ = new LauFitNtuple(histFileName, this->useAsymmFitErrors());
// 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->cacheFitData(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 (iExpt_ = firstExpt_; iExpt_ < (firstExpt_+nExpt_); ++iExpt_) {
// Start the timer to see how long each fit takes
timer_.Start();
inputFitData_->readExperimentData(iExpt_);
this->eventsPerExpt(inputFitData_->nEvents());
if (this->eventsPerExpt() < 1) {
std::cerr << "ERROR in LauAbsFitModel::fit : Zero events in experiment " << iExpt_ << ", 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(tableFileNameBase);
// 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 for the 1st successful experiment
// using the fitted parameters so that the user can compare
// the fit to the actual data. The toy MC stats are a
// factor of 10 higher than the number of events specified
// via setNEvGen. This is to reduce the statistical
// fluctuations for the toy MC data.
if (compareFitData_ == kTRUE && fitStatus_ == 3) {
this->createFitToyMC(fitToyMCFileName_, fitToyMCTableName_);
compareFitData_ = kFALSE; // only do this for the first successful experiment
}
// Keep track of how many fits worked or failed
// NB values of fitStatus_ now 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_ == 3) {
numberOKFits_++;
} else {
numberBadFits_++;
}
} // 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.
std::cout << "INFO in LauAbsFitModel::fit : Number of OK Fits = " << numberOKFits_ << std::endl;
std::cout << "INFO in LauAbsFitModel::fit : Number of Failed Fits = " << numberBadFits_ << std::endl;
Double_t fitEff(0.0);
if (nExpt_ != 0) {fitEff = numberOKFits_/(1.0*nExpt_);}
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::fitSlave(const TString& dataFileName, const TString& dataTreeName, const TString& histFileName, const TString& tableFileNameBase)
{
// Create and setup the fit results ntuple
std::cout << "INFO in LauAbsFitModel::fitSlave : Creating fit ntuple." << std::endl;
if (fitNtuple_ != 0) {delete fitNtuple_; fitNtuple_ = 0;}
fitNtuple_ = new LauFitNtuple(histFileName, this->useAsymmFitErrors());
// 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->cacheFitData(dataFileName,dataTreeName);
if (!dataOK) {
std::cerr << "ERROR in LauAbsFitModel::fitSlave : Problem caching the fit data." << std::endl;
gSystem->Exit(EXIT_FAILURE);
}
// Now process the various requests from the master
TMessage messageToMaster(kMESS_ANY);
while ( kTRUE ) {
sMaster_->Recv( messageFromMaster_ );
if ( messageFromMaster_->What() == kMESS_STRING ) {
TString msgStr;
messageFromMaster_->ReadTString( msgStr );
std::cout << "INFO in LauAbsFitModel::fitSlave : Received message from master: " << msgStr << std::endl;
if ( msgStr == "Send Parameters" ) {
// Update initial fit parameters if required (e.g. if using random numbers).
this->checkInitFitParams();
// Send the fit parameters
TObjArray array;
for ( LauParameterPList::iterator iter = fitVars_.begin(); iter != fitVars_.end(); ++iter ) {
array.Add( *iter );
}
messageToMaster.Reset( kMESS_OBJECT );
messageToMaster.WriteObject( &array );
sMaster_->Send( messageToMaster );
} else if ( msgStr == "Read Expt" ) {
// Read the data for this experiment
messageFromMaster_->ReadUInt( iExpt_ );
inputFitData_->readExperimentData( iExpt_ );
UInt_t nEvent = inputFitData_->nEvents();
this->eventsPerExpt( nEvent );
if ( nEvent < 1 ) {
std::cerr << "ERROR in LauAbsFitModel::fitSlave : Zero events in experiment " << firstExpt_ << ", the master should skip this experiment..." << std::endl;
}
messageToMaster.Reset( kMESS_ANY );
messageToMaster.WriteUInt( slaveId_ );
messageToMaster.WriteUInt( nEvent );
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 == "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 LauAbsFitModel::fitSlave : Message from master to finish" << std::endl;
break;
} else {
std::cerr << "ERROR in LauAbsFitModel::fitSlave : Unexpected message from master" << std::endl;
gSystem->Exit( EXIT_FAILURE );
}
} else if ( messageFromMaster_->What() == kMESS_OBJECT ) {
std::cout << "INFO in LauAbsFitModel::fitSlave : Received message from master: Finalise" << std::endl;
messageFromMaster_->ReadInt( fitStatus_ );
messageFromMaster_->ReadDouble( NLL_ );
TObjArray * objarray = dynamic_cast<TObjArray*>( messageFromMaster_->ReadObject( messageFromMaster_->GetClass() ) );
if ( ! objarray ) {
std::cerr << "ERROR in LauAbsFitModel::fitSlave : Error reading parameters from master" << std::endl;
gSystem->Exit( EXIT_FAILURE );
}
TMatrixD * covMat = dynamic_cast<TMatrixD*>( messageFromMaster_->ReadObject( messageFromMaster_->GetClass() ) );
if ( ! covMat ) {
std::cerr << "ERROR in LauAbsFitModel::fitSlave : Error reading covariance matrix from master" << std::endl;
gSystem->Exit( EXIT_FAILURE );
}
covMatrix_.Clear();
covMatrix_.ResizeTo( covMat->GetNrows(), covMat->GetNcols() );
covMatrix_.SetMatrixArray( covMat->GetMatrixArray() );
delete covMat; covMat = 0;
UInt_t nPars = objarray->GetEntries();
if ( nPars != nParams_ ) {
std::cerr << "ERROR in LauAbsFitModel::fitSlave : Unexpected number of parameters received from master" << std::endl;
std::cerr << " ::fitSlave : Received " << nPars << " when expecting " << nParams_ << std::endl;
gSystem->Exit( EXIT_FAILURE );
}
for ( UInt_t iPar(0); iPar < nPars; ++iPar ) {
LauParameter* parameter = dynamic_cast<LauParameter*>( (*objarray)[iPar] );
if ( ! parameter ) {
std::cerr << "ERROR in LauAbsFitModel::fitSlave : Error reading parameter from master" << std::endl;
gSystem->Exit( EXIT_FAILURE );
}
if ( parameter->name() != fitVars_[iPar]->name() ) {
std::cerr << "ERROR in LauAbsFitModel::fitSlave : Error reading parameter from master" << std::endl;
gSystem->Exit( EXIT_FAILURE );
}
*(fitVars_[iPar]) = *parameter;
}
this->finaliseFitResults( tableFileNameBase );
// Send the finalised parameters
TObjArray array;
for ( LauParameterPList::iterator iter = fitVars_.begin(); iter != fitVars_.end(); ++iter ) {
array.Add( *iter );
}
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);
messageFromMaster_->ReadUInt( nPars );
if ( nPars != nParams_ ) {
std::cerr << "ERROR in LauAbsFitModel::fitSlave : Unexpected number of parameters received from master" << std::endl;
std::cerr << " ::fitSlave : Received " << nPars << " when expecting " << nParams_ << std::endl;
gSystem->Exit( EXIT_FAILURE );
}
messageFromMaster_->ReadFastArray( parValues_, nPars );
for ( UInt_t iPar(0); iPar < nPars; ++iPar ) {
if ( ! fitVars_[iPar]->fixed() ) {
fitVars_[iPar]->value( parValues_[iPar] );
}
}
this->propagateParUpdates();
Double_t negLogLike = this->getTotNegLogLikelihood();
messageToMaster.Reset( kMESS_ANY );
messageToMaster.WriteDouble( negLogLike );
sMaster_->Send( messageToMaster );
} else {
std::cerr << "ERROR in LauAbsFitModel::fitSlave : Unexpected message type" << std::endl;
gSystem->Exit( EXIT_FAILURE );
}
delete messageFromMaster_;
messageFromMaster_ = 0;
}
}
Bool_t LauAbsFitModel::cacheFitData(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
// Reset the worst likelihood found to its catch-all value
worstLogLike_ = std::numeric_limits<Double_t>::max();
// 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_ );
nParams_ = LauFitter::fitter()->nParameters();
nFreeParams_ = LauFitter::fitter()->nFreeParameters();
// Now ready for minimisation step
std::cout << "\nINFO in LauAbsFitModel::fitExpt : Start minimisation...\n";
std::pair<Int_t,Double_t> fitResult = LauFitter::fitter()->minimise();
fitStatus_ = fitResult.first;
NLL_ = fitResult.second;
// 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 ( fitStatus_ != 3 ) {
std::cerr << "ERROR in LauAbsFitModel:fitExpt : Not running second stage fit since first stage failed." << std::endl;
LauFitter::fitter()->releaseSecondStageParameters();
} else {
LauFitter::fitter()->fixFirstStageParameters();
LauFitter::fitter()->releaseSecondStageParameters();
nParams_ = LauFitter::fitter()->nParameters();
nFreeParams_ = LauFitter::fitter()->nFreeParameters();
fitResult = LauFitter::fitter()->minimise();
}
}
fitStatus_ = fitResult.first;
NLL_ = fitResult.second;
const TMatrixD& covMat = LauFitter::fitter()->covarianceMatrix();
covMatrix_.Clear();
covMatrix_.ResizeTo( covMat.GetNrows(), covMat.GetNcols() );
covMatrix_.SetMatrixArray( covMat.GetMatrixArray() );
// 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();
LauFitter::fitter()->releaseFirstStageParameters();
}
void LauAbsFitModel::writeOutAllFitResults()
{
// Write out histograms at end
if (fitNtuple_ != 0) {
fitNtuple_->writeOutFitResults();
}
}
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 eventually
// 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
UInt_t oldNExpt(this->nExpt());
UInt_t oldFirstExpt(this->firstExpt());
UInt_t oldIExpt(iExpt_);
// Turn off Poisson smearing if required
Bool_t poissonSmearing(this->doPoissonSmearing());
this->doPoissonSmearing(fitToyMCPoissonSmear_);
// Turn off embedding, since we need toy MC, not reco'ed events
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
Bool_t origUseDP = this->useDP();
if ( this->pdfsDependOnDP() && !origUseDP ) {
this->useDP( kTRUE );
this->initialiseDPModels();
}
// Generate the toy MC
std::cout << "INFO in LauAbsFitModel::createFitToyMC : Generating toy MC in " << mcFileName << " to compare fit with data..." << std::endl;
std::cout << " : Number of experiments to generate = " << this->nExpt() << ", which is a factor of " <<fitToyMCScale_ << " higher than that originally specified." << 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<Double_t> origGenValues; origGenValues.reserve(nParams_);
for (LauParameterPList::iterator iter = fitVars_.begin(); iter != fitVars_.end(); ++iter) {
origGenValues.push_back((*iter)->genValue());
(*iter)->genValue((*iter)->value());
}
// 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
UInt_t totalExpts = oldNExpt * fitToyMCScale_;
if ( totalExpts > 100 ) {
UInt_t nFiles = totalExpts/100;
if ( totalExpts%100 ) {
nFiles += 1;
}
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
TString extraname = "_file";
extraname += iFile;
TString filename(mcFileName);
filename.Insert( filename.Index("."), extraname );
this->generate(filename, "genResults", "dummy.root", tableFileName);
}
} else {
// Set number of experiments to new value
this->setNExpts(oldNExpt*fitToyMCScale_, 0);
// Generate the toy
this->generate(mcFileName, "genResults", "dummy.root", tableFileName);
}
// Reset number of experiments to original value
iExpt_ = oldIExpt;
this->setNExpts(oldNExpt, oldFirstExpt);
// 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); i<nParams_; ++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 ( LauParameterPList::const_iterator iter = conVars_.begin(); iter != conVars_.end(); ++iter ) {
Double_t val = (*iter)->value();
Double_t mean = (*iter)->constraintMean();
Double_t width = (*iter)->constraintWidth();
Double_t term = ( val - mean ) / width;
penalty += term*term;
}
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);
// 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 > DBL_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 = worstLogLike_;
} else if (logLike < worstLogLike_) {
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 ( ! withinAsymErrorCalc_ ) {
if (static_cast<UInt_t>(npar) != nFreeParams_) {
std::cerr << "ERROR in LauAbsFitModel::setParsFromMinuit : Unexpected number of free parameters: " << npar << ".\n";
std::cerr << " Expected: " << nFreeParams_ << ".\n" << std::endl;
gSystem->Exit(EXIT_FAILURE);
}
}
+ Bool_t recalcNorm(kFALSE);
+
// 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); i<nParams_; ++i) {
if (!fitVars_[i]->fixed()) {
+ std::cout << "par["<< i << "] = " << par[i] << std::endl;
+ std::cout << "fitVars_[" << i << "]->value() = " << fitVars_[i]->value() << std::endl;
+ std::cout << "name = " << fitVars_[i]->name() << std::endl;
+
+ // TODO - obviously we want a way that does not involve string comparisons here
+ if (fitVars_[i]->name().Contains("_MASS")||fitVars_[i]->name().Contains("_WIDTH")){
+ std::cout << "they are mass or width" << std::endl;
+ if ( par[i] != fitVars_[i]->value() ) {
+ std::cout << "they are different" << std::endl;
+ recalcNorm = kTRUE;
+ }
+ }
fitVars_[i]->value(par[i]);
}
}
+ 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 );
}
LauParameterPList& pars = pdf->getParameters();
for (LauParameterPList::iterator pars_iter = pars.begin(); pars_iter != pars.end(); ++pars_iter) {
if ( !(*pars_iter)->clone() && ( !(*pars_iter)->fixed() ||
(this->twoStageFit() && ( (*pars_iter)->secondStage() || (*pars_iter)->firstStage())) ) ) {
fitVars_.push_back(*pars_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;
}
}
}
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 LauParameterPList& pars = (*pdf_iter)->getParameters();
for (LauParameterPList::const_iterator pars_iter = pars.begin(); pars_iter != pars.end(); ++pars_iter) {
if (!(*pars_iter)->clone()) {
fout << (*pars_iter)->name() << " & $";
print.printFormat(fout, (*pars_iter)->value());
if ((*pars_iter)->fixed() == kTRUE) {
fout << "$ (fixed) \\\\";
} else {
fout << " \\pm ";
print.printFormat(fout, (*pars_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); i<nParams_; ++i) {
std::cerr << " " << (fitVars_[i]->name()).Data() << " = " << fitVars_[i]->value() << std::endl;
}
}
diff --git a/src/LauAbsResonance.cc b/src/LauAbsResonance.cc
index 28ab774..20b1bbe 100644
--- a/src/LauAbsResonance.cc
+++ b/src/LauAbsResonance.cc
@@ -1,374 +1,367 @@
-// Copyright University of Warwick 2004 - 2013.
+// Copyright University of Warwick 2004 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauAbsResonance.cc
\brief File containing implementation of LauAbsResonance class.
*/
-//****************************************************************************
-// Abstract class for defining resonance models (Breit-Wigner, Flatte etc.)
-//****************************************************************************
-
-// --CLASS DESCRIPTION [MODEL] --
-// Abstract class for defining resonance models (Breit-Wigner, Flatte etc.)
-
#include <iostream>
-using std::cout;
-using std::cerr;
-using std::endl;
#include "TSystem.h"
#include "LauAbsResonance.hh"
#include "LauConstants.hh"
#include "LauDaughters.hh"
#include "LauKinematics.hh"
+#include "LauParameter.hh"
ClassImp(LauAbsResonance)
- // Constructor
- LauAbsResonance::LauAbsResonance(const TString& resName, Double_t resMass, Double_t resWidth, Int_t resSpin,
- Int_t resCharge, Int_t resPairAmpInt, const LauDaughters* daughters) :
- 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),
- resMass_(resMass),
- resWidth_(resWidth),
- resSpin_(resSpin),
- resCharge_(resCharge),
- resPairAmpInt_(resPairAmpInt),
- flipHelicity_(kFALSE),
- ignoreMomenta_(kFALSE),
- q_(0.0),
- p_(0.0),
- pstar_(0.0)
+// Constructor
+LauAbsResonance::LauAbsResonance(const TString& resName, LauParameter* resMass, LauParameter* resWidth, Int_t resSpin,
+ Int_t resCharge, Int_t resPairAmpInt, const LauDaughters* daughters) :
+ 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),
+ resMass_(resMass),
+ resWidth_(resWidth),
+ resSpin_(resSpin),
+ resCharge_(resCharge),
+ resPairAmpInt_(resPairAmpInt),
+ flipHelicity_(kFALSE),
+ ignoreMomenta_(kFALSE),
+ q_(0.0),
+ p_(0.0),
+ pstar_(0.0)
{
if (daughters_) {
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();
} else {
- cerr<<"ERROR in LauAbsResonance : daughters_ pointer is NULL."<<endl;
+ std::cerr << "ERROR in LauAbsResonance : daughters_ pointer is NULL." << std::endl;
}
// check that the total charge adds up to that of the resonance
Int_t totalCharge = chargeDaug1_ + chargeDaug2_;
if ( (totalCharge != resCharge_) && (resName != "NonReson") && (!resName.BeginsWith("BelleNR")) ) {
- cerr<<"ERROR in LauAbsResonance : "
- <<"Total charge of daughters = "<<totalCharge<<". Resonance charge = "<<resCharge_<<"."<<endl;
+ std::cerr << "ERROR in LauAbsResonance : Total charge of daughters = " << totalCharge << ". Resonance charge = " << resCharge_ << "." << std::endl;
gSystem->Exit(EXIT_FAILURE);
}
+
+ resParameters_.push_back( resMass_ );
+ resParameters_.push_back( resWidth_ );
}
// Destructor
LauAbsResonance::~LauAbsResonance()
{
}
LauComplex LauAbsResonance::amplitude(const LauKinematics* kinematics)
{
// Use LauKinematics interface for amplitude
Double_t mass(0.0), cosHel(0.0);
// 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.
q_ = 0.0; p_ = 0.0; pstar_ = 0.0;
if (resPairAmpInt_ == 1) {
mass = kinematics->getm23();
cosHel = kinematics->getc23();
q_ = kinematics->getp2_23();
p_ = kinematics->getp1_23();
pstar_ = kinematics->getp1_Parent();
} else if (resPairAmpInt_ == 2) {
mass = kinematics->getm13();
cosHel = kinematics->getc13();
q_ = kinematics->getp1_13();
p_ = kinematics->getp2_13();
pstar_ = kinematics->getp2_Parent();
} else if (resPairAmpInt_ == 3) {
mass = kinematics->getm12();
cosHel = kinematics->getc12();
q_ = kinematics->getp1_12();
p_ = kinematics->getp3_12();
pstar_ = kinematics->getp3_Parent();
} else {
- cerr<<"Nonsense setup of resPairAmp array."<<endl;
+ std::cerr << "ERROR in LauAbsResonance::amplitude : Nonsense setup of resPairAmp array." << std::endl;
}
if (this->flipHelicity()) {
cosHel *= -1.0;
}
if (this->ignoreMomenta()) {
- q_ = 1;
- p_ = 1;
+ q_ = 1.0;
+ p_ = 1.0;
}
Double_t spinTerm(1.0);
if (resSpin_ == 1) {
// Calculate vector resonance Zemach helicity factor
spinTerm = -2.0*q_*p_*cosHel;
} else if (resSpin_ == 2) {
// Calculate tensor resonance Zemach helicity factor
Double_t pProd = q_*p_;
spinTerm = 4.0*(pProd*pProd)*(3.0*cosHel*cosHel - 1.0)/3.0;
} else if (resSpin_ == 3) {
// Calculate spin 3 resonance Zemach helicity factor
Double_t pProd = q_*p_;
spinTerm = -8.0*3.0*(pProd*pProd*pProd)*(5.0*cosHel*cosHel*cosHel - 3.0*cosHel)/15.0;
}
LauComplex resAmplitude = this->resAmp(mass, spinTerm);
return resAmplitude;
}
void LauAbsResonance::changeResonance(Double_t newMass, Double_t newWidth, Int_t newSpin)
{
if (newMass > 0.0) {
- resMass_ = newMass;
- cout << "Setting mass to " << resMass_ << endl;
+ resMass_->value(newMass);
+ std::cout << "INFO in LauAbsResonance::changeResonance : Setting mass to " << resMass_->value() << std::endl;
}
if (newWidth > 0.0) {
- resWidth_ = newWidth;
- cout << "Setting width to " << resWidth_ << endl;
+ resWidth_->value(newWidth);
+ std::cout << "INFO in LauAbsResonance::changeResonance : Setting width to " << resWidth_->value() << std::endl;
}
if (newSpin > -1) {
resSpin_ = newSpin;
- cout << "Setting spin to " << resSpin_ << endl;
+ std::cout << "INFO in LauAbsResonance::changeResonance : Setting spin to " << resSpin_ << std::endl;
}
this->initialise();
}
void LauAbsResonance::setResonanceParameter(Double_t value, const TString& name)
{
//This function should always be overwritten if needed in classes inheriting from LauAbsResonance.
- cerr << "WARNING in LauAbsResonance::setResonanceParameter : Unable to set parameter \"" << name << "\" to value: " << value << "." << endl;
+ std::cerr << "WARNING in LauAbsResonance::setResonanceParameter : Unable to set parameter \"" << name << "\" to value: " << value << "." << std::endl;
}
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/LauBelleNR.cc b/src/LauBelleNR.cc
index 50f2ddf..a12be39 100644
--- a/src/LauBelleNR.cc
+++ b/src/LauBelleNR.cc
@@ -1,53 +1,53 @@
-// Copyright University of Warwick 2004 - 2013.
+// Copyright University of Warwick 2004 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauBelleNR.cc
\brief File containing implementation of LauBelleNR class.
*/
#include <iostream>
#include "TMath.h"
#include "LauBelleNR.hh"
#include "LauDaughters.hh"
ClassImp(LauBelleNR)
-LauBelleNR::LauBelleNR(const TString& resName, Double_t resMass, Double_t resWidth, Int_t resSpin,
+LauBelleNR::LauBelleNR(const TString& resName, LauParameter* resMass, LauParameter* resWidth, Int_t resSpin,
Int_t resCharge, Int_t resPairAmpInt, const LauDaughters* daughters) :
LauAbsResonance(resName, resMass, resWidth, resSpin, resCharge, resPairAmpInt, daughters),
alpha_(0.0)
{
}
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;
}
}
LauComplex LauBelleNR::resAmp(Double_t mass, Double_t spinTerm)
{
Double_t magnitude = spinTerm * TMath::Exp(-alpha_*mass*mass);
LauComplex resAmplitude(magnitude, 0.0);
return resAmplitude;
}
diff --git a/src/LauBelleSymNR.cc b/src/LauBelleSymNR.cc
index 944bc1e..2eb3300 100644
--- a/src/LauBelleSymNR.cc
+++ b/src/LauBelleSymNR.cc
@@ -1,109 +1,109 @@
-// Copyright University of Warwick 2004 - 2013.
+// Copyright University of Warwick 2004 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauBelleSymNR.cc
\brief File containing implementation of LauBelleSymNR class.
*/
#include <iostream>
using std::cout;
using std::cerr;
using std::endl;
#include "TMath.h"
#include "LauBelleSymNR.hh"
#include "LauKinematics.hh"
ClassImp(LauBelleSymNR)
-LauBelleSymNR::LauBelleSymNR(const TString& resName, Double_t resMass, Double_t resWidth, Int_t resSpin,
+LauBelleSymNR::LauBelleSymNR(const TString& resName, LauParameter* resMass, LauParameter* resWidth, Int_t resSpin,
Int_t resCharge, Int_t resPairAmpInt, const LauDaughters* daughters) :
LauAbsResonance(resName, resMass, resWidth, resSpin, resCharge, resPairAmpInt, daughters),
alpha_(0.0),
initialised_(kFALSE),
shapeNo_(0)
{
}
LauBelleSymNR::~LauBelleSymNR()
{
// Destructor
}
void LauBelleSymNR::initialise(Bool_t symmetricalDP, Double_t alpha, const TString& shape)
{
alpha_ = alpha;
shapeNo_ = 0;
if (symmetricalDP == kFALSE) {
cerr << "ERROR in LauBelleSymNR::initialise : Dalitz plot is not symmetric - this lineshape is not appropriate." << endl;
return;
}
if (shape == "BelleSymNR") {
cout << "Initialising the Belle non-resonant model with alpha = " << alpha << endl;
shapeNo_ = 1;
} else if (shape == "NRTaylor") {
cout << "Initialising the Taylor expansion non-resonant model with alpha = " << alpha << endl;
shapeNo_ = 2;
} else {
cerr << "ERROR in LauBelleSymNR::initialise : Non-resonant parameterisation not recognised." << endl;
return;
}
initialised_ = kTRUE;
}
LauComplex LauBelleSymNR::amplitude(const LauKinematics* kinematics)
{
if (initialised_ == kFALSE) {
cerr<<"ERROR in LauBelleSymNR::amplitude : LauBelleSymNR is not initialised. Returning zero amplitude."<<endl;
return LauComplex(0.0, 0.0);
}
// 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, u = m_12^2.
Double_t s = kinematics->getm13Sq();
Double_t t = kinematics->getm23Sq();
//Double_t u = kinematics->getm12Sq();
Double_t magnitude(1.0);
if (shapeNo_ == 1) {
magnitude = TMath::Exp(-alpha_*s) + TMath::Exp(-alpha_*t);
} else if (shapeNo_ == 2) {
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)
{
cerr << "ERROR in LauBelleSymNR : This method should never be called." << endl;
cerr << " : Returning zero amplitude for mass = " << mass << " and spinTerm = " << spinTerm << "." << endl;
return LauComplex(0.0, 0.0);
}
diff --git a/src/LauBreitWignerRes.cc b/src/LauBreitWignerRes.cc
index 04d01f3..112081c 100644
--- a/src/LauBreitWignerRes.cc
+++ b/src/LauBreitWignerRes.cc
@@ -1,58 +1,51 @@
-// Copyright University of Warwick 2004 - 2013.
+// Copyright University of Warwick 2004 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauBreitWignerRes.cc
\brief File containing implementation of LauBreitWignerRes class.
*/
-//****************************************************************************
-// Class for defining the Breit-Wigner resonance model
-//****************************************************************************
-
-// --CLASS DESCRIPTION [MODEL] --
-// Class for defining the Breit-Wigner resonance model
-
#include "LauBreitWignerRes.hh"
ClassImp(LauBreitWignerRes)
-LauBreitWignerRes::LauBreitWignerRes(TString resName, Double_t resMass, Double_t resWidth, Int_t resSpin,
+LauBreitWignerRes::LauBreitWignerRes(TString resName, LauParameter* resMass, LauParameter* resWidth, Int_t resSpin,
Int_t resCharge, Int_t resPairAmpInt, const LauDaughters* daughters) :
LauAbsResonance(resName, resMass, resWidth, resSpin, resCharge, 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;
}
diff --git a/src/LauCPFitModel.cc b/src/LauCPFitModel.cc
index e45220c..be9d3ce 100644
--- a/src/LauCPFitModel.cc
+++ b/src/LauCPFitModel.cc
@@ -1,2810 +1,2833 @@
-// Copyright University of Warwick 2004 - 2013.
+// Copyright University of Warwick 2004 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauCPFitModel.cc
\brief File containing implementation of LauCPFitModel class.
*/
#include <iostream>
#include <iomanip>
#include <fstream>
#include <vector>
#include "TVirtualFitter.h"
#include "TSystem.h"
#include "TMinuit.h"
#include "TRandom.h"
#include "TFile.h"
#include "TMath.h"
#include "TH2.h"
#include "LauAbsBkgndDPModel.hh"
#include "LauAbsCoeffSet.hh"
#include "LauAbsDPDynamics.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 "LauKinematics.hh"
#include "LauPrint.hh"
#include "LauRandom.hh"
+#include "LauResonanceMaker.hh"
#include "LauScfMap.hh"
ClassImp(LauCPFitModel)
LauCPFitModel::LauCPFitModel(LauAbsDPDynamics* negModel, LauAbsDPDynamics* 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)
{
LauDaughters* negDaug = negSigModel_->getDaughters();
if (negDaug != 0) {negParent_ = negDaug->getNameParent();}
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( LauParameter* 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;
}
bkgndEvents_[bkgndID] = nBkgndEvents;
bkgndEvents_[bkgndID]->name( nBkgndEvents->name()+"Events" );
Double_t value = nBkgndEvents->value();
bkgndEvents_[bkgndID]->range(-2.0*(TMath::Abs(value)+1.0), 2.0*(TMath::Abs(value)+1.0));
bkgndAsym_[bkgndID] = new LauParameter(nBkgndEvents->name()+"Asym",0.0,-1.0,1.0,kTRUE);
}
void LauCPFitModel::setNBkgndEvents(LauParameter* nBkgndEvents, LauParameter* 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;
}
bkgndEvents_[bkgndID] = nBkgndEvents;
bkgndEvents_[bkgndID]->name( nBkgndEvents->name()+"Events" );
Double_t value = nBkgndEvents->value();
bkgndEvents_[bkgndID]->range(-2.0*(TMath::Abs(value)+1.0), 2.0*(TMath::Abs(value)+1.0));
bkgndAsym_[bkgndID] = bkgndAsym;
bkgndAsym_[bkgndID]->name( nBkgndEvents->name()+"Asym" );
bkgndAsym_[bkgndID]->range(-1.0,1.0);
}
void LauCPFitModel::splitSignalComponent( const TH2* dpHisto, Bool_t upperHalf, 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;
}
LauDaughters* daughters = negSigModel_->getDaughters();
scfFracHist_ = new LauEffModel( daughters, 0 );
scfFracHist_->setEffHisto( dpHisto, kTRUE, kFALSE, 0.0, 0.0, upperHalf, daughters->squareDP() );
scfMap_ = scfMap;
useSCF_ = kTRUE;
useSCFHist_ = kTRUE;
}
void LauCPFitModel::splitSignalComponent( Double_t scfFrac, 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)
{
// Is there a component called compName in the signal model?
TString compName(coeffSet->name());
Bool_t negOK = negSigModel_->hasResonance(compName);
TString conjName = negSigModel_->getConjResName(compName);
Bool_t posOK = posSigModel_->hasResonance(conjName);
if (!negOK) {
std::cerr << "ERROR in LauCPFitModel::setMagPhase : " << negParent_ << " signal DP model doesn't contain component \"" << compName << "\"." << std::endl;
return;
}
if (!posOK) {
std::cerr << "ERROR in LauCPFitModel::setMagPhase : " << posParent_ << " signal DP model doesn't contain component \"" << conjName << "\"." << std::endl;
return;
}
// Do we already have it in our list of names?
for (std::vector<LauAbsCoeffSet*>::const_iterator iter=coeffPars_.begin(); iter!=coeffPars_.end(); ++iter) {
if ((*iter)->name() == compName) {
std::cerr << "ERROR in LauCPFitModel::setAmpCoeffSet : Have already set coefficients for \"" << compName << "\"." << std::endl;
return;
}
}
coeffSet->index(nSigComp_);
coeffPars_.push_back(coeffSet);
TString parName = coeffSet->baseName(); parName += "FitFracAsym";
fitFracAsymm_.push_back(LauParameter(parName, 0.0, -1.0, 1.0));
acp_.push_back(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()
{
// First of all check that, if a given component is being used,
// we've got the PDFs for all the variables involved
if ( this->useDP() ) {
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;
}
}
}
}
// 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<TString> varNames = (*pdf_iter)->varNames();
for ( std::vector<TString>::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<TString> varNames = (*pdf_iter)->varNames();
for ( std::vector<TString>::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<TString> varNames = (*pdf_iter)->varNames();
for ( std::vector<TString>::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);
}
// From the initial parameter values calculate the coefficients
// so they can be passed to the signal model
this->updateCoeffs();
// Initialisation
if (this->useDP() == kTRUE) {
this->initialiseDPModels();
}
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);
}
this->setExtraNtupleVars();
}
+void LauCPFitModel::recalculateNormalisation()
+{
+ std::cout << "INFO in LauCPFitModel::recalculateNormalizationInDPModels : Recalc Norm in DP model" << std::endl;
+ negSigModel_->recalculateNormalisation();
+ posSigModel_->recalculateNormalisation();
+ LauFitDataTree* inputFitData = this->fitData();
+ negSigModel_->fillDataTree(*inputFitData);
+ posSigModel_->fillDataTree(*inputFitData);
+}
+
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;
// Need to check that the number of components we have and that the dynamics has matches up
UInt_t nNegAmp = negSigModel_->getnAmp();
UInt_t nPosAmp = posSigModel_->getnAmp();
if ( nNegAmp != nPosAmp ) {
std::cerr << "ERROR in LauCPFitModel::setSignalDPParameters : 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::setSignalDPParameters : Number of signal DP components in the model (" << nNegAmp << ") not equal to number of coefficients supplied (" << nSigComp_ << ")." << std::endl;
gSystem->Exit(EXIT_FAILURE);
}
// Place signal model 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_;
}
}
}
+
+ // get the resonance maker factory
+ LauResonanceMaker& resonanceMaker = LauResonanceMaker::get();
+
+ //Obtain the Resonance Parameters
+ std::vector<LauParameter*> resPars = resonanceMaker.getFloatingParameters();
+ for (LauParameterPList::iterator iter = resPars.begin(); iter != resPars.end(); ++iter) {
+ if ( !(*iter)->clone() ) {
+ 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
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) {
fitVars.push_back(signalAsym_);
++nNormPar_;
}
if (useSCF_ && !useSCFHist_) {
fitVars.push_back(&scfFrac_);
++nNormPar_;
}
if (usingBkgnd_ == kTRUE) {
for (LauBkgndYieldList::iterator iter = bkgndEvents_.begin(); iter != bkgndEvents_.end(); ++iter) {
LauParameter* parameter = (*iter);
fitVars.push_back(parameter);
++nNormPar_;
}
for (LauBkgndYieldList::iterator iter = bkgndAsym_.begin(); iter != bkgndAsym_.end(); ++iter) {
LauParameter* parameter = (*iter);
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();
// 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); i<nSigComp_; ++i) {
if (negFitFrac_[i].size() != nSigComp_) {
std::cerr << "ERROR in LauCPFitModel::setExtraNtupleVars : Initial Fit Fraction array of unexpected dimension: " << negFitFrac_[i].size() << std::endl;
gSystem->Exit(EXIT_FAILURE);
}
}
LauParameterList& extraVars = this->extraPars();
for (UInt_t i(0); i<nSigComp_; ++i) {
for (UInt_t j(i); j<nSigComp_; ++j) {
TString name = negFitFrac_[i][j].name();
name.Insert( name.Index("FitFrac"), "Neg" );
negFitFrac_[i][j].name(name);
extraVars.push_back(negFitFrac_[i][j]);
}
}
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); i<nSigComp_; ++i) {
if (posFitFrac_[i].size() != nSigComp_) {
std::cerr << "ERROR in LauCPFitModel::setExtraNtupleVars : Initial Fit Fraction array of unexpected dimension: " << posFitFrac_[i].size() << std::endl;
gSystem->Exit(EXIT_FAILURE);
}
}
for (UInt_t i(0); i<nSigComp_; ++i) {
for (UInt_t j(i); j<nSigComp_; ++j) {
TString name = posFitFrac_[i][j].name();
name.Insert( name.Index("FitFrac"), "Pos" );
posFitFrac_[i][j].name(name);
extraVars.push_back(posFitFrac_[i][j]);
}
}
// Store any extra parameters/quantities from the DP model (e.g. K-matrix total fit fractions)
std::vector<LauParameter> negExtraPars = negSigModel_->getExtraParameters();
std::vector<LauParameter>::iterator negExtraIter;
for (negExtraIter = negExtraPars.begin(); negExtraIter != negExtraPars.end(); ++negExtraIter) {
LauParameter negExtraParameter = (*negExtraIter);
extraVars.push_back(negExtraParameter);
}
std::vector<LauParameter> posExtraPars = posSigModel_->getExtraParameters();
std::vector<LauParameter>::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); i<nSigComp_; ++i) {
CPCFitFrac_[i].resize(nSigComp_);
CPVFitFrac_[i].resize(nSigComp_);
for (UInt_t j(i); j<nSigComp_; ++j) {
TString name = negFitFrac_[i][j].name();
name.Replace( name.Index("Neg"), 3, "CPC" );
CPCFitFrac_[i][j].name( name );
CPCFitFrac_[i][j].valueAndRange( 0.0, -100.0, 100.0 );
name = negFitFrac_[i][j].name();
name.Replace( name.Index("Neg"), 3, "CPV" );
CPVFitFrac_[i][j].name( name );
CPVFitFrac_[i][j].valueAndRange( 0.0, -100.0, 100.0 );
}
}
}
Double_t denom = negDPRate_ + posDPRate_;
for (UInt_t i(0); i<nSigComp_; ++i) {
for (UInt_t j(i); j<nSigComp_; ++j) {
Double_t negTerm = negFitFrac_[i][j]*negDPRate_;
Double_t posTerm = posFitFrac_[i][j]*posDPRate_;
Double_t cpcFitFrac = (negTerm + posTerm)/denom;
Double_t cpvFitFrac = (negTerm - posTerm)/denom;
CPCFitFrac_[i][j] = cpcFitFrac;
CPVFitFrac_[i][j] = cpvFitFrac;
if (initValues) {
CPCFitFrac_[i][j].genValue(cpcFitFrac);
CPCFitFrac_[i][j].initValue(cpcFitFrac);
CPVFitFrac_[i][j].genValue(cpvFitFrac);
CPVFitFrac_[i][j].initValue(cpvFitFrac);
}
}
}
}
void LauCPFitModel::calcAsymmetries(Bool_t initValues)
{
// Calculate the CP asymmetries
// Also calculate the fit fraction asymmetries
for (UInt_t i = 0; i < nSigComp_; i++) {
acp_[i] = coeffPars_[i]->acp();
LauAsymmCalc asymmCalc(negFitFrac_[i][i].value(), posFitFrac_[i][i].value());
Double_t asym = asymmCalc.getAsymmetry();
fitFracAsymm_[i] = 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) {
(*iter)->updatePull();
}
for (LauBkgndYieldList::iterator iter = bkgndAsym_.begin(); iter != bkgndAsym_.end(); ++iter) {
(*iter)->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); i<nSigComp_; ++i) {
if (negFitFrac[i].size() != nSigComp_) {
std::cerr << "ERROR in LauCPFitModel::finaliseFitResults : Fit Fraction array of unexpected dimension: " << negFitFrac[i].size() << std::endl;
gSystem->Exit(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); i<nSigComp_; ++i) {
if (posFitFrac[i].size() != nSigComp_) {
std::cerr << "ERROR in LauCPFitModel::finaliseFitResults : Fit Fraction array of unexpected dimension: " << posFitFrac[i].size() << std::endl;
gSystem->Exit(EXIT_FAILURE);
}
}
for (UInt_t i(0); i<nSigComp_; ++i) {
for (UInt_t j(i); j<nSigComp_; ++j) {
negFitFrac_[i][j].value(negFitFrac[i][j].value());
posFitFrac_[i][j].value(posFitFrac[i][j].value());
}
}
negMeanEff_.value(negSigModel_->getMeanEff().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<nSigComp_; ++i) {
for (UInt_t j(i); j<nSigComp_; ++j) {
extraVars.push_back(negFitFrac_[i][j]);
}
}
for (UInt_t i(0); i<nSigComp_; ++i) {
for (UInt_t j(i); j<nSigComp_; ++j) {
extraVars.push_back(posFitFrac_[i][j]);
}
}
// Store any extra parameters/quantities from the DP model (e.g. K-matrix total fit fractions)
std::vector<LauParameter> negExtraPars = negSigModel_->getExtraParameters();
std::vector<LauParameter>::iterator negExtraIter;
for (negExtraIter = negExtraPars.begin(); negExtraIter != negExtraPars.end(); ++negExtraIter) {
LauParameter negExtraParameter = (*negExtraIter);
extraVars.push_back(negExtraParameter);
}
std::vector<LauParameter> posExtraPars = posSigModel_->getExtraParameters();
std::vector<LauParameter>::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); 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]);
}
}
for (UInt_t i(0); i<nSigComp_; ++i) {
extraVars.push_back(fitFracAsymm_[i]);
}
for (UInt_t i(0); i<nSigComp_; ++i) {
extraVars.push_back(acp_[i]);
}
this->printFitFractions(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->nll(), 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;
for (UInt_t i = 0; i < nSigComp_; i++) {
coeffPars_[i]->randomiseInitValues();
}
}
LauCPFitModel::LauGenInfo LauCPFitModel::eventsToGenerate()
{
// Determine the number of events to generate for each hypothesis
// If we're smearing then smear each one individually
LauGenInfo nEvtsGen;
// Signal
Double_t evtWeight(1.0);
Double_t nEvts = signalEvents_->genValue();
if ( nEvts < 0.0 ) {
evtWeight = -1.0;
nEvts = TMath::Abs( nEvts );
}
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();
} 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<Int_t>((nEvts/2.0 * (1.0 - asym)) + 0.5);
Int_t nNegEvts = static_cast<Int_t>((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 LauParameter* evtsPar = bkgndEvents_[bkgndID];
const LauParameter* asymPar = bkgndAsym_[bkgndID];
evtWeight = 1.0;
nEvts = TMath::FloorNint( evtsPar->genValue() );
if ( nEvts < 0 ) {
evtWeight = -1.0;
nEvts = TMath::Abs( nEvts );
}
asym = asymPar->genValue();
nPosEvts = static_cast<Int_t>((nEvts/2.0 * (1.0 - asym)) + 0.5);
nNegEvts = static_cast<Int_t>((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);
}
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 LauParameter* evtsPar = bkgndEvents_[bkgndID];
const LauParameter* asymPar = bkgndAsym_[bkgndID];
std::cout << " : " << bkgndClass << " asymmetry = " << asymPar->genValue() << " and number of " << bkgndClass << " events = " << evtsPar->genValue() << std::endl;
}
return nEvtsGen;
}
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
LauGenInfo nEvts = this->eventsToGenerate();
Bool_t genOK(kTRUE);
Int_t evtNum(0);
const UInt_t nBkgnds = this->nBkgndClasses();
std::vector<TString> bkgndClassNames(nBkgnds);
std::vector<TString> 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); iEvt<nEvtsGen; ++iEvt) {
this->setGenNtupleDoubleBranchValue( "evtWeight", evtWeight );
if (type == "signal") {
this->setGenNtupleIntegerBranchValue("genSig",1);
for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) {
this->setGenNtupleIntegerBranchValue( bkgndClassNamesGen[iBkgnd], 0 );
}
genOK = this->generateSignalEvent();
} 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 (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); i<nSigComp_; ++i) {
if (negFitFrac[i].size() != nSigComp_) {
std::cerr << "ERROR in LauCPFitModel::genExpt : Fit Fraction array of unexpected dimension: " << negFitFrac[i].size() << std::endl;
gSystem->Exit(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); i<nSigComp_; ++i) {
if (posFitFrac[i].size() != nSigComp_) {
std::cerr << "ERROR in LauCPFitModel::genExpt : Fit Fraction array of unexpected dimension: " << posFitFrac[i].size() << std::endl;
gSystem->Exit(EXIT_FAILURE);
}
}
for (UInt_t i(0); i<nSigComp_; ++i) {
for (UInt_t j(i); j<nSigComp_; ++j) {
negFitFrac_[i][j].value(negFitFrac[i][j].value());
posFitFrac_[i][j].value(posFitFrac[i][j].value());
}
}
negMeanEff_.value(negSigModel_->getMeanEff().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);
LauAbsDPDynamics* 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 );
LauEffModel * 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");
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<TString> varNames = (*pdf_iter)->varNames();
for ( std::vector<TString>::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) {
(*iter)->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<Int_t>( 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<Double_t> binCentresXCoords;
std::vector<Double_t> 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_.value();
}
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_->value() * 0.5;
if (this->useDP() == kFALSE) {
signalEvents *= (1.0 - curEvtCharge_ * signalAsym_->value());
}
// 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]->value() * 0.5 * (1.0 - curEvtCharge_ * bkgndAsym_[bkgndID]->value());
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_->value();
if (usingBkgnd_) {
for (LauBkgndYieldList::const_iterator iter = bkgndEvents_.begin(); iter != bkgndEvents_.end(); ++iter) {
eventSum += (*iter)->value();
}
}
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_->getEvtDPAmp().abs2();
sigDPLike_ *= posSigModel_->getEvtEff();
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_->getEvtDPAmp().abs2();
sigDPLike_ *= negSigModel_->getEvtEff();
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_->getEvtDPAmp().abs2() * posSigModel_->getEvtEff() +
negSigModel_->getEvtDPAmp().abs2() * negSigModel_->getEvtEff() );
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<Int_t>* trueBins = scfMap_->trueBins(recoBin);
const Int_t nDataEvents = this->eventsPerExpt();
// Loop over the true bins
for (std::vector<Int_t>::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_ ) {
LauAbsDPDynamics* sigModel(0);
if (curEvtCharge_<0) {
sigModel = negSigModel_;
} else {
sigModel = posSigModel_;
}
sigModel->calcLikelihoodInfo( nDataEvents + trueBin );
pTrue = sigModel->getEvtDPAmp().abs2() * sigModel->getEvtEff();
} else {
posSigModel_->calcLikelihoodInfo( nDataEvents + trueBin );
negSigModel_->calcLikelihoodInfo( nDataEvents + trueBin );
pTrue = 0.5 * ( posSigModel_->getEvtDPAmp().abs2() * posSigModel_->getEvtEff() +
negSigModel_->getEvtDPAmp().abs2() * negSigModel_->getEvtEff() );
}
// 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<TString> varNames = (*pdf_iter)->varNames();
for ( std::vector<TString>::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<TString>::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<TString> varNames = (*pdf_iter)->varNames();
for ( std::vector<TString>::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<TString>::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<TString> varNames = (*pdf_iter)->varNames();
for ( std::vector<TString>::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 LauParameter* par = bkgndEvents_[iBkgnd];
if (!par->fixed()) {
numbMap[bkgndClass] = par->genValue();
}
}
}
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 LauParameter* 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<TString> varNames = (*pdf_iter)->varNames();
for ( std::vector<TString>::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<TString> varNames = (*pdf_iter)->varNames();
for ( std::vector<TString>::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<TString> varNames = (*pdf_iter)->varNames();
for ( std::vector<TString>::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());
LauAbsDPDynamics* 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<Int_t>(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_.value();
}
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;
}
if (!reuseEventsWithinEnsemble && reuseEventsWithinExperiment) {
std::cerr << "WARNING in LauCPFitModel::embedNegSignal : Conflicting options provided, will not reuse events at all." << std::endl;
reuseEventsWithinExperiment = kFALSE;
}
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;
}
if (!reuseEventsWithinEnsemble && reuseEventsWithinExperiment) {
std::cerr << "WARNING in LauCPFitModel::embedNegBkgnd : Conflicting options provided, will not reuse events at all." << std::endl;
reuseEventsWithinExperiment = kFALSE;
}
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;
}
if (!reuseEventsWithinEnsemble && reuseEventsWithinExperiment) {
std::cerr << "WARNING in LauCPFitModel::embedPosSignal : Conflicting options provided, will not reuse events at all." << std::endl;
reuseEventsWithinExperiment = kFALSE;
}
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;
}
if (!reuseEventsWithinEnsemble && reuseEventsWithinExperiment) {
std::cerr << "WARNING in LauCPFitModel::embedPosBkgnd : Conflicting options provided, will not reuse events at all." << std::endl;
reuseEventsWithinExperiment = kFALSE;
}
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*/ )
{
std::cerr << "ERROR in LauCPFitModel::weightEvents : Method not available for this fit model." << std::endl;
return;
}
diff --git a/src/LauDabbaRes.cc b/src/LauDabbaRes.cc
index c3a66d7..1b2ac72 100644
--- a/src/LauDabbaRes.cc
+++ b/src/LauDabbaRes.cc
@@ -1,127 +1,120 @@
-// Copyright University of Warwick 2010 - 2013.
+// Copyright University of Warwick 2010 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauDabbaRes.cc
\brief File containing implementation of LauDabbaRes class.
+ Formulae and data values from arXiv:0901.2217 - author D.V.Bugg
*/
-//****************************************************************************
-// Class for defining the Dabba resonance model
-//****************************************************************************
-
-// --CLASS DESCRIPTION [MODEL] --
-// Class for defining the Dabba resonance model
-// Formulae and data values from arXiv:0901.2217 - author D.V.Bugg
-
#include <iostream>
#include "LauConstants.hh"
#include "LauDabbaRes.hh"
ClassImp(LauDabbaRes)
-LauDabbaRes::LauDabbaRes(TString resName, Double_t resMass, Double_t resWidth, Int_t resSpin,
+LauDabbaRes::LauDabbaRes(TString resName, LauParameter* resMass, LauParameter* resWidth, Int_t resSpin,
Int_t resCharge, Int_t resPairAmpInt, const LauDaughters* daughters) :
LauAbsResonance(resName, resMass, resWidth, resSpin, resCharge, resPairAmpInt, daughters),
mSumSq_(0.0),
sAdler_(0.0),
b_(24.49),
alpha_(0.1),
beta_(0.1)
{
}
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::setConstants(Double_t b, Double_t alpha, Double_t beta) {
b_ = b;
alpha_ = alpha;
beta_ = beta;
}
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);
}
Double_t realPart = 1.0 - beta_ * sDiff;
Double_t imagPart = b_ * TMath::Exp( - alpha_ * 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;
}
diff --git a/src/LauFlatNR.cc b/src/LauFlatNR.cc
index 25b8f94..9432825 100644
--- a/src/LauFlatNR.cc
+++ b/src/LauFlatNR.cc
@@ -1,48 +1,48 @@
-// Copyright University of Warwick 2004 - 2013.
+// Copyright University of Warwick 2004 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauFlatNR.cc
\brief File containing implementation of LauFlatNR class.
*/
#include <iostream>
#include "LauKinematics.hh"
#include "LauFlatNR.hh"
ClassImp(LauFlatNR)
-LauFlatNR::LauFlatNR(TString resName, Double_t resMass, Double_t resWidth, Int_t resSpin,
+LauFlatNR::LauFlatNR(TString resName, LauParameter* resMass, LauParameter* resWidth, Int_t resSpin,
Int_t resCharge, Int_t resPairAmpInt, const LauDaughters* daughters) :
LauAbsResonance(resName, resMass, resWidth, resSpin, resCharge, 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 5f20a4d..f02d522 100644
--- a/src/LauFlatteRes.cc
+++ b/src/LauFlatteRes.cc
@@ -1,141 +1,141 @@
-// Copyright University of Warwick 2004 - 2013.
+// Copyright University of Warwick 2004 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauFlatteRes.cc
\brief File containing implementation of LauFlatteRes class.
*/
#include <iostream>
#include "LauConstants.hh"
#include "LauFlatteRes.hh"
ClassImp(LauFlatteRes)
-LauFlatteRes::LauFlatteRes(TString resName, Double_t resMass, Double_t resWidth, Int_t resSpin,
+LauFlatteRes::LauFlatteRes(TString resName, LauParameter* resMass, LauParameter* resWidth, Int_t resSpin,
Int_t resCharge, Int_t resPairAmpInt, const LauDaughters* daughters) :
LauAbsResonance(resName, resMass, resWidth, resSpin, resCharge, resPairAmpInt, daughters),
resMassSq_(0.0),
g1_(0.0),
g2_(0.0),
mSumSq0_(0.0),
mSumSq1_(0.0),
mSumSq2_(0.0),
mSumSq3_(0.0)
{
// constant factors from BES data
// resMass_ should be 0.965 +/- 0.008 +/- 0.006 GeV/c^2
g1_ = 0.165; // +/- 0.010 +/- 0.015 GeV/c^2
g2_ = g1_*4.21; // +/- 0.25 +/- 0.21
// or from E791
//g1_ = 0.09;
//g2_ = 0.02;
// or from CERN/WA76
//g1_ = 0.28;
//g2_ = 0.56;
}
LauFlatteRes::~LauFlatteRes()
{
}
void LauFlatteRes::initialise()
{
Double_t resMass = this->getMass();
resMassSq_ = resMass*resMass;
const TString& resName = this->getResonanceName();
if (resName != "f_0(980)") {
std::cerr << "WARNING in LauFlatteRes::initialise : Unexpected resonance name \"" << resName << "\" for Flatte shape." << std::endl;
std::cerr << " : Setting parameters to \"f0_980\" values." << std::endl;
}
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);
}
void LauFlatteRes::setGFactors(Double_t g1, Double_t g2)
{
this->setg1Parameter(g1);
this->setg2Parameter(g2);
}
void LauFlatteRes::setResonanceParameter(Double_t value, const TString& name)
{
if (name == "g1") {
this->setg1Parameter(value);
TString g1name = "gPiPi";
std::cout << "INFO in LauFlatteRes::setResonanceParameter : Setting " << g1name <<" Parameter to " << this->getg1Parameter() << std::endl;
} else if (name == "g2") {
this->setg2Parameter(value);
TString g2name = "gKK";
std::cout << "INFO in LauFlatteRes::setResonanceParameter : Setting " << g2name << " Parameter to " << this->getg2Parameter() << std::endl;
} else {
std::cerr << "WARNING in LauFlatteRes::setResonanceParameter : Parameter name \"" << name << "\" not recognised." << std::endl;
}
}
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.
Double_t resMass = this->getMass();
Double_t s = mass*mass; // Invariant mass squared combination for the system
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 += g2_*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 += g2_*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 += g1_*resMass*2.0*TMath::Sqrt(mSumSq1_/s - 1.0)/3.0;
}
}
Double_t width1 = g1_*rho1*resMass;
Double_t width2 = g2_*rho2*resMass;
Double_t widthTerm = width1 + width2;
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;
}
diff --git a/src/LauGounarisSakuraiRes.cc b/src/LauGounarisSakuraiRes.cc
index 351327d..be5092a 100644
--- a/src/LauGounarisSakuraiRes.cc
+++ b/src/LauGounarisSakuraiRes.cc
@@ -1,224 +1,215 @@
-// Copyright University of Warwick 2006 - 2013.
+// Copyright University of Warwick 2006 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauGounarisSakuraiRes.cc
\brief File containing implementation of LauGounarisSakuraiRes class.
*/
-//****************************************************************************
-// Class for defining the relativistic Breit-Wigner resonance model, which
-// includes the use of Blatt-Weisskopf barrier factors.
-//****************************************************************************
-
-// --CLASS DESCRIPTION [MODEL] --
-// Class for defining the relativistic Breit-Wigner resonance model, with
-// Blatt-Weisskopf barrier factors.
-
#include <iostream>
#include "LauConstants.hh"
#include "LauGounarisSakuraiRes.hh"
ClassImp(LauGounarisSakuraiRes)
-LauGounarisSakuraiRes::LauGounarisSakuraiRes(TString resName, Double_t resMass, Double_t resWidth, Int_t resSpin,
+LauGounarisSakuraiRes::LauGounarisSakuraiRes(TString resName, LauParameter* resMass, LauParameter* resWidth, Int_t resSpin,
Int_t resCharge, Int_t resPairAmpInt, const LauDaughters* daughters) :
LauAbsResonance(resName, resMass, resWidth, resSpin, resCharge, resPairAmpInt, daughters),
q0_(0.0),
p0_(0.0),
pstar0_(0.0),
resMassSq_(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),
resR_(4.0),
parR_(4.0),
resRSq_(16.0),
parRSq_(16.0),
FR0_(1.0),
FB0_(1.0),
barrierType_(LauAbsResonance::BWPrimeBarrier)
{
}
LauGounarisSakuraiRes::~LauGounarisSakuraiRes()
{
}
void LauGounarisSakuraiRes::initialise()
{
// Set-up various constants. This must be called again if the mass/width/spin
// of a resonance changes...
Int_t resSpin = this->getSpin();
Double_t resMass = this->getMass();
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
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 );
}
// Blatt-Weisskopf barrier factor constant: z = q^2*radius^2
// Calculate the Blatt-Weisskopf form factor for the case when m = m_0
this->setBarrierRadii(resR_, parR_, barrierType_);
// 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_);
}
void LauGounarisSakuraiRes::setBarrierRadii(Double_t resRadius, Double_t parRadius, LauAbsResonance::BarrierType type)
{
// Reset the Blatt-Weisskopf barrier radius for the resonance and its parent
resR_ = resRadius;
parR_ = parRadius;
resRSq_ = resRadius*resRadius;
parRSq_ = parRadius*parRadius;
barrierType_ = type;
// Recalculate the Blatt-Weisskopf form factor for the case when m = m_0
Double_t zR0 = q0_*q0_*resRSq_;
Double_t zB0 = p0_*p0_*parRSq_;
if ( ( type == LauAbsResonance::BWPrimeBarrier ) || ( type == LauAbsResonance::ExpBarrier ) ) {
FR0_ = (resR_==0.0) ? 1.0 : this->calcFFactor(zR0);
FB0_ = (parR_==0.0) ? 1.0 : this->calcFFactor(zB0);
}
}
Double_t LauGounarisSakuraiRes::calcFFactor(Double_t z)
{
// Calculate the requested form factor for the resonance, given the z value
Double_t fFactor(1.0);
if ( barrierType_ == LauAbsResonance::BWBarrier ) {
fFactor = TMath::Sqrt(2.0*z/(z + 1.0));
} else if ( barrierType_ == LauAbsResonance::BWPrimeBarrier ) {
fFactor = TMath::Sqrt(1.0/(z + 1.0));
} else if ( barrierType_ == LauAbsResonance::ExpBarrier ) {
fFactor = TMath::Exp( -TMath::Sqrt(z) );
}
return fFactor;
}
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(...)
Double_t resMass = this->getMass();
Double_t resWidth = this->getWidth();
Double_t q = this->getQ();
Double_t p = this->getP();
//Double_t pstar = this->getPstar();
Double_t zR = q*q*resRSq_;
Double_t zB = p*p*parRSq_;
Double_t fFactorR = this->calcFFactor(zR);
Double_t fFactorB = this->calcFFactor(zB);
Double_t fFactorRRatio = fFactorR/FR0_;
Double_t fFactorBRatio = fFactorB/FB0_;
Double_t qRatio = q/q0_;
Double_t qTerm = qRatio*qRatio*qRatio;
Double_t totWidth = resWidth*qTerm*(resMass/mass)*fFactorRRatio*fFactorRRatio;
Double_t massSq = mass*mass;
Double_t massSqTerm = resMassSq_ - massSq;
Double_t h = 2.0*LauConstants::invPi * q/mass * TMath::Log((mass + 2.0*q)/(2.0*LauConstants::mPi));
Double_t f = totWidth * 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 = fFactorRRatio*fFactorBRatio*spinTerm*(1 + d_ * resWidth/resMass);
Double_t denomFactor = (massSqTerm + f)*(massSqTerm + f) + resMassSq_*totWidth*totWidth;
resAmplitude.rescale(numerFactor/denomFactor);
return resAmplitude;
}
diff --git a/src/LauIsobarDynamics.cc b/src/LauIsobarDynamics.cc
index 4e73a84..058deda 100644
--- a/src/LauIsobarDynamics.cc
+++ b/src/LauIsobarDynamics.cc
@@ -1,1885 +1,1921 @@
-// Copyright University of Warwick 2005 - 2013.
+// Copyright University of Warwick 2005 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauIsobarDynamics.cc
\brief File containing implementation of LauIsobarDynamics class.
*/
#include <iostream>
#include <iomanip>
#include <fstream>
#include "TFile.h"
#include "TRandom.h"
#include "TSystem.h"
#include "LauAbsResonance.hh"
#include "LauBelleNR.hh"
#include "LauBelleSymNR.hh"
#include "LauConstants.hh"
#include "LauDaughters.hh"
#include "LauEffModel.hh"
#include "LauFitDataTree.hh"
#include "LauGounarisSakuraiRes.hh"
#include "LauIntegrals.hh"
#include "LauIsobarDynamics.hh"
#include "LauKinematics.hh"
#include "LauKMatrixPropagator.hh"
#include "LauKMatrixPropFactory.hh"
#include "LauKMatrixProdPole.hh"
#include "LauKMatrixProdSVP.hh"
#include "LauNRAmplitude.hh"
#include "LauPolNR.hh"
#include "LauPrint.hh"
#include "LauRandom.hh"
#include "LauRelBreitWignerRes.hh"
#include "LauResonanceMaker.hh"
ClassImp(LauIsobarDynamics)
// for Kpipi: only one scfFraction 2D histogram is needed
LauIsobarDynamics::LauIsobarDynamics(LauDaughters* daughters, LauEffModel* effModel, LauEffModel* scfFractionModel) :
LauAbsDPDynamics(daughters, effModel, scfFractionModel),
symmetricalDP_(kFALSE),
integralsDone_(kFALSE),
intFileName_("integ.dat"),
m13BinWidth_(0.005),
m23BinWidth_(0.005),
m13Sq_(0.0),
m23Sq_(0.0),
mPrime_(0.0),
thPrime_(0.0),
eff_(0.0),
scfFraction_(0.0),
jacobian_(0.0),
ASq_(0.0),
evtLike_(0.0),
iterationsMax_(100000),
nSigGenLoop_(0),
aSqMaxSet_(1.25),
aSqMaxVar_(0.0),
BelleNRAlpha_(0.0),
LASSScatteringLength_(0.0),
LASSEffectiveRange_(0.0),
LASSResonanceMag_(0.0),
LASSResonancePhase_(0.0),
LASSBackgroundMag_(0.0),
LASSBackgroundPhase_(0.0),
LASSCutOff_(0.0),
changeLASSScatteringLength_(kFALSE),
changeLASSEffectiveRange_(kFALSE),
changeLASSResonanceMag_(kFALSE),
changeLASSResonancePhase_(kFALSE),
changeLASSBackgroundMag_(kFALSE),
changeLASSBackgroundPhase_(kFALSE),
changeLASSCutOff_(kFALSE),
FlatteParameterg1_(0.0),
FlatteParameterg2_(0.0),
changeFlatteParameterg1_(kFALSE),
changeFlatteParameterg2_(kFALSE),
resBarrierRadius_(4.0),
parBarrierRadius_(4.0),
barrierType_( LauAbsResonance::BWPrimeBarrier ),
- flipHelicity_(kTRUE)
+ flipHelicity_(kTRUE),
+ recalcNormalisation_(kFALSE)
{
// Constructor for the isobar signal model
if (daughters != 0) {
symmetricalDP_ = daughters->gotSymmetricalDP();
typDaug_.push_back(daughters->getTypeDaug1());
typDaug_.push_back(daughters->getTypeDaug2());
typDaug_.push_back(daughters->getTypeDaug3());
}
sigResonances_.clear();
kMatrixPropagators_.clear();
kMatrixPropSet_.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, LauEffModel* effModel, LauTagCatScfFractionModelMap scfFractionModel) :
LauAbsDPDynamics(daughters, effModel, scfFractionModel),
symmetricalDP_(kFALSE),
integralsDone_(kFALSE),
intFileName_("integ.dat"),
m13BinWidth_(0.005),
m23BinWidth_(0.005),
m13Sq_(0.0),
m23Sq_(0.0),
mPrime_(0.0),
thPrime_(0.0),
eff_(0.0),
scfFraction_(0.0),
jacobian_(0.0),
ASq_(0.0),
evtLike_(0.0),
iterationsMax_(100000),
nSigGenLoop_(0),
aSqMaxSet_(1.25),
aSqMaxVar_(0.0),
BelleNRAlpha_(0.0),
LASSScatteringLength_(0.0),
LASSEffectiveRange_(0.0),
LASSResonanceMag_(0.0),
LASSResonancePhase_(0.0),
LASSBackgroundMag_(0.0),
LASSBackgroundPhase_(0.0),
LASSCutOff_(0.0),
changeLASSScatteringLength_(kFALSE),
changeLASSEffectiveRange_(kFALSE),
changeLASSResonanceMag_(kFALSE),
changeLASSResonancePhase_(kFALSE),
changeLASSBackgroundMag_(kFALSE),
changeLASSBackgroundPhase_(kFALSE),
changeLASSCutOff_(kFALSE),
FlatteParameterg1_(0.0),
FlatteParameterg2_(0.0),
changeFlatteParameterg1_(kFALSE),
changeFlatteParameterg2_(kFALSE),
resBarrierRadius_(4.0),
parBarrierRadius_(4.0),
barrierType_( LauAbsResonance::BWPrimeBarrier ),
- flipHelicity_(kTRUE)
+ flipHelicity_(kTRUE),
+ recalcNormalisation_(kFALSE)
{
// Constructor for the isobar signal model
if (daughters != 0) {
symmetricalDP_ = daughters->gotSymmetricalDP();
typDaug_.push_back(daughters->getTypeDaug1());
typDaug_.push_back(daughters->getTypeDaug2());
typDaug_.push_back(daughters->getTypeDaug3());
}
sigResonances_.clear();
kMatrixPropagators_.clear();
kMatrixPropSet_.clear();
}
LauIsobarDynamics::~LauIsobarDynamics()
{
}
+void LauIsobarDynamics::recalculateNormalisation()
+{
+ this->initialiseVectors();
+
+ integralsDone_ = kFALSE;
+
+ if ( nAmp_ == 0 ) {
+ std::cout << "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.
+ this->calcDPNormalisation();
+
+ for (UInt_t i = 0; i < nAmp_; i++) {
+ fNorm_[i] = 0.0;
+ if (fSqSum_[i] > 0.0) {fNorm_[i] = TMath::Sqrt(1.0/(fSqSum_[i]));}
+ }
+ }
+ integralsDone_ = kTRUE;
+}
+
void LauIsobarDynamics::initialise(const std::vector<LauComplex>& coeffs)
{
// Check whether we have a valid set of integration constants for
// the normalisation of the signal likelihood function.
this->initialiseVectors();
integralsDone_ = kFALSE;
// Print summary of what we have so far to screen
this->initSummary();
if ( nAmp_ == 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..."<<std::endl;
this->calcDPNormalisation();
// Write the integrals to a file (mainly for debugging purposes)
this->writeIntegralsFile();
}
integralsDone_ = kTRUE;
std::cout << std::setprecision(10);
// Calculate and cache the relative normalisations of each resonance _dynamic_ amplitude
// (e.g. Breit-Wigner contribution, not from the complex amplitude/phase) w.r.t. the
// total DP amplitude. These are stored in fNorm_[i].
// The normalisation uses fSqSum[i], which is calculated within the dynamics() function,
// which has already been called by the calcDPNomalisation() function above to create the
// normalisation integrals.
// fSqSum[i] is the event-by-event running total of the dynamical amplitude
// squared for a given resonance, i. We require that:
// |fNorm_[i]|^2 * |fSqSum[i]|^2 = 1,
// i.e. fNorm_[i] normalises each resonance contribution to give the same number of
// events in the DP, accounting for the total DP area and the
// dynamics of the resonance.
std::cout<<"INFO in LauIsobarDynamics::initialise : Summary of the integrals:"<<std::endl;
for (UInt_t i = 0; i < nAmp_; i++) {
fNorm_[i] = 0.0;
if (fSqSum_[i] > 0.0) {fNorm_[i] = TMath::Sqrt(1.0/(fSqSum_[i]));}
std::cout<<" fNorm["<<i<<"] = "<<fNorm_[i]<<std::endl;
std::cout<<" fSqSum["<<i<<"] = "<<fSqSum_[i]<<std::endl;
}
for (UInt_t i = 0; i < nAmp_; i++) {
for (UInt_t j = 0; j < nAmp_; j++) {
std::cout<<" fifjEffSum["<<i<<"]["<<j<<"] = "<<fifjEffSum_[i][j];
}
std::cout<<std::endl;
}
for (UInt_t i = 0; i < nAmp_; i++) {
for (UInt_t j = 0; j < nAmp_; j++) {
std::cout<<" fifjSum["<<i<<"]["<<j<<"] = "<<fifjSum_[i][j];
}
std::cout<<std::endl;
}
// Calculate the initial fit fractions (for later comparison with Toy MC, if required)
this->updateCoeffs(coeffs);
this->calcExtraInfo(kTRUE);
for (UInt_t i = 0; i < nAmp_; i++) {
for (UInt_t j = i; j < nAmp_; j++) {
std::cout<<"INFO in LauIsobarDynamics::initialise : Initial fit fraction for amplitude ("<<i<<","<<j<<") = "<<fitFrac_[i][j].genValue()<<std::endl;
}
}
std::cout<<"INFO in LauIsobarDynamics::initialise : Initial efficiency = "<<meanDPEff_.initValue()<<std::endl;
std::cout<<"INFO in LauIsobarDynamics::initialise : Initial DPRate = "<<DPRate_.initValue()<<std::endl;
}
void LauIsobarDynamics::initSummary()
{
UInt_t i(0);
TString nameP = daughters_->getNameParent();
TString name1 = daughters_->getNameDaug1();
TString name2 = daughters_->getNameDaug2();
TString name3 = daughters_->getNameDaug3();
std::cout<<"INFO in LauIsobarDynamics::initSummary : We are going to do a DP with "<<nameP<<" going to "<<name1<<" "<<name2<<" "<<name3<<std::endl;
std::cout<<" : For the following resonance combinations:"<<std::endl;
std::cout<<" : In tracks 2 and 3:"<<std::endl;
for (i = 0; i < nAmp_; i++) {
if (resPairAmp_[i] == 1) {
std::cout<<" : "<<resTypAmp_[i]<<" to "<<name2<<", "<< name3<<std::endl;
}
}
std::cout<<std::endl;
std::cout<<" : In tracks 1 and 3:"<<std::endl;
for (i = 0; i < nAmp_; i++) {
if (resPairAmp_[i] == 2) {
std::cout<<" : "<<resTypAmp_[i]<<" to "<<name1<<", "<< name3<<std::endl;
}
}
std::cout<<std::endl;
std::cout<<" : In tracks 1 and 2:"<<std::endl;
for (i = 0; i < nAmp_; i++) {
if (resPairAmp_[i] == 3) {
std::cout<<" : "<<resTypAmp_[i]<<" to "<<name1<<", "<< name2<<std::endl;
}
}
std::cout<<std::endl;
for (i = 0; i < nAmp_; i++) {
if (resPairAmp_[i] == 0) {
std::cout<<" : and a non-resonant amplitude."<<std::endl;
}
}
std::cout<<std::endl;
}
void LauIsobarDynamics::initialiseVectors()
{
fSqSum_.clear(); fSqSum_.resize(nAmp_);
fifjEffSum_.clear(); fifjEffSum_.resize(nAmp_);
fifjSum_.clear(); fifjSum_.resize(nAmp_);
ff_.clear(); ff_.resize(nAmp_);
fNorm_.clear(); fNorm_.resize(nAmp_);
fitFrac_.clear(); fitFrac_.resize(nAmp_);
LauComplex null(0.0, 0.0);
for (UInt_t i = 0; i < nAmp_; i++) {
fSqSum_[i] = 0.0; fNorm_[i] = 0.0;
ff_[i] = null;
fifjEffSum_[i].resize(nAmp_);
fifjSum_[i].resize(nAmp_);
fitFrac_[i].resize(nAmp_);
for (UInt_t j = 0; j < nAmp_; j++) {
fifjEffSum_[i][j] = null;
fifjSum_[i][j] = null;
fitFrac_[i][j].valueAndRange(0.0, -100.0, 100.0);
}
}
UInt_t nKMatrixProps = kMatrixPropagators_.size();
extraParameters_.clear();
extraParameters_.resize( nKMatrixProps );
for ( UInt_t i = 0; i < nKMatrixProps; ++i ) {
extraParameters_[i].valueAndRange(0.0, -100.0, 100.0);
}
}
void LauIsobarDynamics::writeIntegralsFile()
{
// Routine to end integration calculation for loglike normalisation.
// This writes out the normalisation integral output into the file named
// outputFileName.
std::cout<<"INFO in LauIsobarDynamics::writeIntegralsFile : Writing integral output to integrals file "<<intFileName_.Data()<<std::endl;
UInt_t i(0), j(0);
std::ofstream getChar(intFileName_.Data());
getChar << std::setprecision(10);
// Write out daughter types (pi, pi0, K, K0s?)
for (i = 0; i < 3; i++) {
getChar << typDaug_[i] << " ";
}
// Write out number of resonances in the Dalitz plot model
getChar << nAmp_ << std::endl;
// Write out the resonances
for (i = 0; i < nAmp_; i++) {
getChar << resTypAmp_[i] << " ";
}
getChar << std::endl;
// Write out the resonance model types (BW, RelBW etc...)
for (i = 0; i < nAmp_; i++) {
LauAbsResonance* theResonance = sigResonances_[i];
Int_t resModelInt = theResonance->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;
// 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;
}
-void LauIsobarDynamics::addResonance(const TString& resName, Int_t resPairAmpInt, const TString& resType, Double_t newMass, Double_t newWidth, Int_t newSpin)
+void LauIsobarDynamics::addResonance(const TString& resName, Int_t resPairAmpInt, const TString& resType, Bool_t fixMass, Bool_t fixWidth, Double_t newMass, Double_t newWidth, Int_t newSpin)
{
// 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.
- LauAbsResonance *theResonance =
- resonanceMaker_->getResonance(resName, resPairAmpInt, resType);
+ LauResonanceMaker& resonanceMaker = LauResonanceMaker::get();
+ LauAbsResonance *theResonance = resonanceMaker.getResonance(daughters_, resName, resPairAmpInt, resType);
if (theResonance == 0) {
std::cerr<<"ERROR in LauIsobarDynamics::addResonance : Couldn't create the resonance \""<<resName<<"\""<<std::endl;
return;
}
// Change resonance and lineshape parameters as required.
if (newMass > 0.0 || newWidth > 0.0 || newSpin > -1) {
theResonance->changeResonance(newMass, newWidth, newSpin);
}
+ // mass and width of resonances are fixed as default. Here we change the status if it's false
+ if (!fixMass) {
+ recalcNormalisation_ = kTRUE;
+ theResonance->fixMass(fixMass);
+ }
+ if (!fixWidth) {
+ recalcNormalisation_ = kTRUE;
+ theResonance->fixWidth(fixWidth);
+ }
+
+ std::cout << "INFO in LauIsobarDynamics::addResonance : resName: " << resName << ", fixMass = " << theResonance->fixMass() << ", fixWidth = " << theResonance->fixWidth() << std::endl;
+
// implement the helicity flip here
if (flipHelicity_ && daughters_->getCharge(resPairAmpInt) == 0) {
if ( daughters_->getChargeParent() == 0 && daughters_->getTypeParent() > 0 ) {
theResonance->flipHelicity(kTRUE);
}
}
TString resTypeName(resType);
// Reset the Blatt-Weisskopf barrier factors as appropriate
if (!resTypeName.CompareTo("RelBW")) {
LauRelBreitWignerRes* theRBW = dynamic_cast<LauRelBreitWignerRes*>(theResonance);
theRBW->setBarrierRadii(resBarrierRadius_, parBarrierRadius_, barrierType_);
} else if (!resTypeName.CompareTo("GS")) {
LauGounarisSakuraiRes* theGS = dynamic_cast<LauGounarisSakuraiRes*>(theResonance);
theGS->setBarrierRadii(resBarrierRadius_, parBarrierRadius_, barrierType_);
}
if (changeLASSScatteringLength_ == kTRUE && resTypeName.BeginsWith("LASS") ) {
theResonance->setResonanceParameter(LASSScatteringLength_, "a");
}
if (changeLASSEffectiveRange_ == kTRUE && resTypeName.BeginsWith("LASS") ) {
theResonance->setResonanceParameter(LASSEffectiveRange_, "r");
}
if (changeLASSResonanceMag_ == kTRUE && !resTypeName.CompareTo("LASS") ) {
theResonance->setResonanceParameter(LASSResonanceMag_, "R");
}
if (changeLASSResonancePhase_ == kTRUE && !resTypeName.CompareTo("LASS") ) {
theResonance->setResonanceParameter(LASSResonancePhase_, "phiR");
}
if (changeLASSBackgroundMag_ == kTRUE && !resTypeName.CompareTo("LASS") ) {
theResonance->setResonanceParameter(LASSBackgroundMag_, "B");
}
if (changeLASSBackgroundPhase_ == kTRUE && !resTypeName.CompareTo("LASS") ) {
theResonance->setResonanceParameter(LASSBackgroundPhase_, "phiB");
}
if (changeLASSCutOff_ == kTRUE && resTypeName.BeginsWith("LASS") ) {
theResonance->setResonanceParameter(LASSCutOff_, "cutOff");
}
if (changeFlatteParameterg1_ == kTRUE && !resTypeName.CompareTo("Flatte") ) {
theResonance->setResonanceParameter(FlatteParameterg1_, "g1");
}
if (changeFlatteParameterg2_ == kTRUE && !resTypeName.CompareTo("Flatte") ) {
theResonance->setResonanceParameter(FlatteParameterg2_, "g2");
}
TString resonanceName = theResonance->getResonanceName();
if ( resonanceName.BeginsWith("BelleNR", TString::kExact) ) {
LauBelleNR* belleNR = dynamic_cast<LauBelleNR*>(theResonance);
if (belleNR != 0) {
belleNR->setAlpha(BelleNRAlpha_);
} else {
std::cerr<<"ERROR in LauIsobarDynamics::addResonance : Belle non-resonant object is null"<<std::endl;
}
} else if ( resonanceName.BeginsWith("BelleSymNR", TString::kExact) ) {
LauBelleSymNR* belleNR = dynamic_cast<LauBelleSymNR*>(theResonance);
if (belleNR != 0) {
belleNR->initialise(symmetricalDP_, BelleNRAlpha_, resTypeName);
} else {
std::cerr<<"ERROR in LauIsobarDynamics::addResonance : Symmetric Belle non-resonant object is null"<<std::endl;
}
} else if ( resonanceName.BeginsWith("PolNR", TString::kExact) ) {
LauPolNR* polNR = dynamic_cast<LauPolNR*>(theResonance);
Double_t omega = 0.5*(daughters_->getMassParent()+(1./3)*(daughters_->getMassDaug1()+daughters_->getMassDaug2()+daughters_->getMassDaug3()));
if (polNR != 0) {
polNR->setOmega(omega);
} else {
std::cerr<<"ERROR in LauIsobarDynamics::addResonance : Polynomial non-resonant object is null"<<std::endl;
}
}
// Initialise the resonance model
theResonance->initialise();
// Set the resonance name and what track is the bachelor
resTypAmp_.push_back(resonanceName);
- resIntAmp_.push_back(resonanceMaker_->resTypeInt(resonanceName));
+ resIntAmp_.push_back(resonanceMaker.resTypeInt(resonanceName));
// Always force the non-resonant amplitude pair to have resPairAmp = 0
// in case the user chooses the wrong number.
if ( (resonanceName.BeginsWith("NonReson", TString::kExact) == kTRUE) ||
(resonanceName.BeginsWith("BelleSymNR", TString::kExact) == kTRUE) ||
(resonanceName.BeginsWith("NRModel", TString::kExact) == kTRUE)) {
std::cout<<"INFO in LauIsobarDynamics::addResonance : Setting resPairAmp to 0 for "<<resonanceName<<" contribution."<<std::endl;
resPairAmp_.push_back(0);
} else {
resPairAmp_.push_back(resPairAmpInt);
}
// Increment the number of resonance amplitudes we have so far
++nAmp_;
// Finally, add the resonance object to the internal array
sigResonances_.push_back(theResonance);
std::cout<<"INFO in LauIsobarDynamics::addResonance : Successfully added resonance. Total number of resonances so far = "<<nAmp_<<std::endl;
}
void LauIsobarDynamics::defineKMatrixPropagator(const TString& propName, const TString& paramFileName, Int_t resPairAmpInt,
Int_t nChannels, Int_t nPoles, Int_t rowIndex)
{
// Define the K-matrix propagator. The resPairAmpInt integer specifies which mass combination should be used
// for the invariant mass-squared variable "s". The pole masses and coupling constants are defined in the
// paramFileName parameter file. The number of channels and poles are defined by the nChannels and nPoles integers, respectively.
// The integer rowIndex specifies which row of the propagator should be used when
// summing over all amplitude channels: S-wave will be the first row, so rowIndex = 1.
if (rowIndex < 1) {
std::cerr<<"Error in defineKMatrixPropagator: rowIndex must be > 0 but is equal to "<<rowIndex<<std::endl;
return;
}
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)
{
// 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 "<<poleIndex
<<" is not between 1 and "<<nPoles<<". Not adding production pole "<<poleName
<<" for K-matrix propagator "<<propName<<std::endl;
return;
}
// Now add the K-matrix production pole amplitude to the vector of LauAbsResonance pointers.
Int_t resPairAmpInt = thePropagator->getResPairAmpInt();
LauAbsResonance* prodPole = new LauKMatrixProdPole(poleName, poleIndex, resPairAmpInt, thePropagator, daughters_);
resTypAmp_.push_back(poleName);
resIntAmp_.push_back(0);
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 = "<<nAmp_<<std::endl;
} else {
std::cerr<<"ERROR in LauIsobarDynamics::addKMatrixProdPole : The propagator of the name "<<propName
<<" could not be found for the production pole "<<poleName<<std::endl;
}
}
void LauIsobarDynamics::addKMatrixProdSVP(const TString& SVPName, const TString& propName, Int_t channelIndex)
{
// Add a K-matrix production "slowly-varying part" (SVP) term, using the K-matrix propagator
// given by the propName. Here, channelIndex is the integer specifying the channel number.
// First, find the K-matrix propagator.
KMPropMap::iterator mapIter = kMatrixPropagators_.find(propName);
if (mapIter != kMatrixPropagators_.end()) {
LauKMatrixPropagator* thePropagator = mapIter->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 "<<channelIndex
<<" is not between 1 and "<<nChannels<<". Not adding production slowly-varying part "<<SVPName
<<" for K-matrix propagator "<<propName<<std::endl;
return;
}
// Now add the K-matrix production SVP amplitude to the vector of LauAbsResonance pointers.
Int_t resPairAmpInt = thePropagator->getResPairAmpInt();
LauAbsResonance* prodSVP = new LauKMatrixProdSVP(SVPName, channelIndex, resPairAmpInt, thePropagator, daughters_);
resTypAmp_.push_back(SVPName);
resIntAmp_.push_back(0);
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 = "<<nAmp_<<std::endl;
} else {
std::cerr<<"ERROR in LauIsobarDynamics::addKMatrixProdSVP : The propagator of the name "<<propName
<<" could not be found for the production slowly-varying part "<<SVPName<<std::endl;
}
}
LauAbsResonance* LauIsobarDynamics::findResonance(const TString& name)
{
TString testName(name);
testName.ToLower();
LauAbsResonance* theResonance(0);
for (std::vector<LauAbsResonance*>::iterator iter=sigResonances_.begin(); iter!=sigResonances_.end(); ++iter) {
theResonance = (*iter);
if (theResonance != 0) {
TString resString = theResonance->getResonanceName();
resString.ToLower();
if (resString.BeginsWith(testName, TString::kExact)) {
return theResonance;
}
}
}
std::cerr<<"ERROR in LauIsobarDynamics::findResonance : Couldn't find resonance \""<<name<<"\" in the model."<<std::endl;
return 0;
}
const LauAbsResonance* LauIsobarDynamics::findResonance(const TString& name) const
{
TString testName(name);
testName.ToLower();
const LauAbsResonance* theResonance(0);
for (std::vector<LauAbsResonance*>::const_iterator iter=sigResonances_.begin(); iter!=sigResonances_.end(); ++iter) {
theResonance = (*iter);
if (theResonance != 0) {
TString resString = theResonance->getResonanceName();
resString.ToLower();
if (resString.BeginsWith(testName, TString::kExact)) {
return theResonance;
}
}
}
std::cerr<<"ERROR in LauIsobarDynamics::findResonance : Couldn't find resonance \""<<name<<"\" in the model."<<std::endl;
return 0;
}
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::changeResonance(const TString& resName, Double_t newMass, Double_t newWidth, Int_t newSpin)
{
// Change the mass, width or spin of a resonance.
if (newMass > 0.0 || newWidth > 0.0 || newSpin > -1) {
std::cerr<<"ERROR in LauIsobarDynamics::changeResonance : mass, width and spin parameters all out of range."<<std::endl;
return;
}
LauAbsResonance* theRes = this->findResonance(resName);
if (theRes != 0) {
theRes->changeResonance(newMass, newWidth, newSpin);
}
}
void LauIsobarDynamics::calcDPNormalisation()
{
// Use Gauss-Legendre quadrature integration
// Get the rectangle that encloses the DP
Double_t minm13 = kinematics_->getm13Min();
Double_t maxm13 = kinematics_->getm13Max();
Double_t minm23 = kinematics_->getm23Min();
Double_t maxm23 = kinematics_->getm23Max();
Double_t minm12 = kinematics_->getm12Min();
Double_t maxm12 = kinematics_->getm12Max();
// Find out whether we have narrow resonances in the DP (defined here as width < 20 MeV).
std::multimap<Double_t,Double_t> m13NarrowRes;
std::multimap<Double_t,Double_t> m23NarrowRes;
std::multimap<Double_t,Double_t> m12NarrowRes;
for ( std::vector<LauAbsResonance*>::const_iterator iter = sigResonances_.begin(); iter != sigResonances_.end(); ++iter ) {
Double_t width = (*iter)->getWidth();
if ( width > 0.020 || width == 0.0 ) { continue; }
Double_t mass = (*iter)->getMass();
Int_t pair = (*iter)->getPairInt();
TString name = (*iter)->getResonanceName();
std::cout<<"INFO in LauIsobarDynamics::calcDPNormalisation : Found narrow resonance: "<<name<<", mass = "<<mass<<", width = "<<width<<", pair int = "<<pair<<std::endl;
if ( pair == 1 ) {
if ( mass < minm23 || mass > maxm23 ){ continue; }
m23NarrowRes.insert( std::make_pair(width,mass) );
} else if ( pair == 2 ) {
if ( mass < minm13 || mass > maxm13 ){ continue; }
m13NarrowRes.insert( std::make_pair(width,mass) );
} else if ( pair == 3 ) {
if ( mass < minm12 || mass > maxm12 ){ continue; }
m12NarrowRes.insert( std::make_pair(width,mass) );
} else {
std::cerr<<"WARNING in LauIsobarDynamics::calcDPNormalisation : strange pair integer, "<<pair<<", for resonance \""<<(*iter)->getResonanceName()<<std::endl;
}
}
// Find the narrowest resonance in each mass pairing
const Bool_t e12 = m12NarrowRes.empty();
const Bool_t e13 = m13NarrowRes.empty();
const Bool_t e23 = m23NarrowRes.empty();
//const UInt_t s12 = e12 ? 0 : m12NarrowRes.size();
const UInt_t s13 = e13 ? 0 : m13NarrowRes.size();
const UInt_t s23 = e23 ? 0 : m23NarrowRes.size();
const Double_t w12 = e12 ? DBL_MAX : m12NarrowRes.begin()->first / 100.0;
const Double_t w13 = e13 ? DBL_MAX : m13NarrowRes.begin()->first / 100.0;
const Double_t w23 = e23 ? DBL_MAX : m23NarrowRes.begin()->first / 100.0;
// Start off with default bin width (5 MeV)
Double_t m13BinWidth = m13BinWidth_;
Double_t m23BinWidth = m23BinWidth_;
// Depending on how many narrow resonances we have and where they
// are we adopt different approaches
if ( e12 && e13 && e23 ) {
// If we have no narrow resonances just integrate the whole
// DP with the standard bin widths
std::cout<<"INFO in LauIsobarDynamics::calcDPNormalisation : No narrow resonances found, integrating over whole Dalitz plot..."<<std::endl;
this->calcDPPartialIntegral(minm13, maxm13, minm23, maxm23, m13BinWidth, m23BinWidth);
} else if ( ! e12 ) {
// If we have a narrow resonance on the diagonal then we'll have to
// just use a narrow bin width over the whole DP (1/10 of the width
// of the narrowest resonance in any mass pair)
m13BinWidth = m23BinWidth = 10.0*TMath::Min( w12, TMath::Min( w13, w23 ) );
std::cout<<"INFO in LauIsobarDynamics::calcDPNormalisation : One or more narrow resonances found in m12, integrating over whole Dalitz plot with bin width of "<<m13BinWidth<<" GeV/c2..."<<std::endl;
this->calcDPPartialIntegral(minm13, maxm13, minm23, maxm23, m13BinWidth, m23BinWidth);
} else if ( s13==1 && e23 ) {
// We have a single narrow resonance in m13
// Divide the plot into 3 regions: the resonance band and
// the two areas either side.
Double_t mass = m13NarrowRes.begin()->second;
Double_t width = m13NarrowRes.begin()->first;
Double_t resMin = mass - 5.0*width;
Double_t resMax = mass + 5.0*width;
// if the resonance is close to threshold just go from
// threshold to resMax, otherwise treat threshold to resMin
// as a separate region
if ( resMin < (minm13+50.0*m13BinWidth_) ) {
std::cout<<"INFO in LauIsobarDynamics::calcDPNormalisation : One narrow resonance found in m13, close to threshold, dividing Dalitz plot into two regions..."<<std::endl;
this->calcDPPartialIntegral(resMax, maxm13, minm23, maxm23, m13BinWidth, m23BinWidth);
m13BinWidth = w13;
this->calcDPPartialIntegral(minm13, resMax, minm23, maxm23, m13BinWidth, m23BinWidth);
} else {
std::cout<<"INFO in LauIsobarDynamics::calcDPNormalisation : One narrow resonance found in m13, dividing Dalitz plot into three regions..."<<std::endl;
this->calcDPPartialIntegral(minm13, resMin, minm23, maxm23, m13BinWidth, m23BinWidth);
this->calcDPPartialIntegral(resMax, maxm13, minm23, maxm23, m13BinWidth, m23BinWidth);
m13BinWidth = w13;
this->calcDPPartialIntegral(resMin, resMax, minm23, maxm23, m13BinWidth, m23BinWidth);
}
} else if ( s13==2 && e23 ) {
// We have a two narrow resonances in m13
// Divide the plot into 5 regions: the resonance bands,
// the two areas either side and the area in between.
std::multimap<Double_t,Double_t> massordered;
for ( std::map<Double_t,Double_t>::const_iterator iter = m13NarrowRes.begin(); iter != m13NarrowRes.end(); ++iter ) {
massordered.insert( std::make_pair( iter->second, iter->first ) );
}
Double_t res1Mass = massordered.begin()->first;
Double_t res1Width = massordered.begin()->second;
Double_t res1Min = res1Mass - 5.0*res1Width;
Double_t res1Max = res1Mass + 5.0*res1Width;
Double_t res2Mass = (++(massordered.begin()))->first;
Double_t res2Width = (++(massordered.begin()))->second;
Double_t res2Min = res2Mass - 5.0*res2Width;
Double_t res2Max = res2Mass + 5.0*res2Width;
// if the resonance is close to threshold just go from
// threshold to resMax, otherwise treat threshold to resMin
// as a separate region
if ( res1Min < (minm13+50.0*m13BinWidth_) ) {
std::cout<<"INFO in LauIsobarDynamics::calcDPNormalisation : Two narrow resonances found in m13, one close to threshold, dividing Dalitz plot into four regions..."<<std::endl;
this->calcDPPartialIntegral(res1Max, res2Min, minm23, maxm23, m13BinWidth, m23BinWidth);
this->calcDPPartialIntegral(res2Max, maxm13, minm23, maxm23, m13BinWidth, m23BinWidth);
m13BinWidth = res1Width/100.0;
this->calcDPPartialIntegral(minm13, res1Max, minm23, maxm23, m13BinWidth, m23BinWidth);
m13BinWidth = res2Width/100.0;
this->calcDPPartialIntegral(res2Min, res2Max, minm23, maxm23, m13BinWidth, m23BinWidth);
} else {
std::cout<<"INFO in LauIsobarDynamics::calcDPNormalisation : Two narrow resonances found in m13, dividing Dalitz plot into five regions..."<<std::endl;
this->calcDPPartialIntegral(minm13, res1Min, minm23, maxm23, m13BinWidth, m23BinWidth);
this->calcDPPartialIntegral(res1Max, res2Min, minm23, maxm23, m13BinWidth, m23BinWidth);
this->calcDPPartialIntegral(res2Max, maxm13, minm23, maxm23, m13BinWidth, m23BinWidth);
m13BinWidth = res1Width/100.0;
this->calcDPPartialIntegral(res1Min, res1Max, minm23, maxm23, m13BinWidth, m23BinWidth);
m13BinWidth = res2Width/100.0;
this->calcDPPartialIntegral(res2Min, res2Max, minm23, maxm23, m13BinWidth, m23BinWidth);
}
} else if ( s23==1 && e13 ) {
// We have a single narrow resonance in m23
// Divide the plot into 3 regions: the resonance band and
// the two areas either side.
Double_t mass = m23NarrowRes.begin()->second;
Double_t width = m23NarrowRes.begin()->first;
Double_t resMin = mass - 5.0*width;
Double_t resMax = mass + 5.0*width;
// if the resonance is close to threshold just go from
// threshold to resMax, otherwise treat threshold to resMin
// as a separate region
if ( resMin < (minm23+50.0*m23BinWidth_) ) {
std::cout<<"INFO in LauIsobarDynamics::calcDPNormalisation : One narrow resonance found in m23, close to threshold, dividing Dalitz plot into two regions..."<<std::endl;
this->calcDPPartialIntegral(minm13, maxm13, resMax, maxm23, m13BinWidth, m23BinWidth);
m23BinWidth = w23;
this->calcDPPartialIntegral(minm13, maxm13, minm23, resMax, m13BinWidth, m23BinWidth);
} else {
std::cout<<"INFO in LauIsobarDynamics::calcDPNormalisation : One narrow resonance found in m23, dividing Dalitz plot into three regions..."<<std::endl;
this->calcDPPartialIntegral(minm13, maxm13, minm23, resMin, m13BinWidth, m23BinWidth);
this->calcDPPartialIntegral(minm13, maxm13, resMax, maxm23, m13BinWidth, m23BinWidth);
m23BinWidth = w23;
this->calcDPPartialIntegral(minm13, maxm13, resMin, resMax, m13BinWidth, m23BinWidth);
}
} else if ( s23==2 && e13 ) {
// We have a two narrow resonances in m23
// Divide the plot into 5 regions: the resonance bands,
// the two areas either side and the area in between.
std::multimap<Double_t,Double_t> massordered;
for ( std::map<Double_t,Double_t>::const_iterator iter = m23NarrowRes.begin(); iter != m23NarrowRes.end(); ++iter ) {
massordered.insert( std::make_pair( iter->second, iter->first ) );
}
Double_t res1Mass = massordered.begin()->first;
Double_t res1Width = massordered.begin()->second;
Double_t res1Min = res1Mass - 5.0*res1Width;
Double_t res1Max = res1Mass + 5.0*res1Width;
Double_t res2Mass = (++(massordered.begin()))->first;
Double_t res2Width = (++(massordered.begin()))->second;
Double_t res2Min = res2Mass - 5.0*res2Width;
Double_t res2Max = res2Mass + 5.0*res2Width;
// if the resonance is close to threshold just go from
// threshold to resMax, otherwise treat threshold to resMin
// as a separate region
if ( res1Min < (minm23+50.0*m23BinWidth_) ) {
std::cout<<"INFO in LauIsobarDynamics::calcDPNormalisation : Two narrow resonances found in m23, one close to threshold, dividing Dalitz plot into four regions..."<<std::endl;
this->calcDPPartialIntegral(minm13, maxm13, res1Max, res2Min, m13BinWidth, m23BinWidth);
this->calcDPPartialIntegral(minm13, maxm13, res2Max, maxm23, m13BinWidth, m23BinWidth);
m23BinWidth = res1Width/100.0;
this->calcDPPartialIntegral(minm13, maxm13, minm23, res1Max, m13BinWidth, m23BinWidth);
m23BinWidth = res2Width/100.0;
this->calcDPPartialIntegral(minm13, maxm13, res2Min, res2Max, m13BinWidth, m23BinWidth);
} else {
std::cout<<"INFO in LauIsobarDynamics::calcDPNormalisation : Two narrow resonances found in m23, dividing Dalitz plot into five regions..."<<std::endl;
this->calcDPPartialIntegral(minm13, maxm13, minm23, res1Min, m13BinWidth, m23BinWidth);
this->calcDPPartialIntegral(minm13, maxm13, res1Max, res2Min, m13BinWidth, m23BinWidth);
this->calcDPPartialIntegral(minm13, maxm13, res2Max, maxm23, m13BinWidth, m23BinWidth);
m23BinWidth = res1Width/100.0;
this->calcDPPartialIntegral(minm13, maxm13, res1Min, res1Max, m13BinWidth, m23BinWidth);
m23BinWidth = res2Width/100.0;
this->calcDPPartialIntegral(minm13, maxm13, res2Min, res2Max, m13BinWidth, m23BinWidth);
}
} else if ( s13==1 && s23==1 ) {
// We have a single narrow resonance in both m13 and m23
// Divide the plot into 9 regions: the point where the
// resonance bands cross, the four other parts of the bands
// and the four remaining areas of the DP.
Double_t mass23 = m23NarrowRes.begin()->second;
Double_t width23 = m23NarrowRes.begin()->first;
Double_t resMin23 = mass23 - 5.0*width23;
Double_t resMax23 = mass23 + 5.0*width23;
Double_t mass13 = m13NarrowRes.begin()->second;
Double_t width13 = m13NarrowRes.begin()->first;
Double_t resMin13 = mass13 - 5.0*width13;
Double_t resMax13 = mass13 + 5.0*width13;
// if either resonance is close to threshold just go from
// threshold to resMax, otherwise treat threshold to resMin
// as a separate region
if ( resMin13 < (minm13+50.0*m13BinWidth_) && resMin23 < (minm23+50.0*m23BinWidth_) ) {
std::cout<<"INFO in LauIsobarDynamics::calcDPNormalisation : One narrow resonance found in m13 and one in m23, both close to threshold, dividing Dalitz plot into four regions..."<<std::endl;
m13BinWidth = m13BinWidth_;
m23BinWidth = m23BinWidth_;
this->calcDPPartialIntegral(resMax13, maxm13, resMax23, maxm23, m13BinWidth, m23BinWidth);
m13BinWidth = m13BinWidth_;
m23BinWidth = w23;
this->calcDPPartialIntegral(resMax13, maxm13, minm23, resMax23, m13BinWidth, m23BinWidth);
m13BinWidth = w13;
m23BinWidth = m23BinWidth_;
this->calcDPPartialIntegral(minm13, resMax13, resMax23, maxm23, m13BinWidth, m23BinWidth);
m13BinWidth = w13;
m23BinWidth = w23;
this->calcDPPartialIntegral(minm13, resMax13, minm23, resMax23, m13BinWidth, m23BinWidth);
} else if ( resMin13 < (minm13+50.0*m13BinWidth_) ) {
std::cout<<"INFO in LauIsobarDynamics::calcDPNormalisation : One narrow resonance found in m13, close to threshold, and one in m23, not close to threshold, dividing Dalitz plot into six regions..."<<std::endl;
this->calcDPPartialIntegral(resMax13, maxm13, minm23, resMin23, m13BinWidth, m23BinWidth);
this->calcDPPartialIntegral(resMax13, maxm13, resMax23, maxm23, m13BinWidth, m23BinWidth);
m13BinWidth = m13BinWidth_;
m23BinWidth = w23;
this->calcDPPartialIntegral(resMax13, maxm13, resMin23, resMax23, m13BinWidth, m23BinWidth);
m13BinWidth = w13;
m23BinWidth = m23BinWidth_;
this->calcDPPartialIntegral(minm13, resMax13, minm23, resMin23, m13BinWidth, m23BinWidth);
this->calcDPPartialIntegral(minm13, resMax13, resMax23, maxm23, m13BinWidth, m23BinWidth);
m13BinWidth = w13;
m23BinWidth = w23;
this->calcDPPartialIntegral(minm13, resMax13, resMin23, resMax23, m13BinWidth, m23BinWidth);
} else if ( resMin23 < (minm23+50.0*m23BinWidth_) ) {
std::cout<<"INFO in LauIsobarDynamics::calcDPNormalisation : One narrow resonance found in m23, close to threshold, and one in m13, not close to threshold, dividing Dalitz plot into six regions..."<<std::endl;
this->calcDPPartialIntegral(minm13, resMin13, resMax23, maxm23, m13BinWidth, m23BinWidth);
this->calcDPPartialIntegral(resMax13, maxm13, resMax23, maxm23, m13BinWidth, m23BinWidth);
m13BinWidth = m13BinWidth_;
m23BinWidth = w23;
this->calcDPPartialIntegral(minm13, resMin13, minm23, resMax23, m13BinWidth, m23BinWidth);
this->calcDPPartialIntegral(resMax13, maxm13, minm23, resMax23, m13BinWidth, m23BinWidth);
m13BinWidth = w13;
m23BinWidth = m23BinWidth_;
this->calcDPPartialIntegral(resMin13, resMax13, resMax23, maxm23, m13BinWidth, m23BinWidth);
m13BinWidth = w13;
m23BinWidth = w23;
this->calcDPPartialIntegral(resMin13, resMax13, minm23, resMax23, m13BinWidth, m23BinWidth);
} else {
std::cout<<"INFO in LauIsobarDynamics::calcDPNormalisation : One narrow resonance found in both m13 and m23, neither close to threshold, dividing Dalitz plot into nine regions..."<<std::endl;
this->calcDPPartialIntegral(minm13, resMin13, minm23, resMin23, m13BinWidth, m23BinWidth);
this->calcDPPartialIntegral(minm13, resMin13, resMax23, maxm23, m13BinWidth, m23BinWidth);
this->calcDPPartialIntegral(resMax13, maxm13, minm23, resMin23, m13BinWidth, m23BinWidth);
this->calcDPPartialIntegral(resMax13, maxm13, resMax23, maxm23, m13BinWidth, m23BinWidth);
m13BinWidth = m13BinWidth_;
m23BinWidth = w23;
this->calcDPPartialIntegral(minm13, resMin13, resMin23, resMax23, m13BinWidth, m23BinWidth);
this->calcDPPartialIntegral(resMax13, maxm13, resMin23, resMax23, m13BinWidth, m23BinWidth);
m13BinWidth = w13;
m23BinWidth = m23BinWidth_;
this->calcDPPartialIntegral(resMin13, resMax13, minm23, resMin23, m13BinWidth, m23BinWidth);
this->calcDPPartialIntegral(resMin13, resMax13, resMax23, maxm23, m13BinWidth, m23BinWidth);
m13BinWidth = w13;
m23BinWidth = w23;
this->calcDPPartialIntegral(resMin13, resMax13, resMin23, resMax23, m13BinWidth, m23BinWidth);
}
} else if ( e23 && s13>1 ) {
// We have multiple narrow resonances in m13 only.
// Divide the plot into 2 regions: threshold to the most
// massive of the narrow resonances, and the rest
std::cout<<"INFO in LauIsobarDynamics::calcDPNormalisation : Multiple narrow resonances found in m13, dividing Dalitz plot into two regions..."<<std::endl;
Double_t mass = 0.0;
Double_t width = 0.0;
for ( std::map<Double_t,Double_t>::const_iterator iter = m13NarrowRes.begin(); iter != m13NarrowRes.end(); ++iter ) {
if ( mass < iter->second ) {
mass = iter->second;
width = iter->first;
}
}
Double_t resMax = mass + 5.0*width;
this->calcDPPartialIntegral(resMax, maxm13, minm23, maxm23, m13BinWidth, m23BinWidth);
m13BinWidth = w13;
this->calcDPPartialIntegral(minm13, resMax, minm23, maxm23, m13BinWidth, m23BinWidth);
} else if ( e13 && s23>1 ) {
// We have multiple narrow resonances in m23 only.
// Divide the plot into 2 regions: threshold to the most
// massive of the narrow resonances, and the rest
std::cout<<"INFO in LauIsobarDynamics::calcDPNormalisation : Multiple narrow resonances found in m23, dividing Dalitz plot into two regions..."<<std::endl;
Double_t mass = 0.0;
Double_t width = 0.0;
for ( std::map<Double_t,Double_t>::const_iterator iter = m23NarrowRes.begin(); iter != m23NarrowRes.end(); ++iter ) {
if ( mass < iter->second ) {
mass = iter->second;
width = iter->first;
}
}
Double_t resMax = mass + 5.0*width;
this->calcDPPartialIntegral(minm13, maxm13, resMax, maxm23, m13BinWidth, m23BinWidth);
m23BinWidth = w23;
this->calcDPPartialIntegral(minm13, maxm13, minm23, resMax, m13BinWidth, m23BinWidth);
} else if ( s13==1 && s23>1 ) {
// We've got a single narrow resonance in m13 and multiple
// narrow resonances in m23. Divide the plot into 6 regions.
Double_t mass23 = 0.0;
Double_t width23 = 0.0;
for ( std::map<Double_t,Double_t>::const_iterator iter = m23NarrowRes.begin(); iter != m23NarrowRes.end(); ++iter ) {
if ( mass23 < iter->second ) {
mass23 = iter->second;
width23 = iter->first;
}
}
Double_t resMax23 = mass23 + 5.0*width23;
Double_t mass13 = m13NarrowRes.begin()->second;
Double_t width13 = m13NarrowRes.begin()->first;
Double_t resMin13 = mass13 - 5.0*width13;
Double_t resMax13 = mass13 + 5.0*width13;
// if the m13 resonance is close to threshold just go from
// threshold to resMax, otherwise treat threshold to resMin
// as a separate region
if ( resMin13 < (minm13+50.0*m13BinWidth_) ) {
std::cout<<"INFO in LauIsobarDynamics::calcDPNormalisation : Multiple narrow resonances found in m23 and one in m13, close to threshold, dividing Dalitz plot into four regions..."<<std::endl;
m13BinWidth = m13BinWidth_;
m23BinWidth = m23BinWidth_;
this->calcDPPartialIntegral(resMax13, maxm13, resMax23, maxm23, m13BinWidth, m23BinWidth);
m13BinWidth = m13BinWidth_;
m23BinWidth = w23;
this->calcDPPartialIntegral(resMax13, maxm13, minm23, resMax23, m13BinWidth, m23BinWidth);
m13BinWidth = w13;
m23BinWidth = m23BinWidth_;
this->calcDPPartialIntegral(minm13, resMax13, resMax23, maxm23, m13BinWidth, m23BinWidth);
m13BinWidth = w13;
m23BinWidth = w23;
this->calcDPPartialIntegral(minm13, resMax13, minm23, resMax23, m13BinWidth, m23BinWidth);
} else {
std::cout<<"INFO in LauIsobarDynamics::calcDPNormalisation : Multiple narrow resonances found in m23 and one in m13, not close to threshold, dividing Dalitz plot into six regions..."<<std::endl;
m13BinWidth = m13BinWidth_;
m23BinWidth = m23BinWidth_;
this->calcDPPartialIntegral(minm13, resMin13, resMax23, maxm23, m13BinWidth, m23BinWidth);
this->calcDPPartialIntegral(resMax13, maxm13, resMax23, maxm23, m13BinWidth, m23BinWidth);
m13BinWidth = m13BinWidth_;
m23BinWidth = w23;
this->calcDPPartialIntegral(minm13, resMin13, minm23, resMax23, m13BinWidth, m23BinWidth);
this->calcDPPartialIntegral(resMax13, maxm13, minm23, resMax23, m13BinWidth, m23BinWidth);
m13BinWidth = w13;
m23BinWidth = m23BinWidth_;
this->calcDPPartialIntegral(resMin13, resMax13, resMax23, maxm23, m13BinWidth, m23BinWidth);
m13BinWidth = w13;
m23BinWidth = w23;
this->calcDPPartialIntegral(resMin13, resMax13, minm23, resMax23, m13BinWidth, m23BinWidth);
}
} else if ( s13>1 && s23==1 ) {
// We've got a single narrow resonance in m23 and multiple
// narrow resonances in m13. Divide the plot into 6 regions.
Double_t mass13 = 0.0;
Double_t width13 = 0.0;
for ( std::map<Double_t,Double_t>::const_iterator iter = m13NarrowRes.begin(); iter != m13NarrowRes.end(); ++iter ) {
if ( mass13 < iter->second ) {
mass13 = iter->second;
width13 = iter->first;
}
}
Double_t resMax13 = mass13 + 5.0*width13;
Double_t mass23 = m23NarrowRes.begin()->second;
Double_t width23 = m23NarrowRes.begin()->first;
Double_t resMin23 = mass23 - 5.0*width23;
Double_t resMax23 = mass23 + 5.0*width23;
// if the m23 resonance is close to threshold just go from
// threshold to resMax, otherwise treat threshold to resMin
// as a separate region
if ( resMin23 < (minm23+50.0*m23BinWidth_) ) {
std::cout<<"INFO in LauIsobarDynamics::calcDPNormalisation : Multiple narrow resonances found in m13 and one in m23, close to threshold, dividing Dalitz plot into four regions..."<<std::endl;
m13BinWidth = m13BinWidth_;
m23BinWidth = m23BinWidth_;
this->calcDPPartialIntegral(resMax13, maxm13, resMax23, maxm23, m13BinWidth, m23BinWidth);
m13BinWidth = m13BinWidth_;
m23BinWidth = w23;
this->calcDPPartialIntegral(resMax13, maxm13, minm23, resMax23, m13BinWidth, m23BinWidth);
m13BinWidth = w13;
m23BinWidth = m23BinWidth_;
this->calcDPPartialIntegral(minm13, resMax13, resMax23, maxm23, m13BinWidth, m23BinWidth);
m13BinWidth = w13;
m23BinWidth = w23;
this->calcDPPartialIntegral(minm13, resMax13, minm23, resMax23, m13BinWidth, m23BinWidth);
} else {
std::cout<<"INFO in LauIsobarDynamics::calcDPNormalisation : Multiple narrow resonances found in m13 and one in m23, not close to threshold, dividing Dalitz plot into six regions..."<<std::endl;
this->calcDPPartialIntegral(resMax13, maxm13, minm23, resMin23, m13BinWidth, m23BinWidth);
this->calcDPPartialIntegral(resMax13, maxm13, resMax23, maxm23, m13BinWidth, m23BinWidth);
m13BinWidth = m13BinWidth_;
m23BinWidth = w23;
this->calcDPPartialIntegral(resMax13, maxm13, resMin23, resMax23, m13BinWidth, m23BinWidth);
m13BinWidth = w13;
m23BinWidth = m23BinWidth_;
this->calcDPPartialIntegral(minm13, resMax13, minm23, resMin23, m13BinWidth, m23BinWidth);
this->calcDPPartialIntegral(minm13, resMax13, resMax23, maxm23, m13BinWidth, m23BinWidth);
m13BinWidth = w13;
m23BinWidth = w23;
this->calcDPPartialIntegral(minm13, resMax13, resMin23, resMax23, m13BinWidth, m23BinWidth);
}
} else {
// We've got multiple narrow resonances in both m13 and m23.
// Divide the plot into 4 regions.
std::cout<<"INFO in LauIsobarDynamics::calcDPNormalisation : Multiple narrow resonances found in both m13 and m23, dividing Dalitz plot into four regions..."<<std::endl;
Double_t mass13 = 0.0;
Double_t width13 = 0.0;
for ( std::map<Double_t,Double_t>::const_iterator iter = m13NarrowRes.begin(); iter != m13NarrowRes.end(); ++iter ) {
if ( mass13 < iter->second ) {
mass13 = iter->second;
width13 = iter->first;
}
}
Double_t resMax13 = mass13 + 5.0*width13;
Double_t mass23 = 0.0;
Double_t width23 = 0.0;
for ( std::map<Double_t,Double_t>::const_iterator iter = m23NarrowRes.begin(); iter != m23NarrowRes.end(); ++iter ) {
if ( mass23 < iter->second ) {
mass23 = iter->second;
width23 = iter->first;
}
}
Double_t resMax23 = mass23 + 5.0*width23;
m13BinWidth = m13BinWidth_;
m23BinWidth = m23BinWidth_;
this->calcDPPartialIntegral(resMax13, maxm13, resMax23, maxm23, m13BinWidth, m23BinWidth);
m13BinWidth = m13BinWidth_;
m23BinWidth = w23;
this->calcDPPartialIntegral(resMax13, maxm13, minm23, resMax23, m13BinWidth, m23BinWidth);
m13BinWidth = w13;
m23BinWidth = m23BinWidth_;
this->calcDPPartialIntegral(minm13, resMax13, resMax23, maxm23, m13BinWidth, m23BinWidth);
m13BinWidth = w13;
m23BinWidth = w23;
this->calcDPPartialIntegral(minm13, resMax13, minm23, resMax23, m13BinWidth, m23BinWidth);
}
}
void LauIsobarDynamics::setIntegralBinWidths(Double_t m13BinWidth, Double_t m23BinWidth)
{
// Specify whether we're going to use Gauss-Legendre integration to calculate the normalisation
// integrals, and the bin widths we require for the m13 and m23 axes. Note that the integration
// is done over m13, m23 space, with the appropriate Jacobian applied, and not m13^2, m23^2 space.
// The default bin widths in m13 and m23 space are 5 MeV.
m13BinWidth_ = m13BinWidth;
m23BinWidth_ = m23BinWidth;
}
void LauIsobarDynamics::calcDPPartialIntegral(Double_t minm13, Double_t maxm13, Double_t minm23, Double_t maxm23,
Double_t m13BinWidth, Double_t m23BinWidth)
{
// Calculate the total DP area, as well as finding the normalisation terms for
// the signal resonances
Int_t i(0), j(0);
Double_t precision(1e-6);
Double_t meanm13 = 0.5*(minm13 + maxm13);
Double_t rangem13 = maxm13 - minm13;
Double_t halfRangem13 = 0.5*rangem13;
Double_t meanm23 = 0.5*(minm23 + maxm23);
Double_t rangem23 = maxm23 - minm23;
Double_t halfRangem23 = 0.5*rangem23;
Double_t intFactor = halfRangem13*halfRangem23;
// Choose smallest of mass ranges to set number of bins, given specified bin width
Int_t nm13Points = static_cast<Int_t>((rangem13/m13BinWidth));
Int_t nm23Points = static_cast<Int_t>((rangem23/m23BinWidth));
// Avoid integral if we have no points in either x or y space
if (nm13Points == 0 || nm23Points == 0) {return;}
std::cout<<"INFO in LauIsobarDynamics::calcDPPartialIntegral : nm13Points = "<<nm13Points<<", nm23Points = "<<nm23Points<<std::endl;
std::cout<<" : m13BinWidth = "<<m13BinWidth<<", m23BinWidth = "<<m23BinWidth<<std::endl;
std::cout<<" : Integrating over m13 = "<<minm13<<" to "<<maxm13<<", m23 = "<<minm23<<" to "<<maxm23<<std::endl;
LauIntegrals DPIntegrals(precision);
std::vector<Double_t> m13Weights, m23Weights;
std::vector<Double_t> m13Abscissas, m23Abscissas;
DPIntegrals.calcGaussLegendreWeights(nm13Points, m13Abscissas, m13Weights);
DPIntegrals.calcGaussLegendreWeights(nm23Points, m23Abscissas, m23Weights);
Int_t nm13Weights = static_cast<Int_t>(m13Weights.size());
Int_t nm23Weights = static_cast<Int_t>(m23Weights.size());
//std::cout<<" : nm13Weights = "<<nm13Weights<<", nm23Weights = "<<nm23Weights<<std::endl;
// Print out abscissas and weights for the integration
Double_t totm13Weight(0.0), totm23Weight(0.0);
for (i = 0; i < nm13Weights; i++) {
totm13Weight += m13Weights[i];
}
for (i = 0; i < nm23Weights; i++) {
totm23Weight += m23Weights[i];
}
std::cout<<" : totm13Weight = "<<totm13Weight<<", totm23Weight = "<<totm23Weight<<std::endl;
std::vector<Double_t> m13(nm13Weights), m23(nm23Weights);
std::vector<Double_t> m13Sq(nm13Weights), m23Sq(nm23Weights);
// Use same number of abscissas for x and y co-ordinates
Int_t m = (nm13Weights + 1)/2;
for (i = 0; i < m; i++) {
Int_t ii = nm13Weights - 1 - i; // symmetric i index
Double_t dm13 = halfRangem13*m13Abscissas[i];
Double_t m13Val = meanm13 - dm13;
m13[i] = m13Val;
m13Sq[i] = m13Val*m13Val;
m13Val = meanm13 + dm13;
m13[ii] = m13Val;
m13Sq[ii] = m13Val*m13Val;
}
m = (nm23Weights +1)/2;
for (i = 0; i < m; i++) {
Int_t ii = nm23Weights - 1 - i; // symmetric i index
Double_t dm23 = halfRangem23*m23Abscissas[i];
Double_t m23Val = meanm23 - dm23;
m23[i] = m23Val;
m23Sq[i] = m23Val*m23Val;
m23Val = meanm23 + dm23;
m23[ii] = m23Val;
m23Sq[ii] = m23Val*m23Val;
}
// Now compute the integral
Double_t dpArea(0.0);
for (i = 0; i < nm13Weights; i++) {
for (j = 0; j < nm23Weights; j++) {
Double_t weight = m13Weights[i]*m23Weights[j];
Double_t Jacobian = 4.0*m13[i]*m23[j];
weight *= (Jacobian*intFactor);
// Calculate the integral contributions for each resonance.
// Only resonances within the DP area contribute.
// This also calculates the total DP area as a check.
Bool_t withinDP = kinematics_->withinDPLimits(m13Sq[i], m23Sq[j]);
if (withinDP == kTRUE) {
kinematics_->updateKinematics(m13Sq[i], m23Sq[j]);
this->dynamics(kFALSE, 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 = "<<dpArea<<std::endl;
}
void LauIsobarDynamics::dynamics(Bool_t cacheResData, Double_t weight, Bool_t useEff)
{
// Routine that calculates the Dalitz plot amplitude, incorporating
// resonance dynamics (using resAmp()) and any interference between them.
// Used by the fit() and sigGen() functions.
UInt_t i(0), j(0);
// Reset the total amplitude to zero
totAmp_.zero();
// Loop over the number of resonance amplitudes defined in the model
// Have we already calculated this for this event (during fit?)
// Or do we have a resonance that has varying pole mass/width/other factors?
if (cacheResData == kFALSE) {
for (i = 0; i < nAmp_; i++) {
// Calculate the dynamics for this resonance, using the resAmp function.
ff_[i] = resAmp(i);
//std::cout<<"ff_["<<i<<"] = "<<ff_[i]<<std::endl;
// If we have a symmetrical Dalitz plot, flip the m_13^2 and m_23^2
// variables, recalculate the dynamics, and average both contributions.
// Although, the factor of 0.5 cancels out with the fact that
// the resonance appears on both sides of the Dalitz plot.
if (symmetricalDP_ == kTRUE) { // was tieSg_ == 12
kinematics_->flipAndUpdateKinematics();
ff_[i] += resAmp(i);
// Flip the m_13^2 and m_23^2 variables back to their original values
kinematics_->flipAndUpdateKinematics();
}
} // Loop over amplitudes
// If we haven't cached the data, then we need to find out the efficiency.
eff_ = this->retrieveEfficiency();
} // Already cached data?
if (integralsDone_ == kTRUE) {
// Loop over all signal amplitudes
LauComplex ATerm;
for (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
//std::cout<<"For i = "<<i<<", ATerm = "<<ATerm<<", Amp = "<<Amp_[i]<<", ff = "<<ff_[i]<<std::endl;
totAmp_ += ATerm;
} // Loop over amplitudes
// |Sum of partial amplitudes|^2
ASq_ = totAmp_.abs2();
// Apply the efficiency correction for this event.
// Multiply the amplitude squared sum by the DP efficiency
if ( useEff ) {
ASq_ *= eff_;
}
} else { // integrals not done
// Find the efficiency correction to be applied for this event.
eff_ = this->retrieveEfficiency();
Double_t effWeight = eff_*weight;
// Need this for integrals for normalisation of likelihood function.
LauComplex fifjEffSumTerm;
LauComplex fifjSumTerm;
for (i = 0; i < nAmp_; i++) {
// Add the dynamical amplitude squared for this resonance.
Double_t fSqVal = ff_[i].abs2();
fSqSum_[i] += fSqVal*weight;
for (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;
}
}
}
}
LauComplex LauIsobarDynamics::resAmp(Int_t index)
{
// Routine to calculate the resonance dynamics (amplitude)
// using the appropriate Breit-Wigner/Form Factors.
// Called by the dynamics() function.
// Get the signal resonance from the stored vector
LauAbsResonance* sigResonance = sigResonances_[index];
if (sigResonance == 0) {
std::cout<<"ERROR in LauIsobarDynamics::resAmp : Couldn't retrieve resonance with index = "<<index<<std::endl;
return LauComplex(0.0, 0.0);
}
// Get the integer index of the resonance.
Int_t resInt = resIntAmp_[index];
LauComplex resAmplitude(0.0, 0.0);
- if (resInt < 0 || resInt >= static_cast<Int_t>(this->getnDefinedResonances())) {
+ if ( resInt < 0 || resInt >= static_cast<Int_t>(LauResonanceMaker::get().getNResDefMax()) ) {
std::cout<<"ERROR in LauIsobarDynamics::resAmp : Probably bad resonance name."<<std::endl;
resAmplitude = LauComplex(0.0, 0.0);
} else {
resAmplitude = sigResonance->amplitude(kinematics_);
}
return resAmplitude;
}
void LauIsobarDynamics::setFFTerm(UInt_t index, Double_t realPart, Double_t imagPart)
{
// Function to set the internal ff = resAmp() term.
if ( index >= nAmp_ ) {
std::cerr<<"ERROR in LauIsobarDynamics::setFFTerm : index = "<<index<<" is not within the range 0 and "<<nAmp_-1<<". Bailing out."<<std::endl;
return;
}
ff_[index].setRealImagPart( realPart, imagPart );
}
void LauIsobarDynamics::calcExtraInfo(Bool_t init)
{
// This method calculates the fit fractions, mean efficiency and total DP rate
Double_t fifjEffTot(0.0), fifjTot(0.0);
UInt_t i, j;
for (i = 0; i < nAmp_; i++) {
// Calculate the diagonal terms
TString name = "A"; name += i; name += "Sq_FitFrac";
fitFrac_[i][i].name(name);
Double_t fifjSumReal = fifjSum_[i][i].re();
Double_t sumTerm = Amp_[i].abs2()*fifjSumReal*fNorm_[i]*fNorm_[i];
fifjTot += sumTerm;
Double_t fifjEffSumReal = fifjEffSum_[i][i].re();
Double_t sumEffTerm = Amp_[i].abs2()*fifjEffSumReal*fNorm_[i]*fNorm_[i];
fifjEffTot += sumEffTerm;
fitFrac_[i][i] = sumTerm;
}
for (i = 0; i < nAmp_; i++) {
for (j = i+1; j < nAmp_; j++) {
// Calculate the cross-terms
TString name = "A"; name += i; name += "A"; name += j; name += "_FitFrac";
fitFrac_[i][j].name(name);
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] = crossTerm;
}
}
if (TMath::Abs(fifjTot) > 1e-10) {
meanDPEff_ = fifjEffTot/fifjTot;
if (init) {
meanDPEff_.genValue( meanDPEff_.value() );
meanDPEff_.initValue( meanDPEff_.value() );
}
}
DPRate_ = 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_; i++) {
for (j = i; j < nAmp_; j++) {
// Get the actual fractions by dividing by the total DP rate
fitFrac_[i][j] /= fifjTot;
if (init) {
fitFrac_[i][j].genValue( fitFrac_[i][j].value() );
fitFrac_[i][j].initValue( fitFrac_[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] = kMatrixTotFitFrac;
if (init) {
extraParameters_[propInt].genValue(kMatrixTotFitFrac);
extraParameters_[propInt].initValue(kMatrixTotFitFrac);
}
std::cout<<"INFO in LauIsobarDynamics::calcExtraInfo : Total K-matrix fit fraction for propagator "<<propName<<" is "<<kMatrixTotFitFrac<<std::endl;
++propInt;
}
}
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];
}
}
return DPNorm_;
}
Bool_t LauIsobarDynamics::generate()
{
// Routine to generate a signal event according to the Dalitz plot
// model we have defined.
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
if ( symmetricalDP_ && m13Sq > m23Sq ) {
Double_t tmpSq = m13Sq;
m13Sq = m23Sq;
m23Sq = tmpSq;
}
// calculates the amplitudes and total amplitude for the given DP point
this->calcLikelihoodInfo(m13Sq, m23Sq);
if (integralsDone_ == kTRUE) {
// No need for efficiency correction here. It is already done in
// the dynamics() function (unlike the Fortran version).
// Very important line to avoid bias in MC generation for the accept/reject method.
// Make sure that the total amplitude squared is below some number, given
// by aSqMaxSet_. If it is, then the event is valid.
// Otherwise, go through another toy MC loop until we can generate the event
// OK, or until we reach the maximum iteration limit.
Double_t randNo = LauRandom::randomFun()->Rndm();
if (randNo > ASq_/aSqMaxSet_) {
nSigGenLoop_++;
} else {
generatedSig = kTRUE;
nSigGenLoop_ = 0;
if (ASq_ > aSqMaxVar_) {aSqMaxVar_ = ASq_;}
}
} else {
// For toy MC numerical integration only
generatedSig = kTRUE;
}
} // while loop
Bool_t sigGenOK(kTRUE);
if (GenOK != this->checkToyMC(kFALSE,kFALSE)) {
sigGenOK = kFALSE;
}
return sigGenOK;
}
LauAbsDPDynamics::ToyMCStatus LauIsobarDynamics::checkToyMC(Bool_t printErrorMessages, Bool_t printInfoMessages)
{
// Check whether we have generated the toy MC OK.
ToyMCStatus ok(GenOK);
if (nSigGenLoop_ >= iterationsMax_) {
if (printErrorMessages) {
std::cerr<<"WARNING in LauIsobarDynamics::checkToyMC : More than "<<iterationsMax_<<" iterations required."<<std::endl;
std::cerr<<" : Try to decrease the maximum allowed value of the total amplitude squared using the "
<<"LauIsobarDynamics::setASqMaxValue(Double_t) function and re-run."<<std::endl;
std::cerr<<" : This needs to be, perhaps significantly, less than "<<aSqMaxSet_<<std::endl;
std::cerr<<" : Maximum value of ASq so far = "<<aSqMaxVar_<<std::endl;
}
aSqMaxSet_ = 1.01 * aSqMaxVar_;
std::cout<<"INFO in LauIsobarDynamics::checkToyMC : |A|^2 max reset to "<<aSqMaxSet_<<std::endl;
ok = MaxIterError;
} else if (aSqMaxVar_ > aSqMaxSet_) {
if (printErrorMessages) {
std::cerr<<"WARNING in LauIsobarDynamics::checkToyMC : aSqMaxSet_ was set to "<<aSqMaxSet_<<" but actual aSqMax was "<<aSqMaxVar_<<std::endl;
std::cerr<<" : Run was invalid, as any generated MC will be biased, according to the accept/reject method!"<<std::endl;
std::cerr<<" : Please set aSqMaxSet >= "<<aSqMaxVar_<<" using the LauIsobarDynamics::setASqMaxValue(Double_t) function and re-run."<<std::endl;
}
aSqMaxSet_ = 1.01 * aSqMaxVar_;
std::cout<<"INFO in LauIsobarDynamics::checkToyMC : |A|^2 max reset to "<<aSqMaxSet_<<std::endl;
ok = ASqMaxError;
} else if (printInfoMessages) {
std::cout<<"INFO in LauIsobarDynamics::checkToyMC : aSqMaxSet = "<<aSqMaxSet_<<" and aSqMaxVar = "<<aSqMaxVar_<<std::endl;
}
return ok;
}
void LauIsobarDynamics::setDataEventNo(UInt_t iEvt)
{
this->LauAbsDPDynamics::setDataEventNo(iEvt);
m13Sq_ = currentEvent_->retrievem13Sq();
m23Sq_ = currentEvent_->retrievem23Sq();
mPrime_ = currentEvent_->retrievemPrime();
thPrime_ = currentEvent_->retrievethPrime();
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(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
for (UInt_t i = 0; i < nAmp_; i++) {
this->setFFTerm(i, currentEvent_->retrieveRealAmp()[i], currentEvent_->retrieveImagAmp()[i]);
}
// Update the dynamics - calculates totAmp_ and then ASq_ = totAmp_.abs2() * eff_
// All calculated using cached information on the individual amplitudes and efficiency.
this->dynamics(kTRUE, 1.0);
// Calculate the normalised matrix element squared value
if (DPNorm_ > 1e-10) {
evtLike_ = ASq_/DPNorm_;
}
}
void LauIsobarDynamics::calcLikelihoodInfo(Double_t m13Sq, Double_t m23Sq)
{
this->calcLikelihoodInfo(m13Sq, m23Sq, -1);
}
void LauIsobarDynamics::calcLikelihoodInfo(Double_t m13Sq, Double_t m23Sq, 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) {
// If cacheResData == kFALSE, updateKinematics has been called before dynamics(). Then get Jacobian.
jacobian_ = kinematics_->calcSqDPJacobian();
}
// calculates the ff_ terms and retrieves eff_ from the efficiency model
// then calculates totAmp_ and finally ASq_ = totAmp_.abs2() * eff_
this->dynamics(kFALSE, 1.0);
// Calculate the normalised matrix element squared value
if (DPNorm_ > 1e-10) {
evtLike_ = ASq_/DPNorm_;
}
}
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.
UInt_t nBranches = inputFitTree.nBranches();
if (nBranches < 2) {
std::cout<<"ERROR in LauIsobarDynamics::fillDataTree : Expecting at least 2 variables "
<<"in input data tree, but there are "<<nBranches<<"! Make sure you have "
<<"the right number of variables in your input data file!"<<std::endl;
gSystem->Exit(-1);
}
// Data structure that will cache the variables required to
// calculate the signal likelihood for this experiment
for ( std::vector<LauCacheData*>::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<Double_t> 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<Int_t>(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]->storeEff(eff);
data_[iEvt]->storeScfFraction(scfFraction);
data_[iEvt]->storeJacobian(jacobian);
data_[iEvt]->storeRealAmp(realAmp);
data_[iEvt]->storeImagAmp(imagAmp);
}
}
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);
this->dynamics(kFALSE, 1.0, 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 dynamics from the current kinematics
this->dynamics(kFALSE, 1.0, kFALSE);
if (ASq_ > aSqMaxVar_) {aSqMaxVar_ = ASq_;}
// return the event weight = the value of the squared amplitude divided
// by the user-defined ceiling
return ASq_ / aSqMaxSet_;
}
diff --git a/src/LauKMatrixProdPole.cc b/src/LauKMatrixProdPole.cc
index dfccfac..4b06303 100644
--- a/src/LauKMatrixProdPole.cc
+++ b/src/LauKMatrixProdPole.cc
@@ -1,78 +1,78 @@
-// Copyright University of Warwick 2008 - 2013.
+// Copyright University of Warwick 2008 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauKMatrixProdPole.cc
\brief File containing implementation of LauKMatrixProdPole class.
*/
#include "LauKMatrixProdPole.hh"
#include "LauKMatrixPropagator.hh"
#include <iostream>
ClassImp(LauKMatrixProdPole)
LauKMatrixProdPole::LauKMatrixProdPole(const TString& poleName, Int_t poleIndex, Int_t resPairAmpInt,
LauKMatrixPropagator* propagator, const LauDaughters* daughters) :
- LauAbsResonance(poleName, 0.0, 0.0, 0, 0, resPairAmpInt, daughters),
+ LauAbsResonance(poleName, 0, 0, 0, 0, resPairAmpInt, daughters),
thePropagator_(propagator),
poleIndex_(poleIndex - 1) // poleIndex goes from 1 to nPoles
{
}
LauKMatrixProdPole::~LauKMatrixProdPole()
{
}
LauComplex LauKMatrixProdPole::resAmp(Double_t mass, Double_t spinTerm)
{
std::cerr << "ERROR in LauKMatrixProdPole::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);
}
LauComplex LauKMatrixProdPole::amplitude(const LauKinematics* kinematics)
{
// Calculate the amplitude for the K-matrix production pole.
// First, make sure the K-matrix propagator is up-to-date for
// the given centre-of-mass squared value ("s") from the kinematics.
LauComplex amp(0.0, 0.0);
if (thePropagator_ == 0) {
std::cerr << "ERROR in LauKMatrixProdPole::amplitude : The propagator is null" << std::endl;
return amp;
}
thePropagator_->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_);
amp.rescale(poleDenom);
return amp;
}
diff --git a/src/LauKMatrixProdSVP.cc b/src/LauKMatrixProdSVP.cc
index 243f327..d1dec43 100644
--- a/src/LauKMatrixProdSVP.cc
+++ b/src/LauKMatrixProdSVP.cc
@@ -1,66 +1,66 @@
-// Copyright University of Warwick 2008 - 2013.
+// Copyright University of Warwick 2008 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauKMatrixProdSVP.cc
\brief File containing implementation of LauKMatrixProdSVP class.
*/
#include "LauKMatrixProdSVP.hh"
#include "LauKMatrixPropagator.hh"
#include <iostream>
ClassImp(LauKMatrixProdSVP)
LauKMatrixProdSVP::LauKMatrixProdSVP(const TString& poleName, Int_t channelIndex, Int_t resPairAmpInt,
LauKMatrixPropagator* propagator, const LauDaughters* daughters) :
- LauAbsResonance(poleName, 0.0, 0.0, 0, 0, resPairAmpInt, daughters),
+ LauAbsResonance(poleName, 0, 0, 0, 0, resPairAmpInt, daughters),
thePropagator_(propagator),
channelIndex_(channelIndex - 1) // channelIndex goes from 1 to nChannels.
{
// Constructor
}
LauKMatrixProdSVP::~LauKMatrixProdSVP()
{
// Destructor
}
LauComplex LauKMatrixProdSVP::resAmp(Double_t mass, Double_t spinTerm)
{
std::cerr << "ERROR in LauKMatrixProdSVP::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);
}
LauComplex LauKMatrixProdSVP::amplitude(const LauKinematics* kinematics)
{
// Calculate the amplitude for the K-matrix production pole.
// First, make sure the K-matrix propagator is up-to-date for
// the given centre-of-mass squared value ("s") from the kinematics.
LauComplex amp(0.0, 0.0);
if (thePropagator_ == 0) {
std::cerr << "ERROR in LauKMatrixProdSVP::amplitude : The propagator is null" << std::endl;
return amp;
}
thePropagator_->updatePropagator(kinematics);
Double_t SVPTerm = thePropagator_->getProdSVPTerm();
amp = thePropagator_->getPropTerm(channelIndex_);
amp.rescale(SVPTerm);
return amp;
}
diff --git a/src/LauKappaRes.cc b/src/LauKappaRes.cc
index 3cd1afa..f250b5f 100644
--- a/src/LauKappaRes.cc
+++ b/src/LauKappaRes.cc
@@ -1,131 +1,131 @@
-// Copyright University of Warwick 2004 - 2013.
+// Copyright University of Warwick 2004 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauKappaRes.cc
\brief File containing implementation of LauKappaRes class.
*/
#include <iostream>
#include "LauConstants.hh"
#include "LauKappaRes.hh"
ClassImp(LauKappaRes)
-LauKappaRes::LauKappaRes(TString resName, Double_t resMass, Double_t resWidth, Int_t resSpin,
+LauKappaRes::LauKappaRes(TString resName, LauParameter* resMass, LauParameter* resWidth, Int_t resSpin,
Int_t resCharge, Int_t resPairAmpInt, const LauDaughters* daughters) :
LauAbsResonance(resName, resMass, resWidth, resSpin, resCharge, resPairAmpInt, daughters),
mSum_(0.0),
mSumSq_(0.0),
sAdler_(0.0),
b1_(0.0),
b2_(0.0),
A_(0.0),
m0_(0.0),
m0Sq_(0.0),
denom_(0.0)
{
// Initialise various constants
mSum_ = LauConstants::mPi + LauConstants::mK;
mSumSq_ = mSum_*mSum_;
sAdler_ = LauConstants::mKSq - LauConstants::mPiSq*0.5; // Adler zero at (mK)^2 - 0.5*(mpi)^2
// Default constant factors from BES data
Double_t b1 = 24.49;
Double_t b2 = 0.0;
Double_t A = 2.5;
Double_t m0 = 3.3;
this->setConstants( b1, b2, A, m0 );
}
LauKappaRes::~LauKappaRes()
{
}
void LauKappaRes::initialise()
{
this->checkDaughterTypes();
Double_t resSpin = this->getSpin();
if (resSpin != 0) {
std::cerr << "ERROR in LauKappaRes : spin = " << resSpin << " is not zero!" << std::endl;
}
}
void LauKappaRes::setConstants(Double_t b1, Double_t b2, Double_t A, Double_t m0) {
b1_ = b1;
b2_ = b2;
A_ = A;
m0_ = m0;
m0Sq_ = m0_*m0_;
denom_ = m0Sq_ - sAdler_;
}
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;
}
// Check that daughter types agree
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);}
Double_t f = b2_*s + b1_; // f(s) function
Double_t numerator = s - sAdler_;
Double_t gamma(0.0);
if (TMath::Abs(denom_) > 1e-10 && TMath::Abs(A_) > 1e-10) {
// Decay width of the system
gamma = rho*(numerator/denom_)*f*TMath::Exp(-(s - m0Sq_)/A_);
}
// 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*m0_;
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;
}
diff --git a/src/LauLASSBWRes.cc b/src/LauLASSBWRes.cc
index f24d2e2..f1e7a7f 100644
--- a/src/LauLASSBWRes.cc
+++ b/src/LauLASSBWRes.cc
@@ -1,169 +1,169 @@
-// Copyright University of Warwick 2008 - 2013.
+// Copyright University of Warwick 2008 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauLASSBWRes.cc
\brief File containing implementation of LauLASSBWRes class.
*/
#include <iostream>
#include "LauConstants.hh"
#include "LauLASSBWRes.hh"
ClassImp(LauLASSBWRes)
-LauLASSBWRes::LauLASSBWRes(TString resName, Double_t resMass, Double_t resWidth, Int_t resSpin,
+LauLASSBWRes::LauLASSBWRes(TString resName, LauParameter* resMass, LauParameter* resWidth, Int_t resSpin,
Int_t resCharge, Int_t resPairAmpInt, const LauDaughters* daughters) :
LauAbsResonance(resName, resMass, resWidth, resSpin, resCharge, resPairAmpInt, daughters),
q0_(0.0),
mDaugSum_(0.0),
mDaugSumSq_(0.0),
mDaugDiff_(0.0),
mDaugDiffSq_(0.0),
resMassSq_(0.0),
r_(0.0),
a_(0.0),
B_(0.0),
R_(0.0),
phiB_(0.0),
phiR_(0.0),
cutOff_(0.0)
{
// Default values for LASS parameters
r_ = 3.32;
a_ = 2.07;
R_ = 1.0;
B_ = 1.0;
phiR_ = 0.0;
phiB_ = 0.0;
cutOff_ = 1.8;
}
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_;
// Decay momentum of either daughter in the resonance rest frame
// when resonance mass = rest-mass value, m_0 (PDG value)
Double_t resMass = this->getMass();
resMassSq_ = resMass*resMass;
q0_ = TMath::Sqrt((resMassSq_ - mDaugSumSq_)*(resMassSq_ - mDaugDiffSq_))/(2.0*resMass);
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 );
}
}
LauComplex LauLASSBWRes::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 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
Double_t q = this->getQ();
Double_t resMass = this->getMass();
Double_t resWidth = this->getWidth();
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(spinTerm*(resMassSq_*resWidth/q0_)/(massSqTerm*massSqTerm + resMassSq_*totWidth*totWidth));
// Calculate the phase shift term
Double_t deltaB = TMath::ATan((2.0*a_*q)/(2.0 + a_*r_*q*q));
Double_t cos2PhaseShift = TMath::Cos(2.0*(deltaB + phiB_));
Double_t sin2PhaseShift = TMath::Sin(2.0*(deltaB + phiB_));
LauComplex phaseShift(cos2PhaseShift, sin2PhaseShift);
// Add in the R e^{i phiR} term
Double_t reR = R_ * TMath::Cos(phiR_);
Double_t imR = R_ * TMath::Sin(phiR_);
LauComplex R(reR, imR);
// Multiply by the phase shift and R e^{i phiR}
resAmplitude = resAmplitude * phaseShift * R;
// There is no spin term for the LASS shape
// Just set it 1.0 in case anyone decides to use it at a later date.
spinTerm = 1.0;
return resAmplitude;
}
void LauLASSBWRes::setResonanceParameter(Double_t value, const TString& name)
{
// 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 if (name == "R") {
this->setResonanceMag(value);
std::cout << "INFO in LauLASSBWRes::setResonanceParameter : Setting LASS Resonance Magnitude = " << this->getResonanceMag() << std::endl;
}
else if (name == "B") {
this->setBackgroundMag(value);
std::cout << "INFO in LauLASSBWRes::setResonanceParameter : Setting LASS Background Magnitude = " << this->getBackgroundMag() << std::endl;
}
else if (name == "phiR") {
this->setResonancePhase(value);
std::cout << "INFO in LauLASSBWRes::setResonanceParameter : Setting LASS Resonance Phase = " << this->getResonancePhase() << std::endl;
}
else if (name == "phiB") {
this->setBackgroundPhase(value);
std::cout << "INFO in LauLASSBWRes::setResonanceParameter : Setting LASS Background Phase = " << this->getBackgroundPhase() << std::endl;
}
else if (name == "cutOff") {
this->setCutOff(value);
std::cout << "INFO in LauLASSBWRes::setResonanceParameter : Setting LASS Cut Off = " << this->getCutOff() << std::endl;
}
else {
std::cerr << "WARNING in LauLASSBWRes::setResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl;
}
}
diff --git a/src/LauLASSNRRes.cc b/src/LauLASSNRRes.cc
index eefd18e..3888e43 100644
--- a/src/LauLASSNRRes.cc
+++ b/src/LauLASSNRRes.cc
@@ -1,158 +1,158 @@
-// Copyright University of Warwick 2008 - 2013.
+// Copyright University of Warwick 2008 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauLASSNRRes.cc
\brief File containing implementation of LauLASSNRRes class.
*/
#include <iostream>
#include "LauConstants.hh"
#include "LauLASSNRRes.hh"
ClassImp(LauLASSNRRes)
-LauLASSNRRes::LauLASSNRRes(TString resName, Double_t resMass, Double_t resWidth, Int_t resSpin,
+LauLASSNRRes::LauLASSNRRes(TString resName, LauParameter* resMass, LauParameter* resWidth, Int_t resSpin,
Int_t resCharge, Int_t resPairAmpInt, const LauDaughters* daughters) :
LauAbsResonance(resName, resMass, resWidth, resSpin, resCharge, resPairAmpInt, daughters),
q0_(0.0),
mDaugSum_(0.0),
mDaugSumSq_(0.0),
mDaugDiff_(0.0),
mDaugDiffSq_(0.0),
resMassSq_(0.0),
r_(0.0),
a_(0.0),
B_(0.0),
R_(0.0),
phiB_(0.0),
phiR_(0.0),
cutOff_(0.0)
{
// Default values for LASS parameters
r_ = 3.32;
a_ = 2.07;
R_ = 1.0;
B_ = 1.0;
phiR_ = 0.0;
phiB_ = 0.0;
cutOff_ = 1.8;
}
LauLASSNRRes::~LauLASSNRRes()
{
}
void LauLASSNRRes::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_;
// Decay momentum of either daughter in the resonance rest frame
// when resonance mass = rest-mass value, m_0 (PDG value)
Double_t resMass = this->getMass();
resMassSq_ = resMass*resMass;
q0_ = TMath::Sqrt((resMassSq_ - mDaugSumSq_)*(resMassSq_ - mDaugDiffSq_))/(2.0*resMass);
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)
{
// This function returns the complex dynamical amplitude for a Breit-Wigner resonance,
// given the invariant mass and cos(helicity) values.
LauComplex totAmplitude(0.0, 0.0);
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);
}
// q is the momentum of either daughter in the resonance rest-frame
Double_t q = this->getQ();
// Calculate the phase shift term
Double_t deltaB = TMath::ATan((2.0*a_*q)/(2.0 + a_*r_*q*q));
// Form the real and imaginary parts
Double_t realTerm = q/TMath::Tan(deltaB + phiB_);
Double_t imagTerm = q;
// Compute the complex amplitude
bkgAmplitude = LauComplex(realTerm, imagTerm);
// Scale by the numerator and denominator factors
bkgAmplitude.rescale(spinTerm*mass*B_/(realTerm*realTerm + imagTerm*imagTerm));
if (mass < cutOff_) {
totAmplitude = bkgAmplitude;
}
// There is no spin term for the LASS shape
// Just set it 1.0 in case anyone decides to use it at a later date.
spinTerm = 1.0;
return totAmplitude;
}
void LauLASSNRRes::setResonanceParameter(Double_t value, const TString& name)
{
// 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 if (name == "R") {
this->setResonanceMag(value);
std::cout << "INFO in LauLASSNRRes::setResonanceParameter : Setting LASS Resonance Magnitude = " << this->getResonanceMag() << std::endl;
}
else if (name == "B") {
this->setBackgroundMag(value);
std::cout << "INFO in LauLASSNRRes::setResonanceParameter : Setting LASS Background Magnitude = " << this->getBackgroundMag() << std::endl;
}
else if (name == "phiR") {
this->setResonancePhase(value);
std::cout << "INFO in LauLASSNRRes::setResonanceParameter : Setting LASS Resonance Phase = " << this->getResonancePhase() << std::endl;
}
else if (name == "phiB") {
this->setBackgroundPhase(value);
std::cout << "INFO in LauLASSNRRes::setResonanceParameter : Setting LASS Background Phase = " << this->getBackgroundPhase() << std::endl;
}
else if (name == "cutOff") {
this->setCutOff(value);
std::cout << "INFO in LauLASSNRRes::setResonanceParameter : Setting LASS Cut Off = " << this->getCutOff() << std::endl;
}
else {
std::cerr << "WARNING in LauLASSNRRes::setResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl;
}
}
diff --git a/src/LauLASSRes.cc b/src/LauLASSRes.cc
index fb6fc61..c9ba36e 100644
--- a/src/LauLASSRes.cc
+++ b/src/LauLASSRes.cc
@@ -1,201 +1,201 @@
-// Copyright University of Warwick 2004 - 2013.
+// Copyright University of Warwick 2004 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauLASSRes.cc
\brief File containing implementation of LauLASSRes class.
*/
#include <iostream>
#include "LauConstants.hh"
#include "LauLASSRes.hh"
ClassImp(LauLASSRes)
-LauLASSRes::LauLASSRes(TString resName, Double_t resMass, Double_t resWidth, Int_t resSpin,
+LauLASSRes::LauLASSRes(TString resName, LauParameter* resMass, LauParameter* resWidth, Int_t resSpin,
Int_t resCharge, Int_t resPairAmpInt, const LauDaughters* daughters) :
LauAbsResonance(resName, resMass, resWidth, resSpin, resCharge, resPairAmpInt, daughters),
q0_(0.0),
mDaugSum_(0.0),
mDaugSumSq_(0.0),
mDaugDiff_(0.0),
mDaugDiffSq_(0.0),
resMassSq_(0.0),
r_(0.0),
a_(0.0),
B_(0.0),
R_(0.0),
phiB_(0.0),
phiR_(0.0),
cutOff_(0.0)
{
// Default values for LASS parameters
r_ = 3.32;
a_ = 2.07;
R_ = 1.0;
B_ = 1.0;
phiR_ = 0.0;
phiB_ = 0.0;
cutOff_ = 1.8;
}
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_;
// Decay momentum of either daughter in the resonance rest frame
// when resonance mass = rest-mass value, m_0 (PDG value)
Double_t resMass = this->getMass();
resMassSq_ = resMass*resMass;
q0_ = TMath::Sqrt((resMassSq_ - mDaugSumSq_)*(resMassSq_ - mDaugDiffSq_))/(2.0*resMass);
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 );
}
}
LauComplex LauLASSRes::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);
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
Double_t q = this->getQ();
Double_t resMass = this->getMass();
Double_t resWidth = this->getWidth();
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(spinTerm*(resMassSq_*resWidth/q0_)/(massSqTerm*massSqTerm + resMassSq_*totWidth*totWidth));
// Calculate the phase shift term
Double_t deltaB = TMath::ATan((2.0*a_*q)/(2.0 + a_*r_*q*q));
Double_t cos2PhaseShift = TMath::Cos(2.0*(deltaB + phiB_));
Double_t sin2PhaseShift = TMath::Sin(2.0*(deltaB + phiB_));
LauComplex phaseShift(cos2PhaseShift, sin2PhaseShift);
// Add in the R e^{i phiR} term
Double_t reR = R_ * TMath::Cos(phiR_);
Double_t imR = R_ * TMath::Sin(phiR_);
LauComplex R(reR, imR);
// Multiply by the phase shift and R e^{i phiR}
resAmplitude = resAmplitude * phaseShift * R;
//--------------------------------
// Now do the effective range part
//--------------------------------
// Form the real and imaginary parts
Double_t realTerm = q/TMath::Tan(deltaB + phiB_);
Double_t imagTerm = q;
// Compute the complex amplitude
bkgAmplitude = LauComplex(realTerm, imagTerm);
// Scale by the numerator and denominator factors
bkgAmplitude.rescale(mass*B_/(realTerm*realTerm + imagTerm*imagTerm));
//------------------
// Add them together
//------------------
if (mass > cutOff_) {
totAmplitude = resAmplitude;
} else {
totAmplitude = bkgAmplitude + resAmplitude;
}
// There is no spin term for the LASS shape
// Just set it 1.0 in case anyone decides to use it at a later date.
spinTerm = 1.0;
return totAmplitude;
}
void LauLASSRes::setResonanceParameter(Double_t value, const TString& name)
{
// 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 if (name == "R") {
this->setResonanceMag(value);
std::cout << "INFO in LauLASSRes::setResonanceParameter : Setting LASS Resonance Magnitude = " << this->getResonanceMag() << std::endl;
}
else if (name == "B") {
this->setBackgroundMag(value);
std::cout << "INFO in LauLASSRes::setResonanceParameter : Setting LASS Background Magnitude = " << this->getBackgroundMag() << std::endl;
}
else if (name == "phiR") {
this->setResonancePhase(value);
std::cout << "INFO in LauLASSRes::setResonanceParameter : Setting LASS Resonance Phase = " << this->getResonancePhase() << std::endl;
}
else if (name == "phiB") {
this->setBackgroundPhase(value);
std::cout << "INFO in LauLASSRes::setResonanceParameter : Setting LASS Background Phase = " << this->getBackgroundPhase() << std::endl;
}
else if (name == "cutOff") {
this->setCutOff(value);
std::cout << "INFO in LauLASSRes::setResonanceParameter : Setting LASS Cut Off = " << this->getCutOff() << std::endl;
}
else {
std::cerr << "WARNING in LauLASSRes::setResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl;
}
}
diff --git a/src/LauNRAmplitude.cc b/src/LauNRAmplitude.cc
index 1fc91a6..1d66e78 100644
--- a/src/LauNRAmplitude.cc
+++ b/src/LauNRAmplitude.cc
@@ -1,72 +1,72 @@
-// Copyright University of Warwick 2004 - 2013.
+// Copyright University of Warwick 2004 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauNRAmplitude.cc
\brief File containing implementation of LauNRAmplitude class.
*/
#include <iostream>
#include "LauKinematics.hh"
#include "LauNRAmplitude.hh"
ClassImp(LauNRAmplitude)
-LauNRAmplitude::LauNRAmplitude(TString resName, Double_t resMass, Double_t resWidth, Int_t resSpin,
+LauNRAmplitude::LauNRAmplitude(TString resName, LauParameter* resMass, LauParameter* resWidth, Int_t resSpin,
Int_t resCharge, Int_t resPairAmpInt, const LauDaughters* daughters) :
LauAbsResonance(resName, resMass, resWidth, resSpin, resCharge, resPairAmpInt, daughters),
d_(1.3232e-3),
c1_(0.65),
c2_(0.55),
p1_(18.0),
p2_(15.0)
{
}
LauNRAmplitude::~LauNRAmplitude()
{
}
void LauNRAmplitude::initialise()
{
}
LauComplex LauNRAmplitude::amplitude(const LauKinematics* kinematics)
{
// Get the information from the kinematics object
Double_t m13Sq = kinematics->getm13Sq();
Double_t m23Sq = kinematics->getm23Sq();
Double_t m13 = kinematics->getm13();
Double_t m23 = kinematics->getm23();
// Calculate the magnitude
Double_t magnitude = TMath::Sqrt( m13 * m23 *
this->f(m23Sq, c1_, p1_) *
this->f(m13Sq, c2_, p2_) *
TMath::Exp( -1.0 * d_ * 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(Double_t s, Double_t c, Double_t p) const
{
return 1.0 / (1.0 + TMath::Exp( c * (s-p) ));
}
diff --git a/src/LauPolNR.cc b/src/LauPolNR.cc
index 321d137..ee0382b 100644
--- a/src/LauPolNR.cc
+++ b/src/LauPolNR.cc
@@ -1,78 +1,78 @@
-// Copyright University of Warwick 2004 - 2013.
+// Copyright University of Warwick 2004 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauPolNR.cc
\brief File containing implementation of LauPolNR class.
*/
#include <iostream>
#include "TMath.h"
#include "LauPolNR.hh"
#include "LauDaughters.hh"
ClassImp(LauPolNR)
-LauPolNR::LauPolNR(const TString& resName, Double_t resMass, Double_t resWidth, Int_t resSpin,
+LauPolNR::LauPolNR(const TString& resName, LauParameter* resMass, LauParameter* resWidth, Int_t resSpin,
Int_t resCharge, Int_t resPairAmpInt, const LauDaughters* daughters) :
LauAbsResonance(resName, resMass, resWidth, resSpin, resCharge, resPairAmpInt, daughters),
omega_(0.0),
order_(0)
{
this->ignoreMomenta(kTRUE);
}
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;
}
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/LauRelBreitWignerRes.cc b/src/LauRelBreitWignerRes.cc
index 742a2af..0f5d128 100644
--- a/src/LauRelBreitWignerRes.cc
+++ b/src/LauRelBreitWignerRes.cc
@@ -1,245 +1,256 @@
-// Copyright University of Warwick 2004 - 2013.
+// Copyright University of Warwick 2004 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauRelBreitWignerRes.cc
\brief File containing implementation of LauRelBreitWignerRes class.
*/
#include <iostream>
#include "LauConstants.hh"
#include "LauRelBreitWignerRes.hh"
ClassImp(LauRelBreitWignerRes)
-LauRelBreitWignerRes::LauRelBreitWignerRes(TString resName, Double_t resMass, Double_t resWidth, Int_t resSpin,
+LauRelBreitWignerRes::LauRelBreitWignerRes(TString resName, LauParameter* resMass, LauParameter* resWidth, Int_t resSpin,
Int_t resCharge, Int_t resPairAmpInt, const LauDaughters* daughters) :
LauAbsResonance(resName, resMass, resWidth, resSpin, resCharge, resPairAmpInt, daughters),
q0_(0.0),
p0_(0.0),
pstar0_(0.0),
+ resMass_(0.0),
resMassSq_(0.0),
+ resWidth_(0.0),
mDaugSum_(0.0),
mDaugSumSq_(0.0),
mDaugDiff_(0.0),
mDaugDiffSq_(0.0),
mParentSq_(0.0),
mBachSq_(0.0),
resR_(4.0),
parR_(4.0),
resRSq_(16.0),
parRSq_(16.0),
FR0_(1.0),
FB0_(1.0),
barrierType_(LauAbsResonance::BWPrimeBarrier)
{
}
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();
+
Int_t resSpin = this->getSpin();
- Double_t resMass = this->getMass();
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;
+ 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 effResMass = resMass_;
+ Double_t effResMassSq = resMassSq_;
if (resMassSq_ - mDaugSumSq_ < 0.0 ){
Double_t minMass = mDaugSum_;
Double_t maxMass = massParent - massBachelor;
- Double_t tanhTerm = std::tanh( (resMass - ((minMass + maxMass)/2))/(maxMass-minMass));
+ Double_t tanhTerm = std::tanh( (resMass_ - ((minMass + maxMass)/2))/(maxMass-minMass));
effResMass = minMass + (maxMass-minMass)*(1+tanhTerm)/2;
+ effResMassSq = effResMass*effResMass;
}
- Double_t 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 );
}
// Blatt-Weisskopf barrier factor constant: z = q^2*radius^2
// Calculate the Blatt-Weisskopf form factor for the case when m = m_0
this->setBarrierRadii(resR_, parR_, barrierType_);
if (resSpin > 3) {
std::cerr << "WARNING in LauRelBreitWignerRes::initialise : Resonances spin is > 3. Blatt-Weisskopf form factors will be set to 1.0" << std::endl;
}
}
void LauRelBreitWignerRes::setBarrierRadii(Double_t resRadius, Double_t parRadius, LauAbsResonance::BarrierType type)
{
// Reset the Blatt-Weisskopf barrier radius for the resonance and its parent
resR_ = resRadius;
parR_ = parRadius;
resRSq_ = resRadius*resRadius;
parRSq_ = parRadius*parRadius;
barrierType_ = type;
// Recalculate the Blatt-Weisskopf form factor for the case when m = m_0
Double_t zR0 = q0_*q0_*resRSq_;
Double_t zB0 = p0_*p0_*parRSq_;
if ( ( type == LauAbsResonance::BWPrimeBarrier ) || ( type == LauAbsResonance::ExpBarrier ) ) {
FR0_ = (resR_==0.0) ? 1.0 : this->calcFFactor(zR0);
FB0_ = (parR_==0.0) ? 1.0 : this->calcFFactor(zB0);
}
}
Double_t LauRelBreitWignerRes::calcFFactor(Double_t z)
{
// Calculate the requested form factor for the resonance, given the z value
Double_t fFactor(1.0);
// For scalars the form factor is always unity
// TODO: and we currently don't have formulae for spin > 3
Int_t resSpin = this->getSpin();
if ( (resSpin == 0) || (resSpin>3) ) {
return fFactor;
}
if ( barrierType_ == LauAbsResonance::BWBarrier ) {
if (resSpin == 1) {
fFactor = TMath::Sqrt(2.0*z/(z + 1.0));
} else if (resSpin == 2) {
fFactor = TMath::Sqrt(13.0*z*z/(z*z + 3.0*z + 9.0));
} else if (resSpin == 3) {
fFactor = TMath::Sqrt(277.0*z*z*z/(z*z*z + 6.0*z*z + 45.0*z + 225.0));
}
} else if ( barrierType_ == LauAbsResonance::BWPrimeBarrier ) {
if (resSpin == 1) {
fFactor = TMath::Sqrt(1.0/(z + 1.0));
} else if (resSpin == 2) {
fFactor = TMath::Sqrt(1.0/(z*z + 3.0*z + 9.0));
} else if (resSpin == 3) {
fFactor = TMath::Sqrt(1.0/(z*z*z + 6.0*z*z + 45.0*z + 225.0));
}
} else if ( barrierType_ == LauAbsResonance::ExpBarrier ) {
if (resSpin == 1) {
fFactor = TMath::Exp( -TMath::Sqrt(z) );
} else if (resSpin == 2) {
fFactor = TMath::Exp( -z );
} else if (resSpin == 3) {
fFactor = TMath::Exp( -TMath::Sqrt(z*z*z) );
}
}
return fFactor;
}
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(...)
Int_t resSpin = this->getSpin();
Double_t resMass = this->getMass();
Double_t resWidth = this->getWidth();
Double_t q = this->getQ();
Double_t p = this->getP();
//Double_t pstar = this->getPstar();
+ // If either of the mass and width are floating and their values have changed
+ // we need to recalculate everything that assumes those values
+ if ( ( (!this->fixMass()) && resMass != resMass_ ) || ( (!this->fixWidth()) && resWidth != resWidth_ ) ) {
+ this->initialise();
+ }
+
Double_t zR = q*q*resRSq_;
Double_t zB = p*p*parRSq_;
Double_t fFactorR = (resR_==0.0) ? 1.0 : this->calcFFactor(zR);
Double_t fFactorB = (parR_==0.0) ? 1.0 : this->calcFFactor(zB);
Double_t fFactorRRatio = fFactorR/FR0_;
Double_t fFactorBRatio = fFactorB/FB0_;
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 = TMath::Power(qRatio, 5.0);
+ qTerm = qRatio*qRatio*qRatio*qRatio*qRatio;
} else {
qTerm = TMath::Power(qRatio, 2*resSpin + 1);
}
Double_t totWidth = resWidth*qTerm*(resMass/mass)*fFactorRRatio*fFactorRRatio;
Double_t massSq = mass*mass;
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 and Blatt-Weisskopf factors
resAmplitude.rescale((fFactorRRatio*fFactorBRatio*spinTerm)/(massSqTerm*massSqTerm + resMassSq_*totWidth*totWidth));
return resAmplitude;
}
diff --git a/src/LauResonanceInfo.cc b/src/LauResonanceInfo.cc
index 4c02a83..4224d48 100644
--- a/src/LauResonanceInfo.cc
+++ b/src/LauResonanceInfo.cc
@@ -1,29 +1,96 @@
-// Copyright University of Warwick 2006 - 2013.
+// Copyright University of Warwick 2006 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauResonanceInfo.cc
\brief File containing implementation of LauResonanceInfo class.
*/
+#include <iostream>
+
+#include "LauParameter.hh"
#include "LauResonanceInfo.hh"
ClassImp(LauResonanceInfo)
LauResonanceInfo::LauResonanceInfo(const TString& name, Double_t mass, Double_t width, Int_t spin, Int_t charge, Double_t range) :
name_(name),
- mass_(mass),
- width_(width),
+ mass_(new LauParameter(name+"_MASS",mass,0.0,range,kTRUE)),
+ width_(new LauParameter(name+"_WIDTH",width,0.0,3*width,kTRUE)),
spin_(spin),
charge_(charge),
range_(range)
{
}
+LauResonanceInfo::~LauResonanceInfo()
+{
+ delete mass_; mass_ = 0;
+ delete width_; width_ = 0;
+}
+
+LauResonanceInfo::LauResonanceInfo( const LauResonanceInfo& other ) :
+ name_( other.name_ ),
+ mass_( other.mass_->createClone() ),
+ width_( other.width_->createClone() ),
+ spin_( other.spin_ ),
+ charge_( other.charge_ ),
+ range_( other.range_ )
+{
+}
+
+LauResonanceInfo::LauResonanceInfo( const LauResonanceInfo& other, const TString& newName, const Int_t newCharge ) :
+ name_( newName ),
+ mass_( other.mass_->createClone( newName+"_MASS" ) ),
+ width_( other.width_->createClone( newName+"_WIDTH" ) ),
+ spin_( other.spin_ ),
+ charge_( newCharge ),
+ range_( other.range_ )
+{
+}
+
+LauResonanceInfo* LauResonanceInfo::createChargeConjugate() const
+{
+ 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 );
+
+ return conjugate;
+}
+
+ostream& operator<<( 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 << "range = " << infoRecord.getRange();
+
+ return stream;
+}
+
+
diff --git a/src/LauResonanceMaker.cc b/src/LauResonanceMaker.cc
index 2a22574..7518ca5 100644
--- a/src/LauResonanceMaker.cc
+++ b/src/LauResonanceMaker.cc
@@ -1,446 +1,583 @@
-// Copyright University of Warwick 2004 - 2013.
+// Copyright University of Warwick 2004 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauResonanceMaker.cc
\brief File containing implementation of LauResonanceMaker class.
*/
#include <iostream>
#include "LauAbsResonance.hh"
#include "LauBelleNR.hh"
#include "LauBelleSymNR.hh"
#include "LauBreitWignerRes.hh"
#include "LauDabbaRes.hh"
#include "LauDaughters.hh"
#include "LauFlatteRes.hh"
#include "LauFlatNR.hh"
#include "LauGounarisSakuraiRes.hh"
#include "LauKappaRes.hh"
#include "LauLASSRes.hh"
#include "LauLASSBWRes.hh"
#include "LauLASSNRRes.hh"
#include "LauNRAmplitude.hh"
#include "LauPolNR.hh"
#include "LauRelBreitWignerRes.hh"
#include "LauResonanceInfo.hh"
#include "LauResonanceMaker.hh"
#include "LauSigmaRes.hh"
ClassImp(LauResonanceMaker)
-LauResonanceMaker::LauResonanceMaker(const LauDaughters* daughters) :
- nResDefMax_(0),
- daughters_(daughters)
+LauResonanceMaker* LauResonanceMaker::resonanceMaker_ = 0;
+
+
+LauResonanceMaker::LauResonanceMaker() :
+ nResDefMax_(0)
{
this->createResonanceVector();
}
LauResonanceMaker::~LauResonanceMaker()
{
}
+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;
+ 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, range parameter (defaults to 4.0)
+ // rho resonances name, mass, width, spin, charge, range parameter (defaults to 4.0)
// rho(770)
- resInfo_.push_back(LauResonanceInfo("rho0(770)", 0.77549, 0.1491, 1, 0, 5.3));
- resInfo_.push_back(LauResonanceInfo("rho+(770)", 0.77549, 0.1491, 1, +1, 5.3));
- resInfo_.push_back(LauResonanceInfo("rho-(770)", 0.77549, 0.1491, 1, -1, 5.3));
+ neutral = new LauResonanceInfo("rho0(770)", 0.77549, 0.1491, 1, 0, 5.3);
+ positve = new LauResonanceInfo("rho+(770)", 0.77549, 0.1491, 1, 1, 5.3);
+ negatve = positve->createChargeConjugate();
+ resInfo_.push_back( neutral );
+ resInfo_.push_back( positve );
+ resInfo_.push_back( negatve );
// rho(1450)
- resInfo_.push_back(LauResonanceInfo("rho0(1450)", 1.465, 0.400, 1, 0 ));
- resInfo_.push_back(LauResonanceInfo("rho+(1450)", 1.465, 0.400, 1, +1 ));
- resInfo_.push_back(LauResonanceInfo("rho-(1450)", 1.465, 0.400, 1, -1 ));
+ neutral = new LauResonanceInfo("rho0(1450)", 1.465, 0.400, 1, 0 );
+ positve = new LauResonanceInfo("rho+(1450)", 1.465, 0.400, 1, 1 );
+ negatve = positve->createChargeConjugate();
+ resInfo_.push_back( neutral );
+ resInfo_.push_back( positve );
+ resInfo_.push_back( negatve );
// rho(1700)
- resInfo_.push_back(LauResonanceInfo("rho0(1700)", 1.720, 0.250, 1, 0 ));
- resInfo_.push_back(LauResonanceInfo("rho+(1700)", 1.720, 0.250, 1, +1 ));
- resInfo_.push_back(LauResonanceInfo("rho-(1700)", 1.720, 0.250, 1, -1 ));
-
- // K* resonances name, mass, width, spin, charge, range parameter (defaults to 4.0)
+ neutral = new LauResonanceInfo("rho0(1700)", 1.720, 0.250, 1, 0 );
+ positve = new LauResonanceInfo("rho+(1700)", 1.720, 0.250, 1, 1 );
+ negatve = positve->createChargeConjugate();
+ resInfo_.push_back( neutral );
+ resInfo_.push_back( positve );
+ resInfo_.push_back( negatve );
+
+ // K* resonances name, mass, width, spin, charge, range parameter (defaults to 4.0)
// K*(892)
- resInfo_.push_back(LauResonanceInfo("K*0(892)", 0.89594, 0.0487, 1, 0, 3.4));
- resInfo_.push_back(LauResonanceInfo("K*+(892)", 0.89166, 0.0508, 1, +1, 3.4));
- resInfo_.push_back(LauResonanceInfo("K*-(892)", 0.89166, 0.0508, 1, -1, 3.4));
+ neutral = new LauResonanceInfo("K*0(892)", 0.89594, 0.0487, 1, 0, 3.4);
+ positve = new LauResonanceInfo("K*+(892)", 0.89166, 0.0508, 1, 1, 3.4);
+ negatve = positve->createChargeConjugate();
+ resInfo_.push_back( neutral );
+ resInfo_.push_back( positve );
+ resInfo_.push_back( negatve );
// K*(1410)
- resInfo_.push_back(LauResonanceInfo("K*0(1410)", 1.414, 0.232, 1, 0 ));
- resInfo_.push_back(LauResonanceInfo("K*+(1410)", 1.414, 0.232, 1, +1 ));
- resInfo_.push_back(LauResonanceInfo("K*-(1410)", 1.414, 0.232, 1, -1 ));
+ neutral = new LauResonanceInfo("K*0(1410)", 1.414, 0.232, 1, 0 );
+ positve = new LauResonanceInfo("K*+(1410)", 1.414, 0.232, 1, 1 );
+ negatve = positve->createChargeConjugate();
+ resInfo_.push_back( neutral );
+ resInfo_.push_back( positve );
+ resInfo_.push_back( negatve );
// K*_0(1430)
- resInfo_.push_back(LauResonanceInfo("K*0_0(1430)", 1.425, 0.270, 0, 0 ));
- resInfo_.push_back(LauResonanceInfo("K*+_0(1430)", 1.425, 0.270, 0, +1 ));
- resInfo_.push_back(LauResonanceInfo("K*-_0(1430)", 1.425, 0.270, 0, -1 ));
+ neutral = new LauResonanceInfo("K*0_0(1430)", 1.425, 0.270, 0, 0 );
+ positve = new LauResonanceInfo("K*+_0(1430)", 1.425, 0.270, 0, 1 );
+ negatve = positve->createChargeConjugate();
+ resInfo_.push_back( neutral );
+ resInfo_.push_back( positve );
+ resInfo_.push_back( negatve );
// K*_2(1430)
- resInfo_.push_back(LauResonanceInfo("K*0_2(1430)", 1.4324, 0.109, 2, 0 ));
- resInfo_.push_back(LauResonanceInfo("K*+_2(1430)", 1.4256, 0.0985, 2, +1 ));
- resInfo_.push_back(LauResonanceInfo("K*-_2(1430)", 1.4256, 0.0985, 2, -1 ));
+ neutral = new LauResonanceInfo("K*0_2(1430)", 1.4324, 0.109, 2, 0 );
+ positve = new LauResonanceInfo("K*+_2(1430)", 1.4256, 0.0985, 2, 1 );
+ negatve = positve->createChargeConjugate();
+ resInfo_.push_back( neutral );
+ resInfo_.push_back( positve );
+ resInfo_.push_back( negatve );
// K*(1680)
- resInfo_.push_back(LauResonanceInfo("K*0(1680)", 1.717, 0.322, 1, 0 ));
- resInfo_.push_back(LauResonanceInfo("K*+(1680)", 1.717, 0.322, 1, +1 ));
- resInfo_.push_back(LauResonanceInfo("K*-(1680)", 1.717, 0.322, 1, -1 ));
-
- // phi resonances name, mass, width, spin, charge, range parameter (defaults to 4.0)
+ neutral = new LauResonanceInfo("K*0(1680)", 1.717, 0.322, 1, 0 );
+ positve = new LauResonanceInfo("K*+(1680)", 1.717, 0.322, 1, 1 );
+ negatve = positve->createChargeConjugate();
+ resInfo_.push_back( neutral );
+ resInfo_.push_back( positve );
+ resInfo_.push_back( negatve );
+
+ // phi resonances name, mass, width, spin, charge, range parameter (defaults to 4.0)
// phi(1020)
- resInfo_.push_back(LauResonanceInfo("phi(1020)", 1.019455, 0.00426, 1, 0 ));
+ neutral = new LauResonanceInfo("phi(1020)", 1.019455, 0.00426, 1, 0 );
+ resInfo_.push_back( neutral );
// phi(1680)
- resInfo_.push_back(LauResonanceInfo("phi(1680)", 1.680, 0.150, 1, 0 ));
+ neutral = new LauResonanceInfo("phi(1680)", 1.680, 0.150, 1, 0 );
+ resInfo_.push_back( neutral );
- // f resonances name, mass, width, spin, charge, range parameter (defaults to 4.0)
+ // f resonances name, mass, width, spin, charge, range parameter (defaults to 4.0)
// f_0(980)
- resInfo_.push_back(LauResonanceInfo("f_0(980)", 0.990, 0.070, 0, 0 ));
+ neutral = new LauResonanceInfo("f_0(980)", 0.990, 0.070, 0, 0 );
+ resInfo_.push_back( neutral );
// f_2(1270)
- resInfo_.push_back(LauResonanceInfo("f_2(1270)", 1.2751, 0.1851, 2, 0 ));
+ neutral = new LauResonanceInfo("f_2(1270)", 1.2751, 0.1851, 2, 0 );
+ resInfo_.push_back( neutral );
// f_0(1370)
- resInfo_.push_back(LauResonanceInfo("f_0(1370)", 1.370, 0.350, 0, 0 ));
+ neutral = new LauResonanceInfo("f_0(1370)", 1.370, 0.350, 0, 0 );
+ resInfo_.push_back( neutral );
// f'_0(1300), from Belle's Kspipi paper
- resInfo_.push_back(LauResonanceInfo("f'_0(1300)", 1.449, 0.126, 0, 0 ));
+ neutral = new LauResonanceInfo("f'_0(1300)", 1.449, 0.126, 0, 0 );
+ resInfo_.push_back( neutral );
// f_0(1500)
- resInfo_.push_back(LauResonanceInfo("f_0(1500)", 1.505, 0.109, 0, 0 ));
+ neutral = new LauResonanceInfo("f_0(1500)", 1.505, 0.109, 0, 0 );
+ resInfo_.push_back( neutral );
// f'_2(1525)
- resInfo_.push_back(LauResonanceInfo("f'_2(1525)", 1.525, 0.073, 2, 0 ));
+ neutral = new LauResonanceInfo("f'_2(1525)", 1.525, 0.073, 2, 0 );
+ resInfo_.push_back( neutral );
// f_0(1710)
- resInfo_.push_back(LauResonanceInfo("f_0(1710)", 1.720, 0.135, 0, 0 ));
+ neutral = new LauResonanceInfo("f_0(1710)", 1.720, 0.135, 0, 0 );
+ resInfo_.push_back( neutral );
- // omega resonances name, mass, width, spin, charge, range parameter (defaults to 4.0)
+ // omega resonances name, mass, width, spin, charge, range parameter (defaults to 4.0)
// omega(782)
- resInfo_.push_back(LauResonanceInfo("omega(782)", 0.78265, 0.00849, 1, 0 ));
+ neutral = new LauResonanceInfo("omega(782)", 0.78265, 0.00849, 1, 0 );
+ resInfo_.push_back( neutral );
- // a resonances name, mass, width, spin, charge, range parameter (defaults to 4.0)
+ // a resonances name, mass, width, spin, charge, range parameter (defaults to 4.0)
// a_0(980)
- resInfo_.push_back(LauResonanceInfo("a0_0(980)", 0.9847, 0.092, 0, 0 ));
- resInfo_.push_back(LauResonanceInfo("a+_0(980)", 0.9847, 0.092, 0, +1 ));
- resInfo_.push_back(LauResonanceInfo("a-_0(980)", 0.9847, 0.092, 0, -1 ));
+ neutral = new LauResonanceInfo("a0_0(980)", 0.9847, 0.092, 0, 0 );
+ positve = new LauResonanceInfo("a+_0(980)", 0.9847, 0.092, 0, 1 );
+ negatve = positve->createChargeConjugate();
+ resInfo_.push_back( neutral );
+ resInfo_.push_back( positve );
+ resInfo_.push_back( negatve );
// a_0(1450)
- resInfo_.push_back(LauResonanceInfo("a0_0(1450)", 1.474, 0.265, 0, 0 ));
- resInfo_.push_back(LauResonanceInfo("a+_0(1450)", 1.474, 0.265, 0, +1 ));
- resInfo_.push_back(LauResonanceInfo("a-_0(1450)", 1.474, 0.265, 0, -1 ));
+ neutral = new LauResonanceInfo("a0_0(1450)", 1.474, 0.265, 0, 0 );
+ positve = new LauResonanceInfo("a+_0(1450)", 1.474, 0.265, 0, 1 );
+ negatve = positve->createChargeConjugate();
+ resInfo_.push_back( neutral );
+ resInfo_.push_back( positve );
+ resInfo_.push_back( negatve );
// a_2(1320)
- resInfo_.push_back(LauResonanceInfo("a0_2(1320)", 1.3183, 0.107, 2, 0 ));
- resInfo_.push_back(LauResonanceInfo("a+_2(1320)", 1.3183, 0.107, 2, +1 ));
- resInfo_.push_back(LauResonanceInfo("a-_2(1320)", 1.3183, 0.107, 2, -1 ));
-
- // charmonium resonances name, mass, width, spin, charge, range parameter (defaults to 4.0)
+ neutral = new LauResonanceInfo("a0_2(1320)", 1.3183, 0.107, 2, 0 );
+ positve = new LauResonanceInfo("a+_2(1320)", 1.3183, 0.107, 2, 1 );
+ negatve = positve->createChargeConjugate();
+ resInfo_.push_back( neutral );
+ resInfo_.push_back( positve );
+ resInfo_.push_back( negatve );
+
+ // charmonium resonances name, mass, width, spin, charge, range parameter (defaults to 4.0)
// chi_c0
- resInfo_.push_back(LauResonanceInfo("chi_c0", 3.41475, 0.0104, 0, 0 ));
+ neutral = new LauResonanceInfo("chi_c0", 3.41475, 0.0104, 0, 0 );
+ resInfo_.push_back( neutral );
// chi_c2
- resInfo_.push_back(LauResonanceInfo("chi_c2", 3.55620, 0.00198, 2, 0 ));
+ neutral = new LauResonanceInfo("chi_c2", 3.55620, 0.00198, 2, 0 );
+ resInfo_.push_back( neutral );
// X(3872)
- resInfo_.push_back(LauResonanceInfo("X(3872)", 3.87168, 0.0012, 1, 0 ));
+ neutral = new LauResonanceInfo("X(3872)", 3.87168, 0.0012, 1, 0 );
+ resInfo_.push_back( neutral );
- // unknown scalars name, mass, width, spin, charge, range parameter (defaults to 4.0)
+ // unknown scalars name, mass, width, spin, charge, range parameter (defaults to 4.0)
// sigma
- resInfo_.push_back(LauResonanceInfo("sigma0", 0.560, 0.500, 0, 0 ));
- resInfo_.push_back(LauResonanceInfo("sigma+", 0.560, 0.500, 0, +1 ));
- resInfo_.push_back(LauResonanceInfo("sigma-", 0.560, 0.500, 0, -1 ));
+ neutral = new LauResonanceInfo("sigma0", 0.560, 0.500, 0, 0 );
+ positve = new LauResonanceInfo("sigma+", 0.560, 0.500, 0, 1 );
+ negatve = positve->createChargeConjugate();
+ resInfo_.push_back( neutral );
+ resInfo_.push_back( positve );
+ resInfo_.push_back( negatve );
// kappa
- resInfo_.push_back(LauResonanceInfo("kappa0", 0.720, 0.700, 0, 0 ));
- resInfo_.push_back(LauResonanceInfo("kappa+", 0.720, 0.700, 0, +1 ));
- resInfo_.push_back(LauResonanceInfo("kappa-", 0.720, 0.700, 0, -1 ));
+ neutral = new LauResonanceInfo("kappa0", 0.720, 0.700, 0, 0 );
+ positve = new LauResonanceInfo("kappa+", 0.720, 0.700, 0, 1 );
+ negatve = positve->createChargeConjugate();
+ resInfo_.push_back( neutral );
+ resInfo_.push_back( positve );
+ resInfo_.push_back( negatve );
// dabba
- resInfo_.push_back(LauResonanceInfo("dabba0", 2.098, 0.520, 0, 0 ));
- resInfo_.push_back(LauResonanceInfo("dabba+", 2.098, 0.520, 0, +1 ));
- resInfo_.push_back(LauResonanceInfo("dabba-", 2.098, 0.520, 0, -1 ));
-
- // excited charm states name, mass, width, spin, charge, range parameter (defaults to 4.0)
+ neutral = new LauResonanceInfo("dabba0", 2.098, 0.520, 0, 0 );
+ positve = new LauResonanceInfo("dabba+", 2.098, 0.520, 0, 1 );
+ negatve = positve->createChargeConjugate();
+ resInfo_.push_back( neutral );
+ resInfo_.push_back( positve );
+ resInfo_.push_back( negatve );
+
+ // excited charm states name, mass, width, spin, charge, range parameter (defaults to 4.0)
// D*
- resInfo_.push_back(LauResonanceInfo("D*0", 2.00698, 0.0021, 1, 0 ));
- resInfo_.push_back(LauResonanceInfo("D*+", 2.01028, 0.000096, 1, +1 ));
- resInfo_.push_back(LauResonanceInfo("D*-", 2.01028, 0.000096, 1, -1 ));
+ neutral = new LauResonanceInfo("D*0", 2.00698, 0.0021, 1, 0 );
+ positve = new LauResonanceInfo("D*+", 2.01028, 0.000096, 1, 1 );
+ negatve = positve->createChargeConjugate();
+ resInfo_.push_back( neutral );
+ resInfo_.push_back( positve );
+ resInfo_.push_back( negatve );
// D*_0
- resInfo_.push_back(LauResonanceInfo("D*0_0", 2.318, 0.267, 0, 0 ));
- resInfo_.push_back(LauResonanceInfo("D*+_0", 2.403, 0.283, 0, +1 ));
- resInfo_.push_back(LauResonanceInfo("D*-_0", 2.403, 0.283, 0, -1 ));
+ neutral = new LauResonanceInfo("D*0_0", 2.318, 0.267, 0, 0 );
+ positve = new LauResonanceInfo("D*+_0", 2.403, 0.283, 0, 1 );
+ negatve = positve->createChargeConjugate();
+ resInfo_.push_back( neutral );
+ resInfo_.push_back( positve );
+ resInfo_.push_back( negatve );
// D*_2
- resInfo_.push_back(LauResonanceInfo("D*0_2", 2.4626, 0.049, 2, 0 ));
- //AVERAGE--resInfo_.push_back(LauResonanceInfo("D*0_2", 2.4618, 0.049, 2, 0 ));
- resInfo_.push_back(LauResonanceInfo("D*+_2", 2.4644, 0.037, 2, +1 ));
- resInfo_.push_back(LauResonanceInfo("D*-_2", 2.4644, 0.037, 2, -1 ));
+ //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 );
+ positve = new LauResonanceInfo("D*+_2", 2.4644, 0.037, 2, 1 );
+ negatve = positve->createChargeConjugate();
+ resInfo_.push_back( neutral );
+ resInfo_.push_back( positve );
+ resInfo_.push_back( negatve );
// D1(2420)
- resInfo_.push_back(LauResonanceInfo("D1(2420)", 2.4213, 0.0271, 1, 0 ));
+ neutral = new LauResonanceInfo("D1(2420)", 2.4213, 0.0271, 1, 0 );
+ resInfo_.push_back( neutral );
// D(2600)
- //OLD--resInfo_.push_back(LauResonanceInfo("D0(2600)", 2.6087, 0.093, 0, 0 ));
- resInfo_.push_back(LauResonanceInfo("D0(2600)", 2.612, 0.093, 0, 0 ));
- resInfo_.push_back(LauResonanceInfo("D+(2600)", 2.6213, 0.093, 0, +1 ));
- resInfo_.push_back(LauResonanceInfo("D-(2600)", 2.6213, 0.093, 0, -1 ));
+ //OLD--neutral = new LauResonanceInfo("D0(2600)", 2.6087, 0.093, 0, 0 );
+ neutral = new LauResonanceInfo("D0(2600)", 2.612, 0.093, 0, 0 );
+ positve = new LauResonanceInfo("D+(2600)", 2.6213, 0.093, 0, 1 );
+ negatve = positve->createChargeConjugate();
+ resInfo_.push_back( neutral );
+ resInfo_.push_back( positve );
+ resInfo_.push_back( negatve );
// D(2760)
- //OLD--resInfo_.push_back(LauResonanceInfo("D0(2760)", 2.7633, 0.061, 1, 0 ));
- resInfo_.push_back(LauResonanceInfo("D0(2760)", 2.761, 0.063, 1, 0 ));
- resInfo_.push_back(LauResonanceInfo("D+(2760)", 2.7697, 0.061, 1, +1 ));
- resInfo_.push_back(LauResonanceInfo("D-(2760)", 2.7697, 0.061, 1, -1 ));
+ //OLD-- neutral = new LauResonanceInfo("D0(2760)", 2.7633, 0.061, 1, 0 );
+ neutral = new LauResonanceInfo("D0(2760)", 2.761, 0.063, 1, 0 );
+ positve = new LauResonanceInfo("D+(2760)", 2.7697, 0.061, 1, 1 );
+ negatve = positve->createChargeConjugate();
+ resInfo_.push_back( neutral );
+ resInfo_.push_back( positve );
+ resInfo_.push_back( negatve );
// D(2900)
- resInfo_.push_back(LauResonanceInfo("D0(3000)", 3.0, 0.15, 0, 0 ));
+ neutral = new LauResonanceInfo("D0(3000)", 3.0, 0.15, 0, 0 );
+ resInfo_.push_back( neutral );
// D(3400)
- resInfo_.push_back(LauResonanceInfo("D0(3400)", 3.4, 0.15, 0, 0 ));
+ neutral = new LauResonanceInfo("D0(3400)", 3.4, 0.15, 0, 0 );
+ resInfo_.push_back( neutral );
- // excited strange charm states name, mass, width, spin, charge, range parameter (defaults to 4.0)
+ // excited strange charm name, mass, width, spin, charge, range parameter (defaults to 4.0)
// Ds*
- resInfo_.push_back(LauResonanceInfo("Ds*+", 2.1123, 0.002, 1, +1 ));
- resInfo_.push_back(LauResonanceInfo("Ds*-", 2.1123, 0.002, 1, -1 ));
+ positve = new LauResonanceInfo("Ds*+", 2.1123, 0.002, 1, 1 );
+ negatve = positve->createChargeConjugate();
+ resInfo_.push_back( positve );
+ resInfo_.push_back( negatve );
// Ds0*(2317)
- resInfo_.push_back(LauResonanceInfo("Ds0*+(2317)", 2.3178, 0.004, 0, +1 ));
- resInfo_.push_back(LauResonanceInfo("Ds0*-(2317)", 2.3178, 0.004, 0, -1 ));
+ positve = new LauResonanceInfo("Ds0*+(2317)", 2.3178, 0.004, 0, 1 );
+ negatve = positve->createChargeConjugate();
+ resInfo_.push_back( positve );
+ resInfo_.push_back( negatve );
// Ds2*(2573)
- resInfo_.push_back(LauResonanceInfo("Ds2*+(2573)", 2.5719, 0.017, 2, +1 ));
- resInfo_.push_back(LauResonanceInfo("Ds2*-(2573)", 2.5719, 0.017, 2, -1 ));
+ positve = new LauResonanceInfo("Ds2*+(2573)", 2.5719, 0.017, 2, 1 );
+ negatve = positve->createChargeConjugate();
+ resInfo_.push_back( positve );
+ resInfo_.push_back( negatve );
// Ds1*(2700)
- resInfo_.push_back(LauResonanceInfo("Ds1*+(2700)", 2.709, 0.125, 1, +1 ));
- resInfo_.push_back(LauResonanceInfo("Ds1*-(2700)", 2.709, 0.125, 1, -1 ));
+ positve = new LauResonanceInfo("Ds1*+(2700)", 2.709, 0.125, 1, 1 );
+ negatve = positve->createChargeConjugate();
+ resInfo_.push_back( positve );
+ resInfo_.push_back( negatve );
- // excited bottom states
+ // excited bottom states name, mass, width, spin, charge, range parameter (defaults to 4.0)
// B*
- resInfo_.push_back(LauResonanceInfo("B*0", 5.3252, 0.00, 1, 0 ));
- resInfo_.push_back(LauResonanceInfo("B*+", 5.3250, 0.00, 1, +1 ));
- resInfo_.push_back(LauResonanceInfo("B*-", 5.3250, 0.00, 1, -1 ));
-
- // excited strange bottom states
+ neutral = new LauResonanceInfo("B*0", 5.3252, 0.00, 1, 0, 6.0);
+ positve = new LauResonanceInfo("B*+", 5.3250, 0.00, 1, 1, 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, range parameter (defaults to 4.0)
// Bs*
- resInfo_.push_back(LauResonanceInfo("Bs*0", 5.4154, 0.00, 1, 0 ));
+ neutral = new LauResonanceInfo("Bs*0", 5.4154, 0.00, 1, 0, 6.0);
+ resInfo_.push_back( neutral );
- // nonresonant models name, mass, width, spin, charge, range parameter (defaults to 4.0)
- // Phase-space nonresonant model
- resInfo_.push_back(LauResonanceInfo("NonReson", 0.0, 0.0, 0, 0 ));
- // Theory-based nonresonant model
- resInfo_.push_back(LauResonanceInfo("NRModel", 0.0, 0.0, 0, 0 ));
- // Babar nonresonant polynomial model
- resInfo_.push_back(LauResonanceInfo("BabarNR", 0.0, 0.0, 0, 0 ));
- // Belle nonresonant models
- resInfo_.push_back(LauResonanceInfo("BelleSymNR", 0.0, 0.0, 0, 0 ));
- resInfo_.push_back(LauResonanceInfo("BelleNR", 0.0, 0.0, 0, 0 ));
- resInfo_.push_back(LauResonanceInfo("BelleNR_Swave", 0.0, 0.0, 0, 0 ));
- resInfo_.push_back(LauResonanceInfo("BelleNR_Pwave", 0.0, 0.0, 1, 0 ));
- resInfo_.push_back(LauResonanceInfo("BelleNR_Dwave", 0.0, 0.0, 2, 0 ));
-
+ // nonresonant models name, mass, width, spin, charge, range parameter (defaults to 4.0)
+ // Phase-space nonresonant model
+ neutral = new LauResonanceInfo("NonReson", 0.0, 0.0, 0, 0 );
+ resInfo_.push_back( neutral );
+ // Theory-based nonresonant model
+ neutral = new LauResonanceInfo("NRModel", 0.0, 0.0, 0, 0 );
+ resInfo_.push_back( neutral );
+ // Belle nonresonant models
+ neutral = new LauResonanceInfo("BelleSymNR", 0.0, 0.0, 0, 0 );
+ resInfo_.push_back( neutral );
+ neutral = new LauResonanceInfo("BelleNR", 0.0, 0.0, 0, 0 );
+ resInfo_.push_back( neutral );
+ neutral = new LauResonanceInfo("BelleNR_Swave", 0.0, 0.0, 0, 0 );
+ resInfo_.push_back( neutral );
+ neutral = new LauResonanceInfo("BelleNR_Pwave", 0.0, 0.0, 1, 0 );
+ resInfo_.push_back( neutral );
+ neutral = new LauResonanceInfo("BelleNR_Dwave", 0.0, 0.0, 2, 0 );
+ resInfo_.push_back( neutral );
+ // Taylor expansion nonresonant model
+ neutral = new LauResonanceInfo("NRTaylor", 0.0, 0.0, 0, 0 );
+ resInfo_.push_back( neutral );
// Polynomial nonresonant models
- resInfo_.push_back(LauResonanceInfo("PolNR", 0.0, 0.0, 0, 0 ));
- resInfo_.push_back(LauResonanceInfo("PolNR_S0", 0.0, 0.0, 0, 0 ));
- resInfo_.push_back(LauResonanceInfo("PolNR_S1", 0.0, 0.0, 0, 0 ));
- resInfo_.push_back(LauResonanceInfo("PolNR_S2", 0.0, 0.0, 0, 0 ));
- resInfo_.push_back(LauResonanceInfo("PolNR_P0", 0.0, 0.0, 1, 0 ));
- resInfo_.push_back(LauResonanceInfo("PolNR_P1", 0.0, 0.0, 1, 0 ));
- resInfo_.push_back(LauResonanceInfo("PolNR_P2", 0.0, 0.0, 1, 0 ));
-
-
- // Taylor expansion nonresonant model
- resInfo_.push_back(LauResonanceInfo("NRTaylor", 0.0, 0.0, 0, 0 ));
- // LASS nonresonant model
- resInfo_.push_back(LauResonanceInfo("LASSNR", 1.412, 0.294, 0, 0 ));
+ neutral = new LauResonanceInfo("PolNR_S0", 0.0, 0.0, 0, 0 );
+ resInfo_.push_back( neutral );
+ neutral = new LauResonanceInfo("PolNR_S1", 0.0, 0.0, 0, 0 );
+ resInfo_.push_back( neutral );
+ neutral = new LauResonanceInfo("PolNR_S2", 0.0, 0.0, 0, 0 );
+ resInfo_.push_back( neutral );
+ neutral = new LauResonanceInfo("PolNR_P0", 0.0, 0.0, 1, 0 );
+ resInfo_.push_back( neutral );
+ neutral = new LauResonanceInfo("PolNR_P1", 0.0, 0.0, 1, 0 );
+ resInfo_.push_back( neutral );
+ neutral = new LauResonanceInfo("PolNR_P2", 0.0, 0.0, 1, 0 );
+ resInfo_.push_back( neutral );
+ // LASS nonresonant model
+ neutral = new LauResonanceInfo("LASSNR", 1.412, 0.294, 0, 0 );
+ resInfo_.push_back( neutral );
nResDefMax_ = resInfo_.size();
}
-LauAbsResonance* LauResonanceMaker::getResonance(const TString& resName, Int_t resPairAmpInt, const TString& resType)
+LauAbsResonance* LauResonanceMaker::getResonance(const LauDaughters* daughters, const TString& resName, Int_t resPairAmpInt, const TString& resType)
{
// 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).
- Double_t resMass(0.0);
- Double_t resWidth(0.0);
+ LauParameter* resMass(0);
+ LauParameter* resWidth(0);
Int_t resSpin(0);
Int_t resCharge(0);
//Double_t resRange(0.0);
Bool_t gotResonance(kFALSE);
// Loop over all possible resonance states we have defined in
// createResonanceVector() until we get a match with the name of the resonance
- for (std::vector<LauResonanceInfo>::const_iterator iter=resInfo_.begin(); iter!=resInfo_.end(); ++iter) {
+ for (std::vector<LauResonanceInfo*>::const_iterator iter=resInfo_.begin(); iter!=resInfo_.end(); ++iter) {
- if (resName == (*iter).getName()) {
+ if (resName == (*iter)->getName()) {
// We have recognised the resonance name.
std::cout<<"INFO in LauResonanceMaker::getResonance : Creating resonance: "<<resName<<std::endl;
- resMass = (*iter).getMass();
- resWidth = (*iter).getWidth();
- resSpin = (*iter).getSpin();
- resCharge = (*iter).getCharge();
- //resRange = (*iter).getRange();
+ resMass = (*iter)->getMass();
+ resWidth = (*iter)->getWidth();
+ resSpin = (*iter)->getSpin();
+ resCharge = (*iter)->getCharge();
+ //resRange = (*iter)->getRange();
// stop looping
gotResonance = kTRUE;
break;
}
}
// if we couldn't find the right resonance then we should return a null pointer
if (!gotResonance) {
return 0;
}
LauAbsResonance* theResonance(0);
// Now construct the resonnace using the right type.
// If we don't recognise the resonance model name, just use a simple Breit-Wigner.
TString resTypeName(resType); resTypeName.ToLower();
if (!resTypeName.CompareTo("flatte")) {
// Flatte distribution - coupled channel Breit-Wigner
std::cout<<" : Using Flatte lineshape. "<<std::endl;
theResonance =
new LauFlatteRes(resName, resMass, resWidth, resSpin, resCharge,
- resPairAmpInt, daughters_);
+ resPairAmpInt, daughters);
} else if (!resTypeName.CompareTo("relbw")) {
// Relativistic Breit-Wigner with Blatt-Weisskopf factors.
std::cout<<" : Using relativistic Breit-Wigner lineshape. "<<std::endl;
theResonance =
new LauRelBreitWignerRes(resName, resMass, resWidth, resSpin, resCharge,
- resPairAmpInt, daughters_);
+ resPairAmpInt, daughters);
// Set the Blatt-Weisskopf barrier radius for the resonance and its parent
//LauRelBreitWignerRes * theRBW = dynamic_cast<LauRelBreitWignerRes*>(theResonance);
//Double_t parentRange = 4.0;
//theRBW->setBarrierRadii(resRange, parentRange);
} else if (!resTypeName.CompareTo("dabba")) {
// Dabba model - should only be used for the D-pi system
std::cout<<" : Using Dabba lineshape. "<<std::endl;
theResonance =
new LauDabbaRes(resName, resMass, resWidth, resSpin, resCharge,
- resPairAmpInt, daughters_);
+ resPairAmpInt, daughters);
} else if (!resTypeName.CompareTo("kappa")) {
// Kappa model - should only be used for the K-pi system
std::cout<<" : Using Kappa lineshape. "<<std::endl;
theResonance =
new LauKappaRes(resName, resMass, resWidth, resSpin, resCharge,
- resPairAmpInt, daughters_);
+ resPairAmpInt, daughters);
} else if (!resTypeName.CompareTo("sigma")) {
// Sigma model - should only be used for the pi-pi system
std::cout<<" : Using Sigma lineshape. "<<std::endl;
theResonance =
new LauSigmaRes(resName, resMass, resWidth, resSpin, resCharge,
- resPairAmpInt, daughters_);
+ resPairAmpInt, daughters);
} else if (!resTypeName.CompareTo("lass-bw")) {
// LASS function to try and model the K-pi S-wave better
std::cout<<" : Using LASS lineshape (resonant part only). "<<std::endl;
theResonance =
new LauLASSBWRes(resName, resMass, resWidth, resSpin, resCharge,
- resPairAmpInt, daughters_);
+ resPairAmpInt, daughters);
} else if (!resTypeName.CompareTo("lass-nr")) {
// LASS function to try and model the K-pi S-wave better
std::cout<<" : Using LASS lineshape (nonresonant part only). "<<std::endl;
theResonance =
new LauLASSNRRes(resName, resMass, resWidth, resSpin, resCharge,
- resPairAmpInt, daughters_);
+ resPairAmpInt, daughters);
} else if (!resTypeName.CompareTo("lass")) {
// LASS function to try and model the K-pi S-wave better
std::cout<<" : Using LASS lineshape. "<<std::endl;
theResonance =
new LauLASSRes(resName, resMass, resWidth, resSpin, resCharge,
- resPairAmpInt, daughters_);
+ resPairAmpInt, daughters);
} else if (!resTypeName.CompareTo("gs")) {
// Gounaris-Sakurai function to try and model the rho(770) better
std::cout<<" : Using Gounaris-Sakurai lineshape. "<<std::endl;
theResonance =
new LauGounarisSakuraiRes(resName, resMass, resWidth, resSpin, resCharge,
- resPairAmpInt, daughters_);
+ resPairAmpInt, daughters);
} else if (!resTypeName.CompareTo("flatnr")) {
// uniform NR amplitude - arguments are there to preserve the interface
std::cout<<" : Using uniform NR lineshape. "<<std::endl;
theResonance =
new LauFlatNR(resName, resMass, resWidth, resSpin, resCharge,
- resPairAmpInt, daughters_);
+ resPairAmpInt, daughters);
} else if (!resTypeName.CompareTo("nrmodel")) {
// NR amplitude model - arguments are there to preserve the interface
std::cout<<" : Using NR-model lineshape. "<<std::endl;
theResonance =
new LauNRAmplitude(resName, resMass, resWidth, resSpin, resCharge,
- resPairAmpInt, daughters_);
+ resPairAmpInt, daughters);
} else if ( !resTypeName.CompareTo("bellesymnr") || !resTypeName.CompareTo("nrtaylor") ) {
// Belle NR amplitude model - arguments are there to preserve the interface
std::cout<<" : Using Belle symmetric NR lineshape. "<<std::endl;
theResonance =
new LauBelleSymNR(resName, resMass, resWidth, resSpin, resCharge,
- resPairAmpInt, daughters_);
+ resPairAmpInt, daughters);
} else if ( !resTypeName.CompareTo("bellenr") ) {
// Belle NR amplitude model - arguments are there to preserve the interface
std::cout<<" : Using Belle NR lineshape. "<<std::endl;
theResonance =
new LauBelleNR(resName, resMass, resWidth, resSpin, resCharge,
- resPairAmpInt, daughters_);
+ resPairAmpInt, daughters);
} else if ( !resTypeName.CompareTo("polnr") ) {
// Polynomial NR amplitude model - arguments are there to preserve the interface
std::cout<<" : Using polynomial NR lineshape. "<<std::endl;
theResonance =
new LauPolNR(resName, resMass, resWidth, resSpin, resCharge,
- resPairAmpInt, daughters_);
+ resPairAmpInt, daughters);
} else if (!resTypeName.CompareTo("bw")) {
// Simple non-relativistic Breit-Wigner
std::cout<<" : Using simple Breit-Wigner lineshape. "<<std::endl;
theResonance =
new LauBreitWignerRes(resName, resMass, resWidth, resSpin, resCharge,
- resPairAmpInt, daughters_);
+ resPairAmpInt, daughters);
} else {
std::cerr << "ERROR in LauResonanceMaker::getResonance : Could not match resonace type \"" << resTypeName << "\"." << std::endl;
return 0;
}
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<LauResonanceInfo>::const_iterator iter=resInfo_.begin(); iter!=resInfo_.end(); ++iter) {
+ for (std::vector<LauResonanceInfo*>::const_iterator iter=resInfo_.begin(); iter!=resInfo_.end(); ++iter) {
- if (name.BeginsWith((*iter).getName(), TString::kExact) == kTRUE) {
+ 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;
}
+std::vector<LauParameter*> LauResonanceMaker::getFloatingParameters()
+{
+ std::vector<LauParameter*> param;
+
+ for (std::vector<LauResonanceInfo*>::const_iterator iter=resInfo_.begin(); iter!=resInfo_.end(); ++iter) {
+ LauParameter* massPar = (*iter)->getMass();
+ if ( (!massPar->fixed()) && (!massPar->clone()) ) {
+ std::cout << "INFO in LauResonanceMaker::getFloatingParameters: resNameMass = " << massPar->name() << ", fixed = "<< massPar->fixed() << std::endl;
+ param.push_back(massPar);
+ }
+
+ LauParameter* widthPar = (*iter)->getWidth();
+ if ( (!widthPar->fixed()) && (!widthPar->clone()) ) {
+ std::cout << "INFO in LauResonanceMaker::getFloatingParameters: resNameWidth = " << widthPar->name() << ", fixed = "<< widthPar->fixed() << std::endl;
+ param.push_back(widthPar);
+ }
+ }
+
+ return param;
+}
+
+void LauResonanceMaker::printAll( ostream& stream ) const
+{
+ for ( std::vector<LauResonanceInfo*>::const_iterator iter = resInfo_.begin(); iter != resInfo_.end(); ++iter ) {
+ stream << (**iter) << std::endl;
+ }
+}
+
diff --git a/src/LauSigmaRes.cc b/src/LauSigmaRes.cc
index 80aa29b..cfa9fad 100644
--- a/src/LauSigmaRes.cc
+++ b/src/LauSigmaRes.cc
@@ -1,131 +1,131 @@
-// Copyright University of Warwick 2004 - 2013.
+// Copyright University of Warwick 2004 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauSigmaRes.cc
\brief File containing implementation of LauSigmaRes class.
*/
#include <iostream>
#include "LauConstants.hh"
#include "LauSigmaRes.hh"
ClassImp(LauSigmaRes)
-LauSigmaRes::LauSigmaRes(TString resName, Double_t resMass, Double_t resWidth, Int_t resSpin,
+LauSigmaRes::LauSigmaRes(TString resName, LauParameter* resMass, LauParameter* resWidth, Int_t resSpin,
Int_t resCharge, Int_t resPairAmpInt, const LauDaughters* daughters) :
LauAbsResonance(resName, resMass, resWidth, resSpin, resCharge, resPairAmpInt, daughters),
mPiSq4_(0.0),
sAdler_(0.0),
b1_(0.0),
b2_(0.0),
A_(0.0),
m0_(0.0),
m0Sq_(0.0),
denom_(0.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
Double_t b1 = 0.5843;
Double_t b2 = 1.6663;
Double_t A = 1.082;
Double_t m0 = 0.9264;
this->setConstants(b1, b2, A, m0);
}
LauSigmaRes::~LauSigmaRes()
{
}
void LauSigmaRes::initialise()
{
this->checkDaughterTypes();
Double_t resSpin = this->getSpin();
if (resSpin != 0) {
std::cerr << "ERROR in LauSigmaRes : spin = " << resSpin << " is not zero!" << std::endl;
}
}
void LauSigmaRes::setConstants(Double_t b1, Double_t b2, Double_t A, Double_t m0) {
b1_ = b1;
b2_ = b2;
A_ = A;
m0_ = m0;
m0Sq_ = m0_*m0_;
denom_ = m0Sq_ - sAdler_;
}
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 \""<<nameDaug1<<"\" and \""<<nameDaug2<<"\", which are not pions." << std::endl;
}
}
}
LauComplex LauSigmaRes::resAmp(Double_t mass, Double_t spinTerm)
{
// This function returns the complex dynamical amplitude for a Sigma 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 Sigma distribution. Returns the
// integer defined by the enum LauSigmaRes::SigmaPartType.
Double_t s = mass*mass; // Invariant mass squared combination for the system
Double_t rho(0.0); // Phase-space factor
if (s > mPiSq4_) {rho = TMath::Sqrt(1.0 - mPiSq4_/s);}
Double_t f = b2_*s + b1_; // f(s) function
Double_t numerator = s - sAdler_;
Double_t gamma(0.0);
if (TMath::Abs(denom_) > 1e-10 && TMath::Abs(A_) > 1e-10) {
// Decay width of the system
gamma = rho*(numerator/denom_)*f*TMath::Exp(-(s - m0Sq_)/A_);
}
// 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*m0_;
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;
}
diff --git a/src/LauSimpleFitModel.cc b/src/LauSimpleFitModel.cc
index cf69e8f..a89ea2f 100644
--- a/src/LauSimpleFitModel.cc
+++ b/src/LauSimpleFitModel.cc
@@ -1,2066 +1,2089 @@
-// Copyright University of Warwick 2004 - 2013.
+// Copyright University of Warwick 2004 - 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Authors:
// Thomas Latham
// John Back
// Paul Harrison
/*! \file LauSimpleFitModel.cc
\brief File containing implementation of LauSimpleFitModel class.
*/
#include <iostream>
#include <iomanip>
#include <fstream>
#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 "LauAbsDPDynamics.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 "LauResonanceMaker.hh"
#include "LauScfMap.hh"
#include "LauSimpleFitModel.hh"
ClassImp(LauSimpleFitModel)
LauSimpleFitModel::LauSimpleFitModel(LauAbsDPDynamics* 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(LauParameter* 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;
}
bkgndEvents_[bkgndID] = nBkgndEvents;
bkgndEvents_[bkgndID]->name( nBkgndEvents->name()+"Events" );
Double_t value = nBkgndEvents->value();
bkgndEvents_[bkgndID]->range(-2.0*(TMath::Abs(value)+1.0), 2.0*(TMath::Abs(value)+1.0));
}
void LauSimpleFitModel::splitSignalComponent( const TH2* dpHisto, Bool_t upperHalf, 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;
}
LauDaughters* daughters = sigDPModel_->getDaughters();
scfFracHist_ = new LauEffModel( daughters, 0 );
scfFracHist_->setEffHisto( dpHisto, kTRUE, kFALSE, 0.0, 0.0, upperHalf, daughters->squareDP() );
scfMap_ = scfMap;
useSCF_ = kTRUE;
useSCFHist_ = kTRUE;
}
void LauSimpleFitModel::splitSignalComponent( Double_t scfFrac, 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)
{
// Is there a component called compName in the signal model?
TString compName(coeffSet->name());
Bool_t ok = sigDPModel_->hasResonance(compName);
if (!ok) {
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?
for (std::vector<LauAbsCoeffSet*>::const_iterator iter = coeffPars_.begin(); iter != coeffPars_.end(); ++iter) {
if ((*iter)->name() == compName) {
std::cerr << "ERROR in LauSimpleFitModel::setAmpCoeffSet : Have already set coefficients for \"" << compName << "\"." << std::endl;
return;
}
}
coeffSet->index(nSigComp_);
coeffPars_.push_back(coeffSet);
++nSigComp_;
std::cout << "INFO in LauSimpleFitModel::setAmpCoeffSet : Added coefficients for component \"" << compName << "\" to the fit model." << std::endl;
coeffSet->printParValues();
}
void LauSimpleFitModel::initialise()
{
// First of all check that, we have all the Dalitz-plot models
if (this->useDP()) {
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;
}
}
}
}
// 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<TString> varNames = (*pdf_iter)->varNames();
for ( std::vector<TString>::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<TString> varNames = (*pdf_iter)->varNames();
for ( std::vector<TString>::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<TString> varNames = (*pdf_iter)->varNames();
for ( std::vector<TString>::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);
}
// From the initial parameter values calculate the coefficients
// so they can be passed to the signal model
this->updateCoeffs();
// Initialisation
if (this->useDP() == kTRUE) {
this->initialiseDPModels();
}
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);
}
this->setExtraNtupleVars();
}
void LauSimpleFitModel::initialiseDPModels()
{
std::cout << "INFO in LauSimpleFitModel::initialiseDPModels : Initialising signal DP model" << 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();
+ LauFitDataTree* inputFitData = this->fitData();
+ sigDPModel_->fillDataTree(*inputFitData);
+}
+
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;
// Need to check that the number of components we have and that the dynamics has matches up
UInt_t nAmp = sigDPModel_->getnAmp();
if (nAmp != nSigComp_) {
std::cerr << "ERROR in LauSimpleFitModel::setSignalDPParameters : Number of signal DP components with magnitude and phase set not right." << std::endl;
gSystem->Exit(EXIT_FAILURE);
}
// Place signal model 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_;
}
}
}
+
+ // get the resonanceMaker from any of the two {pos,neg}SigModel_
+ LauResonanceMaker& resonanceMaker = LauResonanceMaker::get();
+
+ //Obtain the Resonance Parameters
+ std::vector<LauParameter*> resPars = resonanceMaker.getFloatingParameters();
+ for (LauParameterPList::iterator iter = resPars.begin(); iter != resPars.end(); ++iter) {
+ //cout << "resName = " << (*iter)->name() << ", fixed = "<< (*iter)->fixed() << endl;
+ if ( !(*iter)->clone() ) {
+ //cout << "adding " << (*iter)->name() << endl;
+ 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) {
LauParameter* parameter = (*iter);
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); i<nSigComp_; ++i) {
if (fitFrac_[i].size() != nSigComp_) {
std::cerr << "ERROR in LauSimpleFitModel::setExtraNtupleVars : Initial Fit Fraction array of unexpected dimension: " << fitFrac_[i].size() << std::endl;
gSystem->Exit(EXIT_FAILURE);
}
}
for (UInt_t i = 0; i < nSigComp_; i++) {
for (UInt_t j = i; j < nSigComp_; j++) {
extraVars.push_back(fitFrac_[i][j]);
}
}
// Store any extra parameters/quantities from the DP model (e.g. K-matrix total fit fractions)
std::vector<LauParameter> extraParams = sigDPModel_->getExtraParameters();
std::vector<LauParameter>::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) {
(*iter)->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); i<nSigComp_; ++i) {
if (fitFrac[i].size() != nSigComp_) {
std::cerr << "ERROR in LauSimpleFitModel::finaliseFitResults : Fit Fraction array of unexpected dimension: " << fitFrac[i].size() << std::endl;
gSystem->Exit(EXIT_FAILURE);
}
}
for (UInt_t i(0); i<nSigComp_; ++i) {
for (UInt_t j(i); j<nSigComp_; ++j) {
fitFrac_[i][j].value(fitFrac[i][j].value());
}
}
meanEff_.value(sigDPModel_->getMeanEff().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<nSigComp_; ++i) {
for (UInt_t j(i); j<nSigComp_; ++j) {
extraVars.push_back(fitFrac_[i][j]);
}
}
// Store any extra parameters/quantities from the DP model (e.g. K-matrix total fit fractions)
std::vector<LauParameter> extraParams = sigDPModel_->getExtraParameters();
std::vector<LauParameter>::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->nll(), 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();
}
}
LauSimpleFitModel::LauGenInfo LauSimpleFitModel::eventsToGenerate()
{
// Determine the number of events to generate for each hypothesis
// If we're smearing then smear each one individually
LauGenInfo nEvtsGen;
// 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 );
// Backgrounds
const UInt_t nBkgnds = this->nBkgndClasses();
for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) {
const TString& bkgndClass = this->bkgndClassName(bkgndID);
const LauParameter* 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 );
}
return nEvtsGen;
}
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
LauGenInfo nEvts = this->eventsToGenerate();
Bool_t genOK(kTRUE);
Int_t evtNum(0);
const UInt_t nBkgnds = this->nBkgndClasses();
std::vector<TString> bkgndClassNames(nBkgnds);
std::vector<TString> 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); iEvt<nEvtsGen; ++iEvt) {
this->setGenNtupleDoubleBranchValue( "evtWeight", evtWeight );
if (type == "signal") {
this->setGenNtupleIntegerBranchValue("genSig",1);
for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) {
this->setGenNtupleIntegerBranchValue( bkgndClassNamesGen[iBkgnd], 0 );
}
genOK = this->generateSignalEvent();
} 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 (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); i<nSigComp_; ++i) {
if (fitFrac[i].size() != nSigComp_) {
std::cerr << "ERROR in LauSimpleFitModel::genExpt : Fit Fraction array of unexpected dimension: " << fitFrac[i].size() << std::endl;
gSystem->Exit(EXIT_FAILURE);
}
}
for (UInt_t i(0); i<nSigComp_; ++i) {
for (UInt_t j = i; j < nSigComp_; j++) {
fitFrac_[i][j].value(fitFrac[i][j].value());
}
}
meanEff_.value(sigDPModel_->getMeanEff().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<Int_t>(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 );
LauEffModel * 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<Int_t>(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");
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<TString> varNames = (*pdf_iter)->varNames();
for ( std::vector<TString>::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) {
(*iter)->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<Double_t> binCentresXCoords;
std::vector<Double_t> 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_.value();
}
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_->value() * sigLike;
const UInt_t nBkgnds = this->nBkgndClasses();
for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) {
likelihood += (bkgndEvents_[bkgndID]->value() * bkgndDPLike_[bkgndID] * bkgndExtraLike_[bkgndID]);
}
return likelihood;
}
Double_t LauSimpleFitModel::getEventSum() const
{
Double_t eventSum(0.0);
eventSum += signalEvents_->value();
for (LauBkgndYieldList::const_iterator iter = bkgndEvents_.begin(); iter != bkgndEvents_.end(); ++iter) {
eventSum += (*iter)->value();
}
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<Int_t>* trueBins = scfMap_->trueBins(recoBin);
Int_t nDataEvents = this->eventsPerExpt();
// Loop over the true bins
for (std::vector<Int_t>::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<TString> varNames = (*pdf_iter)->varNames();
for ( std::vector<TString>::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<TString>::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<TString> varNames = (*pdf_iter)->varNames();
for ( std::vector<TString>::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<TString>::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<TString> varNames = (*pdf_iter)->varNames();
for ( std::vector<TString>::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 LauParameter* par = bkgndEvents_[iBkgnd];
if (!par->fixed()) {
numbMap[bkgndClass] = par->genValue();
}
}
}
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 LauParameter* 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<TString> varNames = (*pdf_iter)->varNames();
for ( std::vector<TString>::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<TString> varNames = (*pdf_iter)->varNames();
for ( std::vector<TString>::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<TString> varNames = (*pdf_iter)->varNames();
for ( std::vector<TString>::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_.value();
}
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;
}
if (!reuseEventsWithinEnsemble && reuseEventsWithinExperiment) {
std::cerr << "WARNING in LauSimpleFitModel::embedSignal : Conflicting options provided, will not reuse events at all." << std::endl;
reuseEventsWithinExperiment = kFALSE;
}
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;
}
if (!reuseEventsWithinEnsemble && reuseEventsWithinExperiment) {
std::cerr << "WARNING in LauSimpleFitModel::embedBkgnd : Conflicting options provided, will not reuse events at all." << std::endl;
reuseEventsWithinExperiment = kFALSE;
}
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->cacheFitData(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 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 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();
}
if (LauAbsDPDynamics::GenOK != sigDPModel_->checkToyMC(kTRUE,kFALSE)) {
std::cerr << "WARNING in LauSimpleFitModel::weightEvents : Problem in calculating the weight, aborting." << std::endl;
delete weightsTuple;
return;
}
}
weightsTuple->setDoubleBranchValue( "dpModelWeight", dpModelWeight );
weightsTuple->fillBranches();
}
}
weightsTuple->buildIndex( "iExpt", "iEvtWithinExpt" );
weightsTuple->addFriendTree(dataFileName, dataTreeName);
weightsTuple->writeOutGenResults();
delete weightsTuple;
}

File Metadata

Mime Type
text/x-diff
Expires
Tue, Nov 19, 4:07 PM (1 d, 13 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3805082
Default Alt Text
(594 KB)

Event Timeline